@idle-screens/schema 3.12.0 → 3.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FORMAT.md +111 -19
- package/dist/index.d.ts +170 -9
- package/dist/index.js +1998 -344
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/saver-spec.schema.json +105 -9
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/steer.ts","../src/sequence.ts","../src/timeline.ts","../src/validate.ts","../src/shapes.ts","../src/simulate.ts","../src/compile.ts","../src/paint.ts","../src/field.ts","../src/finish.ts","../src/advise.ts","../src/luma.ts","../src/cohesion.ts","../src/perceive.ts","../src/describe.ts","../src/examples/aquarium.ts","../src/examples/aurora.ts","../src/examples/comets.ts","../src/examples/constellation.ts","../src/examples/dev-dashboard.ts","../src/examples/sparse-night.ts","../src/examples/signal-board.ts","../src/examples/phase-duet.ts","../src/examples/web-work.ts","../src/examples/shard-fall.ts","../src/examples/murmur.ts","../src/examples/three-movements.ts","../src/examples/facets.ts","../src/examples/haiku.ts","../src/examples/lanterns.ts","../src/examples/lobby-talk.ts","../src/examples/matrix-rain.ts","../src/examples/nostalghia-candle.ts","../src/examples/polygons.ts","../src/examples/orrery.ts","../src/examples/pings.ts","../src/examples/procession.ts","../src/examples/rain.ts","../src/examples/relay-board.ts","../src/examples/sakura.ts","../src/examples/snowfall.ts","../src/examples/thermal-field.ts","../src/examples/warp-tunnel.ts","../src/examples/typed-cue.ts","../src/examples/index.ts"],"sourcesContent":["/**\n * Declarative, agent-authorable saver format. A `SaverSpec` describes a saver as DATA\n * (no code), which `compileSaver` turns into a seeded, deterministic, flash-safe\n * SaverPlugin. It models the \"drifting sprite field\" family that covers most classic\n * savers (fish, toasters, DVD, rain, messages): a static background plus one or more\n * layers of entities that move.\n *\n * SAFETY INVARIANT: there is deliberately NO full-field strobe/flash primitive — the\n * background is static and entities are bounded sprites — so a compiled spec cannot\n * produce photosensitive flashing by construction (proven by sampling a compiled spec\n * through @idle-screens/validator).\n */\nexport const SCHEMA_VERSION = 1 as const;\n\nexport interface SaverSpec {\n schemaVersion: 1;\n id: string;\n label: string;\n /** Deterministic seed; falls back to the host's SaverContext.seed. */\n seed?: number;\n background?: BackgroundSpec;\n layers: LayerSpec[];\n motionIntensity?: 'calm' | 'moderate' | 'energetic';\n /**\n * Declared density intent. `sparse` says the emptiness is the point (one\n * mark on a dark ground, long silences): `adviseSpec` withholds\n * `sparse-scene`, and scorers that gate on coverage should read this before\n * calling a faithful scene broken. `dense` withholds `dense-scene` the same\n * way. Either declaration is checked against the measured coverage and a\n * `density-mismatch` advisory fires when the scene contradicts it. Omitted\n * means `normal`. A hint only — it changes no pixel.\n */\n density?: 'sparse' | 'normal' | 'dense';\n /**\n * Frame persistence (0..1, capped at LIMITS.maxGhosting). Instead of fully clearing,\n * each frame the background is painted at reduced alpha so moving entities leave\n * decaying after-images (Mystify smears, long-exposure light). Inherently\n * flash-safe: ghosting can only smooth luminance changes, never sharpen them.\n * `renderFrame(t)` stays deterministic for seeks via a fixed-step warm-up replay.\n */\n ghosting?: number;\n /**\n * The print finish — grain and a dither screen composited over the\n * finished frame as the last step of every render. See `FinishSpec`.\n * Absent ⇒ the frame is presented exactly as drawn.\n */\n finish?: FinishSpec;\n /**\n * Authored keyframes on the scene's own clock — see `Timeline`. Absent ⇒\n * the scene is exactly what it was before the field existed. **Native:**\n * ignored ⇒ the base spec (author it as the piece's rest state).\n */\n timeline?: Timeline;\n /** Named layer groups — see `LayerGroup`. Absent ⇒ no layer is grouped (today's behaviour). */\n groups?: Record<string, LayerGroup>;\n /** Dimensional unit system. 'viewport' (default) = all sizes/speeds/distances are fractions of min(w,h). */\n units?: 'viewport' | 'px';\n /**\n * Resolution at which this spec was designed. Density scaling kicks in above this\n * threshold: entity counts scale by min(w,h) / referenceViewport. Default: 1080.\n * Set to your design resolution so a spec authored at 4K doesn't over-densify.\n */\n referenceViewport?: number;\n}\n\n/**\n * A print finish over the finished frame: `grain` (0..1) screens a seeded\n * zero-mean noise tile at up to 35 % alpha; `dither` (0..1) screens an 8×8\n * ordered Bayer tile at up to 25 % — a stylistic screen, not per-pixel\n * dithering of the image. Both composite with a symmetric blend (`overlay`)\n * so the frame's mean luminance is unchanged: flash-safe by construction,\n * and invisible to `luminanceGrid`. The grain tile is generated once per\n * mount from the spec seed and sits still; `animate: true` steps its offset\n * deterministically from the frame's time bucket (12 Hz), never randomly —\n * ignored on the `basic` / `minimal` capability tiers (static tile). The\n * finish is applied on a presentation canvas, never fed back into\n * `ghosting`'s persistence. `grain` and `dither` are numeric paint paths\n * (`finish.grain`) and glide.\n */\nexport interface FinishSpec {\n grain?: number;\n dither?: number;\n animate?: boolean;\n}\n\nexport type BackgroundSpec =\n | { type: 'solid'; color: string }\n | { type: 'gradient'; stops: GradientStop[]; band?: BandSpec; drift?: BackgroundDrift }\n | FieldBackground;\n\n/**\n * A scalar-field background: seeded, warped value noise quantised into\n * `bands` — thermal maps, contour terrain, sonar landmasses, riso washes.\n * Pure in `(x, y, t, seed)`: the renderer paints it as a low-res raster\n * (short side 96 px; 48 on the `basic` / `minimal` tiers) scaled to the\n * canvas, recomputed once per 100 ms bucket while drifting and once ever\n * otherwise, and the perception grid samples the same function directly.\n * The sampler uses its own hash, never the entity RNG, so adding a field to\n * a spec leaves every entity where it was.\n */\nexport interface FieldBackground {\n type: 'field';\n /** Noise features across the short side, 0.5..8 (LIMITS.minFieldScale / maxFieldScale). */\n scale: number;\n /** Octaves of detail, integer 1..4 (default 2). */\n octaves?: number;\n /** Domain-warp amount 0..1 (default 0) — folds round blobs into smeared contours. */\n warp?: number;\n /**\n * Levels to posterise the field into, integer 2..8, or 0 for smooth\n * interpolation between bands (Aura, Mist). Default `bands.length`: one\n * hard band per level.\n */\n quantize?: number;\n /** 2..8 hex colours, darkest-to-lightest or whatever ramp the look wants. */\n bands: string[];\n /** Slow domain travel — the field's \"animate\". Period floored at 10 s (flash guard). */\n drift?: FieldDrift;\n /** Field seed; defaults to the spec seed. Independent of the entity stream. */\n seed?: number;\n}\n\n/** Slow travel of a field's sample domain: a circle of radius `amount` feature units per `period`. */\nexport interface FieldDrift {\n /** Full loop period in ms. Floor: LIMITS.minDriftPeriod (10 s) — the flash guard. */\n period: number;\n /** Radius of the domain travel in feature units, 0..1. Default 0.3. */\n amount?: number;\n}\n\n/** A vertical gradient stop (`at` 0 = top, 1 = bottom). */\nexport interface GradientStop {\n at: number;\n color: string;\n}\n\n/** An optional solid band at the bottom (e.g. an aquarium seafloor). */\nexport interface BandSpec {\n color: string;\n /** Band height — px or a viewport fraction, per the spec's `units`. */\n height: number;\n}\n\n/** Slow oscillation of gradient stop positions — makes the background feel alive. */\nexport interface BackgroundDrift {\n /** Full cycle period in ms. Floor: LIMITS.minDriftPeriod (10 s). */\n period: number;\n /** How far stops shift (fraction of the 0..1 range). Default 0.15, max 0.3. */\n amount?: number;\n}\n\n/**\n * A paint-level transform applied to a whole layer at draw time, about the\n * viewport centre: translate by (`x`, `y`) in `min(w, h)` units, rotate by\n * `rotate` degrees, scale by `scale` (× `scaleX` horizontally — `scaleX`\n * toward 0 reads as a turn about the vertical axis). Kept out of the\n * structural signature, so it glides under steering, a `timeline` key or a\n * `morph` — a camera for timed pieces, a slow drift for ambient ones. Every\n * field optional; an empty transform is the identity. **Native:** ignored ⇒\n * identity.\n */\nexport interface LayerTransform {\n x?: number;\n y?: number;\n scale?: number;\n scaleX?: number;\n rotate?: number;\n /**\n * What `scale` / `scaleX` / `rotate` turn about. `'viewport'` (default) is\n * the viewport centre — a camera move. `'anchor'` is the layer's own\n * `position` point (with `dx`/`dy`; for a `list`/`table` layout, the block's\n * anchor; without `position`, the centre of its `region`) — a slam word\n * punches in place, on every aspect. Group transforms always turn about the\n * viewport centre. **Native:** ignored with the rest of `transform`.\n */\n origin?: 'viewport' | 'anchor';\n}\n\n/**\n * A named set of layers painted through one shared `transform` and\n * `opacity` (`SaverSpec.groups`, joined by `LayerSpec.group`): the group's\n * transform wraps each member's own (it turns about the viewport centre, a\n * camera), and its opacity multiplies theirs. Paint — outside the structural\n * signature — so a steer (`groups.<name>.transform.scale`), a `timeline` key\n * or a `morph` glides a whole multi-layer subject as one thing. **Native:**\n * ignored ⇒ identity, opacity 1.\n */\nexport interface LayerGroup {\n transform?: LayerTransform;\n opacity?: number;\n}\n\n/** One authored key of a `Timeline`: at scene time `t` (ms), glide `path` to `value` over `dur` ms. */\nexport interface TimelineKey {\n /** Scene time in ms (the instance's own clock — a sequence segment's `localT`). */\n t: number;\n /** A steering path (`layers.0.sprite.color`, `key.sprite.color`, `background.stops.1.color`, …). It must already exist on the spec, as for `setParam`. */\n path: string;\n /** The target value; the key must still validate when applied. */\n value: unknown;\n /** Default `smooth`. */\n ease?: 'step' | 'linear' | 'smooth';\n /** Glide length in ms, starting at `t`. Default 1000 (as live steering); 0 = a cut. */\n dur?: number;\n}\n\n/**\n * Authored change on the scene's own clock — keyframes. A scene without a\n * timeline is unchanged (ambient, today's behaviour); with one, each key\n * glides its path at its time, and the scene can loop. Distinct from the\n * channel's live `track`, whose `t` is a wall-clock stamp: live steering still\n * layers on top, and a steer on a path the timeline animates holds until that\n * path's next key.\n */\nexport interface Timeline {\n /** Repeat every `duration` ms. A looping path's value before its first key is its last key's value (the loop wraps). */\n loop?: boolean;\n /** Loop length in ms; required with `loop`, and at least the latest key's `t`. */\n duration?: number;\n keys: TimelineKey[];\n}\n\nexport interface LayerSpec {\n count: number;\n sprite: SpriteSpec;\n /** Sprite size range in px (font size for emoji/text; ignored for circle). */\n size?: [number, number];\n motion: MotionSpec;\n /** Wrap around the opposite edge when leaving the viewport. Default true. */\n wrap?: boolean;\n /** Flip the sprite horizontally to face its heading. Default false. */\n flip?: boolean;\n /** Per-entity opacity range, both 0..1. Default [1,1]. */\n alpha?: [number, number];\n /**\n * Compositing for this layer. 'lighter' = additive (glow stacking); 'screen' =\n * gentler additive for pale backgrounds; 'multiply' = darkening (shadows,\n * silhouettes). Default source-over. None of these can strobe.\n */\n blend?: 'lighter' | 'screen' | 'multiply';\n /**\n * Fractional spawn window (0 = left/top, 1 = right/bottom). Constrains where\n * entities are PLACED, not where they may travel. Default full viewport.\n */\n region?: { x?: [number, number]; y?: [number, number] };\n /**\n * Sinusoidal opacity breathing. SAFETY: amp is capped (LIMITS.maxPulseAmp),\n * period has a floor (LIMITS.minPulsePeriod — max 2 Hz), and every entity gets\n * its own seeded phase, so a layer can never strobe in unison. Effective alpha\n * is clamped to 0..1.\n *\n * `wave` derives each entity's phase from its spawn position instead of a seeded\n * draw, turning independent breathing into a traveling wave across the field\n * (ripples, wind through grass). `wavelength` is dimensional (px or viewport\n * units); `angle` is the propagation direction in degrees (0 = rightward,\n * default 0). Still flash-safe: neighbors are out of phase by construction.\n */\n pulse?: { amp: number; period: number; wave?: { wavelength: number; angle?: number } };\n /**\n * Per-entity rotation speed in degrees/sec (positive = clockwise).\n * Each entity gets a seeded starting angle. Composes with any motion type.\n * A scalar applies one speed to every entity; a `[min, max]` range gives each\n * entity a seeded speed within the range (like `speed`/`alpha`) — confetti,\n * tumbling debris, foliage. Existing scalar specs are unaffected (the range\n * form draws one extra seeded value, only when present).\n */\n spin?: number | [number, number];\n /**\n * Static per-entity rotation in degrees (positive = clockwise), ±360. A\n * scalar turns every entity the same way; a `[min, max]` range gives each\n * entity a seeded angle — thrown blades, scattered glyphs, a tilted grid.\n * Composes with `spin` (added to its seeded start angle). Note that `spin:\n * [0, 0]` does NOT do this: a zero spin speed renders at angle 0, its\n * seeded phase unused. Structural (baked into entities). The range form\n * draws one seeded value per entity, only when declared, so existing\n * specs keep identical streams.\n */\n rotate?: number | [number, number];\n /**\n * Sinusoidal size breathing, parallel to `pulse` for opacity. `amp` is a\n * fraction of base size (0.3 = ±30 %). `period` in ms with the same\n * flash-safety floor as pulse. Per-entity seeded phase.\n */\n grow?: { amp: number; period: number };\n /**\n * Addressable name for this layer. Enables `setParam` to use `key.field` paths\n * instead of `layers.N.field` indices. Also makes specs self-documenting.\n */\n key?: string;\n /**\n * Exact fractional position {x, y} for a single entity (0 = left/top, 1 = right/bottom).\n * Only valid when `count` is 1 — or, with a `list` / `table` layout, as the\n * top-left anchor of the whole block. Overrides `region` scatter placement.\n */\n position?: {\n x: number;\n y: number;\n /**\n * An offset from `x`/`y` in `min(w, h)` units (px under `units: 'px'`).\n * `x`/`y` are fractions of width and height while every size is a fraction\n * of `min(w, h)`, so parts placed at computed fractions only register at\n * the aspect they were computed for; anchor on a shared fraction (the\n * centre is the only aspect-safe one) and offset in size units instead.\n * Placement, like `x`/`y` (structural). Absent ⇒ 0. **Native:** tvOS\n * ignores the offset until it reads the field.\n */\n dx?: number;\n dy?: number;\n };\n /**\n * Paint-level layer opacity, 0..1 (default 1): multiplies the per-entity\n * `alpha` and the `life` envelope at draw time. Unlike `alpha` (a range baked\n * into every entity at build), it is **paint** — kept out of the structural\n * signature — so `setParam`, a `timeline` key or a sequence `morph` glides it\n * instead of re-seeding the layer. **Native:** ignored ⇒ 1.\n */\n opacity?: number;\n /** Paint-level transform of the whole layer — see `LayerTransform`. */\n transform?: LayerTransform;\n /** The name of a `SaverSpec.groups` entry this layer is painted through (see `LayerGroup`). */\n group?: string;\n /**\n * Inter-entity links. `mode` picks the wiring:\n * - 'nearest' (default): each entity's k nearest neighbors within maxDist.\n * - 'chain': entities connected in order (0-1-2-…) — Mystify polygons, string\n * art. Ignores k/maxDist; `closed` joins the last entity back to the first.\n * - 'random': a fixed golden-ratio-stride wiring (k partners per entity,\n * deterministic, no RNG draws) — breaks the crystalline k-nearest look.\n * `falloff` fades link alpha with distance/maxDist, killing pop-in at the cutoff.\n * Capped at LIMITS.maxLinksK. Layer count must be <= LIMITS.maxLinkLayerCount when set.\n */\n links?: {\n k: number;\n maxDist: number;\n color?: string;\n alpha?: number;\n width?: number;\n mode?: 'nearest' | 'chain' | 'random';\n falloff?: boolean;\n closed?: boolean;\n };\n /**\n * Afterglow trail behind moving entities. Samples past positions analytically\n * (no state, fully deterministic). `length` in ms, `fade` 0..1 (default 1 = full fade).\n */\n trail?: { length: number; fade?: number };\n /**\n * Grid placement instead of random scatter: entities fill cells row-major within\n * `region`. `columns` defaults to an aspect-fit square-ish grid; `jitter` (0..1,\n * scalar or per-axis) offsets each entity within its cell by a seeded fraction of\n * the cell size — `{ y: 1 }` keeps columns crisp while scattering vertically\n * (Matrix rain). Unlocks column effects, LED walls, mosaics, uniform dot fields.\n */\n layout?:\n | { type: 'grid'; columns?: number; jitter?: number | { x?: number; y?: number } }\n /**\n * Data layouts — entities in READING ORDER, no scatter. `list` stacks them\n * in one column `gap` apart (viewport units of min(w,h), default 0.06);\n * `table` fills `columns` row-major with `gap` `{x, y}` (one number = both).\n * Text and emoji sprites take `strings[i]` / `glyphs[i]` in order instead of\n * a seeded pick, and palette `colors[i]` likewise, so N labels or N bars are\n * ONE layer. `position` (with any count) is the block's top-left anchor;\n * without it the block is centred in `region`.\n */\n | { type: 'list'; gap?: number }\n | { type: 'table'; columns: number; gap?: number | { x?: number; y?: number } };\n /**\n * Layer lifecycle for act structure — a pure function of t, no state. Alpha is 0\n * before `enter` (ms), ramps up over `fade` ms (default 1000), holds at 1, then\n * ramps down starting at `exit`. Entities are skipped entirely while at alpha 0.\n */\n life?: { enter?: number; exit?: number; fade?: number };\n /**\n * Sparse events — marks that appear, expand and fade in place, one at a time,\n * with long silences between (the \"one ping\" primitive). Each entity is dark\n * except for a window of `life` ms that recurs every `every` ms at a\n * per-entity offset: `jitter` 1 (default) scatters the offsets (a fixed\n * low-discrepancy sequence — not seeded, so declaring `emit` disturbs no\n * other draw and the same spec times its events identically under every\n * seed), 0 spreads the entities evenly across the period — a metronome, one\n * event at a time as long as `life ≤ every / count`.\n * Inside a window the entity fades in over the first quarter and out over\n * the rest; `grow` scales its size from `grow[0]` to `grow[1]` across the\n * window — expansion rather than travel. A pure function of t. Flash safety:\n * `every` ≥ 1000 ms and `life` ≥ 500 ms, so no entity fires more than once a\n * second and never as a hard cut. Composes with `pulse`, `life`, `trail` and\n * every motion; with `motion.ease` the eased travel restarts on every event.\n */\n emit?: { every: number; life: number; jitter?: number; grow?: [number, number] };\n /**\n * Phase-lock. Replaces the seeded per-entity phases of `pulse`, `grow` and\n * `cycle` with one shared phase (`phase` in turns, 0..1, default 0) and runs\n * those three at `rate` × scene time (default 1). Two layers declaring the\n * same clock breathe in step; different phases give a fixed offset (call and\n * response). `pulse.wave` still adds its position-derived phase on top, so a\n * clocked wave stays a wave. Because a clocked layer moves in unison, its\n * `pulse`/`grow` periods must satisfy `period / rate ≥ 1000 ms` (1 Hz).\n */\n clock?: { phase?: number; rate?: number };\n}\n\n/**\n * Closed-form velocity easing for `drift`, `rise` and `wander`. `settle`\n * starts at the entity's speed and decelerates to rest with time constant\n * `tau` ms — it travels `speed × tau` and stops, a mark flung and coming to\n * rest. `buoyant` starts at rest and approaches the speed over `tau` — a\n * bubble reaching terminal velocity. Position stays an analytic function of\n * t (no integration state). With `emit`, the eased travel restarts from the\n * spawn point on every event. For `wander` only the base velocity eases —\n * the harmonic meander keeps breathing, so a settled wanderer hovers rather\n * than freezes.\n */\nexport interface MotionEase {\n type: 'settle' | 'buoyant';\n tau: number;\n}\n\nexport type SpriteSpec =\n | { kind: 'emoji'; glyphs: string[]; cycle?: CycleSpec }\n | {\n kind: 'text';\n strings: string[];\n color?: string;\n font?: string;\n align?: 'left' | 'center' | 'right';\n baseline?: 'top' | 'middle' | 'bottom';\n maxWidth?: number;\n cycle?: CycleSpec;\n /** See `TextRole`. Absent ⇒ no legibility advisories, no pixel change. */\n role?: TextRole;\n }\n /** `soft` renders a radial falloff (glow orb) instead of a hard disc.\n * `colorWeights` (same length as `colors`) biases the seeded per-entity pick —\n * \"mostly cool tones, occasional ember\" without duplicating entries. */\n | { kind: 'circle'; radius: [number, number]; color: string; soft?: boolean; colors?: string[]; colorWeights?: number[] }\n /** Unfilled circle (bubbles, portals, sonar pings). `width` = stroke width. */\n | { kind: 'ring'; radius: [number, number]; color: string; width?: number; colors?: string[]; colorWeights?: number[] }\n /**\n * A line segment oriented along the entity's instantaneous heading (derived\n * analytically from its motion) with a faded tail — rain that reads as rain,\n * shooting stars, warp stars. `length` is the segment length range; `width` the\n * stroke width.\n */\n | { kind: 'streak'; length: [number, number]; color: string; width?: number; colors?: string[]; colorWeights?: number[] }\n /**\n * Axis-aligned rectangle (rotates with `spin`). `width` is the horizontal size\n * range; `aspect` the height/width ratio range (default [1,1] = squares).\n * `feather` (0..1) softens the edges: that fraction of the half-size fades\n * out toward the border — Rothko's soft-edged block at 0.5–0.8.\n * Mondrian blocks, confetti, city lights.\n */\n | { kind: 'rect'; width: [number, number]; aspect?: [number, number]; color: string; feather?: number; colors?: string[]; colorWeights?: number[] }\n /**\n * A data bar. Entity i draws a bar `length × values[i] / max` long (viewport\n * units of min(w,h)), `thickness` thick, growing from its position toward\n * `direction` (default 'right'). `values` are PAINT — steer\n * `layers.N.sprite.values` and the bars glide; `max` defaults to the largest\n * value. Pair with a `list` layout: a chart is one layer, labels another.\n */\n | {\n kind: 'bar';\n values: number[];\n length: number;\n thickness: number;\n color: string;\n max?: number;\n direction?: 'right' | 'left' | 'up' | 'down';\n colors?: string[];\n colorWeights?: number[];\n }\n /**\n * Regular or custom polygon. `sides` (3..12, default 6) draws a regular\n * n-gon of the seeded `radius` (circumradius), point up; `points` (3..24\n * unit coordinates in −1..1, scaled by the radius) draws any facet — a\n * Picasso shard, a Kandinsky triangle, a Mondrian plane. `soft` feathers\n * the fill from the centre like a soft circle. Rotates with `spin`.\n */\n | { kind: 'polygon'; radius: [number, number]; color: string; sides?: number; points?: Array<[number, number]>; soft?: boolean; colors?: string[]; colorWeights?: number[] }\n /**\n * A freehand mark: a path through `points` (2..24 unit coordinates in\n * −1..1, scaled by the seeded `length`) stroked `width` wide with round\n * joins. `curve: 'smooth'` (default) runs a Catmull-Rom spline through the\n * points, `'linear'` a polyline. `taper` thins the mark to almost nothing at\n * both ends — a brush stroke rather than a line. `orient` turns the path's\n * +x along the entity's heading (like `streak`). Rotates with `spin`. Van\n * Gogh's stroke, Hokusai's contour, O'Keeffe's petal, Basquiat's scrawl.\n */\n | {\n kind: 'stroke';\n length: [number, number];\n points: Array<[number, number]>;\n color: string;\n width?: number;\n curve?: 'smooth' | 'linear';\n taper?: boolean;\n orient?: boolean;\n colors?: string[];\n colorWeights?: number[];\n }\n /**\n * Multi-line text block with deterministic line-breaking. Unlike `text` (one\n * string drawn as a single fillText call), `textBlock` wraps `text` within\n * `maxWidth` using a fixed metrics table so line breaks are identical across\n * platforms (same seed → same frames). All dimensions are viewport-fraction\n * (of `min(w,h)`), not px — addresses the absolute-font-size inconsistency.\n * Use with `count: 1`, `motion: { type: 'static' }`, and `position`.\n */\n | {\n kind: 'textBlock';\n text: string;\n /** Wrap width as a fraction of `min(w,h)` (up to 2.0 — `text-off-screen` catches overflow). */\n maxWidth: number;\n fontSize: number;\n lineHeight?: number;\n /** Moves the painted lines inside the wrap width (ragged edge); never the block. */\n align?: 'left' | 'center' | 'right';\n color?: string;\n reveal?: TextRevealSpec;\n /**\n * Which point of the rendered text (widest line × lines·lineHeight, as\n * `align` lays it out) `position` names. Absent: today's behaviour —\n * `position` is the top-left of the `maxWidth` layout box. With\n * `'center'` the block is centred at `position` on every aspect ratio.\n * Placement, so it is in the structural signature.\n */\n anchor?: TextBlockAnchor;\n /**\n * CSS font family and/or weight/style only (`\"bold monospace\"`,\n * `\"300 'Inter', sans-serif\"`). A size inside it is rejected —\n * `fontSize` owns size. Absent: `system-ui, sans-serif`.\n */\n font?: string;\n /**\n * 0..1 multiplier on the block's paint alpha (default 1). Paint, not\n * carpentry: excluded from the structural signature, so steering it\n * with `dur` glides the block in or out without a rebuild. Declare it\n * (`\"opacity\": 1`) to make the path steerable.\n */\n opacity?: number;\n /** See `TextRole`. Absent ⇒ no legibility advisories, no pixel change. */\n role?: TextRole;\n };\n\n/**\n * What a text layer is *for* — a declaration, not a pixel. `read` says the\n * words must be readable from across the room and opts the layer into\n * `adviseSpec`'s legibility advisories (`text-legibility`, `text-safe-area`).\n * `atmosphere` says the text is texture (a haiku fading in a corner, dim\n * labels on a wall board) and is the same as absent: silent. Changes no\n * pixel anywhere, on any client; never part of the structural signature.\n */\nexport type TextRole = 'read' | 'atmosphere';\n\n/** Compass points of a `textBlock`'s rendered box that `position` may name. */\nexport type TextBlockAnchor =\n | 'top-left' | 'top' | 'top-right'\n | 'left' | 'center' | 'right'\n | 'bottom-left' | 'bottom' | 'bottom-right';\n\n/**\n * Animated typing/deleting for `textBlock`. Layout always runs on the FULL\n * text — reveal only masks which glyphs are painted, so lines never reflow\n * and the block's box never changes size. `progress` is a numeric paint\n * param (excluded from the structural signature), so steering it with\n * `dur`/`ease` animates typing client-side in one call; gliding it back to 0\n * deletes. With center/right `align`, the revealing line stays anchored to\n * its alignment as it types (only left-aligned text reads as a classic\n * typewriter).\n */\nexport interface TextRevealSpec {\n /**\n * 0..1 fraction of the text revealed (default 1 = fully shown). Quantized\n * by `mode`. Steerable paint — glide it to animate typing or deleting.\n */\n progress?: number;\n /**\n * Reveal granularity: per-grapheme (default), per-word, per-line, or\n * `glyphFade` — each glyph fades in over a staggered alpha ramp instead of\n * appearing whole (the caption look). Still a pure function of `progress`.\n */\n mode?: 'typewriter' | 'word' | 'line' | 'glyphFade';\n /**\n * Self-typing rate in graphemes/second from scene start (media time). The\n * effective progress is `min(progress, speed·t/total)` — so a steered\n * `progress` can hold or delete even while `speed` is set. 0 = off.\n */\n speed?: number;\n /**\n * Caret at the reveal frontier. `true` for defaults, or configure blink\n * rate (Hz, full cycles/sec, capped at 3 for flash safety) and color.\n * Blink is a square wave of `t` — deterministic like everything else.\n */\n caret?: boolean | { blink?: number; color?: string };\n /**\n * `glyphFade` only: each glyph's fade window as a fraction of progress\n * (0 exclusive to 1, default 0.15). Small = soft typewriter; large = a\n * wave of overlapping fades. Ignored by the other modes.\n */\n fade?: number;\n}\n\n/** Rotate through sprite variants over time. Each entity offsets by its seeded phase. */\nexport interface CycleSpec {\n period: number;\n}\n\nexport type MotionSpec =\n /**\n * Drift at a per-entity speed picked from `speed` (px/sec) along `angle` degrees\n * (0 = right, 90 = down; default 0). `bidirectional` randomly flips horizontal\n * direction per entity (e.g. fish swimming both ways); `bob` adds a small vertical\n * wobble amplitude (px). Covers horizontal fields, diagonals (toasters) and rain\n * (angle 90).\n */\n | { type: 'drift'; speed: [number, number]; angle?: number; bidirectional?: boolean; bob?: number; ease?: MotionEase }\n /** Rise upward (px/sec) with an optional horizontal sway amplitude (px) — bubbles. */\n | { type: 'rise'; speed: [number, number]; sway?: number; ease?: MotionEase }\n /** Bounce diagonally at a per-entity speed, reflecting off the edges (px/sec). */\n | { type: 'bounce'; speed: [number, number] }\n /** Entity stays exactly where placed. No movement. Use with `position` for pinned elements. */\n | { type: 'static' }\n /**\n * Orbit around a center point. Each entity gets a seeded radius from `radius`\n * and a seeded phase. `speed` is angular velocity in degrees/sec. `center` is\n * fractional {x, y} (default {0.5, 0.5} = viewport center) — or\n * `{ layer: key }` to orbit a single-entity parent layer (moons around a\n * wandering planet). Strictly one level deep: the parent may not itself\n * orbit a layer, and must have `count: 1`.\n */\n | { type: 'orbit'; speed: [number, number]; radius: [number, number]; center?: { x: number; y: number } | { layer: string } }\n /**\n * Organic harmonic drift — the analytic flow field. Each entity moves at a base\n * velocity from `speed` plus 3 seeded sine octaves per axis, producing flowing\n * curved paths (Flurry streams, aurora, jellyfish) with zero simulation state.\n * `angle` fixes the base heading in degrees (omit for a seeded heading per\n * entity); `meander` scales the harmonic amplitude (dimensional, default 0.05\n * viewport units); `coherence` (0..1) blends every entity's harmonics toward a\n * shared layer-level set — at 1 the field undulates in unison (fake flocking).\n */\n | { type: 'wander'; speed: [number, number]; angle?: number; meander?: number; coherence?: number; ease?: MotionEase }\n /**\n * Perspective starfield: entities live on a depth axis and stream toward the\n * viewer, projected as `screen = center + offset / z`. Size and alpha scale\n * with 1/z (small and faint at the far plane, large and fast up close), and z\n * wraps — the honest warp tunnel. `speed` is in depth-units/sec\n * (1 = full near-to-far span per second, capped at LIMITS.maxWarpSpeed).\n */\n | { type: 'warp'; speed: [number, number]; center?: { x: number; y: number } }\n /**\n * Choreographed spline motion: entities traverse `points` (fractional {x,y})\n * over `duration` ms. `curve: 'smooth'` (default) uses Catmull-Rom through the\n * points; 'linear' uses straight segments. `closed` (default true) loops the\n * path; open paths ping-pong. Each entity gets a seeded phase offset along the\n * path, and `scatter` (dimensional) adds a seeded per-entity offset so shared\n * paths don't stack. Figure-eights, sweeping arcs, patrol routes.\n */\n | {\n type: 'path';\n points: Array<{ x: number; y: number }>;\n duration: number;\n curve?: 'linear' | 'smooth';\n closed?: boolean;\n scatter?: number;\n };\n\n/** A validation problem, pointing at a JSON path within the spec. */\nexport interface SpecError {\n path: string;\n message: string;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n errors: SpecError[];\n /** Non-blocking warnings about unknown/misplaced properties or likely authoring mistakes. */\n warnings?: SpecWarning[];\n}\n\n/** An advisory warning (non-blocking). Returned by `adviseSpec`. */\nexport interface SpecWarning {\n path: string;\n code: string;\n message: string;\n /**\n * Viewport-fraction boxes (`x`, `y`, `w`, `h` of `width`/`height`) the\n * warning is about — `text-overlap` carries the two text boxes so an agent\n * can move one without re-deriving the layout. Present only where a\n * warning has geometry to report.\n */\n boxes?: WarningBox[];\n}\n\n/** A rectangle in viewport fractions (x/w of width, y/h of height). */\nexport interface WarningBox {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/** Perf/safety caps enforced by `validateSpec`. */\nexport const LIMITS = {\n maxPerLayer: 400,\n maxTotal: 800,\n maxLayers: 36,\n maxSpeed: 4000, // px/sec — bounds motion so nothing teleports\n maxPulseAmp: 0.5, // opacity breathing amplitude cap\n minPulsePeriod: 500, // ms — caps pulse at 2 Hz (WCAG flash threshold is 3 Hz)\n maxSpin: 360, // degrees/sec — one full revolution per second\n maxRotate: 360, // degrees — static per-entity rotation, one turn either way\n maxGrowAmp: 0.8, // size breathing amplitude cap (fraction of base size)\n maxOrbitSpeed: 180, // degrees/sec — half a revolution per second\n maxLinksK: 8,\n maxLinkLayerCount: 200,\n minCyclePeriod: 500, // ms — same flash-safety floor as pulse\n referenceViewport: 1080, // for validating viewport-unit dimensional caps\n maxTrailLength: 5000, // ms — cap trail duration\n maxTrailSamples: 24, // dots per trail\n minDriftPeriod: 10000, // ms — background drift floor (10 s), gradient and field alike\n maxDriftAmount: 0.3, // fraction of gradient stop shift\n minFieldScale: 0.5, // features per short side — below this the field is one flat blob\n maxFieldScale: 8, // above this a 96 px raster cell spans more than one feature\n maxFieldOctaves: 4,\n minFieldBands: 2,\n maxFieldBands: 8,\n maxFieldQuantize: 8,\n maxFieldDriftAmount: 1, // feature units of domain travel\n maxGhosting: 0.95, // frame persistence cap — bounds the seek warm-up replay\n maxGhostReplayFrames: 120, // fixed-step frames replayed on a non-contiguous seek\n maxMeander: 500, // px — wander harmonic amplitude cap (viewport cap: /referenceViewport)\n maxWarpSpeed: 1.5, // depth-units/sec — full near-to-far span in ~0.7 s at max\n minPathPoints: 2,\n maxPathPoints: 24,\n minPathDuration: 2000, // ms — a path lap can't be faster than this\n maxGridColumns: 100,\n maxTextBlockLength: 2000,\n minTextBlockFontSize: 0.01,\n maxTextBlockFontSize: 0.2,\n maxTextBlockMaxWidth: 2.0, // of min(w,h) — wider than the frame is legal; text-off-screen reports the overflow\n maxRevealSpeed: 120, // graphemes/sec — faster than any readable typing\n maxCaretBlinkHz: 3, // full blink cycles/sec — WCAG 2.3.1 flash-safety cap\n maxSegments: 24,\n minSegmentDuration: 1000, // ms — flash-safety floor: segment cuts are luminance transitions\n maxTransitionDur: 5000,\n minTransitionDur: 200,\n minEmitEvery: 1000, // ms — at most one event per second per entity (flash safety)\n maxTimelineKeys: 256,\n minTimelineKeyInterval: 200, // ms — distinct key times on one path (flash safety; the timeline design's floor)\n maxTimelineKeyDur: 30000, // ms — one key's glide\n maxTimelineDuration: 86400000, // ms — a looping timeline's lap (a day)\n maxLayerTransformOffset: 2, // min(w,h) units — transform x/y and position dx/dy\n maxLayerTransformOffsetPx: 17280, // px, under `units: 'px'` — twice the largest referenceViewport\n maxLayerTransformScale: 8,\n maxLayerTransformRotate: 3600, // degrees\n maxGroups: 16,\n maxEmitEvery: 600000, // ms — ten minutes; longer silences than that are `life.enter`\n minEmitLife: 500, // ms — an event is a smooth envelope, never a cut\n maxEmitGrow: 8, // × base size across an event window\n minClockedPeriod: 1000, // ms — a `clock`ed layer breathes in unison, so 1 Hz not 2\n minClockRate: 0.1,\n maxClockRate: 4,\n defaultListGap: 0.06, // viewport units between list/table cells (40 px in px specs)\n defaultListGapPx: 40,\n minPolygonSides: 3,\n maxPolygonSides: 12,\n maxShapePoints: 24, // polygon.points / stroke.points\n minEaseTau: 100, // ms\n maxEaseTau: 120000, // ms\n} as const;\n\n// ---------------------------------------------------------------------------\n// Sequence envelope — multi-segment timeline over unmodified SaverSpecs\n// ---------------------------------------------------------------------------\n\nexport type SequenceTransition =\n | { type: 'cut' }\n /**\n * Interpolate numbers and hex colours into the next (structurally\n * identical) segment over `dur` ms. Strings step on the first frame —\n * unless `text: 'crossfade'`, which draws each `text` / `textBlock` layer\n * whose string(s) differ twice for the window: the outgoing string at\n * `1 − k`, the incoming at `k` (k = the morph's eased progress). `'dip'`\n * draws the same two passes one after the other instead — the outgoing\n * words fade out over the first half, the incoming fade in over the second —\n * so the two strings never overlap. Default `'step'`, today's behaviour,\n * byte for byte.\n */\n | { type: 'morph'; dur: number; text?: 'step' | 'crossfade' | 'dip' }\n /**\n * Cross-fade into the next segment over `dur` ms: the outgoing segment\n * stays alive on its own canvas and is composited over the incoming one\n * at `1 − easeSmooth(localT / dur)`. Works between unlike segments (no\n * structural requirement). Hosts on the `basic`/`minimal` capability tier\n * render it as `cut` (see `SequenceMountContext.capabilityTier`).\n */\n | { type: 'fade'; dur: number };\n\nexport interface SequenceSegment {\n key: string;\n scene: SaverSpec;\n /** Segment duration in ms. Only the final segment may omit this (holds until input). */\n duration?: number;\n /** How the segment advances: 'auto' (timer), 'input' (external event), 'either'. */\n advance?: 'auto' | 'input' | 'either';\n transition?: SequenceTransition;\n}\n\nexport interface IdleSequence {\n format: 'idle-sequence';\n schemaVersion: 1;\n id: string;\n label: string;\n seed?: number;\n loop: boolean;\n /**\n * What the sequence clock is anchored to. `mount` (default — today's\n * behaviour): every viewer starts at T = 0 when it mounts, so a joiner sees\n * segment 0 (pre-roll semantics). `epoch`: a viewer handed `sequenceBaseT`\n * on its mount context (the host's `Date.now() − epoch`) starts its clock\n * there, so every screen in a room shows the same segment — a late joiner\n * lands mid-loop. `advance: 'input'` holds stay armed under either mode.\n */\n sync?: 'mount' | 'epoch';\n /**\n * Honour a `morph` declared on the last segment at the loop wrap (the lap\n * morphs back into segment 0 instead of cutting). Opt-in: without it a\n * last-segment morph stays a cut at the wrap, as every stored sequence\n * expects. Takes effect only when the whole loop is one morph chain (every\n * segment morphs into the next, and the last is a structural twin of the\n * first) — so every lap reuses the same child and seed; otherwise it is a\n * cut and the validator says why. Needs `loop: true`.\n */\n wrapMorph?: boolean;\n /**\n * A scene drawn under every segment on the sequence's **global** clock —\n * the ground that does not reset at a boundary or under a `sequence.segment`\n * steer. Segments render over it transparently (their `background` and\n * `ghosting` are ignored; the bed may declare its own). Its entities count\n * toward the perf cap together with the largest segment's, since the two\n * are live at once. Steer it with `bed.<path>`. Absent ⇒ every segment\n * paints its own ground, exactly as before the field existed.\n */\n bed?: SaverSpec;\n /**\n * A print finish applied once per composed frame — over bed, segment and\n * any fade together, on the sequence's presentation canvas. Overrides\n * every segment's own `finish` while set; absent, the active segment's\n * `finish` applies when it declares one (a bed's is ignored — the bed is\n * ground, finish the sequence). Children never apply their own.\n */\n finish?: FinishSpec;\n segments: SequenceSegment[];\n}\n","/**\n * Pure helpers for LIVE steering of compiled specs (setParam / applyTrack).\n * A track's deltas address spec fields by dot-path (\"layers.0.count\",\n * \"background.stops.1.color\") or layer key (\"fireflies.count\"). Steering\n * changes existing values only — unknown paths are ignored (the server\n * validates and rejects them; the runtime stays lenient).\n */\nimport { LIMITS, type IdleSequence, type SaverSpec, type SpriteSpec } from './types';\n// Cycle (validate.ts imports structuralSignature from here) is safe: neither\n// module touches the other's exports at load time, only inside functions.\nimport { ignoredPropertyPaths } from './validate';\n\ninterface PathTarget {\n parent: Record<string, unknown> | unknown[];\n key: string | number;\n}\n\nconst UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\nconst STEERABLE_ROOT_KEYS = new Set(['ghosting', 'referenceViewport', 'finish', 'groups']);\n\n/** Resolve a dot-path (key-aware) to its parent + final key; null if absent. */\nexport function resolveSpecPath(spec: unknown, path: string): PathTarget | null {\n if (!spec || typeof spec !== 'object' || !path) return null;\n const parts = path.split('.');\n if (parts.some((p) => UNSAFE_KEYS.has(p))) return null;\n const s = spec as { layers?: Array<Record<string, unknown>> };\n if (parts[0] !== 'layers' && parts[0] !== 'background' && Array.isArray(s.layers)) {\n // A layer's own key wins over a root field of the same name — a layer\n // named \"ghosting\" or \"referenceViewport\" must still resolve to itself,\n // not get shadowed by the identically-named root scalar.\n const idx = s.layers.findIndex((l) => l && l.key === parts[0]);\n if (idx !== -1) {\n parts.splice(0, 1, 'layers', String(idx));\n } else if (!STEERABLE_ROOT_KEYS.has(parts[0]!)) {\n return null;\n }\n }\n // Group membership and a transform's `origin` are enums that can only step\n // — a steer or key on them would jump — so they are not steer targets.\n if (parts[0] === 'layers' && parts.length === 3 && parts[2] === 'group') return null;\n if (parts.length >= 2 && parts[parts.length - 1] === 'origin' && parts[parts.length - 2] === 'transform') return null;\n let node: unknown = spec;\n for (let i = 0; i < parts.length - 1; i++) {\n if (node === null || typeof node !== 'object') return null;\n node = (node as Record<string, unknown>)[parts[i]!];\n }\n if (node === null || typeof node !== 'object') return null;\n const last = parts[parts.length - 1]!;\n const key: string | number = Array.isArray(node) ? Number(last) : last;\n const exists = Array.isArray(node)\n ? Number.isInteger(key as number) && (key as number) >= 0 && (key as number) < node.length\n : last in (node as Record<string, unknown>);\n return exists ? { parent: node as PathTarget['parent'], key } : null;\n}\n\n/**\n * The index form of a key-aware dot-path (`fireflies.sprite.color` →\n * `layers.3.sprite.color`), or null when it does not resolve. Two paths that\n * address the same field compare equal after this — how a live steer finds\n * out whether a `timeline` key animates the field it touches.\n */\nexport function canonicalSpecPath(spec: unknown, path: string): string | null {\n if (!resolveSpecPath(spec, path)) return null;\n const parts = path.split('.');\n const s = spec as { layers?: Array<Record<string, unknown>> };\n if (parts[0] !== 'layers' && parts[0] !== 'background' && Array.isArray(s.layers)) {\n const idx = s.layers.findIndex((l) => l && l.key === parts[0]);\n if (idx !== -1) parts.splice(0, 1, 'layers', String(idx));\n }\n return parts.join('.');\n}\n\n/** Read the value at a dot-path, or undefined when it does not resolve. */\nexport function readSpecPath(spec: unknown, path: string): unknown {\n const loc = resolveSpecPath(spec, path);\n return loc ? (loc.parent as Record<string | number, unknown>)[loc.key] : undefined;\n}\n\nconst TRANSFORM_IDENTITY: Record<string, number> = { x: 0, y: 0, scale: 1, scaleX: 1, rotate: 0 };\n\n/** Two layer `transform` objects with each one's missing fields filled with the identity, so a glide between them never steps (inputs returned as-is otherwise). */\nfunction alignTransform(a: unknown, b: unknown): [unknown, unknown] {\n const isObj = (v: unknown): v is Record<string, unknown> => !!v && typeof v === 'object' && !Array.isArray(v);\n if (!isObj(a) || !isObj(b)) return [a, b];\n let fa: Record<string, unknown> | null = null;\n let fb: Record<string, unknown> | null = null;\n for (const key of new Set([...Object.keys(a), ...Object.keys(b)])) {\n const id = TRANSFORM_IDENTITY[key];\n if (id === undefined) continue;\n if (a[key] === undefined) (fa ??= { ...a })[key] = id;\n if (b[key] === undefined) (fb ??= { ...b })[key] = id;\n }\n return [fa ?? a, fb ?? b];\n}\n\n/**\n * When only one end of a spec lerp declares a layer's paint `opacity` or\n * `transform`, give the other end the identity value (opacity 1, x/y/rotate 0,\n * scale/scaleX 1) so the lerp glides from how the layer actually looks\n * instead of stepping. Returns the inputs themselves when no layer differs —\n * every spec without these fields lerps exactly as it always has.\n */\nfunction alignPaintFields(a: unknown, b: unknown): [unknown, unknown] {\n const la = (a as { layers?: unknown[] } | null)?.layers;\n const lb = (b as { layers?: unknown[] } | null)?.layers;\n if (!Array.isArray(la) || !Array.isArray(lb)) return [a, b];\n let outA: unknown[] | null = null;\n let outB: unknown[] | null = null;\n const n = Math.min(la.length, lb.length);\n for (let i = 0; i < n; i++) {\n const x = la[i] as Record<string, unknown> | null;\n const y = lb[i] as Record<string, unknown> | null;\n if (!x || !y || typeof x !== 'object' || typeof y !== 'object') continue;\n let nx = x;\n let ny = y;\n // A layer that joins or leaves a group keeps the membership through the\n // lerp; the group branch below gives the end without that group an\n // identity entry, so the group's paint glides instead of dropping.\n if ((x.group === undefined) !== (y.group === undefined)) {\n if (x.group === undefined) nx = { ...nx, group: y.group };\n else ny = { ...ny, group: x.group };\n }\n if ((x.opacity === undefined) !== (y.opacity === undefined)) {\n if (x.opacity === undefined) nx = { ...nx, opacity: 1 };\n else ny = { ...ny, opacity: 1 };\n }\n const tx = x.transform as Record<string, unknown> | undefined;\n const ty = y.transform as Record<string, unknown> | undefined;\n if (tx || ty) {\n const fx: Record<string, unknown> = { ...(tx ?? {}) };\n const fy: Record<string, unknown> = { ...(ty ?? {}) };\n let changed = !tx || !ty;\n for (const key of new Set([...Object.keys(fx), ...Object.keys(fy)])) {\n const id = TRANSFORM_IDENTITY[key];\n if (id === undefined) continue;\n if (fx[key] === undefined) { fx[key] = id; changed = true; }\n if (fy[key] === undefined) { fy[key] = id; changed = true; }\n }\n if (changed) { nx = { ...nx, transform: fx }; ny = { ...ny, transform: fy }; }\n }\n if (nx !== x) (outA ??= la.slice())[i] = nx;\n if (ny !== y) (outB ??= lb.slice())[i] = ny;\n }\n let ra: unknown = outA ? { ...(a as object), layers: outA } : a;\n let rb: unknown = outB ? { ...(b as object), layers: outB } : b;\n // Groups: a group present on only one end glides from the identity (no\n // transform, opacity 1); so does a group opacity set on one end only.\n const ga = (a as { groups?: Record<string, Record<string, unknown>> }).groups;\n const gb = (b as { groups?: Record<string, Record<string, unknown>> }).groups;\n if (ga || gb) {\n const na: Record<string, Record<string, unknown>> = { ...(ga ?? {}) };\n const nb: Record<string, Record<string, unknown>> = { ...(gb ?? {}) };\n let changed = !ga || !gb;\n for (const name of new Set([...Object.keys(na), ...Object.keys(nb)])) {\n const x = na[name] ?? {};\n const y = nb[name] ?? {};\n if (!na[name] || !nb[name]) changed = true;\n let nx = x;\n let ny = y;\n if ((x.opacity === undefined) !== (y.opacity === undefined)) {\n if (x.opacity === undefined) nx = { ...nx, opacity: 1 };\n else ny = { ...ny, opacity: 1 };\n changed = true;\n }\n if (!x.transform !== !y.transform) {\n if (!x.transform) nx = { ...nx, transform: {} };\n else ny = { ...ny, transform: {} };\n changed = true;\n }\n na[name] = nx;\n nb[name] = ny;\n }\n if (changed) {\n ra = { ...(ra as object), groups: na };\n rb = { ...(rb as object), groups: nb };\n }\n }\n return [ra, rb];\n}\n\n/** A steering delta as carried on a channel control-track. */\nexport interface SteerDelta {\n t: number;\n path: string;\n value: unknown;\n ease?: string;\n dur?: number;\n}\n\n/** Apply deltas to a deep copy of the spec (last-wins, target values). */\nexport function applyDeltasToSpec(spec: SaverSpec, deltas: SteerDelta[]): SaverSpec {\n const copy = JSON.parse(JSON.stringify(spec)) as SaverSpec;\n for (const d of deltas) {\n const loc = resolveSpecPath(copy, d.path);\n if (loc) (loc.parent as Record<string | number, unknown>)[loc.key] = d.value;\n }\n return copy;\n}\n\nconst HEX = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;\n\nfunction hexToRgb(hex: string): [number, number, number] {\n const h = hex.length === 4 ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex;\n const n = parseInt(h.slice(1), 16);\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\n\nfunction lerpHex(a: string, b: string, k: number): string {\n const ca = hexToRgb(a);\n const cb = hexToRgb(b);\n const mix = ca.map((v, i) => Math.round(v + (cb[i]! - v) * k));\n return `#${mix.map((v) => v.toString(16).padStart(2, '0')).join('')}`;\n}\n\n/**\n * Interpolate between two structurally-similar specs at progress k (0..1).\n * Numbers lerp, hex colours lerp per channel, everything else steps to the\n * target immediately (k > 0). Layer counts round to integers.\n */\nexport function lerpSpec(from: SaverSpec, to: SaverSpec, k: number): SaverSpec {\n const kk = Math.max(0, Math.min(1, k));\n const out = lerpValue(from, to, kk, true) as SaverSpec;\n return out;\n}\n\n/**\n * The walk behind `lerpSpec`, for any value: numbers lerp, hex colours lerp\n * per channel, equal-length arrays and objects recurse, everything else steps\n * to the target at k > 0 (`count` rounds). At a spec's root a `timeline` steps\n * too — two timelines' key times must never blend. No existing spec carries a\n * timeline, so every stored morph and glide is unchanged.\n */\nexport function lerpValue(from: unknown, to: unknown, k: number, specRoot = false, rootKey?: string): unknown {\n if (specRoot) [from, to] = alignPaintFields(from, to);\n if (rootKey === 'transform') [from, to] = alignTransform(from, to);\n const kk = Math.max(0, Math.min(1, k));\n const walk = (a: unknown, b: unknown, key?: string | number, root = false): unknown => {\n if (typeof a === 'number' && typeof b === 'number') {\n const v = a + (b - a) * kk;\n return key === 'count' ? Math.max(1, Math.round(v)) : v;\n }\n if (typeof a === 'string' && typeof b === 'string' && HEX.test(a) && HEX.test(b)) {\n return lerpHex(a, b, kk);\n }\n if (Array.isArray(a) && Array.isArray(b) && a.length === b.length) {\n return b.map((bv, i) => walk(a[i], bv, i));\n }\n if (a && b && typeof a === 'object' && typeof b === 'object' && !Array.isArray(a) && !Array.isArray(b)) {\n const out: Record<string, unknown> = {};\n for (const kName of Object.keys(b as Record<string, unknown>)) {\n const av = (a as Record<string, unknown>)[kName];\n const bv = (b as Record<string, unknown>)[kName];\n out[kName] = root && kName === 'timeline' ? (kk > 0 ? bv : av) : kName === 'transform' ? walk(...alignTransform(av, bv), kName) : walk(av, bv, kName);\n }\n return out;\n }\n return kk > 0 ? b : a; // non-interpolable → step to target\n };\n return walk(from, to, rootKey, specRoot);\n}\n\n/**\n * The string(s) a text layer paints — `strings` of a `text` sprite, `text`\n * of a `textBlock` — or null for every other sprite.\n */\nexport function textStringsOf(sprite: SpriteSpec): string[] | null {\n if (sprite.kind === 'text') return sprite.strings;\n if (sprite.kind === 'textBlock') return [sprite.text];\n return null;\n}\n\n/**\n * Whether the text layer at index `i` paints different words in `a` and\n * `b` — the layers a morph `text: 'crossfade'` draws twice. False for\n * non-text layers and when the strings match.\n */\nexport function textStringsDiffer(a: SaverSpec, b: SaverSpec, i: number): boolean {\n const sa = a.layers[i]?.sprite;\n const sb = b.layers[i]?.sprite;\n if (!sa || !sb) return false;\n const ta = textStringsOf(sa);\n const tb = textStringsOf(sb);\n if (!ta || !tb) return false;\n return ta.length !== tb.length || ta.some((s, j) => s !== tb[j]);\n}\n\n/**\n * True when a morph from `a` to `b` has nothing to interpolate: the two specs\n * differ, yet every difference is a value lerpSpec steps (strings such as\n * `textBlock.text`, mismatched arrays) rather than a number or hex colour it\n * glides. Such a morph looks exactly like a cut. Identical specs return\n * false: a no-op morph is continuity, not a cut. Under `textCrossfade`\n * (the transition declared `text: 'crossfade'`) differing text is something\n * to morph — the words cross-fade — so such twins return false too.\n *\n * Walks `a`/`b` directly rather than sampling `lerpSpec(a, b, 0.5)`: two hex\n * colours a single 8-bit step apart (`#000000` → `#010101`) round their\n * midpoint to the target channel-for-channel, which would make a genuine\n * (if subtle) colour glide look identical to a step. `id`/`label`/\n * `schemaVersion`/layer `key` are identification metadata, never rendered\n * (excluded from `structuralSignature`/`steerablePaths` for the same reason)\n * — a segment pair that differs only there renders identically and is not a\n * morph at all.\n */\nconst NON_RENDERED_KEYS = new Set(['id', 'label', 'schemaVersion', 'key']);\n\nexport function morphNothingMorphable(a: SaverSpec, b: SaverSpec, opts: { textCrossfade?: boolean } = {}): boolean {\n if (opts.textCrossfade && a.layers.some((_, i) => textStringsDiffer(a, b, i))) return false;\n let hasDiff = false;\n let hasGlide = false;\n const walk = (x: unknown, y: unknown, key?: string): void => {\n if (key !== undefined && NON_RENDERED_KEYS.has(key)) return;\n if (x === y) return;\n if (typeof x === 'number' && typeof y === 'number') {\n hasDiff = true;\n hasGlide = true;\n return;\n }\n if (typeof x === 'string' && typeof y === 'string' && HEX.test(x) && HEX.test(y)) {\n const ca = hexToRgb(x);\n const cb = hexToRgb(y);\n if (ca.some((v, i) => v !== cb[i])) {\n hasDiff = true;\n hasGlide = true;\n }\n // else: same colour under a different spelling (case, 3- vs 6-digit) — a no-op, not a difference.\n return;\n }\n if (Array.isArray(x) && Array.isArray(y) && x.length === y.length) {\n for (let i = 0; i < y.length; i++) walk(x[i], y[i]);\n return;\n }\n if (x && y && typeof x === 'object' && typeof y === 'object' && !Array.isArray(x) && !Array.isArray(y)) {\n const keys = new Set([...Object.keys(x as Record<string, unknown>), ...Object.keys(y as Record<string, unknown>)]);\n for (const k of keys) {\n walk((x as Record<string, unknown>)[k], (y as Record<string, unknown>)[k], k);\n }\n return;\n }\n hasDiff = true; // non-interpolable → steps to target\n };\n walk(a, b);\n return hasDiff && !hasGlide;\n}\n\n/**\n * Enumerate all steerable leaf paths in a (resolved) spec. Returns dot-paths\n * like \"layers.0.count\", \"background.stops.1.color\", \"background.bands.2\", etc. Metadata fields\n * (id, label, schemaVersion, seed, units, kind, type, key) are excluded —\n * they describe structure, not tuneable values.\n *\n * Properties the validator flags as unknown or misplaced (e.g. `angle` on a\n * gradient background, `blend` inside a sprite) are excluded too: the\n * renderer never reads them, so advertising them invites a steer that\n * silently does nothing. Same source of truth as validateSpec's\n * \"will be ignored\" warnings (`ignoredPropertyPaths`).\n *\n * Layer keys are NOT substituted: paths always use numeric indices.\n * Consumers can map to key-based paths via resolveSpecPath if needed.\n */\nexport function steerablePaths(spec: unknown): string[] {\n if (!spec || typeof spec !== 'object') return [];\n // `group` (membership) and `origin` are enums that step, not knobs; the\n // `timeline` is authored structure, not a steer target (resolveSpecPath\n // refuses it), so none of them are advertised.\n const SKIP = new Set(['kind', 'type', 'key', 'schemaVersion', 'id', 'label', 'seed', 'units', 'motionIntensity', 'mode', 'curve', 'layer', 'group', 'origin']);\n const SKIP_ROOT = new Set(['timeline']);\n // `bands` (a field background's palette) is indexed like `stops`, so\n // `background.bands.2` is a hex paint path that glides.\n const INDEXED = new Set(['layers', 'stops', 'bands']);\n // Mirror resolveSpecPath's layer-key precedence: a root field named the\n // same as a layer's key resolves to that layer, not the scalar, so don't\n // advertise a root path we can't actually deliver a delta to.\n const layers = (spec as { layers?: unknown }).layers;\n const shadowedRootKeys = new Set(\n Array.isArray(layers)\n ? layers\n .map((l) => (l && typeof l === 'object' ? (l as Record<string, unknown>).key : undefined))\n .filter((k): k is string => typeof k === 'string' && STEERABLE_ROOT_KEYS.has(k))\n : [],\n );\n const out: string[] = [];\n const walk = (node: unknown, prefix: string, key: string): void => {\n if (Array.isArray(node) && INDEXED.has(key)) {\n node.forEach((child, i) => walk(child, `${prefix}.${i}`, ''));\n return;\n }\n if (Array.isArray(node)) {\n if (prefix) out.push(prefix);\n return;\n }\n if (node && typeof node === 'object') {\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n // Group names are user-chosen: a group called `label` is still a group.\n if (SKIP.has(k) && prefix !== 'groups') continue;\n if (!prefix && (shadowedRootKeys.has(k) || SKIP_ROOT.has(k))) continue;\n walk(v, prefix ? `${prefix}.${k}` : k, k);\n }\n return;\n }\n if (prefix) out.push(prefix);\n };\n walk(spec, '', '');\n const ignored = ignoredPropertyPaths(spec);\n if (ignored.length === 0) return out;\n return out.filter((p) => !ignored.some((ig) => p === ig || p.startsWith(`${ig}.`)));\n}\n\n/**\n * Every path a sequence accepts on its track: `sequence.segment` (the\n * clicker), the bed's paths under the `bed.` prefix, and the union of every\n * segment's paths (a segment path lands on whichever segment owns it — see\n * `SequenceInstance.applyTrack`). Deduplicated, numeric layer indices as in\n * `steerablePaths`.\n */\nexport function sequenceSteerablePaths(seq: IdleSequence): string[] {\n const out = new Set<string>(['sequence.segment']);\n if (seq.bed) for (const p of steerablePaths(seq.bed)) out.add(`bed.${p}`);\n for (const seg of seq.segments) for (const p of steerablePaths(seg.scene)) out.add(p);\n return [...out];\n}\n\n/** Smooth (ease-in-out) progress curve used for glides. */\nexport function easeSmooth(k: number): number {\n const c = Math.max(0, Math.min(1, k));\n return c * c * (3 - 2 * c);\n}\n\n/**\n * Fields that require re-seeding entities when they change (placement/motion\n * are baked at build time). Colour/alpha/pulse-only changes redraw in place.\n */\nexport function structuralSignature(spec: SaverSpec): string {\n return JSON.stringify([\n spec.units,\n // Normalized against the same default every renderer uses — an omitted\n // referenceViewport and an explicit 1080 render identically, so they must\n // hash identically or a same-sizing morph gets rejected as structural.\n spec.referenceViewport ?? LIMITS.referenceViewport,\n spec.layers.map((l) => {\n const s = l.sprite as Record<string, unknown>;\n return [\n l.count,\n l.size,\n l.region,\n l.position,\n l.motion,\n l.wrap,\n l.flip,\n l.alpha,\n l.pulse,\n l.spin,\n l.grow,\n l.layout,\n l.emit,\n l.clock,\n l.sprite.kind,\n // Dimensional draws baked into entities: radius (circle/ring), length\n // (streak), width+aspect (rect), palette pick (all shaped sprites).\n s.radius,\n s.length,\n l.sprite.kind === 'rect' ? [s.width, s.aspect] : l.sprite.kind === 'bar' ? [s.length, s.thickness] : undefined,\n Array.isArray(s.colors) ? s.colors.length : undefined,\n s.colorWeights,\n l.sprite.kind === 'emoji'\n ? [l.sprite.glyphs.length, l.sprite.cycle?.period]\n : l.sprite.kind === 'text'\n ? [l.sprite.strings.length, l.sprite.cycle?.period]\n : l.sprite.kind === 'textBlock'\n // `anchor` is placement (in); `font`/`opacity`/`text` are paint\n // (out — opacity must glide). Appended only when set so every\n // existing spec's signature string is byte-identical.\n ? (l.sprite.anchor ? [l.sprite.fontSize, l.sprite.anchor] : [l.sprite.fontSize])\n : undefined,\n // Static rotation is baked into entities (a range draws a seeded\n // angle). Appended only when set — same rule as `anchor` above.\n ...(l.rotate !== undefined ? [l.rotate] : []),\n ];\n }),\n ]);\n}\n","import { structuralSignature } from './steer';\nimport { LIMITS, type IdleSequence, type SequenceTransition } from './types';\n\nexport interface ResolvedSegment {\n index: number;\n localT: number;\n /** Cumulative start time of this segment in the global timeline. */\n startT: number;\n /**\n * Present (true) when the timeline has run past this segment's duration but\n * the segment has `advance: 'input'` and no input has released it yet — the\n * scene keeps animating (`localT` keeps growing) while the show waits for\n * the presenter.\n */\n held?: true;\n}\n\nexport interface ResolveOptions {\n /**\n * Segments below this index have been released by input: a `sequence.segment`\n * steer to index `n` counts as the presenter clicking past every hold before\n * `n`. `SequenceInstance` maintains this; callers resolving a bare timeline\n * leave it at 0, so every `advance: 'input'` hold is honoured.\n */\n releasedBelow?: number;\n}\n\n/** Global start time of segment `index` — the prefix sum of the durations before it. */\nexport function segmentStart(seq: IdleSequence, index: number): number {\n let t = 0;\n const n = Math.max(0, Math.min(index, seq.segments.length - 1));\n for (let i = 0; i < n; i++) t += seq.segments[i]!.duration ?? 0;\n return t;\n}\n\n/**\n * Map global time T to (segmentIndex, localT) via prefix sums of durations.\n * Segments are half-open: [start, start+duration). The final segment may omit\n * duration, in which case it holds indefinitely (T past the last timed segment\n * always resolves to the final one).\n *\n * `advance: 'input'` makes a timed segment hold at its end instead of yielding\n * to the next one — the clicker. `auto` (default) and `either` advance on the\n * timer. A hold is released by a `sequence.segment` steer (see\n * `ResolveOptions.releasedBelow`); the held scene keeps its clock running, so\n * `localT` grows past `duration` rather than freezing.\n *\n * With `loop: true`, T wraps modulo the total duration of all segments — but\n * only once every hold on the current lap has been released; after a wrap\n * every hold is armed again. If the final segment has no duration, looping is\n * over the timed prefix only — the durationless tail is unreachable in loop\n * mode (validated elsewhere).\n */\nexport function resolveSegment(seq: IdleSequence, T: number, opts: ResolveOptions = {}): ResolvedSegment {\n const { segments, loop } = seq;\n if (segments.length === 0) return { index: 0, localT: 0, startT: 0 };\n\n let totalTimed = 0;\n for (const seg of segments) {\n if (seg.duration != null) totalTimed += seg.duration;\n else break;\n }\n\n const t0 = Math.max(0, T);\n\n // Walk the timed prefix once; null means the clock ran off the end.\n const walk = (t: number, releasedBelow: number): ResolvedSegment | null => {\n let cumulative = 0;\n for (let i = 0; i < segments.length; i++) {\n const seg = segments[i]!;\n if (seg.duration == null) {\n // A durationless tail holds forever — except in loop mode, where it\n // is unreachable and the clock wraps instead.\n return loop ? null : { index: i, localT: t - cumulative, startT: cumulative };\n }\n if (t < cumulative + seg.duration) {\n return { index: i, localT: t - cumulative, startT: cumulative };\n }\n if (seg.advance === 'input' && i >= releasedBelow) {\n return { index: i, localT: t - cumulative, startT: cumulative, held: true };\n }\n cumulative += seg.duration;\n }\n return null;\n };\n\n const first = walk(t0, opts.releasedBelow ?? 0);\n if (first) return first;\n\n if (loop && totalTimed > 0) {\n // A fresh lap, with every hold armed again. Always modulo: subtracting\n // one lap (`t0 - totalTimed`) leaves later laps (T ≥ 2×totalTimed) still\n // past the end of the loop, so a released clock lands on the last hold\n // with a growing localT instead of wrapping.\n const wrapped = walk(t0 % totalTimed, 0);\n if (wrapped) return wrapped;\n }\n\n const last = segments.length - 1;\n const lastStart = totalTimed - (segments[last]!.duration ?? 0);\n return { index: last, localT: t0 - lastStart, startT: lastStart };\n}\n\n// ---------------------------------------------------------------------------\n// Render seeds — shared by SequenceInstance (compile.ts) and\n// perceiveSequenceFrame (perceive.ts), so both derive the same seed from the\n// same sequence. Kept in one place after two review rounds found the\n// perception side had drifted from the renderer's exact derivation.\n// ---------------------------------------------------------------------------\n\n/** Whether the boundary from `from` to `from + 1` morphs: same scene structure, `morph` transition. */\nexport function canMorph(seq: IdleSequence, from: number): boolean {\n const seg = seq.segments[from];\n if (!seg || seg.transition?.type !== 'morph') return false;\n const next = seq.segments[from + 1];\n if (!next) return false;\n return structuralSignature(seg.scene) === structuralSignature(next.scene);\n}\n\n/**\n * Walk back through consecutive `morph` boundaries to the chain's origin. A\n * morph-chained segment's entities are never re-seeded at the boundary —\n * they're the same stream continued from wherever the chain started — so its\n * actual render seed (see `segmentRenderSeed`) is always the chain root's,\n * never its own index's.\n */\nexport function morphChainRoot(seq: IdleSequence, index: number): number {\n let i = index;\n while (i > 0 && canMorph(seq, i - 1)) i--;\n return i;\n}\n\n/**\n * Whether a looping sequence's wrap (last segment → segment 0) plays the last\n * segment's `morph`. Opt-in via `wrapMorph: true`, and only when the whole lap\n * is one morph chain — every boundary morphs and the last segment is a\n * structural twin of segment 0 — so the wrap keeps the chain root's seed and\n * entity placement and nothing pops. Otherwise the wrap is the hard cut it has\n * always been (the validator warns when `wrapMorph` asks for one it can't do).\n */\nexport function canWrapMorph(seq: IdleSequence): boolean {\n if (seq.wrapMorph !== true || seq.loop !== true) return false;\n const last = seq.segments.length - 1;\n if (last < 1) return false;\n const seg = seq.segments[last]!;\n if (seg.transition?.type !== 'morph' || seg.duration == null) return false;\n if (morphChainRoot(seq, last) !== 0) return false;\n return structuralSignature(seg.scene) === structuralSignature(seq.segments[0]!.scene);\n}\n\n/** `SpecInstance`'s seed normalization: 0 is falsy, so a valid `seed: 0` lands on 1. */\nexport function normalizeSeed(seed: number): number {\n return (seed >>> 0) || 1;\n}\n\n/**\n * The seed segment `index`'s entities actually render with — its chain\n * root's own seed, else `seq.seed + ` the chain root's index, normalized\n * exactly like `SpecInstance`. `undefined` when neither is set: the same\n * \"unknowable ahead of time\" case a bare `SaverSpec` has via `ctx.seed`,\n * which callers fall back to their own default for (as `perceiveScene` does).\n */\nexport function segmentRenderSeed(seq: IdleSequence, index: number): number | undefined {\n const root = morphChainRoot(seq, index);\n const scene = seq.segments[root]?.scene;\n if (!scene) return undefined;\n const raw = scene.seed ?? (seq.seed !== undefined ? seq.seed + root : undefined);\n return raw === undefined ? undefined : normalizeSeed(raw);\n}\n\n/**\n * The seed the bed's entities actually render with — its own seed, else\n * `seq.seed + LIMITS.maxSegments` (past every segment's `seq.seed + index`,\n * so a bed and segment 0 never share a stream), normalized like\n * `SpecInstance`. `undefined` when there's no bed or no derivable seed.\n */\nexport function bedRenderSeed(seq: IdleSequence): number | undefined {\n if (!seq.bed) return undefined;\n const raw = seq.bed.seed ?? (seq.seed !== undefined ? seq.seed + LIMITS.maxSegments : undefined);\n return raw === undefined ? undefined : normalizeSeed(raw);\n}\n\n/**\n * Whether any scene in the sequence — the sequence itself or any segment —\n * declares a `finish`. Mirrors `SequenceInstance`'s construction-time check:\n * a finish anywhere allocates the presentation pass for the instance's whole\n * lifetime, so this is also what `sequenceSwapCompatible` must agree on\n * before and after a swap.\n */\nexport function sequenceWantsFinish(seq: IdleSequence): boolean {\n return seq.finish !== undefined || seq.segments.some((s) => s.scene.finish !== undefined);\n}\n\n/**\n * Whether a republished sequence can be swapped into a live\n * `SequenceInstance` in place of `prev` without a remount\n * (`SequenceInstance.hotSwapSequence`). True only when every part of the\n * running instance that is fixed at mount — or that a running clock is\n * measured against — is unchanged:\n *\n * - the same number of segments;\n * - every segment's scene is a structural twin (`structuralSignature`) of\n * its counterpart, so the live child's entities survive a `hotSwapSpec`;\n * - the same render seed per segment (`segmentRenderSeed`) — a child's seed\n * is fixed at construction, so a changed seed could only take effect at\n * the next boundary, leaving the room half-swapped;\n * - a `bed` on both sides or neither, structural twins with the same seed\n * when present;\n * - the same top-level `seq.seed`, compared normalized (like the mount-time\n * seed itself) so a change of an exact multiple of 2^32 isn't flagged —\n * but ONLY when either side has a sequence-level `finish`: that's the one\n * place `seq.seed` reaches rendering on its own (`frameFinishSeed` uses the\n * instance's mount-time seed for a sequence-level finish's grain, which a\n * swap cannot update). Without a sequence-level `finish`, every consumer of\n * `seq.seed` is a `segmentRenderSeed`/`bedRenderSeed` fallback, and those\n * are already compared per segment and for the bed below — so when every\n * segment and the bed carry their own seed, `seq.seed` is dead weight and\n * changing it is free;\n * - the same finish presence (`sequenceWantsFinish`) — the presentation\n * pass is allocated once at construction, so a swap that adds or removes\n * every `finish` in the sequence cannot (de)allocate it;\n * - the same `loop` and `sync` (absent `sync` is `'mount'`);\n * - the same `duration`, `advance` (absent is `'auto'`) and `transition`\n * (absent is `cut`; `text` on a morph defaults to `'step'`) on every\n * segment. Durations move segment boundaries under a clock that keeps\n * running, and `clockOffset`/`releasedBelow` on the instance are measured\n * in that timeline — so a timing edit is a remount for now.\n *\n * Paint stays free: colours, words, `background`, `ghosting`, ids and\n * labels, segment keys. Layer `alpha` is a per-entity range baked at build\n * time (like `size`), so it is already covered by the structural twin check\n * above and is not free — an alpha-only edit correctly falls back to a\n * remount. Mirrors idle-server's `sequenceSignaturesEqual` precondition and\n * adds the timing terms.\n */\nexport function sequenceSwapCompatible(prev: IdleSequence, next: IdleSequence): boolean {\n if (prev.segments.length !== next.segments.length) return false;\n // seq.seed only reaches rendering directly through a sequence-level finish\n // (frameFinishSeed); otherwise segmentRenderSeed/bedRenderSeed below already\n // cover every way it can matter, so it's pinned only when one side has one.\n if (prev.finish !== undefined || next.finish !== undefined) {\n if ((prev.seed === undefined) !== (next.seed === undefined)) return false;\n if (prev.seed !== undefined && next.seed !== undefined && normalizeSeed(prev.seed) !== normalizeSeed(next.seed)) return false;\n }\n if (sequenceWantsFinish(prev) !== sequenceWantsFinish(next)) return false;\n if (prev.loop !== next.loop) return false;\n if ((prev.sync ?? 'mount') !== (next.sync ?? 'mount')) return false;\n if (!!prev.bed !== !!next.bed) return false;\n if (prev.bed && next.bed) {\n if (structuralSignature(prev.bed) !== structuralSignature(next.bed)) return false;\n if (bedRenderSeed(prev) !== bedRenderSeed(next)) return false;\n }\n for (let i = 0; i < prev.segments.length; i++) {\n const a = prev.segments[i]!;\n const b = next.segments[i]!;\n if (a.duration !== b.duration) return false;\n if ((a.advance ?? 'auto') !== (b.advance ?? 'auto')) return false;\n if (transitionKey(a.transition) !== transitionKey(b.transition)) return false;\n if (structuralSignature(a.scene) !== structuralSignature(b.scene)) return false;\n if (segmentRenderSeed(prev, i) !== segmentRenderSeed(next, i)) return false;\n }\n return true;\n}\n\n/** A transition's shape with its defaults filled in, so `undefined` and `{ type: 'cut' }` compare equal. */\nfunction transitionKey(tr: SequenceTransition | undefined): string {\n if (!tr || tr.type === 'cut') return 'cut';\n if (tr.type === 'morph') return `morph:${tr.dur}:${tr.text ?? 'step'}`;\n return `fade:${tr.dur}`;\n}\n","/**\n * `timeline` — authored keyframes on a scene's own clock.\n *\n * Everything here is a pure function of `(spec, t)`: resolving a scene at a\n * time never depends on what was rendered before, so a timeline scene is as\n * seekable and frame-addressable as any other (ghosting warm-up replays call\n * `resolveTimelineAt` at each replay frame's own time). A spec without a\n * `timeline` is returned untouched, which is what keeps every existing scene\n * byte-identical.\n *\n * Semantics:\n * - Keys address the same dot-paths as live steering; a path must already\n * exist on the spec (a key cannot create a field).\n * - A key glides from wherever its path is at `t` to `value` over `dur` ms\n * (default 1000, the live-steering default; 0 is a cut), eased `smooth`\n * unless it says otherwise. Overlapping glides are fine: the later one\n * starts from the earlier one's in-flight value.\n * - Without `loop`, a path holds the base spec's value before its first key.\n * - With `loop`, time wraps every `duration` ms and a path's value before its\n * first key is its LAST key's value — the lap is one closed cycle, and lap 1\n * looks exactly like lap 7 (the value depends only on `t mod duration`).\n */\nimport type { SaverSpec, Timeline, TimelineKey } from './types';\nimport { applyDeltasToSpec, canonicalSpecPath, easeSmooth, lerpValue, readSpecPath } from './steer';\n\n/** Default glide length for a key without `dur` — the same as a live steer's. */\nexport const DEFAULT_KEY_DUR = 1000;\n\ntype Tracks = Map<string, TimelineKey[]>;\nconst tracksCache = new WeakMap<Timeline, { spec: SaverSpec; tracks: Tracks }>();\n\n/** The spec without its `timeline` (a shallow copy — the layers are shared, never mutated). */\nexport function withoutTimeline(spec: SaverSpec): SaverSpec {\n if (!spec.timeline) return spec;\n const rest: Partial<SaverSpec> = { ...spec };\n delete rest.timeline;\n return rest as SaverSpec;\n}\n\n/**\n * The spec's keys grouped by the field they animate (index-form path), each\n * group sorted by time (stable, so equal times keep authored order and the\n * later one wins). Keys whose path does not resolve are dropped — the\n * validator rejects them, and the runtime stays lenient like steering.\n */\nexport function timelineTracks(spec: SaverSpec): Tracks {\n const tl = spec.timeline;\n if (!tl) return new Map();\n const hit = tracksCache.get(tl);\n if (hit && hit.spec === spec) return hit.tracks;\n const base = withoutTimeline(spec);\n const tracks: Tracks = new Map();\n for (const k of tl.keys ?? []) {\n const cp = canonicalSpecPath(base, k.path);\n if (!cp) continue;\n const list = tracks.get(cp) ?? [];\n list.push(k);\n tracks.set(cp, list);\n }\n for (const list of tracks.values()) list.sort((a, b) => a.t - b.t);\n tracksCache.set(tl, { spec, tracks });\n return tracks;\n}\n\n/** Scene time folded into the timeline's own clock: `t mod duration` under `loop`, else `t`. */\nexport function timelineLocalTime(tl: Timeline, t: number): number {\n const d = tl.duration ?? 0;\n if (tl.loop && d > 0) return ((t % d) + d) % d;\n return t;\n}\n\nfunction ease(k: TimelineKey, x: number): number {\n const c = x <= 0 ? 0 : x >= 1 ? 1 : x;\n if (k.ease === 'step') return c >= 1 ? 1 : 0;\n if (k.ease === 'linear') return c;\n return easeSmooth(c);\n}\n\n/** One path's value at timeline-local time `tt`, starting from `start`. */\nfunction evalTrack(keys: TimelineKey[], start: unknown, tt: number, leaf?: string): unknown {\n let from = start;\n let key: TimelineKey | null = null;\n const at = (tau: number): unknown => {\n if (!key) return from;\n const dur = key.dur ?? DEFAULT_KEY_DUR;\n if (dur <= 0 || tau >= key.t + dur) return key.value;\n return lerpValue(from, key.value, ease(key, (tau - key.t) / dur), false, leaf);\n };\n for (const k of keys) {\n if (k.t > tt) break;\n from = at(k.t);\n key = k;\n }\n return at(tt);\n}\n\n/**\n * The scene at time `t` with every key applied — and without its `timeline`,\n * so the result can be rendered, perceived, lerped or steered like any plain\n * spec. A spec without a timeline comes back as the same object.\n */\nexport function resolveTimelineAt(spec: SaverSpec, t: number): SaverSpec {\n const tl = spec.timeline;\n if (!tl) return spec;\n const base = withoutTimeline(spec);\n const tracks = timelineTracks(spec);\n if (tracks.size === 0) return base;\n const tt = timelineLocalTime(tl, t);\n const deltas: Array<{ t: number; path: string; value: unknown }> = [];\n for (const [path, keys] of tracks) {\n const start = tl.loop ? keys[keys.length - 1]!.value : readSpecPath(base, path);\n deltas.push({ t: 0, path, value: evalTrack(keys, start, tt, path.slice(path.lastIndexOf('.') + 1)) });\n }\n return applyDeltasToSpec(base, deltas);\n}\n\n/**\n * When the timeline next takes a path back: the scene time of that path's\n * next key after `t`, and that key's glide length — or null when no key will\n * ever touch it again (no key on the path, or a non-looping timeline past its\n * last key). A live steer on the path holds until `at`, then glides back to\n * the timeline over `dur`.\n */\nexport function nextKeyAfter(spec: SaverSpec, path: string, t: number): { at: number; dur: number } | null {\n const tl = spec.timeline;\n if (!tl) return null;\n const cp = canonicalSpecPath(withoutTimeline(spec), path);\n const keys = cp ? timelineTracks(spec).get(cp) : undefined;\n if (!keys || keys.length === 0) return null;\n const tt = timelineLocalTime(tl, t);\n const next = keys.find((k) => k.t > tt);\n if (next) return { at: t + (next.t - tt), dur: next.dur ?? DEFAULT_KEY_DUR };\n if (tl.loop && (tl.duration ?? 0) > 0) {\n const first = keys[0]!;\n return { at: t + (tl.duration! - tt) + first.t, dur: first.dur ?? DEFAULT_KEY_DUR };\n }\n return null;\n}\n\n/**\n * Scene times (timeline-local; within one lap under `loop`) where the keys'\n * combined state is worth checking: time 0, and every key's start, end and\n * glide quarter-points. Two keys can each be valid alone and invalid together\n * (a `clock.rate` and a `pulse.period` the flash floor bounds as a ratio), so\n * validation samples the composed scene here. `dense: false` keeps only the\n * starts and ends, for the per-steer check a live viewer runs. Capped (evenly\n * subsampled) so a 256-key timeline stays cheap to check.\n */\nexport function timelineSampleTimes(spec: SaverSpec, dense = true, cap = 120, only?: (path: string) => boolean): number[] {\n const tl = spec.timeline;\n if (!tl) return [];\n const d = tl.duration ?? 0;\n const fold = (t: number): number => (tl.loop && d > 0 ? ((t % d) + d) % d : t);\n // Every key's start and end is always checked (≤ 2 × 256): a settled state\n // must never be thinned away — the last key's end is the state a scene\n // stays in. Only the in-glide quarter-points share a budget (`cap`).\n // `only` limits the keys to those on matching (index-form) paths.\n const bounds = new Set<number>([0]);\n const extras = new Set<number>();\n const keys: TimelineKey[] = [];\n for (const [path, list] of timelineTracks(spec)) if (!only || only(path)) keys.push(...list);\n for (const k of keys) {\n if (!Number.isFinite(k.t)) continue;\n const dur = k.dur ?? DEFAULT_KEY_DUR;\n bounds.add(fold(k.t));\n bounds.add(fold(k.t + dur));\n if (dense) for (const f of [0.25, 0.5, 0.75]) extras.add(fold(k.t + dur * f));\n }\n let extra = [...extras].filter((t) => !bounds.has(t)).sort((a, b) => a - b);\n if (extra.length > cap) {\n const step = extra.length / cap;\n extra = Array.from({ length: cap }, (_, i) => extra[Math.floor(i * step)]!);\n }\n return [...new Set([...bounds, ...extra])].filter(Number.isFinite).sort((a, b) => a - b);\n}\n\n/** The absolute scene times at or after `now` where `timelineSampleTimes` fall — the next lap's occurrences under `loop`. */\nexport function timelineSampleTimesAfter(spec: SaverSpec, now: number, dense = false, only?: (path: string) => boolean): number[] {\n const tl = spec.timeline;\n if (!tl) return [];\n const local = timelineSampleTimes(spec, dense, 120, only);\n const d = tl.duration ?? 0;\n if (tl.loop && d > 0) {\n const phase = ((now % d) + d) % d;\n return local.map((s) => now + (((s - phase) % d) + d) % d).sort((a, b) => a - b);\n }\n return local.filter((s) => s > now);\n}\n","import { LIMITS, SCHEMA_VERSION, type IdleSequence, type SaverSpec, type SpecError, type SpecWarning, type ValidationResult } from './types';\nimport { applyDeltasToSpec, canonicalSpecPath, morphNothingMorphable, readSpecPath, structuralSignature } from './steer';\nimport { canWrapMorph, morphChainRoot } from './sequence';\nimport { DEFAULT_KEY_DUR, resolveTimelineAt, timelineSampleTimes, timelineTracks, withoutTimeline } from './timeline';\n\nconst HEX = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;\nconst isObj = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null && !Array.isArray(v);\nconst isStr = (v: unknown): v is string => typeof v === 'string';\nconst isNum = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v);\nconst isRange = (v: unknown): v is [number, number] =>\n Array.isArray(v) && v.length === 2 && isNum(v[0]) && isNum(v[1]) && v[0] <= v[1];\n\n// Known properties at each level — used to detect unknown/misplaced fields\nconst KNOWN_TOP = new Set(['schemaVersion', 'id', 'label', 'seed', 'motionIntensity', 'density', 'units', 'referenceViewport', 'background', 'layers', 'ghosting', 'finish', 'timeline', 'groups']);\nconst KNOWN_FINISH = new Set(['grain', 'dither', 'animate']);\nconst KNOWN_LAYER = new Set([\n 'count', 'sprite', 'motion', 'size', 'wrap', 'flip', 'alpha', 'blend',\n 'region', 'pulse', 'spin', 'grow', 'key', 'position', 'trail', 'links',\n 'layout', 'life', 'emit', 'clock', 'rotate', 'opacity', 'transform', 'group',\n]);\nconst KNOWN_TRANSFORM = new Set(['x', 'y', 'scale', 'scaleX', 'rotate', 'origin']);\nconst KNOWN_GROUP = new Set(['transform', 'opacity']);\nconst GROUP_NAME = /^[A-Za-z][A-Za-z0-9_-]{0,31}$/;\nconst KNOWN_POSITION = new Set(['x', 'y', 'dx', 'dy']);\nconst KNOWN_TIMELINE = new Set(['loop', 'duration', 'keys']);\nconst KNOWN_TIMELINE_KEY = new Set(['t', 'path', 'value', 'ease', 'dur']);\nconst KNOWN_CIRCLE = new Set(['kind', 'radius', 'color', 'soft', 'colors', 'colorWeights']);\nconst KNOWN_RING = new Set(['kind', 'radius', 'color', 'width', 'colors', 'colorWeights']);\nconst KNOWN_STREAK = new Set(['kind', 'length', 'color', 'width', 'colors', 'colorWeights']);\nconst KNOWN_RECT = new Set(['kind', 'width', 'aspect', 'color', 'feather', 'colors', 'colorWeights']);\nconst KNOWN_BAR = new Set(['kind', 'values', 'length', 'thickness', 'color', 'max', 'direction', 'colors', 'colorWeights']);\nconst KNOWN_POLYGON = new Set(['kind', 'radius', 'color', 'sides', 'points', 'soft', 'colors', 'colorWeights']);\nconst KNOWN_STROKE = new Set(['kind', 'length', 'points', 'color', 'width', 'curve', 'taper', 'orient', 'colors', 'colorWeights']);\nconst KNOWN_EMOJI = new Set(['kind', 'glyphs', 'cycle']);\nconst KNOWN_TEXT = new Set(['kind', 'strings', 'color', 'font', 'align', 'baseline', 'maxWidth', 'cycle', 'role']);\nconst KNOWN_TEXT_BLOCK = new Set(['kind', 'text', 'maxWidth', 'fontSize', 'lineHeight', 'align', 'color', 'reveal', 'anchor', 'font', 'opacity', 'role']);\nconst TEXT_ROLES = new Set(['read', 'atmosphere']);\nconst TEXT_BLOCK_ANCHORS = new Set(['top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right']);\n/**\n * A CSS length inside a textBlock `font` — size belongs to `fontSize`. No\n * trailing boundary check: a `\\b`-based (or lookahead-based) version misses\n * \"50% monospace\" (`%` isn't a word character, so there is no boundary after\n * it when the next char is whitespace) and \"14pxmonospace\" (glued straight\n * onto the family name, so the word boundary between two word characters\n * passes it through). The leading `\\d` immediately before the unit is enough\n * to identify an embedded size regardless of what follows it.\n */\nconst FONT_SIZE_RE = /\\d(?:px|pt|pc|em|rem|ex|ch|vw|vh|vmin|vmax|%)/i;\nconst KNOWN_REVEAL = new Set(['progress', 'mode', 'speed', 'caret', 'fade']);\nconst KNOWN_REVEAL_CARET = new Set(['blink', 'color']);\nconst KNOWN_DRIFT = new Set(['type', 'speed', 'angle', 'bidirectional', 'bob', 'ease']);\nconst KNOWN_RISE = new Set(['type', 'speed', 'sway', 'ease']);\nconst KNOWN_BOUNCE = new Set(['type', 'speed']);\nconst KNOWN_STATIC = new Set(['type']);\nconst KNOWN_ORBIT = new Set(['type', 'speed', 'radius', 'center']);\nconst KNOWN_WANDER = new Set(['type', 'speed', 'angle', 'meander', 'coherence', 'ease']);\nconst KNOWN_WARP = new Set(['type', 'speed', 'center']);\nconst KNOWN_PATH = new Set(['type', 'points', 'duration', 'curve', 'closed', 'scatter']);\nconst KNOWN_BG_SOLID = new Set(['type', 'color']);\nconst KNOWN_BG_GRADIENT = new Set(['type', 'stops', 'band', 'drift']);\nconst KNOWN_BG_FIELD = new Set(['type', 'scale', 'octaves', 'warp', 'quantize', 'bands', 'drift', 'seed']);\nconst KNOWN_FIELD_DRIFT = new Set(['period', 'amount']);\n\n// Layer-level properties that models commonly misplace inside sprite\nconst LAYER_PROPS_ON_SPRITE = new Set(['blend', 'trail', 'alpha', 'pulse', 'spin', 'grow', 'region', 'links', 'flip', 'wrap', 'key', 'emit', 'clock', 'life', 'layout', 'rotate']);\n\nfunction unknownKeys(obj: Record<string, unknown>, known: Set<string>): string[] {\n return Object.keys(obj).filter((k) => !known.has(k));\n}\n\n/**\n * The unit a spec's dimensional values are written in, for error messages.\n * Mirrors the compiler: anything but an explicit `units: 'px'` is viewport\n * units (fractions of min(width, height)), so a message must not say \"px\"\n * to an author who never opted into px.\n */\nfunction dimUnit(spec: unknown): string {\n return isObj(spec) && spec.units === 'px' ? 'px' : 'fractions of min(width, height)';\n}\n\n/**\n * Bound and unit for a layer offset (`transform.x`/`y`, `position.dx`/`dy`):\n * ±2 in min(w, h) units, or px under `units: 'px'` — where the renderer reads\n * the same numbers as pixels.\n */\nfunction offsetBound(spec: unknown): [number, string] {\n return isObj(spec) && spec.units === 'px'\n ? [LIMITS.maxLayerTransformOffsetPx, 'px']\n : [LIMITS.maxLayerTransformOffset, 'min(w, h) units'];\n}\n\n/** \"must be a [min,max] range of positive <unit>\" — unit-aware (see dimUnit). */\nfunction rangeMsg(spec: unknown, note?: string): string {\n return `must be a [min,max] range of positive ${dimUnit(spec)}${note ? ` (${note})` : ''}`;\n}\n\n/**\n * A scalar-only positive number (ring/streak/stroke `width`, bar `length`,\n * links `maxDist`, …). A [min,max] range here is the common slip — most size\n * fields ARE ranges — and reporting \"must be > 0\" for `[0.003, 0.006]`\n * (whose values are all > 0) sends the author hunting for the wrong bug.\n */\nfunction positiveScalar(v: unknown, path: string, err: (p: string, m: string) => void, msg = 'must be > 0'): void {\n if (Array.isArray(v)) err(path, 'must be a single number > 0, not a [min,max] range');\n else if (!isNum(v) || v <= 0) err(path, msg);\n}\n\n/**\n * Validate an untrusted (agent- or JSON-authored) spec structurally + semantically.\n * Returns typed errors and warnings; never throws. `compileSaver` refuses to run an invalid spec.\n *\n * Warnings are non-blocking advisories about unknown/misplaced properties and\n * near-zero speeds. They don't prevent compilation but indicate likely authoring mistakes.\n */\n/**\n * Normalize: if a sprite has `colors[]` but no `color`, default `color` to\n * `colors[0]`. Author intent is unambiguous (pick from the palette), and\n * requiring both is a known footgun (F3). Mutates the spec in place — the\n * added field is always correct.\n */\nfunction normalizeColors(spec: unknown): void {\n if (!isObj(spec) || !Array.isArray(spec.layers)) return;\n for (const layer of spec.layers) {\n if (!isObj(layer)) continue;\n const sprite = (layer as Record<string, unknown>).sprite;\n if (!isObj(sprite)) continue;\n const sp = sprite as Record<string, unknown>;\n if (Array.isArray(sp.colors) && sp.colors.length > 0 && sp.color === undefined) {\n sp.color = sp.colors[0];\n }\n }\n}\n\nexport function validateSpec(spec: unknown): ValidationResult {\n normalizeColors(spec);\n return validateSpecCore(spec);\n}\n\n/**\n * Dot-paths (numeric layer indices, as `steerablePaths` spells them) of every\n * property the validator flags as unknown or misplaced — i.e. fields the\n * renderer never reads, so steering them does nothing. Pure: unlike\n * `validateSpec` it never normalises colours into the caller's spec.\n */\nexport function ignoredPropertyPaths(spec: unknown): string[] {\n if (!isObj(spec)) return [];\n return (validateSpecCore(spec).warnings ?? [])\n .filter((w) => w.code === 'unknown-property' || w.code === 'misplaced-property')\n .map((w) => w.path.replace(/\\[(\\d+)\\]/g, '.$1'));\n}\n\n/**\n * Validity of only the parts of a spec that `paths` (index-form dot-paths,\n * as `canonicalSpecPath` spells them) live in: each touched layer, the\n * background, the finish — plus the cross-layer entity cap. A layer's rules\n * (the `clock`/`pulse`/`grow` flash floors, `emit`, orbit parents) are all\n * judged inside that layer, so a change confined to layer N can only break\n * layer N or the total. Any other top-level path falls back to the full\n * `validateSpec`. For the timeline's composed-state checks, which run at every\n * key boundary and on every live steer: the whole-spec check costs a\n * full validation per sample, this one a layer or two.\n */\nexport function validateSpecPaths(spec: SaverSpec, paths: Iterable<string>): boolean {\n const layers = new Set<number>();\n let background = false;\n let finish = false;\n let groups = false;\n for (const p of paths) {\n // A layer's `key`, `count` or `motion` is what another layer's orbit\n // parent refers to — a change there can break a layer it doesn't live in.\n if (/^layers\\.\\d+(\\.(key|count|motion)(\\.|$)|$)/.test(p)) return validateSpec(spec).valid;\n // Replacing `groups` whole can drop a name a member still references.\n if (p === 'groups') return validateSpec(spec).valid;\n const [head, idx] = p.split('.');\n if (head === 'layers' && idx !== undefined && /^\\d+$/.test(idx)) layers.add(Number(idx));\n else if (head === 'background') background = true;\n else if (head === 'finish') finish = true;\n else if (head === 'groups') groups = true;\n else return validateSpec(spec).valid;\n }\n let ok = true;\n const err = (): void => { ok = false; };\n const warn: WarnFn = () => undefined;\n if (!Array.isArray(spec.layers)) return false;\n for (const i of layers) {\n const layer = spec.layers[i];\n if (layer === undefined) return false;\n validateLayer(layer, `layers[${i}]`, err, warn, spec);\n // The one spec-level rule a layer change can break: textBlock sizes are\n // viewport fractions, so `units: 'px'` rejects a textBlock layer (see\n // validateSpecCore).\n if (spec.units === 'px' && isObj(layer) && isObj(layer.sprite) && layer.sprite.kind === 'textBlock') ok = false;\n }\n if (background && spec.background !== undefined) validateBackground(spec.background, err, warn);\n if (finish && spec.finish !== undefined) validateFinish(spec.finish, 'finish', err, warn);\n // A group's paint cannot break a member layer's rules — only the group itself.\n if (groups && spec.groups !== undefined) validateGroups(spec.groups, err, warn, spec);\n if (layers.size > 0) {\n const total = spec.layers.reduce((n, l) => n + (isObj(l) && isNum(l.count) ? l.count : 0), 0);\n if (total > LIMITS.maxTotal) ok = false;\n }\n return ok;\n}\n\nfunction validateSpecCore(spec: unknown): ValidationResult {\n const errors: SpecError[] = [];\n const warnings: SpecWarning[] = [];\n const err = (path: string, message: string): void => void errors.push({ path, message });\n const warn = (path: string, code: string, message: string): void => void warnings.push({ path, code, message });\n\n if (!isObj(spec)) return { valid: false, errors: [{ path: '', message: 'spec must be an object' }], warnings: [] };\n\n if (spec.schemaVersion !== SCHEMA_VERSION) err('schemaVersion', `must be ${SCHEMA_VERSION}`);\n if (!isStr(spec.id) || spec.id.trim() === '') err('id', 'must be a non-empty string');\n if (!isStr(spec.label) || spec.label.trim() === '') err('label', 'must be a non-empty string');\n if (spec.seed !== undefined && !isNum(spec.seed)) err('seed', 'must be a number');\n if (spec.motionIntensity !== undefined && !['calm', 'moderate', 'energetic'].includes(spec.motionIntensity as string)) {\n err('motionIntensity', 'must be calm | moderate | energetic');\n }\n if (spec.density !== undefined && !['sparse', 'normal', 'dense'].includes(spec.density as string)) {\n err('density', 'must be sparse | normal | dense');\n }\n if (spec.units !== undefined && spec.units !== 'px' && spec.units !== 'viewport') {\n err('units', \"must be 'px' | 'viewport'\");\n }\n if (spec.units === 'px' && Array.isArray(spec.layers)) {\n for (const l of spec.layers) {\n if (isObj(l) && isObj((l as Record<string, unknown>).sprite) && ((l as Record<string, unknown>).sprite as Record<string, unknown>).kind === 'textBlock') {\n err('units', \"textBlock dimensions are viewport fractions — units: 'px' is not supported with textBlock sprites\");\n break;\n }\n }\n }\n if (spec.referenceViewport !== undefined) {\n if (!isNum(spec.referenceViewport) || spec.referenceViewport < 100 || spec.referenceViewport > 8640) {\n err('referenceViewport', 'must be a number between 100 and 8640');\n }\n }\n if (spec.ghosting !== undefined && (!isNum(spec.ghosting) || spec.ghosting < 0 || spec.ghosting > LIMITS.maxGhosting)) {\n err('ghosting', `must be a number 0..${LIMITS.maxGhosting}`);\n }\n\n for (const k of unknownKeys(spec, KNOWN_TOP)) {\n warn(k, 'unknown-property', `unknown top-level property '${k}' — will be ignored`);\n }\n\n if (spec.background !== undefined) validateBackground(spec.background, err, warn);\n if (spec.finish !== undefined) validateFinish(spec.finish, 'finish', err, warn);\n if (spec.groups !== undefined) validateGroups(spec.groups, err, warn, spec);\n\n if (!Array.isArray(spec.layers) || spec.layers.length === 0) {\n err('layers', 'must be a non-empty array');\n } else {\n if (spec.layers.length > LIMITS.maxLayers) err('layers', `at most ${LIMITS.maxLayers} layers`);\n let total = 0;\n spec.layers.forEach((layer, i) => {\n total += isObj(layer) && isNum(layer.count) ? layer.count : 0;\n validateLayer(layer, `layers[${i}]`, err, warn, spec);\n });\n if (total > LIMITS.maxTotal) err('layers', `total entities ${total} exceeds cap ${LIMITS.maxTotal}`);\n }\n\n // Keys are checked against the base spec, so only once the base is valid.\n if (spec.timeline !== undefined && errors.length === 0) validateTimeline(spec as unknown as SaverSpec, err, warn);\n\n return { valid: errors.length === 0, errors, warnings };\n}\n\n/** A paint `transform` (a layer's, or a group's — `anchorOk: false` forbids `origin: 'anchor'`). */\nfunction validateTransform(tf: unknown, path: string, err: (p: string, m: string) => void, warn: WarnFn, spec: unknown, anchorOk: boolean): void {\n if (!isObj(tf)) return err(path, 'must be an object {x?, y?, scale?, scaleX?, rotate?, origin?}');\n for (const k of unknownKeys(tf, KNOWN_TRANSFORM)) warn(`${path}.${k}`, 'unknown-property', `unknown transform property '${k}' — will be ignored`);\n const [off, unit] = offsetBound(spec);\n const sc = LIMITS.maxLayerTransformScale;\n for (const axis of ['x', 'y'] as const) {\n if (tf[axis] !== undefined && (!isNum(tf[axis]) || Math.abs(tf[axis] as number) > off)) err(`${path}.${axis}`, `must be a number within ±${off} (${unit})`);\n }\n if (tf.scale !== undefined && (!isNum(tf.scale) || tf.scale < 0 || tf.scale > sc)) err(`${path}.scale`, `must be a number 0..${sc}`);\n if (tf.scaleX !== undefined && (!isNum(tf.scaleX) || Math.abs(tf.scaleX) > sc)) err(`${path}.scaleX`, `must be a number within ±${sc} (negative mirrors)`);\n if (tf.rotate !== undefined && (!isNum(tf.rotate) || Math.abs(tf.rotate) > LIMITS.maxLayerTransformRotate)) {\n err(`${path}.rotate`, `must be a number of degrees within ±${LIMITS.maxLayerTransformRotate}`);\n }\n if (tf.origin !== undefined) {\n if (tf.origin !== 'viewport' && tf.origin !== 'anchor') err(`${path}.origin`, \"must be 'viewport' | 'anchor'\");\n else if (tf.origin === 'anchor' && !anchorOk) err(`${path}.origin`, \"a group transform always turns about the viewport centre — 'anchor' is for a layer's own transform\");\n }\n}\n\n/** `groups`: named paint sets — see `LayerGroup`. */\nfunction validateGroups(groups: unknown, err: (p: string, m: string) => void, warn: WarnFn, spec: unknown): void {\n if (!isObj(groups)) return err('groups', 'must be an object of named groups {name: {transform?, opacity?}}');\n const names = Object.keys(groups);\n if (names.length > LIMITS.maxGroups) err('groups', `at most ${LIMITS.maxGroups} groups`);\n for (const name of names) {\n const p = `groups.${name}`;\n if (!GROUP_NAME.test(name)) err(p, 'group names are 1–32 letters, digits, - or _, starting with a letter');\n const g = groups[name];\n if (!isObj(g)) { err(p, 'must be an object {transform?, opacity?}'); continue; }\n for (const k of unknownKeys(g, KNOWN_GROUP)) warn(`${p}.${k}`, 'unknown-property', `unknown group property '${k}' — will be ignored`);\n if (g.opacity !== undefined && (!isNum(g.opacity) || g.opacity < 0 || g.opacity > 1)) err(`${p}.opacity`, 'must be a number 0..1');\n if (g.transform !== undefined) validateTransform(g.transform, `${p}.transform`, err, warn, spec, false);\n }\n}\n\n/**\n * `timeline`: each key's path must already exist on the spec (as for\n * `setParam`) and the spec must still validate with the key's value applied.\n * Distinct key times on one path sit at least `minTimelineKeyInterval` apart\n * (across the wrap too, under `loop`) — the flash-safety floor that replaces a\n * sequence's 1 s segment minimum for change inside a scene.\n */\nfunction validateTimeline(spec: SaverSpec, errOuter: (p: string, m: string) => void, warn: WarnFn): void {\n let failed = false;\n const err = (p: string, m: string): void => { failed = true; errOuter(p, m); };\n const tl = spec.timeline as unknown;\n if (!isObj(tl)) return err('timeline', 'must be an object {loop?, duration?, keys}');\n for (const k of unknownKeys(tl, KNOWN_TIMELINE)) warn(`timeline.${k}`, 'unknown-property', `unknown timeline property '${k}' — will be ignored`);\n if (tl.loop !== undefined && typeof tl.loop !== 'boolean') err('timeline.loop', 'must be a boolean');\n if (tl.duration !== undefined && (!isNum(tl.duration) || tl.duration <= 0 || tl.duration > LIMITS.maxTimelineDuration)) {\n err('timeline.duration', `must be a number of ms, 0 < duration <= ${LIMITS.maxTimelineDuration}`);\n }\n if (tl.loop === true && tl.duration === undefined) err('timeline.duration', 'loop: true needs a duration (the lap length in ms)');\n if (!Array.isArray(tl.keys) || tl.keys.length === 0) return err('timeline.keys', 'must be a non-empty array');\n if (tl.keys.length > LIMITS.maxTimelineKeys) return err('timeline.keys', `at most ${LIMITS.maxTimelineKeys} keys`);\n\n const base = withoutTimeline(spec);\n const baseSig = structuralSignature(base);\n const times = new Map<string, number[]>();\n let latest = 0;\n tl.keys.forEach((key, i) => {\n const p = `timeline.keys[${i}]`;\n if (!isObj(key)) return err(p, 'must be an object {t, path, value, ease?, dur?}');\n for (const k of unknownKeys(key, KNOWN_TIMELINE_KEY)) warn(`${p}.${k}`, 'unknown-property', `unknown key property '${k}' — will be ignored`);\n let ok = true;\n if (!isNum(key.t) || key.t < 0) { err(`${p}.t`, 'must be a number of ms >= 0'); ok = false; }\n if (key.ease !== undefined && key.ease !== 'step' && key.ease !== 'linear' && key.ease !== 'smooth') err(`${p}.ease`, \"must be 'step' | 'linear' | 'smooth'\");\n if (key.dur !== undefined && (!isNum(key.dur) || key.dur < 0 || key.dur > LIMITS.maxTimelineKeyDur)) {\n err(`${p}.dur`, `must be a number of ms, 0..${LIMITS.maxTimelineKeyDur}`);\n }\n if (!('value' in key)) { err(`${p}.value`, 'is required'); ok = false; }\n const cp = isStr(key.path) ? canonicalSpecPath(base, key.path) : null;\n if (!isStr(key.path) || key.path.trim() === '') { err(`${p}.path`, 'must be a non-empty dot-path'); ok = false; }\n else if (/\\.group$/.test(key.path) || /\\.transform\\.origin$/.test(key.path)) {\n err(`${p}.path`, `'${key.path}' is an enum that can only step — group membership and a transform's origin are fixed per scene`);\n ok = false;\n }\n else if (!cp) { err(`${p}.path`, `'${key.path}' does not resolve on the spec — a key can only animate a field the spec already has`); ok = false; }\n else if (cp === 'timeline' || cp.startsWith('timeline.') || cp === 'schemaVersion' || cp === 'id' || cp === 'label' || cp === 'seed') {\n err(`${p}.path`, `'${key.path}' is not animatable`);\n ok = false;\n }\n if (!ok || !cp) return;\n const t = key.t as number;\n latest = Math.max(latest, t);\n const applied = applyDeltasToSpec(base, [{ t: 0, path: cp, value: key.value }]);\n // The base is valid, so only the part the key changes can break; the full\n // validation runs just to name the failure.\n const r = validateSpecPaths(applied, [cp]) ? { valid: true, errors: [] as SpecError[] } : validateSpec(applied);\n if (!r.valid) {\n for (const e of r.errors) err(`${p}.value`, `applied at '${key.path}' → ${e.path || '<root>'}: ${e.message}`);\n return;\n }\n // `origin` is an enum: a whole-`transform` key that changes it switches\n // the pivot on the key's first frame — a jump, not a glide.\n if (isObj(key.value) && cp.endsWith('transform')) {\n const before = readSpecPath(base, cp);\n const o0 = isObj(before) ? before.origin ?? 'viewport' : 'viewport';\n const o1 = (key.value as Record<string, unknown>).origin ?? 'viewport';\n if (o0 !== o1) warn(`${p}.value`, 'timeline-origin-steps', `this key changes the transform's origin (${String(o0)} → ${String(o1)}): the pivot switches on the key's first frame, so the layer jumps — keep one origin per layer`);\n }\n if (structuralSignature(applied) !== baseSig) {\n warn(`${p}.path`, 'timeline-structural-key', `'${key.path}' is structural (placement, count, motion, size…): the scene rebuilds at this key and entities re-seed — a pop, not a glide. Animate paint (colour, opacity, transform, polygon points) instead`);\n }\n const list = times.get(cp) ?? [];\n list.push(t);\n times.set(cp, list);\n const dur = isNum(key.dur) ? key.dur : DEFAULT_KEY_DUR;\n if (tl.loop === true && isNum(tl.duration) && t + dur > tl.duration) {\n warn(`${p}.dur`, 'timeline-glide-overruns-lap', `this key's glide ends at ${t + dur} ms, after the ${tl.duration} ms lap — the wrap cuts it short`);\n }\n });\n if (tl.loop === true && isNum(tl.duration) && latest >= tl.duration) {\n err('timeline.duration', `must be greater than the latest key's t (${latest} ms) under loop`);\n }\n const minGap = LIMITS.minTimelineKeyInterval;\n for (const [path, list] of times) {\n const distinct = [...new Set(list)].sort((a, b) => a - b);\n for (let i = 1; i < distinct.length; i++) {\n if (distinct[i]! - distinct[i - 1]! < minGap) {\n err('timeline.keys', `keys on '${path}' at ${distinct[i - 1]} and ${distinct[i]} ms are closer than ${minGap} ms (flash safety)`);\n }\n }\n if (tl.loop === true && isNum(tl.duration) && distinct.length > 1) {\n const wrapGap = tl.duration - distinct[distinct.length - 1]! + distinct[0]!;\n if (wrapGap < minGap) err('timeline.keys', `keys on '${path}' at ${distinct[distinct.length - 1]} ms and ${distinct[0]} ms (next lap) are closer than ${minGap} ms across the loop wrap (flash safety)`);\n }\n }\n // Each key was checked applied alone; keys that are each valid can still\n // combine into an invalid scene (a `clock.rate` and a `pulse.period` share\n // one flash-safety floor). Check the composed scene where it can change:\n // every key's start, end and glide quarter-points.\n if (failed) return;\n // Every key boundary, plus up to 120 in-glide points: this runs at every\n // mount, so the glide sampling is budgeted — the settled states are not.\n const keyed = [...timelineTracks(spec).keys()];\n const seen = new Set<string>();\n for (const t of timelineSampleTimes(spec, true, 120)) {\n const r = resolveTimelineAt(spec, t);\n // Only the keyed values change between samples: skip a state already judged.\n const state = JSON.stringify(keyed.map((p) => readSpecPath(r, p)));\n if (seen.has(state)) continue;\n seen.add(state);\n if (validateSpecPaths(r, keyed)) continue;\n const e = validateSpec(r).errors[0];\n err('timeline', `at t = ${Math.round(t)} ms the keys combine into an invalid scene — ${e ? `${e.path || '<root>'}: ${e.message}` : 'invalid'}`);\n return;\n }\n}\n\nfunction color(v: unknown, path: string, err: (p: string, m: string) => void): void {\n if (!isStr(v) || !HEX.test(v)) err(path, 'must be a hex colour like #0a3a52');\n}\n\ntype WarnFn = (path: string, code: string, message: string) => void;\n\n/**\n * A `finish` block (spec- or sequence-level). `grain` / `dither` are bounded\n * to 0..1: at 1 they composite at their fixed maximum alphas (35 % / 25 %),\n * which is as strong as a zero-mean screen can be before it reads as the\n * subject; both stay mean-luminance-neutral at every value, so nothing here\n * is a flash bound — the finish cannot flash at any setting.\n */\nfunction validateFinish(f: unknown, path: string, err: (p: string, m: string) => void, warn: WarnFn): void {\n if (!isObj(f)) return err(path, 'must be an object');\n for (const k of ['grain', 'dither'] as const) {\n if (f[k] !== undefined && (!isNum(f[k]) || (f[k] as number) < 0 || (f[k] as number) > 1)) err(`${path}.${k}`, 'must be a number 0..1');\n }\n if (f.animate !== undefined && typeof f.animate !== 'boolean') err(`${path}.animate`, 'must be a boolean');\n for (const k of unknownKeys(f, KNOWN_FINISH)) {\n warn(`${path}.${k}`, 'unknown-property', `unknown finish property '${k}' — will be ignored`);\n }\n}\n\nfunction validateBackground(bg: unknown, err: (p: string, m: string) => void, warn: WarnFn): void {\n if (!isObj(bg)) return err('background', 'must be an object');\n if (bg.type === 'solid') {\n color(bg.color, 'background.color', err);\n for (const k of unknownKeys(bg, KNOWN_BG_SOLID)) {\n warn(`background.${k}`, 'unknown-property', `unknown background property '${k}' — will be ignored`);\n }\n } else if (bg.type === 'gradient') {\n if (!Array.isArray(bg.stops) || bg.stops.length < 2) {\n err('background.stops', 'gradient needs at least 2 stops');\n } else {\n bg.stops.forEach((s, i) => {\n if (!isObj(s) || !isNum(s.at) || s.at < 0 || s.at > 1) err(`background.stops[${i}].at`, 'must be 0..1');\n color(isObj(s) ? s.color : undefined, `background.stops[${i}].color`, err);\n });\n }\n if (bg.drift !== undefined) {\n if (!isObj(bg.drift)) err('background.drift', 'must be an object');\n else {\n if (!isNum(bg.drift.period) || bg.drift.period < LIMITS.minDriftPeriod) {\n err('background.drift.period', `must be >= ${LIMITS.minDriftPeriod} ms`);\n }\n if (bg.drift.amount !== undefined && (!isNum(bg.drift.amount) || bg.drift.amount <= 0 || bg.drift.amount > LIMITS.maxDriftAmount)) {\n err('background.drift.amount', `must be > 0 and <= ${LIMITS.maxDriftAmount}`);\n }\n }\n }\n if (bg.band !== undefined) {\n if (!isObj(bg.band)) err('background.band', 'must be an object');\n else {\n color(bg.band.color, 'background.band.color', err);\n positiveScalar(bg.band.height, 'background.band.height', err);\n }\n }\n for (const k of unknownKeys(bg, KNOWN_BG_GRADIENT)) {\n warn(`background.${k}`, 'unknown-property', `unknown background property '${k}' — will be ignored`);\n }\n } else if (bg.type === 'field') {\n validateFieldBackground(bg, err, warn);\n } else {\n err('background.type', 'must be solid | gradient | field');\n }\n}\n\n/**\n * A `field` background. Every bound here is a rendering or safety limit:\n * `scale` is capped so a raster cell never spans more than a feature (the\n * upscaled raster would alias), `octaves` so a 96×54 raster stays cheap to\n * recompute ten times a second, and `drift.period` is floored at\n * LIMITS.minDriftPeriod — the same 10 s guard the gradient's drift carries —\n * because the drift is the ONLY way a field changes over time: with the\n * domain travelling a bounded circle once per period, no point of the field\n * can change faster than that, so a field can never strobe.\n */\nfunction validateFieldBackground(bg: Record<string, unknown>, err: (p: string, m: string) => void, warn: WarnFn): void {\n if (!isNum(bg.scale) || bg.scale < LIMITS.minFieldScale || bg.scale > LIMITS.maxFieldScale) {\n err('background.scale', `must be a number ${LIMITS.minFieldScale}..${LIMITS.maxFieldScale} (features across the short side)`);\n }\n if (bg.octaves !== undefined && (!isNum(bg.octaves) || !Number.isInteger(bg.octaves) || bg.octaves < 1 || bg.octaves > LIMITS.maxFieldOctaves)) {\n err('background.octaves', `must be an integer 1..${LIMITS.maxFieldOctaves}`);\n }\n if (bg.warp !== undefined && (!isNum(bg.warp) || bg.warp < 0 || bg.warp > 1)) {\n err('background.warp', 'must be a number 0..1');\n }\n if (bg.quantize !== undefined && (!isNum(bg.quantize) || !Number.isInteger(bg.quantize) || bg.quantize < 0 || bg.quantize === 1 || bg.quantize > LIMITS.maxFieldQuantize)) {\n err('background.quantize', `must be 0 (smooth) or an integer 2..${LIMITS.maxFieldQuantize}`);\n }\n if (!Array.isArray(bg.bands) || bg.bands.length < LIMITS.minFieldBands || bg.bands.length > LIMITS.maxFieldBands) {\n err('background.bands', `must be ${LIMITS.minFieldBands}..${LIMITS.maxFieldBands} hex colours`);\n } else {\n // Indexed, not forEach: forEach skips holes in a sparse array, which\n // would let a hole through validation and crash the renderer later on\n // an undefined colour.\n for (let i = 0; i < bg.bands.length; i++) color(bg.bands[i], `background.bands[${i}]`, err);\n }\n if (bg.drift !== undefined) {\n if (!isObj(bg.drift)) err('background.drift', 'must be an object');\n else {\n if (!isNum(bg.drift.period) || bg.drift.period < LIMITS.minDriftPeriod) {\n err('background.drift.period', `must be >= ${LIMITS.minDriftPeriod} ms`);\n }\n if (bg.drift.amount !== undefined && (!isNum(bg.drift.amount) || bg.drift.amount < 0 || bg.drift.amount > LIMITS.maxFieldDriftAmount)) {\n err('background.drift.amount', `must be a number 0..${LIMITS.maxFieldDriftAmount}`);\n }\n for (const k of unknownKeys(bg.drift, KNOWN_FIELD_DRIFT)) {\n warn(`background.drift.${k}`, 'unknown-property', `unknown drift property '${k}' — will be ignored`);\n }\n }\n }\n if (bg.seed !== undefined && !isNum(bg.seed)) err('background.seed', 'must be a number');\n for (const k of unknownKeys(bg, KNOWN_BG_FIELD)) {\n warn(`background.${k}`, 'unknown-property', `unknown background property '${k}' — will be ignored`);\n }\n}\n\nfunction validateLayer(layer: unknown, path: string, err: (p: string, m: string) => void, warn: WarnFn, spec?: unknown): void {\n if (!isObj(layer)) return err(path, 'must be an object');\n\n for (const k of unknownKeys(layer, KNOWN_LAYER)) {\n if (k === 'id') {\n warn(`${path}.id`, 'misplaced-property', `'id' is not a layer property — did you mean 'key'? Use 'key' to name a layer`);\n } else if (k === 'depth') {\n warn(`${path}.depth`, 'unknown-property', `'depth' is not a layer property — use motion type 'warp' for true perspective depth, or fake parallax with size/speed/alpha across layers`);\n } else {\n warn(`${path}.${k}`, 'unknown-property', `unknown layer property '${k}' — will be ignored`);\n }\n }\n if (!isNum(layer.count) || !Number.isInteger(layer.count) || layer.count < 1) {\n err(`${path}.count`, 'must be a positive integer');\n } else if (layer.count > LIMITS.maxPerLayer) {\n err(`${path}.count`, `at most ${LIMITS.maxPerLayer} per layer`);\n }\n if (layer.size !== undefined && (!isRange(layer.size) || layer.size[0] <= 0)) {\n err(`${path}.size`, rangeMsg(spec));\n }\n if (layer.wrap !== undefined && typeof layer.wrap !== 'boolean') err(`${path}.wrap`, 'must be a boolean');\n if (layer.flip !== undefined && typeof layer.flip !== 'boolean') err(`${path}.flip`, 'must be a boolean');\n\n if (layer.alpha !== undefined && (!isRange(layer.alpha) || layer.alpha[0] < 0 || layer.alpha[1] > 1)) {\n err(`${path}.alpha`, 'must be a [min,max] range within 0..1');\n }\n if (layer.blend !== undefined && !['lighter', 'screen', 'multiply'].includes(layer.blend as string)) {\n err(`${path}.blend`, \"must be 'lighter' | 'screen' | 'multiply' when set\");\n }\n if (layer.key !== undefined && (!isStr(layer.key) || layer.key.trim() === '')) {\n err(`${path}.key`, 'must be a non-empty string');\n }\n if (layer.opacity !== undefined && (!isNum(layer.opacity) || layer.opacity < 0 || layer.opacity > 1)) {\n err(`${path}.opacity`, 'must be a number 0..1');\n }\n if (layer.transform !== undefined) validateTransform(layer.transform, `${path}.transform`, err, warn, spec, true);\n if (layer.group !== undefined) {\n const groups = isObj(spec) && isObj(spec.groups) ? spec.groups : undefined;\n if (!isStr(layer.group)) err(`${path}.group`, 'must be the name of a `groups` entry');\n else if (!groups || !Object.prototype.hasOwnProperty.call(groups, layer.group) || !isObj(groups[layer.group])) err(`${path}.group`, `'${layer.group}' is not in \\`groups\\` — declare it there first`);\n }\n if (layer.position !== undefined) {\n if (!isObj(layer.position) || !isNum(layer.position.x) || !isNum(layer.position.y)) {\n err(`${path}.position`, 'must be {x, y} with numbers 0..1');\n } else {\n if (layer.position.x < 0 || layer.position.x > 1) err(`${path}.position.x`, 'must be 0..1');\n if (layer.position.y < 0 || layer.position.y > 1) err(`${path}.position.y`, 'must be 0..1');\n const [off, unit] = offsetBound(spec);\n for (const axis of ['dx', 'dy'] as const) {\n const v = layer.position[axis];\n if (v !== undefined && (!isNum(v) || Math.abs(v) > off)) {\n err(`${path}.position.${axis}`, `must be a number within ±${off} (${unit})`);\n }\n }\n for (const k of unknownKeys(layer.position, KNOWN_POSITION)) warn(`${path}.position.${k}`, 'unknown-property', `unknown position property '${k}' — will be ignored`);\n const dataLayout = isObj(layer.layout) && (layer.layout.type === 'list' || layer.layout.type === 'table');\n if (isNum(layer.count) && layer.count !== 1 && !dataLayout) {\n err(`${path}.position`, \"position requires count: 1 — or a layout of type 'list' / 'table', where it anchors the whole block\");\n }\n }\n }\n if (layer.region !== undefined) {\n if (!isObj(layer.region)) err(`${path}.region`, 'must be an object');\n else {\n for (const axis of ['x', 'y'] as const) {\n const r = layer.region[axis];\n if (r !== undefined && (!isRange(r) || r[0] < 0 || r[1] > 1)) {\n err(`${path}.region.${axis}`, 'must be a [min,max] range within 0..1');\n }\n }\n }\n }\n if (layer.pulse !== undefined) {\n if (!isObj(layer.pulse)) err(`${path}.pulse`, 'must be an object');\n else {\n if (!isNum(layer.pulse.amp) || layer.pulse.amp <= 0 || layer.pulse.amp > LIMITS.maxPulseAmp) {\n err(`${path}.pulse.amp`, `must be within 0..${LIMITS.maxPulseAmp}`);\n }\n if (!isNum(layer.pulse.period) || layer.pulse.period < LIMITS.minPulsePeriod) {\n err(`${path}.pulse.period`, `must be >= ${LIMITS.minPulsePeriod} ms (flash-safety floor)`);\n }\n if (layer.pulse.wave !== undefined) {\n if (!isObj(layer.pulse.wave)) err(`${path}.pulse.wave`, 'must be an object');\n else {\n if (!isNum(layer.pulse.wave.wavelength) || layer.pulse.wave.wavelength <= 0) {\n err(`${path}.pulse.wave.wavelength`, 'must be > 0 (px or viewport-units)');\n }\n if (layer.pulse.wave.angle !== undefined && !isNum(layer.pulse.wave.angle)) {\n err(`${path}.pulse.wave.angle`, 'must be a number (degrees)');\n }\n }\n }\n }\n }\n if (layer.spin !== undefined) {\n if (isRange(layer.spin)) {\n if (Math.abs(layer.spin[0]) > LIMITS.maxSpin || Math.abs(layer.spin[1]) > LIMITS.maxSpin) {\n err(`${path}.spin`, `each end of the range must be within ±${LIMITS.maxSpin} deg/sec`);\n }\n } else if (!isNum(layer.spin)) {\n err(`${path}.spin`, 'must be a number or a [min,max] range (degrees/sec)');\n } else if (Math.abs(layer.spin) > LIMITS.maxSpin) {\n err(`${path}.spin`, `must be within ±${LIMITS.maxSpin} deg/sec`);\n }\n }\n if (layer.rotate !== undefined) {\n if (isRange(layer.rotate)) {\n if (Math.abs(layer.rotate[0]) > LIMITS.maxRotate || Math.abs(layer.rotate[1]) > LIMITS.maxRotate) {\n err(`${path}.rotate`, `each end of the range must be within ±${LIMITS.maxRotate} degrees`);\n }\n } else if (!isNum(layer.rotate)) {\n err(`${path}.rotate`, 'must be a number or a [min,max] range (degrees)');\n } else if (Math.abs(layer.rotate) > LIMITS.maxRotate) {\n err(`${path}.rotate`, `must be within ±${LIMITS.maxRotate} degrees`);\n }\n }\n if (layer.grow !== undefined) {\n if (!isObj(layer.grow)) err(`${path}.grow`, 'must be an object');\n else {\n if (!isNum(layer.grow.amp) || layer.grow.amp <= 0 || layer.grow.amp > LIMITS.maxGrowAmp) {\n err(`${path}.grow.amp`, `must be within 0..${LIMITS.maxGrowAmp}`);\n }\n if (!isNum(layer.grow.period) || layer.grow.period < LIMITS.minPulsePeriod) {\n err(`${path}.grow.period`, `must be >= ${LIMITS.minPulsePeriod} ms (flash-safety floor)`);\n }\n }\n }\n\n if (layer.links !== undefined) {\n if (!isObj(layer.links)) err(`${path}.links`, 'must be an object');\n else {\n if (!isNum(layer.links.k) || !Number.isInteger(layer.links.k) || layer.links.k < 1 || layer.links.k > LIMITS.maxLinksK) {\n err(`${path}.links.k`, `must be an integer 1..${LIMITS.maxLinksK}`);\n }\n positiveScalar(layer.links.maxDist, `${path}.links.maxDist`, err);\n if (layer.links.color !== undefined) color(layer.links.color, `${path}.links.color`, err);\n if (layer.links.alpha !== undefined && (!isNum(layer.links.alpha) || layer.links.alpha < 0 || layer.links.alpha > 1)) {\n err(`${path}.links.alpha`, 'must be 0..1');\n }\n if (layer.links.width !== undefined) positiveScalar(layer.links.width, `${path}.links.width`, err);\n if (layer.links.mode !== undefined && !['nearest', 'chain', 'random'].includes(layer.links.mode as string)) {\n err(`${path}.links.mode`, \"must be 'nearest' | 'chain' | 'random'\");\n }\n if (layer.links.falloff !== undefined && typeof layer.links.falloff !== 'boolean') {\n err(`${path}.links.falloff`, 'must be a boolean');\n }\n if (layer.links.closed !== undefined && typeof layer.links.closed !== 'boolean') {\n err(`${path}.links.closed`, 'must be a boolean');\n }\n if (isNum(layer.count) && layer.count > LIMITS.maxLinkLayerCount) {\n err(`${path}.links`, `layer count must be <= ${LIMITS.maxLinkLayerCount} when links is set`);\n }\n }\n }\n\n if (layer.layout !== undefined) {\n if (isObj(layer.layout) && (layer.layout.type === 'list' || layer.layout.type === 'table')) {\n const lay = layer.layout;\n if (lay.type === 'table' && (!isNum(lay.columns) || !Number.isInteger(lay.columns) || lay.columns < 1 || lay.columns > LIMITS.maxGridColumns)) {\n err(`${path}.layout.columns`, `must be an integer 1..${LIMITS.maxGridColumns}`);\n }\n const gapOk = (v: unknown): boolean => isNum(v) && v > 0;\n if (lay.gap !== undefined) {\n if (isNum(lay.gap)) {\n if (!gapOk(lay.gap)) err(`${path}.layout.gap`, 'must be > 0 (viewport units of min(w,h), or px)');\n } else if (lay.type === 'table' && isObj(lay.gap)) {\n if (lay.gap.x !== undefined && !gapOk(lay.gap.x)) err(`${path}.layout.gap.x`, 'must be > 0');\n if (lay.gap.y !== undefined && !gapOk(lay.gap.y)) err(`${path}.layout.gap.y`, 'must be > 0');\n for (const k of unknownKeys(lay.gap, new Set(['x', 'y']))) {\n warn(`${path}.layout.gap.${k}`, 'unknown-property', `unknown gap property '${k}' — will be ignored`);\n }\n } else {\n err(`${path}.layout.gap`, lay.type === 'table' ? 'must be a number > 0 or { x?, y? }' : 'must be a number > 0');\n }\n }\n for (const k of unknownKeys(lay, new Set(lay.type === 'list' ? ['type', 'gap'] : ['type', 'columns', 'gap']))) {\n warn(`${path}.layout.${k}`, 'unknown-property', `unknown layout property '${k}' — will be ignored`);\n }\n // A data layout reads variants in order: N labels want N strings.\n const sp = layer.sprite;\n if (isObj(sp) && isNum(layer.count)) {\n const variants = sp.kind === 'text' && Array.isArray(sp.strings) ? sp.strings.length\n : sp.kind === 'emoji' && Array.isArray(sp.glyphs) ? sp.glyphs.length\n : sp.kind === 'bar' && Array.isArray(sp.values) ? sp.values.length : null;\n if (variants !== null && variants !== layer.count) {\n warn(`${path}.count`, 'list-length-mismatch', `count is ${layer.count} but the sprite carries ${variants} ${sp.kind === 'bar' ? 'values' : 'variants'} — a ${lay.type} layout reads them in order, so they cycle or go unused`);\n }\n }\n } else if (!isObj(layer.layout) || layer.layout.type !== 'grid') {\n err(`${path}.layout`, \"must be an object with type: 'grid' | 'list' | 'table'\");\n } else {\n if (layer.layout.columns !== undefined && (!isNum(layer.layout.columns) || !Number.isInteger(layer.layout.columns) || layer.layout.columns < 1 || layer.layout.columns > LIMITS.maxGridColumns)) {\n err(`${path}.layout.columns`, `must be an integer 1..${LIMITS.maxGridColumns}`);\n }\n const jit = layer.layout.jitter;\n if (jit !== undefined) {\n const jitterOk = (v: unknown): boolean => isNum(v) && v >= 0 && v <= 1;\n if (isNum(jit)) {\n if (!jitterOk(jit)) err(`${path}.layout.jitter`, 'must be 0..1');\n } else if (isObj(jit)) {\n if (jit.x !== undefined && !jitterOk(jit.x)) err(`${path}.layout.jitter.x`, 'must be 0..1');\n if (jit.y !== undefined && !jitterOk(jit.y)) err(`${path}.layout.jitter.y`, 'must be 0..1');\n } else {\n err(`${path}.layout.jitter`, 'must be a number 0..1 or { x?, y? }');\n }\n }\n if (layer.position !== undefined) {\n warn(`${path}.layout`, 'layout-with-position', 'position overrides layout for the single entity — layout has no effect');\n }\n }\n }\n\n if (layer.life !== undefined) {\n if (!isObj(layer.life)) err(`${path}.life`, 'must be an object');\n else {\n if (layer.life.enter !== undefined && (!isNum(layer.life.enter) || layer.life.enter < 0)) {\n err(`${path}.life.enter`, 'must be >= 0 (ms)');\n }\n if (layer.life.exit !== undefined && (!isNum(layer.life.exit) || layer.life.exit < 0)) {\n err(`${path}.life.exit`, 'must be >= 0 (ms)');\n }\n if (isNum(layer.life.enter) && isNum(layer.life.exit) && layer.life.exit <= layer.life.enter) {\n err(`${path}.life.exit`, 'must be greater than life.enter');\n }\n if (layer.life.fade !== undefined && (!isNum(layer.life.fade) || layer.life.fade < 0)) {\n err(`${path}.life.fade`, 'must be >= 0 (ms)');\n }\n }\n }\n\n if (layer.trail !== undefined) {\n if (!isObj(layer.trail)) err(`${path}.trail`, 'must be an object');\n else {\n if (!isNum(layer.trail.length) || layer.trail.length <= 0 || layer.trail.length > LIMITS.maxTrailLength) {\n err(`${path}.trail.length`, `must be > 0 and <= ${LIMITS.maxTrailLength} ms`);\n }\n if (layer.trail.fade !== undefined && (!isNum(layer.trail.fade) || layer.trail.fade < 0 || layer.trail.fade > 1)) {\n err(`${path}.trail.fade`, 'must be 0..1');\n }\n }\n }\n\n if (layer.emit !== undefined) {\n if (!isObj(layer.emit)) err(`${path}.emit`, 'must be an object { every, life, jitter?, grow? }');\n else {\n const em = layer.emit;\n if (!isNum(em.every) || em.every < LIMITS.minEmitEvery || em.every > LIMITS.maxEmitEvery) {\n err(`${path}.emit.every`, `must be ${LIMITS.minEmitEvery}..${LIMITS.maxEmitEvery} ms (at most one event per second per entity)`);\n }\n if (!isNum(em.life) || em.life < LIMITS.minEmitLife) {\n err(`${path}.emit.life`, `must be >= ${LIMITS.minEmitLife} ms (an event is a smooth envelope, never a cut)`);\n } else if (isNum(em.every) && em.life > em.every) {\n err(`${path}.emit.life`, 'must be <= emit.every (the visible window cannot outlast its period)');\n }\n if (em.jitter !== undefined && (!isNum(em.jitter) || em.jitter < 0 || em.jitter > 1)) {\n err(`${path}.emit.jitter`, 'must be 0..1 (0 = evenly staggered, 1 = scattered by a fixed sequence)');\n }\n if (em.grow !== undefined) {\n if (!Array.isArray(em.grow) || em.grow.length !== 2 || !isNum(em.grow[0]) || !isNum(em.grow[1])) {\n err(`${path}.emit.grow`, 'must be [from, to] size multipliers');\n } else if (em.grow[0] < 0 || em.grow[1] < 0 || em.grow[0] > LIMITS.maxEmitGrow || em.grow[1] > LIMITS.maxEmitGrow) {\n err(`${path}.emit.grow`, `each multiplier must be 0..${LIMITS.maxEmitGrow}`);\n }\n }\n // jitter 0 promises one event at a time; that only holds while a window\n // is shorter than the stagger between entities.\n if (em.jitter === 0 && isNum(em.every) && isNum(em.life) && isNum(layer.count) && layer.count > 1 && em.life > em.every / layer.count) {\n warn(`${path}.emit.life`, 'emit-overlap', `jitter 0 staggers ${layer.count} entities ${(em.every / layer.count).toFixed(0)} ms apart but each stays lit ${em.life} ms — windows overlap, so more than one event is visible at a time. Shorten life or lengthen every`);\n }\n for (const k of unknownKeys(em, new Set(['every', 'life', 'jitter', 'grow']))) {\n warn(`${path}.emit.${k}`, 'unknown-property', `unknown emit property '${k}' — will be ignored`);\n }\n }\n }\n if (layer.clock !== undefined) {\n if (!isObj(layer.clock)) err(`${path}.clock`, 'must be an object { phase?, rate? }');\n else {\n const ck = layer.clock;\n if (ck.phase !== undefined && (!isNum(ck.phase) || ck.phase < 0 || ck.phase > 1)) {\n err(`${path}.clock.phase`, 'must be 0..1 (turns)');\n }\n const rate = ck.rate === undefined ? 1 : ck.rate;\n if (!isNum(rate) || rate < LIMITS.minClockRate || rate > LIMITS.maxClockRate) {\n err(`${path}.clock.rate`, `must be ${LIMITS.minClockRate}..${LIMITS.maxClockRate}`);\n } else {\n // A clocked layer pulses in unison — every entity at once — so the\n // per-entity-phase defence is gone and the period floor doubles.\n const floor = LIMITS.minClockedPeriod * rate;\n if (isObj(layer.pulse) && isNum(layer.pulse.period) && layer.pulse.period < floor) {\n err(`${path}.pulse.period`, `must be >= ${floor} ms when the layer has a clock (period / rate >= ${LIMITS.minClockedPeriod} — the whole layer breathes in unison)`);\n }\n if (isObj(layer.grow) && isNum(layer.grow.period) && layer.grow.period < floor) {\n err(`${path}.grow.period`, `must be >= ${floor} ms when the layer has a clock (period / rate >= ${LIMITS.minClockedPeriod})`);\n }\n const sp = layer.sprite;\n if (isObj(sp) && isObj(sp.cycle) && isNum(sp.cycle.period) && sp.cycle.period < floor) {\n err(`${path}.sprite.cycle.period`, `must be >= ${floor} ms when the layer has a clock (period / rate >= ${LIMITS.minClockedPeriod})`);\n }\n }\n for (const k of unknownKeys(ck, new Set(['phase', 'rate']))) {\n warn(`${path}.clock.${k}`, 'unknown-property', `unknown clock property '${k}' — will be ignored`);\n }\n }\n }\n validateSprite(layer.sprite, `${path}.sprite`, err, warn, spec);\n validateMotion(layer.motion, `${path}.motion`, err, warn, spec);\n}\n\nfunction validateSprite(sprite: unknown, path: string, err: (p: string, m: string) => void, warn: WarnFn, spec?: unknown): void {\n if (!isObj(sprite)) return err(path, 'must be an object');\n\n let knownSet: Set<string>;\n if (sprite.kind === 'emoji') {\n knownSet = KNOWN_EMOJI;\n if (!Array.isArray(sprite.glyphs) || sprite.glyphs.length === 0 || !sprite.glyphs.every(isStr)) {\n err(`${path}.glyphs`, 'must be a non-empty array of strings');\n }\n validateCycle(sprite, path, err);\n } else if (sprite.kind === 'text') {\n knownSet = KNOWN_TEXT;\n if (!Array.isArray(sprite.strings) || sprite.strings.length === 0 || !sprite.strings.every(isStr)) {\n err(`${path}.strings`, 'must be a non-empty array of strings');\n }\n if (sprite.color !== undefined) color(sprite.color, `${path}.color`, err);\n if (sprite.font !== undefined && !isStr(sprite.font)) {\n err(`${path}.font`, 'must be a string');\n }\n if (sprite.align !== undefined && !['left', 'center', 'right'].includes(sprite.align as string)) {\n err(`${path}.align`, 'must be left | center | right');\n }\n if (sprite.baseline !== undefined && !['top', 'middle', 'bottom'].includes(sprite.baseline as string)) {\n err(`${path}.baseline`, 'must be top | middle | bottom');\n }\n if (sprite.maxWidth !== undefined) positiveScalar(sprite.maxWidth, `${path}.maxWidth`, err, 'must be a positive number');\n validateTextRole(sprite, path, err);\n validateCycle(sprite, path, err);\n } else if (sprite.kind === 'circle') {\n knownSet = KNOWN_CIRCLE;\n if (!isRange(sprite.radius) || sprite.radius[0] <= 0) err(`${path}.radius`, rangeMsg(spec));\n color(sprite.color, `${path}.color`, err);\n if (sprite.soft !== undefined && typeof sprite.soft !== 'boolean') err(`${path}.soft`, 'must be a boolean');\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'ring') {\n knownSet = KNOWN_RING;\n if (!isRange(sprite.radius) || sprite.radius[0] <= 0) err(`${path}.radius`, rangeMsg(spec));\n color(sprite.color, `${path}.color`, err);\n if (sprite.width !== undefined) positiveScalar(sprite.width, `${path}.width`, err);\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'streak') {\n knownSet = KNOWN_STREAK;\n if (!isRange(sprite.length) || sprite.length[0] <= 0) err(`${path}.length`, rangeMsg(spec));\n color(sprite.color, `${path}.color`, err);\n if (sprite.width !== undefined) positiveScalar(sprite.width, `${path}.width`, err);\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'rect') {\n knownSet = KNOWN_RECT;\n if (!isRange(sprite.width) || sprite.width[0] <= 0) err(`${path}.width`, rangeMsg(spec));\n if (sprite.aspect !== undefined && (!isRange(sprite.aspect) || sprite.aspect[0] <= 0)) {\n err(`${path}.aspect`, 'must be a [min,max] range of positive height/width ratios');\n }\n if (sprite.feather !== undefined && (!isNum(sprite.feather) || sprite.feather < 0 || sprite.feather > 1)) {\n err(`${path}.feather`, 'must be 0..1 (fraction of the half-size that fades out)');\n }\n color(sprite.color, `${path}.color`, err);\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'bar') {\n knownSet = KNOWN_BAR;\n if (!Array.isArray(sprite.values) || sprite.values.length === 0 || sprite.values.length > LIMITS.maxPerLayer || !sprite.values.every((v) => isNum(v) && v >= 0)) {\n err(`${path}.values`, `must be 1..${LIMITS.maxPerLayer} numbers >= 0`);\n }\n positiveScalar(sprite.length, `${path}.length`, err, 'must be > 0 (full-scale bar length)');\n positiveScalar(sprite.thickness, `${path}.thickness`, err);\n if (sprite.max !== undefined) positiveScalar(sprite.max, `${path}.max`, err);\n if (sprite.direction !== undefined && !['right', 'left', 'up', 'down'].includes(sprite.direction as string)) {\n err(`${path}.direction`, \"must be 'right' | 'left' | 'up' | 'down'\");\n }\n color(sprite.color, `${path}.color`, err);\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'polygon') {\n knownSet = KNOWN_POLYGON;\n if (!isRange(sprite.radius) || sprite.radius[0] <= 0) err(`${path}.radius`, rangeMsg(spec, 'circumradius'));\n if (sprite.sides !== undefined && sprite.points !== undefined) {\n err(`${path}.sides`, 'use sides (a regular polygon) or points (a custom one), not both');\n }\n if (sprite.sides !== undefined && (!isNum(sprite.sides) || !Number.isInteger(sprite.sides) || sprite.sides < LIMITS.minPolygonSides || sprite.sides > LIMITS.maxPolygonSides)) {\n err(`${path}.sides`, `must be an integer ${LIMITS.minPolygonSides}..${LIMITS.maxPolygonSides}`);\n }\n if (sprite.points !== undefined) validateShapePoints(sprite.points, `${path}.points`, 3, err);\n if (sprite.soft !== undefined && typeof sprite.soft !== 'boolean') err(`${path}.soft`, 'must be a boolean');\n color(sprite.color, `${path}.color`, err);\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'stroke') {\n knownSet = KNOWN_STROKE;\n if (!isRange(sprite.length) || sprite.length[0] <= 0) err(`${path}.length`, rangeMsg(spec, \"the mark's bounding size\"));\n validateShapePoints(sprite.points, `${path}.points`, 2, err);\n if (sprite.width !== undefined) positiveScalar(sprite.width, `${path}.width`, err);\n if (sprite.curve !== undefined && sprite.curve !== 'smooth' && sprite.curve !== 'linear') err(`${path}.curve`, \"must be 'smooth' | 'linear'\");\n if (sprite.taper !== undefined && typeof sprite.taper !== 'boolean') err(`${path}.taper`, 'must be a boolean');\n if (sprite.orient !== undefined && typeof sprite.orient !== 'boolean') err(`${path}.orient`, 'must be a boolean');\n color(sprite.color, `${path}.color`, err);\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'textBlock') {\n knownSet = KNOWN_TEXT_BLOCK;\n if (typeof sprite.text !== 'string' || sprite.text.length === 0) {\n err(`${path}.text`, 'must be a non-empty string');\n } else if (sprite.text.length > LIMITS.maxTextBlockLength) {\n err(`${path}.text`, `must be at most ${LIMITS.maxTextBlockLength} characters`);\n }\n if (Array.isArray(sprite.maxWidth)) {\n err(`${path}.maxWidth`, 'must be a single number (viewport fraction), not a [min,max] range');\n } else if (!isNum(sprite.maxWidth) || sprite.maxWidth <= 0 || sprite.maxWidth > LIMITS.maxTextBlockMaxWidth) {\n err(`${path}.maxWidth`, `must be a positive number up to ${LIMITS.maxTextBlockMaxWidth} (viewport fraction)`);\n }\n if (Array.isArray(sprite.fontSize)) {\n err(`${path}.fontSize`, 'must be a single number (viewport fraction), not a [min,max] range');\n } else if (!isNum(sprite.fontSize) || sprite.fontSize < LIMITS.minTextBlockFontSize || sprite.fontSize > LIMITS.maxTextBlockFontSize) {\n err(`${path}.fontSize`, `must be between ${LIMITS.minTextBlockFontSize} and ${LIMITS.maxTextBlockFontSize} (viewport fraction)`);\n }\n if (sprite.lineHeight !== undefined && (!isNum(sprite.lineHeight) || sprite.lineHeight < 0.5 || sprite.lineHeight > 4)) {\n err(`${path}.lineHeight`, 'must be between 0.5 and 4 (multiplier)');\n }\n if (sprite.align !== undefined && !['left', 'center', 'right'].includes(sprite.align as string)) {\n err(`${path}.align`, \"must be 'left' | 'center' | 'right'\");\n }\n if (sprite.color !== undefined) color(sprite.color, `${path}.color`, err);\n if (sprite.anchor !== undefined && !TEXT_BLOCK_ANCHORS.has(sprite.anchor as string)) {\n err(`${path}.anchor`, \"must be 'top-left' | 'top' | 'top-right' | 'left' | 'center' | 'right' | 'bottom-left' | 'bottom' | 'bottom-right'\");\n }\n if (sprite.font !== undefined) {\n if (!isStr(sprite.font) || sprite.font.trim() === '') {\n err(`${path}.font`, 'must be a non-empty string (family and/or weight)');\n } else if (FONT_SIZE_RE.test(sprite.font)) {\n err(`${path}.font`, 'must name a family and/or weight only — fontSize owns the size');\n }\n }\n if (sprite.opacity !== undefined && (!isNum(sprite.opacity) || sprite.opacity < 0 || sprite.opacity > 1)) {\n err(`${path}.opacity`, 'must be a number between 0 and 1');\n }\n validateTextRole(sprite, path, err);\n if (sprite.reveal !== undefined) {\n const rv = sprite.reveal as Record<string, unknown>;\n if (typeof rv !== 'object' || rv === null || Array.isArray(rv)) {\n err(`${path}.reveal`, 'must be an object');\n } else {\n for (const k of Object.keys(rv)) {\n if (!KNOWN_REVEAL.has(k)) err(`${path}.reveal.${k}`, 'unknown reveal field');\n }\n if (rv.progress !== undefined && (!isNum(rv.progress) || rv.progress < 0 || rv.progress > 1)) {\n err(`${path}.reveal.progress`, 'must be a number between 0 and 1');\n }\n if (rv.mode !== undefined && !['typewriter', 'word', 'line', 'glyphFade'].includes(rv.mode as string)) {\n err(`${path}.reveal.mode`, \"must be 'typewriter' | 'word' | 'line' | 'glyphFade'\");\n }\n if (rv.fade !== undefined && (!isNum(rv.fade) || rv.fade <= 0 || rv.fade > 1)) {\n err(`${path}.reveal.fade`, 'must be between 0 (exclusive) and 1 (fraction of progress)');\n }\n if (rv.speed !== undefined && (!isNum(rv.speed) || rv.speed < 0 || rv.speed > LIMITS.maxRevealSpeed)) {\n err(`${path}.reveal.speed`, `must be between 0 and ${LIMITS.maxRevealSpeed} (graphemes/sec)`);\n }\n if (rv.caret !== undefined && typeof rv.caret !== 'boolean') {\n const caret = rv.caret as Record<string, unknown>;\n if (typeof caret !== 'object' || caret === null || Array.isArray(caret)) {\n err(`${path}.reveal.caret`, 'must be a boolean or an object');\n } else {\n for (const k of Object.keys(caret)) {\n if (!KNOWN_REVEAL_CARET.has(k)) err(`${path}.reveal.caret.${k}`, 'unknown caret field');\n }\n if (caret.blink !== undefined && (!isNum(caret.blink) || caret.blink <= 0 || caret.blink > LIMITS.maxCaretBlinkHz)) {\n err(`${path}.reveal.caret.blink`, `must be between 0 (exclusive) and ${LIMITS.maxCaretBlinkHz} Hz (flash safety)`);\n }\n if (caret.color !== undefined) color(caret.color, `${path}.reveal.caret.color`, err);\n }\n }\n }\n }\n } else {\n err(`${path}.kind`, 'must be emoji | text | circle | ring | streak | rect | bar | polygon | stroke | textBlock');\n return;\n }\n\n for (const k of unknownKeys(sprite, knownSet)) {\n if (LAYER_PROPS_ON_SPRITE.has(k)) {\n warn(`${path}.${k}`, 'misplaced-property', `'${k}' belongs on the layer, not inside sprite — move it up one level`);\n } else {\n warn(`${path}.${k}`, 'unknown-property', `unknown sprite property '${k}' — will be ignored`);\n }\n }\n}\n\n/** Shared colors[] + colorWeights[] validation for circle/ring/streak/rect sprites. */\nfunction validatePalette(sprite: Record<string, unknown>, path: string, err: (p: string, m: string) => void): void {\n if (sprite.colors !== undefined) {\n if (!Array.isArray(sprite.colors) || sprite.colors.length === 0) {\n err(`${path}.colors`, 'must be a non-empty array of hex colours');\n } else {\n sprite.colors.forEach((c: unknown, ci: number) => color(c, `${path}.colors[${ci}]`, err));\n }\n }\n if (sprite.colorWeights !== undefined) {\n if (!Array.isArray(sprite.colors)) {\n err(`${path}.colorWeights`, 'requires colors to be set');\n } else if (!Array.isArray(sprite.colorWeights) || sprite.colorWeights.length !== sprite.colors.length) {\n err(`${path}.colorWeights`, 'must be an array the same length as colors');\n } else if (!sprite.colorWeights.every((v: unknown) => isNum(v) && v >= 0) || !sprite.colorWeights.some((v: unknown) => isNum(v) && v > 0)) {\n err(`${path}.colorWeights`, 'weights must be >= 0 with at least one > 0');\n }\n }\n}\n\n/** `role` on `text` / `textBlock`: a declaration of intent, one of two words. */\nfunction validateTextRole(sprite: Record<string, unknown>, path: string, err: (p: string, m: string) => void): void {\n if (sprite.role !== undefined && !TEXT_ROLES.has(sprite.role as string)) {\n err(`${path}.role`, \"must be 'read' | 'atmosphere'\");\n }\n}\n\nfunction validateCycle(sprite: Record<string, unknown>, path: string, err: (p: string, m: string) => void): void {\n if (sprite.cycle === undefined) return;\n if (!isObj(sprite.cycle)) return err(`${path}.cycle`, 'must be an object');\n if (!isNum(sprite.cycle.period) || sprite.cycle.period < LIMITS.minCyclePeriod) {\n err(`${path}.cycle.period`, `must be >= ${LIMITS.minCyclePeriod} ms (flash-safety floor)`);\n }\n}\n\nfunction validateMotion(motion: unknown, path: string, err: (p: string, m: string) => void, warn: WarnFn, spec?: unknown): void {\n if (!isObj(motion)) return err(path, 'must be an object');\n const isViewport = !isObj(spec) || (spec as Record<string, unknown>).units !== 'px';\n const refVp = isObj(spec) && isNum((spec as Record<string, unknown>).referenceViewport) ? (spec as Record<string, unknown>).referenceViewport as number : LIMITS.referenceViewport;\n const speedCap = isViewport ? LIMITS.maxSpeed / refVp : LIMITS.maxSpeed;\n const speedOk = (v: unknown, p: string): void => {\n if (!isRange(v)) err(p, 'must be a [min,max] range');\n else if (v[0] < 0) err(p, 'speed lower bound must be >= 0');\n else if (v[1] > speedCap) err(p, `speed exceeds cap ${isViewport ? speedCap.toFixed(2) + ' viewport-units/sec' : LIMITS.maxSpeed + ' px/sec'}`);\n };\n\n let knownSet: Set<string>;\n if (motion.type === 'drift') {\n knownSet = KNOWN_DRIFT;\n speedOk(motion.speed, `${path}.speed`);\n if (motion.angle !== undefined && !isNum(motion.angle)) err(`${path}.angle`, 'must be a number (degrees)');\n if (motion.bidirectional !== undefined && typeof motion.bidirectional !== 'boolean') err(`${path}.bidirectional`, 'must be a boolean');\n if (motion.bob !== undefined && !isNum(motion.bob)) err(`${path}.bob`, 'must be a number');\n validateEase(motion.ease, `${path}.ease`, err, warn);\n if (isRange(motion.speed) && motion.speed[1] < 1 && !isViewport) {\n warn(`${path}.speed`, 'near-zero-speed', `max speed is ${motion.speed[1]} px/sec — entities will appear frozen. Typical range: 10–200 px/sec`);\n }\n } else if (motion.type === 'rise') {\n knownSet = KNOWN_RISE;\n speedOk(motion.speed, `${path}.speed`);\n if (motion.sway !== undefined && !isNum(motion.sway)) err(`${path}.sway`, 'must be a number');\n validateEase(motion.ease, `${path}.ease`, err, warn);\n if (isRange(motion.speed) && motion.speed[1] < 1 && !isViewport) {\n warn(`${path}.speed`, 'near-zero-speed', `max speed is ${motion.speed[1]} px/sec — entities will appear frozen. Typical range: 5–80 px/sec`);\n }\n } else if (motion.type === 'bounce') {\n knownSet = KNOWN_BOUNCE;\n speedOk(motion.speed, `${path}.speed`);\n if (isRange(motion.speed) && motion.speed[1] < 1 && !isViewport) {\n warn(`${path}.speed`, 'near-zero-speed', `max speed is ${motion.speed[1]} px/sec — entities will appear frozen. Typical range: 20–150 px/sec`);\n }\n } else if (motion.type === 'static') {\n knownSet = KNOWN_STATIC;\n } else if (motion.type === 'orbit') {\n knownSet = KNOWN_ORBIT;\n if (!isRange(motion.speed)) err(`${path}.speed`, 'must be a [min,max] range');\n else {\n if (Math.abs(motion.speed[0]) > LIMITS.maxOrbitSpeed || Math.abs(motion.speed[1]) > LIMITS.maxOrbitSpeed) err(`${path}.speed`, `orbit speed exceeds cap ${LIMITS.maxOrbitSpeed} deg/sec`);\n if (Math.max(Math.abs(motion.speed[0]), Math.abs(motion.speed[1])) < 1) {\n warn(`${path}.speed`, 'near-zero-speed', `orbit speed is near zero — entities will appear frozen. Typical range: 5–60 deg/sec`);\n }\n }\n if (!isRange(motion.radius) || motion.radius[0] <= 0) err(`${path}.radius`, rangeMsg(spec));\n if (motion.center !== undefined) {\n if (!isObj(motion.center)) {\n err(`${path}.center`, 'must be {x, y} (0..1) or { layer: key }');\n } else if ('layer' in motion.center) {\n if (!isStr(motion.center.layer) || motion.center.layer.trim() === '') {\n err(`${path}.center.layer`, 'must be a non-empty layer key');\n } else if (isObj(spec) && Array.isArray((spec as Record<string, unknown>).layers)) {\n // Scene-graph lite: parent must exist, be a single entity, and not itself\n // orbit a layer (strictly one level deep — keeps positionAt analytic).\n const layers = (spec as { layers: unknown[] }).layers;\n const parent = layers.find((l) => isObj(l) && l.key === (motion.center as { layer: string }).layer) as Record<string, unknown> | undefined;\n if (!parent) {\n err(`${path}.center.layer`, `no layer with key '${motion.center.layer}'`);\n } else {\n if (parent.count !== 1) err(`${path}.center.layer`, 'parent layer must have count: 1');\n const pm = parent.motion;\n if (isObj(pm) && pm.type === 'orbit' && isObj(pm.center) && 'layer' in pm.center) {\n err(`${path}.center.layer`, 'parent may not itself orbit a layer (one level deep only)');\n }\n }\n }\n } else if (!isNum(motion.center.x) || !isNum(motion.center.y)) {\n err(`${path}.center`, 'must be {x, y} with numbers 0..1');\n } else {\n if (motion.center.x < 0 || motion.center.x > 1) err(`${path}.center.x`, 'must be 0..1');\n if (motion.center.y < 0 || motion.center.y > 1) err(`${path}.center.y`, 'must be 0..1');\n }\n }\n } else if (motion.type === 'wander') {\n knownSet = KNOWN_WANDER;\n validateEase(motion.ease, `${path}.ease`, err, warn);\n speedOk(motion.speed, `${path}.speed`);\n if (motion.angle !== undefined && !isNum(motion.angle)) err(`${path}.angle`, 'must be a number (degrees)');\n const meanderCap = isViewport ? LIMITS.maxMeander / refVp : LIMITS.maxMeander;\n if (motion.meander !== undefined && (!isNum(motion.meander) || motion.meander <= 0 || motion.meander > meanderCap)) {\n err(`${path}.meander`, `must be > 0 and <= ${isViewport ? meanderCap.toFixed(3) + ' viewport-units' : LIMITS.maxMeander + ' px'}`);\n }\n if (motion.coherence !== undefined && (!isNum(motion.coherence) || motion.coherence < 0 || motion.coherence > 1)) {\n err(`${path}.coherence`, 'must be 0..1');\n }\n } else if (motion.type === 'warp') {\n knownSet = KNOWN_WARP;\n if (!isRange(motion.speed) || motion.speed[0] < 0) err(`${path}.speed`, 'must be a [min,max] range >= 0 (depth-units/sec)');\n else if (motion.speed[1] > LIMITS.maxWarpSpeed) err(`${path}.speed`, `warp speed exceeds cap ${LIMITS.maxWarpSpeed} depth-units/sec`);\n if (motion.center !== undefined) {\n if (!isObj(motion.center) || !isNum(motion.center.x) || !isNum(motion.center.y)) {\n err(`${path}.center`, 'must be {x, y} with numbers 0..1');\n } else {\n if (motion.center.x < 0 || motion.center.x > 1) err(`${path}.center.x`, 'must be 0..1');\n if (motion.center.y < 0 || motion.center.y > 1) err(`${path}.center.y`, 'must be 0..1');\n }\n }\n } else if (motion.type === 'path') {\n knownSet = KNOWN_PATH;\n if (!Array.isArray(motion.points) || motion.points.length < LIMITS.minPathPoints || motion.points.length > LIMITS.maxPathPoints) {\n err(`${path}.points`, `must be an array of ${LIMITS.minPathPoints}..${LIMITS.maxPathPoints} points`);\n } else {\n motion.points.forEach((p: unknown, pi: number) => {\n if (!isObj(p) || !isNum(p.x) || !isNum(p.y) || p.x < 0 || p.x > 1 || p.y < 0 || p.y > 1) {\n err(`${path}.points[${pi}]`, 'must be {x, y} with numbers 0..1');\n }\n });\n }\n if (!isNum(motion.duration) || motion.duration < LIMITS.minPathDuration) {\n err(`${path}.duration`, `must be >= ${LIMITS.minPathDuration} ms`);\n }\n if (motion.curve !== undefined && motion.curve !== 'linear' && motion.curve !== 'smooth') {\n err(`${path}.curve`, \"must be 'linear' | 'smooth'\");\n }\n if (motion.closed !== undefined && typeof motion.closed !== 'boolean') err(`${path}.closed`, 'must be a boolean');\n const scatterCap = isViewport ? LIMITS.maxMeander / refVp : LIMITS.maxMeander;\n if (motion.scatter !== undefined && (!isNum(motion.scatter) || motion.scatter <= 0 || motion.scatter > scatterCap)) {\n err(`${path}.scatter`, `must be > 0 and <= ${isViewport ? scatterCap.toFixed(3) + ' viewport-units' : LIMITS.maxMeander + ' px'}`);\n }\n } else {\n err(`${path}.type`, 'must be drift | rise | bounce | static | orbit | wander | warp | path');\n return;\n }\n\n for (const k of unknownKeys(motion, knownSet)) {\n warn(`${path}.${k}`, 'unknown-property', `unknown motion property '${k}' — will be ignored`);\n }\n}\n\n/** `points` for polygon/stroke: 2..24 (or 3..24) unit pairs inside the −1..1 box. */\nfunction validateShapePoints(points: unknown, path: string, min: number, err: (p: string, m: string) => void): void {\n if (!Array.isArray(points) || points.length < min || points.length > LIMITS.maxShapePoints) {\n return err(path, `must be ${min}..${LIMITS.maxShapePoints} [x, y] pairs in unit coordinates (-1..1)`);\n }\n for (let i = 0; i < points.length; i++) {\n const pt: unknown = points[i]; // by index, so a sparse array's holes are rejected too\n if (!Array.isArray(pt) || pt.length !== 2 || !isNum(pt[0]) || !isNum(pt[1]) || Math.abs(pt[0]) > 1 || Math.abs(pt[1]) > 1) {\n err(`${path}[${i}]`, 'must be an [x, y] pair with each coordinate in -1..1');\n }\n }\n}\n\nfunction validateEase(ease: unknown, path: string, err: (p: string, m: string) => void, warn: WarnFn): void {\n if (ease === undefined) return;\n if (!isObj(ease)) return err(path, \"must be an object { type: 'settle' | 'buoyant', tau }\");\n if (ease.type !== 'settle' && ease.type !== 'buoyant') err(`${path}.type`, \"must be 'settle' | 'buoyant'\");\n if (!isNum(ease.tau) || ease.tau < LIMITS.minEaseTau || ease.tau > LIMITS.maxEaseTau) {\n err(`${path}.tau`, `must be ${LIMITS.minEaseTau}..${LIMITS.maxEaseTau} ms`);\n }\n for (const k of unknownKeys(ease, new Set(['type', 'tau']))) {\n warn(`${path}.${k}`, 'unknown-property', `unknown ease property '${k}' — will be ignored`);\n }\n}\n\n/** Narrowing helper: validate + cast. Throws with a joined message when invalid. */\nexport function assertValidSpec(spec: unknown): SaverSpec {\n const r = validateSpec(spec);\n if (!r.valid) {\n throw new Error(`invalid saver spec:\\n${r.errors.map((e) => ` ${e.path || '<root>'}: ${e.message}`).join('\\n')}`);\n }\n return spec as SaverSpec;\n}\n\n/**\n * Validate a sequence envelope. Each segment's `scene` goes through `validateSpec`;\n * sequence-level rules (segment count, duration floors, key uniqueness, transition\n * bounds) are checked here.\n */\nexport function validateSequence(seq: unknown): ValidationResult {\n // Normalize each segment's scene (F3: colors-without-color auto-default)\n if (isObj(seq) && Array.isArray(seq.segments)) {\n for (const seg of seq.segments) {\n if (isObj(seg) && isObj((seg as Record<string, unknown>).scene)) {\n normalizeColors((seg as Record<string, unknown>).scene);\n }\n }\n }\n if (isObj(seq) && isObj(seq.bed)) normalizeColors(seq.bed);\n const errors: SpecError[] = [];\n const warnings: SpecWarning[] = [];\n const err = (path: string, message: string): void => void errors.push({ path, message });\n\n if (!isObj(seq)) return { valid: false, errors: [{ path: '', message: 'sequence must be an object' }], warnings: [] };\n\n if (seq.format !== 'idle-sequence') err('format', \"must be 'idle-sequence'\");\n if (seq.schemaVersion !== SCHEMA_VERSION) err('schemaVersion', `must be ${SCHEMA_VERSION}`);\n if (!isStr(seq.id) || seq.id.trim() === '') err('id', 'must be a non-empty string');\n if (!isStr(seq.label) || seq.label.trim() === '') err('label', 'must be a non-empty string');\n if (seq.seed !== undefined && !isNum(seq.seed)) err('seed', 'must be a number');\n if (typeof seq.loop !== 'boolean') err('loop', 'must be a boolean');\n if (seq.sync !== undefined && seq.sync !== 'mount' && seq.sync !== 'epoch') err('sync', \"must be 'mount' | 'epoch'\");\n if (seq.wrapMorph !== undefined && typeof seq.wrapMorph !== 'boolean') err('wrapMorph', 'must be a boolean');\n if (seq.finish !== undefined) validateFinish(seq.finish, 'finish', err, (p, code, message) => void warnings.push({ path: p, code, message }));\n\n if (!Array.isArray(seq.segments) || seq.segments.length === 0) {\n err('segments', 'must be a non-empty array');\n return { valid: false, errors, warnings };\n }\n\n if (seq.segments.length > LIMITS.maxSegments) {\n err('segments', `at most ${LIMITS.maxSegments} segments`);\n }\n\n const keys = new Set<string>();\n let hasDurationless = false;\n\n for (let i = 0; i < seq.segments.length; i++) {\n const s = seq.segments[i];\n const p = `segments[${i}]`;\n if (!isObj(s)) { err(p, 'must be an object'); continue; }\n\n if (!isStr(s.key) || s.key.trim() === '') {\n err(`${p}.key`, 'must be a non-empty string');\n } else if (keys.has(s.key as string)) {\n err(`${p}.key`, `duplicate key '${s.key}'`);\n } else {\n keys.add(s.key as string);\n }\n\n if (s.duration !== undefined) {\n if (hasDurationless) {\n err(`${p}.duration`, 'a segment after a durationless segment may not have a duration');\n }\n if (!isNum(s.duration) || s.duration < LIMITS.minSegmentDuration) {\n err(`${p}.duration`, `must be >= ${LIMITS.minSegmentDuration} ms`);\n }\n } else {\n if (i < seq.segments.length - 1) {\n err(`${p}.duration`, 'only the final segment may omit duration');\n }\n hasDurationless = true;\n }\n\n if (s.advance !== undefined && !['auto', 'input', 'either'].includes(s.advance as string)) {\n err(`${p}.advance`, \"must be 'auto' | 'input' | 'either'\");\n }\n\n if (s.transition !== undefined) {\n if (!isObj(s.transition)) {\n err(`${p}.transition`, 'must be an object');\n } else if (s.transition.type === 'morph' || s.transition.type === 'fade') {\n if (!isNum(s.transition.dur) || s.transition.dur < LIMITS.minTransitionDur || s.transition.dur > LIMITS.maxTransitionDur) {\n err(`${p}.transition.dur`, `must be a number between ${LIMITS.minTransitionDur} and ${LIMITS.maxTransitionDur}`);\n }\n } else if (s.transition.type !== 'cut') {\n err(`${p}.transition.type`, \"must be 'cut', 'morph' or 'fade'\");\n }\n if (isObj(s.transition) && s.transition.text !== undefined) {\n if (s.transition.type !== 'morph') {\n err(`${p}.transition.text`, 'is a morph option (fade already cross-fades whole frames; cut has no window)');\n } else if (s.transition.text !== 'step' && s.transition.text !== 'crossfade' && s.transition.text !== 'dip') {\n err(`${p}.transition.text`, \"must be 'step' | 'crossfade' | 'dip'\");\n }\n }\n }\n\n if (isObj(s.scene)) {\n const sceneResult = validateSpec(s.scene);\n for (const e of sceneResult.errors) errors.push({ path: `${p}.scene.${e.path}`, message: e.message });\n if (sceneResult.warnings) {\n for (const w of sceneResult.warnings) warnings.push({ path: `${p}.scene.${w.path}`, code: w.code, message: w.message });\n }\n } else {\n err(`${p}.scene`, 'must be a valid SaverSpec object');\n }\n }\n\n if (seq.loop === true && hasDurationless) {\n err('loop', 'loop: true requires all segments to have a duration');\n }\n\n // The bed: a full SaverSpec, live alongside whichever segment is up.\n if (seq.bed !== undefined) {\n if (!isObj(seq.bed)) {\n err('bed', 'must be a SaverSpec object');\n } else {\n const bedResult = validateSpec(seq.bed);\n for (const e of bedResult.errors) errors.push({ path: `bed.${e.path}`, message: e.message });\n for (const w of bedResult.warnings ?? []) warnings.push({ path: `bed.${w.path}`, code: w.code, message: w.message });\n if (bedResult.valid) {\n const entityTotal = (spec: unknown): number =>\n isObj(spec) && Array.isArray(spec.layers)\n ? spec.layers.reduce<number>((n, l) => n + (isObj(l) && isNum(l.count) ? l.count : 0), 0)\n : 0;\n const bedTotal = entityTotal(seq.bed);\n const largest = seq.segments.reduce<number>((m, s) => Math.max(m, isObj(s) ? entityTotal(s.scene) : 0), 0);\n if (bedTotal + largest > LIMITS.maxTotal) {\n err('bed', `bed entities ${bedTotal} + largest segment ${largest} = ${bedTotal + largest} exceeds cap ${LIMITS.maxTotal} (the two are live at once)`);\n }\n // The bed owns the ground: a segment background is never painted over it.\n seq.segments.forEach((s, i) => {\n if (isObj(s) && isObj(s.scene) && s.scene.background !== undefined) {\n warnings.push({\n path: `segments[${i}].scene.background`,\n code: 'bed-hides-segment-background',\n message: `segment ${i} declares a background but the sequence has a bed — segments render transparently over the bed, so this background is never painted`,\n });\n }\n });\n }\n }\n }\n\n // Warn when morph is requested but signatures differ (will fall back to cut)\n if (errors.length === 0 && Array.isArray(seq.segments)) {\n for (let i = 0; i < seq.segments.length; i++) {\n const s = seq.segments[i];\n if (!isObj(s) || !isObj(s.transition) || s.transition.type !== 'morph') continue;\n const next = seq.segments[i + 1];\n if (!next || !isObj(next) || !isObj(s.scene) || !isObj(next.scene)) continue;\n const sigA = structuralSignature(s.scene as unknown as SaverSpec);\n const sigB = structuralSignature((next as Record<string, unknown>).scene as unknown as SaverSpec);\n if (sigA !== sigB) {\n warnings.push({\n path: `segments[${i}].transition`,\n code: 'morph-structural-mismatch',\n message: `segments ${i}→${i + 1} differ structurally: morph will fall back to cut`,\n });\n } else if (s.scene.timeline === undefined && (next as Record<string, unknown> & { scene: Record<string, unknown> }).scene.timeline === undefined\n && morphNothingMorphable(s.scene as unknown as SaverSpec, (next as Record<string, unknown>).scene as unknown as SaverSpec, { textCrossfade: s.transition.text === 'crossfade' || s.transition.text === 'dip' })) {\n // Structural twins whose only differences are values lerpSpec steps\n // (strings — textBlock.text above all). The morph runs, but every\n // frame of it shows segment i+1: it reads as a cut. A warning, never\n // an error, so every stored sequence stays valid.\n warnings.push({\n path: `segments[${i}].transition`,\n code: 'morph-nothing-morphable',\n message: `segments ${i}→${i + 1} differ only in values morph cannot interpolate (strings such as textBlock.text step on the first frame): the morph will look like a cut — fade text via colour or reveal.progress`,\n });\n }\n }\n }\n\n // `wrapMorph`: say why the wrap will still be a cut, when it will.\n if (errors.length === 0 && seq.wrapMorph === true) {\n const sq = seq as unknown as IdleSequence;\n const last = sq.segments.length - 1;\n const lastTr = sq.segments[last]?.transition;\n let why: string | null = null;\n if (sq.loop !== true) why = 'the sequence does not loop';\n else if (last < 1) why = 'there is only one segment';\n else if (lastTr?.type !== 'morph') why = 'the last segment declares no morph transition';\n else if (structuralSignature(sq.segments[last]!.scene) !== structuralSignature(sq.segments[0]!.scene)) why = `segment ${last} and segment 0 differ structurally`;\n else if (morphChainRoot(sq, last) !== 0) why = `the lap is not one morph chain (segment ${morphChainRoot(sq, last)} starts a new chain), so the wrap would jump seeds`;\n if (why || !canWrapMorph(sq)) {\n warnings.push({ path: 'wrapMorph', code: 'wrap-morph-inactive', message: `wrapMorph has no effect: ${why ?? 'the wrap cannot morph'} — the wrap stays a cut` });\n }\n }\n\n return { valid: errors.length === 0, errors, warnings };\n}\n\nexport function assertValidSequence(seq: unknown): IdleSequence {\n const r = validateSequence(seq);\n if (!r.valid) {\n throw new Error(`invalid sequence:\\n${r.errors.map((e) => ` ${e.path || '<root>'}: ${e.message}`).join('\\n')}`);\n }\n return seq as IdleSequence;\n}\n","/**\n * Shape glyph geometry — pure, renderer-free, shared by the compiler (what to\n * stroke/fill), perception (how much ink that is) and advise. Everything is\n * computed from the sprite spec + the entity's seeded size, so the canvas and\n * the analytic model agree by construction.\n *\n * Unit coordinates: `polygon.points` and `stroke.points` live in a −1..1 box\n * that is scaled by the entity's half-size (circumradius for polygons, half of\n * `length` for strokes), so the seeded size range is the glyph's bounding\n * diameter — the same rule `circle.radius` / `streak.length` already follow.\n */\nimport type { SpriteSpec } from './types';\n\nexport type ShapedSprite = Extract<SpriteSpec, { kind: 'circle' | 'ring' | 'streak' | 'rect' | 'polygon' | 'stroke' | 'bar' }>;\nexport type BarSprite = Extract<SpriteSpec, { kind: 'bar' }>;\nexport type PolygonSprite = Extract<SpriteSpec, { kind: 'polygon' }>;\nexport type StrokeSprite = Extract<SpriteSpec, { kind: 'stroke' }>;\n\n/** Every sprite that paints with `color` / `colors[]` (as opposed to glyphs). */\nexport function isShapedSprite(s: SpriteSpec): s is ShapedSprite {\n return s.kind === 'circle' || s.kind === 'ring' || s.kind === 'streak' || s.kind === 'rect' || s.kind === 'polygon' || s.kind === 'stroke' || s.kind === 'bar';\n}\n\n/** 0..1 fill of bar `index`: `values[i] / max`, `max` defaulting to the largest value. Read at paint time so steered values glide. */\nexport function barFraction(s: BarSprite, index: number): number {\n const n = s.values.length;\n if (n === 0) return 0;\n const v = s.values[((index % n) + n) % n] ?? 0;\n const max = s.max ?? s.values.reduce((m, x) => Math.max(m, x), 0);\n if (!(max > 0)) return 0;\n return Math.max(0, Math.min(1, v / max));\n}\n\n/** Box of a bar `len` long and `thick` thick growing from (0,0) toward `direction`: centre + half extents, px. */\nexport function barBox(direction: NonNullable<BarSprite['direction']>, len: number, thick: number): { cx: number; cy: number; halfX: number; halfY: number } {\n switch (direction) {\n case 'left': return { cx: -len / 2, cy: 0, halfX: len / 2, halfY: thick / 2 };\n case 'up': return { cx: 0, cy: -len / 2, halfX: thick / 2, halfY: len / 2 };\n case 'down': return { cx: 0, cy: len / 2, halfX: thick / 2, halfY: len / 2 };\n default: return { cx: len / 2, cy: 0, halfX: len / 2, halfY: thick / 2 };\n }\n}\n\nexport const DEFAULT_POLYGON_SIDES = 6;\n/** Minimum samples along a stroke path; grows with the control-point count (6 per segment). */\nexport const STROKE_SAMPLES = 24;\n\n/** Polygon vertices centred on (0,0), unrotated, circumradius `radius` px. Regular n-gons point up. */\nexport function polygonPoints(s: PolygonSprite, radius: number): Array<{ x: number; y: number }> {\n if (s.points && s.points.length >= 3) {\n return s.points.map(([x, y]) => ({ x: x * radius, y: y * radius }));\n }\n const n = Math.max(3, Math.round(s.sides ?? DEFAULT_POLYGON_SIDES));\n const out: Array<{ x: number; y: number }> = [];\n for (let k = 0; k < n; k++) {\n const a = -Math.PI / 2 + (2 * Math.PI * k) / n;\n out.push({ x: Math.cos(a) * radius, y: Math.sin(a) * radius });\n }\n return out;\n}\n\n/**\n * Signed-area magnitude of a polygon (shoelace), px². Exact for simple\n * polygons; a self-intersecting outline (a bow-tie) has lobes of opposite\n * winding that cancel here while the canvas's nonzero fill paints both, so\n * perception under-reports such glyphs. Author facets as simple polygons.\n */\nexport function polygonArea(pts: Array<{ x: number; y: number }>): number {\n let a = 0;\n for (let i = 0; i < pts.length; i++) {\n const p = pts[i]!;\n const q = pts[(i + 1) % pts.length]!;\n a += p.x * q.y - q.x * p.y;\n }\n return Math.abs(a) / 2;\n}\n\n/**\n * Fraction of the circumscribed disc a polygon fills — the perception weight of\n * a SMALL polygon splat. Polygons spanning more than a few grid cells are\n * rasterized by their real outline instead (`luminanceGrid`).\n */\nexport function polygonFill(s: PolygonSprite, radius: number): number {\n if (radius <= 0) return 0;\n const disc = Math.PI * radius * radius;\n return Math.min(1, polygonArea(polygonPoints(s, radius)) / disc);\n}\n\nfunction catmullRom(p0: number, p1: number, p2: number, p3: number, u: number): number {\n const u2 = u * u;\n const u3 = u2 * u;\n return 0.5 * (2 * p1 + (-p0 + p2) * u + (2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 + (-p0 + 3 * p1 - 3 * p2 + p3) * u3);\n}\n\n/**\n * The stroke's path, sampled: `n` points (default STROKE_SAMPLES) centred on\n * (0,0) and scaled so the unit box spans `halfSize` px each way. `curve:\n * 'smooth'` (default) is an open Catmull-Rom through the control points with\n * clamped ends; `'linear'` samples the polyline. Two control points give a\n * straight segment either way.\n */\nexport function strokeSamples(s: StrokeSprite, halfSize: number, n?: number): Array<{ x: number; y: number }> {\n const pts = s.points.map(([x, y]) => ({ x: x * halfSize, y: y * halfSize }));\n const m = pts.length;\n if (m < 2) return pts;\n const smooth = s.curve !== 'linear' && m >= 3;\n const segs = m - 1;\n // Enough samples that every spline segment gets interior points — a\n // 24-point stroke must not collapse to its control polyline.\n n = n ?? Math.max(STROKE_SAMPLES, segs * 6 + 1);\n const at = (k: number): { x: number; y: number } => pts[Math.max(0, Math.min(m - 1, k))]!;\n const out: Array<{ x: number; y: number }> = [];\n for (let i = 0; i < n; i++) {\n const u = (i / (n - 1)) * segs;\n const seg = Math.min(segs - 1, Math.floor(u));\n const local = u - seg;\n const p1 = at(seg);\n const p2 = at(seg + 1);\n if (!smooth) {\n out.push({ x: p1.x + (p2.x - p1.x) * local, y: p1.y + (p2.y - p1.y) * local });\n } else {\n const p0 = at(seg - 1);\n const p3 = at(seg + 2);\n out.push({ x: catmullRom(p0.x, p1.x, p2.x, p3.x, local), y: catmullRom(p0.y, p1.y, p2.y, p3.y, local) });\n }\n }\n return out;\n}\n\n/** Total length of a sampled path, px. */\nexport function pathLength(pts: Array<{ x: number; y: number }>): number {\n let l = 0;\n for (let i = 1; i < pts.length; i++) {\n const dx = pts[i]!.x - pts[i - 1]!.x;\n const dy = pts[i]!.y - pts[i - 1]!.y;\n l += Math.sqrt(dx * dx + dy * dy);\n }\n return l;\n}\n\n/**\n * Taper profile along a stroke, 0..1 of the way along: a brush mark that\n * thins to (almost) nothing at both ends. Floored so a stroke never vanishes\n * mid-mark on a coarse display.\n */\nexport function strokeTaper(u: number): number {\n return Math.max(0.15, Math.sin(Math.PI * Math.max(0, Math.min(1, u))));\n}\n\n/** Stroke width in px for a sprite, with the same default rule as `ring`/`streak`. */\nexport function strokeWidthPx(s: { width?: number }, scale: number): number {\n return Math.max(0.5, (s.width ?? (scale === 1 ? 2 : 0.002)) * scale);\n}\n\n/**\n * Per-step alphas for a feathered rect drawn as `steps` nested fills from the\n * outside in, so the COMPOSITED alpha ramps linearly from 1/steps at the\n * outer edge to 1 at the core. Under source-over each fill sees the ones\n * before it, so step k needs 1/(steps−k+1); under additive blends the fills\n * simply sum, so each contributes 1/steps.\n */\nexport function featherAlphas(steps: number, additive: boolean): number[] {\n const out: number[] = [];\n for (let k = 1; k <= steps; k++) out.push(additive ? 1 / steps : 1 / (steps - k + 1));\n return out;\n}\nexport const FEATHER_STEPS = 6;\n","import type { Rng } from '@idle-screens/core';\nimport type { CycleSpec, LayerSpec, SaverSpec, SpriteSpec, TextBlockAnchor } from './types';\nimport { LIMITS } from './types';\nimport { isShapedSprite } from './shapes';\n\n/**\n * The two scale factors every entity builder must agree on, computed in ONE\n * place. `scale` turns viewport-unit dimensions into px (1 for `units: \"px\"`,\n * min(w,h) otherwise — the default is viewport, so an omitted `units` scales);\n * `countScale` thins or thickens scatter density against `referenceViewport`\n * and is clamped so the projected total never exceeds LIMITS.maxTotal.\n *\n * Four callers (compile, perceive, advise, describe) each carried their own\n * copy of this arithmetic and they drifted twice: describeScene inverted the\n * units default and built every shipped example at scale 1 (F48), and\n * advise/describe skipped the maxTotal clamp so above ~4.6K they measured a\n * scene the renderer never draws — and because the RNG stream is shared across\n * layers, one early layer's different count shifts every later layer's\n * positions too (F49).\n */\nexport function entityScales(spec: SaverSpec, w: number, h: number): { scale: number; countScale: number } {\n const scale = spec.units === 'px' ? 1 : Math.min(w, h);\n const refVp = spec.referenceViewport ?? LIMITS.referenceViewport;\n let countScale = scale > 1 ? Math.min(w, h) / refVp : 1;\n if (countScale > 1) {\n const rawTotal = spec.layers.reduce((s, l) => s + Math.round(l.count * countScale), 0);\n if (rawTotal > LIMITS.maxTotal) countScale *= LIMITS.maxTotal / rawTotal;\n }\n return { scale, countScale };\n}\n\n/** Near plane for warp motion. z lives in [WARP_NEAR, 1]; screen scale is 1/z. */\nexport const WARP_NEAR = 0.08;\n/** Cap on the 1/z size multiplier so near stars don't blow out. */\nexport const WARP_MAX_SCALE = 8;\n\n/** One axis-pair of seeded harmonic octaves for wander motion (amps px, freqs rad/ms). */\nexport interface WanderOsc {\n ax: number[];\n fx: number[];\n phx: number[];\n ay: number[];\n fy: number[];\n phy: number[];\n}\n\n/** A seeded entity: initial state + resolved velocity. `positionAt` is a pure function\n * of this + time, so the rAF loop and renderFrame(t) produce identical results.\n * IMPORTANT (determinism/compat): fields for newer features are OPTIONAL and only\n * set when the feature is declared, so older specs snapshot byte-identically. */\nexport interface Entity {\n x0: number;\n y0: number;\n size: number;\n spriteIndex: number;\n phase: number;\n vx: number; // px/sec\n vy: number; // px/sec\n bob: number; // vertical bob / horizontal sway amplitude (px)\n motion: 'drift' | 'rise' | 'bounce' | 'static' | 'orbit' | 'wander' | 'warp' | 'path';\n headingLeft: boolean;\n alpha: number; // resolved base opacity (default 1)\n pulseAmp: number; // opacity breathing amplitude (0 = none)\n pulsePeriod: number; // ms\n pulsePhase: number;\n spinSpeed: number; // degrees/sec (0 = no rotation)\n spinPhase: number; // seeded starting angle (radians)\n growAmp: number; // size breathing amplitude as fraction (0 = none)\n growPeriod: number; // ms\n growPhase: number;\n orbitR: number; // orbit radius (px, 0 = not orbiting)\n orbitCx: number; // orbit center x (px)\n orbitCy: number; // orbit center y (px)\n colorIndex: number; // index into sprite colors[] (-1 = use sprite.color)\n cyclePeriod: number; // ms (0 = no cycling)\n /** Rect sprite second dimension (height px), or bar thickness. Only set for rect / bar sprites. */\n size2?: number;\n /** Reading-order index into `bar.values`. Only set for bar sprites. */\n barIndex?: number;\n /** Placed by a list/table layout: variants cycle from the ordered base index, in step. Only set for data layouts. */\n ordered?: true;\n /** Orbit parent layer key (motion.center = { layer }). Center resolved at render time. */\n orbitParent?: string;\n /** Present only when the layer explicitly disables edge wrapping. */\n wrapDisabled?: true;\n /** Harmonic drift params. Only set for wander motion. */\n wander?: { own: WanderOsc; shared: WanderOsc; coherence: number; margin: number };\n /** Depth-axis params. Only set for warp motion. */\n warp?: { ux: number; uy: number; z0: number; vz: number; cx: number; cy: number };\n /** Sparse-event window. Only set when `layer.emit` is declared. `phase` ms offset. */\n emit?: { every: number; life: number; phase: number; growFrom: number; growTo: number };\n /** Shared-clock time multiplier for pulse/grow/cycle. Only set when `layer.clock` is declared. */\n clockRate?: number;\n /** Shared cycle phase (radians). Only set when `layer.clock` is declared. */\n cyclePhase?: number;\n /** Velocity easing. Only set when the motion declares `ease`. */\n ease?: { type: 'settle' | 'buoyant'; tau: number };\n /** Static rotation (radians), added to any spin. Only set when `layer.rotate` is declared. */\n rotate?: number;\n /** Spline params (pts in px, shared per layer). Only set for path motion. */\n path?: {\n pts: Array<{ x: number; y: number }>;\n duration: number;\n closed: boolean;\n smooth: boolean;\n phase: number; // 0..1 offset along the path\n offX: number; // per-entity scatter (px)\n offY: number;\n };\n}\n\nexport interface Placed {\n x: number;\n y: number;\n flip: boolean;\n}\n\nexport function spriteVariants(sprite: SpriteSpec): number {\n if (sprite.kind === 'emoji') return sprite.glyphs.length;\n if (sprite.kind === 'text') return sprite.strings.length;\n return 1;\n}\n\nconst OCT_AMP = [1, 0.5, 0.25];\nconst OCT_PERIOD: Array<[number, number]> = [\n [6000, 14000],\n [3000, 7000],\n [1500, 4000],\n];\n\n/** Draw one set of 3 harmonic octaves per axis (18 rng draws). `amp` in px. */\nfunction drawOsc(rng: Rng, amp: number): WanderOsc {\n const osc: WanderOsc = { ax: [], fx: [], phx: [], ay: [], fy: [], phy: [] };\n for (let i = 0; i < 3; i++) {\n osc.ax.push(amp * OCT_AMP[i]! * rng.range(0.6, 1.4));\n osc.fx.push((2 * Math.PI) / rng.range(OCT_PERIOD[i]![0], OCT_PERIOD[i]![1]));\n osc.phx.push(rng.range(0, Math.PI * 2));\n }\n for (let i = 0; i < 3; i++) {\n osc.ay.push(amp * OCT_AMP[i]! * rng.range(0.6, 1.4));\n osc.fy.push((2 * Math.PI) / rng.range(OCT_PERIOD[i]![0], OCT_PERIOD[i]![1]));\n osc.phy.push(rng.range(0, Math.PI * 2));\n }\n return osc;\n}\n\nconst GOLDEN = 0.6180339887498949;\n\n/**\n * Per-entity sparse-event parameters. NO rng draws: the scattered offset is a\n * fixed low-discrepancy (golden-ratio) sequence over the entity index, so\n * declaring `emit` never disturbs this layer's — or any later layer's —\n * seeded stream, and the same spec times its events identically under every\n * seed (event timing is composition, like a grid, not scatter). `jitter`\n * blends an even stagger (entity i at i/n of the period — a metronome) with\n * that scattered offset.\n */\nfunction emitParams(\n emit: NonNullable<LayerSpec['emit']>,\n i: number,\n n: number,\n): NonNullable<Entity['emit']> {\n const every = emit.every;\n const jitter = Math.max(0, Math.min(1, emit.jitter ?? 1));\n const scattered = (((i + 0.5) * GOLDEN) % 1) * every;\n const even = (i / Math.max(1, n)) * every;\n const phase = ((even * (1 - jitter) + scattered * jitter) % every + every) % every;\n return {\n every,\n life: Math.min(emit.life, every),\n phase,\n growFrom: emit.grow?.[0] ?? 1,\n growTo: emit.grow?.[1] ?? 1,\n };\n}\n\n/** Weighted index pick from a single uniform draw. Weights are validated positive. */\nfunction weightedIndex(u: number, weights: number[]): number {\n const total = weights.reduce((a, b) => a + b, 0);\n let acc = 0;\n for (let i = 0; i < weights.length; i++) {\n acc += weights[i]! / total;\n if (u < acc) return i;\n }\n return weights.length - 1;\n}\n\n/** Deterministically place a layer's entities using the seeded RNG (never Math.random).\n * `scale` multiplies every dimensional draw (default 1). Used for viewport units.\n * `countScale` multiplies entity count for density-aware scaling (default 1). */\nexport function buildEntities(layer: LayerSpec, rng: Rng, w: number, h: number, scale = 1, countScale = 1): Entity[] {\n // Grid layers are EXEMPT from count scaling. A grid is an exact lattice —\n // columns × rows, authored cell by cell — and scaling its count doesn't thin\n // it like a scatter field, it TRUNCATES it row-major: the last cells simply\n // never spawn. Found live (Entablature, 2026-08-14): on a viewport at\n // countScale ≈ 0.67, an 18-column single-row grid rendered 12 cells and died\n // at two-thirds width, while the analytic perception path (countScale 1)\n // showed it full-width — a renderer-vs-perception split that burned four\n // publishes to isolate. Upscaling is equally wrong: it invents phantom cells\n // beyond the authored lattice. Grid cost is already bounded by maxPerLayer.\n const effectiveCount = countScale === 1 || layer.layout !== undefined\n ? layer.count\n : Math.max(1, Math.min(\n Math.round(layer.count * countScale),\n layer.links ? LIMITS.maxLinkLayerCount : LIMITS.maxPerLayer,\n ));\n // Defaults are authored as their 1080p-equivalent viewport fractions. Using\n // the legacy px defaults directly would multiply 20..40 by the viewport.\n const defaultSize = scale === 1\n ? [20, 40] as const\n : [20 / LIMITS.referenceViewport, 40 / LIMITS.referenceViewport] as const;\n const [smin, smax] = layer.size ?? defaultSize;\n const variants = spriteVariants(layer.sprite);\n const sprite = layer.sprite;\n const spriteColors = isShapedSprite(sprite) ? sprite.colors : undefined;\n const colorWeights = isShapedSprite(sprite) ? sprite.colorWeights : undefined;\n const colorsLen = spriteColors?.length ?? 0;\n const cycle: CycleSpec | undefined = (sprite.kind === 'emoji' || sprite.kind === 'text') ? sprite.cycle : undefined;\n\n // Layer-level draws for new motion types happen BEFORE the entity loop, guarded by\n // the motion type so pre-existing specs keep bit-identical entity streams.\n const mSpec = layer.motion;\n let sharedOsc: WanderOsc | null = null;\n let meanderPx = 0;\n if (mSpec.type === 'wander') {\n meanderPx = (mSpec.meander ?? (scale === 1 ? 60 : 0.05)) * scale;\n sharedOsc = drawOsc(rng, meanderPx);\n }\n let pathPts: Array<{ x: number; y: number }> | null = null;\n if (mSpec.type === 'path') {\n pathPts = mSpec.points.map((p) => ({ x: p.x * w, y: p.y * h }));\n }\n const ease = (mSpec.type === 'drift' || mSpec.type === 'rise' || mSpec.type === 'wander') ? mSpec.ease : undefined;\n const clockPhase = layer.clock ? ((layer.clock.phase ?? 0) % 1) * Math.PI * 2 : 0;\n\n // Grid layout geometry (pure — no draws).\n const layout = layer.layout;\n // Data layouts (list / table): reading order from an anchor, no scatter.\n const ordered = layout?.type === 'list' || layout?.type === 'table';\n let gapX = 0;\n let gapY = 0;\n let listX0 = 0;\n let listY0 = 0;\n let listCols = 1;\n if (layout?.type === 'list' || layout?.type === 'table') {\n const dflt = scale === 1 ? LIMITS.defaultListGapPx : LIMITS.defaultListGap;\n const g = layout.gap ?? dflt;\n gapX = (typeof g === 'number' ? g : g.x ?? dflt) * scale;\n gapY = (typeof g === 'number' ? g : g.y ?? dflt) * scale;\n listCols = layout.type === 'list' ? 1 : Math.max(1, Math.round(layout.columns));\n const rows = Math.max(1, Math.ceil(effectiveCount / listCols));\n if (layer.position) {\n listX0 = layer.position.x * w;\n listY0 = layer.position.y * h;\n // `dx`/`dy`: an offset in min(w,h) units (#71). Only added when set, so\n // every existing anchor is the same float it always was.\n if (layer.position.dx) listX0 += layer.position.dx * scale;\n if (layer.position.dy) listY0 += layer.position.dy * scale;\n } else {\n const [rx0, rx1] = layer.region?.x ?? [0, 1];\n const [ry0, ry1] = layer.region?.y ?? [0, 1];\n listX0 = ((rx0 + rx1) / 2) * w - ((listCols - 1) * gapX) / 2;\n listY0 = ((ry0 + ry1) / 2) * h - ((rows - 1) * gapY) / 2;\n }\n }\n let gridCols = 0;\n let cellW = 0;\n let cellH = 0;\n let gridX0 = 0;\n let gridY0 = 0;\n if (layout?.type === 'grid') {\n const [rx0, rx1] = layer.region?.x ?? [0, 1];\n const [ry0, ry1] = layer.region?.y ?? [0, 1];\n const gw = Math.max(1, (rx1 - rx0) * w);\n const gh = Math.max(1, (ry1 - ry0) * h);\n gridCols = Math.min(\n layout.columns ?? Math.max(1, Math.round(Math.sqrt(effectiveCount * (gw / gh)))),\n LIMITS.maxGridColumns,\n );\n const gridRows = Math.max(1, Math.ceil(effectiveCount / gridCols));\n cellW = gw / gridCols;\n cellH = gh / gridRows;\n gridX0 = rx0 * w;\n gridY0 = ry0 * h;\n }\n\n const out: Entity[] = [];\n for (let i = 0; i < effectiveCount; i++) {\n const size =\n sprite.kind === 'textBlock'\n ? sprite.fontSize * scale\n : sprite.kind === 'circle' || sprite.kind === 'ring' || sprite.kind === 'polygon'\n ? rng.range(sprite.radius[0], sprite.radius[1]) * 2 * scale\n : sprite.kind === 'streak' || sprite.kind === 'stroke'\n ? rng.range(sprite.length[0], sprite.length[1]) * scale\n : sprite.kind === 'rect'\n ? rng.range(sprite.width[0], sprite.width[1]) * scale\n : sprite.kind === 'bar'\n ? sprite.length * scale\n : rng.range(smin, smax) * scale;\n // Guarded extra draw: only rect sprites with an aspect range consume it.\n const size2 = sprite.kind === 'rect'\n ? size * (sprite.aspect ? rng.range(sprite.aspect[0], sprite.aspect[1]) : 1)\n : sprite.kind === 'bar'\n ? sprite.thickness * scale\n : undefined;\n\n let vx = 0;\n let vy = 0;\n let bob = 0;\n let motion: Entity['motion'] = 'drift';\n let warpParams: Entity['warp'];\n let pathPhase = 0;\n let pathOffX = 0;\n let pathOffY = 0;\n const m = layer.motion;\n if (m.type === 'static') {\n motion = 'static';\n } else if (m.type === 'drift') {\n const s = rng.range(m.speed[0], m.speed[1]) * scale;\n let angle = ((m.angle ?? 0) * Math.PI) / 180;\n if (m.bidirectional && rng.next() < 0.5) angle = Math.PI - angle;\n vx = s * Math.cos(angle);\n vy = s * Math.sin(angle);\n bob = (m.bob ?? 0) * scale;\n } else if (m.type === 'rise') {\n motion = 'rise';\n vy = -rng.range(m.speed[0], m.speed[1]) * scale; // upward\n bob = (m.sway ?? 0) * scale;\n } else if (m.type === 'bounce') {\n motion = 'bounce';\n const s = rng.range(m.speed[0], m.speed[1]) * scale;\n const a = rng.range(0, Math.PI * 2);\n vx = s * Math.cos(a);\n vy = s * Math.sin(a);\n } else if (m.type === 'orbit') {\n motion = 'orbit';\n vx = rng.range(m.speed[0], m.speed[1]); // angular speed in deg/sec, stored in vx (not scaled)\n } else if (m.type === 'wander') {\n motion = 'wander';\n const s = rng.range(m.speed[0], m.speed[1]) * scale;\n const heading = m.angle !== undefined ? (m.angle * Math.PI) / 180 : rng.range(0, Math.PI * 2);\n vx = s * Math.cos(heading);\n vy = s * Math.sin(heading);\n } else if (m.type === 'warp') {\n motion = 'warp';\n const vz = rng.range(m.speed[0], m.speed[1]); // depth-units/sec (not scaled)\n const theta = rng.range(0, Math.PI * 2);\n const r = rng.range(0.15, 1); // radial offset in the projection plane\n warpParams = {\n ux: Math.cos(theta) * r,\n uy: Math.sin(theta) * r,\n z0: rng.range(WARP_NEAR, 1),\n vz,\n cx: (m.center?.x ?? 0.5) * w,\n cy: (m.center?.y ?? 0.5) * h,\n };\n } else if (m.type === 'path') {\n motion = 'path';\n pathPhase = rng.next();\n if (m.scatter) {\n pathOffX = rng.range(-1, 1) * m.scatter * scale;\n pathOffY = rng.range(-1, 1) * m.scatter * scale;\n }\n }\n\n let x0: number;\n let y0: number;\n if (layer.position && layer.count === 1) {\n x0 = layer.position.x * w;\n y0 = layer.position.y * h;\n if (layer.position.dx) x0 += layer.position.dx * scale;\n if (layer.position.dy) y0 += layer.position.dy * scale;\n } else if (layout?.type === 'list' || layout?.type === 'table') {\n // Reading order from the anchor. Burn the two scatter draws so toggling a\n // data layout on or off leaves the rest of this layer's stream intact.\n rng.next();\n rng.next();\n x0 = listX0 + (i % listCols) * gapX;\n y0 = listY0 + Math.floor(i / listCols) * gapY;\n } else if (layout?.type === 'grid') {\n // Grid cells row-major; same 2-draw budget as scatter so toggling layout\n // shifts only THIS layer's stream (layout is structural — rebuild anyway).\n const col = i % gridCols;\n const row = Math.floor(i / gridCols);\n const j = layout.jitter ?? 0;\n const jx = typeof j === 'number' ? j : j.x ?? 0;\n const jy = typeof j === 'number' ? j : j.y ?? 0;\n x0 = gridX0 + (col + 0.5) * cellW + rng.range(-0.5, 0.5) * jx * cellW;\n y0 = gridY0 + (row + 0.5) * cellH + rng.range(-0.5, 0.5) * jy * cellH;\n } else {\n // Spawn window defaults to the full viewport. IMPORTANT (determinism/compat):\n // optional features must only consume EXTRA rng draws when declared, so specs\n // written before a feature existed keep bit-identical entity streams.\n const [rx0, rx1] = layer.region?.x ?? [0, 1];\n const [ry0, ry1] = layer.region?.y ?? [0, 1];\n x0 = rng.range(rx0 * w, rx1 * w);\n y0 = rng.range(ry0 * h, ry1 * h);\n }\n\n const orbitParent = m.type === 'orbit' && m.center && 'layer' in m.center ? m.center.layer : undefined;\n\n out.push({\n x0,\n y0,\n size,\n // Data layouts read variants in order — strings[i] beside bar i. The\n // seeded draw is still consumed so a layout is placement only: toggling\n // list/table never disturbs the layer's alpha, pulse or spin stream.\n spriteIndex: variants > 1 ? (ordered ? (rng.int(0, variants - 1), i % variants) : rng.int(0, variants - 1)) : 0,\n phase: rng.range(0, Math.PI * 2),\n vx,\n vy,\n bob,\n motion,\n headingLeft: vx < 0,\n alpha: layer.alpha ? rng.range(layer.alpha[0], layer.alpha[1]) : 1,\n pulseAmp: layer.pulse?.amp ?? 0,\n pulsePeriod: layer.pulse?.period ?? 1000,\n pulsePhase: layer.pulse ? rng.range(0, Math.PI * 2) : 0,\n // New draws AFTER pulsePhase — guarded so existing specs keep identical streams.\n // Scalar spin: no draw here, one phase draw below (unchanged). Range spin\n // (new): one seeded speed draw here, then the phase draw — array form is new\n // so the extra draw can't perturb any existing spec's entity stream.\n spinSpeed:\n typeof layer.spin === 'number'\n ? (layer.spin * Math.PI) / 180 // deg/sec → rad/sec\n : Array.isArray(layer.spin)\n ? (rng.range(layer.spin[0], layer.spin[1]) * Math.PI) / 180\n : 0,\n spinPhase: layer.spin ? rng.range(0, Math.PI * 2) : 0,\n growAmp: layer.grow?.amp ?? 0,\n growPeriod: layer.grow?.period ?? 1000,\n growPhase: layer.grow ? rng.range(0, Math.PI * 2) : 0,\n orbitR: m.type === 'orbit' ? rng.range(m.radius[0], m.radius[1]) * scale : 0,\n orbitCx: m.type === 'orbit' && !orbitParent ? ((m.center as { x?: number } | undefined)?.x ?? 0.5) * w : 0,\n orbitCy: m.type === 'orbit' && !orbitParent ? ((m.center as { y?: number } | undefined)?.y ?? 0.5) * h : 0,\n // New draws AFTER orbit — guarded so existing specs keep identical streams.\n colorIndex: colorsLen > 0\n ? (colorWeights && colorWeights.length === colorsLen\n ? weightedIndex(rng.next(), colorWeights)\n : ordered\n ? (rng.int(0, colorsLen - 1), i % colorsLen) // data layouts: palette in reading order; draw burned for stream parity\n : rng.int(0, colorsLen - 1))\n : -1,\n cyclePeriod: cycle ? cycle.period : 0,\n // Optional feature fields last (guarded draws inside — wander draws 18 here).\n ...(size2 !== undefined ? { size2 } : {}),\n ...(sprite.kind === 'bar' ? { barIndex: i } : {}),\n ...(ordered ? { ordered: true as const } : {}),\n ...(orbitParent ? { orbitParent } : {}),\n ...(layer.wrap === false ? { wrapDisabled: true as const } : {}),\n ...(m.type === 'wander'\n ? {\n wander: {\n own: drawOsc(rng, meanderPx),\n shared: sharedOsc!,\n coherence: Math.max(0, Math.min(1, m.coherence ?? 0)),\n margin: meanderPx * (OCT_AMP[0]! + OCT_AMP[1]! + OCT_AMP[2]!) * 1.4,\n },\n }\n : {}),\n ...(warpParams ? { warp: warpParams } : {}),\n ...(m.type === 'path' && pathPts\n ? {\n path: {\n pts: pathPts,\n duration: m.duration,\n closed: m.closed !== false,\n smooth: m.curve !== 'linear',\n phase: pathPhase,\n offX: pathOffX,\n offY: pathOffY,\n },\n }\n : {}),\n // Time-structure fields (2026-09): ease draws nothing; emit's one draw\n // per entity happens in a pass AFTER this loop (see below).\n ...(ease ? { ease: { type: ease.type, tau: ease.tau } } : {}),\n // Static rotation (2026-09-10): a scalar draws nothing; the range form\n // draws one value here, last, only when declared.\n ...(typeof layer.rotate === 'number'\n ? { rotate: (layer.rotate * Math.PI) / 180 }\n : Array.isArray(layer.rotate)\n ? { rotate: (rng.range(layer.rotate[0], layer.rotate[1]) * Math.PI) / 180 }\n : {}),\n });\n\n if (layer.clock) {\n // Phase-lock: the seeded pulse/grow phases were drawn above (stream\n // stays put); the shared phase replaces them here. Cycle gets its own\n // field — `phase` also drives bob/sway/orbit, which must stay per-entity.\n const ent = out[out.length - 1]!;\n ent.pulsePhase = clockPhase;\n ent.growPhase = clockPhase;\n ent.cyclePhase = clockPhase;\n ent.clockRate = layer.clock.rate ?? 1;\n }\n if (layer.pulse?.wave) {\n // Position-derived phase: sin(ωt + phase) becomes a traveling wave along\n // `angle`. Patched AFTER the push so the seeded pulsePhase draw stays in its\n // historical stream position (toggling wave must not shift other draws).\n // A clock's phase offsets the wave rather than flattening it.\n const wl = Math.max(1e-6, layer.pulse.wave.wavelength * scale);\n const ang = ((layer.pulse.wave.angle ?? 0) * Math.PI) / 180;\n out[out.length - 1]!.pulsePhase = clockPhase - ((x0 * Math.cos(ang) + y0 * Math.sin(ang)) / wl) * Math.PI * 2;\n }\n }\n if (layer.emit) {\n // Assigned after the loop and without any rng draw (see emitParams), so\n // toggling `emit` rearranges nothing — not this layer, not the ones after.\n for (let i = 0; i < out.length; i++) out[i]!.emit = emitParams(layer.emit, i, out.length);\n }\n return out;\n}\n\n/** Depth of a warp entity at time t: wraps from far (1) to near (WARP_NEAR). Pure. */\nfunction warpZ(e: Entity, t: number): number {\n const wp = e.warp!;\n return wrap(wp.z0 - wp.vz * (t / 1000), WARP_NEAR, 1);\n}\n\nfunction smoothstep(x: number): number {\n const c = x < 0 ? 0 : x > 1 ? 1 : x;\n return c * c * (3 - 2 * c);\n}\n\n/** Fraction of an emit window spent fading in; the rest fades out. */\nconst EMIT_ATTACK = 0.25;\n\n/**\n * Where entity `e` sits in its current emit window at time `t`: 0..1 across\n * the visible `life` ms, or null while dark (or when the layer has no `emit`).\n * Pure — the window index is `floor((t - phase) / every)`, no state.\n */\nexport function emitWindow(e: Entity, t: number): number | null {\n const em = e.emit;\n if (!em) return null;\n const local = (((t - em.phase) % em.every) + em.every) % em.every;\n return local < em.life ? local / em.life : null;\n}\n\n/** Alpha envelope across an emit window: fast smooth attack, slow smooth decay. */\nexport function emitEnvelope(u: number): number {\n if (u < 0 || u >= 1) return 0;\n return u < EMIT_ATTACK ? smoothstep(u / EMIT_ATTACK) : 1 - smoothstep((u - EMIT_ATTACK) / (1 - EMIT_ATTACK));\n}\n\n/** Scene time as the layer's clock sees it (pulse/grow/cycle only). */\nfunction clockTime(e: Entity, t: number): number {\n return e.clockRate ? t * e.clockRate : t;\n}\n\n/**\n * Seconds of travel at time `t` for the velocity-integral motions. Identity\n * without `ease`. `settle`: τ(1 − e^(−t/τ)) — decelerates to rest having\n * travelled speed·τ. `buoyant`: t − τ(1 − e^(−t/τ)) — from rest to terminal\n * speed. With `emit`, t is window-local so every event restarts the travel.\n */\nfunction motionSeconds(e: Entity, t: number): number {\n if (!e.ease) return t / 1000;\n let tl = t;\n if (e.emit) tl = (((t - e.emit.phase) % e.emit.every) + e.emit.every) % e.emit.every;\n const tau = e.ease.tau;\n const k = 1 - Math.exp(-tl / tau);\n return (e.ease.type === 'settle' ? tau * k : tl - tau * k) / 1000;\n}\n\n/** Analytic opacity of an entity at logical time `t` (ms). Pure, clamped to 0..1. */\nexport function alphaAt(e: Entity, t: number): number {\n let a = e.alpha;\n if (e.pulseAmp) a = e.alpha + e.pulseAmp * Math.sin((clockTime(e, t) * 2 * Math.PI) / e.pulsePeriod + e.pulsePhase);\n if (e.motion === 'warp') {\n // Fade in over the first 20% of depth after respawning at the far plane,\n // masking the wrap pop-in.\n const z = warpZ(e, t);\n a *= Math.max(0, Math.min(1, (1 - z) / 0.2));\n }\n if (e.emit) {\n const u = emitWindow(e, t);\n a = u === null ? 0 : a * emitEnvelope(u);\n }\n return a < 0 ? 0 : a > 1 ? 1 : a;\n}\n\n/** Analytic size multiplier at time `t` (ms). Pure, clamped to > 0. */\nexport function sizeAt(e: Entity, t: number): number {\n let s = e.size;\n if (e.growAmp) s = e.size * (1 + e.growAmp * Math.sin((clockTime(e, t) * 2 * Math.PI) / e.growPeriod + e.growPhase));\n if (e.motion === 'warp') s *= Math.min(1 / warpZ(e, t), WARP_MAX_SCALE);\n if (e.emit && (e.emit.growFrom !== 1 || e.emit.growTo !== 1)) {\n const u = emitWindow(e, t);\n if (u !== null) s *= e.emit.growFrom + (e.emit.growTo - e.emit.growFrom) * u;\n }\n return s > 0 ? s : 0.1;\n}\n\n/**\n * Analytic rotation angle at time `t` (ms) in radians. Pure. A static\n * `rotate` is the base; a spinning entity adds its seeded start angle and\n * speed × t on top. With neither, 0 — and with `spin: [0, 0]` also 0: a zero\n * spin speed never rotates, so its seeded phase is not applied (that is what\n * `rotate` is for).\n */\nexport function rotationAt(e: Entity, t: number): number {\n const base = e.rotate ?? 0;\n if (!e.spinSpeed) return base;\n return base + e.spinPhase + e.spinSpeed * (t / 1000);\n}\n\n/** Layer lifecycle alpha multiplier at time `t` (ms). Pure. 1 when `life` is unset. */\nexport function lifeAlphaAt(life: { enter?: number; exit?: number; fade?: number } | undefined, t: number): number {\n if (!life) return 1;\n const fade = life.fade ?? 1000;\n let a = 1;\n if (life.enter !== undefined) {\n if (t < life.enter) return 0;\n a = fade > 0 ? Math.min(1, (t - life.enter) / fade) : 1;\n }\n if (life.exit !== undefined && t >= life.exit) {\n a *= fade > 0 ? Math.max(0, 1 - (t - life.exit) / fade) : 0;\n }\n return a;\n}\n\nfunction wrap(v: number, min: number, max: number): number {\n const range = max - min;\n return ((((v - min) % range) + range) % range) + min;\n}\n\nfunction reflect(v: number, min: number, max: number): number {\n const range = max - min;\n if (range <= 0) return min;\n const period = 2 * range;\n const p = (((v - min) % period) + period) % period;\n return min + (p < range ? p : period - p);\n}\n\nfunction catmullRom(p0: number, p1: number, p2: number, p3: number, u: number): number {\n const u2 = u * u;\n const u3 = u2 * u;\n return 0.5 * (2 * p1 + (-p0 + p2) * u + (2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 + (-p0 + 3 * p1 - 3 * p2 + p3) * u3);\n}\n\nfunction pathPosition(e: Entity, t: number): { x: number; y: number } {\n const p = e.path!;\n const n = p.pts.length;\n let s = ((t / p.duration) + p.phase) % 1;\n if (s < 0) s += 1;\n if (!p.closed) {\n // Ping-pong so open paths reverse smoothly instead of teleporting.\n const pp = s * 2;\n s = pp < 1 ? pp : 2 - pp;\n }\n const segs = p.closed ? n : n - 1;\n const u = Math.min(s * segs, segs - 1e-9);\n const i = Math.floor(u);\n const local = u - i;\n const at = (k: number): { x: number; y: number } =>\n p.closed ? p.pts[((k % n) + n) % n]! : p.pts[Math.max(0, Math.min(n - 1, k))]!;\n const p1 = at(i);\n const p2 = at(i + 1);\n if (!p.smooth) {\n return {\n x: p1.x + (p2.x - p1.x) * local + p.offX,\n y: p1.y + (p2.y - p1.y) * local + p.offY,\n };\n }\n const p0 = at(i - 1);\n const p3 = at(i + 2);\n return {\n x: catmullRom(p0.x, p1.x, p2.x, p3.x, local) + p.offX,\n y: catmullRom(p0.y, p1.y, p2.y, p3.y, local) + p.offY,\n };\n}\n\n/** Analytic position of an entity at logical time `t` (ms). Pure & deterministic. */\nexport function positionAt(e: Entity, t: number, w: number, h: number): Placed {\n if (e.motion === 'static') return { x: e.x0, y: e.y0, flip: false };\n if (e.motion === 'orbit') {\n const angle = e.phase + (e.vx * Math.PI / 180) * (t / 1000);\n return {\n x: e.orbitCx + e.orbitR * Math.cos(angle),\n y: e.orbitCy + e.orbitR * Math.sin(angle),\n flip: false,\n };\n }\n if (e.motion === 'warp') {\n const wp = e.warp!;\n const persp = 1 / warpZ(e, t);\n const halfMin = Math.min(w, h) / 2;\n return {\n x: wp.cx + wp.ux * halfMin * persp,\n y: wp.cy + wp.uy * halfMin * persp,\n flip: false,\n };\n }\n if (e.motion === 'path') {\n const pos = pathPosition(e, t);\n return { x: pos.x, y: pos.y, flip: false };\n }\n const dt = motionSeconds(e, t);\n const m = e.size;\n if (e.motion === 'bounce') {\n return {\n x: reflect(e.x0 + e.vx * dt, m / 2, w - m / 2),\n y: reflect(e.y0 + e.vy * dt, m / 2, h - m / 2),\n flip: false,\n };\n }\n if (e.motion === 'rise') {\n const y = e.y0 + e.vy * dt;\n return {\n x: e.x0 + (e.bob ? e.bob * Math.sin(t / 700 + e.phase) : 0),\n y: e.wrapDisabled ? y : wrap(y, -m, h + m),\n flip: false,\n };\n }\n if (e.motion === 'wander') {\n const wp = e.wander!;\n const c = wp.coherence;\n let hx = 0;\n let hy = 0;\n for (let i = 0; i < 3; i++) {\n if (c < 1) {\n hx += (1 - c) * wp.own.ax[i]! * Math.sin(wp.own.fx[i]! * t + wp.own.phx[i]!);\n hy += (1 - c) * wp.own.ay[i]! * Math.sin(wp.own.fy[i]! * t + wp.own.phy[i]!);\n }\n if (c > 0) {\n hx += c * wp.shared.ax[i]! * Math.sin(wp.shared.fx[i]! * t + wp.shared.phx[i]!);\n hy += c * wp.shared.ay[i]! * Math.sin(wp.shared.fy[i]! * t + wp.shared.phy[i]!);\n }\n }\n const margin = m + wp.margin;\n const x = e.x0 + e.vx * dt + hx;\n const y = e.y0 + e.vy * dt + hy;\n return {\n x: e.wrapDisabled ? x : wrap(x, -margin, w + margin),\n y: e.wrapDisabled ? y : wrap(y, -margin, h + margin),\n flip: e.headingLeft,\n };\n }\n // drift\n const rawX = e.x0 + e.vx * dt;\n const x = e.wrapDisabled ? rawX : wrap(rawX, -m, w + m);\n const rawY = e.y0 + e.vy * dt;\n let y = e.vy !== 0 && !e.wrapDisabled ? wrap(rawY, -m, h + m) : rawY;\n if (e.bob) y += e.bob * Math.sin(t / 500 + e.phase);\n return { x, y, flip: e.headingLeft };\n}\n\n/**\n * Analytic heading (radians) at time `t`, from a finite difference of positionAt.\n * Used to orient streak sprites. Returns null across a wrap seam (position jump\n * larger than half the viewport) — callers should skip orientation that frame.\n */\nexport function headingAt(e: Entity, t: number, w: number, h: number): number | null {\n const dtMs = 32;\n const t1 = t < dtMs ? t + dtMs : t;\n const t0 = t1 - dtMs;\n const a = positionAt(e, t0, w, h);\n const b = positionAt(e, t1, w, h);\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n if (Math.abs(dx) > w / 2 || Math.abs(dy) > h / 2) return null;\n if (dx === 0 && dy === 0) return null;\n return Math.atan2(dy, dx);\n}\n\n/** Time-varying sprite index for text/emoji cycling. Returns static index when cyclePeriod is 0. */\nexport function spriteIndexAt(e: Entity, t: number, variants: number): number {\n if (!e.cyclePeriod || variants <= 1) return e.spriteIndex;\n // Under a data layout the rows keep their reading order and advance in\n // step — a marquee — instead of each entity cycling from its own phase.\n if (e.ordered) return (e.spriteIndex + Math.floor(clockTime(e, t) / e.cyclePeriod)) % variants;\n return Math.floor(clockTime(e, t) / e.cyclePeriod + (e.cyclePhase ?? e.phase) / (2 * Math.PI)) % variants;\n}\n\n/** An inter-entity link edge with its (wrap-aware) distance, for falloff alpha. */\nexport interface LinkEdge {\n i: number;\n j: number;\n dist: number;\n}\n\nfunction wrapDist(\n pi: { x: number; y: number },\n pj: { x: number; y: number },\n doWrap: boolean,\n w: number,\n h: number,\n): number {\n let dx = pj.x - pi.x;\n let dy = pj.y - pi.y;\n if (doWrap) {\n if (Math.abs(dx) > w / 2) dx = dx > 0 ? dx - w : dx + w;\n if (Math.abs(dy) > h / 2) dy = dy > 0 ? dy - h : dy + h;\n }\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n/**\n * Edge list for a layer's `links`, dispatching on mode:\n * 'nearest' (default) k-nearest within maxDist; 'chain' sequential order\n * (Mystify — ignores k/maxDist, `closed` joins last to first); 'random' a fixed\n * golden-ratio-stride wiring filtered by maxDist (deterministic, no RNG draws).\n */\nexport function linkEdges(\n links: { k: number; maxDist: number; mode?: 'nearest' | 'chain' | 'random'; closed?: boolean },\n positions: Array<{ x: number; y: number }>,\n maxDistPx: number,\n doWrap: boolean,\n w: number,\n h: number,\n): LinkEdge[] {\n const n = positions.length;\n const mode = links.mode ?? 'nearest';\n if (mode === 'chain') {\n const out: LinkEdge[] = [];\n for (let i = 0; i < n - 1; i++) {\n out.push({ i, j: i + 1, dist: wrapDist(positions[i]!, positions[i + 1]!, doWrap, w, h) });\n }\n if (links.closed && n > 2) out.push({ i: n - 1, j: 0, dist: wrapDist(positions[n - 1]!, positions[0]!, doWrap, w, h) });\n return out;\n }\n if (mode === 'random') {\n const stride = Math.max(1, Math.round(n * 0.381966)); // golden-ratio conjugate — spreads partners\n const edges = new Set<string>();\n const out: LinkEdge[] = [];\n for (let i = 0; i < n; i++) {\n for (let mIdx = 1; mIdx <= links.k; mIdx++) {\n const j = (i + mIdx * stride) % n;\n if (j === i) continue;\n const dist = wrapDist(positions[i]!, positions[j]!, doWrap, w, h);\n if (dist > maxDistPx) continue;\n const key = `${Math.min(i, j)}:${Math.max(i, j)}`;\n if (!edges.has(key)) {\n edges.add(key);\n out.push({ i: Math.min(i, j), j: Math.max(i, j), dist });\n }\n }\n }\n return out;\n }\n return linkPairs(positions, links.k, maxDistPx, doWrap, w, h).map(([i, j]) => ({\n i,\n j,\n dist: wrapDist(positions[i]!, positions[j]!, doWrap, w, h),\n }));\n}\n\n/** K-nearest-neighbor edge list. Deterministic tie-break: (dist, index).\n * When `doWrap` is true, uses toroidal distance so links don't streak across wrap seams. */\nexport function linkPairs(\n positions: Array<{ x: number; y: number }>,\n k: number,\n maxDist: number,\n doWrap: boolean,\n w: number,\n h: number,\n): Array<[number, number]> {\n const n = positions.length;\n const edges = new Set<string>();\n const out: Array<[number, number]> = [];\n\n for (let i = 0; i < n; i++) {\n const pi = positions[i]!;\n const neighbors: Array<{ dist: number; j: number }> = [];\n for (let j = 0; j < n; j++) {\n if (i === j) continue;\n const pj = positions[j]!;\n let dx = pj.x - pi.x;\n let dy = pj.y - pi.y;\n if (doWrap) {\n if (Math.abs(dx) > w / 2) dx = dx > 0 ? dx - w : dx + w;\n if (Math.abs(dy) > h / 2) dy = dy > 0 ? dy - h : dy + h;\n }\n const dist = Math.sqrt(dx * dx + dy * dy);\n if (dist <= maxDist) neighbors.push({ dist, j });\n }\n neighbors.sort((a, b) => a.dist - b.dist || a.j - b.j);\n for (let ni = 0; ni < Math.min(k, neighbors.length); ni++) {\n const j = neighbors[ni]!.j;\n const lo = Math.min(i, j);\n const hi = Math.max(i, j);\n const key = `${lo}:${hi}`;\n if (!edges.has(key)) {\n edges.add(key);\n out.push([lo, hi]);\n }\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Deterministic text-block line breaking\n// ---------------------------------------------------------------------------\n\nconst CHAR_NARROW = new Set('iIljtf1!|.,;:\\'\"()[]{}');\nconst CHAR_WIDE = new Set('mwMWGOQD@%');\n\n/**\n * Which advance table the line-breaker uses. `proportional` is the\n * character-class table below (the default, and the only table until\n * `textBlock.font` existed); `mono` is a uniform 0.6 em advance — the classic\n * monospace cell (Courier, Menlo, SF Mono all sit within a percent of it).\n */\nexport type TextMetricsClass = 'proportional' | 'mono';\n\nconst MONO_FAMILY_RE = /\\b(?:ui-)?mono(?:space)?\\b|courier|menlo|monaco|sfmono|consolas|inconsolata|fira\\s*code|source\\s*code|jetbrains|ibm\\s*plex\\s*mono|roboto\\s*mono/i;\n\n/**\n * Metrics class for a `textBlock.font` string: `mono` when the family names\n * a monospace face (the generic `monospace`, or a well-known fixed-pitch\n * family), else `proportional`. Absent font ⇒ proportional, as before.\n */\nexport function textMetricsClassFor(font?: string): TextMetricsClass {\n return font && MONO_FAMILY_RE.test(font) ? 'mono' : 'proportional';\n}\n\nconst MONO_ADVANCE_EM = 0.6;\n\n/**\n * Approximate glyph width as a fraction of em. Uses character-class buckets\n * so line breaks are identical across platforms (no measureText). The average\n * across Latin text lands near 0.55, close to perceive.ts's 0.62 heuristic\n * but with per-class refinement. Under `mono` every glyph (space included)\n * advances the same cell.\n */\nfunction charWidthEm(ch: string, metrics: TextMetricsClass = 'proportional'): number {\n if (metrics === 'mono') return MONO_ADVANCE_EM;\n if (ch === ' ' || ch === '\\t') return 0.3;\n if (CHAR_NARROW.has(ch)) return 0.35;\n if (CHAR_WIDE.has(ch)) return 0.72;\n return 0.55;\n}\n\n/**\n * Em-width of a string under the same character-class table `breakTextBlock`\n * uses. `mono` counts grapheme clusters, not UTF-16 code units — an emoji or\n * combining/ZWJ sequence is one advance-width cell, matching what's painted,\n * not one cell per surrogate half or combining mark.\n */\nexport function textWidthEm(str: string, metrics: TextMetricsClass = 'proportional'): number {\n if (metrics === 'mono') return graphemeClusters(str).length * MONO_ADVANCE_EM;\n let w = 0;\n for (let i = 0; i < str.length; i++) w += charWidthEm(str[i]!, metrics);\n return w;\n}\n\nexport interface TextBlockLine {\n text: string;\n widthEm: number;\n}\n\n/**\n * Break `text` into lines that fit within `maxWidthEm` em-widths. Splits on\n * whitespace; a single word wider than the limit gets its own line unbroken.\n * Explicit `\\n` always forces a break. Pure, deterministic, no canvas needed.\n */\nexport function breakTextBlock(text: string, maxWidthEm: number, metrics: TextMetricsClass = 'proportional'): TextBlockLine[] {\n const paragraphs = text.split('\\n');\n const lines: TextBlockLine[] = [];\n\n for (const para of paragraphs) {\n if (para.length === 0) {\n lines.push({ text: '', widthEm: 0 });\n continue;\n }\n const words = para.split(/\\s+/).filter((w) => w.length > 0);\n if (words.length === 0) {\n lines.push({ text: '', widthEm: 0 });\n continue;\n }\n\n let lineText = words[0]!;\n let lineW = textWidthEm(lineText, metrics);\n const spaceW = charWidthEm(' ', metrics);\n\n for (let i = 1; i < words.length; i++) {\n const word = words[i]!;\n const wordW = textWidthEm(word, metrics);\n if (lineW + spaceW + wordW <= maxWidthEm) {\n lineText += ' ' + word;\n lineW += spaceW + wordW;\n } else {\n lines.push({ text: lineText, widthEm: lineW });\n lineText = word;\n lineW = wordW;\n }\n }\n lines.push({ text: lineText, widthEm: lineW });\n }\n\n return lines;\n}\n\n/**\n * Where an anchored textBlock's layout origin sits relative to `position`:\n * the (dx, dy) to ADD to `position` so that the named point of the rendered\n * text lands on it. The rendered box is the widest line wide (placed inside\n * the `maxWidth` box by `align`) and `lines × lineHeight` tall — so `anchor`\n * says where the block sits and `align` only shapes its ragged edge. Absent\n * anchor ⇒ (0, 0): `position` stays the layout box's top-left, exactly as\n * before the field existed. Renderer, perception and advisories all call\n * this, so their boxes agree by construction.\n */\nexport function textBlockAnchorOffset(\n s: { anchor?: TextBlockAnchor; align?: 'left' | 'center' | 'right' },\n maxWPx: number,\n maxLineW: number,\n totalH: number,\n): { dx: number; dy: number } {\n if (!s.anchor) return { dx: 0, dy: 0 };\n const ax = s.anchor.endsWith('left') ? 0 : s.anchor.endsWith('right') ? 1 : 0.5;\n const ay = s.anchor.startsWith('top') ? 0 : s.anchor.startsWith('bottom') ? 1 : 0.5;\n // Ink left edge relative to the layout origin, as `align` places it.\n const inkX0 = s.align === 'center' ? (maxWPx - maxLineW) / 2 : s.align === 'right' ? maxWPx - maxLineW : 0;\n return { dx: -(inkX0 + ax * maxLineW), dy: -(ay * totalH) };\n}\n\n// ---------------------------------------------------------------------------\n// Deterministic text reveal (textBlock `reveal` — typing/deleting)\n// ---------------------------------------------------------------------------\n\n// Combining/attaching code points that must never be painted without their\n// base: combining diacritics, variation selectors, skin-tone modifiers,\n// keycap. Deliberately a fixed table rather than Intl.Segmenter, which is\n// not required to segment identically across engines — same philosophy (and\n// same determinism reason) as the charWidthEm buckets above.\nfunction isClusterExtend(cp: number): boolean {\n return (\n (cp >= 0x0300 && cp <= 0x036f) || // combining diacritics\n (cp >= 0x1ab0 && cp <= 0x1aff) ||\n (cp >= 0x20d0 && cp <= 0x20ff) ||\n (cp >= 0xfe00 && cp <= 0xfe0f) || // variation selectors\n (cp >= 0x1f3fb && cp <= 0x1f3ff) || // skin tones\n cp === 0x20e3 // combining enclosing keycap\n );\n}\n\nfunction isRegionalIndicator(cp: number): boolean {\n return cp >= 0x1f1e6 && cp <= 0x1f1ff;\n}\n\nconst ZWJ = 0x200d;\n\n/**\n * Split a string into paint-safe grapheme clusters: surrogate pairs stay\n * whole, combining marks / variation selectors / skin tones attach to their\n * base, ZWJ joins sequences (emoji families), regional indicators pair up\n * (flags). Deterministic across engines by construction.\n */\nexport function graphemeClusters(text: string): string[] {\n const out: string[] = [];\n let i = 0;\n while (i < text.length) {\n const cp = text.codePointAt(i)!;\n let end = i + (cp > 0xffff ? 2 : 1);\n // Flag pair: two regional indicators form one cluster.\n if (isRegionalIndicator(cp) && end < text.length) {\n const next = text.codePointAt(end)!;\n if (isRegionalIndicator(next)) end += next > 0xffff ? 2 : 1;\n }\n // Attach extenders and ZWJ-joined sequences.\n while (end < text.length) {\n const next = text.codePointAt(end)!;\n if (isClusterExtend(next)) {\n end += next > 0xffff ? 2 : 1;\n } else if (next === ZWJ && end + 1 < text.length) {\n const after = text.codePointAt(end + 1)!;\n end += 1 + (after > 0xffff ? 2 : 1);\n } else {\n break;\n }\n }\n out.push(text.slice(i, end));\n i = end;\n }\n return out;\n}\n\nexport interface TextRevealInput {\n progress?: number;\n mode?: 'typewriter' | 'word' | 'line' | 'glyphFade';\n speed?: number;\n fade?: number;\n}\n\nexport interface RevealState {\n /** Effective 0..1 progress after combining authored progress and speed at t. */\n progress: number;\n /** Number of fully visible lines. */\n fullLines: number;\n /** Grapheme-safe visible prefix of the next line ('' when none). */\n partialText: string;\n /** Caret anchor: line index and the visible prefix on that line. */\n caretLine: number;\n caretPrefix: string;\n /**\n * `glyphFade` mode only: per-line per-grapheme alpha (0..1), indexed\n * parallel to `graphemeClusters(lines[i].text)`. Alphas only decrease in\n * reading order, so a renderer may stop at the first zero.\n */\n glyphAlphas?: number[][];\n}\n\n/**\n * Resolve which glyphs of a broken textBlock are visible at time `tMs`.\n * Pure function of (lines, reveal, tMs) — the renderer paints exactly this,\n * and perceive models exactly this, so agents and pixels agree. `speed` is\n * graphemes/sec regardless of mode; mode only quantizes the frontier.\n */\nexport function revealState(lines: TextBlockLine[], reveal: TextRevealInput, tMs: number): RevealState {\n const lineClusters = lines.map((l) => graphemeClusters(l.text));\n const totalGraphemes = lineClusters.reduce((n, c) => n + c.length, 0);\n\n const authored = Math.max(0, Math.min(1, reveal.progress ?? 1));\n const speed = reveal.speed ?? 0;\n const timed = speed > 0 && totalGraphemes > 0 ? Math.min(1, (speed * tMs) / 1000 / totalGraphemes) : 1;\n const progress = Math.min(authored, timed);\n\n const mode = reveal.mode ?? 'typewriter';\n let fullLines = 0;\n let partialText = '';\n\n // glyphFade: glyph g starts fading at (g/total)·(1−fade) and ramps to\n // opaque over a `fade`-wide window of progress, so every glyph is 0 at\n // progress 0 and 1 at progress 1. The frontier below (shared with\n // typewriter) still anchors the caret. Pure paint, like everything here.\n let glyphAlphas: number[][] | undefined;\n if (mode === 'glyphFade') {\n // The 0.01 floor is defensive only — validation already enforces the\n // public contract fade ∈ (0, 1] (FORMAT.md). It exists so direct callers\n // that skip validateSpec can't make the divide below infinite, not to\n // remap legal values: anything ≥ 0.01 passes through untouched.\n const f = Math.min(1, Math.max(0.01, reveal.fade ?? 0.15));\n let g = 0;\n glyphAlphas = lineClusters.map((clusters) =>\n clusters.map(() => {\n const start = totalGraphemes > 0 ? (g++ / totalGraphemes) * (1 - f) : 0;\n return Math.max(0, Math.min(1, (progress - start) / f));\n }),\n );\n }\n\n if (mode === 'line') {\n fullLines = Math.round(progress * lines.length);\n } else if (mode === 'word') {\n const lineWords = lines.map((l) => (l.text.length === 0 ? [] : l.text.split(' ')));\n const totalWords = lineWords.reduce((n, ws) => n + ws.length, 0);\n let remaining = Math.round(progress * totalWords);\n for (const ws of lineWords) {\n if (remaining >= ws.length) {\n remaining -= ws.length;\n fullLines++;\n // A zero-word (empty) line is \"full\" for free; keep consuming.\n continue;\n }\n if (remaining > 0) partialText = ws.slice(0, remaining).join(' ');\n break;\n }\n } else {\n let remaining = Math.round(progress * totalGraphemes);\n for (const clusters of lineClusters) {\n if (remaining >= clusters.length) {\n remaining -= clusters.length;\n fullLines++;\n continue;\n }\n if (remaining > 0) partialText = clusters.slice(0, remaining).join('');\n break;\n }\n }\n\n // Caret sits at the reveal frontier: end of the partial line, else end of\n // the last full line, else the start of the block.\n let caretLine: number;\n let caretPrefix: string;\n if (partialText.length > 0) {\n caretLine = fullLines;\n caretPrefix = partialText;\n } else if (fullLines > 0) {\n caretLine = fullLines - 1;\n caretPrefix = lines[fullLines - 1]!.text;\n } else {\n caretLine = 0;\n caretPrefix = '';\n }\n\n return { progress, fullLines, partialText, caretLine, caretPrefix, glyphAlphas };\n}\n","import {\n createRng,\n type ControlTrack,\n type ParamDelta,\n type SaverContext,\n type SaverInstance,\n type SaverManifest,\n type SaverPlugin,\n} from '@idle-screens/core';\nimport { assertValidSpec, assertValidSequence, validateSpec, validateSpecPaths } from './validate';\nimport { alphaAt, breakTextBlock, buildEntities, entityScales, graphemeClusters, headingAt, lifeAlphaAt, linkEdges, positionAt, revealState, rotationAt, sizeAt, spriteIndexAt, textBlockAnchorOffset, textMetricsClassFor, type Entity } from './simulate';\nimport {\n applyDeltasToSpec,\n canonicalSpecPath,\n easeSmooth,\n lerpSpec,\n lerpValue,\n readSpecPath,\n resolveSpecPath,\n structuralSignature,\n textStringsDiffer,\n type SteerDelta,\n} from './steer';\nimport { transformOrigin } from './paint';\nimport { nextKeyAfter, resolveTimelineAt, timelineSampleTimesAfter } from './timeline';\nimport type { FieldBackground, IdleSequence, LayerSpec, LayerTransform, SaverSpec, SpriteSpec } from './types';\nimport { LIMITS } from './types';\nimport { FIELD_RASTER_SHORT_SIDE, FIELD_RASTER_SHORT_SIDE_LOW, fieldRgbAt, fieldSampleTime } from './field';\nimport { createFinishPass, createSceneCanvas, presentWithFinish, type FinishPass } from './finish';\nimport { canMorph, canWrapMorph, morphChainRoot, normalizeSeed, resolveSegment, segmentRenderSeed, segmentStart, sequenceSwapCompatible, sequenceWantsFinish } from './sequence';\nimport { FEATHER_STEPS, barBox, barFraction, featherAlphas, isShapedSprite, polygonPoints, strokeSamples, strokeTaper, strokeWidthPx } from './shapes';\n\nconst DEFAULT_STEER_DUR = 1000;\n\n/**\n * Apply steering deltas to a spec one at a time, keeping each only if its\n * path resolves on this spec AND the result validates. This is the routing\n * rule for a sequence's retained track: a key path (`bars.sprite.values`) lands on\n * whichever segment owns the key and is a no-op on the others, and one delta\n * that is out of bounds for a given segment does not take the rest down with\n * it. Returns `spec` itself (same reference) when nothing applied, so callers\n * can skip work — and so a sequence with no track is byte-identical.\n */\nfunction applyRetainedDeltas(spec: SaverSpec, deltas: Iterable<SteerDelta>): SaverSpec {\n let out = spec;\n for (const d of deltas) {\n if (!resolveSpecPath(out, d.path)) continue;\n const next = applyDeltasToSpec(out, [d]);\n if (validateSpec(next).valid) out = next;\n }\n return out;\n}\n\n/** Expand #rgb/#rrggbb to an rgba() string — needed for gradient stops with alpha. */\nfunction hexToRgba(hex: string, alpha: number): string {\n const h = hex.length === 4 ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex;\n const n = parseInt(h.slice(1), 16);\n return `rgba(${(n >> 16) & 255},${(n >> 8) & 255},${n & 255},${alpha})`;\n}\n\nconst FONT_PREFIX_RE = /^((?:(?:italic|oblique|bold|bolder|lighter|normal|\\d{3})\\s+)+)/;\n\n/**\n * Matches the size token in a CSS font shorthand (\"bold 26px monospace\").\n *\n * The digit runs are bounded on purpose. This ran as `(\\d*\\.?\\d+)px`, where\n * `\\d*` and `\\d+` can split the same digit run many ways, so a long run that\n * never reaches \"px\" makes the engine retry every split at every start\n * position. `sprite.font` comes straight from an authored SaverSpec, so that\n * input is reachable by anyone who can publish a scene: 1 000 digits took\n * 600 ms and 5 000 took 62 SECONDS, which is a denial of service rather than\n * a slow path. Bounding each run makes the work per start position constant —\n * 200 000 chars now costs about 4 ms.\n *\n * The bounds are far past anything real: no CSS font size needs more than\n * five integer digits or four decimals. `.5px` still parses via the second\n * branch.\n */\nconst FONT_PX_RE = /(\\d{1,5}(?:\\.\\d{1,4})?|\\.\\d{1,4})px/;\n\n/**\n * Rescale an explicit px size inside a font shorthand.\n *\n * A spec in the default `viewport` units expresses every other dimension as a\n * fraction of `min(w, h)`, so a font pinned to absolute pixels is the one thing\n * that does NOT adapt: `bold 26px monospace` renders 26px whether the canvas is\n * 1920 or 320 wide, which is how the dashboard's text came to overlap itself at\n * thumbnail size. Scaling it by `min(w, h) / referenceViewport` makes it behave\n * like the rest of the spec. Specs that opt into `units: 'px'` are asking for\n * absolute sizes and are left alone.\n */\nfunction scaleFontPx(font: string, factor: number): string {\n if (factor === 1) return font;\n return font.replace(FONT_PX_RE, (_m, n: string) => `${(Number(n) * factor).toFixed(2)}px`);\n}\n\n/** Build a valid CSS font shorthand: weight/style tokens must precede the size. */\nfunction composeFontShorthand(sz: number, font: string): string {\n const m = FONT_PREFIX_RE.exec(font);\n if (m) return `${m[1].trim()} ${sz}px ${font.slice(m[0].length)}`;\n return `${sz}px ${font}`;\n}\n\n/** Derive a manifest so a compiled spec composes with @idle-screens/capabilities. */\nexport function manifestFor(spec: SaverSpec): SaverManifest {\n const total = spec.layers.reduce((n, l) => n + l.count, 0);\n const costTier = total < 30 ? 'idle' : total < 150 ? 'low' : total < 400 ? 'medium' : 'high';\n return {\n id: spec.id,\n label: spec.label,\n // Declarative specs are closed-form by construction: every entity is a\n // pure function of (seed, t), which is the whole point of the format.\n timeModel: 'closed-form',\n passthrough: false,\n minBackend: 'canvas2d',\n costTier,\n motionIntensity: spec.motionIntensity ?? 'moderate',\n reducedMotionFallback: 'static',\n // Flash-safe by construction: static background + bounded sprites, no strobe\n // primitive. Proven by sampling a compiled spec through @idle-screens/validator.\n a11y: { flashSafe: true },\n workerReady: true,\n };\n}\n\ninterface Built {\n layer: LayerSpec;\n entities: Entity[];\n}\n\n/**\n * Internal, per-layer: paint the layer twice for a window — the `outgoing`\n * sprite (the same sprite with the previous words) at `1 − k`, the layer's\n * own sprite at `k`. Set by a `SequenceInstance` for the `text` / `textBlock`\n * layers of a morph declared `text: 'crossfade'`; never from a spec field.\n * Only text sprites are ever drawn this way.\n */\ninterface LayerPaintOverride {\n outgoing: SpriteSpec;\n k: number;\n /**\n * `crossfade` (absent): outgoing at `1 − k` over incoming at `k`, both\n * strings on screen mid-morph. `dip`: outgoing fades out over the first\n * half, incoming fades in over the second — never two strings at once.\n */\n mode?: 'crossfade' | 'dip';\n}\n\n/** One draw's paint override: which sprite to paint, and an alpha multiplier on top of the entity's own. */\ninterface PaintPass {\n sprite?: SpriteSpec;\n alpha: number;\n}\n\n/**\n * The device's compute tier (`computeTier` from `@idle-screens/capabilities`;\n * the string union is repeated here so schema does not depend on that\n * package). Hosts pass it on the mount context; a compiled scene reads it to\n * step down work that a `basic` / `minimal` device cannot afford.\n */\nexport type CapabilityTier = 'minimal' | 'basic' | 'standard' | 'high';\n\n/**\n * Mount context for a compiled spec. A plain `SaverContext` works — every\n * field here is optional. `capabilityTier` `basic` / `minimal` halves a\n * `field` background's raster resolution (48 px short side instead of 96).\n * Absent ⇒ full resolution.\n */\nexport interface SpecMountContext extends SaverContext {\n capabilityTier?: CapabilityTier;\n}\n\n/**\n * A `field` background's cached raster: the field sampled once per cell at\n * the bucketed time, kept until the bucket, the config or the canvas size\n * changes. Drawing a frame is one `drawImage` of this, scaled to the canvas.\n */\ninterface FieldRaster {\n canvas: HTMLCanvasElement | OffscreenCanvas;\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\n cols: number;\n rows: number;\n /** `JSON.stringify` of the config plus dims plus the sample time it was painted for. */\n key: string;\n}\n\n/** Per-instance options a host (today: `SequenceInstance`) sets; a plain compileSaver mount sets none. */\ninterface SpecInstanceOptions {\n /** See `SpecMountContext.capabilityTier`. */\n capabilityTier?: CapabilityTier;\n /**\n * The host presents the frame and applies any `finish` itself (a\n * `SequenceInstance` does, once per composed frame), so this instance\n * never opens a presentation pass of its own — its spec's `finish` is the\n * host's to honour. A plain compileSaver mount presents itself.\n */\n hostPresents?: boolean;\n /**\n * Draw over whatever is already on the surface: `drawBackground` is skipped,\n * the frame is not cleared to a colour, and `ghosting` is ignored (a smear\n * needs an opaque ground to decay into — the surface owner may declare its\n * own). The instance never clears the surface either; the owner does.\n * A sequence's segment children over a `bed` render this way.\n */\n transparent?: boolean;\n /**\n * Skip the constructor's own eager paused-mount paint. For a transparent\n * instance whose owner is about to call `renderFrame` again immediately\n * with paint overrides already set (a morph chain-root child, mounted\n * mid-morph) — the constructor's plain paint would otherwise leave a\n * stray full-opacity frame on the shared surface underneath, which a\n * partial-alpha override pass (`text: 'crossfade'`) then composites over\n * rather than replaces.\n */\n skipInitialPaint?: boolean;\n}\n\nconst clamp01 = (v: number): number => (v <= 0 ? 0 : v >= 1 ? 1 : v);\n\n/** A live steer held on a timeline scene — see `SpecInstance.overrides`. */\ninterface TimelineOverride {\n /** The path's last segment — lets a whole-`transform` glide fill identity fields (see `lerpValue`). */\n leaf: string;\n from: unknown;\n to: unknown;\n t0: number;\n dur: number;\n until: number;\n outDur: number;\n}\nconst EXPIRED = Symbol('expired');\n\n/** An override's glide-in value at scene time `t` (before `until`). */\nfunction overrideHeldAt(o: TimelineOverride, t: number): unknown {\n const k = o.dur > 0 ? easeSmooth(clamp01((t - o.t0) / o.dur)) : 1;\n return k >= 1 ? o.to : lerpValue(o.from, o.to, k, false, o.leaf);\n}\n\n/**\n * An override's value at scene time `t`: glide in, hold, glide back to the\n * timeline, then expire. The glide back starts from wherever the glide in\n * had reached at `until` — a key that lands mid-glide takes the path back\n * from there, not from the steer's target (which would be a jump).\n */\nfunction overrideValueAt(o: TimelineOverride, t: number, timelineValue: () => unknown): unknown {\n if (t < o.until) return overrideHeldAt(o, t);\n if (o.outDur > 0 && t < o.until + o.outDur) return lerpValue(overrideHeldAt(o, o.until), timelineValue(), easeSmooth((t - o.until) / o.outDur), false, o.leaf);\n return EXPIRED;\n}\n\n/** A steer's identity across re-sends: the server's stamp and the value (see `SpecInstance.seenSteers`). */\nconst steerId = (d: SteerDelta): string => `${d.t}|${JSON.stringify(d.value)}`;\n\n/** Arm one steer on a timeline scene at scene time `now` — the steering rule: held until the path's next key, or sticky when no key will touch it. */\nfunction armOverride(authored: SaverSpec, path: string, from: unknown, to: unknown, now: number, glide: number): TimelineOverride {\n const next = nextKeyAfter(authored, path, now);\n return { leaf: path.slice(path.lastIndexOf('.') + 1), from, to, t0: now, dur: glide, until: next ? next.at : Number.POSITIVE_INFINITY, outDur: next ? next.dur : 0 };\n}\n\n/**\n * `resolved` (a timeline resolved at `t`) with the live overrides layered on.\n * `expired` collects the paths whose override has run out, so an owner can\n * drop them; nothing is mutated here.\n */\nfunction applyOverridesAt(resolved: SaverSpec, overrides: ReadonlyMap<string, TimelineOverride>, t: number, expired?: string[]): SaverSpec {\n if (overrides.size === 0) return resolved;\n const deltas: SteerDelta[] = [];\n for (const [path, o] of overrides) {\n const v = overrideValueAt(o, t, () => readSpecPath(resolved, path));\n if (v === EXPIRED) { expired?.push(path); continue; }\n deltas.push({ t: 0, path, value: v });\n }\n return deltas.length > 0 ? applyDeltasToSpec(resolved, deltas) : resolved;\n}\n\n/**\n * Whether a timeline scene stays valid with these overrides on it — now, and\n * at every key boundary still ahead (a sticky steer outlives the keys, and\n * two values each valid alone can break a flash-safety ratio together).\n */\nfunction overridesStayValid(authored: SaverSpec, overrides: ReadonlyMap<string, TimelineOverride>, now: number): boolean {\n // Only the layers (or background/finish) the overrides live in can be broken\n // by them — the timeline alone was validated with the spec — so judge just\n // those, and only at states not already judged.\n const paths = [...overrides.keys()];\n if (paths.length === 0) return true;\n const groupOf = (p: string): string => p.split('.').slice(0, p.startsWith('layers.') ? 2 : 1).join('.');\n const groups = [...new Set(paths.map(groupOf))];\n // The keys that can combine with these steers are those in the same\n // groups (or any, when a steer falls back to the full check).\n const full = paths.some((p) => /^layers\\.\\d+(\\.(key|count|motion)(\\.|$)|$)/.test(p) || p === 'groups' || !/^(layers|background|finish|groups)(\\.|$)/.test(p));\n const only = full ? undefined : (p: string): boolean => groups.includes(groupOf(p));\n const seen = new Set<string>();\n for (const t of [now, ...timelineSampleTimesAfter(authored, now, false, only)]) {\n const held = new Map<string, TimelineOverride>();\n // Judge each override at its held value (the glide-back runs between two valid values).\n for (const [p, o] of overrides) if (t < o.until) held.set(p, { ...o, t0: Number.NEGATIVE_INFINITY });\n const r = applyOverridesAt(resolveTimelineAt(authored, t), held, t);\n const state = JSON.stringify(groups.map((g) => readSpecPath(r, g))) + '|' + [...held.keys()].join(',');\n if (seen.has(state)) continue;\n seen.add(state);\n if (!validateSpecPaths(r, paths)) return false;\n }\n return true;\n}\n\nclass SpecInstance implements SaverInstance {\n private readonly canvas: HTMLCanvasElement | OffscreenCanvas;\n private readonly ownsCanvas: boolean;\n private readonly transparent: boolean;\n private readonly ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\n private readonly saverCtx: SaverContext;\n private readonly seed: number;\n private w: number;\n private h: number;\n private layers: Built[] = [];\n private frameId: number | null = null;\n private paused = false;\n private startT = 0;\n private baseT = 0; // elapsed logical time carried across pause/resume\n private lastT = 0;\n /** Last time painted — detects non-contiguous seeks for the ghosting warm-up replay. */\n private lastRenderT = Number.NEGATIVE_INFINITY;\n\n /** The spec currently being rendered (base spec + any applied steering). */\n private effSpec: SaverSpec;\n /** Active glide between two resolved specs (live setParam/applyTrack). */\n private transition: { from: SaverSpec; to: SaverSpec; startT: number; dur: number } | null = null;\n private lastStructural = '';\n /** See `LayerPaintOverride`; null (the default, and every plain mount) draws every layer once. */\n private paintOverrides: ReadonlyMap<number, LayerPaintOverride> | null = null;\n /**\n * The authored spec when it carries a `timeline` (null for every other\n * scene — which then never enters the timeline path). Each painted frame\n * resolves it at that frame's own time, so ghosting's warm-up replay and\n * any seek see the timeline exactly where it was.\n */\n private authored: SaverSpec | null = null;\n /**\n * Live steers on a timeline scene, by index-form path. A steer on a path no\n * key animates holds forever (sticky, exactly as on a scene without a\n * timeline); on an animated path it holds `until` that path's next key,\n * then glides back to the timeline over `outDur`.\n */\n private overrides: Map<string, TimelineOverride> = new Map();\n /**\n * The last registered steer per path, as `t|value`. A host re-sends the\n * whole channel track on every steer (idle-server broadcasts the full track\n * so viewers converge), and a steer's `t` is the server's stamp — stable\n * across re-sends. Without this, an unrelated later steer would re-arm a\n * hold the timeline had already taken back. Keyed by path (not by the full\n * `path|t|value` history) so a long-running instance re-steered thousands\n * of times doesn't accumulate an unbounded set — only the most recent id\n * per path can ever recur.\n */\n private seenSteers = new Map<string, string>();\n /** Raster short side for a `field` background — halved on the low tiers. */\n private readonly fieldShortSide: number;\n /** The `field` background's cached raster; null until a field is first painted. */\n private field: FieldRaster | null = null;\n /**\n * The presentation pass when this instance applies a `finish`: the\n * visible canvas plus the cached screen tiles. When set, `this.canvas` is\n * an offscreen SCENE canvas — the surface every layer (and `ghosting`'s\n * persistence) draws into — and each frame ends by copying it to the\n * visible canvas and screening the finish over the copy. The finish thus\n * never enters the persistence loop. Null (every plain mount without a\n * finish, every sequence child) draws straight onto the visible canvas,\n * exactly as before the field existed.\n */\n private finishPass: FinishPass | null = null;\n /** False on the `basic`/`minimal` tiers — `finish.animate` renders as a static tile. */\n private readonly animateFinish: boolean;\n\n constructor(\n private readonly spec: SaverSpec,\n ctx: SaverContext,\n opts: SpecInstanceOptions = {},\n ) {\n this.effSpec = spec;\n if (spec.timeline) {\n this.authored = spec;\n this.effSpec = resolveTimelineAt(spec, 0);\n }\n this.saverCtx = ctx;\n this.transparent = opts.transparent === true;\n const tier = opts.capabilityTier;\n this.fieldShortSide = tier === 'basic' || tier === 'minimal' ? FIELD_RASTER_SHORT_SIDE_LOW : FIELD_RASTER_SHORT_SIDE;\n this.animateFinish = tier !== 'basic' && tier !== 'minimal';\n this.seed = normalizeSeed(spec.seed ?? ctx.seed);\n let canvas: HTMLCanvasElement | OffscreenCanvas;\n if (ctx.surface) {\n canvas = ctx.surface;\n this.ownsCanvas = false;\n } else {\n const el = document.createElement('canvas');\n el.style.cssText = 'display:block;width:100%;height:100%';\n el.setAttribute('aria-hidden', 'true');\n ctx.host.appendChild(el);\n canvas = el;\n this.ownsCanvas = true;\n }\n if (spec.finish !== undefined && !this.transparent && !opts.hostPresents) {\n // Present through a pass: the visible canvas becomes the pass's, and\n // the scene draws offscreen. Decided once, from the mounted spec — a\n // steer can only change a `finish` that already exists.\n const pass = createFinishPass(canvas, this.seed);\n if (pass) {\n this.finishPass = pass;\n canvas = createSceneCanvas(ctx.width, ctx.height);\n }\n }\n this.canvas = canvas;\n // Transparent instances (a bed's own offscreen fade canvas) never paint a\n // background, so their cleared/unpainted pixels must stay actually\n // transparent for `composite()`'s drawImage to blend only the ink onto\n // the bed — an opaque (alpha: false) context turns those pixels solid\n // black instead. Opaque instances keep alpha: false (unchanged).\n const c2d = canvas.getContext('2d', { alpha: this.transparent }) as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;\n if (!c2d) throw new Error('schema saver: no 2d context');\n this.ctx = c2d;\n\n this.w = ctx.width;\n this.h = ctx.height;\n this.sizeCanvas();\n this.rebuild();\n\n this.paused = ctx.reducedMotion;\n if (this.paused) {\n if (!opts.skipInitialPaint) this.renderFrame(0, this.seed);\n } else {\n this.start();\n }\n }\n\n /** Viewport factor for absolute px sizes — 1 for `units: 'px'` specs. */\n private fontScale(): number {\n if (this.effSpec.units === 'px') return 1;\n return Math.min(this.w, this.h) / (this.effSpec.referenceViewport ?? LIMITS.referenceViewport);\n }\n\n private sizeCanvas(): void {\n const dpr = Math.min(this.saverCtx.dpr, 2);\n // Assign only on a real change: writing `width`/`height` wipes a canvas\n // even when the value is the same, and a sequence child shares its\n // parent's surface — a segment mounting over a `bed` used to erase the\n // bed painted a moment earlier, one black frame at every cut. A fresh\n // canvas is blank anyway, and every frame repaints (or, after a resize,\n // the ghosting warm-up below replays from a full clear).\n const cw = Math.max(1, Math.round(this.w * dpr));\n const ch = Math.max(1, Math.round(this.h * dpr));\n if (this.canvas.width !== cw) this.canvas.width = cw;\n if (this.canvas.height !== ch) this.canvas.height = ch;\n this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n if (this.finishPass) {\n // The visible canvas mirrors the scene canvas, same size and transform.\n if (this.finishPass.canvas.width !== cw) this.finishPass.canvas.width = cw;\n if (this.finishPass.canvas.height !== ch) this.finishPass.canvas.height = ch;\n this.finishPass.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n }\n // Resizing clears the canvas — force a ghosting warm-up on the next frame.\n this.lastRenderT = Number.NEGATIVE_INFINITY;\n }\n\n /** (Re)seed and place all entities — deterministic for the seed + viewport. */\n private rebuild(): void {\n const rng = createRng(this.seed);\n const { scale, countScale } = entityScales(this.effSpec, this.w, this.h);\n this.layers = this.effSpec.layers.map((layer) => ({ layer, entities: buildEntities(layer, rng, this.w, this.h, scale, countScale) }));\n this.lastStructural = structuralSignature(this.effSpec);\n }\n\n private start(): void {\n if (this.frameId !== null || typeof requestAnimationFrame === 'undefined') return;\n this.startT = 0;\n this.frameId = requestAnimationFrame((now) => this.loop(now));\n }\n\n private stop(): void {\n if (this.frameId !== null) {\n cancelAnimationFrame(this.frameId);\n this.frameId = null;\n }\n // Freeze elapsed time so resume continues the scene instead of restarting at t=0.\n this.baseT = this.lastT;\n }\n\n private loop(now: number): void {\n this.frameId = requestAnimationFrame((n) => this.loop(n));\n if (this.startT === 0) this.startT = now;\n this.lastT = now - this.startT + this.baseT;\n this.renderFrame(this.lastT, this.seed);\n }\n\n private drawBackground(t: number): void {\n const { ctx, w, h } = this;\n const bg = this.effSpec.background;\n if (!bg || bg.type === 'solid') {\n ctx.fillStyle = bg?.color ?? '#05050a';\n ctx.fillRect(0, 0, w, h);\n return;\n }\n if (bg.type === 'field') {\n this.drawField(bg, t);\n return;\n }\n const g = ctx.createLinearGradient(0, 0, 0, h);\n const drift = bg.drift;\n for (let i = 0; i < bg.stops.length; i++) {\n const s = bg.stops[i]!;\n let at = s.at;\n if (drift) {\n const amount = drift.amount ?? 0.15;\n const phase = (i / bg.stops.length) * Math.PI * 2;\n at = Math.max(0, Math.min(1, at + amount * Math.sin((t * 2 * Math.PI) / drift.period + phase)));\n }\n g.addColorStop(at, s.color);\n }\n ctx.fillStyle = g;\n ctx.fillRect(0, 0, w, h);\n if (bg.band) {\n ctx.fillStyle = bg.band.color;\n const bh = bg.band.height * (this.effSpec.units === 'px' ? 1 : Math.min(w, h));\n ctx.fillRect(0, h - bh, w, bh);\n }\n }\n\n /**\n * Paint a `field` background: sample the field into a low-res raster (short\n * side `fieldShortSide`, the long side by aspect) and draw it scaled to the\n * canvas — nearest-neighbour for quantised bands so contours stay crisp,\n * smoothed for `quantize: 0`. The raster is recomputed only when its key\n * changes: the config (steering glides it), the canvas size, or — while\n * drifting — the 100 ms bucket `t` falls in (`fieldSampleTime`); a static\n * field is sampled exactly once per mount. `luminanceGrid` samples the same\n * function at the same bucketed time, so perception and paint agree.\n */\n private drawField(bg: FieldBackground, t: number): void {\n const { ctx, w, h } = this;\n const short = Math.max(1, Math.min(w, h));\n const cols = Math.max(1, Math.round((this.fieldShortSide * w) / short));\n const rows = Math.max(1, Math.round((this.fieldShortSide * h) / short));\n const ft = fieldSampleTime(bg, t);\n // `w`x`h`, not just the rounded `cols`x`rows`: a resize that changes the\n // aspect ratio without moving the rounded raster size would otherwise\n // reuse a raster sampled for the old aspect ratio.\n const key = `${JSON.stringify(bg)}|${w}x${h}|${cols}x${rows}|${ft}`;\n let raster = this.field;\n if (!raster || raster.key !== key) {\n if (!raster || raster.cols !== cols || raster.rows !== rows) {\n const canvas: HTMLCanvasElement | OffscreenCanvas = typeof document !== 'undefined'\n ? document.createElement('canvas')\n : new OffscreenCanvas(cols, rows);\n canvas.width = cols;\n canvas.height = rows;\n const rctx = canvas.getContext('2d') as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;\n if (!rctx) return;\n raster = { canvas, ctx: rctx, cols, rows, key: '' };\n }\n const img = raster.ctx.createImageData(cols, rows);\n const data = img.data;\n const seed = this.seed;\n let i = 0;\n for (let r = 0; r < rows; r++) {\n // Cell centres in short-side units — the same normalisation perceive uses.\n const v = ((r + 0.5) * h) / rows / short;\n for (let c = 0; c < cols; c++) {\n const u = ((c + 0.5) * w) / cols / short;\n const rgb = fieldRgbAt(u, v, ft, bg, seed);\n data[i++] = rgb[0];\n data[i++] = rgb[1];\n data[i++] = rgb[2];\n data[i++] = 255;\n }\n }\n raster.ctx.putImageData(img, 0, 0);\n raster.key = key;\n this.field = raster;\n }\n const smooth = Math.round(bg.quantize ?? bg.bands.length) < 2;\n const prev = ctx.imageSmoothingEnabled;\n ctx.imageSmoothingEnabled = smooth;\n ctx.drawImage(raster.canvas, 0, 0, w, h);\n ctx.imageSmoothingEnabled = prev;\n }\n\n /** Position with parent-orbit resolution: a layer-parented orbit entity's\n * positionAt is an offset around (0,0); add the parent's own analytic position. */\n private entityPos(e: Entity, t: number, parentE: Entity | null): { x: number; y: number; flip: boolean } {\n const p = positionAt(e, t, this.w, this.h);\n if (parentE && e.orbitParent) {\n const pp = positionAt(parentE, t, this.w, this.h);\n p.x += pp.x;\n p.y += pp.y;\n }\n return p;\n }\n\n /** Resolve the single parent entity for a layer-parented orbit layer (or null). */\n private parentEntityFor(built: Built): Entity | null {\n const m = built.layer.motion;\n if (m.type !== 'orbit' || !m.center || !('layer' in m.center)) return null;\n const key = m.center.layer;\n const parent = this.layers.find((b) => b.layer.key === key);\n return parent?.entities[0] ?? null;\n }\n\n private drawTrail(built: Built, e: Entity, t: number, lifeA: number, parentE: Entity | null): void {\n const trail = built.layer.trail;\n if (!trail) return;\n const { ctx, w, h } = this;\n const fade = trail.fade ?? 1;\n const n = Math.min(Math.ceil(trail.length / 50), LIMITS.maxTrailSamples);\n const headAlpha = alphaAt(e, t) * lifeA;\n const headSize = sizeAt(e, t);\n const sprite = built.layer.sprite;\n const resolvedColor = isShapedSprite(sprite)\n ? (sprite.colors?.[e.colorIndex] ?? sprite.color)\n : sprite.kind === 'text' || sprite.kind === 'textBlock' ? (sprite.color ?? '#e6e8ef') : '#e6e8ef';\n const isSoft = sprite.kind === 'circle' && sprite.soft;\n const wrap = built.layer.wrap !== false;\n\n const head = this.entityPos(e, t, parentE);\n let prevX = head.x;\n let prevY = head.y;\n\n for (let s = 1; s <= n; s++) {\n const k = s / n;\n const pastT = t - k * trail.length;\n if (pastT < 0) break;\n const pos = this.entityPos(e, pastT, parentE);\n\n if (wrap) {\n const dx = pos.x - prevX;\n const dy = pos.y - prevY;\n if (Math.abs(dx) > w / 2 || Math.abs(dy) > h / 2) break;\n }\n prevX = pos.x;\n prevY = pos.y;\n\n const a = headAlpha * (1 - k * fade);\n if (a <= 0) break;\n const r = (headSize / 2) * (1 - k * 0.7);\n if (r < 0.2) break;\n\n ctx.globalAlpha = a;\n if (isSoft) {\n const g = ctx.createRadialGradient(pos.x, pos.y, 0, pos.x, pos.y, r);\n g.addColorStop(0, resolvedColor);\n g.addColorStop(0.35, hexToRgba(resolvedColor, 0.75));\n g.addColorStop(1, hexToRgba(resolvedColor, 0));\n ctx.fillStyle = g;\n } else {\n ctx.fillStyle = resolvedColor;\n }\n ctx.beginPath();\n ctx.arc(pos.x, pos.y, r, 0, Math.PI * 2);\n ctx.fill();\n }\n }\n\n private drawEntity(built: Built, e: Entity, t: number, lifeA: number, parentE: Entity | null, paint?: PaintPass): void {\n const { ctx } = this;\n const p = this.entityPos(e, t, parentE);\n const sprite = paint?.sprite ?? built.layer.sprite;\n const sz = sizeAt(e, t);\n const rot = rotationAt(e, t);\n const unitScale = this.effSpec.units === 'px' ? 1 : Math.min(this.w, this.h);\n ctx.globalAlpha = alphaAt(e, t) * lifeA * (paint?.alpha ?? 1);\n if (sprite.kind === 'ring') {\n const r = sz / 2;\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n ctx.strokeStyle = resolvedColor;\n ctx.lineWidth = Math.max(0.5, (sprite.width ?? (unitScale === 1 ? 2 : 0.002)) * unitScale);\n ctx.beginPath();\n ctx.arc(p.x, p.y, r, 0, Math.PI * 2);\n ctx.stroke();\n return;\n }\n if (sprite.kind === 'streak') {\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n const heading = (headingAt(e, t, this.w, this.h) ?? 0) + rot;\n const tailX = p.x - Math.cos(heading) * sz;\n const tailY = p.y - Math.sin(heading) * sz;\n const g = ctx.createLinearGradient(tailX, tailY, p.x, p.y);\n g.addColorStop(0, hexToRgba(resolvedColor, 0));\n g.addColorStop(1, resolvedColor);\n ctx.strokeStyle = g;\n ctx.lineWidth = Math.max(0.5, (sprite.width ?? (unitScale === 1 ? 2 : 0.002)) * unitScale);\n ctx.lineCap = 'round';\n ctx.beginPath();\n ctx.moveTo(tailX, tailY);\n ctx.lineTo(p.x, p.y);\n ctx.stroke();\n return;\n }\n if (sprite.kind === 'rect') {\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n const rh = e.size2 !== undefined\n ? e.size2 * (e.size > 0 ? sz / e.size : 1) // grow/warp scale height with width\n : sz;\n ctx.save();\n ctx.translate(p.x, p.y);\n if (rot) ctx.rotate(rot);\n ctx.fillStyle = resolvedColor;\n const feather = sprite.feather ?? 0;\n if (feather > 0) {\n // Soft edge: nested fills from the OUTSIDE IN — the full-size rect\n // first at the faintest alpha, the core last at full — so the\n // composited alpha ramps linearly across the feathered band (see\n // featherAlphas). Only `lighter` sums alphas; `screen` still\n // composites source-over, so it takes the source-over schedule.\n const base = ctx.globalAlpha;\n const additive = built.layer.blend === 'lighter';\n const alphas = featherAlphas(FEATHER_STEPS, additive);\n for (let j = 1; j <= FEATHER_STEPS; j++) {\n const f = 1 - (feather * (j - 1)) / FEATHER_STEPS; // j=1 full size … j=K the core\n const fw = sz * f;\n const fh = rh * f;\n ctx.globalAlpha = base * alphas[j - 1]!;\n ctx.fillRect(-fw / 2, -fh / 2, fw, fh);\n }\n ctx.globalAlpha = base;\n } else {\n ctx.fillRect(-sz / 2, -rh / 2, sz, rh);\n }\n ctx.restore();\n return;\n }\n if (sprite.kind === 'bar') {\n const len = sz * barFraction(sprite, e.barIndex ?? 0);\n if (len <= 0) return;\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n const th = e.size2 !== undefined ? e.size2 * (e.size > 0 ? sz / e.size : 1) : sz * 0.2;\n const box = barBox(sprite.direction ?? 'right', len, th);\n ctx.save();\n ctx.translate(p.x, p.y);\n if (rot) ctx.rotate(rot);\n ctx.fillStyle = resolvedColor;\n ctx.fillRect(box.cx - box.halfX, box.cy - box.halfY, box.halfX * 2, box.halfY * 2);\n ctx.restore();\n return;\n }\n if (sprite.kind === 'polygon') {\n const r = sz / 2;\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n const pts = polygonPoints(sprite, r);\n ctx.save();\n ctx.translate(p.x, p.y);\n if (rot) ctx.rotate(rot);\n if (sprite.soft) {\n const g = ctx.createRadialGradient(0, 0, 0, 0, 0, r);\n g.addColorStop(0, resolvedColor);\n g.addColorStop(0.35, hexToRgba(resolvedColor, 0.75));\n g.addColorStop(1, hexToRgba(resolvedColor, 0));\n ctx.fillStyle = g;\n } else {\n ctx.fillStyle = resolvedColor;\n }\n ctx.beginPath();\n ctx.moveTo(pts[0]!.x, pts[0]!.y);\n for (let i = 1; i < pts.length; i++) ctx.lineTo(pts[i]!.x, pts[i]!.y);\n ctx.closePath();\n ctx.fill();\n ctx.restore();\n return;\n }\n if (sprite.kind === 'stroke') {\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n const pts = strokeSamples(sprite, sz / 2);\n const lw = strokeWidthPx(sprite, unitScale);\n ctx.save();\n ctx.translate(p.x, p.y);\n let angle = rot;\n if (sprite.orient) angle += headingAt(e, t, this.w, this.h) ?? 0;\n if (angle) ctx.rotate(angle);\n ctx.strokeStyle = resolvedColor;\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n if (sprite.taper) {\n // A brush mark: each sampled segment at its own width.\n for (let i = 1; i < pts.length; i++) {\n ctx.lineWidth = Math.max(0.5, lw * strokeTaper((i - 0.5) / (pts.length - 1)));\n ctx.beginPath();\n ctx.moveTo(pts[i - 1]!.x, pts[i - 1]!.y);\n ctx.lineTo(pts[i]!.x, pts[i]!.y);\n ctx.stroke();\n }\n } else {\n ctx.lineWidth = lw;\n ctx.beginPath();\n ctx.moveTo(pts[0]!.x, pts[0]!.y);\n for (let i = 1; i < pts.length; i++) ctx.lineTo(pts[i]!.x, pts[i]!.y);\n ctx.stroke();\n }\n ctx.restore();\n return;\n }\n if (sprite.kind === 'circle') {\n const r = sz / 2;\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n ctx.save();\n if (rot) {\n ctx.translate(p.x, p.y);\n ctx.rotate(rot);\n ctx.translate(-p.x, -p.y);\n }\n if (sprite.soft) {\n const g = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, r);\n g.addColorStop(0, resolvedColor);\n g.addColorStop(0.35, hexToRgba(resolvedColor, 0.75));\n g.addColorStop(1, hexToRgba(resolvedColor, 0));\n ctx.fillStyle = g;\n } else {\n ctx.fillStyle = resolvedColor;\n }\n ctx.beginPath();\n ctx.arc(p.x, p.y, r, 0, Math.PI * 2);\n ctx.fill();\n ctx.restore();\n return;\n }\n if (sprite.kind === 'textBlock') {\n const unitScale = Math.min(this.w, this.h);\n const fsPx = sprite.fontSize * unitScale;\n const lh = (sprite.lineHeight ?? 1.4) * fsPx;\n const maxWPx = sprite.maxWidth * unitScale;\n const maxWEm = maxWPx / fsPx;\n const lines = breakTextBlock(sprite.text, maxWEm, textMetricsClassFor(sprite.font));\n const align = sprite.align ?? 'left';\n // Reveal masks glyphs; layout above always ran on the full text, so\n // lines never reflow while typing.\n const reveal = sprite.reveal;\n const rs = reveal ? revealState(lines, reveal, t) : null;\n const fullLines = rs ? rs.fullLines : lines.length;\n ctx.save();\n ctx.translate(p.x, p.y);\n if (rot) ctx.rotate(rot);\n if (sprite.anchor) {\n // `position` names a point of the rendered text, not the layout box's\n // top-left. Offset after line-breaking so the block's real extent\n // (widest line × lines) is what gets anchored; rotation stays about\n // the anchor point. Same arithmetic as perceive/advise (simulate.ts).\n const maxLineW = lines.reduce((m, l) => Math.max(m, l.widthEm), 0) * fsPx;\n const { dx, dy } = textBlockAnchorOffset(sprite, maxWPx, maxLineW, lines.length * lh);\n if (dx !== 0 || dy !== 0) ctx.translate(dx, dy);\n }\n // Paint-level alpha for the block only (layer `alpha` is baked per entity).\n if (sprite.opacity !== undefined) ctx.globalAlpha *= sprite.opacity;\n ctx.font = sprite.font ? composeFontShorthand(fsPx, sprite.font) : `${fsPx}px system-ui, sans-serif`;\n ctx.fillStyle = sprite.color ?? '#e6e8ef';\n ctx.textBaseline = 'top';\n ctx.textAlign = align;\n const xOff = align === 'center' ? maxWPx / 2 : align === 'right' ? maxWPx : 0;\n if (rs?.glyphAlphas) {\n // glyphFade: the contiguous fully-opaque leading run draws as ONE\n // fillText — a single draw forms ligatures and pair kerning exactly\n // like the un-revealed path (pixel parity once fully revealed), and it\n // drops the O(n²) per-frame prefix re-measure for glyphs that have\n // finished fading. Only the fading tail draws glyph-by-glyph, each at\n // its full-line prefix advance. measureText is paint-only (the caret's\n // trick) — positions come from the platform's real glyph widths, never\n // the em table, and depend only on the fixed prefix, so glyphs never\n // shift as they fade.\n ctx.textAlign = 'left';\n const baseAlpha = ctx.globalAlpha;\n for (let li = 0; li < lines.length; li++) {\n const alphas = rs.glyphAlphas[li] ?? [];\n if (alphas.length > 0 && alphas[0]! <= 0) break;\n const clusters = graphemeClusters(lines[li]!.text);\n const lw = ctx.measureText(lines[li]!.text).width;\n const x0 = align === 'center' ? (maxWPx - lw) / 2 : align === 'right' ? maxWPx - lw : 0;\n let opaque = 0;\n while (opaque < clusters.length && (alphas[opaque] ?? 0) >= 1) opaque++;\n let prefix = '';\n if (opaque > 0) {\n prefix = clusters.slice(0, opaque).join('');\n ctx.globalAlpha = baseAlpha;\n ctx.fillText(prefix, x0, li * lh);\n }\n for (let gi = opaque; gi < clusters.length; gi++) {\n const a = alphas[gi] ?? 0;\n if (a <= 0) break; // alphas only fall in reading order\n ctx.globalAlpha = baseAlpha * a;\n ctx.fillText(clusters[gi]!, x0 + ctx.measureText(prefix).width, li * lh);\n prefix += clusters[gi]!;\n }\n }\n ctx.globalAlpha = baseAlpha;\n } else {\n for (let li = 0; li < fullLines; li++) {\n ctx.fillText(lines[li]!.text, xOff, li * lh);\n }\n if (rs && rs.partialText.length > 0) {\n ctx.fillText(rs.partialText, xOff, fullLines * lh);\n }\n }\n if (rs && reveal!.caret) {\n const cfg = reveal!.caret === true ? {} : reveal!.caret;\n const hz = Math.min(3, cfg.blink ?? 1.2);\n const on = hz <= 0 || Math.floor((t / 1000) * hz * 2) % 2 === 0;\n if (on) {\n // measureText is paint-only here: it positions the caret against the\n // platform's real glyph widths but never influences layout, which\n // stays on the fixed metrics table.\n const pw = ctx.measureText(rs.caretPrefix).width;\n const cx = align === 'center' ? xOff + pw / 2 : align === 'right' ? xOff : pw;\n ctx.fillStyle = cfg.color ?? sprite.color ?? '#e6e8ef';\n ctx.fillRect(cx + fsPx * 0.06, rs.caretLine * lh, Math.max(1, fsPx * 0.08), fsPx);\n }\n }\n ctx.restore();\n return;\n }\n ctx.save();\n ctx.translate(p.x, p.y);\n if (rot) ctx.rotate(rot);\n if (p.flip && built.layer.flip) ctx.scale(-1, 1);\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n if (sprite.kind === 'emoji') {\n const idx = spriteIndexAt(e, t, sprite.glyphs.length);\n ctx.font = `${sz}px serif`;\n ctx.fillText(sprite.glyphs[idx] ?? sprite.glyphs[0]!, 0, 0);\n } else {\n ctx.textAlign = sprite.align ?? 'center';\n ctx.textBaseline = sprite.baseline ?? 'middle';\n // A full CSS shorthand (contains a px size) is used verbatim; a family/weight\n // only ('bold monospace') composes with the seeded per-entity size.\n ctx.font = sprite.font\n ? (FONT_PX_RE.test(sprite.font)\n ? scaleFontPx(sprite.font, this.fontScale())\n : composeFontShorthand(sz, sprite.font))\n : `${sz}px system-ui, sans-serif`;\n ctx.fillStyle = sprite.color ?? '#e6e8ef';\n const idx = spriteIndexAt(e, t, sprite.strings.length);\n const text = sprite.strings[idx] ?? sprite.strings[0]!;\n const mw = sprite.maxWidth ? sprite.maxWidth * (this.effSpec.units === 'px' ? 1 : Math.min(this.w, this.h)) : undefined;\n if (mw) ctx.fillText(text, 0, 0, mw);\n else ctx.fillText(text, 0, 0);\n }\n ctx.restore();\n }\n\n /** Advance any live steering glide; rebuild entities on structural change. */\n private stepTransition(t: number): void {\n const tr = this.transition;\n if (!tr) return;\n const k = tr.dur <= 0 ? 1 : (t - tr.startT) / tr.dur;\n this.effSpec = k >= 1 ? tr.to : lerpSpec(tr.from, tr.to, easeSmooth(k));\n if (k >= 1) this.transition = null;\n // Placement/motion fields are baked into entities at build time; rebuild\n // (deterministic — same seed → same stream) only when those change.\n const sig = structuralSignature(this.effSpec);\n if (sig !== this.lastStructural) this.rebuild();\n else this.layers.forEach((b, i) => { b.layer = this.effSpec.layers[i] ?? b.layer; });\n }\n\n /**\n * Live steering: glide from what's currently rendered to the track's target\n * state (deltas applied last-wins). Duration = the longest delta `dur`.\n */\n applyTrack(track: ControlTrack): void {\n const deltas = (track?.deltas ?? []) as unknown as SteerDelta[];\n if (this.authored) {\n const glide = deltas.length ? deltas.reduce((m, d) => Math.max(m, d.dur ?? DEFAULT_STEER_DUR), 0) : DEFAULT_STEER_DUR;\n if (!this.overrideAuthored(deltas, this.paused ? 0 : glide)) return;\n if (this.paused) this.renderFrame(this.sceneNow(), this.seed);\n return;\n }\n const target = applyDeltasToSpec(this.effSpec, deltas);\n if (!validateSpec(target).valid) return;\n const dur = deltas.length\n ? deltas.reduce((m, d) => Math.max(m, d.dur ?? DEFAULT_STEER_DUR), 0)\n : DEFAULT_STEER_DUR;\n this.transition = {\n from: JSON.parse(JSON.stringify(this.effSpec)) as SaverSpec,\n to: target,\n startT: this.lastT,\n dur,\n };\n if (this.paused) {\n // No frames will run the glide — jump straight to the target.\n this.transition = null;\n this.effSpec = target;\n if (structuralSignature(this.effSpec) !== this.lastStructural) this.rebuild();\n else this.layers.forEach((b, i) => { b.layer = this.effSpec.layers[i] ?? b.layer; });\n this.renderFrame(this.lastT, this.seed);\n }\n }\n\n /**\n * Apply steering deltas immediately: no glide, no frame painted. Each delta\n * is routed by `applyRetainedDeltas` (unresolvable or invalid ones are\n * skipped on this spec alone). `SequenceInstance` uses this to hand a\n * freshly created child the track the sequence has retained, so a steer\n * made while another segment was active lands on the segment that owns the\n * path. Not painting matters: a child is created inside the parent's\n * renderFrame, and a stray t=0 paint here would make the real frame that\n * follows look \"contiguous\" to the ghosting warm-up — but the constructor\n * already painted ONE stray t=0 frame of the pre-steer spec (SpecInstance's\n * own mount does an immediate render when paused, which every sequence\n * child is), so `lastRenderT` must be reset too: otherwise, with `ghosting`\n * on, the real frame that follows still finds itself \"contiguous\" with\n * that stray paint and composites over it at partial alpha, briefly\n * showing a ghost of the un-steered scene.\n */\n applyDeltasNow(deltas: Iterable<SteerDelta>): void {\n if (this.authored) {\n // Retained steers land under the timeline's steering rule — as one\n // batch when they validate together (one composed check), else per\n // delta, skipping any that don't (as `applyRetainedDeltas` does).\n const all = [...deltas];\n if (!this.overrideAuthored(all, 0)) for (const d of all) this.overrideAuthored([d], 0);\n this.transition = null;\n this.lastRenderT = Number.NEGATIVE_INFINITY;\n return;\n }\n const next = applyRetainedDeltas(this.effSpec, deltas);\n if (next === this.effSpec) return;\n this.transition = null;\n this.lastRenderT = Number.NEGATIVE_INFINITY;\n this.effSpec = next;\n if (structuralSignature(this.effSpec) !== this.lastStructural) this.rebuild();\n else this.layers.forEach((b, i) => { b.layer = this.effSpec.layers[i] ?? b.layer; });\n }\n\n private drawLinks(built: Built, t: number, lifeA: number, parentE: Entity | null): void {\n const { links } = built.layer;\n if (!links) return;\n const { ctx } = this;\n // Toroidal link drawing only makes sense for motions that actually wrap —\n // bounce/orbit/path entities never cross an edge, so a \"nearest image\" line\n // would cut across the screen.\n const motionWraps = ['drift', 'rise', 'wander'].includes(built.layer.motion.type);\n const wrap = built.layer.wrap !== false && motionWraps;\n const positions = built.entities.map((e) => this.entityPos(e, t, parentE));\n const maxDistPx = links.maxDist * (this.effSpec.units === 'px' ? 1 : Math.min(this.w, this.h));\n const edges = linkEdges(links, positions, maxDistPx, wrap, this.w, this.h);\n const unitScale = this.effSpec.units === 'px' ? 1 : Math.min(this.w, this.h);\n const defaultWidth = unitScale === 1 ? 1 : 1 / LIMITS.referenceViewport;\n const lw = (links.width ?? defaultWidth) * unitScale;\n ctx.lineWidth = lw;\n ctx.lineCap = 'butt'; // streak sprites set 'round'; reset so link ends stay crisp\n\n for (const { i, j, dist } of edges) {\n const pi = positions[i]!;\n const pj = positions[j]!;\n const ei = built.entities[i]!;\n let resolvedColor = links.color;\n if (!resolvedColor) {\n const sprite = built.layer.sprite;\n if (isShapedSprite(sprite)) {\n resolvedColor = sprite.colors?.[ei.colorIndex] ?? sprite.color;\n } else resolvedColor = '#e6e8ef';\n }\n let a = links.alpha ?? alphaAt(ei, t);\n if (links.falloff) a *= Math.max(0, 1 - dist / maxDistPx);\n ctx.globalAlpha = a * lifeA;\n ctx.strokeStyle = resolvedColor;\n // Draw toward nearest image of pj (avoids full-canvas streaks at wrap seams)\n let dx = pj.x - pi.x;\n let dy = pj.y - pi.y;\n if (wrap) {\n if (Math.abs(dx) > this.w / 2) dx = dx > 0 ? dx - this.w : dx + this.w;\n if (Math.abs(dy) > this.h / 2) dy = dy > 0 ? dy - this.h : dy + this.h;\n }\n ctx.beginPath();\n ctx.moveTo(pi.x, pi.y);\n ctx.lineTo(pi.x + dx, pi.y + dy);\n ctx.stroke();\n }\n }\n\n /** Paint one composite pass at time t. `bgAlpha` < 1 leaves the previous frame\n * showing through — the ghosting smear. */\n private paintFrame(t: number, bgAlpha: number): void {\n const { ctx } = this;\n if (this.authored) this.resolveAuthored(t);\n if (!this.transparent) {\n ctx.globalAlpha = bgAlpha;\n ctx.globalCompositeOperation = 'source-over';\n this.drawBackground(t);\n }\n ctx.globalAlpha = 1;\n for (let li = 0; li < this.layers.length; li++) {\n const built = this.layers[li]!;\n const opacity = built.layer.opacity;\n // A grouped layer paints through its group too (`groups`): opacity\n // multiplies, the group's transform wraps the layer's own. Ungrouped\n // layers take exactly the path they always have.\n const group = built.layer.group === undefined ? undefined : this.effSpec.groups?.[built.layer.group];\n let lifeA = opacity === undefined ? lifeAlphaAt(built.layer.life, t) : lifeAlphaAt(built.layer.life, t) * clamp01(opacity);\n if (group?.opacity !== undefined) lifeA *= clamp01(group.opacity);\n if (lifeA <= 0) continue;\n const parentE = this.parentEntityFor(built);\n const tf = built.layer.transform;\n const gtf = group?.transform;\n if (tf || gtf) {\n ctx.save();\n if (gtf) this.applyLayerTransform(gtf, null);\n if (tf) this.applyLayerTransform(tf, built.layer);\n }\n ctx.globalCompositeOperation = built.layer.blend ?? 'source-over';\n this.drawLinks(built, t, lifeA, parentE);\n const override = this.paintOverrides?.get(li) ?? null;\n for (const e of built.entities) {\n this.drawTrail(built, e, t, lifeA, parentE);\n if (override === null) {\n this.drawEntity(built, e, t, lifeA, parentE);\n continue;\n }\n // A text cross-fade: the previous words fading out under the new\n // ones fading in. Either pass at alpha 0 is skipped, so k = 0 and\n // k = 1 each cost exactly one draw, like a plain frame.\n const [aOut, aIn] = override.mode === 'dip'\n ? [Math.max(0, 1 - 2 * override.k), Math.max(0, 2 * override.k - 1)]\n : [1 - override.k, override.k];\n if (aOut > 0) this.drawEntity(built, e, t, lifeA, parentE, { sprite: override.outgoing, alpha: aOut });\n if (aIn > 0) this.drawEntity(built, e, t, lifeA, parentE, { alpha: aIn });\n }\n if (tf || gtf) ctx.restore();\n }\n ctx.globalAlpha = 1;\n ctx.globalCompositeOperation = 'source-over';\n }\n\n /**\n * A `transform`, in min(w,h) units (px under `units: 'px'`), about the\n * viewport centre — or, with `origin: 'anchor'`, about `layer`'s own anchor\n * (a group's transform passes no layer: always the viewport centre).\n */\n private applyLayerTransform(tf: LayerTransform, layer: LayerSpec | null): void {\n const { ctx, w, h } = this;\n const unit = this.effSpec.units === 'px' ? 1 : Math.min(w, h);\n const { x: cx, y: cy } = transformOrigin(tf, layer, w, h, unit);\n ctx.translate(cx + (tf.x ?? 0) * unit, cy + (tf.y ?? 0) * unit);\n if (tf.rotate) ctx.rotate((tf.rotate * Math.PI) / 180);\n const s = tf.scale ?? 1;\n ctx.scale(s * (tf.scaleX ?? 1), s);\n ctx.translate(-cx, -cy);\n }\n\n /** Scene time for a timeline decision: the last painted frame's, else the loop clock's. */\n private sceneNow(): number {\n return this.lastRenderT !== Number.NEGATIVE_INFINITY ? this.lastRenderT : this.lastT;\n }\n\n /** Resolve the authored timeline at `t`, layer the live overrides on top, and adopt the result. */\n private resolveAuthored(t: number): void {\n const expired: string[] = [];\n const spec = applyOverridesAt(resolveTimelineAt(this.authored!, t), this.overrides, t, expired);\n for (const p of expired) this.overrides.delete(p);\n this.effSpec = spec;\n const sig = structuralSignature(spec);\n if (sig !== this.lastStructural) this.rebuild();\n else this.layers.forEach((b, i) => { b.layer = spec.layers[i] ?? b.layer; });\n }\n\n /** Register live steers on a timeline scene under the steering rule (see `overrides`). */\n private overrideAuthored(deltas: readonly SteerDelta[], glide: number): boolean {\n const now = this.sceneNow();\n const shown = this.effSpec;\n // One steer per field: a re-sent track can carry several deltas that\n // address the same field (an appended track, key- and index-form paths),\n // and only the last is the steer — otherwise each re-send would flip the\n // dedup id below and re-arm a hold the timeline already took back.\n const latest = new Map<string, SteerDelta>();\n for (const d of deltas) {\n const path = canonicalSpecPath(shown, d.path);\n if (!path) continue;\n latest.delete(path);\n latest.set(path, d);\n }\n const next = new Map(this.overrides);\n const armed: Array<[string, string]> = [];\n for (const [path, d] of latest) {\n const id = steerId(d);\n if (this.seenSteers.get(path) === id) continue;\n armed.push([path, id]);\n next.set(path, armOverride(this.authored!, path, glide > 0 ? readSpecPath(shown, path) : d.value, d.value, now, glide));\n }\n if (armed.length === 0) return true;\n // Validate the scene as it will actually be — every live override, now\n // and at each key still ahead — not the new deltas alone.\n if (!overridesStayValid(this.authored!, next, now)) return false;\n for (const [p, id] of armed) this.seenSteers.set(p, id);\n this.overrides = next;\n return true;\n }\n\n /** A copy of the live overrides — a sequence carries them into a morph's outgoing endpoint. */\n timelineOverrides(): Map<string, TimelineOverride> | null {\n return this.authored ? new Map(this.overrides) : null;\n }\n\n /** A copy of which server steers this child already applied, per field (see `seenSteers`). */\n timelineSeen(): Map<string, string> {\n return new Map(this.seenSteers);\n }\n\n /** The spec painted by the last frame (timeline and overrides resolved). */\n presentedSpec(): SaverSpec {\n return this.effSpec;\n }\n\n /**\n * Deterministic, frame-addressable render (shared by the rAF loop).\n *\n * With `ghosting` set, contiguous frames composite over the previous frame with a\n * refresh-rate-normalized fade. A non-contiguous seek (pause render, e2e frame\n * addressing) replays a bounded fixed-step warm-up from a full clear, so the\n * accumulated smear at time t is identical on every run — the determinism proof\n * survives statefulness because the \"state\" is reconstructed from pure history.\n */\n renderFrame(t: number, _seed: number): void {\n this.stepTransition(t);\n const g = this.transparent ? 0 : (this.effSpec.ghosting ?? 0);\n if (g > 0) {\n const dt = 1000 / 60;\n const contiguous = this.lastRenderT !== Number.NEGATIVE_INFINITY\n && t > this.lastRenderT\n && t - this.lastRenderT <= 250;\n if (contiguous) {\n this.paintFrame(t, 1 - Math.pow(g, (t - this.lastRenderT) / dt));\n } else {\n const k = Math.min(Math.ceil(Math.log(1 / 255) / Math.log(g)), LIMITS.maxGhostReplayFrames);\n const t0 = Math.max(0, t - k * dt);\n this.paintFrame(t0, 1);\n for (let ft = t0 + dt; ft < t - dt / 2; ft += dt) this.paintFrame(ft, 1 - g);\n if (t > t0) this.paintFrame(t, 1 - g);\n }\n } else {\n this.paintFrame(t, 1);\n }\n this.lastRenderT = t;\n // Presentation, last of all: the finished scene (ghosting included) is\n // copied to the visible canvas and the finish screened over the copy —\n // after persistence has done its work, and never into it.\n if (this.finishPass) presentWithFinish(this.finishPass, this.canvas, this.w, this.h, t, this.effSpec.finish, this.animateFinish);\n }\n\n setPaused(paused: boolean): void {\n this.paused = paused;\n if (paused) {\n this.stop();\n } else {\n this.start();\n }\n }\n\n resize(width: number, height: number, dpr?: number): void {\n this.w = width;\n this.h = height;\n if (dpr !== undefined) this.saverCtx.dpr = dpr;\n this.sizeCanvas();\n this.rebuild();\n if (this.paused) this.renderFrame(0, this.seed);\n }\n\n /**\n * Replace the rendered spec without triggering a transition glide.\n * Checks structural signature — use `hotSwapPaint` only when the caller\n * already knows the signature is unchanged.\n */\n hotSwapSpec(spec: SaverSpec): void {\n this.adoptAuthored(spec);\n if (this.authored) { this.resolveAuthored(this.sceneNow()); return; }\n this.effSpec = spec;\n const sig = structuralSignature(this.effSpec);\n if (sig !== this.lastStructural) this.rebuild();\n else this.layers.forEach((b, i) => { b.layer = this.effSpec.layers[i] ?? b.layer; });\n }\n\n /**\n * Track whether `spec` carries a timeline. Live overrides belong to the\n * scene they were made on: a different spec (a new publish, a sequence's\n * re-steered segment, a morph frame) drops them, as a plain hot-swap\n * replaces `effSpec` wholesale; the host re-sends the live track.\n */\n private adoptAuthored(spec: SaverSpec, keepSteers = false): void {\n const next = spec.timeline ? spec : null;\n if (next !== this.authored && !(keepSteers && next && this.authored)) {\n this.overrides.clear();\n this.seenSteers.clear();\n }\n this.authored = next;\n }\n\n /**\n * A sequence's hot swap of a timeline segment: the new scene replaces the\n * old, but the live steers (and which server steers were already applied)\n * carry over — a steer the timeline already took back stays taken back —\n * and only a steer this child has never seen is armed, now. Frame\n * continuity is kept, so ghosting trails do not restart.\n */\n hotSwapKeepingSteers(spec: SaverSpec, retained: Iterable<SteerDelta>): void {\n if (!spec.timeline) {\n this.hotSwapSpec(spec);\n return;\n }\n if (!this.authored) {\n // The swap adds a timeline: the old scene carried the retained steers\n // baked in, the new one takes them as live steers from here.\n this.hotSwapSpec(spec);\n this.applyDeltasNow(retained);\n return;\n }\n this.adoptAuthored(spec, true);\n for (const d of retained) this.overrideAuthored([d], 0);\n this.resolveAuthored(this.sceneNow());\n }\n\n /** Arm a steer made while a sequence was mid-morph, on the outgoing end's override set, at that end's scene time. */\n static armInto(authored: SaverSpec, overrides: Map<string, TimelineOverride>, seen: Map<string, string>, deltas: readonly SteerDelta[], now: number): void {\n const at = resolveTimelineAt(authored, now);\n // As `overrideAuthored`: the last delta per field is the steer, and a\n // re-sent one (the host re-broadcasts the whole track) is not re-armed.\n const latest = new Map<string, SteerDelta>();\n for (const d of deltas) {\n const path = canonicalSpecPath(at, d.path);\n if (!path) continue;\n latest.delete(path);\n latest.set(path, d);\n }\n for (const [path, d] of latest) {\n const id = steerId(d);\n if (seen.get(path) === id) continue;\n const trial = new Map(overrides).set(path, armOverride(authored, path, d.value, d.value, now, 0));\n if (overridesStayValid(authored, trial, now)) {\n overrides.set(path, trial.get(path)!);\n seen.set(path, id);\n }\n }\n }\n\n /** Paint-only hot-swap: skips structuralSignature (caller guarantees match). */\n hotSwapPaint(spec: SaverSpec): void {\n this.adoptAuthored(spec);\n if (this.authored) { this.resolveAuthored(this.sceneNow()); return; }\n this.effSpec = spec;\n this.layers.forEach((b, i) => { b.layer = this.effSpec.layers[i] ?? b.layer; });\n }\n\n /**\n * Internal (see `LayerPaintOverride`): draw the listed layers twice —\n * outgoing sprite at `1 − k`, own sprite at `k` — until cleared with\n * `null`. Keyed by layer index. A `SequenceInstance` sets it per morph\n * frame under `text: 'crossfade'`; nothing else does.\n */\n setLayerPaintOverrides(overrides: ReadonlyMap<number, LayerPaintOverride> | null): void {\n this.paintOverrides = overrides && overrides.size > 0 ? overrides : null;\n }\n\n dispose(): void {\n this.stop();\n this.field = null; // the raster canvas was never attached; dropping the reference frees it\n // With a finish, the visible canvas is the pass's and `this.canvas` is\n // the offscreen scene (never attached) — drop the pass and its tiles.\n const visible = this.finishPass?.canvas ?? this.canvas;\n this.finishPass = null;\n if (this.ownsCanvas && typeof HTMLCanvasElement !== 'undefined' && visible instanceof HTMLCanvasElement) visible.remove();\n }\n}\n\n/**\n * Compile a declarative spec into a runnable SaverPlugin. Throws if the spec is invalid\n * (so an agent-authored spec is validated before it can run). The result is seeded,\n * deterministic, `renderFrame(t,seed)`-addressable, and flash-safe by construction.\n */\nexport function compileSaver(spec: unknown): SaverPlugin {\n const valid = assertValidSpec(spec);\n return {\n manifest: manifestFor(valid),\n mount: (ctx: SaverContext) => new SpecInstance(valid, ctx, { capabilityTier: (ctx as SpecMountContext).capabilityTier }),\n spec: valid,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Sequence — multi-segment timeline compiled as a single SaverPlugin\n// ---------------------------------------------------------------------------\n\n/**\n * Mount context for a compiled sequence. A plain `SaverContext` works — the\n * clock starts at 0, as every SaverPlugin's does. `sequenceBaseT` is read\n * only when the sequence declares `sync: 'epoch'`; hosts pass the shared\n * clock's elapsed ms (idlescreens.com: `Date.now() − scene.epoch`) so every\n * viewer of that sequence resolves the same segment.\n */\nexport interface SequenceMountContext extends SpecMountContext {\n /** ms already elapsed on the shared sequence clock. Ignored unless `sync: 'epoch'`. */\n sequenceBaseT?: number;\n /**\n * See `SpecMountContext.capabilityTier`. A `fade` transition keeps two\n * segments live for `dur`, which `basic` (canvas2d only) and `minimal`\n * cannot afford: on those tiers fade renders as `cut`. The tier is also\n * handed to every child and the bed (a `field` background's raster steps\n * down with it). Absent ⇒ fade enabled, full resolution.\n */\n capabilityTier?: CapabilityTier;\n}\n\n/** A segment child on a canvas of its own, composited onto the shared surface during a `fade`. */\ninterface OffscreenChild {\n index: number;\n child: SpecInstance;\n canvas: HTMLCanvasElement | OffscreenCanvas;\n}\n\n/** `bed.<path>` routes a steer to the sequence's bed when one exists. */\nconst BED_PREFIX = 'bed.';\n\n/**\n * What `compileSequence().mount()` returns: a `SaverInstance` that can also\n * take a republished sequence in place. Hosts feature-detect it with\n * `hasHotSwapSequence` (an older engine's instance simply lacks the method)\n * and fall through to a remount when it returns `false`.\n */\nexport interface SequenceSaverInstance extends SaverInstance {\n renderFrame(t: number, seed: number): void;\n applyTrack(track: ControlTrack): void;\n /**\n * Swap `next` in for the running sequence without remounting, when the\n * two are `sequenceSwapCompatible`: every live segment child (and the bed)\n * hot-swaps to its new scene, the clock, the active segment, every\n * released hold and the retained track stay exactly where they were, and\n * the next frame resolves to the same `(segment, localT)` as if nothing\n * had happened — a mid-show caption fix that does not send the room back\n * to segment 0. Returns `false` and changes nothing when the sequences are\n * not compatible (a structural or timing edit); the host remounts then.\n */\n hotSwapSequence(next: IdleSequence): boolean;\n}\n\n/** `compileSequence`'s plugin: `mount` is typed to the sequence instance and `spec` to the validated sequence. */\nexport interface SequenceSaverPlugin extends SaverPlugin {\n mount(ctx: SequenceMountContext): SequenceSaverInstance;\n spec: IdleSequence;\n}\n\n/** Feature-detect `hotSwapSequence` on any mounted instance (false for a plain scene, or a sequence from an older engine). */\nexport function hasHotSwapSequence(inst: SaverInstance): inst is SequenceSaverInstance {\n return typeof (inst as { hotSwapSequence?: unknown }).hotSwapSequence === 'function';\n}\n\nclass SequenceInstance implements SequenceSaverInstance {\n /** Replaced wholesale by `hotSwapSequence`; every per-segment lookup (`segmentStart`, `canMorph`, `childScene`) reads it live, so there are no derived tables to refresh. */\n private seq: IdleSequence;\n private readonly childCtx: SaverContext;\n private readonly canvas: HTMLCanvasElement | null;\n private readonly children: (SpecInstance | null)[];\n private activeIndex = -1;\n private paused = false;\n /**\n * When a morph is active, the child at `morphFromIndex` renders with a\n * lerped spec. The child stays keyed to the *outgoing* segment's slot so\n * its seed (and entity placement) is continuous.\n */\n private morphFromIndex = -1;\n private readonly seed: number;\n private frameId: number | null = null;\n private startT = 0;\n private baseT = 0;\n private lastT = 0;\n /** The T most recently passed to renderFrame — the clock a steer displaces. */\n private renderedT = 0;\n /**\n * The clicker's two pieces of state. `clockOffset` is added to every T so\n * a `sequence.segment` steer lands the timeline at the target segment's\n * start and STAYS there as the wall clock keeps ticking — the steer moves\n * the clock instead of fighting it. `releasedBelow` records that the steer\n * counts as the presenter clicking past every `advance: 'input'` hold\n * before the target (see `resolveSegment`).\n */\n private clockOffset = 0;\n private releasedBelow = 0;\n /**\n * Set by a `sequence.segment` steer that targets segment 0 under `loop:\n * true`: the steer resets the clock to segment 0's own start (localT 0),\n * so `renderFrame`'s wrap check (which compares the raw, ever-increasing\n * clock against `timedTotal()`) can no longer recognize the jump as a\n * wrap. This flag lets the clicker's jump to 0 still count as one, so the\n * last segment's fade plays instead of a hard cut. Cleared once the wrap\n * window (if any) has passed.\n */\n private pendingWrapFade = false;\n /** The morph in progress: its ends, and the override sets each end resolves with (see `morphEndpoint`). */\n private morphEnds: { from: number; to: number; outT: number; out: Map<string, TimelineOverride> | null; seenOut: Map<string, string>; in: Map<string, TimelineOverride> | null } | null = null;\n /**\n * Every non-`sequence.segment` delta this instance has been handed, last\n * wins per path, merged across `applyTrack` calls. Children are created\n * lazily and disposed on every segment switch, so a steer forwarded only\n * to the active child would evaporate at the next boundary — and a steer\n * to a path only a *later* segment owns (`bars.sprite.values` while the title\n * slide is up) would land nowhere. Re-applied to every child on creation\n * and folded into the morph endpoints; each child keeps the deltas that\n * resolve on it (see `applyRetainedDeltas`).\n */\n private readonly retainedDeltas = new Map<string, SteerDelta>();\n /**\n * Every `bed.<path>` delta (prefix stripped, last wins per path). The bed\n * is never re-created, so these are applied to it once on arrival — the\n * map exists only so `hotSwapSequence` can put a steered bed colour back\n * after the bed takes its republished scene. Absent a swap it is never read.\n */\n private readonly retainedBedDeltas = new Map<string, SteerDelta>();\n /** The outgoing segment while a `fade` runs; null otherwise. */\n private fading: OffscreenChild | null = null;\n /**\n * The incoming segment while a `fade` runs over a `bed`. Children over a\n * bed are transparent, so a cross-fade needs both of them on canvases of\n * their own — the incoming composited at k, the outgoing at 1 − k. Without\n * a bed the incoming paints its own opaque ground on the shared surface and\n * this stays null.\n */\n private fadingIn: OffscreenChild | null = null;\n /** False on the `basic`/`minimal` capability tiers — fade renders as cut. */\n private readonly fadeEnabled: boolean;\n /** The mount's tier, handed to every child and the bed. */\n private readonly capabilityTier: CapabilityTier | undefined;\n /**\n * The sequence's presentation pass when it — or any segment — declares a\n * `finish`: children and the bed draw into an offscreen scene canvas\n * (`childCtx.surface`), and every frame ends by copying it to the visible\n * surface with the finish screened over the copy — once per composed\n * frame, bed + segment + fade together. Null when no finish is declared\n * anywhere: children draw straight onto the visible surface, as before.\n */\n private readonly finishPass: FinishPass | null = null;\n /** False on the `basic`/`minimal` tiers — `finish.animate` renders as a static tile. */\n private readonly animateFinish: boolean;\n /**\n * The sequence's `bed`: one scene on the shared surface, drawn first every\n * frame at the sequence clock — WITHOUT `clockOffset`, so a\n * `sequence.segment` steer rewinds the segment and never the bed — and never\n * re-created. Segments render over it transparently. Null when absent.\n */\n private readonly bed: SpecInstance | null;\n\n constructor(seq: IdleSequence, ctx: SequenceMountContext) {\n this.seq = seq;\n const { sequenceBaseT, capabilityTier, ...plainCtx } = ctx;\n this.capabilityTier = capabilityTier;\n this.fadeEnabled = capabilityTier !== 'basic' && capabilityTier !== 'minimal';\n // `sync: 'epoch'`: seed the clock from the host's shared time, the same\n // way `baseT` carries SpecInstance's clock across pause/resume — the first\n // frame renders at `baseT`, not 0. Absent/`mount` ignores the hint and T\n // starts at 0 exactly as before the field existed. Holds are untouched:\n // `releasedBelow` stays 0, so a late joiner whose clock is past an\n // unreleased `advance: 'input'` hold lands ON the held segment.\n if (seq.sync === 'epoch' && typeof sequenceBaseT === 'number' && Number.isFinite(sequenceBaseT)) {\n this.baseT = Math.max(0, sequenceBaseT);\n this.lastT = this.baseT;\n this.renderedT = this.baseT;\n }\n\n let surface = ctx.surface ?? null;\n let canvas: HTMLCanvasElement | null = null;\n if (!surface && typeof document !== 'undefined') {\n canvas = document.createElement('canvas');\n canvas.style.cssText = 'display:block;width:100%;height:100%';\n canvas.setAttribute('aria-hidden', 'true');\n ctx.host.appendChild(canvas);\n surface = canvas;\n }\n this.canvas = canvas;\n\n // Prefer the sequence's own seed (same precedence SpecInstance uses for\n // scene.seed ?? ctx.seed). Children still resolve per-segment via childSeed.\n this.seed = ((seq.seed ?? ctx.seed ?? 0) >>> 0) || 1;\n this.animateFinish = capabilityTier !== 'basic' && capabilityTier !== 'minimal';\n // A finish anywhere in the sequence moves the children onto an offscreen\n // scene canvas for the sequence's lifetime; which finish applies is\n // decided per frame (see `frameFinish`).\n if (sequenceWantsFinish(seq) && surface) {\n const pass = createFinishPass(surface, this.seed);\n if (pass) {\n this.finishPass = pass;\n surface = createSceneCanvas(ctx.width, ctx.height);\n }\n }\n // Children are always parent-driven: reducedMotion:true keeps SpecInstance\n // from starting its own rAF. SequenceInstance.loop is the only clock.\n // `hostPresents`: a child's own `finish` is this instance's to apply.\n this.childCtx = { ...plainCtx, surface: surface!, reducedMotion: true };\n this.sizeVisible();\n this.children = new Array(seq.segments.length).fill(null) as (SpecInstance | null)[];\n if (seq.bed) {\n this.bed = new SpecInstance(this.bedScene(seq.bed), this.childCtx, { capabilityTier, hostPresents: true });\n this.bed.setPaused(true);\n } else {\n this.bed = null;\n }\n this.paused = ctx.reducedMotion;\n if (this.paused) this.renderFrame(this.baseT, this.seed);\n else this.start();\n }\n\n private childSeed(index: number, fallback: number): number {\n return this.seq.segments[index]!.scene.seed ?? this.seq.seed ?? fallback;\n }\n\n /**\n * The bed's seed follows the segment rule (own seed, else the sequence seed)\n * but offset by `maxSegments`, past every segment's `seed + index`, so a bed\n * and segment 0 never share an entity stream and adding a segment does not\n * re-seat the bed.\n */\n private bedScene(bed: SaverSpec): SaverSpec {\n if (bed.seed != null) return bed;\n if (this.seq.seed != null) return { ...bed, seed: this.seq.seed + LIMITS.maxSegments };\n return bed;\n }\n\n private childScene(index: number): SaverSpec {\n const seg = this.seq.segments[index]!;\n if (seg.scene.seed != null) return seg.scene;\n if (this.seq.seed != null) return { ...seg.scene, seed: this.seq.seed + index };\n return seg.scene;\n }\n\n /** Whether the boundary from `from` to `from+1` should morph. */\n private canMorph(from: number): boolean {\n return canMorph(this.seq, from);\n }\n\n /** Walk back through consecutive morph boundaries to find the chain origin. */\n private morphChainRoot(index: number): number {\n return morphChainRoot(this.seq, index);\n }\n\n private morphDur(from: number): number {\n const tr = this.seq.segments[from]?.transition;\n return tr?.type === 'morph' ? tr.dur : 0;\n }\n\n /** Whether the morph out of `from` paints its text in two passes — `crossfade` or `dip` (default `step`: strings switch at k > 0). */\n private morphTextCrossfades(from: number): boolean {\n const tr = this.seq.segments[from]?.transition;\n return tr?.type === 'morph' && (tr.text === 'crossfade' || tr.text === 'dip');\n }\n\n /** The morph out of `from`'s two-pass text mode, for `crossfadeOverrides`. */\n private morphTextMode(from: number): 'crossfade' | 'dip' {\n const tr = this.seq.segments[from]?.transition;\n return tr?.type === 'morph' && tr.text === 'dip' ? 'dip' : 'crossfade';\n }\n\n /**\n * The paint overrides for one crossfade frame: every text layer whose\n * words differ between the outgoing and incoming specs, painting the\n * outgoing words (in the lerped frame's paint — colour and alpha glide as\n * usual) at `1 − k` under the incoming at `k`. Null when nothing differs,\n * so a crossfade between same-worded twins is a plain morph frame.\n */\n private crossfadeOverrides(specA: SaverSpec, specB: SaverSpec, lerped: SaverSpec, k: number, mode: 'crossfade' | 'dip' = 'crossfade'): Map<number, LayerPaintOverride> | null {\n let map: Map<number, LayerPaintOverride> | null = null;\n for (let i = 0; i < lerped.layers.length; i++) {\n if (!textStringsDiffer(specA, specB, i)) continue;\n const from = specA.layers[i]!.sprite;\n const now = lerped.layers[i]!.sprite;\n const outgoing: SpriteSpec = from.kind === 'text' && now.kind === 'text'\n ? { ...now, strings: from.strings }\n : from.kind === 'textBlock' && now.kind === 'textBlock'\n ? { ...now, text: from.text }\n : now;\n if (outgoing === now) continue;\n // `mode` is only written for `dip`, so a crossfade override is the\n // exact object it has always been.\n (map ??= new Map()).set(i, mode === 'dip' ? { outgoing, k, mode } : { outgoing, k });\n }\n return map;\n }\n\n /** Length of the fade out of segment `from`, or 0 (no fade, or a tier that plays it as cut). */\n private fadeDur(from: number): number {\n const tr = this.seq.segments[from]?.transition;\n return this.fadeEnabled && tr?.type === 'fade' ? tr.dur : 0;\n }\n\n /** Sum of every timed segment — the lap length under `loop: true`. */\n private timedTotal(): number {\n const last = this.seq.segments.length - 1;\n return segmentStart(this.seq, last) + (this.seq.segments[last]!.duration ?? 0);\n }\n\n private releaseFading(): void {\n if (this.fading) {\n this.fading.child.dispose();\n this.fading = null;\n }\n if (this.fadingIn) {\n this.fadingIn.child.dispose();\n this.fadingIn = null;\n }\n }\n\n /**\n * A segment child on a canvas of its own. Like a morph it mounts on its\n * chain root's scene and seed (so its entities are the ones the viewer was\n * watching) and hot-swaps to the segment's spec; the retained track is\n * applied last. Transparent over a bed, opaque otherwise.\n */\n private offscreenChild(index: number, root: number): OffscreenChild {\n const canvas: HTMLCanvasElement | OffscreenCanvas = typeof document !== 'undefined'\n ? document.createElement('canvas')\n : new OffscreenCanvas(Math.max(1, this.childCtx.width), Math.max(1, this.childCtx.height));\n const child = new SpecInstance(this.childScene(root), { ...this.childCtx, surface: canvas }, { transparent: this.bed !== null, capabilityTier: this.capabilityTier, hostPresents: true });\n child.setPaused(true);\n if (root !== index) child.hotSwapSpec(this.childScene(index));\n if (this.retainedDeltas.size > 0) child.applyDeltasNow(this.retainedDeltas.values());\n return { index, child, canvas };\n }\n\n /** Render an offscreen child; a transparent one never clears, so its owner does here. */\n private renderOffscreen(oc: OffscreenChild, t: number, seed: number): void {\n if (this.bed) {\n const c = oc.canvas.getContext('2d') as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;\n c?.clearRect(0, 0, this.childCtx.width, this.childCtx.height);\n }\n oc.child.renderFrame(t, seed);\n }\n\n /** Draw an offscreen canvas onto the shared surface at `alpha`. */\n private composite(canvas: HTMLCanvasElement | OffscreenCanvas, alpha: number): void {\n const main = this.childCtx.surface?.getContext('2d') as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null | undefined;\n if (!main) return;\n main.save();\n main.globalAlpha = alpha;\n main.globalCompositeOperation = 'source-over';\n main.drawImage(canvas, 0, 0, this.childCtx.width, this.childCtx.height);\n main.restore();\n }\n\n /**\n * Render the outgoing segment `from` of a live fade onto its own canvas. It\n * keeps animating at `duration(from) + localT` (it does not freeze — and if\n * it was an `advance: 'input'` hold it resumes from its duration, not from\n * wherever the hold had reached). Two live segments for `dur` only; the\n * outgoing one is disposed when the fade ends.\n */\n private renderOutgoing(from: number, localT: number, seed: number): OffscreenChild {\n if (this.fading && this.fading.index !== from) {\n this.fading.child.dispose();\n this.fading = null;\n }\n if (!this.fading) this.fading = this.offscreenChild(from, this.morphChainRoot(from));\n const outDur = this.seq.segments[from]!.duration ?? 0;\n this.renderOffscreen(this.fading, outDur + localT, this.childSeed(this.morphChainRoot(from), seed));\n return this.fading;\n }\n\n /**\n * One end of a morph at segment time `t`. A scene without a timeline is its\n * steered scene, as always. With a timeline, the retained track follows the\n * same rule a child applies (held until the path's next key, sticky\n * otherwise): the outgoing end uses its child's live overrides when the\n * morph began from one, and otherwise — like the incoming end, whose child\n * does not exist yet — arms the retained steers at segment time 0, as a\n * freshly mounted child would.\n */\n private morphEndpoint(index: number, t: number, side: 'out' | 'in'): SaverSpec {\n const scene = this.childScene(index);\n if (!scene.timeline) return this.steeredScene(scene);\n const ends = this.morphEnds;\n if (ends && side === 'out') ends.outT = t;\n let ov = side === 'out' ? ends?.out ?? null : ends?.in ?? null;\n if (!ov) {\n ov = this.armRetained(scene, side === 'out' ? ends?.seenOut : undefined);\n if (ends) { if (side === 'out') ends.out = ov; else ends.in = ov; }\n }\n return applyOverridesAt(resolveTimelineAt(scene, t), ov, t);\n }\n\n /** The retained steers that resolve (and validate) on a timeline scene, armed at segment time 0. */\n private armRetained(scene: SaverSpec, seen?: Map<string, string>): Map<string, TimelineOverride> {\n const out = new Map<string, TimelineOverride>();\n if (this.retainedDeltas.size === 0) return out;\n const at0 = resolveTimelineAt(scene, 0);\n for (const d of this.retainedDeltas.values()) {\n const path = canonicalSpecPath(at0, d.path);\n if (!path) continue;\n const trial = new Map(out).set(path, armOverride(scene, path, d.value, d.value, 0, 0));\n if (overridesStayValid(scene, trial, 0)) {\n out.set(path, trial.get(path)!);\n seen?.set(path, steerId(d));\n }\n }\n return out;\n }\n\n /** A segment's scene with the retained track applied — `scene` itself when nothing resolves on it. */\n private steeredScene(scene: SaverSpec): SaverSpec {\n return this.retainedDeltas.size === 0 ? scene : applyRetainedDeltas(scene, this.retainedDeltas.values());\n }\n\n /**\n * The child for segment `index`, created paused on the shared surface if\n * the slot is empty. `rootScene` (a morph chain's root) mounts the child\n * with the root's scene so its seed and entity placement are continuous\n * with the chain, then hot-swaps to the segment's own spec. Either way the\n * retained track is applied last, so a steer made while another segment\n * was up is already in effect on this child's first frame. `skipInitialPaint`\n * is for a caller (the morph branch) that is about to render a real frame,\n * paint overrides included, in this same call — see `SpecInstanceOptions`.\n */\n private ensureChild(index: number, rootScene?: SaverSpec, skipInitialPaint?: boolean): SpecInstance {\n if (index < 0 || index >= this.seq.segments.length) index = 0;\n let child = this.children[index];\n if (!child) {\n // Over a bed the child is transparent ink on the shared surface, and\n // every caller renders the real frame right after this — so its\n // constructor paint (t = 0) would only leave a stray frame of ink under\n // it. Transparent children ignore ghosting, so skipping it changes no\n // warm-up. Without a bed the opaque child repaints its ground over it.\n child = new SpecInstance(rootScene ?? this.childScene(index), this.childCtx, { transparent: this.bed !== null, skipInitialPaint: skipInitialPaint || this.bed !== null, capabilityTier: this.capabilityTier, hostPresents: true });\n this.children[index] = child;\n // Belt-and-suspenders: never let a child self-drive, even if childCtx\n // reducedMotion is ever relaxed.\n child.setPaused(true);\n if (rootScene) child.hotSwapSpec(this.childScene(index));\n if (this.retainedDeltas.size > 0) child.applyDeltasNow(this.retainedDeltas.values());\n }\n return child;\n }\n\n private releaseChild(index: number): void {\n const child = this.children[index];\n if (child) {\n child.dispose();\n this.children[index] = null;\n }\n }\n\n private start(): void {\n if (this.frameId !== null || typeof requestAnimationFrame === 'undefined') return;\n this.startT = 0;\n this.frameId = requestAnimationFrame((now) => this.loop(now));\n }\n\n private stop(): void {\n if (this.frameId !== null) {\n cancelAnimationFrame(this.frameId);\n this.frameId = null;\n }\n this.baseT = this.lastT;\n }\n\n private loop(now: number): void {\n this.frameId = requestAnimationFrame((n) => this.loop(n));\n if (this.startT === 0) this.startT = now;\n this.lastT = now - this.startT + this.baseT;\n this.renderFrame(this.lastT, this.seed);\n }\n\n /**\n * With a presentation pass, size the visible surface like a child sizes\n * the scene canvas (children never touch the visible surface then).\n */\n private sizeVisible(): void {\n const fp = this.finishPass;\n if (!fp) return;\n const dpr = Math.min(this.childCtx.dpr, 2);\n fp.canvas.width = Math.max(1, Math.round(this.childCtx.width * dpr));\n fp.canvas.height = Math.max(1, Math.round(this.childCtx.height * dpr));\n fp.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n }\n\n /**\n * The finish this frame applies: the sequence's own overrides; else the\n * active segment's (the incoming one during a fade) — read through\n * `steeredScene` so a retained steer to `finish.grain`/`finish.dither`\n * takes effect immediately instead of the authored value; a bed's is\n * ignored.\n */\n private frameFinish(): SaverSpec['finish'] {\n if (this.seq.finish !== undefined) return this.seq.finish;\n if (this.activeIndex < 0) return undefined;\n const scene = this.childScene(this.activeIndex);\n if (scene.timeline) {\n // A timeline may key `finish.*`: read what the rendering child painted\n // (its chain-root slot mid-morph), not the authored base.\n const live = (this.fadingIn?.index === this.activeIndex ? this.fadingIn.child : null)\n ?? this.children[this.activeIndex] ?? this.children[this.morphChainRoot(this.activeIndex)];\n if (live) return live.presentedSpec().finish;\n }\n return this.steeredScene(scene).finish;\n }\n\n /**\n * The seed `frameFinish()`'s grain resolves against — the sequence's own\n * for a sequence-level finish, else the active segment's actual render\n * seed (`segmentRenderSeed`: chain-root-aware and normalized exactly like\n * `SpecInstance`, so it agrees with what that segment's entities render\n * with, morph or not).\n */\n private frameFinishSeed(): number {\n if (this.seq.finish !== undefined) return this.seed;\n if (this.activeIndex < 0) return this.seed;\n return segmentRenderSeed(this.seq, this.activeIndex) ?? this.seed;\n }\n\n renderFrame(T: number, seed: number): void {\n this.renderScene(T, seed);\n // Once per composed frame, after bed, segment and any fade composite.\n if (this.finishPass) {\n presentWithFinish(this.finishPass, this.childCtx.surface!, this.childCtx.width, this.childCtx.height, T, this.frameFinish(), this.animateFinish, this.frameFinishSeed());\n }\n }\n\n private renderScene(T: number, seed: number): void {\n this.renderedT = T;\n const resolved = resolveSegment(this.seq, T + this.clockOffset, { releasedBelow: this.releasedBelow });\n const { index, localT } = resolved;\n\n // The bed is the ground: painted first, on the global clock. `T` here is\n // the sequence clock before `clockOffset`, so the clicker never rewinds it.\n this.bed?.renderFrame(T, this.seq.bed?.seed ?? this.seq.seed ?? seed);\n\n // A fade comes from the previous segment in the list — or, under\n // `loop: true`, from the last segment when the lap wraps to 0, so the\n // last segment's `fade` is the wrap's transition. Cut and morph paths\n // are untouched: fadeDur is 0 for them.\n const lastIdx = this.seq.segments.length - 1;\n const wrapped = this.seq.loop && index === 0 && lastIdx > 0\n && (T + this.clockOffset >= this.timedTotal() || this.pendingWrapFade);\n\n // Check if the *previous* segment has a morph into this one — or, with\n // `wrapMorph` on a loop that is one morph chain, whether the last\n // segment morphs into segment 0 at the wrap (`canWrapMorph`). Without\n // `wrapMorph` the wrap stays the hard cut it has always been.\n // Only on a natural lap wrap: a clicker jump to segment 0 (`pendingWrapFade`)\n // arrives from wherever the presenter was, not from the last segment, so\n // it cuts — morphing from the last segment would flash a frame of it.\n const naturalWrap = this.seq.loop && index === 0 && lastIdx > 0 && T + this.clockOffset >= this.timedTotal();\n const prevIdx = index > 0 ? index - 1 : -1;\n const morphFrom = prevIdx >= 0 ? prevIdx : naturalWrap && canWrapMorph(this.seq) ? lastIdx : -1;\n const morphActive = morphFrom >= 0\n && (morphFrom === prevIdx ? this.canMorph(prevIdx) : true)\n && localT < this.morphDur(morphFrom);\n const fadeFrom = prevIdx >= 0 ? prevIdx : wrapped ? lastIdx : -1;\n const fadeActive = fadeFrom >= 0 && localT < this.fadeDur(fadeFrom);\n if (!fadeActive && this.fading) this.releaseFading();\n // The flag only needs to survive the frames still inside the wrap fade\n // window; once that ends (or the clock moves off segment 0) it has done\n // its job.\n if (this.pendingWrapFade && (index !== 0 || !fadeActive)) this.pendingWrapFade = false;\n\n if (morphActive) {\n // Morph in progress: keep the child keyed to the chain root\n // (preserves its seed/entity placement through chained morphs).\n const chainRoot = this.morphChainRoot(index);\n if (this.morphFromIndex !== morphFrom || this.morphEnds?.to !== index) {\n // A new morph: carry the outgoing segment's live steers (held/expired\n // per the timeline rule, on its own clock) into the lerp, before its\n // child is released or hot-swapped to the lerped frame.\n const outChild = this.children[morphFrom];\n this.morphEnds = { from: morphFrom, to: index, outT: 0, out: outChild?.timelineOverrides() ?? null, seenOut: outChild?.timelineSeen() ?? new Map(), in: null };\n }\n this.morphFromIndex = morphFrom;\n this.activeIndex = index;\n\n // Release all children except the chain root's slot\n for (let i = 0; i < this.children.length; i++) {\n if (i !== chainRoot) this.releaseChild(i);\n }\n\n // A fresh mount here is about to be repainted for real a few lines\n // down (hotSwapPaint + overrides + renderFrame) within this same call.\n // Only `text: 'crossfade'` needs the constructor's own paint skipped —\n // its partial-alpha passes would otherwise composite over a stray\n // full-opacity frame underneath; `step` (the common case) is left to\n // paint at construction as it always has, so a fresh mount's ghosting\n // contiguity (`lastRenderT`) is unaffected.\n const child = this.ensureChild(chainRoot, undefined, this.morphTextCrossfades(morphFrom));\n const dur = this.morphDur(morphFrom);\n const k = easeSmooth(localT / dur);\n // The lerp endpoints carry the retained track, so without this a\n // steered colour would vanish for `dur` and snap back when the morph\n // finalises. `canMorph` only guarantees specA/specB share structure\n // BEFORE the retained set is applied — a structural delta (`layers.0.\n // count`, a motion change) could validate on one endpoint and not the\n // other, or change both identically but differ from what this child\n // was last built with. hotSwapSpec (not hotSwapPaint) re-checks the\n // signature every frame and rebuilds when it moved, so a structural\n // steer actually takes effect instead of leaving stale entities.\n //\n // A segment with a `timeline` is resolved on its own clock first — the\n // outgoing one at its end (its duration + localT, so a looping\n // timeline keeps cycling through the morph), the incoming at localT —\n // and the timeline-free results are lerped. Without timelines\n // resolveTimelineAt returns its argument, so this is the old frame.\n const outDur = this.seq.segments[morphFrom]!.duration ?? 0;\n const specA = this.morphEndpoint(morphFrom, outDur + localT, 'out');\n const specB = this.morphEndpoint(index, localT, 'in');\n const lerped = lerpSpec(specA, specB, k);\n child.hotSwapSpec(lerped);\n // Default (`step`): no overrides, the frame is what it always was —\n // strings already switched inside `lerped` at k > 0.\n child.setLayerPaintOverrides(this.morphTextCrossfades(morphFrom) ? this.crossfadeOverrides(specA, specB, lerped, k, this.morphTextMode(morphFrom)) : null);\n child.renderFrame(localT, this.childSeed(chainRoot, seed));\n } else {\n // No morph (or morph complete). If we were morphing, finalize.\n if (this.morphFromIndex >= 0) {\n // Morph just completed — release the chain-root child.\n const oldRoot = this.morphChainRoot(this.morphFromIndex);\n this.releaseChild(oldRoot);\n if (oldRoot !== this.morphFromIndex) this.releaseChild(this.morphFromIndex);\n this.morphFromIndex = -1;\n this.morphEnds = null;\n }\n\n if (index !== this.activeIndex) {\n for (let i = 0; i < this.children.length; i++) {\n if (i !== index) this.releaseChild(i);\n }\n this.activeIndex = index;\n }\n\n // Determine the effective seed: if this segment was reached via a\n // morph chain, use the chain-root's seed so entity placement is\n // continuous across all morphed segments and seeks match playthrough.\n const chainRoot = this.morphChainRoot(index);\n const useMorphSeed = chainRoot < index;\n const effSeed = useMorphSeed ? this.childSeed(chainRoot, seed) : this.childSeed(index, seed);\n\n if (fadeActive && this.bed) {\n // Over a bed both segments are transparent ink, so both go to canvases\n // of their own: incoming at k, outgoing over it at 1 − k. The incoming\n // moves to the shared surface (via ensureChild) once the fade ends.\n const k = easeSmooth(localT / this.fadeDur(fadeFrom));\n if (this.fadingIn && this.fadingIn.index !== index) {\n this.fadingIn.child.dispose();\n this.fadingIn = null;\n }\n if (!this.fadingIn) this.fadingIn = this.offscreenChild(index, useMorphSeed ? chainRoot : index);\n this.renderOffscreen(this.fadingIn, localT, effSeed);\n const out = this.renderOutgoing(fadeFrom, localT, seed);\n this.composite(this.fadingIn.canvas, k);\n this.composite(out.canvas, 1 - k);\n return;\n }\n\n // If using morph seed, mount the child with the chain root's scene+seed\n // but immediately hot-swap to the current segment's spec.\n const child = useMorphSeed ? this.ensureChild(index, this.childScene(chainRoot)) : this.ensureChild(index);\n child.renderFrame(localT, effSeed);\n if (fadeActive) {\n // The outgoing segment on its own canvas over the incoming frame at\n // 1 − easeSmooth(k): the incoming's opaque ground fades in beneath it.\n const out = this.renderOutgoing(fadeFrom, localT, seed);\n this.composite(out.canvas, 1 - easeSmooth(localT / this.fadeDur(fadeFrom)));\n }\n }\n }\n\n setPaused(paused: boolean): void {\n this.paused = paused;\n if (paused) this.stop();\n else this.start();\n // Do NOT forward pause=false to children — that would start SpecInstance\n // rAF loops alongside SequenceInstance.loop (double clock, wrong localT).\n // Children stay paused; the parent loop is the sole driver.\n for (const child of this.children) {\n child?.setPaused(true);\n }\n this.fading?.child.setPaused(true);\n this.fadingIn?.child.setPaused(true);\n this.bed?.setPaused(true);\n }\n\n resize(width: number, height: number, dpr?: number): void {\n // Children are created lazily (first rAF tick, segment switches, morph\n // finalization), so the new size must outlive the children that exist right\n // now. Without this, a resize while a slot is empty is forgotten and the\n // next child mounts at the stale mount-time size — a viewer that mounted\n // in a hidden/unpainted tab (width 0) stays a 1×1 canvas forever, and a\n // segment cut after any resize snaps back to the old dimensions.\n this.childCtx.width = width;\n this.childCtx.height = height;\n if (dpr !== undefined) this.childCtx.dpr = dpr;\n this.sizeVisible();\n for (const child of this.children) {\n child?.resize(width, height, dpr);\n }\n this.fading?.child.resize(width, height, dpr);\n this.fadingIn?.child.resize(width, height, dpr);\n this.bed?.resize(width, height, dpr);\n }\n\n applyTrack(track: ControlTrack): void {\n const all = (track?.deltas ?? []) as unknown as SteerDelta[];\n // `bed.<path>` goes to the bed with the prefix stripped — only when a bed\n // exists; otherwise the path reaches the segments as today (a layer keyed\n // `bed` keeps working).\n const isBedPath = (d: SteerDelta): boolean => this.bed !== null && typeof d.path === 'string' && d.path.startsWith(BED_PREFIX);\n const bedDeltas = all.filter(isBedPath).map((d) => ({ ...d, path: d.path.slice(BED_PREFIX.length) }));\n if (bedDeltas.length > 0) {\n for (const d of bedDeltas) this.retainedBedDeltas.set(d.path, d);\n this.bed!.applyTrack({ ...track, deltas: bedDeltas as unknown as ParamDelta[] });\n }\n const deltas = all.filter((d) => !isBedPath(d));\n // Retain first: a `sequence.segment` steer in the same track creates the\n // target child inside renderFrame below, and it must see these deltas.\n for (const d of deltas) {\n if (d.path !== 'sequence.segment' && typeof d.path === 'string') this.retainedDeltas.set(d.path, d);\n }\n const segDelta = deltas.find((d) => d.path === 'sequence.segment');\n let switchedSegment = false;\n if (segDelta !== undefined && typeof segDelta.value === 'number') {\n const idx = Math.max(0, Math.min(this.seq.segments.length - 1, Math.round(segDelta.value as number)));\n // A steer to segment 0 under loop is the clicker doing the same jump\n // the wall clock does on a natural lap wrap — it should trigger the\n // last segment's fade the same way (see `pendingWrapFade`).\n this.pendingWrapFade = this.seq.loop && idx === 0 && this.seq.segments.length > 1;\n // Displace the clock so T + offset == the target segment's start: the\n // segment begins at localT 0 (its `life.enter` build replays) and the\n // next animation frame resolves to the same segment instead of snapping\n // back to whatever the wall clock said. The steer also releases every\n // `advance: 'input'` hold before the target; holds at and after it stay\n // armed, so steering backwards re-arms the ones in between.\n this.clockOffset = segmentStart(this.seq, idx) - this.renderedT;\n this.releasedBelow = idx;\n this.renderFrame(this.renderedT, this.seed);\n switchedSegment = true;\n }\n\n const childDeltas = deltas.filter((d) => d.path !== 'sequence.segment');\n if (childDeltas.length > 0) {\n if (this.morphFromIndex >= 0) {\n // Mid-morph, the rendered child lives at the chain-root slot, not\n // `children[activeIndex]` — forwarding a child.applyTrack() there\n // would silently no-op AND get overwritten by the morph's own\n // hotSwapSpec on the very next frame regardless, so a transition\n // glide on this path can't coexist with the morph's own cross-fade.\n // The delta is already retained above, so a re-render is all that's\n // needed to reach it via steeredScene: it takes effect this frame,\n // immediately rather than gliding over its own `dur`. Skip only when\n // the segDelta branch above already re-rendered with these deltas\n // retained.\n // Timeline ends resolve through `morphEnds`: arm the new steer on the\n // outgoing set at its current time, and re-arm the incoming side.\n const ends = this.morphEnds;\n if (ends) {\n const outScene = this.childScene(ends.from);\n if (ends.out && outScene.timeline) SpecInstance.armInto(outScene, ends.out, ends.seenOut, childDeltas, ends.outT);\n ends.in = null;\n }\n if (!switchedSegment) this.renderFrame(this.renderedT, this.seed);\n } else if (this.activeIndex >= 0) {\n // Not mid-morph: the active child still gets the track directly, as\n // before retention — a steer to a path it owns glides on this call\n // rather than snapping at the next boundary.\n const child = this.children[this.activeIndex];\n child?.applyTrack({ ...track, deltas: childDeltas as unknown as ParamDelta[] });\n }\n // The outgoing segment during a fade — and, over a bed, the incoming\n // one too, since both are standalone offscreen SpecInstances, not\n // `this.children` — would otherwise freeze at whatever they last\n // rendered instead of picking up a mid-fade steer like the active\n // child does. Independent of the morph/active branching above: fade\n // and morph are mutually exclusive per-frame states.\n this.fading?.child.applyTrack({ ...track, deltas: childDeltas as unknown as ParamDelta[] });\n this.fadingIn?.child.applyTrack({ ...track, deltas: childDeltas as unknown as ParamDelta[] });\n }\n }\n\n /**\n * See `SequenceSaverInstance.hotSwapSequence`. Nothing that positions the\n * show is touched: `clockOffset`, `releasedBelow`, `activeIndex`,\n * `morphFromIndex`, `pendingWrapFade`, `renderedT` and the retained deltas\n * all keep their values, and the timing terms `sequenceSwapCompatible`\n * pins (durations, advance, transitions, loop) are the same on both sides,\n * so `resolveSegment` at the next frame lands where it would have anyway.\n * Each live child takes its new scene with the retained track re-applied\n * (`steeredScene` — the same routing a fresh child gets), so steered paint\n * survives the swap; `hotSwapSpec` keeps the entities (the signatures\n * match) and does not reset ghosting contiguity, so a drifting entity is\n * where it was 1 ms ago. Children are always paused, so none of them has a\n * glide in flight for the swap to interrupt (`SpecInstance.applyTrack`\n * snaps when paused). A morph in progress is untouched here: its chain-root\n * child is re-lerped from the new endpoints on the very next frame.\n */\n hotSwapSequence(next: IdleSequence): boolean {\n if (!sequenceSwapCompatible(this.seq, next)) return false;\n this.seq = next;\n // Routed like a child's retained set (`applyRetainedDeltas`, not\n // `applyDeltasNow`): the latter resets ghosting contiguity, and the bed's\n // trails must not restart on a swap.\n if (this.bed && next.bed) this.bed.hotSwapSpec(applyRetainedDeltas(this.bedScene(next.bed), this.retainedBedDeltas.values()));\n const swap = (child: SpecInstance | null | undefined, index: number): void => {\n if (!child) return;\n const scene = this.childScene(index);\n if (!scene.timeline) { child.hotSwapSpec(this.steeredScene(scene)); return; }\n // A timeline child keeps its live steers across the swap (the steering\n // rule), rather than having them baked into its base (which would make\n // a steer on an animated path sticky) or re-armed from scratch (which\n // would bring back one the timeline already took back).\n child.hotSwapKeepingSteers(scene, this.retainedDeltas.values());\n };\n for (let i = 0; i < this.children.length; i++) swap(this.children[i], i);\n if (this.fading) swap(this.fading.child, this.fading.index);\n if (this.fadingIn) swap(this.fadingIn.child, this.fadingIn.index);\n this.morphEnds = null;\n // A paused instance (reducedMotion, or a sleeping host) has no next frame\n // to paint the new words with; a running one repaints on its own tick.\n if (this.paused) this.renderFrame(this.renderedT, this.seed);\n return true;\n }\n\n dispose(): void {\n this.stop();\n this.releaseFading();\n for (let i = 0; i < this.children.length; i++) {\n this.releaseChild(i);\n }\n this.bed?.dispose();\n if (this.finishPass) {\n // The scene canvas was never attached; the pass's visible canvas is\n // `this.canvas` (removed below) or the host's surface.\n this.finishPass.grain = null;\n this.finishPass.dither = null;\n }\n if (this.canvas) this.canvas.remove();\n }\n}\n\nfunction sequenceManifest(seq: IdleSequence): SaverManifest {\n const maxSegment = seq.segments.reduce((max, s) => {\n const t = s.scene.layers.reduce((n, l) => n + l.count, 0);\n return Math.max(max, t);\n }, 0);\n // A bed is live alongside whichever segment is up, so it costs on top of the largest.\n const bedTotal = seq.bed ? seq.bed.layers.reduce((n, l) => n + l.count, 0) : 0;\n const maxTotal = bedTotal + maxSegment;\n const costTier = maxTotal < 30 ? 'idle' : maxTotal < 150 ? 'low' : maxTotal < 400 ? 'medium' : 'high';\n return {\n id: seq.id,\n label: seq.label,\n timeModel: 'closed-form',\n passthrough: false,\n minBackend: 'canvas2d',\n costTier,\n motionIntensity: 'moderate',\n reducedMotionFallback: 'static',\n a11y: { flashSafe: true },\n workerReady: false,\n };\n}\n\nexport function compileSequence(spec: unknown): SequenceSaverPlugin {\n const valid = assertValidSequence(spec);\n return {\n manifest: sequenceManifest(valid),\n mount: (ctx: SequenceMountContext) => new SequenceInstance(valid, ctx),\n spec: valid,\n };\n}\n","/**\n * Analytic models of the paint-level layer fields — `transform` (with its\n * `origin`), `opacity`, and the `groups` a layer paints through — shared by\n * the renderer's maths, perception and the advisories. Internal, not\n * exported from the package. They mirror SpecInstance's draw-time canvas\n * transform: a member of a group is drawn through G·L, where L is the layer's\n * own transform (about its origin) and G the group's (about the viewport\n * centre), so a point p lands at G(L(p)).\n */\nimport type { LayerGroup, LayerSpec, LayerTransform, SaverSpec } from './types';\n\nexport interface Pt { x: number; y: number }\n\n/**\n * A layer's own anchor in px: its `position` point (plus `dx`/`dy`; for a\n * `list`/`table` layout the block's anchor), else the centre of its `region`,\n * else the viewport centre.\n */\nexport function layerAnchor(layer: LayerSpec, w: number, h: number, unit: number): Pt {\n const p = layer.position;\n if (p) return { x: p.x * w + (p.dx ?? 0) * unit, y: p.y * h + (p.dy ?? 0) * unit };\n const rx = layer.region?.x ?? [0, 1];\n const ry = layer.region?.y ?? [0, 1];\n return { x: ((rx[0] + rx[1]) / 2) * w, y: ((ry[0] + ry[1]) / 2) * h };\n}\n\n/** What a layer transform turns about, in px: the viewport centre, or (`origin: 'anchor'`) the layer's anchor. */\nexport function transformOrigin(tf: LayerTransform, layer: LayerSpec | null, w: number, h: number, unit: number): Pt {\n return tf.origin === 'anchor' && layer ? layerAnchor(layer, w, h, unit) : { x: w / 2, y: h / 2 };\n}\n\n/**\n * Where a transform puts a point: about `origin` (default the viewport\n * centre), offsets in min(w,h) units (px under `units: 'px'`). Sprites are not\n * rotated here; the maps model ink, not glyph angle.\n */\nexport function transformPoint(tf: LayerTransform, p: Pt, w: number, h: number, unit: number, origin: Pt = { x: w / 2, y: h / 2 }): Pt {\n const s = tf.scale ?? 1;\n const sx = s * (tf.scaleX ?? 1);\n let x = (p.x - origin.x) * sx;\n let y = (p.y - origin.y) * s;\n if (tf.rotate) {\n const r = (tf.rotate * Math.PI) / 180;\n const c = Math.cos(r);\n const n = Math.sin(r);\n [x, y] = [x * c - y * n, x * n + y * c];\n }\n return { x: x + origin.x + (tf.x ?? 0) * unit, y: y + origin.y + (tf.y ?? 0) * unit };\n}\n\n/** A transform's linear size factor (the geometric mean of its two axes' scales). */\nexport function transformSize(tf: LayerTransform | undefined): number {\n if (!tf) return 1;\n const s = tf.scale ?? 1;\n return s * Math.sqrt(Math.abs(tf.scaleX ?? 1));\n}\n\n/** The group a layer paints through, if it names one that exists. */\nexport function groupOf(spec: SaverSpec, layer: LayerSpec): LayerGroup | undefined {\n return layer.group === undefined ? undefined : spec.groups?.[layer.group];\n}\n\nconst clamp01 = (v: number): number => (v <= 0 ? 0 : v >= 1 ? 1 : v);\n\n/** A layer's paint opacity as a multiplier: its own `opacity` × its group's (1 when unset). */\nexport function paintOpacity(spec: SaverSpec, layer: LayerSpec): number {\n const own = layer.opacity === undefined ? 1 : clamp01(layer.opacity);\n const g = groupOf(spec, layer);\n return g?.opacity === undefined ? own : own * clamp01(g.opacity);\n}\n\n/** Back-compat alias: a layer's own paint opacity (no group). */\nexport const layerOpacity = (layer: LayerSpec): number => (layer.opacity === undefined ? 1 : clamp01(layer.opacity));\n\n/** The combined linear size factor of a layer's own and its group's transforms. */\nexport function paintSize(spec: SaverSpec, layer: LayerSpec): number {\n return transformSize(layer.transform) * transformSize(groupOf(spec, layer)?.transform);\n}\n\n/**\n * The point map a layer is painted through — its own transform about its\n * origin, then its group's about the viewport centre — or null when neither\n * is set (the caller keeps the untouched path).\n */\nexport function paintMap(spec: SaverSpec, layer: LayerSpec, w: number, h: number, unit: number): ((p: Pt) => Pt) | null {\n const tf = layer.transform;\n const gtf = groupOf(spec, layer)?.transform;\n if (!tf && !gtf) return null;\n const o = tf ? transformOrigin(tf, layer, w, h, unit) : null;\n return (p) => {\n const q = tf ? transformPoint(tf, p, w, h, unit, o!) : p;\n return gtf ? transformPoint(gtf, q, w, h, unit) : q;\n };\n}\n\n/** The axis-aligned box a mapped rectangle covers (its four corners through `map`). */\nexport function mapBox(map: (p: Pt) => Pt, box: { x0: number; y0: number; x1: number; y1: number }): { x0: number; y0: number; x1: number; y1: number } {\n const pts = [[box.x0, box.y0], [box.x1, box.y0], [box.x0, box.y1], [box.x1, box.y1]].map(([x, y]) => map({ x: x!, y: y! }));\n return {\n x0: Math.min(...pts.map((p) => p.x)),\n y0: Math.min(...pts.map((p) => p.y)),\n x1: Math.max(...pts.map((p) => p.x)),\n y1: Math.max(...pts.map((p) => p.y)),\n };\n}\n\n/** Back-compat: the box a layer transform (about the viewport centre) covers. */\nexport function transformBox(tf: LayerTransform, box: { x0: number; y0: number; x1: number; y1: number }, w: number, h: number, unit: number): { x0: number; y0: number; x1: number; y1: number } {\n return mapBox((p) => transformPoint(tf, p, w, h, unit), box);\n}\n","/**\n * The `field` background sampler — seeded, dependency-free value noise that\n * is a PURE function of `(u, v, t, config, seed)`.\n *\n * Why it is its own module, and why it never touches the entity RNG: a\n * background must be able to change without re-seating a single entity. The\n * sampler hashes an integer lattice with its own mixing function, so a spec\n * that adds (or steers) a field keeps the exact `buildEntities` stream it\n * had before — `field.test.ts` asserts it. Because the value at any point is\n * closed-form, the renderer (a low-res raster, upscaled) and the perception\n * grid (`luminanceGrid`) sample the SAME function and agree by construction;\n * that is the analytic guarantee FORMAT.md states for the field.\n *\n * Coordinates: `u`, `v` are in short-side units — `xPx / min(w, h)`,\n * `yPx / min(w, h)` — so `scale` reads as \"features across the short side\"\n * on every aspect ratio, and a 16:9 frame simply shows more of the same field\n * than a square one does. Callers on both sides normalise the same way.\n */\nimport type { FieldBackground } from './types';\n\nconst TWO_PI = Math.PI * 2;\n\n/** Cache bucket for a drifting field: the raster is recomputed at most this often. */\nexport const FIELD_BUCKET_MS = 100;\n/** Raster short side (px) the renderer paints the field at, then upscales. */\nexport const FIELD_RASTER_SHORT_SIDE = 96;\n/** Raster short side on the `basic` / `minimal` capability tiers. */\nexport const FIELD_RASTER_SHORT_SIDE_LOW = 48;\n/** How far (in feature units) `warp: 1` displaces the sample domain. */\nconst WARP_GAIN = 2;\n/** Radius (in feature units) of the slow domain circle at `drift.amount: 1`. */\nconst DRIFT_GAIN = 1;\n/** Default `drift.amount`. */\nexport const FIELD_DRIFT_DEFAULT_AMOUNT = 0.3;\n/**\n * Contrast stretch per octave count. Bilinear value noise (and more so an\n * octave sum) crowds around 0.5, so evenly spaced band thresholds would give\n * the middle bands almost everything. Each factor rescales the raw value so\n * its spread approaches a uniform 0..1 (σ 0.26–0.30 with ≤ 11 % of samples\n * clamped to an end band, a six-band histogram within 11–22 % per band);\n * measured over 4·10⁵ samples per octave count, symmetric about 0.5.\n */\nconst CONTRAST: readonly number[] = [1, 1.45, 1.8, 1.95, 2.0];\n\nconst clamp01 = (v: number): number => (v < 0 ? 0 : v > 1 ? 1 : v);\n\n/**\n * Integer-lattice hash → 0..1. Every product goes through `Math.imul` so the\n * arithmetic stays in int32 and the result is identical on every platform\n * (a float multiply of large ints would drift by ULPs across engines).\n */\nexport function latticeHash(ix: number, iy: number, seed: number): number {\n let h = Math.imul(ix | 0, 0x27d4eb2d) ^ Math.imul(iy | 0, 0x165667b1) ^ Math.imul(seed | 0, 0x9e3779b1);\n h = Math.imul(h ^ (h >>> 15), 0x85ebca6b);\n h = Math.imul(h ^ (h >>> 13), 0xc2b2ae35);\n h ^= h >>> 16;\n return (h >>> 0) / 4294967296;\n}\n\nconst smoothstep = (k: number): number => k * k * (3 - 2 * k);\n\n/** One octave of smooth value noise at (x, y), 0..1. */\nfunction valueNoise(x: number, y: number, seed: number): number {\n const x0 = Math.floor(x);\n const y0 = Math.floor(y);\n const fx = smoothstep(x - x0);\n const fy = smoothstep(y - y0);\n const a = latticeHash(x0, y0, seed);\n const b = latticeHash(x0 + 1, y0, seed);\n const c = latticeHash(x0, y0 + 1, seed);\n const d = latticeHash(x0 + 1, y0 + 1, seed);\n const top = a + (b - a) * fx;\n const bottom = c + (d - c) * fx;\n return top + (bottom - top) * fy;\n}\n\n/** Fractal sum of `octaves` value-noise octaves (amplitude halves, frequency doubles), normalised to 0..1. */\nfunction fbm(x: number, y: number, seed: number, octaves: number): number {\n let sum = 0;\n let amp = 1;\n let norm = 0;\n let f = 1;\n for (let i = 0; i < octaves; i++) {\n // Each octave samples a shifted lattice with its own seed so octave\n // boundaries never line up into a visible grid.\n sum += amp * valueNoise(x * f + i * 17.3, y * f + i * 31.7, seed + i * 101);\n norm += amp;\n amp *= 0.5;\n f *= 2;\n }\n return sum / norm;\n}\n\n/** The clamped, rounded octave count a config resolves to (steering may glide it through fractions). */\nexport function fieldOctaves(cfg: Pick<FieldBackground, 'octaves'>): number {\n const o = Math.round(cfg.octaves ?? 2);\n return o < 1 ? 1 : o > 4 ? 4 : o;\n}\n\n/**\n * The time the field is sampled at for scene time `t`: with `drift` at a\n * nonzero `amount`, the start of the 100 ms bucket `t` falls in (the renderer\n * recomputes its raster once per bucket and holds it, so the perception grid\n * samples the same instant); without `drift`, or with `drift.amount: 0` (the\n * domain never moves), the field is static and the answer is always 0 — so a\n * legally-static drift config isn't rebucketed, and re-rastered, ten times a\n * second for nothing.\n */\nexport function fieldSampleTime(cfg: Pick<FieldBackground, 'drift'>, t: number): number {\n return cfg.drift && cfg.drift.amount !== 0 ? Math.floor(t / FIELD_BUCKET_MS) * FIELD_BUCKET_MS : 0;\n}\n\n/**\n * The scalar field at short-side coordinates `(u, v)` and time `t` (ms),\n * 0..1. `seed` is the spec's seed; `cfg.seed` overrides it. Pure — no state,\n * no RNG stream, so the same inputs give the same value in every call on\n * every platform.\n */\nexport function fieldAt(u: number, v: number, t: number, cfg: FieldBackground, seed: number): number {\n const scale = cfg.scale;\n const octaves = fieldOctaves(cfg);\n const s = (cfg.seed ?? seed) >>> 0;\n let x = u * scale;\n let y = v * scale;\n const drift = cfg.drift;\n if (drift) {\n // The sample domain travels a slow circle of radius `amount` feature\n // units: the field loops exactly every `period`, no pixel ever jumps, and\n // the fastest any point can change is bounded by amount / period — which\n // the validator floors at 10 s, so a field can never flash.\n const phase = (TWO_PI * t) / drift.period;\n const r = (drift.amount ?? FIELD_DRIFT_DEFAULT_AMOUNT) * DRIFT_GAIN;\n x += r * Math.sin(phase);\n y += r * Math.cos(phase);\n }\n const warp = cfg.warp ?? 0;\n if (warp > 0) {\n // Domain warp: displace the sample point by a second, independent field.\n // Turns round noise blobs into the smeared, folded contours of a thermal\n // map or a weather chart.\n const qx = fbm(x + 5.2, y + 1.3, s + 7919, octaves) - 0.5;\n const qy = fbm(x + 1.7, y + 9.2, s + 104729, octaves) - 0.5;\n x += warp * WARP_GAIN * qx;\n y += warp * WARP_GAIN * qy;\n }\n const raw = fbm(x, y, s, octaves);\n return clamp01(0.5 + (raw - 0.5) * CONTRAST[octaves]!);\n}\n\n/** `#rgb` / `#rrggbb` → integer channels 0..255. Malformed input reads as mid grey. */\nexport function hexToRgb255(hex: string): [number, number, number] {\n const h = hex.length === 4 ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex;\n const n = /^#[0-9a-f]{6}$/i.test(h) ? parseInt(h.slice(1), 16) : NaN;\n if (Number.isNaN(n)) return [128, 128, 128];\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\n\n/** Perceptual luma (0..1) of integer RGB — the same weights `hexLuma` uses, so a band's luma matches its hex's. */\nexport function rgb255Luma(rgb: readonly [number, number, number]): number {\n return (0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2]) / 255;\n}\n\n/**\n * The colour a field value paints: `quantize ≥ 2` posterises the value into\n * that many levels and reads each level off the `bands` ramp (`quantize ===\n * bands.length`, the default, is exactly one band per level — hard, crisp\n * contours); `quantize: 0` interpolates the ramp smoothly (Aura, Mist). A\n * steered `quantize` gliding through fractions rounds to the nearest level\n * count. Integer channels, so a quantised band is byte-exact its hex.\n */\nexport function fieldRgb(value: number, bands: readonly string[], quantize: number | undefined): [number, number, number] {\n const n = bands.length;\n const q = Math.round(quantize ?? n);\n let f: number; // position along the ramp, 0..n-1\n if (q >= 2) {\n const level = Math.min(q - 1, Math.floor(clamp01(value) * q));\n f = (level * (n - 1)) / (q - 1); // multiply first: q === n gives an exact integer\n } else {\n f = clamp01(value) * (n - 1);\n }\n const i = Math.min(n - 2, Math.floor(f));\n const k = f - i;\n const a = hexToRgb255(bands[i]!);\n if (k === 0) return a;\n const b = hexToRgb255(bands[i + 1]!);\n return [\n Math.round(a[0] + (b[0] - a[0]) * k),\n Math.round(a[1] + (b[1] - a[1]) * k),\n Math.round(a[2] + (b[2] - a[2]) * k),\n ];\n}\n\n/** The painted colour at short-side coordinates `(u, v)`: `fieldRgb(fieldAt(...))`. */\nexport function fieldRgbAt(u: number, v: number, t: number, cfg: FieldBackground, seed: number): [number, number, number] {\n return fieldRgb(fieldAt(u, v, t, cfg, seed), cfg.bands, cfg.quantize);\n}\n","/**\n * The print `finish` — grain and a dither screen composited over a finished\n * frame as the LAST step of a render, after every layer and after ghosting\n * has done its work.\n *\n * Two rules make it flash-safe and deterministic:\n *\n * 1. **Zero-mean, bounded.** The grain tile is noise centred on mid grey and\n * the dither tile is an ordered Bayer matrix whose mean is mid grey; both\n * are composited with a symmetric blend (`overlay`, falling back to\n * `soft-light`, then `multiply`) at a small alpha, so the frame's mean\n * luminance is unchanged — a finish can neither brighten nor darken a\n * wall, and the analytic `luminanceGrid` ignores it entirely.\n * 2. **Seeded, never `Math.random`.** The grain tile is generated once per\n * mount from the spec seed with the same lattice hash the field uses. Its\n * offset is fixed for the mount; with `animate: true` it steps\n * deterministically from the frame's time bucket (12 Hz), so two viewers\n * at the same `t` show the same grain, and a seek is exact.\n *\n * The persistence rule: the finish is applied on a *presentation* canvas,\n * never on the canvas `ghosting` decays into — see `presentWithFinish`. Fed\n * back into the persistence loop, a static tile would reinforce itself every\n * frame into mud.\n */\nimport { latticeHash } from './field';\nimport type { FinishSpec } from './types';\n\n/** Grain tile side (px). Repeats across the frame. */\nexport const GRAIN_TILE = 256;\n/** Ordered-dither tile side (px): an 8×8 Bayer matrix. */\nexport const DITHER_TILE = 8;\n/** Composite alpha at `grain: 1`. */\nexport const GRAIN_ALPHA = 0.35;\n/** Composite alpha at `dither: 1`. */\nexport const DITHER_ALPHA = 0.25;\n/** Offset step rate under `animate: true`. */\nexport const FINISH_ANIMATE_HZ = 12;\n\nconst clamp01 = (v: number): number => (v < 0 ? 0 : v > 1 ? 1 : v);\n\n/** The clamped strengths a spec's finish resolves to (0 when absent). */\nexport function finishStrength(f: FinishSpec | undefined): { grain: number; dither: number } {\n return { grain: clamp01(f?.grain ?? 0), dither: clamp01(f?.dither ?? 0) };\n}\n\n/**\n * RGBA pixels of the grain tile for `seed`: zero-mean grey noise (the sum of\n * two lattice hashes — a triangular distribution, softer than uniform —\n * centred on 128), alpha 255. Pure; the same seed gives the same tile on\n * every platform.\n */\nexport function grainTilePixels(seed: number): Uint8ClampedArray {\n const px = new Uint8ClampedArray(GRAIN_TILE * GRAIN_TILE * 4);\n const s = seed >>> 0;\n let i = 0;\n for (let y = 0; y < GRAIN_TILE; y++) {\n for (let x = 0; x < GRAIN_TILE; x++) {\n const v = (latticeHash(x, y, s) + latticeHash(x, y, s + 0x5bd1e995)) / 2;\n const g = Math.round(128 + (v - 0.5) * 255);\n px[i++] = g;\n px[i++] = g;\n px[i++] = g;\n px[i++] = 255;\n }\n }\n return px;\n}\n\n/** The 8×8 Bayer ordered-dither matrix (values 0..63, recursively built). */\nexport function bayerMatrix(): number[][] {\n let m: number[][] = [[0]];\n for (let n = 1; n < DITHER_TILE; n *= 2) {\n const next: number[][] = [];\n for (let y = 0; y < n * 2; y++) {\n const row: number[] = [];\n for (let x = 0; x < n * 2; x++) {\n const base = m[y % n]![x % n]! * 4;\n const quadrant = (y >= n ? 2 : 0) + (x >= n ? 1 : 0);\n row.push(base + [0, 2, 3, 1][quadrant]!);\n }\n next.push(row);\n }\n m = next;\n }\n return m;\n}\n\n/**\n * RGBA pixels of the dither tile: the Bayer matrix as grey levels\n * `(v + 0.5) / 64 × 255`, so the tile's mean is mid grey (zero-mean under a\n * symmetric blend). A stylistic screen — it is composited at low alpha, not\n * used to threshold the image per pixel.\n */\nexport function bayerTilePixels(): Uint8ClampedArray {\n const m = bayerMatrix();\n const px = new Uint8ClampedArray(DITHER_TILE * DITHER_TILE * 4);\n let i = 0;\n for (let y = 0; y < DITHER_TILE; y++) {\n for (let x = 0; x < DITHER_TILE; x++) {\n const g = Math.round(((m[y]![x]! + 0.5) / (DITHER_TILE * DITHER_TILE)) * 255);\n px[i++] = g;\n px[i++] = g;\n px[i++] = g;\n px[i++] = 255;\n }\n }\n return px;\n}\n\n/**\n * Where the grain tile sits for scene time `t`: fixed at the origin unless\n * `animate`, in which case it steps to a seeded offset (0..255 per axis)\n * once per 1/12 s bucket — a pure function of `(t, seed)`.\n */\nexport function grainOffset(t: number, seed: number, animate: boolean): { x: number; y: number } {\n if (!animate) return { x: 0, y: 0 };\n const bucket = Math.floor((t * FINISH_ANIMATE_HZ) / 1000);\n const s = seed >>> 0;\n return {\n x: Math.floor(latticeHash(bucket, 1, s) * GRAIN_TILE),\n y: Math.floor(latticeHash(bucket, 2, s) * GRAIN_TILE),\n };\n}\n\nexport type ScreenOp = 'overlay' | 'soft-light' | 'multiply';\n\n/**\n * The symmetric blend the finish composites with. `overlay` is what every\n * shipping canvas2d implements; the readback detect exists for the odd\n * context that rejects it (an assignment the context does not support leaves\n * the previous value in place).\n */\nexport function pickScreenOp(ctx: { globalCompositeOperation: string }): ScreenOp {\n const prev = ctx.globalCompositeOperation;\n let op: ScreenOp = 'multiply';\n for (const candidate of ['overlay', 'soft-light'] as const) {\n ctx.globalCompositeOperation = candidate;\n if (ctx.globalCompositeOperation === candidate) {\n op = candidate;\n break;\n }\n }\n ctx.globalCompositeOperation = prev;\n return op;\n}\n\ntype Canvas2D = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\ntype AnyCanvas = HTMLCanvasElement | OffscreenCanvas;\n\n/**\n * A presentation pass: the visible canvas and the tiles (as repeat\n * patterns, created lazily and cached — patterns are bound to the context\n * that made them). Owned by the instance that presents; the scene itself is\n * drawn on a separate canvas that this pass copies from.\n */\nexport interface FinishPass {\n canvas: AnyCanvas;\n ctx: Canvas2D;\n op: ScreenOp;\n grain: CanvasPattern | null;\n dither: CanvasPattern | null;\n /** Seed the grain tile was generated for. */\n seed: number;\n}\n\n/** A canvas of `size`² px carrying `pixels`, or null where ImageData is unavailable. */\nfunction tileCanvas(size: number, pixels: Uint8ClampedArray): AnyCanvas | null {\n const canvas: AnyCanvas = typeof document !== 'undefined' ? document.createElement('canvas') : new OffscreenCanvas(size, size);\n canvas.width = size;\n canvas.height = size;\n const ctx = canvas.getContext('2d') as Canvas2D | null;\n if (!ctx || typeof ctx.createImageData !== 'function') return null;\n const img = ctx.createImageData(size, size);\n img.data.set(pixels);\n ctx.putImageData(img, 0, 0);\n return canvas;\n}\n\n/** Open a presentation pass on `visible`; null if it has no 2d context. */\nexport function createFinishPass(visible: AnyCanvas, seed: number): FinishPass | null {\n const ctx = visible.getContext('2d', { alpha: false }) as Canvas2D | null;\n if (!ctx) return null;\n return { canvas: visible, ctx, op: pickScreenOp(ctx), grain: null, dither: null, seed };\n}\n\n/** A fresh scene canvas for the instance to draw into (never attached to the DOM). */\nexport function createSceneCanvas(width: number, height: number): AnyCanvas {\n if (typeof document === 'undefined') return new OffscreenCanvas(Math.max(1, width), Math.max(1, height));\n const canvas = document.createElement('canvas');\n canvas.width = Math.max(1, width);\n canvas.height = Math.max(1, height);\n return canvas;\n}\n\nfunction pattern(fp: FinishPass, size: number, pixels: Uint8ClampedArray): CanvasPattern | null {\n const tile = tileCanvas(size, pixels);\n if (!tile || typeof fp.ctx.createPattern !== 'function') return null;\n return fp.ctx.createPattern(tile as CanvasImageSource, 'repeat');\n}\n\n/**\n * Copy `scene` onto the pass's canvas and screen the finish over it:\n * grain at `grain × 0.35` (tile offset per `grainOffset`), then dither at\n * `dither × 0.25`, both with the pass's blend op and no image smoothing (a\n * crisp screen). With nothing to apply it is a plain copy. `w`/`h` are the\n * logical size the context transform maps to the canvas. `seed` is the\n * effective seed the *current* finish resolves to — a sequence with a\n * segment-level finish can present a different seed per frame (one segment\n * to the next); it defaults to the pass's own seed, so a single-scene\n * caller (whose seed never changes) can omit it. The cached grain pattern\n * is rebuilt whenever the seed changes.\n */\nexport function presentWithFinish(\n fp: FinishPass,\n scene: AnyCanvas,\n w: number,\n h: number,\n t: number,\n finish: FinishSpec | undefined,\n animateAllowed: boolean,\n seed: number = fp.seed,\n): void {\n const p = fp.ctx;\n p.globalAlpha = 1;\n p.globalCompositeOperation = 'source-over';\n p.drawImage(scene as CanvasImageSource, 0, 0, w, h);\n // Same normalization SpecInstance applies to every seed it renders with\n // (0 is falsy, so a valid `seed: 0` lands on 1) — callers may pass a raw,\n // un-normalized seed, and the comparison below needs both sides in the\n // same space or a `seed: 0` scene would never match `fp.seed`.\n const normalizedSeed = (seed >>> 0) || 1;\n if (normalizedSeed !== fp.seed) {\n fp.seed = normalizedSeed;\n fp.grain = null;\n }\n const { grain, dither } = finishStrength(finish);\n if (grain > 0) {\n fp.grain ??= pattern(fp, GRAIN_TILE, grainTilePixels(fp.seed));\n if (fp.grain) screen(fp, fp.grain, grain * GRAIN_ALPHA, grainOffset(t, fp.seed, animateAllowed && finish?.animate === true), w, h);\n }\n if (dither > 0) {\n fp.dither ??= pattern(fp, DITHER_TILE, bayerTilePixels());\n if (fp.dither) screen(fp, fp.dither, dither * DITHER_ALPHA, { x: 0, y: 0 }, w, h);\n }\n}\n\nfunction screen(fp: FinishPass, pat: CanvasPattern, alpha: number, off: { x: number; y: number }, w: number, h: number): void {\n const p = fp.ctx;\n p.save();\n p.globalCompositeOperation = fp.op;\n p.globalAlpha = alpha;\n p.imageSmoothingEnabled = false;\n p.fillStyle = pat;\n // The pattern's origin follows the transform: shift it by the offset and\n // fill the same frame rectangle from there.\n p.translate(-off.x, -off.y);\n p.fillRect(off.x, off.y, w, h);\n p.restore();\n}\n","import { createRng } from '@idle-screens/core';\nimport { additivePlate, backgroundLuma, backgroundRgb, backgroundRgbAt, colourSeparation, hexLuma, hexRgb, legibilityRatio, relativeLuminance, sourceOverPlate, spriteHex, type Rgb } from './luma';\nimport { COHESION_T, cohesionOf, seamsWorthWarning } from './cohesion';\nimport { barFraction, polygonArea, polygonPoints } from './shapes';\nimport { breakTextBlock, buildEntities, entityScales, linkEdges, linkPairs, positionAt, textBlockAnchorOffset, textMetricsClassFor, textWidthEm, WARP_MAX_SCALE, type Entity } from './simulate';\nimport { morphNothingMorphable, structuralSignature } from './steer';\nimport { luminanceGrid } from './perceive';\nimport { groupOf, mapBox, paintMap, paintOpacity, paintSize } from './paint';\nimport { resolveTimelineAt, timelineTracks } from './timeline';\nimport { LIMITS, type IdleSequence, type LayerSpec, type SaverSpec, type SpecWarning, type WarningBox } from './types';\n\n/**\n * Minimum RGB-space colour distance (see `colourSeparation`) between a layer\n * and its background before the layer stops reading as a distinct thing.\n *\n * Calibrated against real specs rather than picked: a layer painted the literal\n * background hex measures 0.000, a near-background dark-on-dark layer ~0.036,\n * while every one of the 15 shipped examples and all 150 style-eval screens\n * clear it except the genuinely-flawed ones. Note this is a *colour* distance —\n * a Seurat-style gold-on-grey field separates by 0.39 here but only 0.013 in\n * luma, which is exactly why the measure is not luminance-based.\n */\nconst LOW_CONTRAST_FLOOR = 0.05;\n\n/**\n * A spec that declares `density: 'sparse'` is promising a mostly-empty frame.\n * Above this alpha-weighted coverage the promise is broken (2 % of the frame\n * is a comfortable field, not restraint — `lanterns` measures ~1.5 %).\n */\nconst SPARSE_DECLARED_MAX_COVERAGE = 0.02;\n\n/**\n * WCAG AA floor for body text. Only layers that declare `role: 'read'` are\n * measured against it — atmospheric text is texture, not copy, and the\n * shipped examples paint it at 2–3:1 on purpose.\n */\nconst READ_LEGIBILITY_FLOOR = 4.5;\n\n/** A `role: 'read'` box closer than this to any edge is in the overscan / bezel zone. */\nconst READ_SAFE_AREA = 0.05;\n\n/**\n * Alpha-weighted area (in viewport-areas) that additive `lighter`/`screen`\n * layers stack onto the frame before the analytic model is warned that it can\n * no longer see what it is measuring. The analytic luminance/dominance model\n * sums glow splats with no saturation ceiling, so a stack that clips to white\n * on a real canvas reports tame numbers and zero advisories (F35 — a\n * 250-entity white/cream `lighter` stack came back coverage 0.25, meanLuminance\n * 0.25, advisories []). Measured: the brightest shipped examples (`aurora`,\n * `warp-tunnel`) sit at 0.1, the recommended \"80 tiny soft circles at alpha\n * 0.2\" atmosphere at 0.0, and that stack at 2.0 — so 1.0 is an order of\n * magnitude above anything shipped and still half of the known blowout.\n */\nconst ADDITIVE_INK_CEILING = 1.0;\n\n/** True when a region window is butted against an edge on the given axis and\n * is a band rather than the whole axis — the shape of a deliberate anchor\n * (a skyline along the bottom, a ceiling of stars along the top). */\nfunction edgeAnchored(range: [number, number] | undefined): boolean {\n if (!range) return false;\n const [a, b] = range;\n return (a <= 0.02 || b >= 0.98) && b - a <= 0.6;\n}\n\n/**\n * Non-blocking advisory warnings for a valid spec. Does NOT replace validateSpec —\n * call advise only on specs that have already passed validation.\n */\nexport function adviseSpec(\n spec: SaverSpec,\n viewport = { width: 1920, height: 1080 },\n /**\n * Sample point. `perceiveScene` forwards its own `t`/`seed` so the advisories\n * describe the same scene its other channels do — without them a caller\n * perceiving at t = 30 s would get `form` for that instant beside an\n * `overlap-seams` advisory computed for a different one.\n *\n * `backgroundSeed` is separate from `seed` because a sequence's\n * `inkOverBed` (the segment's ink layers judged against the bed's\n * background — see `perceiveSequenceFrame`) mixes two scenes with\n * potentially different seeds: `seed` drives the ink layers' own entity\n * stream, `backgroundSeed` samples the bed's field. Defaults to `seed` —\n * every other caller has one scene and one seed for both.\n */\n opts: { t?: number; seed?: number; backgroundSeed?: number } = {},\n): SpecWarning[] {\n // Which layers never show in this scene — paint opacity (the layer's own ×\n // its group's) 0 at every key boundary of its timeline, or simply 0 without\n // one. A timed piece keeps every prop in every act and hides the unused\n // ones; judging those would bury the real advisories. Without `opacity` or\n // `groups` no layer is hidden and every check below runs as it always has.\n const hidden = hiddenLayers(spec);\n // A `timeline` resolves at the sample time; without one this is `spec` itself.\n spec = resolveTimelineAt(spec, opts.t ?? COHESION_T);\n const warnings: SpecWarning[] = [];\n const w = viewport.width;\n const h = viewport.height;\n const { scale, countScale } = entityScales(spec, w, h);\n const rng = createRng(opts.seed ?? spec.seed ?? 42);\n const allEntities = spec.layers.map((l) => buildEntities(l, rng, w, h, scale, countScale));\n\n // Do overlapping layers actually merge? Computed once from the entities we\n // already built; the advisory below fires only on the case where the author\n // clearly wanted one shape and the paint settings defeat it.\n const cohesion = cohesionOf(\n spec.layers.map((layer, i) => ({ layer, entities: allEntities[i]! })),\n opts.t ?? COHESION_T, w, h,\n );\n\n let totalEntities = 0;\n let textLayerCount = 0;\n let motionLayerCount = 0;\n\n for (let li = 0; li < spec.layers.length; li++) {\n if (hidden?.[li]) continue;\n const layer = spec.layers[li]!;\n const entities = allEntities[li]!;\n totalEntities += entities.length;\n\n const isText = layer.sprite.kind === 'text' || layer.sprite.kind === 'textBlock';\n const isStaticText = isText && layer.motion.type === 'static';\n if (isStaticText) textLayerCount++;\n if (layer.motion.type !== 'static') motionLayerCount++;\n\n const coh = cohesion[li]!;\n if (seamsWorthWarning(layer, coh, entities.length)) {\n // A soft or feathered edge has no edge to paint: overlaps pool into\n // smooth lumps, which is a cloud or a haze, not a seam. Measured live\n // (X423): the hard-edged control showed every overlap as an outline,\n // the soft storm showed none. What soft cannot do is make ONE solid\n // shape — say that, and leave clouds to the author.\n const s = layer.sprite;\n const softEdged = ((s.kind === 'circle' || s.kind === 'polygon') && s.soft) || (s.kind === 'rect' && !!s.feather);\n warnings.push({\n path: `layers[${li}]`,\n code: 'overlap-seams',\n message: softEdged\n ? `entities bury ${Math.round((coh.overlap ?? 0) * 100)}% of each other's outlines, but ${coh.seamCause}: `\n + 'overlaps pool into soft lumps rather than one solid silhouette (no hard edges — a cloud, smoke or haze reads well this way). '\n + 'If this layer is meant to be ONE solid shape, make it one flat colour at alpha 1, hard-edged, with no blend and no pulse.'\n : `entities bury ${Math.round((coh.overlap ?? 0) * 100)}% of each other's outlines, so this layer is drawn as one shape — `\n + `but ${coh.seamCause}, so every overlap paints a visible edge and it will read as a pile of sprites instead. `\n + 'A layer merges into a single silhouette only when it is one flat colour at alpha 1, hard-edged, with no blend and no pulse.',\n });\n }\n\n if (layer.trail && layer.motion.type === 'static') {\n warnings.push({\n path: `layers[${li}].trail`,\n code: 'trail-on-static',\n message: 'trail has no effect on static entities — they have no past positions to draw',\n });\n }\n\n // A spinning streak has an orientation of its own (a rotor, a clock hand),\n // so \"no heading\" is not a problem for it (F34.5).\n if ((layer.sprite.kind === 'streak' || (layer.sprite.kind === 'stroke' && layer.sprite.orient)) && layer.motion.type === 'static' && !layer.spin) {\n warnings.push({\n path: `layers[${li}].sprite`,\n code: 'streak-on-static',\n message: `${layer.sprite.kind === 'streak' ? 'streak sprites orient' : 'an oriented stroke turns'} along the motion heading — static entities have none, so the heading contributes nothing and it renders at angle 0`,\n });\n }\n\n if (layer.motion.type === 'wander' && layer.motion.coherence === 1 && entities.length >= 20) {\n warnings.push({\n path: `layers[${li}].motion.coherence`,\n code: 'full-coherence',\n message: 'coherence 1 makes every entity share identical harmonics — the layer moves as a rigid sheet. 0.5–0.8 reads as schooling',\n });\n }\n\n if (layer.sprite.kind === 'circle') {\n const maxR = entities.reduce((m, e) => Math.max(m, e.size / 2), 0);\n const maxAlpha = entities.reduce((m, e) => Math.max(m, e.alpha), 0);\n if (maxR * maxAlpha < 0.05) {\n warnings.push({\n path: `layers[${li}]`,\n code: 'invisible-layer',\n message: `layer's max visible radius (${maxR.toFixed(1)}px × ${maxAlpha.toFixed(2)} alpha) is below perceptual floor`,\n });\n }\n }\n\n // Colour separation: a layer painted the same brightness as the plate\n // behind it is invisible no matter how big or opaque it is. `invisible-layer`\n // above only measures radius × alpha, so a full-strength layer in a\n // background-matched colour passes every other check in this file.\n if (entities.length > 0 && layer.sprite.kind !== 'emoji') {\n // Judge against the plate the layer actually sits on: a gradient is\n // sampled across the layer's vertical extent (its region window, or its\n // pinned position), not averaged over a sky the layer never touches. A\n // layer is visible if it separates ANYWHERE in that extent (F19).\n const [y0, y1] = layer.position ? [layer.position.y, layer.position.y] : (layer.region?.y ?? [0, 1]);\n const plates = [y0, (y0 + y1) / 2, y1].map((y) => {\n const rgb = backgroundRgbAt(spec, y * h, h, scale, undefined, undefined, opts.backgroundSeed ?? opts.seed, opts.t ?? COHESION_T);\n return { rgb, luma: 0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b };\n });\n // A palette layer is visible if ANY of its colours separates — flag only\n // when every colour it can paint with disappears into the plate.\n const seps = entities.map((e) => {\n const hex = spriteHex(layer, e);\n if (hex === null) return Infinity;\n const ink = { rgb: hexRgb(hex), luma: hexLuma(hex) };\n const sep = Math.max(...plates.map((bg) => colourSeparation(layer, ink, bg)));\n if (sep >= LOW_CONTRAST_FLOOR || layer.blend === 'lighter' || layer.blend === 'screen') return sep;\n // Close to the page colour — but the page may not be what is behind\n // it. A dark key plate on an opaque yellow panel is judged against the\n // panel, which is what the eye (and perception's dominance) sees (X388).\n const under = groundUnder(spec, allEntities, li, hidden, positionAt(e, 0, w, h), w, h);\n return under ? colourSeparation(layer, ink, under) : sep;\n });\n const best = Math.max(...seps);\n if (best < LOW_CONTRAST_FLOOR) {\n const additive = layer.blend === 'lighter' || layer.blend === 'screen';\n warnings.push({\n path: `layers[${li}].sprite`,\n code: 'low-contrast-layer',\n message: additive\n ? `additive layer adds almost no light (luma ${best.toFixed(3)}) — a \"lighter\"/\"screen\" layer is only as visible as it is bright`\n : `layer colour is within ${best.toFixed(3)} of the background, or of the solid layer under it (floor ${LOW_CONTRAST_FLOOR}) — it will read as background, not as content`,\n });\n }\n }\n\n }\n\n // Alpha-weighted pixel coverage: how much of the viewport is \"visibly filled\"\n let totalCoverage = 0;\n let additiveInk = 0;\n for (let li = 0; li < spec.layers.length; li++) {\n if (hidden?.[li]) continue;\n const layer = spec.layers[li]!;\n const entities = allEntities[li]!;\n // Paint opacity weighs coverage like alpha does (unset ⇒ exactly as before).\n const paintA = layer.opacity === undefined && layer.group === undefined ? 1 : paintOpacity(spec, layer);\n // A layer/group transform scales what is painted, so it scales the area\n // too — the text boxes below already land where the transform puts them,\n // and coverage must judge the same picture (X418: a word zoomed 8× read\n // as both \"the scene is empty\" and \"the text runs 33 000 px off-screen\").\n const map = paintMap(spec, layer, w, h, scale);\n const areaScale = map ? paintSize(spec, layer) ** 2 : 1;\n const additive = layer.blend === 'lighter' || layer.blend === 'screen';\n for (const e of entities) {\n const r = e.size / 2;\n let pixArea: number;\n if (layer.sprite.kind === 'circle') {\n pixArea = Math.PI * r * r;\n } else if (layer.sprite.kind === 'polygon') {\n // The outline's own area, not its bounding square (4r²) — a flat band\n // or ridge fills a fraction of that.\n pixArea = polygonArea(polygonPoints(layer.sprite, r));\n } else if (layer.sprite.kind === 'bar') {\n pixArea = e.size * barFraction(layer.sprite, e.barIndex ?? 0) * (e.size2 ?? e.size * 0.2);\n } else if (layer.sprite.kind === 'textBlock') {\n const fsPx = layer.sprite.fontSize * scale;\n const lh = (layer.sprite.lineHeight ?? 1.4) * fsPx;\n const maxWPx = layer.sprite.maxWidth * scale;\n const lines = breakTextBlock(layer.sprite.text, maxWPx / fsPx, textMetricsClassFor(layer.sprite.font));\n pixArea = maxWPx * lines.length * lh * 0.55 * (layer.sprite.opacity ?? 1);\n } else if (layer.sprite.kind === 'text') {\n // The renderer's own box (a px `font` wins over the seeded size), at\n // the ~55 % ink fill a textBlock line is credited with.\n const b = textBoxAt(layer.sprite, e, positionAt(e, 0, w, h), spec, w, h);\n pixArea = (b.x1 - b.x0) * (b.y1 - b.y0) * 0.55;\n } else {\n pixArea = e.size * e.size; // emoji: approximate as square of its size\n }\n // Scaled by the transform, and never more than the frame it lands in.\n if (areaScale !== 1) pixArea *= areaScale;\n if (pixArea > w * h) pixArea = w * h;\n // Sparse-event layers are lit only for `life` of every `every` ms, at a\n // mean envelope of ~½, and at a mean grown size — judge their coverage\n // by that duty, not by whichever instant we happen to sample.\n let duty = 1;\n if (layer.emit) {\n // Area scales with size², so the time-mean over a linear size ramp\n // a→b is mean(f²) = (a² + ab + b²) / 3, not mean(f)².\n const [ga, gb] = layer.emit.grow ?? [1, 1];\n const g2 = (ga * ga + ga * gb + gb * gb) / 3;\n duty = (Math.min(layer.emit.life, layer.emit.every) / layer.emit.every) * 0.5 * g2;\n }\n const ink = paintA === 1 ? (pixArea * e.alpha * duty) / (w * h) : (pixArea * e.alpha * duty * paintA) / (w * h);\n totalCoverage += ink;\n if (additive) additiveInk += ink;\n }\n // Link lines are visual coverage too (for Mystify-style scenes they ARE the scene).\n if (layer.links) {\n const positions = entities.map((e) => positionAt(e, 0, w, h));\n const maxDistPx = layer.links.maxDist * scale;\n const edges = linkEdges(layer.links, positions, maxDistPx, layer.wrap !== false, w, h);\n const defaultWidth = scale === 1 ? 1 : 1 / LIMITS.referenceViewport;\n const lwPx = (layer.links.width ?? defaultWidth) * scale;\n const la = layer.links.alpha ?? 1;\n for (const edge of edges) totalCoverage += paintA === 1 ? (edge.dist * lwPx * la) / (w * h) : (edge.dist * lwPx * la * paintA) / (w * h);\n }\n }\n\n // A declared `density` is read before either density advisory fires — and\n // then checked against the measurement, so the declaration cannot be used\n // to silence a scene that is empty by accident rather than by intent.\n const density = spec.density ?? 'normal';\n const wouldBeSparse = totalCoverage < 0.0005 && spec.layers.length > 0;\n if (wouldBeSparse && density !== 'sparse') {\n warnings.push({\n path: 'layers',\n code: 'sparse-scene',\n message: `alpha-weighted coverage is ${(totalCoverage * 100).toFixed(4)}% — scene will look empty on most displays`,\n });\n }\n\n if (additiveInk > ADDITIVE_INK_CEILING) {\n warnings.push({\n path: 'layers',\n code: 'additive-saturation',\n message: `\"lighter\"/\"screen\" layers stack ${additiveInk.toFixed(1)}× the frame's area in alpha-weighted light — overlapping additive sprites clip to white on a real canvas, and the analytic perception model sums them without a ceiling so its coverage/luminance/dominance numbers cannot see it. Thin the count, lower alpha (summed additive alpha at any point ≲ 0.5), or drop blend on the densest layer`,\n });\n }\n\n if (totalEntities > 500 && density !== 'dense') {\n warnings.push({\n path: 'layers',\n code: 'dense-scene',\n message: `${totalEntities} entities — scene may feel crowded and hurt performance on low-end devices`,\n });\n }\n\n if (density === 'sparse' && totalCoverage > SPARSE_DECLARED_MAX_COVERAGE) {\n warnings.push({\n path: 'density',\n code: 'density-mismatch',\n message: `declared sparse but alpha-weighted coverage is ${(totalCoverage * 100).toFixed(2)}% — either the declaration or the scene is wrong`,\n });\n } else if (density === 'dense' && wouldBeSparse) {\n warnings.push({\n path: 'density',\n code: 'density-mismatch',\n message: `declared dense but alpha-weighted coverage is ${(totalCoverage * 100).toFixed(4)}% — the scene will look empty`,\n });\n }\n\n if (spec.layers.length > 0 && textLayerCount > 0 && motionLayerCount === 0) {\n const textRatio = textLayerCount / spec.layers.length;\n if (textRatio >= 0.8) {\n warnings.push({\n path: 'layers',\n code: 'text-heavy',\n message: 'most layers are static text — reads as a document, not a screensaver',\n });\n }\n }\n\n // Link starvation: links layer where few edges actually form.\n // Chain mode always forms its edges — only distance-gated modes can starve.\n for (let li = 0; li < spec.layers.length; li++) {\n if (hidden?.[li]) continue;\n const layer = spec.layers[li]!;\n if (!layer.links || layer.links.mode === 'chain') continue;\n const entities = allEntities[li]!;\n const positions = entities.map((e) => positionAt(e, 0, w, h));\n const maxDist = layer.links.maxDist * scale;\n const pairs = linkPairs(positions, layer.links.k, maxDist, layer.wrap !== false, w, h);\n const maxPossible = Math.min(entities.length * layer.links.k, entities.length * (entities.length - 1) / 2);\n if (maxPossible > 0 && pairs.length / maxPossible < 0.1) {\n warnings.push({\n path: `layers[${li}].links`,\n code: 'link-starvation',\n message: `only ${pairs.length}/${maxPossible} possible edges formed — raise count or widen links.maxDist`,\n });\n }\n }\n\n // Motion variety: all entities in a layer have nearly identical velocity\n for (let li = 0; li < spec.layers.length; li++) {\n if (hidden?.[li]) continue;\n const layer = spec.layers[li]!;\n if (layer.motion.type === 'static') continue;\n const entities = allEntities[li]!;\n if (entities.length < 3) continue;\n const speeds = entities.map((e) => Math.sqrt(e.vx * e.vx + e.vy * e.vy));\n const mean = speeds.reduce((a, b) => a + b, 0) / speeds.length;\n if (mean === 0) continue;\n const maxDev = Math.max(...speeds.map((s) => Math.abs(s - mean)));\n if (maxDev / mean < 0.05) {\n warnings.push({\n path: `layers[${li}].motion`,\n code: 'uniform-motion',\n message: 'all entities move at nearly identical speed — widen the speed range for visual variety',\n });\n }\n }\n\n // Composition balance: entities clustered in one region. Motions that sweep the\n // whole viewport (bounce, warp, path) have transient spawn positions that say\n // nothing about composition — exclude them from the centroid.\n const composed = spec.layers\n .map((l, li) => ({ l, li, ents: allEntities[li]! }))\n .filter(({ li }) => !hidden?.[li])\n .filter(({ l }) => !['bounce', 'warp', 'path'].includes(l.motion.type))\n // Layer-parented orbits position relative to their parent (resolved at render\n // time) — their raw positionAt is an offset around (0,0), not a screen position.\n .filter(({ l }) => !(l.motion.type === 'orbit' && l.motion.center && 'layer' in l.motion.center));\n const composedCount = composed.reduce((s, c) => s + c.ents.length, 0);\n if (composedCount >= 8) {\n const positions = composed.flatMap(({ ents }) => ents.map((e) => positionAt(e, 0, w, h)));\n const px = positions.reduce((s, p) => s + p.x, 0) / positions.length / w;\n const py = positions.reduce((s, p) => s + p.y, 0) / positions.length / h;\n // A skyline sits low on purpose. When the offset is along ONE axis and most\n // of the composed entities come from layers whose region is butted against\n // an edge on that axis, the offset is the composition, not a mistake (F20).\n const offX = Math.abs(px - 0.5);\n const offY = Math.abs(py - 0.5);\n const anchoredOn = (axis: 'x' | 'y'): number =>\n composed.reduce((n, { l, ents }) => n + (edgeAnchored(l.region?.[axis]) ? ents.length : 0), 0) / composedCount;\n const intentional =\n (offY > 0.2 && offX <= 0.2 && anchoredOn('y') >= 0.5) ||\n (offX > 0.2 && offY <= 0.2 && anchoredOn('x') >= 0.5);\n if ((offX > 0.2 || offY > 0.2) && !intentional) {\n // Where the entities are is only a suspicion; where the ink is decides.\n // Confirmed on the same luminance grid — the same rule, cells weighted\n // by how far they sit from the background — that perception reports\n // beside it, so the two can no longer disagree in one response (X384:\n // 24 overlapping slivers in one half outweighed a full-height stripe in\n // the other, 0.73 counted vs 0.58 seen). It can only silence the head\n // count, never add a warning, and costs a grid only when it fires.\n const grid = luminanceGrid({ ...spec, layers: composed.map(({ l }) => l) }, { viewport: { width: w, height: h }, t: opts.t ?? COHESION_T, seed: opts.seed });\n const c = grid.centroid;\n if (c && (Math.abs(c.x - 0.5) > 0.2 || Math.abs(c.y - 0.5) > 0.2)) {\n warnings.push({\n path: 'layers',\n code: 'off-center',\n message: `centroid at (${c.x.toFixed(2)}, ${c.y.toFixed(2)}) — composition is heavily offset from center`,\n });\n }\n }\n }\n\n // Spatial text: the one layout bug an author without eyes makes most and\n // cannot detect — a caption that runs off the frame, a title painted over a\n // body. Only static text is judged (moving text has no fixed box). Boxes use\n // the character-class width table the textBlock line-breaker uses, so the\n // estimate is the renderer's own idea of the text, not a separate guess.\n const textBoxes: TextBoxAt[] = [];\n for (let li = 0; li < spec.layers.length; li++) {\n if (hidden?.[li]) continue;\n const layer = spec.layers[li]!;\n const s = layer.sprite;\n if (layer.motion.type !== 'static') continue;\n if (s.kind !== 'text' && s.kind !== 'textBlock') continue;\n const label = layer.key ? `\\`${layer.key}\\`` : `layers[${li}]`;\n for (const e of allEntities[li]!) {\n const p = positionAt(e, 0, w, h);\n const raw = s.kind === 'textBlock' ? textBlockBoxAt(s, p, w, h) : textBoxAt(s, e, p, spec, w, h);\n // A layer `transform` moves (and scales) the painted text: judge the box where it lands.\n const map = paintMap(spec, layer, w, h, scale);\n const box = map ? { ...raw, ...mapBox(map, raw) } : raw;\n // What the layer guarantees it paints, worst case: base alpha minus its\n // pulse trough (ignoring `emit`'s on/off envelope — a mark's on-screen\n // duty cycle is a readability question, not an ink-colour one; sampling\n // at `t = 0` would otherwise flag every emitting layer as invisible)\n // times a textBlock's own `opacity` — so faint or invisible\n // `role: 'read'` text can't hide behind an unmeasured alpha.\n const baseAlpha = Math.max(0, Math.min(1, e.alpha - e.pulseAmp)) * (s.kind === 'textBlock' ? (s.opacity ?? 1) : 1);\n const alpha = layer.opacity === undefined && layer.group === undefined ? baseAlpha : baseAlpha * paintOpacity(spec, layer);\n const str = s.kind === 'textBlock' ? s.text : (s.strings[e.spriteIndex] ?? s.strings[0] ?? '');\n textBoxes.push({ li, label, alpha, str, ...box });\n }\n }\n const asFraction = (b: Pick<Box, 'x0' | 'y0' | 'x1' | 'y1'>): WarningBox => ({\n x: +(b.x0 / w).toFixed(4),\n y: +(b.y0 / h).toFixed(4),\n w: +((b.x1 - b.x0) / w).toFixed(4),\n h: +((b.y1 - b.y0) / h).toFixed(4),\n });\n\n // Off-screen: any edge past the viewport by more than 1% of that dimension\n // (the width table is approximate; a hairline overhang is not a finding).\n const tolX = w * 0.01;\n const tolY = h * 0.01;\n const offFlagged = new Set<number>();\n for (const b of textBoxes) {\n if (offFlagged.has(b.li)) continue;\n const edges: string[] = [];\n if (b.x0 < -tolX) edges.push(`left edge by ~${Math.round(-b.x0)}px`);\n if (b.x1 > w + tolX) edges.push(`right edge by ~${Math.round(b.x1 - w)}px`);\n if (b.y0 < -tolY) edges.push(`top edge by ~${Math.round(-b.y0)}px`);\n if (b.y1 > h + tolY) edges.push(`bottom edge by ~${Math.round(b.y1 - h)}px`);\n if (edges.length === 0) continue;\n offFlagged.add(b.li);\n warnings.push({\n path: `layers[${b.li}]`,\n code: 'text-off-screen',\n message: `${b.label} text runs off the ${edges.join(' and the ')} at ${w}×${h} — move position, or shrink fontSize / maxWidth`,\n });\n }\n\n // Overlap: two different static text layers whose boxes share more than 10%\n // of the smaller box. Reported once per layer pair, on the earlier layer.\n const pairFlagged = new Set<string>();\n for (let i = 0; i < textBoxes.length; i++) {\n for (let j = i + 1; j < textBoxes.length; j++) {\n const a = textBoxes[i]!;\n const b = textBoxes[j]!;\n if (a.li === b.li) continue;\n const pair = `${Math.min(a.li, b.li)}:${Math.max(a.li, b.li)}`;\n if (pairFlagged.has(pair)) continue;\n const ix = Math.min(a.x1, b.x1) - Math.max(a.x0, b.x0);\n const iy = Math.min(a.y1, b.y1) - Math.max(a.y0, b.y0);\n if (ix <= 0 || iy <= 0) continue;\n const smaller = Math.min((a.x1 - a.x0) * (a.y1 - a.y0), (b.x1 - b.x0) * (b.y1 - b.y0));\n if (smaller <= 0) continue;\n const share = (ix * iy) / smaller;\n if (share <= 0.1) continue;\n if (isOutlineStack(a, b)) continue;\n pairFlagged.add(pair);\n const [first, second] = a.li < b.li ? [a, b] : [b, a];\n warnings.push({\n path: `layers[${first.li}]`,\n code: 'text-overlap',\n message: `${first.label} and ${second.label} text boxes overlap (~${Math.round(share * 100)}% of the smaller one) — they will paint over each other; move one or shrink it`,\n // The two boxes, so an agent can move one without re-deriving the\n // layout. Additive: the message is unchanged.\n boxes: [asFraction(first), asFraction(second)],\n });\n }\n }\n\n // Legibility, for text that declared it must be read (`role: 'read'`).\n // Everything below is opt-in: a layer without the role is never measured,\n // so the atmospheric text the examples paint at 2–3:1 stays silent.\n const readFlagged = new Set<number>();\n for (const b of textBoxes) {\n if (readFlagged.has(b.li)) continue;\n const layer = spec.layers[b.li]!;\n const s = layer.sprite;\n if ((s.kind !== 'text' && s.kind !== 'textBlock') || s.role !== 'read') continue;\n // Every box of the layer (a `list` of labels is several), worst one wins.\n const boxes = textBoxes.filter((x) => x.li === b.li);\n readFlagged.add(b.li);\n\n const ink = hexRgb(s.color ?? '#e6e8ef');\n // What the layer actually paints over `base`, at its own alpha and blend —\n // a `role: 'read'` label at low opacity, or under `lighter`/`screen`/\n // `multiply`, is not free to hide behind a source-over assumption.\n const textPlate = (base: Rgb, alpha: number): Rgb => {\n if (layer.blend === 'lighter' || layer.blend === 'screen') return additivePlate(base, ink, alpha, layer.blend);\n if (layer.blend === 'multiply') {\n return {\n r: base.r * (1 - alpha + ink.r * alpha),\n g: base.g * (1 - alpha + ink.g * alpha),\n b: base.b * (1 - alpha + ink.b * alpha),\n };\n }\n return sourceOverPlate(base, ink, alpha);\n };\n let worst: { ground: number; plate: number; plateLabel: string | null } | null = null;\n for (const box of boxes) {\n const cy = (box.y0 + box.y1) / 2;\n const cx = (box.x0 + box.x1) / 2;\n const groundRgb = backgroundRgbAt(spec, cy, h, scale, cx, w, opts.backgroundSeed ?? opts.seed, opts.t ?? COHESION_T);\n const ground = legibilityRatio(textPlate(groundRgb, box.alpha), groundRgb);\n const lit = brightestAdditivePlate(spec, allEntities, groundRgb, box, w, h);\n const plate = lit ? legibilityRatio(textPlate(lit.rgb, box.alpha), lit.rgb) : Infinity;\n if (!worst || Math.min(ground, plate) < Math.min(worst.ground, worst.plate)) {\n worst = { ground, plate, plateLabel: lit?.label ?? null };\n }\n }\n if (worst && Math.min(worst.ground, worst.plate) < READ_LEGIBILITY_FLOOR) {\n const under = worst.plateLabel\n ? ` and ${worst.plate.toFixed(1)}:1 under ${worst.plateLabel} at its brightest`\n : '';\n warnings.push({\n path: `layers[${b.li}].sprite`,\n code: 'text-legibility',\n message: `${b.label} is declared role: 'read' but its colour reads at ${worst.ground.toFixed(1)}:1 against the background at the box centre${under} — below ${READ_LEGIBILITY_FLOOR}:1; brighten the text, darken the ground under it, or declare role: 'atmosphere' if it is texture`,\n });\n }\n\n // Safe area: readable text that sits in the outer 5 % of the frame lands\n // in the bezel / overscan zone on a real display.\n const edges: string[] = [];\n const x0 = Math.min(...boxes.map((x) => x.x0));\n const x1 = Math.max(...boxes.map((x) => x.x1));\n const y0 = Math.min(...boxes.map((x) => x.y0));\n const y1 = Math.max(...boxes.map((x) => x.y1));\n if (x0 < w * READ_SAFE_AREA) edges.push('left');\n if (x1 > w * (1 - READ_SAFE_AREA)) edges.push('right');\n if (y0 < h * READ_SAFE_AREA) edges.push('top');\n if (y1 > h * (1 - READ_SAFE_AREA)) edges.push('bottom');\n if (edges.length > 0) {\n warnings.push({\n path: `layers[${b.li}]`,\n code: 'text-safe-area',\n message: `${b.label} is declared role: 'read' but its box is within ${READ_SAFE_AREA * 100}% of the ${edges.join(' and ')} edge${edges.length === 1 ? '' : 's'} at ${w}×${h} — displays crop and bezels hide that zone; move it inward`,\n boxes: [asFraction({ x0, y0, x1, y1 })],\n });\n }\n }\n\n return warnings;\n}\n\n/**\n * The brightest ground a `role: 'read'` box can find itself on: for every\n * additive layer (`lighter` / `screen`) whose entities can reach the box and\n * are big enough to sit under a glyph, the brightest per-entity plate — its\n * own colour composited at its own peak alpha (base + pulse), never a\n * different entity's alpha borrowed onto it. Reach is judged at rest: a\n * static entity is its disc at `t = 0`; an orbit is its centre ± radius;\n * every travelling motion can be anywhere. The disc's diameter is the\n * entity's largest possible rendered extent — grow breathing, a rect/bar's\n * second dimension (thickness/aspect height can exceed the primary size),\n * and the peak scale warp/emit reach over their lifecycle — so a mote that\n * balloons under a line is not dismissed as dust because it starts small.\n */\nfunction brightestAdditivePlate(\n spec: SaverSpec,\n allEntities: Entity[][],\n ground: Rgb,\n box: TextBoxAt,\n w: number,\n h: number,\n): { rgb: Rgb; label: string } | null {\n let best: { rgb: Rgb; label: string; lum: number } | null = null;\n for (let lj = 0; lj < spec.layers.length; lj++) {\n const layer = spec.layers[lj]!;\n const blend = layer.blend;\n if (blend !== 'lighter' && blend !== 'screen') continue;\n if (lj === box.li) continue;\n const entities = allEntities[lj]!;\n // Only a layer that is actually moved at draw time (its own or its\n // group's transform) may reach anywhere; opacity alone moves nothing.\n const moved = layer.transform !== undefined || groupOf(spec, layer)?.transform !== undefined;\n for (const e of entities) {\n const hex = spriteHex(layer, e);\n if (hex === null) continue;\n const growScale = (e.motion === 'warp' ? WARP_MAX_SCALE : 1) * (e.emit ? Math.max(e.emit.growFrom, e.emit.growTo) : 1);\n const maxDim = Math.max(e.size, e.size2 ?? 0) * (1 + e.growAmp) * growScale;\n if (maxDim < box.fs) continue;\n // A transformed layer is moved at draw time: treat it like a moving one (it may reach anywhere).\n if (!moved && !entityReachesBox(e, maxDim / 2, box, w, h)) continue;\n const a = layer.opacity === undefined && layer.group === undefined ? Math.min(1, e.alpha + e.pulseAmp) : Math.min(1, e.alpha + e.pulseAmp) * paintOpacity(spec, layer);\n if (a <= 0) continue;\n const plate = additivePlate(ground, hexRgb(hex), a, blend);\n const lum = relativeLuminance(plate);\n if (!best || lum > best.lum) {\n best = { rgb: plate, label: layer.key ? `\\`${layer.key}\\`` : `layers[${lj}]`, lum };\n }\n }\n }\n return best ? { rgb: best.rgb, label: best.label } : null;\n}\n\n/**\n * What an earlier layer has painted at `pt` (t = 0), composited over the\n * page colour, or null when nothing solid sits there. Conservative on\n * purpose: only static, transform-free, normal-blend, hard-edged shapes\n * count, with exact containment for circles, axis-aligned (or quarter-turned)\n * rects and unrotated polygons — so the low-contrast check can only be\n * talked out of firing by a plate that is really there.\n */\nfunction groundUnder(\n spec: SaverSpec,\n allEntities: Entity[][],\n li: number,\n hidden: boolean[] | null,\n pt: { x: number; y: number },\n w: number,\n h: number,\n): { rgb: Rgb; luma: number } | null {\n let plate: Rgb = backgroundRgb(spec);\n let covered = false;\n for (let lj = 0; lj < li; lj++) {\n if (hidden?.[lj]) continue;\n const layer = spec.layers[lj]!;\n const sp = layer.sprite;\n if (layer.motion.type !== 'static' || layer.blend !== undefined || layer.transform !== undefined || groupOf(spec, layer)?.transform !== undefined) continue;\n if ((sp.kind === 'circle' || sp.kind === 'polygon') && sp.soft) continue;\n if (sp.kind !== 'circle' && sp.kind !== 'rect' && sp.kind !== 'polygon') continue;\n const a = layer.opacity === undefined && layer.group === undefined ? 1 : paintOpacity(spec, layer);\n for (const e of allEntities[lj]!) {\n if (e.spinSpeed !== 0 || e.alpha * a <= 0) continue;\n const hex = spriteHex(layer, e);\n if (hex === null) continue;\n const c = positionAt(e, 0, w, h);\n const dx = pt.x - c.x;\n const dy = pt.y - c.y;\n let inside = false;\n if (sp.kind === 'circle') inside = Math.hypot(dx, dy) <= e.size / 2;\n else if (sp.kind === 'rect') {\n const rot = ((e.rotate ?? 0) % Math.PI + Math.PI) % Math.PI;\n const quarter = Math.abs(rot - Math.PI / 2) < 0.01;\n if (rot > 0.01 && rot < Math.PI - 0.01 && !quarter) continue;\n const hx = (quarter ? (e.size2 ?? e.size) : e.size) / 2;\n const hy = (quarter ? e.size : (e.size2 ?? e.size)) / 2;\n inside = Math.abs(dx) <= hx && Math.abs(dy) <= hy;\n } else {\n if (e.rotate) continue;\n inside = pointInPolygon(dx, dy, polygonPoints(sp, e.size / 2));\n }\n if (!inside) continue;\n plate = sourceOverPlate(plate, hexRgb(hex), Math.min(1, e.alpha * a));\n covered = true;\n }\n }\n return covered ? { rgb: plate, luma: 0.2126 * plate.r + 0.7152 * plate.g + 0.0722 * plate.b } : null;\n}\n\nfunction pointInPolygon(x: number, y: number, pts: Array<{ x: number; y: number }>): boolean {\n let inside = false;\n for (let i = 0, j = pts.length - 1; i < pts.length; j = i++) {\n const a = pts[i]!;\n const b = pts[j]!;\n if ((a.y > y) !== (b.y > y) && x < ((b.x - a.x) * (y - a.y)) / (b.y - a.y) + a.x) inside = !inside;\n }\n return inside;\n}\n\n/** Whether an entity's disc of half-extent `r` can overlap `box` (see `brightestAdditivePlate`). */\nfunction entityReachesBox(e: Entity, r: number, box: TextBoxAt, w: number, h: number): boolean {\n if (e.motion === 'static') {\n const p = positionAt(e, 0, w, h);\n return p.x + r > box.x0 && p.x - r < box.x1 && p.y + r > box.y0 && p.y - r < box.y1;\n }\n if (e.motion === 'orbit' && !e.orbitParent) {\n const span = e.orbitR + r;\n return e.orbitCx + span > box.x0 && e.orbitCx - span < box.x1 && e.orbitCy + span > box.y0 && e.orbitCy - span < box.y1;\n }\n return true;\n}\n\n/**\n * The outline / drop-shadow idiom (X416): the SAME string painted twice at the\n * same size, nudged a few px — a dark copy under the fill. That is one title,\n * not two labels colliding. \"A few px\" is judged against the glyph height, so\n * it holds at every viewport: centres within 15 % of it, sizes within 10 %.\n */\nconst OUTLINE_STACK_OFFSET = 0.15;\n\nfunction isOutlineStack(a: TextBoxAt, b: TextBoxAt): boolean {\n if (a.str !== b.str || a.str.trim() === '') return false;\n const fs = Math.min(a.fs, b.fs);\n if (fs <= 0 || Math.abs(a.fs - b.fs) > 0.1 * Math.max(a.fs, b.fs)) return false;\n const dx = (a.x0 + a.x1) / 2 - (b.x0 + b.x1) / 2;\n const dy = (a.y0 + a.y1) / 2 - (b.y0 + b.y1) / 2;\n return Math.hypot(dx, dy) <= OUTLINE_STACK_OFFSET * fs;\n}\n\ninterface TextBoxAt {\n li: number;\n label: string;\n /** The painted string — two boxes of one string offset a hair are an outline, not a clash. */\n str: string;\n /**\n * Worst case, not \"at rest\": base alpha minus its pulse trough (never the\n * `emit` envelope, whose on/off duty cycle is excluded on purpose) times a\n * textBlock's own `opacity`.\n */\n alpha: number;\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n /** Glyph height in px — what an additive layer must out-size to sit under a line. */\n fs: number;\n}\n\ntype Box = Pick<TextBoxAt, 'x0' | 'y0' | 'x1' | 'y1' | 'fs'>;\n\n/**\n * Box of one `text` entity, mirroring the renderer: a `font` with a px size is\n * used verbatim (scaled by the same viewport/reference ratio the renderer\n * applies), otherwise the seeded per-entity size; `align`/`baseline` move the\n * anchor; `maxWidth` is a hard cap because `fillText(text, x, y, maxWidth)`\n * squeezes the glyphs to fit.\n */\nfunction textBoxAt(\n s: Extract<LayerSpec['sprite'], { kind: 'text' }>,\n e: Entity,\n p: { x: number; y: number },\n spec: SaverSpec,\n w: number,\n h: number,\n): Box {\n const m = s.font ? /(\\d{1,5}(?:\\.\\d{1,4})?|\\.\\d{1,4})px/.exec(s.font) : null;\n const fontScale = spec.units === 'px' ? 1 : Math.min(w, h) / (spec.referenceViewport ?? LIMITS.referenceViewport);\n const fh = m ? Number(m[1]) * fontScale : e.size;\n const str = s.strings[e.spriteIndex] ?? s.strings[0] ?? '';\n let fw = textWidthEm(str) * fh;\n if (s.maxWidth) fw = Math.min(fw, s.maxWidth * (spec.units === 'px' ? 1 : Math.min(w, h)));\n const align = s.align ?? 'center';\n const baseline = s.baseline ?? 'middle';\n const x0 = align === 'left' ? p.x : align === 'right' ? p.x - fw : p.x - fw / 2;\n const y0 = baseline === 'top' ? p.y : baseline === 'bottom' ? p.y - fh : p.y - fh / 2;\n return { x0, y0, x1: x0 + fw, y1: y0 + fh, fs: fh };\n}\n\n/**\n * Box of a `textBlock`, mirroring the renderer: `position` is the block's\n * top-left, lines break with `breakTextBlock`, `align` moves the painted lines\n * inside the `maxWidth` box (not the box itself).\n */\nfunction textBlockBoxAt(\n s: Extract<LayerSpec['sprite'], { kind: 'textBlock' }>,\n p: { x: number; y: number },\n w: number,\n h: number,\n): Box {\n const unit = Math.min(w, h);\n const fsPx = s.fontSize * unit;\n const lh = (s.lineHeight ?? 1.4) * fsPx;\n const maxWPx = s.maxWidth * unit;\n const lines = breakTextBlock(s.text, maxWPx / fsPx, textMetricsClassFor(s.font));\n const maxLineW = lines.reduce((mx, l) => Math.max(mx, l.widthEm), 0) * fsPx;\n const totalH = lines.length * lh;\n const align = s.align ?? 'left';\n const x0 = align === 'center' ? p.x + (maxWPx - maxLineW) / 2 : align === 'right' ? p.x + maxWPx - maxLineW : p.x;\n // Anchor moves the whole block the same way the renderer does (0,0 when absent).\n const { dx, dy } = textBlockAnchorOffset(s, maxWPx, maxLineW, totalH);\n return { x0: x0 + dx, y0: p.y + dy, x1: x0 + dx + maxLineW, y1: p.y + dy + totalH, fs: fsPx };\n}\n\n/**\n * Per layer, whether it never shows: its own `opacity`, or its group's, is\n * pinned to 0 — 0 in the base scene and every `timeline` key on that path\n * (and no whole-object key above it) sets 0 too. A glide between zeros stays\n * at zero, so this is exact at every instant, not just at key boundaries,\n * and costs no timeline resolution. Membership is fixed per scene (not\n * steerable or keyable), so a group's pin covers its members. Null when no\n * layer uses `opacity` or `groups` (nothing can be hidden — the common case).\n */\nfunction hiddenLayers(spec: SaverSpec): boolean[] | null {\n if (!spec.groups && !spec.layers.some((l) => l.opacity !== undefined)) return null;\n const tracks = spec.timeline ? timelineTracks(spec) : null;\n const pinnedZero = (path: string, base: unknown, ancestors: string[]): boolean => {\n if (base !== 0) return false;\n if (!tracks) return true;\n for (const [p, keys] of tracks) {\n if (p === path && keys.some((k) => k.value !== 0)) return false;\n if (ancestors.includes(p)) return false; // a whole-object key could set anything\n }\n return true;\n };\n const out = spec.layers.map((l, i) => {\n const lp = `layers.${i}`;\n if (pinnedZero(`${lp}.opacity`, l.opacity, ['layers', lp])) return true;\n const g = l.group !== undefined && spec.groups && Object.prototype.hasOwnProperty.call(spec.groups, l.group) ? spec.groups[l.group] : undefined;\n return !!g && pinnedZero(`groups.${l.group}.opacity`, g.opacity, ['groups', `groups.${l.group}`]);\n });\n return out.some(Boolean) ? out : null;\n}\n\n/**\n * Non-blocking advisory warnings for a validated sequence envelope.\n * Checks cross-segment luminance jumps at boundaries and per-segment advisories.\n */\nexport function adviseSequence(\n seq: IdleSequence,\n viewport = { width: 1920, height: 1080 },\n): SpecWarning[] {\n const warnings: SpecWarning[] = [];\n\n for (let i = 0; i < seq.segments.length; i++) {\n const seg = seq.segments[i]!;\n // A timed segment changes as it plays, so its advisories describe ONE\n // stated moment of it — never a moment past its end. The default sample\n // (COHESION_T, 5 s) used to land beyond a 2 s segment and judge its\n // timeline's final frame while the request asked about another (X418).\n const timed = !!seg.scene.timeline && seg.duration !== undefined;\n const tSample = timed ? Math.min(COHESION_T, seg.duration!) : undefined;\n const segWarnings = adviseSpec(seg.scene, viewport, tSample === undefined ? {} : { t: tSample });\n const at = tSample === undefined ? '' : ` (judged ${(tSample / 1000).toFixed(1)} s into this ${(seg.duration! / 1000).toFixed(1)} s segment)`;\n for (const w of segWarnings) {\n warnings.push({ path: `segments[${i}].scene.${w.path}`, code: w.code, message: w.message + at, boxes: w.boxes });\n }\n }\n\n // Informational, once per sequence: a fade costs two live segments for\n // `dur`, which the lowest tiers cannot afford, so they play it as a cut.\n // A `fade` on the last segment only ever runs under `loop: true` (it's the\n // wrap's transition into segment 0) — without loop there is no next\n // segment for it to transition into, so it never executes and should not\n // be counted.\n const fadeBound = seq.loop ? seq.segments.length : seq.segments.length - 1;\n const fades = seq.segments.slice(0, fadeBound).filter((s) => s.transition?.type === 'fade').length;\n if (fades > 0) {\n const first = seq.segments.slice(0, fadeBound).findIndex((s) => s.transition?.type === 'fade');\n warnings.push({\n path: `segments[${first}].transition`,\n code: 'fade-degrades-on-low-tier',\n message: `informational: ${fades} fade transition${fades === 1 ? '' : 's'} declared — viewers on the 'basic' or 'minimal' capability tier render fade as cut (two live segments for dur is over that budget); the show still plays`,\n });\n }\n\n for (let i = 0; i < seq.segments.length - 1; i++) {\n const tr = seq.segments[i]!.transition;\n // The ground each side of the cut actually shows: the outgoing segment at\n // its end, the incoming at its start (a timeline may end on a different\n // colour than it began; without one these are the scenes themselves).\n // A declared `fade` is the documented remedy — the jump is ramped over\n // `dur`, not cut — so it is not raised there (low tiers that play the\n // fade as a cut are covered by `fade-degrades-on-low-tier`).\n const lumaA = backgroundLuma(resolveTimelineAt(seq.segments[i]!.scene, seq.segments[i]!.duration ?? 0));\n const lumaB = backgroundLuma(resolveTimelineAt(seq.segments[i + 1]!.scene, 0));\n const delta = Math.abs(lumaA - lumaB);\n if (delta > 0.5 && tr?.type !== 'fade') {\n warnings.push({\n path: `segments[${i}]`,\n code: 'boundary-luminance-jump',\n message: `background luminance jumps ${delta.toFixed(2)} at boundary ${i}→${i + 1} — may flash on cut; declare transition: { type: 'fade', dur } on segments[${i}] to ramp it`,\n });\n }\n\n if (tr?.type === 'morph') {\n const sigA = structuralSignature(seq.segments[i]!.scene);\n const sigB = structuralSignature(seq.segments[i + 1]!.scene);\n if (sigA !== sigB) {\n warnings.push({\n path: `segments[${i}].transition`,\n code: 'morph-structural-mismatch',\n message: `segments ${i}→${i + 1} differ structurally: morph will fall back to cut`,\n });\n } else if (!seq.segments[i]!.scene.timeline && !seq.segments[i + 1]!.scene.timeline\n && morphNothingMorphable(seq.segments[i]!.scene, seq.segments[i + 1]!.scene, { textCrossfade: tr.text === 'crossfade' || tr.text === 'dip' })) {\n warnings.push({\n path: `segments[${i}].transition`,\n code: 'morph-nothing-morphable',\n message: `segments ${i}→${i + 1} differ only in values morph cannot interpolate (strings such as textBlock.text step on the first frame): the morph will look like a cut — fade text via colour or reveal.progress`,\n });\n }\n }\n }\n\n return warnings;\n}\n","/**\n * Shared luminance helpers.\n *\n * These live in their own module because both `perceive` (which ranks layers by\n * visual weight) and `advise` (which warns about layers that can't be seen)\n * need the same notion of \"how bright is this thing\" — and `perceive` already\n * imports `advise`, so the dependency can only run one way.\n */\n\nimport type { Entity } from './simulate';\nimport { isShapedSprite } from './shapes';\nimport { fieldRgb, fieldRgbAt, fieldSampleTime, hexToRgb255, rgb255Luma } from './field';\nimport type { FieldBackground, LayerSpec, SaverSpec } from './types';\n\n/**\n * The distinct 0..255 RGB colours a field background actually paints: one\n * per quantize level, not the raw `bands` declarations — `quantize` short of\n * `bands.length` never lands on every band (a `quantize: 2` field only ever\n * paints its two end levels, however many bands are declared). `quantize: 0`\n * (smooth) interpolates continuously through every band, so declaration\n * averaging is representative there.\n */\nfunction fieldRenderedRgbs(bg: FieldBackground): Array<readonly [number, number, number]> {\n const n = bg.bands.length;\n const q = Math.round(bg.quantize ?? n);\n if (q < 2) return bg.bands.map((hex) => hexToRgb255(hex));\n const out: Array<readonly [number, number, number]> = [];\n for (let level = 0; level < q; level++) out.push(fieldRgb((level + 0.5) / q, bg.bands, q));\n return out;\n}\n\n/** Perceptual luma (0..1) of a hex colour. */\nexport function hexLuma(hex: string): number {\n const h = hex.length === 4 ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex;\n const n = parseInt(h.slice(1), 16);\n if (Number.isNaN(n)) return 0.7;\n const r = ((n >> 16) & 255) / 255;\n const g = ((n >> 8) & 255) / 255;\n const b = (n & 255) / 255;\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\nexport function spriteLuma(layer: LayerSpec, e: Entity): number {\n const s = layer.sprite;\n if (isShapedSprite(s)) {\n return hexLuma(s.colors?.[e.colorIndex] ?? s.color);\n }\n if (s.kind === 'text' || s.kind === 'textBlock') return hexLuma(s.color ?? '#e6e8ef');\n return 0.75; // emoji: mid-bright approximation\n}\n\n/** The hex a given entity actually paints with, or null for glyph sprites. */\nexport function spriteHex(layer: LayerSpec, e: Entity): string | null {\n const s = layer.sprite;\n if (isShapedSprite(s)) {\n return s.colors?.[e.colorIndex] ?? s.color;\n }\n if (s.kind === 'text' || s.kind === 'textBlock') return s.color ?? '#e6e8ef';\n return null; // emoji carry their own palette\n}\n\n/**\n * Mean luma of the background plate a layer is drawn against. A gradient\n * averages its stops; a field averages the colours it actually renders\n * (`fieldRenderedRgbs` — one per quantize level, not every declared band).\n */\nexport function backgroundLuma(spec: SaverSpec): number {\n const bg = spec.background;\n if (!bg || bg.type === 'solid') return hexLuma(bg?.color ?? '#05050a');\n if (bg.type === 'field') {\n const rgbs = fieldRenderedRgbs(bg);\n return rgbs.reduce((s, c) => s + rgb255Luma(c), 0) / rgbs.length;\n }\n return bg.stops.reduce((s, st) => s + hexLuma(st.color), 0) / bg.stops.length;\n}\n\n/** Unpack a hex colour to 0..1 RGB. */\nexport function hexRgb(hex: string): { r: number; g: number; b: number } {\n const h = hex.length === 4 ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex;\n const n = parseInt(h.slice(1), 16);\n if (Number.isNaN(n)) return { r: 0.7, g: 0.7, b: 0.7 };\n return { r: ((n >> 16) & 255) / 255, g: ((n >> 8) & 255) / 255, b: (n & 255) / 255 };\n}\n\n/** Mean RGB of the background plate — a field averages the colours it\n * actually renders (`fieldRenderedRgbs`), like `backgroundLuma`. */\nexport function backgroundRgb(spec: SaverSpec): { r: number; g: number; b: number } {\n const bg = spec.background;\n if (!bg || bg.type === 'solid') return hexRgb(bg?.color ?? '#05050a');\n if (bg.type === 'field') {\n const rgbs = fieldRenderedRgbs(bg);\n const acc = rgbs.reduce((s, c) => ({ r: s.r + c[0], g: s.g + c[1], b: s.b + c[2] }), { r: 0, g: 0, b: 0 });\n return { r: acc.r / rgbs.length / 255, g: acc.g / rgbs.length / 255, b: acc.b / rgbs.length / 255 };\n }\n const colours = bg.stops.map((st) => st.color);\n const acc = colours.reduce(\n (s, hex) => {\n const c = hexRgb(hex);\n return { r: s.r + c.r, g: s.g + c.g, b: s.b + c.b };\n },\n { r: 0, g: 0, b: 0 },\n );\n const n = colours.length || 1;\n return { r: acc.r / n, g: acc.g / n, b: acc.b / n };\n}\n\n/**\n * How far a layer's colour separates from its background, ignoring alpha and\n * geometry — purely \"can this be told apart from the plate behind it\".\n *\n * **This is a colour distance, not a luminance one, and that distinction is\n * load-bearing.** Equal-luminance/contrasting-hue is a real technique, not a\n * mistake: a Seurat-style field of golden `#e8c060` dots over a pale grey-blue\n * plate differs by 0.013 in luma and is perfectly visible, because the\n * separation lives entirely in hue. A luma-only test flags exactly the\n * pointillist screens it should leave alone.\n *\n * Additive blends are a different question again. Under `lighter`/`screen` the\n * sprite ADDS light, so a colour matching the background is still visible (it\n * doubles it); what makes such a layer vanish is having little light to add —\n * which genuinely is a luminance question.\n *\n * Alpha and radius are deliberately excluded — `invisible-layer` already owns\n * that axis, and the schema actively recommends faint atmospheric layers\n * (\"80 tiny soft circles at alpha 0.2\"), which must not be flagged here.\n */\nexport function colourSeparation(\n layer: LayerSpec,\n sprite: { rgb: { r: number; g: number; b: number }; luma: number },\n bg: { rgb: { r: number; g: number; b: number }; luma: number },\n): number {\n if (layer.blend === 'lighter' || layer.blend === 'screen') return sprite.luma;\n const dr = sprite.rgb.r - bg.rgb.r;\n const dg = sprite.rgb.g - bg.rgb.g;\n const db = sprite.rgb.b - bg.rgb.b;\n // Euclidean in RGB, normalised so 1 = black-to-white. Crude next to CIEDE2000\n // but it separates hue from value, which is the whole point here.\n return Math.sqrt((dr * dr + dg * dg + db * db) / 3);\n}\n\n// ---------------------------------------------------------------------------\n// Legibility — WCAG 2.x relative luminance and the ratio between two colours.\n// Used only by layers that declare `role: 'read'`; `hexLuma` above stays the\n// perceptual (gamma-space) weight the perception grid is built on.\n// ---------------------------------------------------------------------------\n\nexport type Rgb = { r: number; g: number; b: number };\n\n/** sRGB channel (0..1) → linear light, per WCAG 2.x. */\nfunction srgbToLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n}\n\n/** WCAG relative luminance (0..1, linear light) of a 0..1 RGB triple. */\nexport function relativeLuminance(rgb: Rgb): number {\n return 0.2126 * srgbToLinear(rgb.r) + 0.7152 * srgbToLinear(rgb.g) + 0.0722 * srgbToLinear(rgb.b);\n}\n\n/**\n * WCAG legibility ratio (1..21) between two colours, order-free:\n * `(L_lighter + 0.05) / (L_darker + 0.05)`. 4.5 is the AA floor for body\n * text; 3 for large text.\n */\nexport function legibilityRatio(a: Rgb, b: Rgb): number {\n const la = relativeLuminance(a);\n const lb = relativeLuminance(b);\n const hi = Math.max(la, lb);\n const lo = Math.min(la, lb);\n return (hi + 0.05) / (lo + 0.05);\n}\n\n/**\n * The background colour under one point, `yPx` down a `h`-tall viewport:\n * a solid is itself; a gradient is its stops interpolated in sRGB at their\n * rest positions (`drift` moves them ±`amount` over time — the rest position\n * is the mean); a `band` wins where the point falls inside it. `unit` is the\n * spec's dimensional unit (1 for `px`, `min(w,h)` otherwise), for the band.\n * A field is sampled at the point at scene time `t` (bucketed like the\n * renderer and `luminanceGrid`, default 0 — a drifting field's rest) when\n * `xPx`/`w` are given, else it reads as its mean band, like the gradient.\n * `seed` is the effective seed the caller is perceiving with (`opts.seed ??\n * spec.seed`) — pass it through rather than defaulting to `spec.seed` here,\n * or a caller perceiving a specific seed samples the wrong field.\n */\nexport function backgroundRgbAt(spec: SaverSpec, yPx: number, h: number, unit: number, xPx?: number, w?: number, seed?: number, t = 0): Rgb {\n const bg = spec.background;\n if (!bg || bg.type === 'solid') return hexRgb(bg?.color ?? '#05050a');\n if (bg.type === 'field') {\n if (xPx === undefined || w === undefined) return backgroundRgb(spec);\n const short = Math.max(1, Math.min(w, h));\n const ft = fieldSampleTime(bg, t);\n const c = fieldRgbAt(xPx / short, yPx / short, ft, bg, seed ?? spec.seed ?? 42);\n return { r: c[0] / 255, g: c[1] / 255, b: c[2] / 255 };\n }\n if (bg.band) {\n const bh = bg.band.height * unit;\n if (yPx >= h - bh) return hexRgb(bg.band.color);\n }\n const stops = [...bg.stops].sort((a, b) => a.at - b.at);\n const y = h > 0 ? Math.max(0, Math.min(1, yPx / h)) : 0;\n const first = stops[0]!;\n const last = stops[stops.length - 1]!;\n if (y <= first.at) return hexRgb(first.color);\n if (y >= last.at) return hexRgb(last.color);\n for (let i = 1; i < stops.length; i++) {\n const a = stops[i - 1]!;\n const b = stops[i]!;\n if (y > b.at) continue;\n const span = b.at - a.at;\n const k = span > 0 ? (y - a.at) / span : 1;\n const ca = hexRgb(a.color);\n const cb = hexRgb(b.color);\n return { r: ca.r + (cb.r - ca.r) * k, g: ca.g + (cb.g - ca.g) * k, b: ca.b + (cb.b - ca.b) * k };\n }\n return hexRgb(last.color);\n}\n\n/**\n * Standard alpha (source-over) composite of `colour` at `alpha` over `ground` —\n * what a translucent or faint layer actually paints, rather than its\n * configured colour at full strength. Used so a `role: 'read'` text at low\n * alpha (or a `textBlock` with `opacity < 1`) is measured for what it really\n * puts on screen, not the undiluted ink colour.\n */\nexport function sourceOverPlate(ground: Rgb, colour: Rgb, alpha: number): Rgb {\n return {\n r: ground.r + (colour.r - ground.r) * alpha,\n g: ground.g + (colour.g - ground.g) * alpha,\n b: ground.b + (colour.b - ground.b) * alpha,\n };\n}\n\n/**\n * The plate an additive layer leaves behind it at full strength: `colour ×\n * alpha` added to the ground (`lighter`), or screened onto it (`screen`).\n * Per channel, clamped to 1 — the same arithmetic the canvas applies, minus\n * the soft falloff (the centre of a soft disc is at full strength).\n */\nexport function additivePlate(ground: Rgb, colour: Rgb, alpha: number, blend: 'lighter' | 'screen'): Rgb {\n const mix = (g: number, c: number): number => {\n const v = c * alpha;\n return blend === 'lighter' ? Math.min(1, g + v) : 1 - (1 - g) * (1 - v);\n };\n return { r: mix(ground.r, colour.r), g: mix(ground.g, colour.g), b: mix(ground.b, colour.b) };\n}\n","/**\n * Layer cohesion — does a layer read as ONE form, or as N separate marks?\n *\n * The gap this closes: every other perception channel reports a heavily\n * overlapping layer identically whether its sprites merge into a silhouette or\n * stay legible as individual discs. Luminance, coverage, dominance and the\n * braille map are all blind to it, because they measure ink, not edges. An\n * agent drawing a *shape* out of sprites therefore cannot tell success from\n * failure without publishing and looking at real pixels.\n *\n * Two independent facts decide it, so both are reported:\n *\n * - `overlap` — geometry. What fraction of a typical entity's outline is buried\n * inside a sibling. Scattered fields sit near 0; a deliberate mass sits high.\n * - `seamless` — paint. Whether an overlap between two of this layer's entities\n * paints as an invisible join. Only a hard-edged, fully opaque, single-colour,\n * un-blended layer merges; anything else shows every internal edge.\n *\n * Both are analytic, deterministic and renderer-free, like the rest of\n * `perceive.ts`.\n */\n\nimport { polygonArea, polygonPoints } from './shapes';\nimport { lifeAlphaAt, positionAt, rotationAt, sizeAt, type Entity } from './simulate';\nimport type { LayerSpec } from './types';\n\n/**\n * Above this mean covered-outline fraction a layer is treated as *trying* to be\n * one form rather than a field of marks.\n *\n * Calibrated against the shipped examples rather than picked. Measured across\n * all 42 fillable layers in `src/examples/`, the particle fields top out at\n * 0.154 (`facets/planes`; snowfall, lanterns and constellation are all 0.000,\n * `comets/stars` 0.001, `aquarium` 0.015, `procession/lanterns` 0.087), while\n * a layer authored as a silhouette — circles packed several times over their\n * own area, the idiom that draws a wave or a mountain — measures 0.79 to 0.85.\n * `aurora`'s wander curtains are the one shipped layer in the upper band, at\n * 0.892, and they are a deliberate overlapping wash. Nothing sits between\n * 0.154 and 0.786, so the exact threshold is not delicate.\n */\nconst MERGE_FLOOR = 0.35;\n\n/**\n * Below this base opacity a heavily overlapping layer is an atmospheric wash by\n * intent — the playbook's own advice is a field of soft circles at alpha ~0.2 —\n * and its visible internal edges are the effect, not a defect. The advisory\n * stays silent there; the numbers are still reported.\n */\nconst WASH_ALPHA_MAX = 0.45;\n\n/**\n * Sample time for a spec-level cohesion read, matching `perceiveScene`'s own\n * default so the advisory and the reported numbers agree on the usual call.\n * Past all typical `life.enter` staging; `grow` has had time to breathe.\n */\nexport const COHESION_T = 5000;\n\n/** Outline samples per entity. 24 resolves a half-covered circle to ~4 %. */\nconst OUTLINE_SAMPLES = 24;\n\n/**\n * Cap on the entities whose outlines are traced. Above this the measured set is\n * a deterministic stride through the layer (every k-th entity); coverage is\n * still tested against *every* sibling, so the estimate stays unbiased.\n */\nconst MAX_TRACED = 240;\n\n/** What a layer will read as on the wall. */\nexport type CohesionRead =\n /** Entities merge into a single silhouette — the layer draws a shape. */\n | 'mass'\n /** Entities overlap heavily but every overlap paints a visible edge. */\n | 'seamed'\n /** Entities stand alone — a field of marks, which most layers are. */\n | 'marks';\n\nexport interface LayerCohesion {\n layerIndex: number;\n key: string | undefined;\n /**\n * Mean fraction of an entity's outline covered by a same-layer sibling, 0..1.\n * `null` for sprite kinds where a merged silhouette is not a meaningful idea\n * (lines, glyphs and text: ring, streak, stroke, bar, emoji, text, textBlock).\n */\n overlap: number | null;\n /** Do this layer's overlaps paint as invisible joins? */\n seamless: boolean;\n /** Why not, when not — the field to act on. `null` when seamless. */\n seamCause: string | null;\n /** The verdict. `null` when `overlap` is null. */\n reads: CohesionRead | null;\n}\n\n// ---------------------------------------------------------------------------\n// Geometry\n// ---------------------------------------------------------------------------\n\ninterface Shape {\n cx: number;\n cy: number;\n /** Bounding radius, for the pairwise prefilter. */\n br: number;\n /** Enclosed area in px². Zero means the sprite paints nothing — collinear\n * polygon vertices reach here with a nonzero bounding radius. */\n area: number;\n contains(x: number, y: number): boolean;\n outline(n: number): Array<{ x: number; y: number }>;\n}\n\n/**\n * Outline samples are stepped this far INSIDE their own shape, as a fraction of\n * its bounding radius, before being tested. The question asked is then \"is the\n * ink just inside my edge also covered?\" rather than \"is a point exactly on my\n * edge inside a sibling?\".\n *\n * Exact-boundary tests are degenerate in both directions: coincident circles\n * sample every point exactly on the sibling's rim, and a polygon point lying on\n * a horizontal edge fails the ray-cast's `(a.y > y) !== (b.y > y)` test — two\n * flat rects sharing a y therefore reported their buried long edges as exposed.\n *\n * The step follows the edge's inward NORMAL, not the direction of the entity\n * centre: a concave polygon can have its centre outside its own filled area, so\n * a centre-directed nudge would push samples across the concavity and out of\n * the shape. Relative, so it holds at any viewport scale, and four orders of\n * magnitude below a pixel for any real sprite.\n */\nconst EDGE_INSET = 1e-4;\n\nfunction circleShape(cx: number, cy: number, r: number): Shape {\n return {\n cx, cy, br: r, area: Math.PI * r * r,\n contains: (x, y) => (x - cx) * (x - cx) + (y - cy) * (y - cy) < r * r,\n outline: (n) => Array.from({ length: n }, (_, i) => {\n const a = (i / n) * Math.PI * 2;\n const inner = r * (1 - EDGE_INSET); // inward normal of a circle is its radius\n return { x: cx + inner * Math.cos(a), y: cy + inner * Math.sin(a) };\n }),\n };\n}\n\n/** A convex or concave polygon given by absolute vertices. */\nfunction polyShape(cx: number, cy: number, raw: Array<{ x: number; y: number }>): Shape | null {\n // Drop consecutive coincident vertices up front. A zero-length edge has no\n // normal to step along, and leaving one in would emit a sample sitting\n // exactly on the boundary — the degeneracy EDGE_INSET exists to avoid.\n const abs = raw.filter((p, i) => {\n const q = raw[(i + 1) % raw.length]!;\n return Math.hypot(q.x - p.x, q.y - p.y) > 0;\n });\n // Fewer than three distinct vertices encloses no area — the renderer fills\n // nothing, so there is no silhouette to ask about.\n if (abs.length < 3) return null;\n\n let br = 0;\n for (const p of abs) br = Math.max(br, Math.hypot(p.x - cx, p.y - cy));\n const inside = (x: number, y: number): boolean => {\n let hit = false;\n for (let i = 0, j = abs.length - 1; i < abs.length; j = i++) {\n const a = abs[i]!;\n const b = abs[j]!;\n if ((a.y > y) !== (b.y > y) && x < ((b.x - a.x) * (y - a.y)) / (b.y - a.y) + a.x) hit = !hit;\n }\n return hit;\n };\n const seg = abs.map((p, i) => {\n const q = abs[(i + 1) % abs.length]!;\n return Math.hypot(q.x - p.x, q.y - p.y);\n });\n const perimeter = seg.reduce((a, b) => a + b, 0);\n // A shape thinner than the nominal inset would have BOTH normal candidates\n // overshoot it, so the step is bounded by the shortest edge as well as by\n // the bounding radius.\n const shortest = Math.min(...seg);\n const step = Math.min(br * EDGE_INSET, shortest * 0.25);\n const area = polygonArea(abs);\n if (!(area > 0)) return null; // collinear vertices enclose nothing\n return {\n cx, cy, br, area,\n contains: inside,\n /**\n * `n` points spread along the perimeter by ARC LENGTH, not one share per\n * edge — a long skinny rectangle has two edges carrying almost all of its\n * perimeter, and an equal-per-edge split would report a fully buried long\n * side as only a quarter covered. Each point is then stepped along its\n * edge's inward normal, whichever of the two candidates lands inside.\n */\n outline: (n) => {\n if (!(perimeter > 0)) return [];\n const out: Array<{ x: number; y: number }> = [];\n for (let i = 0; i < n; i++) {\n let d = (i / n) * perimeter;\n let k = 0;\n while (k < seg.length - 1 && d > seg[k]!) { d -= seg[k]!; k++; }\n const a = abs[k]!;\n const b = abs[(k + 1) % abs.length]!;\n const len = seg[k]!;\n const f = d / len;\n const px = a.x + (b.x - a.x) * f;\n const py = a.y + (b.y - a.y) * f;\n const ux = (b.x - a.x) / len;\n const uy = (b.y - a.y) / len;\n // Back off until a candidate lands inside: a sliver thinner than even\n // the bounded step still gets the best sample available rather than\n // one outside its own shape.\n // A sample that cannot be placed strictly inside is DROPPED rather than\n // emitted on the boundary: an exact-edge point is the degeneracy the\n // inset exists to remove, and reporting it as exposed would be a guess.\n // The caller measures the samples it got, so an unmeasurable sliver\n // reports no outline instead of a wrong one.\n for (let t = step; t > 0; t /= 8) {\n const qx1 = px - uy * t;\n const qy1 = py + ux * t;\n if (inside(qx1, qy1)) { out.push({ x: qx1, y: qy1 }); break; }\n const qx2 = px + uy * t;\n const qy2 = py - ux * t;\n if (inside(qx2, qy2)) { out.push({ x: qx2, y: qy2 }); break; }\n if (t < step * 1e-3) break;\n }\n }\n return out;\n },\n };\n}\n\nfunction rectShape(cx: number, cy: number, halfW: number, halfH: number, rot: number): Shape | null {\n const cos = Math.cos(rot);\n const sin = Math.sin(rot);\n const corner = (lx: number, ly: number) => ({ x: cx + lx * cos - ly * sin, y: cy + lx * sin + ly * cos });\n return polyShape(cx, cy, [\n corner(-halfW, -halfH), corner(halfW, -halfH), corner(halfW, halfH), corner(-halfW, halfH),\n ]);\n}\n\nfunction polygonShape(cx: number, cy: number, pts: Array<{ x: number; y: number }>, rot: number): Shape | null {\n const cos = Math.cos(rot);\n const sin = Math.sin(rot);\n return polyShape(cx, cy, pts.map((p) => ({ x: cx + p.x * cos - p.y * sin, y: cy + p.x * sin + p.y * cos })));\n}\n\n/** The shape an entity paints at `t`, or null for kinds with no fillable area. */\nfunction shapeOf(layer: LayerSpec, e: Entity, t: number, w: number, h: number): Shape | null {\n const s = layer.sprite;\n if (s.kind !== 'circle' && s.kind !== 'rect' && s.kind !== 'polygon') return null;\n const p = positionAt(e, t, w, h);\n const sz = sizeAt(e, t);\n if (!(sz > 0)) return null;\n if (s.kind === 'circle') return circleShape(p.x, p.y, sz / 2);\n const rot = rotationAt(e, t);\n if (s.kind === 'rect') {\n const h2 = e.size2 !== undefined ? e.size2 * (e.size > 0 ? sz / e.size : 1) : sz;\n return rectShape(p.x, p.y, sz / 2, h2 / 2, rot);\n }\n return polygonShape(p.x, p.y, polygonPoints(s, sz / 2), rot);\n}\n\n// ---------------------------------------------------------------------------\n// Paint: will an overlap show?\n// ---------------------------------------------------------------------------\n\n/**\n * Why this layer's overlaps paint a visible edge, or null when they vanish.\n *\n * Opacity is judged over the whole timeline, not this instant: a layer that\n * breathes with `pulse` is translucent at some point in every cycle, so its\n * seams appear even if the sampled frame happens to catch it at full alpha.\n */\nexport function seamCauseOf(layer: LayerSpec): string | null {\n const s = layer.sprite;\n if ((s.kind === 'circle' || s.kind === 'polygon') && s.soft) {\n return 'sprite.soft — radial falloff never forms a hard union';\n }\n if (s.kind === 'rect' && s.feather) {\n return 'rect.feather — a feathered edge never forms a hard union';\n }\n if (layer.blend) {\n return `blend: ${layer.blend} — overlaps composite instead of covering`;\n }\n const [lo, hi] = layer.alpha ?? [1, 1];\n if (lo < 1 || hi < 1) {\n return `alpha ${lo === hi ? lo : `${lo}..${hi}`} — every overlap paints a darker patch`;\n }\n if (layer.pulse && layer.pulse.amp > 0) {\n return 'pulse — the layer is translucent for part of every cycle';\n }\n // Only palette entries the seeded pick can actually reach count: a\n // `colorWeights` entry of 0 means that colour is never drawn, so it cannot\n // put a seam between two neighbours.\n const palette = 'colors' in s && Array.isArray(s.colors) ? s.colors : null;\n const weights = 'colorWeights' in s && Array.isArray(s.colorWeights) ? s.colorWeights : null;\n if (palette) {\n const aligned = weights !== null && weights.length === palette.length;\n const reachable = new Set(palette.filter((_, i) => !aligned || (weights![i] ?? 0) > 0));\n if (reachable.size > 1) {\n return `sprite.colors has ${reachable.size} reachable colours — neighbours of unlike colour show their join`;\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Public\n// ---------------------------------------------------------------------------\n\n/**\n * Per-layer cohesion for an already-built scene. Takes entities rather than a\n * spec so `perceiveScene` and `adviseSpec` can each pass the scene they already\n * built instead of building a third one.\n */\nexport function cohesionOf(\n layers: Array<{ layer: LayerSpec; entities: Entity[] }>,\n t: number,\n w: number,\n h: number,\n): LayerCohesion[] {\n return layers.map(({ layer, entities }, layerIndex) => {\n const seamCause = seamCauseOf(layer);\n const base: Omit<LayerCohesion, 'overlap' | 'reads'> = {\n layerIndex,\n key: layer.key,\n seamless: seamCause === null,\n seamCause,\n };\n\n // A layer staged out by `life` paints nothing at this instant, so asking\n // what it reads as has no answer — same as an unsupported sprite kind.\n if (lifeAlphaAt(layer.life, t) <= 0) return { ...base, overlap: null, reads: null };\n\n const shapes: Array<Shape | null> = entities.map((e) => shapeOf(layer, e, t, w, h));\n // A sprite that fills nothing is not a sibling: it cannot cover a\n // neighbour's outline and it must not make a lone sprite look like a pair.\n const solid = shapes.filter((x): x is Shape => x !== null && x.area > 0);\n // A single entity has no sibling to merge with, and unsupported kinds have\n // no fillable outline — in both cases the question does not apply.\n if (solid.length < 2) return { ...base, overlap: null, reads: null };\n\n const stride = Math.max(1, Math.ceil(solid.length / MAX_TRACED));\n let covered = 0;\n let traced = 0;\n for (let i = 0; i < solid.length; i += stride) {\n const self = solid[i]!;\n const pts = self.outline(OUTLINE_SAMPLES);\n if (pts.length === 0) continue; // no measurable outline; not 'exposed'\n let hit = 0;\n for (const p of pts) {\n for (let j = 0; j < solid.length; j++) {\n if (j === i) continue;\n const other = solid[j]!;\n const dx = p.x - other.cx;\n const dy = p.y - other.cy;\n if (dx * dx + dy * dy > other.br * other.br) continue; // cheap reject\n if (other.contains(p.x, p.y)) { hit++; break; }\n }\n }\n covered += hit / pts.length;\n traced++;\n }\n\n if (traced === 0) return { ...base, overlap: null, reads: null };\n const overlap = Number((covered / traced).toFixed(4));\n const reads: CohesionRead = overlap < MERGE_FLOOR ? 'marks' : seamCause === null ? 'mass' : 'seamed';\n return { ...base, overlap, reads };\n });\n}\n\n/**\n * True when a `seamed` layer is worth warning about: dense enough to be\n * deliberate, and opaque enough that it cannot be an atmospheric wash. Keeps\n * the advisory off the soft low-alpha glow fields the playbook recommends.\n */\nexport function seamsWorthWarning(layer: LayerSpec, c: LayerCohesion, entityCount: number): boolean {\n if (c.reads !== 'seamed' || entityCount < 6) return false;\n const [lo, hi] = layer.alpha ?? [1, 1];\n if ((lo + hi) / 2 < WASH_ALPHA_MAX) return false;\n return layer.blend !== 'lighter' && layer.blend !== 'screen';\n}\n","/**\n * Perception tools for non-vision agents. Everything here is computed\n * ANALYTICALLY from the spec — positions, sizes, and alphas are pure functions\n * of (seed, t), so no canvas or renderer is involved: these run in Node, are\n * fully deterministic, and are cheap enough to call in an authoring loop.\n *\n * The design premise: a text model doesn't need mimicked eyes, it needs vision\n * translated into modalities it is already strong in —\n * - a compact PICTURE it can actually read (braille luminance map: each Unicode\n * braille char encodes a 2×4 dot cell, ~8× ASCII resolution per token),\n * - 1D structure (row/column luminance profiles — the skeleton of a composition),\n * - OBJECT-level ranking (dominance: where does the eye go),\n * - RELATIVE judgement (diffScenes: \"is B better than A\" beats \"is A good\"),\n * - MOTION as numbers (per-layer displacement stats).\n */\nimport { createRng } from '@idle-screens/core';\nimport { adviseSpec } from './advise';\nimport { cohesionOf, type LayerCohesion } from './cohesion';\nimport { backgroundLuma, backgroundRgb, hexLuma, hexRgb, spriteHex, spriteLuma } from './luma';\nimport { fieldRgbAt, fieldSampleTime, rgb255Luma } from './field';\nimport { barBox, barFraction, pathLength, polygonArea, polygonFill, polygonPoints, strokeSamples, strokeTaper, strokeWidthPx, type PolygonSprite } from './shapes';\nimport {\n alphaAt,\n breakTextBlock,\n buildEntities,\n headingAt,\n lifeAlphaAt,\n linkEdges,\n positionAt,\n revealState,\n rotationAt,\n sizeAt,\n textBlockAnchorOffset,\n textMetricsClassFor,\n entityScales,\n type Entity,\n} from './simulate';\nimport { bedRenderSeed, normalizeSeed, resolveSegment, segmentRenderSeed } from './sequence';\nimport { paintMap, paintOpacity, paintSize, type Pt } from './paint';\nimport { resolveTimelineAt } from './timeline';\nimport { LIMITS, type IdleSequence, type LayerSpec, type SaverSpec } from './types';\n\n// ---------------------------------------------------------------------------\n// Calibration constants\n//\n// The two knobs that tune how closely this analytical model matches the real\n// canvas. Kept together at module level so a calibration pass has one place to\n// look — neither is a per-entity detail.\n// ---------------------------------------------------------------------------\n\n/**\n * How far an additive glow blooms past its radius, as a multiple of that radius.\n * A soft circle drawn with `lighter`/`screen` spreads well beyond its geometric\n * edge on the real canvas (shadowBlur halos, stacked soft discs), so a\n * hard-edged analytical disc badly under-reports coverage for glow-heavy scenes.\n *\n * First pass, tuned by intuition rather than measurement: it fixes the direction\n * and rough magnitude, not the exact number. A playground-calibrated value is\n * future work (docs/future-ideas.md G1).\n */\nconst GLOW_SPREAD = 2.4;\n\n/**\n * How much more visually prominent line-like ink is than the same area of fill.\n * Rings, streaks and link lines catch the eye far more than their pixel area\n * implies, so weighting dominance by raw area alone makes a bright ring lose to\n * a dim disc. Also a first-pass estimate.\n */\nconst LINE_SALIENCE = 3.5;\n\n/**\n * How many past-frame samples model the `ghosting` smear. The live renderer\n * composites every 60 fps frame with persistence `g`, so ink from m frames ago\n * survives at weight g^m; the analytic model samples that decay at GHOST_TAPS\n * points across the visible window (until weight falls below 1/255, capped at\n * LIMITS.maxGhostReplayFrames — the same bound as the renderer's seek warm-up\n * replay), each tap carrying its bracket's summed weight. More taps sharpen the\n * smear's shape; the total energy is set by `g`, not by this constant.\n */\nconst GHOST_TAPS = 12;\n\n/**\n * A polygon whose bounding diameter spans at least this many grid cells is\n * rasterized by its real outline; below it, it splats as its circumscribed\n * disc weighted by `polygonFill`, exactly as before. The two do NOT agree at\n * the boundary: the disc path lights every cell whose centre is within half a\n * cell of the rim at full weight, so it over-reports a small glyph's ink (12\n * hexagons just under 3 cells: mean deviation 0.022 against an analytic 0.014;\n * the outline gives 0.013). Circles carry the same dilation, and keeping it\n * for small polygons keeps a hexagon and a disc of one size reading alike.\n * Above the threshold the disc is materially wrong for any non-round glyph — a\n * full-width flat band reads as a circle, a ridge silhouette as a dome.\n */\nconst POLYGON_OUTLINE_CELLS = 3;\n\n/** Sub-scanlines per grid row when rasterizing a polygon outline. */\nconst POLYGON_SCANLINES = 4;\n\n// ---------------------------------------------------------------------------\n// Shared scene construction (mirrors describeScene/adviseSpec)\n// ---------------------------------------------------------------------------\n\ninterface BuiltScene {\n w: number;\n h: number;\n scale: number;\n /** Normalized exactly like `SpecInstance.seed` (0 is falsy, so it lands on 1). */\n seed: number;\n layers: Array<{ layer: LayerSpec; entities: Entity[] }>;\n byKey: Map<string, Entity[]>;\n /** Entities of layers with a paint `transform` — null (every scene without one) skips the lookup. */\n transforms: Map<Entity, (p: Pt) => Pt> | null;\n}\n\n\nexport interface PerceiveOptions {\n viewport?: { width: number; height: number };\n seed?: number;\n /** Sample time in ms. Default 5000 (past all typical life.enter staging). */\n t?: number;\n}\n\nfunction buildScene(spec: SaverSpec, opts: PerceiveOptions): BuiltScene {\n const { width: w, height: h } = opts.viewport ?? { width: 1920, height: 1080 };\n // Normalized exactly like `SpecInstance.seed` — a valid `seed: 0` lands on 1,\n // matching the renderer, and this same normalized value is reused for field\n // background sampling (see `luminanceGrid`) so both agree on one seed.\n const seed = normalizeSeed(opts.seed ?? spec.seed ?? 42);\n const { scale, countScale } = entityScales(spec, w, h);\n const rng = createRng(seed);\n const layers = spec.layers.map((layer) => ({ layer, entities: buildEntities(layer, rng, w, h, scale, countScale) }));\n const byKey = new Map<string, Entity[]>();\n for (const { layer, entities } of layers) if (layer.key) byKey.set(layer.key, entities);\n let transforms: Map<Entity, (p: Pt) => Pt> | null = null;\n for (const { layer, entities } of layers) {\n // Layer transform (about its origin) wrapped by its group's — see paint.ts.\n const map = paintMap(spec, layer, w, h, scale);\n if (!map) continue;\n transforms ??= new Map();\n for (const e of entities) transforms.set(e, map);\n }\n return { w, h, scale, seed, layers, byKey, transforms };\n}\n\n/** Position with layer-parented-orbit resolution (matches the renderer). */\nfunction posOf(scene: BuiltScene, e: Entity, t: number): { x: number; y: number } {\n const p = positionAt(e, t, scene.w, scene.h);\n if (e.orbitParent) {\n const parent = scene.byKey.get(e.orbitParent)?.[0];\n if (parent) {\n const pp = positionAt(parent, t, scene.w, scene.h);\n p.x += pp.x;\n p.y += pp.y;\n }\n }\n const map = scene.transforms?.get(e);\n return map ? map(p) : p;\n}\n\n/**\n * Text bounding box + anchor, matching the renderer's font rule: a CSS\n * shorthand containing a px size overrides the seeded per-entity size.\n * Returns the box CENTRE (accounting for align/baseline) and half-extents.\n */\nfunction textBox(\n s: Extract<LayerSpec['sprite'], { kind: 'text' }>,\n e: Entity,\n p: { x: number; y: number },\n): { cx: number; cy: number; halfX: number; halfY: number } {\n const m = s.font ? /(\\d+(?:\\.\\d+)?)px/.exec(s.font) : null;\n const fh = m ? Number(m[1]) : e.size;\n const str = s.strings[e.spriteIndex] ?? s.strings[0] ?? '';\n const fw = Math.max(fh, 0.62 * fh * Math.min(str.length, 48));\n const align = s.align ?? 'center';\n const baseline = s.baseline ?? 'middle';\n return {\n cx: align === 'left' ? p.x + fw / 2 : align === 'right' ? p.x - fw / 2 : p.x,\n cy: baseline === 'top' ? p.y + fh * 0.6 : baseline === 'bottom' ? p.y - fh * 0.6 : p.y,\n halfX: fw / 2,\n halfY: fh * 0.6,\n };\n}\n\nfunction textBlockBox(\n s: Extract<LayerSpec['sprite'], { kind: 'textBlock' }>,\n _e: Entity,\n p: { x: number; y: number },\n w: number,\n h: number,\n): { cx: number; cy: number; halfX: number; halfY: number } {\n const unitScale = Math.min(w, h);\n const fsPx = s.fontSize * unitScale;\n const lh = (s.lineHeight ?? 1.4) * fsPx;\n const maxWPx = s.maxWidth * unitScale;\n const maxWEm = maxWPx / fsPx;\n const lines = breakTextBlock(s.text, maxWEm, textMetricsClassFor(s.font));\n const totalH = lines.length * lh;\n const maxLineW = lines.reduce((m, l) => Math.max(m, l.widthEm), 0) * fsPx;\n const align = s.align ?? 'left';\n const cx = align === 'center' ? p.x + maxWPx / 2\n : align === 'right' ? p.x + maxWPx - maxLineW / 2\n : p.x + maxLineW / 2;\n // Anchor moves the whole block the same way the renderer does (0,0 when absent).\n const { dx, dy } = textBlockAnchorOffset(s, maxWPx, maxLineW, totalH);\n return {\n cx: cx + dx,\n cy: p.y + totalH / 2 + dy,\n halfX: maxLineW / 2,\n halfY: totalH / 2,\n };\n}\n\n/**\n * Effective reveal fraction of a textBlock at time t (1 = fully shown).\n * Mirrors the renderer's `revealState` exactly — same line breaking, same\n * grapheme counting — so the perceived ink matches the painted ink.\n */\nfunction textBlockRevealFraction(\n s: Extract<LayerSpec['sprite'], { kind: 'textBlock' }>,\n w: number,\n h: number,\n t: number,\n): number {\n if (!s.reveal) return 1;\n const unitScale = Math.min(w, h);\n const maxWEm = (s.maxWidth * unitScale) / (s.fontSize * unitScale);\n const lines = breakTextBlock(s.text, maxWEm, textMetricsClassFor(s.font));\n const rs = revealState(lines, s.reveal, t);\n if (rs.glyphAlphas) {\n // glyphFade paints partial-alpha glyphs, so the ink fraction is the mean\n // glyph alpha, not the frontier progress.\n let sum = 0;\n let n = 0;\n for (const line of rs.glyphAlphas) for (const a of line) { sum += a; n++; }\n return n > 0 ? sum / n : 1;\n }\n return rs.progress;\n}\n\n// ---------------------------------------------------------------------------\n// Polygon outline rasterization\n// ---------------------------------------------------------------------------\n\n/**\n * Fraction of each cell in the window [c0..c1]×[r0..r1] that a polygon fills,\n * row-major within the window. Scanline with the canvas's own `nonzero` rule:\n * each sub-scanline collects signed edge crossings (half-open in y, so a\n * horizontal edge or a vertex on the line is counted once), and the spans where\n * the winding is nonzero are split exactly across the cells they cross. So\n * coverage is exact horizontally and POLYGON_SCANLINES-sampled vertically, and\n * a self-intersecting outline fills both lobes, as `ctx.fill()` does.\n */\nfunction polygonCellCoverage(\n pts: Array<{ x: number; y: number }>,\n cellW: number,\n cellH: number,\n c0: number,\n c1: number,\n r0: number,\n r1: number,\n): Float64Array {\n const nc = c1 - c0 + 1;\n const cov = new Float64Array(nc * (r1 - r0 + 1));\n const xMin = c0 * cellW;\n const xMax = (c1 + 1) * cellW;\n const share = 1 / POLYGON_SCANLINES;\n const hits: Array<{ x: number; dir: number }> = [];\n const addSpan = (row: number, xa: number, xb: number): void => {\n const a = Math.max(xMin, xa);\n const b = Math.min(xMax, xb);\n if (!(b > a)) return;\n const first = Math.max(c0, Math.floor(a / cellW));\n const last = Math.min(c1, Math.floor(b / cellW));\n for (let c = first; c <= last; c++) {\n const len = Math.min(b, (c + 1) * cellW) - Math.max(a, c * cellW);\n if (len > 0) cov[row * nc + (c - c0)]! += (len / cellW) * share;\n }\n };\n for (let r = r0; r <= r1; r++) {\n for (let k = 0; k < POLYGON_SCANLINES; k++) {\n const y = (r + (k + 0.5) / POLYGON_SCANLINES) * cellH;\n hits.length = 0;\n for (let i = 0; i < pts.length; i++) {\n const p = pts[i]!;\n const q = pts[(i + 1) % pts.length]!;\n const down = p.y <= y && q.y > y;\n if (!down && !(q.y <= y && p.y > y)) continue;\n hits.push({ x: p.x + ((y - p.y) / (q.y - p.y)) * (q.x - p.x), dir: down ? 1 : -1 });\n }\n if (hits.length < 2) continue;\n hits.sort((m, n) => m.x - n.x);\n let wind = 0;\n let start = 0;\n for (const hit of hits) {\n const before = wind;\n wind += hit.dir;\n if (before === 0 && wind !== 0) start = hit.x;\n else if (before !== 0 && wind === 0) addSpan(r - r0, start, hit.x);\n }\n }\n }\n return cov;\n}\n\n/** Distance from (x, y) to the nearest edge of a closed outline. */\nfunction distanceToOutline(pts: Array<{ x: number; y: number }>, x: number, y: number): number {\n let best = Infinity;\n for (let i = 0; i < pts.length; i++) {\n const p = pts[i]!;\n const q = pts[(i + 1) % pts.length]!;\n const ex = q.x - p.x;\n const ey = q.y - p.y;\n const len2 = ex * ex + ey * ey;\n const u = len2 > 0 ? Math.max(0, Math.min(1, ((x - p.x) * ex + (y - p.y) * ey) / len2)) : 0;\n const dx = x - (p.x + ex * u);\n const dy = y - (p.y + ey * u);\n best = Math.min(best, dx * dx + dy * dy);\n }\n return Math.sqrt(best);\n}\n\n// ---------------------------------------------------------------------------\n// Luminance grid\n// ---------------------------------------------------------------------------\n\nexport interface LuminanceGrid {\n cols: number;\n rows: number;\n /** Row-major luminance 0..1 including the background. */\n cells: number[];\n /** Per-row background luminance (what an empty scene would be). For a `field` background: each row's mean. */\n background: number[];\n /**\n * Per-cell background luminance, present only for a `field` background\n * (a solid or gradient varies by row alone, and `background` says it all).\n * Coverage, centroid and the profiles deviate from THIS, so the field's own\n * contours never count as content — a bright field is ground, not ink.\n */\n backgroundCells?: number[];\n meanLuminance: number;\n /** Fraction of cells deviating perceptibly (> 0.03) from the background. */\n coverage: number;\n /** Deviation-weighted centre of visual mass as viewport fractions, or null for a flat scene. */\n centroid: { x: number; y: number } | null;\n /** Mean deviation-from-background per row/column — 1D transects of the composition. */\n rowProfile: number[];\n colProfile: number[];\n}\n\nexport interface LuminanceGridOptions extends PerceiveOptions {\n /** Grid resolution. Defaults 80×48 (→ a 40×12 braille map). */\n cols?: number;\n rows?: number;\n}\n\n/**\n * Sample the spec into a coarse luminance image — analytically, no renderer.\n * Persistence is modeled, not simulated: because positions are pure functions\n * of (seed, t), `ghosting` is a decayed sum of past-frame splats (weight g^m\n * for ink m frames old, mirroring the renderer's warm-up replay) and `trail`\n * re-uses drawTrail's sampling — past positions with decaying alpha and\n * shrinking radius. Polygons larger than POLYGON_OUTLINE_CELLS are scanned by\n * their real (rotated) outline; smaller ones splat as a fill-weighted disc.\n * Remaining approximations (documented, deliberate): soft circles use a linear\n * falloff, background drift is sampled at its rest position. Good enough to\n * perceive composition, focus, balance — and now smear.\n */\nexport function luminanceGrid(spec: SaverSpec, opts: LuminanceGridOptions = {}): LuminanceGrid {\n // A `timeline` resolves at the sample time; without one this is `spec` itself.\n spec = resolveTimelineAt(spec, opts.t ?? 5000);\n const scene = buildScene(spec, opts);\n const t = opts.t ?? 5000;\n const cols = Math.max(8, Math.min(200, opts.cols ?? 80));\n const rows = Math.max(8, Math.min(200, opts.rows ?? 48));\n const { w, h, scale } = scene;\n const cellW = w / cols;\n const cellH = h / rows;\n\n // Background: vertical gradient (or solid) + optional bottom band — or a\n // field, sampled per cell with the renderer's own function at the same\n // bucketed time, so the grid's ground IS what the raster paints.\n const bg = spec.background;\n const bgRow: number[] = new Array(rows).fill(0);\n let bgCells: number[] | undefined;\n if (!bg || bg.type === 'solid') {\n bgRow.fill(hexLuma(bg?.color ?? '#05050a'));\n } else if (bg.type === 'field') {\n bgCells = new Array<number>(cols * rows);\n const short = Math.max(1, Math.min(w, h));\n const seed = scene.seed;\n const ft = fieldSampleTime(bg, t);\n for (let r = 0; r < rows; r++) {\n let rowSum = 0;\n for (let c = 0; c < cols; c++) {\n const lum = rgb255Luma(fieldRgbAt(((c + 0.5) * cellW) / short, ((r + 0.5) * cellH) / short, ft, bg, seed));\n bgCells[r * cols + c] = lum;\n rowSum += lum;\n }\n bgRow[r] = rowSum / cols;\n }\n } else {\n const stops = [...bg.stops].sort((a, b) => a.at - b.at);\n for (let r = 0; r < rows; r++) {\n const y = (r + 0.5) / rows;\n let lum: number;\n if (y <= stops[0]!.at) lum = hexLuma(stops[0]!.color);\n else if (y >= stops[stops.length - 1]!.at) lum = hexLuma(stops[stops.length - 1]!.color);\n else {\n let i = 0;\n while (i < stops.length - 1 && stops[i + 1]!.at < y) i++;\n const a = stops[i]!;\n const b = stops[i + 1]!;\n const k = b.at === a.at ? 0 : (y - a.at) / (b.at - a.at);\n lum = hexLuma(a.color) + (hexLuma(b.color) - hexLuma(a.color)) * k;\n }\n bgRow[r] = lum;\n }\n if (bg.band) {\n const bandPx = bg.band.height * (spec.units === 'px' ? 1 : Math.min(w, h));\n const fromRow = Math.max(0, Math.floor((h - bandPx) / cellH));\n for (let r = fromRow; r < rows; r++) bgRow[r] = hexLuma(bg.band.color);\n }\n }\n\n const cells = new Array<number>(cols * rows);\n for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) cells[r * cols + c] = bgCells ? bgCells[r * cols + c]! : bgRow[r]!;\n\n const compose = (idx: number, lum: number, a: number, blend: LayerSpec['blend']): void => {\n const cur = cells[idx]!;\n if (blend === 'lighter' || blend === 'screen') cells[idx] = Math.min(1, cur + lum * a);\n else if (blend === 'multiply') cells[idx] = cur * (1 - a * (1 - lum));\n else cells[idx] = cur * (1 - a) + lum * a;\n };\n\n // Afterglow dots behind a moving entity — the analytic mirror of the\n // renderer's drawTrail: past positions sampled with decaying alpha and\n // shrinking radius, stopping at wrap seams.\n const splatTrail = (layer: LayerSpec, e: Entity, tPass: number, lifeA: number, alphaScale: number): void => {\n const trail = layer.trail;\n if (!trail) return;\n const fade = trail.fade ?? 1;\n const n = Math.min(Math.ceil(trail.length / 50), LIMITS.maxTrailSamples);\n const headAlpha = alphaAt(e, tPass) * lifeA;\n const headSize = sizeAt(e, tPass);\n const lum = spriteLuma(layer, e);\n const soft = layer.sprite.kind === 'circle' && !!layer.sprite.soft;\n const wrapOn = layer.wrap !== false;\n const head = posOf(scene, e, tPass);\n let prevX = head.x;\n let prevY = head.y;\n for (let s = 1; s <= n; s++) {\n const k = s / n;\n const pastT = tPass - k * trail.length;\n if (pastT < 0) break;\n const pos = posOf(scene, e, pastT);\n if (wrapOn && (Math.abs(pos.x - prevX) > w / 2 || Math.abs(pos.y - prevY) > h / 2)) break;\n prevX = pos.x;\n prevY = pos.y;\n const a = headAlpha * (1 - k * fade) * alphaScale;\n if (a <= 0.004) break;\n const rad = (headSize / 2) * (1 - k * 0.7);\n if (rad < 0.2) break;\n const c0 = Math.max(0, Math.floor((pos.x - rad) / cellW));\n const c1 = Math.min(cols - 1, Math.floor((pos.x + rad) / cellW));\n const r0 = Math.max(0, Math.floor((pos.y - rad) / cellH));\n const r1 = Math.min(rows - 1, Math.floor((pos.y + rad) / cellH));\n for (let r = r0; r <= r1; r++) {\n for (let c = c0; c <= c1; c++) {\n const dx = (c + 0.5) * cellW - pos.x;\n const dy = (r + 0.5) * cellH - pos.y;\n const d = Math.sqrt(dx * dx + dy * dy);\n if (d > rad + Math.min(cellW, cellH) / 2) continue;\n const wgt = soft ? Math.max(0.1, 1 - d / Math.max(rad, 1e-6)) : 1;\n compose(r * cols + c, lum, Math.min(1, a * wgt), layer.blend);\n }\n }\n }\n };\n\n // A polygon painted by its real outline — the renderer's path, rotated by\n // `rotationAt` about the entity — instead of its circumscribed disc. Weight\n // per cell is the fraction of it the outline fills; `soft` is the renderer's\n // radial gradient (centred on the entity, radius = circumradius) clipped to\n // that outline. The additive halo spreads past the OUTLINE, not a disc: its\n // band is GLOW_SPREAD − 1 times the glyph's thickness (2·area/perimeter —\n // the radius for a disc, the apothem for a regular n-gon), so a soft\n // `lighter` hexagon blooms about as far as the disc model did while a\n // full-width band or ridge doesn't re-inflate into a screen-filling dome.\n const splatPolygonOutline = (layer: LayerSpec, s: PolygonSprite, e: Entity, p: { x: number; y: number }, sz: number, a: number, lum: number, tPass: number): void => {\n const radius = sz / 2;\n const rot = rotationAt(e, tPass);\n const cr = Math.cos(rot);\n const sr = Math.sin(rot);\n const pts = polygonPoints(s, radius).map((q) => ({ x: p.x + q.x * cr - q.y * sr, y: p.y + q.x * sr + q.y * cr }));\n const additive = layer.blend === 'lighter' || layer.blend === 'screen';\n const glow = !!s.soft && additive;\n let band = 0;\n if (glow) {\n const perimeter = pts.reduce((acc, q, i) => { const n = pts[(i + 1) % pts.length]!; return acc + Math.hypot(n.x - q.x, n.y - q.y); }, 0);\n band = perimeter > 0 ? (GLOW_SPREAD - 1) * ((2 * polygonArea(pts)) / perimeter) : 0;\n }\n let minX = Infinity;\n let maxX = -Infinity;\n let minY = Infinity;\n let maxY = -Infinity;\n for (const q of pts) {\n minX = Math.min(minX, q.x); maxX = Math.max(maxX, q.x);\n minY = Math.min(minY, q.y); maxY = Math.max(maxY, q.y);\n }\n const c0 = Math.max(0, Math.floor((minX - band) / cellW));\n const c1 = Math.min(cols - 1, Math.floor((maxX + band) / cellW));\n const r0 = Math.max(0, Math.floor((minY - band) / cellH));\n const r1 = Math.min(rows - 1, Math.floor((maxY + band) / cellH));\n if (c0 > c1 || r0 > r1) return;\n const cov = polygonCellCoverage(pts, cellW, cellH, c0, c1, r0, r1);\n const nc = c1 - c0 + 1;\n for (let r = r0; r <= r1; r++) {\n for (let c = c0; c <= c1; c++) {\n const f = cov[(r - r0) * nc + (c - c0)]!;\n const x = (c + 0.5) * cellW;\n const y = (r + 0.5) * cellH;\n let wgt: number;\n if (glow) {\n // Outside the outline's box by more than the band: no halo reaches.\n const outX = Math.max(0, minX - x, x - maxX);\n const outY = Math.max(0, minY - y, y - maxY);\n if (f >= 1) wgt = 1;\n else if (outX * outX + outY * outY >= band * band) wgt = f;\n else {\n const k = band > 0 ? Math.max(0, 1 - distanceToOutline(pts, x, y) / band) : 0;\n wgt = f + (1 - f) * k * k;\n }\n } else if (s.soft) {\n wgt = f * Math.max(0.1, 1 - Math.hypot(x - p.x, y - p.y) / Math.max(radius, 1e-6));\n } else {\n wgt = f;\n }\n if (wgt > 0) compose(r * cols + c, lum, a * Math.min(1, wgt), layer.blend);\n }\n }\n };\n\n // One composite pass at time tPass with all ink scaled by alphaScale — the\n // analytic mirror of the renderer's paintFrame. Ghost passes call this with\n // decayed weights; the live frame calls it with alphaScale 1.\n const splatPass = (tPass: number, alphaScale: number): void => {\n for (const { layer, entities } of scene.layers) {\n const lifeA = layer.opacity === undefined && layer.group === undefined ? lifeAlphaAt(layer.life, tPass) : lifeAlphaAt(layer.life, tPass) * paintOpacity(spec, layer);\n if (lifeA <= 0) continue;\n\n for (const e of entities) {\n splatTrail(layer, e, tPass, lifeA, alphaScale);\n const a = Math.min(1, alphaAt(e, tPass) * lifeA) * alphaScale;\n if (a <= 0.004) continue;\n const lum = spriteLuma(layer, e);\n const p = posOf(scene, e, tPass);\n const sz = layer.transform || layer.group !== undefined ? sizeAt(e, tPass) * paintSize(spec, layer) : sizeAt(e, tPass);\n const s = layer.sprite;\n\n if (s.kind === 'polygon' && sz >= POLYGON_OUTLINE_CELLS * Math.min(cellW, cellH)) {\n splatPolygonOutline(layer, s, e, p, sz, a, lum, tPass);\n continue;\n }\n if (s.kind === 'stroke') {\n // Stamp along the sampled path, rotated like the renderer does.\n const pts = strokeSamples(s, sz / 2);\n let angle = rotationAt(e, tPass);\n if (s.orient) angle += headingAt(e, tPass, w, h) ?? 0;\n const ca = Math.cos(angle);\n const sa = Math.sin(angle);\n const lw = strokeWidthPx(s, scale);\n const stampAt = (q: { x: number; y: number }, u: number): void => {\n const x = p.x + q.x * ca - q.y * sa;\n const y = p.y + q.x * sa + q.y * ca;\n const c = Math.floor(x / cellW);\n const r = Math.floor(y / cellH);\n if (c < 0 || c >= cols || r < 0 || r >= rows) return;\n const taper = s.taper ? strokeTaper(u) : 1;\n compose(r * cols + c, lum, a * Math.min(1, (lw * taper) / cellH), layer.blend);\n };\n // Rasterize each segment at half-cell steps so a long stroke leaves a\n // continuous line of ink, not a dotted one.\n const step = Math.min(cellW, cellH) / 2;\n stampAt(pts[0]!, 0);\n for (let i = 1; i < pts.length; i++) {\n const q0 = pts[i - 1]!;\n const q1 = pts[i]!;\n const segLen = Math.hypot(q1.x - q0.x, q1.y - q0.y);\n const sub = Math.max(1, Math.ceil(segLen / step));\n for (let k = 1; k <= sub; k++) {\n const f = k / sub;\n stampAt({ x: q0.x + (q1.x - q0.x) * f, y: q0.y + (q1.y - q0.y) * f }, (i - 1 + f) / (pts.length - 1));\n }\n }\n continue;\n }\n if (s.kind === 'streak') {\n // Stamp along the segment from tail to head, like the renderer: motion\n // heading plus the entity's own resolved rotation.\n const heading = (headingAt(e, tPass, w, h) ?? 0) + rotationAt(e, tPass);\n const steps = Math.max(2, Math.ceil(sz / Math.min(cellW, cellH)));\n const wgt = Math.min(1, ((s.width ?? (scale === 1 ? 2 : 0.002)) * scale) / cellH);\n for (let i = 0; i <= steps; i++) {\n const k = i / steps;\n const x = p.x - Math.cos(heading) * sz * (1 - k);\n const y = p.y - Math.sin(heading) * sz * (1 - k);\n const c = Math.floor(x / cellW);\n const r = Math.floor(y / cellH);\n if (c < 0 || c >= cols || r < 0 || r >= rows) continue;\n compose(r * cols + c, lum, a * k * wgt, layer.blend);\n }\n continue;\n }\n\n let centerX = p.x;\n let centerY = p.y;\n let halfX = sz / 2;\n let halfY = s.kind === 'rect' ? ((e.size2 ?? sz) * (e.size > 0 ? sz / e.size : 1)) / 2 : sz / 2;\n if (s.kind === 'text') {\n const box = textBox(s, e, p);\n centerX = box.cx;\n centerY = box.cy;\n halfX = box.halfX;\n halfY = box.halfY;\n } else if (s.kind === 'textBlock') {\n const box = textBlockBox(s, e, p, w, h);\n centerX = box.cx;\n centerY = box.cy;\n halfX = box.halfX;\n halfY = box.halfY;\n } else if (s.kind === 'bar') {\n const len = sz * barFraction(s, e.barIndex ?? 0);\n if (len <= 0) continue;\n const th = e.size2 !== undefined ? e.size2 * (e.size > 0 ? sz / e.size : 1) : sz * 0.2;\n const box = barBox(s.direction ?? 'right', len, th);\n // The renderer rotates the bar about the entity with `spin`; rotate\n // the box's offset the same way and take the rotated box's AABB.\n const rot = rotationAt(e, tPass);\n const cr = Math.cos(rot);\n const sr = Math.sin(rot);\n centerX = p.x + box.cx * cr - box.cy * sr;\n centerY = p.y + box.cx * sr + box.cy * cr;\n halfX = Math.abs(box.halfX * cr) + Math.abs(box.halfY * sr);\n halfY = Math.abs(box.halfX * sr) + Math.abs(box.halfY * cr);\n }\n const circular = s.kind === 'circle' || s.kind === 'ring' || s.kind === 'polygon';\n const soft = (s.kind === 'circle' || s.kind === 'polygon') && !!s.soft;\n // A small polygon (under POLYGON_OUTLINE_CELLS) fills only part of its\n // disc; a feathered rect only part of its box. Scale the splat weight\n // rather than trace the outline — large polygons took the outline path.\n const shapeWeight = s.kind === 'polygon'\n ? polygonFill(s, sz / 2)\n : s.kind === 'rect' && s.feather\n ? (1 - s.feather / 2) * (1 - s.feather / 2)\n : 1;\n const additive = layer.blend === 'lighter' || layer.blend === 'screen';\n // Model the halo (see GLOW_SPREAD): reach past the radius with a quadratic\n // falloff outside the solid core, so coverage tracks what the audience\n // actually sees. Non-additive / hard-edged sprites are unchanged.\n const glow = soft && additive;\n const reachX = glow ? halfX * GLOW_SPREAD : halfX;\n const reachY = glow ? halfY * GLOW_SPREAD : halfY;\n const c0 = Math.max(0, Math.floor((centerX - reachX) / cellW));\n const c1 = Math.min(cols - 1, Math.floor((centerX + reachX) / cellW));\n const r0 = Math.max(0, Math.floor((centerY - reachY) / cellH));\n const r1 = Math.min(rows - 1, Math.floor((centerY + reachY) / cellH));\n // Glyphs don't fill their box — ink is sparse. A revealing textBlock\n // has proportionally less ink lit.\n const inkWeight = (s.kind === 'text' || s.kind === 'emoji' || s.kind === 'textBlock' ? 0.55 : 1)\n * (s.kind === 'textBlock' ? textBlockRevealFraction(s, w, h, t) * (s.opacity ?? 1) : 1);\n // rect and bar are fillRect: the canvas paints each cell in proportion\n // to the area the box covers. Without this a 2 px scan line darkened\n // its whole 22 px grid row at full alpha, and 270 of them read as a\n // black veil (mean 0.035 where the canvas paints 0.41).\n const byArea = s.kind === 'rect' || s.kind === 'bar';\n for (let r = r0; r <= r1; r++) {\n const fy = byArea ? Math.max(0, Math.min((r + 1) * cellH, centerY + halfY) - Math.max(r * cellH, centerY - halfY)) / cellH : 1;\n if (fy <= 0) continue;\n for (let c = c0; c <= c1; c++) {\n const dx = (c + 0.5) * cellW - centerX;\n const dy = (r + 0.5) * cellH - centerY;\n if (circular) {\n const d = Math.sqrt(dx * dx + dy * dy);\n const reach = glow ? reachX : halfX;\n if (d > reach + Math.min(cellW, cellH) / 2) continue;\n if (s.kind === 'ring') {\n const strokeW = (s.width ?? (scale === 1 ? 2 : 0.002)) * scale;\n if (d < halfX - strokeW) continue;\n }\n let wgt: number;\n if (glow) {\n const core = halfX;\n if (d <= core) wgt = 1;\n else {\n const f = Math.max(0, 1 - (d - core) / Math.max(reachX - core, 1e-6));\n wgt = f * f;\n }\n } else {\n wgt = soft ? Math.max(0.1, 1 - d / Math.max(halfX, 1e-6)) : 1;\n }\n compose(r * cols + c, lum, a * wgt * shapeWeight, layer.blend);\n } else if (byArea) {\n const fx = Math.max(0, Math.min((c + 1) * cellW, centerX + halfX) - Math.max(c * cellW, centerX - halfX)) / cellW;\n if (fx > 0) compose(r * cols + c, lum, a * shapeWeight * fx * fy, layer.blend);\n } else {\n compose(r * cols + c, lum, a * inkWeight * shapeWeight, layer.blend);\n }\n }\n }\n }\n\n // Link lines are visual mass too (for chain scenes they ARE the scene).\n if (layer.links) {\n const positions = entities.map((e) => posOf(scene, e, tPass));\n const maxDistPx = layer.links.maxDist * scale;\n const motionWraps = ['drift', 'rise', 'wander'].includes(layer.motion.type);\n const edges = linkEdges(layer.links, positions, maxDistPx, layer.wrap !== false && motionWraps, w, h);\n const la = Math.min(1, (layer.links.alpha ?? 0.6) * lifeA);\n const lum = layer.links.color ? hexLuma(layer.links.color) : 0.7;\n const defaultWidth = scale === 1 ? 1 : 1 / LIMITS.referenceViewport;\n const wgt = Math.min(1, ((layer.links.width ?? defaultWidth) * scale) / cellH) * la * alphaScale;\n for (const edge of edges) {\n const pi = positions[edge.i]!;\n const pj = positions[edge.j]!;\n const steps = Math.max(1, Math.ceil(edge.dist / Math.min(cellW, cellH)));\n for (let i = 0; i <= steps; i++) {\n const k = i / steps;\n const c = Math.floor((pi.x + (pj.x - pi.x) * k) / cellW);\n const r = Math.floor((pi.y + (pj.y - pi.y) * k) / cellH);\n if (c < 0 || c >= cols || r < 0 || r >= rows) continue;\n compose(r * cols + c, lum, wgt, layer.blend);\n }\n }\n }\n }\n };\n\n // Ghosting: the renderer composites each 60 fps frame over the last with\n // persistence g, so ink from m frames ago survives at weight g^m. Sample\n // that decay across the visible window (weight ≥ 1/255, capped at the same\n // maxGhostReplayFrames bound as the renderer's seek replay), oldest first so\n // newer ink composites on top. Each tap stands in for the frames in its\n // bracket and carries their summed surviving weight (geometric sum).\n const ghost = spec.ghosting ?? 0;\n if (ghost > 0) {\n const dt = 1000 / 60;\n const windowFrames = Math.min(Math.ceil(Math.log(1 / 255) / Math.log(ghost)), LIMITS.maxGhostReplayFrames);\n const taps = Math.min(GHOST_TAPS, windowFrames);\n const spacing = windowFrames / taps;\n for (let i = taps; i >= 1; i--) {\n const tPass = t - i * spacing * dt;\n if (tPass < 0) continue;\n const bracketWeight =\n (Math.pow(ghost, (i - 1) * spacing + 1) * (1 - Math.pow(ghost, spacing))) / (1 - ghost);\n splatPass(tPass, Math.min(1, bracketWeight));\n }\n }\n splatPass(t, 1);\n\n // Deviation stats\n return finishGrid(cols, rows, cells, bgRow, bgCells);\n}\n\n/**\n * The stats every grid carries, from its cells and per-row background —\n * or, for a field, its per-cell background (`bgCells`), which deviation is\n * measured against instead so the field's own contours read as ground.\n */\nfunction finishGrid(cols: number, rows: number, cells: number[], bgRow: number[], bgCells?: number[]): LuminanceGrid {\n let sum = 0;\n let covered = 0;\n let devSum = 0;\n let cxAcc = 0;\n let cyAcc = 0;\n const rowProfile = new Array<number>(rows).fill(0);\n const colProfile = new Array<number>(cols).fill(0);\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const v = cells[r * cols + c]!;\n sum += v;\n const dev = Math.abs(v - (bgCells ? bgCells[r * cols + c]! : bgRow[r]!));\n if (dev > 0.03) covered++;\n devSum += dev;\n cxAcc += dev * (c + 0.5);\n cyAcc += dev * (r + 0.5);\n rowProfile[r]! += dev;\n colProfile[c]! += dev;\n }\n }\n for (let r = 0; r < rows; r++) rowProfile[r] = rowProfile[r]! / cols;\n for (let c = 0; c < cols; c++) colProfile[c] = colProfile[c]! / rows;\n\n return {\n cols,\n rows,\n cells,\n background: bgRow,\n ...(bgCells ? { backgroundCells: bgCells } : {}),\n meanLuminance: sum / (cols * rows),\n coverage: covered / (cols * rows),\n centroid: devSum > 1e-6 ? { x: cxAcc / devSum / cols, y: cyAcc / devSum / rows } : null,\n rowProfile,\n colProfile,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Braille rendering\n// ---------------------------------------------------------------------------\n\n// Ordered-dither thresholds for a 2×4 braille cell (spatially spread).\nconst DITHER: number[][] = [\n [0.5 / 8, 4.5 / 8],\n [2.5 / 8, 6.5 / 8],\n [1.5 / 8, 5.5 / 8],\n [3.5 / 8, 7.5 / 8],\n];\n// Braille dot bit for (row 0..3, col 0..1): dots 1-2-3-7 left, 4-5-6-8 right.\nconst DOT_BIT: number[][] = [\n [0x01, 0x08],\n [0x02, 0x10],\n [0x04, 0x20],\n [0x40, 0x80],\n];\n\n/**\n * Auto-exposure curve for a grid: most savers live in the bottom of the\n * luminance range, so cells are normalized (min → 98th percentile) with a\n * slight gamma before quantizing — like a camera exposing for the scene. Stats\n * on the grid itself stay raw.\n *\n * Shared by every renderer below, deliberately: if the curve is ever\n * recalibrated (e.g. once GLOW_SPREAD is tuned and coverage shifts), the braille\n * and density views must move together or they'd silently disagree about the\n * same scene.\n */\nfunction autoExpose(grid: LuminanceGrid): (v: number) => number {\n const sorted = [...grid.cells].sort((a, b) => a - b);\n const lo = sorted[0]!;\n const hi = Math.max(sorted[Math.floor(sorted.length * 0.98)]!, lo + 0.08);\n return (v: number): number => Math.pow(Math.max(0, Math.min(1, (v - lo) / (hi - lo))), 0.8);\n}\n\n/**\n * Encode a luminance grid as a braille \"image\": each output character is a 2×4\n * pixel cell, ordered-dithered so mid-tones render as dot density. A grid of\n * 80×48 becomes 12 lines of 40 chars — a picture a text model can read whole.\n */\nexport function renderBrailleMap(grid: LuminanceGrid): string {\n const expose = autoExpose(grid);\n\n const outRows: string[] = [];\n for (let br = 0; br < Math.floor(grid.rows / 4); br++) {\n let line = '';\n for (let bc = 0; bc < Math.floor(grid.cols / 2); bc++) {\n let bits = 0;\n for (let dr = 0; dr < 4; dr++) {\n for (let dc = 0; dc < 2; dc++) {\n const v = expose(grid.cells[(br * 4 + dr) * grid.cols + (bc * 2 + dc)]!);\n if (v > DITHER[dr]![dc]!) bits |= DOT_BIT[dr]![dc]!;\n }\n }\n line += String.fromCharCode(0x2800 + bits);\n }\n outRows.push(line);\n }\n return outRows.join('\\n');\n}\n\n// Density ramp, dark → bright. One char per grid cell (vs braille's 2×4), so a\n// higher-resolution grid reads as a sharper picture — the channel agents found\n// most legible for structure (rings, grids, text blocks) that braille blurs.\nconst DENSITY_RAMP = ' .:-=+*#%@';\n\n/**\n * Encode a luminance grid as a one-char-per-cell ASCII density map. Unlike the\n * braille map (compact, 2×4 dots/char) this is 1:1 with the grid, so pairing it\n * with a larger `cols`/`rows` gives a non-vision agent a genuinely higher-detail\n * read: 120×48 resolves concentric rings and text blocks braille smears into a\n * blob. Shares the braille map's auto-exposure so both views agree.\n */\nexport function renderDensityMap(grid: LuminanceGrid): string {\n const expose = autoExpose(grid);\n const ramp = DENSITY_RAMP;\n const lines: string[] = [];\n for (let r = 0; r < grid.rows; r++) {\n let line = '';\n for (let c = 0; c < grid.cols; c++) {\n const v = expose(grid.cells[r * grid.cols + c]!);\n line += ramp[Math.min(ramp.length - 1, Math.floor(v * ramp.length))]!;\n }\n lines.push(line);\n }\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Text sprite listing\n// ---------------------------------------------------------------------------\n\nexport interface TextSpriteInfo {\n layerIndex: number;\n key: string | undefined;\n /** The literal strings this layer draws (glyphs are invisible in the maps). */\n strings: string[];\n /** How many entities carry text. */\n count: number;\n /** Representative rendered glyph height in px at the sample viewport. */\n sizePx: number;\n /** For a revealing textBlock: effective 0..1 fraction shown at sample t. */\n revealed?: number;\n}\n\n/**\n * List every text layer's actual strings and rendered size. No grid resolution\n * renders glyphs legibly, so a non-vision agent otherwise can't tell whether the\n * words it wrote are on screen, how big, or whether they'll overlap. This closes\n * that blind spot analytically.\n */\nexport function textSprites(spec: SaverSpec, opts: PerceiveOptions = {}): TextSpriteInfo[] {\n spec = resolveTimelineAt(spec, opts.t ?? 5000);\n const scene = buildScene(spec, opts);\n const t = opts.t ?? 5000;\n const out: TextSpriteInfo[] = [];\n scene.layers.forEach(({ layer, entities }, layerIndex) => {\n if (layer.sprite.kind === 'textBlock') {\n const s = layer.sprite;\n const unitScale = Math.min(scene.w, scene.h);\n const sizePx = s.fontSize * unitScale;\n const info: TextSpriteInfo = { layerIndex, key: layer.key, strings: [s.text], count: entities.length, sizePx: Math.round(sizePx) };\n if (s.reveal) info.revealed = Math.round(textBlockRevealFraction(s, scene.w, scene.h, t) * 100) / 100;\n out.push(info);\n return;\n }\n if (layer.sprite.kind !== 'text') return;\n const s = layer.sprite;\n const m = s.font ? /(\\d+(?:\\.\\d+)?)px/.exec(s.font) : null;\n const sizePx = m ? Number(m[1]) : entities[0] ? sizeAt(entities[0], t) : 0;\n out.push({ layerIndex, key: layer.key, strings: [...s.strings], count: entities.length, sizePx: Math.round(sizePx) });\n });\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Dominance ranking\n// ---------------------------------------------------------------------------\n\nexport interface DominanceEntry {\n rank: number;\n layerIndex: number;\n key: string | undefined;\n /** Normalized share of total visual weight, 0..1 (all entries sum to 1). */\n share: number;\n entityCount: number;\n meanLuma: number;\n factors: { area: number; contrast: number; blendBoost: number; motionBoost: number };\n}\n\n/**\n * Rank layers by estimated visual weight — where the eye goes. Weight is\n * on-screen area × alpha, scaled by contrast against the background, an\n * additive-glow boost, and a motion boost. Link lines count as area, and so\n * does persistence ink: trail ribbons and ghosting smear are modeled as swept\n * ribbons, so a comet layer is ranked by its comet, not just its head.\n */\nexport function dominanceRanking(spec: SaverSpec, opts: PerceiveOptions = {}): DominanceEntry[] {\n return rankDominance(rawDominance(spec, opts));\n}\n\ninterface RawDominance {\n layerIndex: number;\n key: string | undefined;\n weight: number;\n entityCount: number;\n meanLuma: number;\n factors: DominanceEntry['factors'];\n}\n\n/** Normalize raw weights to shares and rank — shared by a scene and a composed sequence frame. */\nfunction rankDominance(raw: RawDominance[]): DominanceEntry[] {\n const total = raw.reduce((s, r) => s + r.weight, 0) || 1;\n return raw\n .slice()\n .sort((a, b) => b.weight - a.weight)\n .map((r, i) => ({\n rank: i + 1,\n layerIndex: r.layerIndex,\n key: r.key,\n share: r.weight / total,\n entityCount: r.entityCount,\n meanLuma: r.meanLuma,\n factors: r.factors,\n }));\n}\n\n/** Per-layer un-normalized visual weight at `opts.t` — the body of dominanceRanking. */\nfunction rawDominance(spec: SaverSpec, opts: PerceiveOptions = {}): RawDominance[] {\n spec = resolveTimelineAt(spec, opts.t ?? 5000);\n const scene = buildScene(spec, opts);\n const t = opts.t ?? 5000;\n const { w, h, scale } = scene;\n\n const bgMean = backgroundLuma(spec);\n\n\n // Persistence smears every moving sprite into a ribbon of real visual mass —\n // for a comet layer the trail IS the visual event. Model both effects as\n // swept ribbons (path length × stroke width × mean surviving alpha), using\n // the straight-line displacement as a lower-bound path length and skipping\n // wrap seams. First-pass fidelity, same spirit as GLOW_SPREAD.\n const ghost = spec.ghosting ?? 0;\n let ghostWindowMs = 0;\n let ghostMeanW = 0;\n if (ghost > 0) {\n const dt = 1000 / 60;\n const frames = Math.min(Math.ceil(Math.log(1 / 255) / Math.log(ghost)), LIMITS.maxGhostReplayFrames);\n ghostWindowMs = frames * dt;\n ghostMeanW = (ghost * (1 - Math.pow(ghost, frames))) / (1 - ghost) / frames;\n }\n const sweptDistance = (e: Entity, spanMs: number): number => {\n const span = Math.min(spanMs, t);\n if (span <= 0) return 0;\n const p0 = posOf(scene, e, t - span);\n const p1 = posOf(scene, e, t);\n const dx = p1.x - p0.x;\n const dy = p1.y - p0.y;\n if (Math.abs(dx) > w / 2 || Math.abs(dy) > h / 2) return 0; // wrapped: ambiguous\n return Math.sqrt(dx * dx + dy * dy);\n };\n\n const raw = scene.layers.map(({ layer, entities }, layerIndex) => {\n const lifeA = layer.opacity === undefined && layer.group === undefined ? lifeAlphaAt(layer.life, t) : lifeAlphaAt(layer.life, t) * paintOpacity(spec, layer);\n const painted = layer.transform !== undefined || layer.group !== undefined;\n const areaScale = painted ? paintSize(spec, layer) ** 2 : 1;\n let area = 0;\n let lumAcc = 0;\n for (const e of entities) {\n const a = alphaAt(e, t) * lifeA;\n const sz = sizeAt(e, t);\n const s = layer.sprite;\n let entArea: number;\n if (s.kind === 'circle') entArea = Math.PI * (sz / 2) * (sz / 2);\n else if (s.kind === 'ring') entArea = Math.PI * sz * ((s.width ?? (scale === 1 ? 2 : 0.002)) * scale) * LINE_SALIENCE;\n else if (s.kind === 'streak') entArea = sz * ((s.width ?? (scale === 1 ? 2 : 0.002)) * scale) * LINE_SALIENCE;\n else if (s.kind === 'rect') {\n const h2 = e.size2 !== undefined ? e.size2 * (e.size > 0 ? sz / e.size : 1) : sz;\n const f = s.feather ? (1 - s.feather / 2) * (1 - s.feather / 2) : 1;\n entArea = sz * h2 * f;\n }\n else if (s.kind === 'polygon') entArea = polygonArea(polygonPoints(s, sz / 2));\n else if (s.kind === 'bar') {\n const th = e.size2 !== undefined ? e.size2 * (e.size > 0 ? sz / e.size : 1) : sz * 0.2;\n entArea = sz * barFraction(s, e.barIndex ?? 0) * th;\n }\n else if (s.kind === 'stroke') {\n const meanTaper = s.taper ? 0.64 : 1; // ∫ sin(πu) du = 2/π\n entArea = pathLength(strokeSamples(s, sz / 2)) * strokeWidthPx(s, scale) * meanTaper * LINE_SALIENCE;\n }\n else if (s.kind === 'text') {\n const box = textBox(s, e, { x: 0, y: 0 });\n entArea = box.halfX * 2 * box.halfY * 2 * 0.55;\n } else if (s.kind === 'textBlock') {\n const box = textBlockBox(s, e, { x: 0, y: 0 }, w, h);\n entArea = box.halfX * 2 * box.halfY * 2 * 0.55 * textBlockRevealFraction(s, w, h, t) * (s.opacity ?? 1);\n } else entArea = sz * sz * 0.55; // emoji\n\n area += painted ? entArea * areaScale * a : entArea * a;\n\n // Trail ribbon: dots shrink to 0.3× and fade along the tail, so mean\n // width ≈ 0.65×size and mean alpha ≈ (1 - fade/2) of the head's.\n if (layer.trail) {\n const fade = layer.trail.fade ?? 1;\n const span = sweptDistance(e, layer.trail.length);\n area += span * sz * 0.65 * Math.max(0, 1 - fade / 2) * a;\n }\n // Ghost smear: ink from m frames back survives at g^m, so the sweep over\n // the visible window carries the window's mean surviving weight.\n if (ghost > 0) {\n area += sweptDistance(e, ghostWindowMs) * sz * ghostMeanW * a;\n }\n lumAcc += spriteLuma(layer, e);\n }\n if (layer.links && entities.length > 1) {\n const positions = entities.map((e) => posOf(scene, e, t));\n const motionWraps = ['drift', 'rise', 'wander'].includes(layer.motion.type);\n const edges = linkEdges(layer.links, positions, layer.links.maxDist * scale, layer.wrap !== false && motionWraps, w, h);\n const la = (layer.links.alpha ?? 0.6) * lifeA;\n const defaultWidth = scale === 1 ? 1 : 1 / LIMITS.referenceViewport;\n const lw = (layer.links.width ?? defaultWidth) * scale;\n for (const edge of edges) area += edge.dist * lw * la * LINE_SALIENCE;\n }\n const meanLuma = entities.length ? lumAcc / entities.length : 0;\n const contrast = Math.abs(meanLuma - bgMean) + 0.1;\n const blendBoost = layer.blend === 'lighter' || layer.blend === 'screen' ? 1.3 : layer.blend === 'multiply' ? 1.1 : 1;\n const motionBoost = layer.motion.type === 'static' ? 1 : 1.2;\n const weight = (area / (w * h)) * contrast * blendBoost * motionBoost;\n return { layerIndex, key: layer.key, weight, entityCount: entities.length, meanLuma, factors: { area: area / (w * h), contrast, blendBoost, motionBoost } };\n });\n\n return raw;\n}\n\n// ---------------------------------------------------------------------------\n// Motion stats\n// ---------------------------------------------------------------------------\n\n/**\n * Does each layer read as one merged form or as separate marks? The one thing\n * the luminance maps cannot answer — they measure ink, not edges, so a layer\n * that merged into a silhouette and one that stayed a pile of discs look\n * identical in every other channel. See `cohesion.ts`.\n */\nexport function layerCohesion(spec: SaverSpec, opts: PerceiveOptions = {}): LayerCohesion[] {\n spec = resolveTimelineAt(spec, opts.t ?? 5000);\n const scene = buildScene(spec, opts);\n return cohesionOf(scene.layers, opts.t ?? 5000, scene.w, scene.h);\n}\n\nexport interface LayerMotionStats {\n layerIndex: number;\n key: string | undefined;\n /** Mean / max on-screen speed in px per second at the perceived size (wrap jumps excluded). */\n meanSpeed: number;\n maxSpeed: number;\n /**\n * The same speeds in **viewport units per second** — fractions of\n * min(w, h), the unit a spec's `speed` is authored in — so they do not\n * change with the size the scene is perceived at. 1.0 crosses the short side\n * of the screen every second.\n */\n meanSpeedVp: number;\n maxSpeedVp: number;\n /** meanSpeedVp above MOVING_FLOOR — the same answer at every preview size. */\n moving: boolean;\n /**\n * Direction the layer's mass is going, in screen degrees (0 = right,\n * 90 = down, 180 = left, 270 = up), or null when nothing moves. Sampling a\n * centroid over time gives the WRONG sign for a wrapping full-viewport\n * scatter, which is why this is reported directly.\n */\n heading: number | null;\n /**\n * 0 = every entity moves the same way (a conveyor — the \"screen-wipe\" the\n * schema warns about), 1 = headings cancel out (a scatter, an orbit, a\n * bounce field). |mean unit vector| inverted.\n */\n headingSpread: number | null;\n}\n\n/**\n * Below this many viewport units per second a layer reads as still (half a\n * pixel per second on a 1080 display — what the old px/s threshold of 0.5\n * meant at that one resolution).\n */\nconst MOVING_FLOOR = 0.0005;\n\n\n/**\n * Per-layer displacement between t and t+dt — choreography as numbers.\n *\n * Samples the scene at both ends of the window separately (not just each\n * entity's own position within one scene) so a `timeline`-driven layer\n * `transform` — a camera pan or zoom with every entity otherwise static —\n * registers as motion instead of vanishing between two reads of the same\n * frozen transform.\n */\nexport function motionStats(spec: SaverSpec, opts: PerceiveOptions & { dt?: number } = {}): LayerMotionStats[] {\n const t = opts.t ?? 5000;\n const dt = opts.dt ?? 500;\n const scene0 = buildScene(resolveTimelineAt(spec, t), opts);\n const scene1 = spec.timeline ? buildScene(resolveTimelineAt(spec, t + dt), opts) : scene0;\n const { w, h } = scene0;\n const unit = Math.min(w, h);\n return scene0.layers.map(({ layer, entities }, layerIndex) => {\n const entities1 = scene1.layers[layerIndex]?.entities ?? entities;\n let acc = 0;\n let max = 0;\n let n = 0;\n let ux = 0;\n let uy = 0;\n let moversN = 0;\n entities.forEach((e, i) => {\n const p0 = posOf(scene0, e, t);\n const p1 = posOf(scene1, entities1[i] ?? e, t + dt);\n const dx = p1.x - p0.x;\n const dy = p1.y - p0.y;\n if (Math.abs(dx) > w / 2 || Math.abs(dy) > h / 2) return; // wrap seam\n const dist = Math.sqrt(dx * dx + dy * dy);\n const speed = (dist / dt) * 1000;\n acc += speed;\n max = Math.max(max, speed);\n n++;\n if (dist > 0) {\n ux += dx / dist;\n uy += dy / dist;\n moversN++;\n }\n });\n const meanSpeed = n ? acc / n : 0;\n const meanSpeedVp = meanSpeed / unit;\n const maxSpeedVp = max / unit;\n const moving = meanSpeedVp > MOVING_FLOOR;\n let heading: number | null = null;\n let headingSpread: number | null = null;\n if (moving && moversN > 0) {\n const mx = ux / moversN;\n const my = uy / moversN;\n const mag = Math.sqrt(mx * mx + my * my);\n headingSpread = 1 - mag;\n heading = mag > 0.05 ? ((Math.atan2(my, mx) * 180) / Math.PI + 360) % 360 : null;\n }\n return { layerIndex, key: layer.key, meanSpeed, maxSpeed: max, meanSpeedVp, maxSpeedVp, moving, heading, headingSpread };\n });\n}\n\n// ---------------------------------------------------------------------------\n// Colour — the channel edits are usually about\n// ---------------------------------------------------------------------------\n\nexport interface SceneColour {\n /** Hue of the visible sprite mass in degrees (0 red, 120 green, 240 blue), null when unsaturated. */\n hue: number | null;\n /** HSL saturation 0..1 of the sprite mass. */\n saturation: number;\n /** red minus blue of the mean sprite colour, -1 (cold) .. 1 (warm). The \"cooler/warmer\" axis. */\n warmth: number;\n /** Mean sprite colour as hex, for a model that reads hex better than angles. */\n hex: string;\n /** The same three numbers for the background plate. */\n background: { hue: number | null; saturation: number; warmth: number; hex: string };\n}\n\nfunction rgbToHsl(c: { r: number; g: number; b: number }): { h: number | null; s: number; l: number } {\n const max = Math.max(c.r, c.g, c.b);\n const min = Math.min(c.r, c.g, c.b);\n const l = (max + min) / 2;\n const d = max - min;\n if (d < 1e-6) return { h: null, s: 0, l };\n const sat = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n let h: number;\n if (max === c.r) h = ((c.g - c.b) / d + (c.g < c.b ? 6 : 0)) * 60;\n else if (max === c.g) h = ((c.b - c.r) / d + 2) * 60;\n else h = ((c.r - c.g) / d + 4) * 60;\n return { h: sat < 0.05 ? null : h, s: sat, l };\n}\n\nfunction toHex(c: { r: number; g: number; b: number }): string {\n const q = (v: number) => Math.round(Math.max(0, Math.min(1, v)) * 255).toString(16).padStart(2, '0');\n return `#${q(c.r)}${q(c.g)}${q(c.b)}`;\n}\n\nfunction describeColour(c: { r: number; g: number; b: number }): { hue: number | null; saturation: number; warmth: number; hex: string } {\n const hsl = rgbToHsl(c);\n return { hue: hsl.h === null ? null : Math.round(hsl.h), saturation: +hsl.s.toFixed(3), warmth: +(c.r - c.b).toFixed(3), hex: toHex(c) };\n}\n\n/**\n * What colour the scene IS — the alpha × area weighted mean of every hex a\n * sprite paints with, beside the background plate. A luminance map cannot\n * carry this: a luma-matched red→cyan swap moves every other channel by\n * ~0.001 (comprehension eval 2026-07-28, P2 F3), and `meanLuminance` reads\n * plausible cool tones as *brighter* than the reds they replace, so \"make it\n * cooler\" pushed the only number an agent had in the wrong direction. Emoji\n * carry their own palette and are excluded; a scene of only emoji reports the\n * background.\n */\nexport function sceneColour(spec: SaverSpec, opts: PerceiveOptions = {}): SceneColour {\n const t = opts.t ?? 5000;\n // A timeline can animate colour: read the scene as it is at t.\n spec = resolveTimelineAt(spec, t);\n const scene = buildScene(spec, opts);\n let wr = 0;\n let wg = 0;\n let wb = 0;\n let wsum = 0;\n for (const { layer, entities } of scene.layers) {\n // Paint opacity (layer × group) weighs like alpha: a hidden prop adds no colour.\n const lifeA = lifeAlphaAt(layer.life, t) * (layer.opacity === undefined && layer.group === undefined ? 1 : paintOpacity(spec, layer));\n for (const e of entities) {\n const hex = spriteHex(layer, e);\n if (hex === null) continue;\n const sz = sizeAt(e, t);\n const weight = alphaAt(e, t) * lifeA * (layer.sprite.kind === 'circle' ? Math.PI * (sz / 2) * (sz / 2) : sz * sz);\n if (weight <= 0) continue;\n const c = hexRgb(hex);\n wr += c.r * weight;\n wg += c.g * weight;\n wb += c.b * weight;\n wsum += weight;\n }\n }\n const bg = backgroundRgb(spec);\n const sprites = wsum > 0 ? { r: wr / wsum, g: wg / wsum, b: wb / wsum } : bg;\n return { ...describeColour(sprites), background: describeColour(bg) };\n}\n\n/** Signed shortest hue difference b − a in degrees (−180..180), null when either is unsaturated. */\nfunction hueShift(a: number | null, b: number | null): number | null {\n if (a === null || b === null) return null;\n let d = b - a;\n while (d > 180) d -= 360;\n while (d < -180) d += 360;\n return Math.round(d);\n}\n\n// ---------------------------------------------------------------------------\n// Scene diff — relative sight\n// ---------------------------------------------------------------------------\n\nconst REGION_NAMES = [\n 'top-left', 'top-center', 'top-right',\n 'mid-left', 'center', 'mid-right',\n 'bottom-left', 'bottom-center', 'bottom-right',\n] as const;\n\nfunction regionMeans(grid: LuminanceGrid): number[] {\n const out = new Array<number>(9).fill(0);\n const cnt = new Array<number>(9).fill(0);\n for (let r = 0; r < grid.rows; r++) {\n for (let c = 0; c < grid.cols; c++) {\n const idx = r * grid.cols + c;\n const region = Math.min(2, Math.floor((r / grid.rows) * 3)) * 3 + Math.min(2, Math.floor((c / grid.cols) * 3));\n // A field's own contours are ground, not content (see `backgroundCells`\n // on `LuminanceGrid`): deviate against the per-cell background where\n // one exists, the same rule `finishGrid` applies to coverage/centroid.\n out[region]! += Math.abs(grid.cells[idx]! - (grid.backgroundCells ? grid.backgroundCells[idx]! : grid.background[r]!));\n cnt[region]!++;\n }\n }\n return out.map((v, i) => (cnt[i]! ? v / cnt[i]! : 0));\n}\n\nexport interface SceneDiff {\n t: number;\n coverage: { a: number; b: number; delta: number };\n meanLuminance: { a: number; b: number; delta: number };\n /** Shift of the visual-mass centroid from A to B, in viewport fractions. */\n balanceShift: { dx: number; dy: number } | null;\n /** Mean deviation-from-background per third-by-third region, with deltas. */\n regions: Array<{ region: (typeof REGION_NAMES)[number]; a: number; b: number; delta: number }>;\n /** Dominance changes, matched by layer key (falls back to index). Sorted by |share delta|. */\n dominance: Array<{ key: string; rankA: number | null; rankB: number | null; shareA: number; shareB: number }>;\n /**\n * The hue channel. `hueShift` is the signed shortest rotation A→B in\n * degrees; `warmthDelta` is the cooler/warmer axis (negative = B is cooler)\n * — read THIS for \"cooler\", not `meanLuminance`, which weights cool tones\n * brighter than the reds they replace.\n */\n colour: {\n a: SceneColour;\n b: SceneColour;\n hueShift: number | null;\n saturationDelta: number;\n warmthDelta: number;\n background: { hueShift: number | null; warmthDelta: number };\n };\n /**\n * The motion channel, in viewport units per second. `overall` is the\n * entity-weighted mean across layers; `layers` lists every layer whose speed\n * changed, largest change first. Halving every speed used to leave the diff\n * bit-identical (comprehension eval 2026-07-28, P2 F4).\n */\n motion: {\n overall: { a: number; b: number; delta: number };\n layers: Array<{ key: string; a: number; b: number; delta: number; headingA: number | null; headingB: number | null }>;\n };\n advisories: { added: string[]; removed: string[] };\n}\n\n/**\n * Compare two specs at the same time/viewport — relative perception. A text\n * model is far better at \"is B better than A\" than \"is A good\"; this returns\n * the deltas that question needs: coverage, balance, per-region visual mass,\n * dominance-rank movement, and advisory changes.\n */\nexport function diffScenes(a: SaverSpec, b: SaverSpec, opts: LuminanceGridOptions = {}): SceneDiff {\n const t = opts.t ?? 5000;\n const gridA = luminanceGrid(a, opts);\n const gridB = luminanceGrid(b, opts);\n const regsA = regionMeans(gridA);\n const regsB = regionMeans(gridB);\n const domA = dominanceRanking(a, opts);\n const domB = dominanceRanking(b, opts);\n\n const nameOf = (d: DominanceEntry): string => d.key ?? `layer-${d.layerIndex}`;\n const names = new Set<string>([...domA.map(nameOf), ...domB.map(nameOf)]);\n const dominance = [...names].map((key) => {\n const inA = domA.find((d) => nameOf(d) === key);\n const inB = domB.find((d) => nameOf(d) === key);\n return {\n key,\n rankA: inA?.rank ?? null,\n rankB: inB?.rank ?? null,\n shareA: inA?.share ?? 0,\n shareB: inB?.share ?? 0,\n };\n }).sort((x, y) => Math.abs(y.shareB - y.shareA) - Math.abs(x.shareB - x.shareA));\n\n // Advise at the diff's OWN viewport. This used to run at the 1920×1080\n // default while the caller previewed at 960×540, so the two tools disagreed\n // about the same spec's advisories (comprehension eval 2026-07-28, P3 F6).\n const vp = opts.viewport ?? { width: 1920, height: 1080 };\n const codesA = new Set(adviseSpec(a, vp).map((w) => w.code));\n const codesB = new Set(adviseSpec(b, vp).map((w) => w.code));\n\n const colA = sceneColour(a, opts);\n const colB = sceneColour(b, opts);\n const motA = motionStats(a, opts);\n const motB = motionStats(b, opts);\n const weighted = (stats: LayerMotionStats[], dom: DominanceEntry[]): number => {\n let acc = 0;\n let n = 0;\n for (const m of stats) {\n const c = dom.find((d) => d.layerIndex === m.layerIndex)?.entityCount ?? 1;\n acc += m.meanSpeedVp * c;\n n += c;\n }\n return n ? acc / n : 0;\n };\n const motNameOf = (m: LayerMotionStats): string => m.key ?? `layer-${m.layerIndex}`;\n const motionLayers = [...new Set([...motA.map(motNameOf), ...motB.map(motNameOf)])]\n .map((key) => {\n const ma = motA.find((m) => motNameOf(m) === key);\n const mb = motB.find((m) => motNameOf(m) === key);\n const va = ma?.meanSpeedVp ?? 0;\n const vb = mb?.meanSpeedVp ?? 0;\n return { key, a: va, b: vb, delta: vb - va, headingA: ma?.heading ?? null, headingB: mb?.heading ?? null };\n })\n .filter((m) => Math.abs(m.delta) > 1e-9 || m.headingA !== m.headingB)\n .sort((x, y) => Math.abs(y.delta) - Math.abs(x.delta));\n const overallA = weighted(motA, domA);\n const overallB = weighted(motB, domB);\n\n return {\n t,\n coverage: { a: gridA.coverage, b: gridB.coverage, delta: gridB.coverage - gridA.coverage },\n meanLuminance: { a: gridA.meanLuminance, b: gridB.meanLuminance, delta: gridB.meanLuminance - gridA.meanLuminance },\n balanceShift: gridA.centroid && gridB.centroid\n ? { dx: gridB.centroid.x - gridA.centroid.x, dy: gridB.centroid.y - gridA.centroid.y }\n : null,\n regions: REGION_NAMES.map((region, i) => ({ region, a: regsA[i]!, b: regsB[i]!, delta: regsB[i]! - regsA[i]! })),\n dominance,\n colour: {\n a: colA,\n b: colB,\n hueShift: hueShift(colA.hue, colB.hue),\n saturationDelta: +(colB.saturation - colA.saturation).toFixed(3),\n warmthDelta: +(colB.warmth - colA.warmth).toFixed(3),\n background: {\n hueShift: hueShift(colA.background.hue, colB.background.hue),\n warmthDelta: +(colB.background.warmth - colA.background.warmth).toFixed(3),\n },\n },\n motion: {\n overall: { a: overallA, b: overallB, delta: overallB - overallA },\n layers: motionLayers,\n },\n advisories: {\n added: [...codesB].filter((c) => !codesA.has(c)),\n removed: [...codesA].filter((c) => !codesB.has(c)),\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// One-call perception bundle\n// ---------------------------------------------------------------------------\n\nexport interface ScenePerception {\n t: number;\n /** The picture: a braille luminance map (each char = 2×4 pixels), compact. */\n braille: string;\n /**\n * A one-char-per-cell ASCII density map at the grid resolution — higher\n * fidelity than braille for structure (rings, grids, text blocks). Pair with\n * a larger `cols`/`rows` for a sharper read.\n */\n density: string;\n coverage: number;\n meanLuminance: number;\n centroid: { x: number; y: number } | null;\n rowProfile: number[];\n colProfile: number[];\n dominance: DominanceEntry[];\n motion: LayerMotionStats[];\n /** Per layer: merged silhouette, seamed overlap, or separate marks. */\n form: LayerCohesion[];\n /** What colour the scene is — hue/saturation/warmth of the sprite mass and the plate. */\n colour: SceneColour;\n /** Literal strings + sizes of any text layers (glyphs don't show in the maps). */\n text: TextSpriteInfo[];\n advisories: ReturnType<typeof adviseSpec>;\n}\n\n/**\n * Everything a non-vision agent needs to \"see\" a spec in one deterministic\n * call: the braille picture, a higher-res density map, composition transects,\n * dominance ranking, motion stats, the literal text on screen, and advisories.\n * Intended as the payload behind an MCP previewScene.\n */\nexport function perceiveScene(spec: SaverSpec, opts: LuminanceGridOptions = {}): ScenePerception {\n // motionStats gets the spec WITH its timeline: it resolves t and t + dt\n // itself, and a pre-resolved spec has no timeline left to differ between\n // them — every layer moved only by timeline keys read 0 px/s (X437).\n const timed = spec;\n spec = resolveTimelineAt(spec, opts.t ?? 5000);\n const grid = luminanceGrid(spec, opts);\n return {\n t: opts.t ?? 5000,\n braille: renderBrailleMap(grid),\n density: renderDensityMap(grid),\n coverage: grid.coverage,\n meanLuminance: grid.meanLuminance,\n centroid: grid.centroid,\n rowProfile: grid.rowProfile,\n colProfile: grid.colProfile,\n dominance: dominanceRanking(spec, opts),\n motion: motionStats(timed, opts),\n form: layerCohesion(spec, opts),\n colour: sceneColour(spec, opts),\n text: textSprites(spec, opts),\n advisories: adviseSpec(spec, opts.viewport ?? { width: 1920, height: 1080 }, { t: opts.t, seed: opts.seed }),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Sequence frames — bed + segment\n// ---------------------------------------------------------------------------\n\nexport interface SequenceFramePerception extends ScenePerception {\n /** Which segment the global time `T` resolved to, and where in it. */\n segment: { index: number; key: string; localT: number; held?: true };\n /** True when a bed was composed under the segment. */\n bed: boolean;\n}\n\nexport interface PerceiveSequenceOptions extends Omit<LuminanceGridOptions, 't'> {\n /** Holds released by the clicker so far — see `ResolveOptions.releasedBelow`. */\n releasedBelow?: number;\n}\n\n/** Prefix bed layers so they read apart from the segment's in a merged list. */\nconst bedKey = (key: string | undefined, layerIndex: number): string => `bed:${key ?? layerIndex}`;\n\n/**\n * Perceive one frame of a sequence at global time `T`: resolve the segment,\n * then — when the sequence has a `bed` — compose the bed at `T` (its clock\n * never resets) under the segment's ink at `localT`, the segment's own\n * background dropped, exactly as the renderer stacks them. The luminance maps\n * add the two grids (clamped), so coverage, centroid and the profiles are of\n * the composite; dominance ranks bed and segment layers together by their raw\n * weights, bed layers keyed `bed:<key|index>`; text, motion and form list bed\n * layers first with the same prefix. Bed and segment are assumed to share\n * `units`/`referenceViewport`, as the renderer's shared canvas assumes. The\n * bed and segment seeds come from `segmentRenderSeed`/`bedRenderSeed`\n * (`./sequence`) — the same derivation `SequenceInstance` uses, chain roots\n * and zero-seed normalization included — so the composed frame matches what\n * the renderer actually draws at `T`, not just what the raw specs would show.\n * Without a bed this is `perceiveScene(segment, localT)` plus the `segment`\n * field. Intended as the payload behind a sequence-aware previewScene.\n *\n * Two known approximations, both accepted for a coarse, cheap, renderer-free\n * tool rather than fixed here:\n * - **The transition WINDOW isn't composed.** During a live `fade` or `morph`\n * (i.e. `localT < transition.dur`) the renderer also paints the outgoing\n * (or interpolating) segment, but this only ever perceives the segment\n * `resolveSegment` resolves to — call it at a `T` outside the transition's\n * `dur` for an accurate read. (Outside that window, a morph-chained\n * segment's entities and seed ARE correct — `segmentRenderSeed` already\n * resolves the chain root.) Composing the live window properly needs the\n * same capability-tier gate `SequenceInstance` uses to decide whether\n * `fade` even plays; this analytical path has no such context.\n * - **Ink composites onto the bed by addition, not by blend mode.** This\n * matches a plain `source-over`, opaque-ink segment (the common case), but\n * a segment layer with `blend: 'multiply'`/`'screen'`/etc. or partial alpha\n * composites directionally differently on the real canvas than adding\n * luminance values ever can (`multiply` darkens; addition only brightens).\n * The per-cell grids don't retain per-layer blend/alpha to composite\n * correctly at this resolution.\n */\nexport function perceiveSequenceFrame(seq: IdleSequence, T: number, opts: PerceiveSequenceOptions = {}): SequenceFramePerception {\n const { releasedBelow, ...gridOpts } = opts;\n const r = resolveSegment(seq, T, { releasedBelow });\n const seg = seq.segments[r.index]!;\n const segment: SequenceFramePerception['segment'] = { index: r.index, key: seg.key, localT: r.localT, ...(r.held ? { held: true } : {}) };\n const segOpts: LuminanceGridOptions = { ...gridOpts, t: r.localT, seed: gridOpts.seed ?? segmentRenderSeed(seq, r.index) };\n if (!seq.bed) return { ...perceiveScene(seg.scene, segOpts), segment, bed: false };\n\n const bedOpts: LuminanceGridOptions = { ...gridOpts, t: T, seed: gridOpts.seed ?? bedRenderSeed(seq) };\n const viewport = gridOpts.viewport ?? { width: 1920, height: 1080 };\n // The segment's ink alone: a black ground contributes nothing to the sum,\n // and no ghosting — a transparent child ignores it, as the renderer does.\n const ink: SaverSpec = { ...seg.scene, background: { type: 'solid', color: '#000000' } };\n delete ink.ghosting;\n // For contrast, ink is judged against what is actually behind it: the bed.\n const inkOverBed: SaverSpec = { ...ink, background: seq.bed.background ?? { type: 'solid', color: '#05050a' } };\n\n const bedGrid = luminanceGrid(seq.bed, bedOpts);\n const inkGrid = luminanceGrid(ink, segOpts);\n const cells = bedGrid.cells.map((v, i) => Math.min(1, v + inkGrid.cells[i]!));\n const grid = finishGrid(bedGrid.cols, bedGrid.rows, cells, bedGrid.background, bedGrid.backgroundCells);\n\n const bedLayers = seq.bed.layers.length;\n const dominance = rankDominance([\n ...rawDominance(seq.bed, bedOpts).map((d) => ({ ...d, key: bedKey(d.key, d.layerIndex) })),\n ...rawDominance(inkOverBed, segOpts).map((d) => ({ ...d, layerIndex: d.layerIndex + bedLayers })),\n ]);\n const shift = <X extends { layerIndex: number }>(x: X): X => ({ ...x, layerIndex: x.layerIndex + bedLayers });\n const prefix = <X extends { layerIndex: number; key: string | undefined }>(x: X): X => ({ ...x, key: bedKey(x.key, x.layerIndex) });\n\n return {\n t: r.localT,\n braille: renderBrailleMap(grid),\n density: renderDensityMap(grid),\n coverage: grid.coverage,\n meanLuminance: grid.meanLuminance,\n centroid: grid.centroid,\n rowProfile: grid.rowProfile,\n colProfile: grid.colProfile,\n dominance,\n motion: [...motionStats(seq.bed, bedOpts).map(prefix), ...motionStats(ink, segOpts).map(shift)],\n form: [...layerCohesion(seq.bed, bedOpts).map(prefix), ...layerCohesion(ink, segOpts).map(shift)],\n text: [...textSprites(seq.bed, bedOpts).map(prefix), ...textSprites(ink, segOpts).map(shift)],\n // The segment's sprite mass over the bed's plate — what the screen shows\n // in front of the bed. The bed's own sprites are a slow constant beneath.\n colour: sceneColour(inkOverBed, segOpts),\n advisories: [\n ...adviseSpec(seq.bed, viewport, { t: T, seed: bedOpts.seed }).map((w) => ({ ...w, path: `bed.${w.path}` })),\n // inkOverBed's layers are the segment's (seed: segOpts.seed) but its\n // background is the bed's (seq.bed.background) — a field there must be\n // sampled with the bed's own seed, or a `role: 'read'` legibility\n // advisory checks terrain that isn't what's actually behind the ink.\n // `?? 42`: inkOverBed.seed is the SEGMENT's raw seed field (it's `ink`\n // spread first), so adviseSpec's own `backgroundSeed ?? seed` fallback\n // would substitute the segment's seed, not the bed's, if bedOpts.seed\n // were left undefined — 42 is the same default `luminanceGrid` (and\n // every other field seed fallback) converges on.\n ...adviseSpec(inkOverBed, viewport, { t: r.localT, seed: segOpts.seed, backgroundSeed: bedOpts.seed ?? 42 }),\n ],\n segment,\n bed: true,\n };\n}\n","import { createRng } from '@idle-screens/core';\nimport { polygonArea, polygonPoints } from './shapes';\nimport { buildEntities, entityScales, linkPairs, positionAt } from './simulate';\nimport type { FinishSpec, SaverSpec } from './types';\n\nexport interface LayerSnapshot {\n key: string | undefined;\n count: number;\n centroid: { x: number; y: number };\n coverage: number;\n meanAlpha: number;\n linksDrawn: number | null;\n linksExpected: number | null;\n connectedComponents: number | null;\n isolatedNodes: number | null;\n}\n\nexport interface SceneSnapshot {\n t: number;\n viewport: { w: number; h: number };\n layers: LayerSnapshot[];\n warnings: string[];\n}\n\nexport interface SceneDescription {\n /** `finish` is present only when the spec declares one — a print screen the luminance numbers do not include. */\n spec: { id: string; label: string; units: string; finish?: FinishSpec };\n snapshots: SceneSnapshot[];\n}\n\n/**\n * Deterministic scene analysis at one or more time values. Reuses `buildEntities`\n * and `linkPairs` — no render needed. Returns structured data a non-vision model\n * can use to understand what a spec looks like when rendered.\n */\nexport function describeScene(\n spec: SaverSpec,\n options: {\n viewport?: { width: number; height: number };\n seed?: number;\n times?: number[];\n } = {},\n): SceneDescription {\n const { width: w, height: h } = options.viewport ?? { width: 1920, height: 1080 };\n const seed = options.seed ?? spec.seed ?? 42;\n const times = options.times ?? [0, 5000, 15000];\n const { scale, countScale } = entityScales(spec, w, h);\n\n const rng = createRng(seed);\n const builtLayers = spec.layers.map((layer) => ({\n layer,\n entities: buildEntities(layer, rng, w, h, scale, countScale),\n }));\n\n const snapshots: SceneSnapshot[] = times.map((t) => {\n const layerSnapshots: LayerSnapshot[] = builtLayers.map(({ layer, entities }) => {\n const positions = entities.map((e) => positionAt(e, t, w, h));\n const cx = positions.length > 0 ? positions.reduce((s, p) => s + p.x, 0) / positions.length : 0;\n const cy = positions.length > 0 ? positions.reduce((s, p) => s + p.y, 0) / positions.length : 0;\n\n // Coverage: fraction of viewport area covered by entity bounding circles\n let pixArea = 0;\n for (const e of entities) {\n const r = e.size / 2;\n pixArea += layer.sprite.kind === 'circle'\n ? Math.PI * r * r\n : layer.sprite.kind === 'polygon'\n ? polygonArea(polygonPoints(layer.sprite, r))\n : e.size * e.size;\n }\n const coverage = pixArea / (w * h);\n const meanAlpha = entities.length > 0\n ? entities.reduce((s, e) => s + e.alpha, 0) / entities.length\n : 0;\n\n // Link analysis\n let linksDrawn: number | null = null;\n let linksExpected: number | null = null;\n let connectedComponents: number | null = null;\n let isolatedNodes: number | null = null;\n if (layer.links) {\n const maxDist = layer.links.maxDist * scale;\n const pairs = linkPairs(positions, layer.links.k, maxDist, layer.wrap !== false, w, h);\n linksDrawn = pairs.length;\n linksExpected = Math.min(entities.length * layer.links.k, entities.length * (entities.length - 1) / 2);\n // Connected components via union-find\n const parent = Array.from({ length: entities.length }, (_, i) => i);\n const find = (x: number): number => {\n while (parent[x] !== x) { parent[x] = parent[parent[x]!]!; x = parent[x]!; }\n return x;\n };\n for (const [a, b] of pairs) {\n const ra = find(a); const rb = find(b);\n if (ra !== rb) parent[ra] = rb;\n }\n const roots = new Set(entities.map((_, i) => find(i)));\n connectedComponents = roots.size;\n // Isolated = nodes with zero edges\n const degree = new Uint16Array(entities.length);\n for (const [a, b] of pairs) { degree[a]!++; degree[b]!++; }\n isolatedNodes = degree.filter((d) => d === 0).length;\n }\n\n return {\n key: layer.key,\n count: entities.length,\n centroid: { x: +(cx / w).toFixed(3), y: +(cy / h).toFixed(3) },\n coverage: +coverage.toFixed(4),\n meanAlpha: +meanAlpha.toFixed(3),\n linksDrawn,\n linksExpected,\n connectedComponents,\n isolatedNodes,\n };\n });\n\n // Warnings derived from the numbers\n const warnings: string[] = [];\n for (const ls of layerSnapshots) {\n const label = ls.key ?? `layer`;\n if (ls.coverage * ls.meanAlpha < 0.0005) {\n warnings.push(`${label}: effectively invisible (coverage×alpha=${(ls.coverage * ls.meanAlpha).toFixed(5)})`);\n }\n if (ls.linksDrawn !== null && ls.linksExpected !== null && ls.linksExpected > 0) {\n const ratio = ls.linksDrawn / ls.linksExpected;\n if (ratio < 0.1) {\n warnings.push(`${label}: link starvation — ${ls.linksDrawn}/${ls.linksExpected} edges formed`);\n }\n }\n if (ls.isolatedNodes !== null && ls.count > 0 && ls.isolatedNodes / ls.count > 0.5) {\n warnings.push(`${label}: ${ls.isolatedNodes}/${ls.count} nodes isolated — graph is disconnected`);\n }\n }\n\n return { t, viewport: { w, h }, layers: layerSnapshots, warnings };\n });\n\n return {\n spec: { id: spec.id, label: spec.label, units: spec.units ?? 'viewport', ...(spec.finish ? { finish: spec.finish } : {}) },\n snapshots,\n };\n}\n","import type { SaverSpec } from '../types';\n\n/**\n * Reproduces the hand-coded Fish Aquarium saver as pure DATA — the discriminating test\n * that the schema is actually expressive: two layers (fish drifting both ways at varied\n * speeds with a bob + flip, over a gradient with a seafloor band; bubbles rising with sway).\n */\nexport const AQUARIUM_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'aquarium',\n label: 'Aquarium',\n seed: 42,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#0a3a52' },\n { at: 0.6, color: '#062534' },\n { at: 1, color: '#02141d' },\n ],\n band: { color: '#0b1a12', height: 0.02222 },\n },\n layers: [\n {\n count: 14,\n sprite: { kind: 'emoji', glyphs: ['🐟', '🐠', '🐡', '🦈', '🐙'] },\n size: [0.03148, 0.06667],\n motion: { type: 'drift', speed: [0.02778, 0.1019], bidirectional: true, bob: 0.005556 },\n flip: true,\n },\n {\n count: 22,\n sprite: { kind: 'circle', radius: [0.001852, 0.006481], color: '#c8ebff' },\n motion: { type: 'rise', speed: [0.02222, 0.07222], sway: 0.007407 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Aurora Borealis: the \"fake fluid\" recipe — showcases `wander` motion (harmonic\n * drift) with high `coherence` so the curtain undulates as one body, `pulse.wave`\n * (a traveling shimmer across the star field), weighted palettes, additive blend,\n * and `ghosting` smearing the soft glows into continuous curtains of light.\n */\nexport const AURORA_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'aurora',\n label: 'Aurora',\n seed: 66,\n motionIntensity: 'calm',\n ghosting: 0.85,\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#02030d' },\n { at: 0.65, color: '#050a18' },\n { at: 1, color: '#0a1220' },\n ],\n drift: { period: 40000, amount: 0.1 },\n },\n layers: [\n {\n key: 'stars',\n count: 110,\n sprite: { kind: 'circle', radius: [0.0005, 0.0015], color: '#e8ecff', soft: true },\n motion: { type: 'static' },\n region: { y: [0, 0.75] },\n alpha: [0.2, 0.6],\n // A slow shimmer travels across the sky instead of stars twinkling independently.\n pulse: { amp: 0.25, period: 6000, wave: { wavelength: 0.5, angle: 15 } },\n },\n {\n key: 'curtain-green',\n count: 100,\n sprite: {\n kind: 'circle',\n radius: [0.055, 0.11],\n color: '#1fd68a',\n soft: true,\n colors: ['#1fd68a', '#2ee6c8', '#4bd1ff'],\n colorWeights: [5, 2, 1],\n },\n motion: { type: 'wander', speed: [0.004, 0.012], angle: 0, meander: 0.13, coherence: 0.7 },\n region: { y: [0.1, 0.42] },\n alpha: [0.04, 0.1],\n blend: 'lighter',\n grow: { amp: 0.25, period: 9000 },\n },\n {\n key: 'curtain-violet',\n count: 60,\n sprite: {\n kind: 'circle',\n radius: [0.045, 0.09],\n color: '#8d5bff',\n soft: true,\n colors: ['#8d5bff', '#d14bff', '#ff4bd8'],\n colorWeights: [4, 1.5, 0.5],\n },\n motion: { type: 'wander', speed: [0.003, 0.01], angle: 180, meander: 0.1, coherence: 0.55 },\n region: { y: [0.04, 0.28] },\n alpha: [0.03, 0.08],\n blend: 'lighter',\n grow: { amp: 0.3, period: 12000 },\n },\n {\n key: 'fireflies',\n count: 14,\n sprite: { kind: 'circle', radius: [0.001, 0.003], color: '#b8ffe1', soft: true },\n motion: { type: 'wander', speed: [0.006, 0.02], meander: 0.06 },\n region: { y: [0.55, 0.95] },\n alpha: [0.2, 0.55],\n pulse: { amp: 0.3, period: 3500 },\n blend: 'lighter',\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Comet Shower: showcases trails (afterglow behind moving entities) and background\n * drift (gradient stops breathing slowly). Three layers: a static star field, fast\n * comets with long trails, and slow fireflies with short trails and pulse.\n */\nexport const COMETS_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'comets',\n label: 'Comet Shower',\n seed: 42,\n motionIntensity: 'moderate',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#0a0015' },\n { at: 0.5, color: '#0d1b2a' },\n { at: 1, color: '#1b0a2e' },\n ],\n drift: { period: 25000, amount: 0.12 },\n },\n layers: [\n {\n key: 'stars',\n count: 120,\n sprite: { kind: 'circle', radius: [0.000463, 0.001852], color: '#ffffff', soft: true },\n motion: { type: 'static' },\n alpha: [0.3, 0.7],\n pulse: { amp: 0.15, period: 3000 },\n },\n {\n key: 'comets',\n count: 8,\n sprite: { kind: 'circle', radius: [0.002778, 0.007407], color: '#88ccff', soft: true },\n motion: { type: 'drift', speed: [0.07407, 0.1852], angle: 225 },\n alpha: [0.7, 1],\n blend: 'lighter',\n trail: { length: 1500, fade: 1 },\n },\n {\n key: 'fireflies',\n count: 20,\n sprite: { kind: 'circle', radius: [0.001852, 0.00463], color: '#ffdd44', soft: true },\n motion: { type: 'drift', speed: [0.009259, 0.02778], bidirectional: true, bob: 0.01852 },\n alpha: [0.4, 0.8],\n pulse: { amp: 0.3, period: 2000 },\n blend: 'lighter',\n trail: { length: 800 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Constellation: drifting stars connected by faint k-nearest links. Exercises\n * colors[] (multi-hued stars), links (k-nearest neighbor lines), and cycle\n * (emoji asterisms rotate glyphs). Stars are soft circles in viewport units.\n */\nexport const CONSTELLATION_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'constellation',\n label: 'Constellation',\n seed: 73,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#020212' },\n { at: 0.5, color: '#050520' },\n { at: 1, color: '#0a0830' },\n ],\n },\n layers: [\n // Distant static stars (no links, just atmosphere)\n {\n count: 100,\n sprite: { kind: 'circle', radius: [0.0009259, 0.002778], color: '#667799', colors: ['#8899cc', '#99aadd', '#aabbee', '#7788aa'] },\n alpha: [0.2, 0.7],\n pulse: { amp: 0.2, period: 3000 },\n motion: { type: 'static' },\n },\n // Connected constellation nodes — slow drift, linked\n {\n key: 'nodes',\n count: 40,\n sprite: { kind: 'circle', radius: [0.001852, 0.00463], color: '#88aaff', colors: ['#88aaff', '#aaccff', '#ffcc88', '#ff8866'], soft: true },\n alpha: [0.5, 0.9],\n blend: 'lighter',\n motion: { type: 'drift', speed: [0.001852, 0.007407], bidirectional: true, bob: 0.002778 },\n links: { k: 3, maxDist: 0.1852, alpha: 0.15, width: 0.000463 },\n },\n // Cycling asterism markers\n {\n count: 6,\n sprite: { kind: 'emoji', glyphs: ['✦', '✧', '⋆', '∗'], cycle: { period: 2000 } },\n size: [0.01296, 0.02037],\n alpha: [0.4, 0.7],\n motion: { type: 'drift', speed: [0.0009259, 0.003704], bidirectional: true },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Control Center — VIREO-9, Trans-Lunar Relay Operations.\n *\n * A mission-control WALL BOARD, laid out the way real ops rooms lay them out:\n * framed zones with a clear reading order, one hero display (the orbital\n * plot), dense-but-calm peripheral telemetry, and a boot sequence when the\n * board comes up. The fiction: a small relay station somewhere past GEO,\n * mid-shift, tracking a five-craft fleet (named for this library's own\n * savers — the station runs our little universe).\n *\n * Composed against the validator's 36-layer ceiling deliberately — every\n * layer earns its slot. Schema exercises: grid `layout` LED wall with a\n * traveling `pulse.wave`, `orbit` motion with `trail`s and chain `links`\n * (the relay web between the fleet), `ring` orbit guides, wave-phased rect\n * meters, staged `life` boots per zone. Every reading is keyed so an agent\n * can steer the fiction live (`signal-value`, `feed-1`, `alert`, ...).\n */\nexport const DASHBOARD_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'dev-dashboard',\n label: 'Control Center',\n seed: 256,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#05070d' },\n { at: 0.55, color: '#080b14' },\n { at: 1, color: '#0a0d18' },\n ],\n },\n layers: [\n // ---- ambient: the LED wall behind everything ----\n {\n key: 'led-wall',\n count: 240,\n sprite: { kind: 'circle', radius: [0.0007, 0.0011], color: '#22344c' },\n alpha: [0.04, 0.1],\n layout: { type: 'grid', columns: 24, jitter: 0.1 },\n pulse: { amp: 0.3, period: 6200, wave: { wavelength: 0.4, angle: 24 } },\n motion: { type: 'static' },\n },\n // ---- frame chrome (boots first) ----\n {\n key: 'rule-header', count: 1,\n position: { x: 0.5, y: 0.085 },\n sprite: { kind: 'rect', width: [0.93, 0.93], aspect: [0.0012, 0.0012], color: '#24384f' },\n alpha: [0.8, 0.8],\n motion: { type: 'static' },\n life: { enter: 100, fade: 400 },\n },\n {\n key: 'rule-footer', count: 1,\n position: { x: 0.5, y: 0.915 },\n sprite: { kind: 'rect', width: [0.93, 0.93], aspect: [0.0012, 0.0012], color: '#24384f' },\n alpha: [0.8, 0.8],\n motion: { type: 'static' },\n life: { enter: 100, fade: 400 },\n },\n {\n key: 'rule-col-left', count: 1,\n position: { x: 0.265, y: 0.5 },\n sprite: { kind: 'rect', width: [0.0009, 0.0009], aspect: [620, 620], color: '#1c2c40' },\n alpha: [0.7, 0.7],\n motion: { type: 'static' },\n life: { enter: 100, fade: 400 },\n },\n {\n key: 'rule-col-right', count: 1,\n position: { x: 0.645, y: 0.5 },\n sprite: { kind: 'rect', width: [0.0009, 0.0009], aspect: [620, 620], color: '#1c2c40' },\n alpha: [0.7, 0.7],\n motion: { type: 'static' },\n life: { enter: 100, fade: 400 },\n },\n // ---- header band ----\n {\n key: 'title', count: 1,\n position: { x: 0.035, y: 0.052 },\n sprite: { kind: 'text', strings: ['VIREO-9 · TRANS-LUNAR RELAY · OPS WALL 03'], color: '#7f93ab',\n font: \"600 13px 'SF Mono', monospace\", align: 'left' },\n motion: { type: 'static' },\n life: { enter: 200, fade: 600 },\n },\n {\n key: 'clock', count: 1,\n position: { x: 0.5, y: 0.058 },\n sprite: { kind: 'text', strings: ['04:17:26 UTC'], color: '#c8d4e4',\n font: \"600 20px 'SF Mono', monospace\", align: 'center' },\n motion: { type: 'static' },\n life: { enter: 200, fade: 600 },\n },\n {\n key: 'status', count: 1,\n position: { x: 0.965, y: 0.052 },\n sprite: { kind: 'text', strings: ['● UPLINK LOCKED · WATCH C'], color: '#46d17a',\n font: \"bold 11px 'SF Mono', monospace\", align: 'right' },\n pulse: { amp: 0.18, period: 2600 },\n motion: { type: 'static' },\n life: { enter: 200, fade: 600 },\n },\n // ---- left column: arrays (boots second) ----\n {\n key: 'dish1', count: 1,\n position: { x: 0.035, y: 0.148 },\n sprite: { kind: 'text', strings: ['DSA-1 EAST AZ 214.6° EL 38.2°'], color: '#9fb2c8',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 700, fade: 600 },\n },\n {\n key: 'dish1-bars', count: 14,\n sprite: { kind: 'rect', width: [0.0038, 0.0038], aspect: [0.5, 2.6], color: '#2ee6c8' },\n alpha: [0.3, 0.65],\n layout: { type: 'grid', columns: 14 },\n region: { x: [0.035, 0.15], y: [0.183, 0.203] },\n pulse: { amp: 0.42, period: 1500, wave: { wavelength: 0.09, angle: 0 } },\n motion: { type: 'static' },\n life: { enter: 700, fade: 600 },\n },\n {\n key: 'dish2', count: 1,\n position: { x: 0.035, y: 0.243 },\n sprite: { kind: 'text', strings: ['DSA-2 WEST AZ 097.1° EL 61.7°'], color: '#9fb2c8',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 850, fade: 600 },\n },\n {\n key: 'dish2-bars', count: 14,\n sprite: { kind: 'rect', width: [0.0038, 0.0038], aspect: [0.5, 2.2], color: '#44aaff' },\n alpha: [0.3, 0.6],\n layout: { type: 'grid', columns: 14 },\n region: { x: [0.035, 0.15], y: [0.278, 0.298] },\n pulse: { amp: 0.4, period: 1900, wave: { wavelength: 0.11, angle: 0 } },\n motion: { type: 'static' },\n life: { enter: 850, fade: 600 },\n },\n {\n key: 'dish3', count: 1,\n position: { x: 0.035, y: 0.338 },\n sprite: { kind: 'text', strings: ['DSA-3 POLAR AZ 002.4° EL 12.9° △ WIND'], color: '#5d7089',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1000, fade: 600 },\n },\n {\n key: 'dish3-bars', count: 14,\n sprite: { kind: 'rect', width: [0.0038, 0.0038], aspect: [0.4, 1.1], color: '#5d7089' },\n alpha: [0.2, 0.4],\n layout: { type: 'grid', columns: 14 },\n region: { x: [0.035, 0.15], y: [0.373, 0.393] },\n pulse: { amp: 0.3, period: 2600, wave: { wavelength: 0.14, angle: 0 } },\n motion: { type: 'static' },\n life: { enter: 1000, fade: 600 },\n },\n {\n key: 'dish-leds', count: 3,\n sprite: { kind: 'circle', radius: [0.004, 0.004], color: '#46d17a' },\n alpha: [0.9, 0.9],\n layout: { type: 'grid', columns: 1 },\n region: { x: [0.238, 0.246], y: [0.15, 0.35] },\n pulse: { amp: 0.25, period: 2100 },\n motion: { type: 'static' },\n life: { enter: 1000, fade: 600 },\n },\n // carrier + doppler + station env\n {\n key: 'carrier-wave', count: 30,\n sprite: { kind: 'rect', width: [0.0032, 0.0032], aspect: [0.4, 3.6], color: '#2ee6c8' },\n alpha: [0.25, 0.6],\n layout: { type: 'grid', columns: 30 },\n region: { x: [0.035, 0.245], y: [0.47, 0.5] },\n pulse: { amp: 0.5, period: 2100, wave: { wavelength: 0.16, angle: 0 } },\n motion: { type: 'static' },\n life: { enter: 1150, fade: 600 },\n },\n {\n key: 'doppler', count: 1,\n position: { x: 0.035, y: 0.535 },\n sprite: { kind: 'text', strings: ['CARRIER X-BAND · DOPPLER +2.114 kHz · DRIFT 0.03'], color: '#9fb2c8',\n font: \"10px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1150, fade: 600 },\n },\n {\n key: 'env-line', count: 1,\n position: { x: 0.035, y: 0.6 },\n sprite: { kind: 'text', strings: ['STATION · PWR 28.1 V · THERM 312 K · GYRO NOM · PROP 81%'], color: '#5d7089',\n font: \"10px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1300, fade: 600 },\n },\n // ---- center: the orbital plot (boots third) ----\n {\n key: 'moon', count: 1,\n position: { x: 0.455, y: 0.4 },\n sprite: { kind: 'circle', radius: [0.028, 0.028], color: '#8fa3bd', soft: true },\n alpha: [0.9, 0.9],\n motion: { type: 'static' },\n life: { enter: 1200, fade: 700 },\n },\n {\n key: 'orbit-guides', count: 3,\n // All three guides pin to the plot centre; the seeded radius range\n // spreads them into concentric orbits (`position` is count:1-only).\n region: { x: [0.455, 0.455], y: [0.4, 0.4] },\n sprite: { kind: 'ring', radius: [0.075, 0.185], color: '#1e3a52', width: 0.0011 },\n alpha: [0.55, 0.55],\n motion: { type: 'static' },\n life: { enter: 1200, fade: 700 },\n },\n {\n key: 'fleet',\n count: 5,\n sprite: { kind: 'circle', radius: [0.0045, 0.0065], color: '#2ee6c8',\n colors: ['#2ee6c8', '#44aaff', '#ffd166', '#aa88ff', '#ff9f43'] },\n alpha: [0.85, 0.95],\n blend: 'lighter',\n motion: { type: 'orbit', speed: [4, 11], radius: [0.075, 0.185], center: { x: 0.455, y: 0.4 } },\n trail: { length: 9, fade: 0.75 },\n // The relay web: each craft holds a comm chain to its neighbours.\n links: { k: 2, maxDist: 0.5, color: '#2ee6c8', alpha: 0.2, width: 0.0012, mode: 'chain' },\n life: { enter: 1350, fade: 700 },\n },\n {\n key: 'fleet-legend', count: 1,\n position: { x: 0.455, y: 0.63 },\n sprite: { kind: 'text', strings: ['TRACKING 5 · KESTREL TIDE-2 LIMELIGHT CATWALK-1 SLIPSTREAM'], color: '#5d7089',\n font: \"9px 'SF Mono', monospace\", align: 'center', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1500, fade: 700 },\n },\n // pass schedule under the plot\n {\n key: 'pass-label', count: 1,\n position: { x: 0.3, y: 0.69 },\n sprite: { kind: 'text', strings: ['PASS SCHEDULE'], color: '#41536b',\n font: \"9px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1650, fade: 600 },\n },\n {\n key: 'pass-1', count: 1,\n position: { x: 0.3, y: 0.72 },\n sprite: { kind: 'text', strings: ['04:41 CATWALK-1 ACQUIRE · DSA-1 ▲ 12 MIN'], color: '#c8d4e4',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1650, fade: 600 },\n },\n {\n key: 'pass-2', count: 1,\n position: { x: 0.3, y: 0.757 },\n sprite: { kind: 'text', strings: ['05:03 TIDE-2 OCCULT EXIT · DSA-2'], color: '#7f93ab',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1750, fade: 600 },\n },\n {\n key: 'pass-3', count: 1,\n position: { x: 0.3, y: 0.794 },\n sprite: { kind: 'text', strings: ['05:47 KESTREL RANGING · DSA-1+2'], color: '#7f93ab',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1850, fade: 600 },\n },\n // ---- right column: telemetry (boots fourth) ----\n {\n key: 'signal-label', count: 1,\n position: { x: 0.665, y: 0.115 },\n sprite: { kind: 'text', strings: ['PRIMARY CARRIER · CATWALK-1'], color: '#41536b',\n font: \"9px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1700, fade: 600 },\n },\n {\n key: 'signal-value', count: 1,\n position: { x: 0.665, y: 0.14 },\n sprite: { kind: 'text', strings: ['-112.4 dBm'], color: '#ffd166',\n font: \"bold 30px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1700, fade: 600 },\n },\n {\n key: 'telemetry-row', count: 1,\n position: { x: 0.665, y: 0.215 },\n sprite: { kind: 'text', strings: ['RANGE 1.28 LS DOWNLINK 2.048 Mb/s BUFFER 38%'], color: '#9fb2c8',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1800, fade: 600 },\n },\n // event log\n {\n key: 'feed-1', count: 1,\n position: { x: 0.665, y: 0.3 },\n sprite: { kind: 'text', strings: ['04:15:02 DSA-1 LOCK RE-ACQUIRED'], color: '#9fb2c8',\n font: \"10px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1950, fade: 600 },\n },\n {\n key: 'feed-2', count: 1,\n position: { x: 0.665, y: 0.334 },\n sprite: { kind: 'text', strings: ['04:12:47 CATWALK-1 WHEEL DESAT OK'], color: '#7f93ab',\n font: \"10px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 2050, fade: 600 },\n },\n {\n key: 'feed-3', count: 1,\n position: { x: 0.665, y: 0.368 },\n sprite: { kind: 'text', strings: ['04:09:31 RANGING RESIDUAL 0.4 m'], color: '#5d7089',\n font: \"10px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 2150, fade: 600 },\n },\n // alert + relay load\n {\n key: 'alert', count: 1,\n position: { x: 0.665, y: 0.49 },\n sprite: { kind: 'text', strings: ['△ SOLAR FLUX ELEVATED — MONITORING'], color: '#ff9f43',\n font: \"bold 11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n pulse: { amp: 0.22, period: 3400 },\n motion: { type: 'static' },\n life: { enter: 2450, fade: 600 },\n },\n {\n key: 'load-bars', count: 24,\n sprite: { kind: 'rect', width: [0.0042, 0.0042], aspect: [0.5, 3.2],\n color: '#aa88ff', colors: ['#aa88ff', '#44aaff', '#2ee6c8'], colorWeights: [2, 2, 3] },\n alpha: [0.3, 0.65],\n layout: { type: 'grid', columns: 24 },\n region: { x: [0.665, 0.965], y: [0.58, 0.615] },\n pulse: { amp: 0.45, period: 1800, wave: { wavelength: 0.12, angle: 0 } },\n motion: { type: 'static' },\n life: { enter: 2550, fade: 600 },\n },\n {\n key: 'load-note', count: 1,\n position: { x: 0.665, y: 0.65 },\n sprite: { kind: 'text', strings: ['RELAY LOAD · QUEUE 14 FRAMES · NOMINAL'], color: '#5d7089',\n font: \"10px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 2550, fade: 600 },\n },\n // ---- footer band ----\n {\n key: 'footer', count: 1,\n position: { x: 0.035, y: 0.95 },\n sprite: { kind: 'text', strings: ['NET STATE GREEN · 3 ARRAYS · 5 CARRIERS · DSN HANDOVER 23:34 · NEXT WINDOW 04:41:00'], color: '#41536b',\n font: \"9px 'SF Mono', monospace\", align: 'left' },\n motion: { type: 'static' },\n life: { enter: 2750, fade: 600 },\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Sparse Night — emptiness, declared as intent.\n * A star-grain field (radius under 0.001 — the rung FORMAT.md's ladder calls\n * texture, never the subject) over near-black, one faint linked pentagon as\n * the only figure, and a single satellite that flares for three seconds out of\n * every eighteen. Measured coverage sits around one percent, which `adviseSpec`\n * would flag as `sparse-scene` at every legal count — the spec's\n * `density: 'sparse'` declaration is the point of this example: it withholds\n * that advisory AND opts the scene into `density-mismatch` instead, so the\n * emptiness is a claim the perception API checks rather than a gap it nags\n * about. Before `density` shipped, restraint like this could not pass advise\n * clean; the one-mark house style sat at the suite floor for exactly this\n * reason.\n */\nexport const SPARSE_NIGHT_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"sparse-night\",\n label: \"Sparse Night\",\n seed: 101,\n motionIntensity: \"calm\",\n density: \"sparse\",\n background: { type: \"solid\", color: \"#02030a\" },\n layers: [\n {\n key: \"grain\",\n count: 110,\n sprite: {\n kind: \"circle\",\n radius: [0.0003, 0.0009],\n color: \"#c9d4e6\",\n },\n motion: { type: \"static\" },\n alpha: [0.05, 0.3],\n pulse: { amp: 0.08, period: 7000 },\n },\n {\n key: \"figure\",\n count: 5,\n sprite: {\n kind: \"circle\",\n radius: [0.0016, 0.0022],\n color: \"#dfe8f2\",\n },\n motion: { type: \"drift\", speed: [0.0004, 0.0009] },\n alpha: [0.4, 0.7],\n region: { x: [0.36, 0.64], y: [0.32, 0.62] },\n links: {\n k: 2,\n maxDist: 0.09,\n color: \"#7f97b8\",\n alpha: 0.16,\n width: 0.0004,\n mode: \"chain\",\n closed: true,\n },\n },\n {\n key: \"satellite\",\n count: 1,\n sprite: {\n kind: \"circle\",\n radius: [0.0024, 0.0024],\n color: \"#e8b04a\",\n soft: true,\n },\n motion: { type: \"orbit\", speed: [3, 3], radius: [0.34, 0.4] },\n alpha: [0.85, 0.85],\n blend: \"lighter\",\n emit: { every: 18000, life: 3000, jitter: 0, grow: [0.5, 1.6] },\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Signal Board — the instrument panel, laid out by the format.\n * A 3×3 table of data bars with their labels in a matching table, one\n * monospace caption, and a phosphor sweep crossing the frame every ~90\n * seconds. The teaching layer is `layout: { type: 'table', columns: 3 }`:\n * nine bars and nine labels are TWO layers, not eighteen positioned blocks —\n * entity i reads `values[i]` / `strings[i]` in reading order, and each bar\n * draws `length × values[i] / max` from its cell. `values` are paint, so\n * `setParam(\"readout.sprite.values\", [...])` glides every bar at once, which\n * is the whole point of the shape: a live readout that never re-publishes.\n */\nexport const SIGNAL_BOARD_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"signal-board\",\n label: \"Signal Board\",\n seed: 707,\n motionIntensity: \"calm\",\n background: { type: \"solid\", color: \"#0d0b08\" },\n layers: [\n {\n key: \"readout\",\n count: 9,\n sprite: {\n kind: \"bar\",\n values: [62, 38, 84, 21, 55, 91, 44, 70, 29],\n max: 100,\n // Cell pitch is the table's authored `gap` (0.07), so a full-value\n // bar must stay under that or neighboring cells' bars overlap.\n // 0.06 leaves a hairline margin.\n length: 0.06,\n thickness: 0.013,\n color: \"#ffb000\",\n direction: \"right\",\n },\n motion: { type: \"static\" },\n layout: { type: \"table\", columns: 3, gap: 0.07 },\n region: { x: [0.1, 0.9], y: [0.34, 0.78] },\n alpha: [0.5, 0.62],\n },\n {\n key: \"labels\",\n count: 9,\n sprite: {\n kind: \"text\",\n strings: [\n \"A-01\",\n \"A-02\",\n \"A-03\",\n \"B-01\",\n \"B-02\",\n \"B-03\",\n \"C-01\",\n \"C-02\",\n \"C-03\",\n ],\n color: \"#b08a3a\",\n font: \"monospace\",\n align: \"left\",\n },\n motion: { type: \"static\" },\n size: [0.011, 0.011],\n layout: { type: \"table\", columns: 3, gap: 0.07 },\n region: { x: [0.1, 0.9], y: [0.28, 0.72] },\n alpha: [0.55, 0.55],\n },\n {\n key: \"caption\",\n count: 1,\n sprite: {\n kind: \"textBlock\",\n text: \"STATION 7 — QUIET HOURS\",\n maxWidth: 0.6,\n fontSize: 0.022,\n lineHeight: 1.4,\n align: \"left\",\n anchor: \"top-left\",\n font: \"bold monospace\",\n color: \"#c8862a\",\n },\n motion: { type: \"static\" },\n position: { x: 0.1, y: 0.14 },\n alpha: [0.8, 0.8],\n },\n {\n key: \"sweep\",\n count: 1,\n sprite: {\n kind: \"stroke\",\n length: [1.4, 1.4],\n points: [\n [-1, 0],\n [1, 0],\n ],\n width: 0.0016,\n color: \"#33ff66\",\n },\n motion: { type: \"drift\", speed: [0.012, 0.012], angle: 90 },\n alpha: [0.22, 0.22],\n blend: \"screen\",\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Phase Duet — three layers on one clock.\n * A grid of sixty dots ripples as a traveling wave (`pulse.wave`), three rings\n * swell, and one soft heart breathes — and none of them drift apart, because\n * all three declare the same `clock`. `clock` is the format's answer to\n * coincidence: without it, `pulse`, `grow` and `cycle` run on per-entity\n * seeded phases, so two layers with the same period never line up (they are\n * a room full of people, not a duet). With one shared `clock: { phase: 0,\n * rate: 1 }` they breathe in step and stay there — period ÷ rate must stay\n * ≥ 1000 ms, which is why every layer here runs a 6000 ms cycle.\n */\nexport const PHASE_DUET_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"phase-duet\",\n label: \"Phase Duet\",\n seed: 88,\n motionIntensity: \"calm\",\n background: {\n type: \"gradient\",\n stops: [\n { at: 0, color: \"#0a0f1c\" },\n { at: 0.6, color: \"#101b2e\" },\n { at: 1, color: \"#07141a\" },\n ],\n },\n layers: [\n {\n key: \"ripple\",\n count: 60,\n sprite: {\n kind: \"circle\",\n radius: [0.0018, 0.003],\n color: \"#6fd3c7\",\n colors: [\"#6fd3c7\", \"#9fb8d8\"],\n colorWeights: [2, 1],\n },\n motion: { type: \"static\" },\n layout: { type: \"grid\", columns: 10, jitter: 0 },\n alpha: [0.3, 0.55],\n pulse: { amp: 0.35, period: 6000, wave: { wavelength: 0.7, angle: 25 } },\n clock: { phase: 0, rate: 1 },\n },\n {\n key: \"rings\",\n count: 3,\n sprite: {\n kind: \"ring\",\n radius: [0.05, 0.09],\n width: 0.0012,\n color: \"#6fd3c7\",\n },\n motion: { type: \"static\" },\n alpha: [0.25, 0.35],\n blend: \"lighter\",\n grow: { amp: 0.5, period: 6000 },\n clock: { phase: 0, rate: 1 },\n },\n {\n key: \"heart\",\n count: 1,\n sprite: {\n kind: \"circle\",\n radius: [0.11, 0.11],\n color: \"#9fb8d8\",\n soft: true,\n },\n motion: { type: \"static\" },\n position: { x: 0.5, y: 0.5 },\n alpha: [0.22, 0.22],\n blend: \"lighter\",\n grow: { amp: 0.25, period: 6000 },\n clock: { phase: 0, rate: 1 },\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Web Work — a randomised graph that fades with distance.\n * Forty-four drifting nodes wired `mode: 'random'` (a fixed deterministic\n * wiring, not k-nearest — the difference is topology: nearest gives\n * crystalline clusters, random gives a web that crosses itself) with\n * `falloff: true`, so an edge's alpha fades toward `maxDist` instead of\n * popping in at the cutoff. The second layer is a row of `orient: true`\n * strokes: the mark's +x axis turns to follow the entity's heading, so each\n * one reads as a wind tick rather than a stamp. Both are the difference\n * between \"lines between dots\" and a drawing.\n */\nexport const WEB_WORK_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"web-work\",\n label: \"Web Work\",\n seed: 31,\n motionIntensity: \"calm\",\n background: { type: \"solid\", color: \"#04070c\" },\n layers: [\n {\n key: \"nodes\",\n count: 44,\n sprite: {\n kind: \"circle\",\n radius: [0.0018, 0.0034],\n color: \"#8fb4d8\",\n colors: [\"#8fb4d8\", \"#c9d8e6\"],\n colorWeights: [2, 1],\n },\n motion: {\n type: \"drift\",\n speed: [0.002, 0.006],\n angle: 0,\n bidirectional: true,\n },\n alpha: [0.45, 0.8],\n links: {\n k: 3,\n maxDist: 0.3,\n color: \"#5f7f9f\",\n alpha: 0.16,\n width: 0.0005,\n mode: \"random\",\n falloff: true,\n },\n },\n {\n key: \"flags\",\n count: 22,\n sprite: {\n kind: \"stroke\",\n length: [0.02, 0.045],\n points: [\n [-1, 0.2],\n [-0.2, -0.5],\n [0.6, -0.3],\n [1, 0.1],\n ],\n width: 0.0016,\n taper: true,\n orient: true,\n color: \"#6f93b8\",\n colors: [\"#6f93b8\", \"#9fb8d8\"],\n },\n motion: {\n type: \"drift\",\n speed: [0.01, 0.03],\n angle: 0,\n bidirectional: true,\n },\n alpha: [0.3, 0.6],\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Shard Fall — tumbling shapes and a passing shadow.\n * Two features nothing else here uses. `rotate` is STATIC per-entity rotation\n * (a range seeded per entity), which is not the same as `spin: [0, 0]` — a\n * zero spin speed renders the seeded start angle as 0, so \"tilted but not\n * turning\" was previously inexpressible; here the shards are thrown at\n * `rotate: [-180, 180]` AND tumbling on their own `spin` range, so no two\n * facets agree on an angle. The shadow layer demonstrates `blend:\n * 'multiply'`: two large soft discs darkening a pale plate as they wander,\n * which is how the format does shadow and silhouette — `lighter` adds light,\n * `multiply` removes it, and neither needs a sprite that looks like darkness.\n * The polygons use `points` (unit coordinates scaled by `radius`), which are\n * paint, so two shards with the same point count will morph into each other.\n */\nexport const SHARD_FALL_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"shard-fall\",\n label: \"Shard Fall\",\n seed: 214,\n motionIntensity: \"moderate\",\n background: {\n type: \"gradient\",\n stops: [\n { at: 0, color: \"#efe6d6\" },\n { at: 0.55, color: \"#e6d6bd\" },\n { at: 1, color: \"#d9c39f\" },\n ],\n },\n layers: [\n {\n key: \"shards\",\n count: 26,\n sprite: {\n kind: \"polygon\",\n points: [\n [-1, 0.35],\n [-0.25, -1],\n [0.85, -0.4],\n [0.4, 0.9],\n ],\n radius: [0.012, 0.03],\n color: \"#b4593a\",\n colors: [\"#b4593a\", \"#7f8a5e\", \"#5a6b7d\", \"#8a5a3c\"],\n colorWeights: [2, 2, 1, 2],\n },\n motion: { type: \"drift\", speed: [0.012, 0.032], angle: 90 },\n alpha: [0.85, 0.95],\n rotate: [-180, 180],\n spin: [-35, 35],\n },\n {\n key: \"shadows\",\n count: 2,\n sprite: {\n kind: \"circle\",\n radius: [0.18, 0.22],\n color: \"#5a4a34\",\n soft: true,\n },\n motion: {\n type: \"wander\",\n speed: [0.003, 0.005],\n meander: 0.04,\n coherence: 0.6,\n },\n alpha: [0.2, 0.28],\n blend: \"multiply\",\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Murmur — a flock with no birds in it.\n * Six hundred and twenty entities: two registers of streaks (260 each) on\n * harmonic `wander` with `coherence` near 1, so each layer folds and wheels as\n * one body, and a static grain layer behind them. Nothing here\n * interacts — no entity reads another's position — which is the trick the\n * format is built on: a shared harmonic set plus a wide speed range reads as\n * a murmuration while staying a pure function of (seed, t), so it replays\n * identically and seeks instantly. `density: 'dense'` is doing real work:\n * past 500 entities `adviseSpec` raises `dense-scene`, and the declaration\n * says the crowding is the subject rather than a mistake — while still opting\n * into `density-mismatch` if the scene ever measures as empty instead.\n */\nexport const MURMUR_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"murmur\",\n label: \"Murmur\",\n seed: 512,\n motionIntensity: \"moderate\",\n density: \"dense\",\n background: {\n type: \"gradient\",\n stops: [\n { at: 0, color: \"#151a26\" },\n { at: 0.5, color: \"#232c3d\" },\n { at: 1, color: \"#3a3f52\" },\n ],\n },\n layers: [\n {\n key: \"flock-a\",\n count: 260,\n sprite: {\n kind: \"streak\",\n length: [0.004, 0.012],\n width: 0.0012,\n color: \"#c9d4e6\",\n colors: [\"#c9d4e6\", \"#8fa6c4\"],\n colorWeights: [2, 1],\n },\n motion: {\n type: \"wander\",\n speed: [0.015, 0.06],\n meander: 0.05,\n coherence: 0.95,\n },\n alpha: [0.25, 0.6],\n blend: \"screen\",\n },\n {\n // The cap is 400 per layer, so a flock above it is two registers of the\n // same body — slightly different speed and length ranges read as depth.\n key: \"flock-b\",\n count: 260,\n sprite: {\n kind: \"streak\",\n length: [0.006, 0.014],\n width: 0.0012,\n color: \"#8fa6c4\",\n colors: [\"#8fa6c4\", \"#c9d4e6\"],\n colorWeights: [2, 1],\n },\n motion: {\n type: \"wander\",\n speed: [0.02, 0.05],\n meander: 0.045,\n coherence: 0.93,\n },\n alpha: [0.2, 0.5],\n blend: \"screen\",\n },\n {\n key: \"grain\",\n count: 100,\n sprite: { kind: \"circle\", radius: [0.0005, 0.0012], color: \"#c9d4e6\" },\n motion: { type: \"static\" },\n alpha: [0.06, 0.2],\n },\n ],\n};\n","import type { IdleSequence } from \"../types\";\n\n/**\n * Three Movements — one ground, three scenes, two kinds of transition.\n *\n * The sequence envelope, exercised end to end:\n *\n * - **bed.** A drifting field with a few motes, drawn under every segment on\n * the SEQUENCE clock — it does not reset at a boundary and a\n * `sequence.segment` steer cannot rewind it. That is the fix for the\n * boundary rewind every ambient sequence suffers: put the motion that must\n * be continuous in the bed, the slide content in the segments. (Segments\n * deliberately declare no `background`: over a bed it is never painted on\n * the web, and the validator warns `bed-hides-segment-background` — the\n * native tvOS player, which ignores the bed, will show them over black\n * until it learns the field. Prefer a bed the piece can survive without.)\n * - **morph + text crossfade.** Segments 1 → 2 are structural twins differing\n * only in colour and words, so the transition can MORPH: every numeric and\n * hex value glides over 2500 ms, and because the words differ and the\n * transition declares `text: 'crossfade'`, the outgoing caption fades under\n * the incoming one instead of switching whole-frame. Without the crossfade\n * declaration the morph would still glide — colour alone gives it a\n * `hasGlide` — just with the caption stepping on the first frame instead of\n * fading; the validator only says `morph-nothing-morphable` for a pair\n * whose differences are all values morph cannot glide — strings\n * (`textBlock.text` above all), booleans, mismatched arrays — which this\n * one isn't.\n * - **fade.** Segments 2 → 3 have nothing structurally in common, so a morph\n * is impossible and a `fade` is the honest transition: the outgoing scene\n * keeps animating on its own canvas for 3000 ms while the incoming one\n * fades up. The cost is two live segments during the window, which is why\n * the lowest capability tier degrades a fade to a cut\n * (`fade-degrades-on-low-tier` — informational, and this sequence keeps the\n * fade because the web and native players both honour it).\n * - **finish.** One grain-and-dither pass over the composed frame — bed,\n * segment and any fade together — the sequence-level screen no segment can\n * override.\n *\n * The final segment carries no duration, so it holds indefinitely; `loop` is\n * therefore false (`loop: true` is incompatible with a durationless segment).\n * `sync: 'mount'` is the default and the reason a joiner always sees movement\n * one: pre-roll semantics. An `epoch` sequence would instead start every\n * viewer at the room's shared clock — right for a wall of screens, wrong for\n * a piece that should start when you look at it.\n */\nexport const THREE_MOVEMENTS_SEQUENCE: IdleSequence = {\n format: \"idle-sequence\",\n schemaVersion: 1,\n id: \"three-movements\",\n label: \"Three Movements\",\n seed: 404,\n loop: false,\n sync: \"mount\",\n finish: { grain: 0.3, dither: 0.12 },\n bed: {\n schemaVersion: 1,\n id: \"three-movements-bed\",\n label: \"Three Movements — bed\",\n background: {\n type: \"field\",\n scale: 2.0,\n octaves: 3,\n warp: 0.4,\n quantize: 0,\n bands: [\"#0a0d18\", \"#141c2e\", \"#233046\"],\n drift: { period: 60000, amount: 0.25 },\n },\n layers: [\n {\n key: \"motes\",\n count: 12,\n sprite: {\n kind: \"circle\",\n radius: [0.0012, 0.003],\n color: \"#9fb8d8\",\n soft: true,\n },\n motion: { type: \"drift\", speed: [0.002, 0.006], angle: 90 },\n alpha: [0.1, 0.25],\n },\n ],\n },\n segments: [\n {\n key: \"cold-open\",\n duration: 8000,\n transition: { type: \"morph\", dur: 2500, text: \"crossfade\" },\n scene: {\n schemaVersion: 1,\n id: \"three-movements-cold-open\",\n label: \"Cold Open\",\n seed: 11,\n layers: [\n {\n key: \"caption\",\n count: 1,\n sprite: {\n kind: \"textBlock\",\n text: \"COLD OPEN.\\nThe room before anyone arrives.\",\n maxWidth: 0.6,\n fontSize: 0.028,\n lineHeight: 1.5,\n align: \"left\",\n anchor: \"top-left\",\n font: \"monospace\",\n color: \"#9fb8d8\",\n opacity: 0.9,\n reveal: {\n progress: 1,\n mode: \"typewriter\",\n speed: 12,\n caret: { blink: 1.1 },\n },\n },\n motion: { type: \"static\" },\n position: { x: 0.1, y: 0.4 },\n alpha: [0.9, 0.9],\n },\n {\n key: \"sparks\",\n count: 30,\n sprite: {\n kind: \"circle\",\n radius: [0.0012, 0.0026],\n color: \"#c9d8e6\",\n },\n motion: { type: \"static\" },\n alpha: [0.15, 0.45],\n pulse: { amp: 0.12, period: 6000 },\n },\n ],\n },\n },\n {\n key: \"kindle\",\n duration: 9000,\n transition: { type: \"fade\", dur: 3000 },\n scene: {\n schemaVersion: 1,\n id: \"three-movements-kindle\",\n label: \"Kindle\",\n seed: 12,\n layers: [\n {\n key: \"caption\",\n count: 1,\n sprite: {\n kind: \"textBlock\",\n text: \"KINDLE.\\nOne lamp, and then another.\",\n maxWidth: 0.6,\n fontSize: 0.028,\n lineHeight: 1.5,\n align: \"left\",\n anchor: \"top-left\",\n font: \"monospace\",\n color: \"#e8b878\",\n opacity: 0.9,\n reveal: {\n progress: 1,\n mode: \"typewriter\",\n speed: 12,\n caret: { blink: 1.1 },\n },\n },\n motion: { type: \"static\" },\n position: { x: 0.1, y: 0.4 },\n alpha: [0.9, 0.9],\n },\n {\n key: \"sparks\",\n count: 30,\n sprite: {\n kind: \"circle\",\n radius: [0.0012, 0.0026],\n color: \"#e8b878\",\n },\n motion: { type: \"static\" },\n alpha: [0.15, 0.45],\n pulse: { amp: 0.12, period: 6000 },\n },\n ],\n },\n },\n {\n key: \"dusk\",\n scene: {\n schemaVersion: 1,\n id: \"three-movements-dusk\",\n label: \"Dusk\",\n seed: 13,\n layers: [\n {\n key: \"bloom\",\n count: 3,\n sprite: {\n kind: \"circle\",\n radius: [0.09, 0.14],\n color: \"#7a4a5e\",\n colors: [\"#7a4a5e\", \"#b06a4a\"],\n soft: true,\n },\n motion: {\n type: \"wander\",\n speed: [0.001, 0.002],\n meander: 0.04,\n coherence: 0.7,\n },\n alpha: [0.25, 0.4],\n blend: \"lighter\",\n grow: { amp: 0.3, period: 14000 },\n },\n {\n key: \"strokes\",\n count: 8,\n sprite: {\n kind: \"stroke\",\n length: [0.1, 0.2],\n points: [\n [-1, 0.2],\n [-0.3, -0.6],\n [0.5, -0.4],\n [1, 0.2],\n ],\n width: 0.004,\n taper: true,\n color: \"#c2447a\",\n colors: [\"#c2447a\", \"#8f2c58\"],\n },\n motion: {\n type: \"drift\",\n speed: [0.003, 0.008],\n angle: 20,\n bidirectional: true,\n },\n alpha: [0.3, 0.5],\n rotate: [-30, 30],\n },\n ],\n },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Facets — a composition in the manner of the early abstractionists: three\n * soft-edged colour planes (feathered `rect`) breathing slowly behind a field\n * of tumbling triangular facets (custom `polygon`), tapered brush arcs\n * (`stroke`) drifting across, and a few glowing hexagons (soft regular\n * `polygon`). Every glyph here is a path, not a disc — the shape family nine\n * of the fifteen style profiles asked for.\n */\nexport const FACETS_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'facets',\n label: 'Facets',\n seed: 1911,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#101626' },\n { at: 1, color: '#1c1a2e' },\n ],\n },\n layers: [\n {\n key: 'planes',\n count: 3,\n sprite: {\n kind: 'rect',\n width: [0.28, 0.42],\n aspect: [0.6, 1.4],\n color: '#b3402f',\n colors: ['#b3402f', '#c9862b', '#2d4f8a'],\n feather: 0.6,\n },\n alpha: [0.35, 0.5],\n region: { x: [0.2, 0.8], y: [0.2, 0.8] },\n motion: { type: 'wander', speed: [0.001, 0.003], meander: 0.02 },\n spin: [-2, 2],\n },\n {\n key: 'facets',\n count: 14,\n sprite: {\n kind: 'polygon',\n radius: [0.02, 0.06],\n points: [[-1, 0.9], [0.2, -1], [1, 0.4]],\n color: '#f2e8c9',\n colors: ['#f2e8c9', '#e0b53a', '#6fa8dc', '#d94f3d'],\n },\n alpha: [0.6, 0.9],\n motion: { type: 'wander', speed: [0.003, 0.008], meander: 0.03 },\n spin: [-8, 8],\n },\n {\n key: 'arcs',\n count: 12,\n sprite: {\n kind: 'stroke',\n length: [0.08, 0.18],\n points: [[-1, 0.3], [-0.5, -0.6], [0.3, -0.7], [1, 0.1]],\n width: 0.004,\n taper: true,\n color: '#f2e8c9',\n },\n alpha: [0.5, 0.8],\n motion: { type: 'drift', speed: [0.004, 0.01], angle: 20, bidirectional: true },\n spin: [-4, 4],\n },\n {\n key: 'hexes',\n count: 8,\n sprite: { kind: 'polygon', radius: [0.008, 0.016], sides: 6, color: '#e0b53a', soft: true },\n alpha: [0.5, 0.8],\n blend: 'lighter',\n motion: { type: 'wander', speed: [0.002, 0.005] },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/** Haiku: a centered text block with a slowly drifting haiku over deep indigo. */\nexport const HAIKU_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'haiku',\n label: 'Haiku',\n seed: 42,\n background: { type: 'solid', color: '#080812' },\n layers: [\n {\n count: 1,\n sprite: {\n kind: 'textBlock',\n text: 'An old silent pond\\nA frog jumps into the pond —\\nSplash! Silence again.',\n maxWidth: 0.8,\n fontSize: 0.05,\n lineHeight: 1.8,\n align: 'center',\n color: '#c8cad4',\n },\n motion: { type: 'static' },\n position: { x: 0.1, y: 0.35 },\n },\n {\n count: 30,\n sprite: { kind: 'circle', radius: [0.0005, 0.0015], color: '#3a3a5c' },\n motion: { type: 'drift', speed: [0.002, 0.006], angle: 270 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Night Lanterns (Yi Peng festival sky): depth from four correlated parallax cues —\n * closer layers are LARGER, FASTER, SWAY WIDER, and glow WARMER/BRIGHTER. v2 of this\n * composition exercises the expressive additions the first draft exposed as missing:\n * soft glow orbs + additive blend (lantern light that sums where it overlaps), bounded\n * alpha pulse with per-entity phases (breathing flames, strobe-proof by construction),\n * and spawn regions (stars only above the horizon; dim ember shimmer kept low near\n * the water line).\n */\nexport const LANTERNS_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'lanterns',\n label: 'Night Lanterns',\n seed: 88,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#04060f' },\n { at: 0.55, color: '#0b1026' },\n { at: 0.85, color: '#251731' },\n { at: 1, color: '#472518' },\n ],\n },\n layers: [\n {\n count: 60,\n sprite: { kind: 'circle', radius: [0.000463, 0.001296], color: '#8fa0c8' },\n alpha: [0.35, 1],\n region: { y: [0, 0.62] },\n motion: { type: 'drift', speed: [0.000463, 0.001852], bob: 0.0009259 },\n },\n {\n count: 36,\n sprite: {\n kind: 'circle',\n radius: [0.001389, 0.002778],\n color: '#b06a2a',\n soft: true,\n },\n alpha: [0.5, 0.9],\n blend: 'lighter',\n pulse: { amp: 0.18, period: 2800 },\n motion: { type: 'rise', speed: [0.005556, 0.01296], sway: 0.003704 },\n },\n {\n count: 14,\n sprite: {\n kind: 'circle',\n radius: [0.003241, 0.006019],\n color: '#e08a34',\n soft: true,\n },\n alpha: [0.6, 1],\n blend: 'lighter',\n pulse: { amp: 0.22, period: 3400 },\n motion: { type: 'rise', speed: [0.01481, 0.02593], sway: 0.006481 },\n },\n {\n count: 8,\n sprite: { kind: 'emoji', glyphs: ['🏮'] },\n size: [0.02407, 0.04074],\n alpha: [0.85, 1],\n motion: { type: 'rise', speed: [0.02778, 0.04444], sway: 0.009259 },\n },\n {\n count: 4,\n sprite: { kind: 'emoji', glyphs: ['🏮'] },\n size: [0.0537, 0.07778],\n motion: { type: 'rise', speed: [0.04815, 0.06852], sway: 0.01296 },\n },\n {\n count: 12,\n sprite: { kind: 'circle', radius: [0.001852, 0.00463], color: '#e08a34', soft: true },\n alpha: [0.12, 0.35],\n blend: 'lighter',\n region: { y: [0.93, 1] },\n pulse: { amp: 0.1, period: 2200 },\n motion: { type: 'drift', speed: [0.001852, 0.005556], bob: 0.001852 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Lobby Talk — one screen of a \"quarter in review\" that runs on a lobby wall\n * between meetings: a five-row adoption chart over the same slow haze and\n * dust the whole talk shares. The words are the point, so every text layer\n * declares `role: 'read'` — the opt-in that turns on `adviseSpec`'s\n * legibility advisories (`text-legibility` against the ground *and* the\n * brightest additive layer that can sit under a line, `text-safe-area` for\n * the bezel zone). Tuned to zero advisories: the haze is bright enough to\n * matter and dim enough to leave every label above 4.5:1 at its peak.\n *\n * Schema exercises: `role: 'read'` on both `textBlock` and `text`, a\n * `list`-laid chart in three layers (labels, `bar`s, readouts), additive\n * atmosphere (`lighter` soft circles with `pulse`) under readable copy.\n * Steer `bars.sprite.values` to change the numbers live.\n */\nexport const LOBBY_TALK_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'lobby-talk',\n label: 'Lobby Talk',\n seed: 1207,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#060912' },\n { at: 1, color: '#0b1224' },\n ],\n drift: { period: 40000, amount: 0.1 },\n },\n layers: [\n {\n key: 'haze',\n count: 3,\n sprite: { kind: 'circle', radius: [0.22, 0.3], soft: true, color: '#123a4a', colors: ['#123a4a', '#2a1e4a', '#0e2a3a'] },\n alpha: [0.35, 0.5],\n blend: 'lighter',\n region: { x: [0.2, 0.8], y: [0.3, 0.7] },\n motion: { type: 'wander', speed: [0.002, 0.004], meander: 0.05 },\n pulse: { amp: 0.15, period: 9000 },\n },\n {\n key: 'dust',\n count: 50,\n sprite: { kind: 'circle', radius: [0.0008, 0.0018], soft: true, color: '#7fb8c9' },\n alpha: [0.2, 0.5],\n blend: 'lighter',\n motion: { type: 'wander', speed: [0.001, 0.003] },\n },\n {\n key: 'title',\n count: 1,\n sprite: { kind: 'textBlock', text: 'Adoption by feature, % of accounts', maxWidth: 1.0, fontSize: 0.034, color: '#f2f4f8', role: 'read' },\n motion: { type: 'static' },\n position: { x: 0.12, y: 0.16 },\n },\n {\n key: 'labels',\n count: 5,\n sprite: { kind: 'text', strings: ['Onboarding', 'Search', 'Billing', 'Exports', 'Mobile'], font: 'system-ui', align: 'left', baseline: 'middle', color: '#a9b7cc', role: 'read' },\n size: [0.03, 0.03],\n motion: { type: 'static' },\n position: { x: 0.12, y: 0.32 },\n layout: { type: 'list', gap: 0.085 },\n },\n {\n key: 'bars',\n count: 5,\n sprite: {\n kind: 'bar',\n values: [82, 64, 91, 37, 58],\n max: 100,\n length: 0.42,\n thickness: 0.026,\n color: '#7fe0d2',\n colors: ['#7fe0d2', '#7fe0d2', '#ffcf7a', '#7fe0d2', '#7fe0d2'],\n },\n alpha: [0.9, 0.9],\n motion: { type: 'static' },\n position: { x: 0.33, y: 0.32 },\n layout: { type: 'list', gap: 0.085 },\n },\n {\n key: 'readouts',\n count: 5,\n sprite: { kind: 'text', strings: ['82%', '64%', '91%', '37%', '58%'], font: 'bold system-ui', align: 'left', baseline: 'middle', color: '#f2f4f8', role: 'read' },\n size: [0.03, 0.03],\n motion: { type: 'static' },\n position: { x: 0.78, y: 0.32 },\n layout: { type: 'list', gap: 0.085 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Matrix Rain: showcases `layout: grid` with per-axis jitter ({ y: 1 } keeps the\n * columns crisp while de-syncing them vertically), glyph `cycle`, and `ghosting`\n * doing the classic fading-trail work. Two depths of rain plus rare bright heads.\n */\nexport const MATRIX_RAIN_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'matrix-rain',\n label: 'Matrix Rain',\n seed: 1999,\n motionIntensity: 'moderate',\n ghosting: 0.88,\n background: { type: 'solid', color: '#010401' },\n layers: [\n {\n key: 'rain-far',\n count: 64,\n sprite: {\n kind: 'text',\n strings: ['ア', 'カ', 'サ', 'タ', 'ナ', 'ハ', 'マ', 'ヤ', 'ラ', 'ワ', '0', '1', '7', 'Z', 'X', 'K'],\n color: '#1c7a2e',\n font: 'bold monospace',\n cycle: { period: 900 },\n },\n size: [0.014, 0.02],\n layout: { type: 'grid', columns: 32, jitter: { y: 1 } },\n motion: { type: 'drift', speed: [0.06, 0.14], angle: 90 },\n alpha: [0.35, 0.6],\n },\n {\n key: 'rain-near',\n count: 40,\n sprite: {\n kind: 'text',\n strings: ['ミ', 'ネ', 'リ', 'ソ', 'ツ', 'ヌ', 'ホ', 'ユ', '3', '8', '9', 'V', 'N'],\n color: '#2ecc40',\n font: 'bold monospace',\n cycle: { period: 700 },\n },\n size: [0.022, 0.03],\n layout: { type: 'grid', columns: 20, jitter: { y: 1 } },\n motion: { type: 'drift', speed: [0.16, 0.3], angle: 90 },\n alpha: [0.6, 0.9],\n },\n {\n key: 'heads',\n count: 12,\n sprite: {\n kind: 'text',\n strings: ['ケ', 'メ', 'エ', 'ム', 'ヲ', '5', '2'],\n color: '#c8ffd4',\n font: 'bold monospace',\n cycle: { period: 500 },\n },\n size: [0.024, 0.032],\n layout: { type: 'grid', columns: 12, jitter: { y: 1 } },\n motion: { type: 'drift', speed: [0.2, 0.34], angle: 90 },\n alpha: [0.9, 1],\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Tarkovsky — Nostalghia's candle: a single point of devotion.\n * Near-black warm ground; one small warm-white flame at center with grow/pulse\n * wobble; faint smoke rising; sparse amber embers with long fading trails;\n * a wide near-invisible halo breathing on a 10s cycle. Minimalism as tension —\n * most of the screen is darkness.\n *\n * Note: `pulse.amp` is ADDED to base alpha (not multiplied), so the halo's amp\n * must stay below its base alpha or the trough clamps to fully invisible.\n */\nexport const NOSTALGHIA_CANDLE_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'nostalghia-candle',\n label: \"Nostalghia's Candle\",\n seed: 1983,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#050302' },\n { at: 0.55, color: '#0a0704' },\n { at: 1, color: '#120c08' },\n ],\n },\n layers: [\n {\n key: 'halo',\n count: 1,\n position: { x: 0.5, y: 0.52 },\n sprite: {\n kind: 'circle',\n radius: [0.11, 0.11],\n color: '#c4782a',\n soft: true,\n },\n // Base 0.04 + amp 0.02 → breathes ~0.02..0.06; never clamps to 0.\n // (pulse.amp is ADDED to alpha, not multiplied.) Kept subordinate to the flame.\n alpha: [0.04, 0.04],\n blend: 'lighter',\n pulse: { amp: 0.02, period: 10000 },\n grow: { amp: 0.08, period: 10000 },\n motion: { type: 'static' },\n },\n {\n key: 'smoke',\n count: 3,\n sprite: {\n kind: 'circle',\n radius: [0.01, 0.022],\n color: '#6a6258',\n soft: true,\n },\n alpha: [0.02, 0.04],\n blend: 'lighter',\n region: { x: [0.46, 0.54], y: [0.36, 0.48] },\n pulse: { amp: 0.015, period: 4500 },\n motion: { type: 'rise', speed: [0.002, 0.004], sway: 0.008 },\n },\n {\n key: 'flame-glow',\n count: 1,\n sprite: {\n kind: 'circle',\n radius: [0.028, 0.028],\n color: '#ffb040',\n soft: true,\n },\n alpha: [0.32, 0.32],\n blend: 'lighter',\n pulse: { amp: 0.12, period: 1400 },\n grow: { amp: 0.4, period: 1600 },\n // Tiny orbit = positional lean without drifting off-center (wander has vx).\n motion: {\n type: 'orbit',\n speed: [18, 18],\n radius: [0.003, 0.003],\n center: { x: 0.5, y: 0.52 },\n },\n },\n {\n key: 'flame-core',\n count: 1,\n sprite: {\n kind: 'circle',\n radius: [0.014, 0.014],\n color: '#fff6e0',\n soft: true,\n },\n alpha: [0.95, 0.95],\n blend: 'lighter',\n pulse: { amp: 0.25, period: 900 },\n grow: { amp: 0.55, period: 1100 },\n motion: {\n type: 'orbit',\n speed: [22, 22],\n radius: [0.0025, 0.0025],\n center: { x: 0.5, y: 0.52 },\n },\n },\n {\n key: 'embers',\n count: 7,\n sprite: {\n kind: 'circle',\n radius: [0.0018, 0.004],\n color: '#e08a34',\n soft: true,\n },\n alpha: [0.4, 0.8],\n blend: 'lighter',\n region: { x: [0.35, 0.65], y: [0.4, 0.7] },\n pulse: { amp: 0.2, period: 2200 },\n trail: { length: 2200, fade: 1 },\n motion: {\n type: 'drift',\n speed: [0.004, 0.012],\n angle: 270,\n bob: 0.008,\n },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Polygons: the classic Mystify-style bouncing-polygon saver, expressed as chain links + heavy\n * ghosting. Showcases `links.mode: 'chain'` with `closed` (vertices wired in order\n * into a polygon), `bounce` motion, and high `ghosting` (the decaying after-images\n * ARE the effect — no per-entity trail sampling involved).\n */\nexport const POLYGONS_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'polygons',\n label: 'Polygons',\n seed: 1995,\n motionIntensity: 'moderate',\n ghosting: 0.95,\n background: { type: 'solid', color: '#04040a' },\n layers: [\n {\n key: 'poly-cyan',\n count: 4,\n sprite: { kind: 'circle', radius: [0.0025, 0.0025], color: '#37e5d7' },\n motion: { type: 'bounce', speed: [0.14, 0.24] },\n wrap: false,\n alpha: [0.9, 0.9],\n links: { k: 1, maxDist: 3, mode: 'chain', closed: true, color: '#37e5d7', alpha: 0.85, width: 0.0018 },\n },\n {\n key: 'poly-magenta',\n count: 4,\n sprite: { kind: 'circle', radius: [0.0025, 0.0025], color: '#e83e9c' },\n motion: { type: 'bounce', speed: [0.1, 0.2] },\n wrap: false,\n alpha: [0.9, 0.9],\n links: { k: 1, maxDist: 3, mode: 'chain', closed: true, color: '#e83e9c', alpha: 0.85, width: 0.0018 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Orrery: a mechanical solar system. Exercises orbit motion (concentric rings\n * at different speeds), spin (planets rotate on their axes), and grow (the sun\n * pulses). Soft glow circles with additive blending create the corona and\n * planetary halos.\n */\nexport const ORRERY_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'orrery',\n label: 'Orrery',\n seed: 7,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#020210' },\n { at: 0.5, color: '#06051a' },\n { at: 1, color: '#0a0820' },\n ],\n },\n layers: [\n // Distant stars\n {\n count: 80,\n sprite: { kind: 'circle', radius: [0.0002778, 0.001111], color: '#8899cc' },\n alpha: [0.2, 0.8],\n pulse: { amp: 0.3, period: 3000 },\n motion: { type: 'static' },\n },\n // Sun corona (soft glow)\n {\n key: 'corona',\n count: 1,\n sprite: { kind: 'circle', radius: [0.05556, 0.05556], color: '#ffaa22', soft: true },\n blend: 'lighter',\n alpha: [0.6, 0.6],\n grow: { amp: 0.15, period: 4000 },\n motion: { type: 'static' },\n position: { x: 0.5, y: 0.5 },\n },\n // Sun body\n {\n key: 'sun',\n count: 1,\n sprite: { kind: 'emoji', glyphs: ['☀️'] },\n size: [0.04444, 0.04444],\n grow: { amp: 0.08, period: 4000 },\n motion: { type: 'static' },\n position: { x: 0.5, y: 0.5 },\n },\n // Inner ring — small fast planets\n {\n key: 'inner',\n count: 3,\n sprite: { kind: 'emoji', glyphs: ['🪨', '🔴', '🟠'] },\n size: [0.01481, 0.02037],\n spin: 30,\n motion: { type: 'orbit', speed: [28, 42], radius: [0.07407, 0.1111] },\n },\n // Middle ring — gas giants\n {\n key: 'middle',\n count: 2,\n sprite: { kind: 'emoji', glyphs: ['🟤', '🪐'] },\n size: [0.02593, 0.03519],\n spin: -15,\n motion: { type: 'orbit', speed: [12, 20], radius: [0.1481, 0.1852] },\n },\n // Outer ring — ice giants\n {\n key: 'outer',\n count: 2,\n sprite: { kind: 'emoji', glyphs: ['🔵', '💎'] },\n size: [0.02037, 0.02778],\n spin: 10,\n motion: { type: 'orbit', speed: [5, 10], radius: [0.2222, 0.2778] },\n },\n // Orbital dust ring (soft glow particles orbiting slowly)\n {\n count: 24,\n sprite: { kind: 'circle', radius: [0.0009259, 0.002778], color: '#ccaa66', soft: true },\n alpha: [0.15, 0.4],\n blend: 'lighter',\n pulse: { amp: 0.2, period: 2500 },\n motion: { type: 'orbit', speed: [2, 8], radius: [0.09259, 0.2963] },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Pings — almost nothing, almost never.\n * A near-black ground and one teal hue. Three rings take turns: each one\n * appears, grows sixteenfold (0.15× → 2.4× its radius) and fades over four\n * seconds, then the frame is empty until the next — `emit` with `jitter: 0`\n * spaces them evenly, one event every four seconds, and `life` is kept at\n * the stagger so no two rings are ever lit together. Underneath, a few motes rise,\n * `settle` to rest and fade on their own, longer, seeded schedule. Nothing\n * travels; everything grows and goes. The house style Fathom describes this\n * exactly and, before `emit`, could not be authored.\n */\nexport const PINGS_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'pings',\n label: 'Pings',\n seed: 7,\n motionIntensity: 'calm',\n ghosting: 0.9,\n background: { type: 'solid', color: '#03060a' },\n layers: [\n {\n key: 'ping',\n count: 3,\n sprite: { kind: 'ring', radius: [0.05, 0.05], color: '#4fb3a8', width: 0.0015 },\n alpha: [0.35, 0.35],\n blend: 'lighter',\n region: { x: [0.2, 0.8], y: [0.25, 0.75] },\n motion: { type: 'static' },\n // One ring at a time: three entities evenly staggered across 12 s.\n emit: { every: 12000, life: 4000, jitter: 0, grow: [0.15, 2.4] },\n },\n {\n key: 'motes',\n count: 14,\n sprite: { kind: 'circle', radius: [0.0012, 0.002], color: '#4fb3a8', soft: true },\n alpha: [0.1, 0.22],\n blend: 'lighter',\n // Each mote is flung upward and comes to rest within ~2.5 s of its event.\n motion: { type: 'rise', speed: [0.01, 0.02], sway: 0.004, ease: { type: 'settle', tau: 2500 } },\n emit: { every: 16000, life: 7000, grow: [0.6, 1.4] },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Night Procession: a choreographed scene. Showcases `path` motion (a smooth\n * figure-eight lantern route with scatter), layer-parented `orbit` (moths circling\n * a wandering lantern-bearer), `life` staging (stars first, the procession enters\n * at 4 s, moths at 7 s), plus `ring` and `rect` sprites.\n */\nexport const PROCESSION_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'procession',\n label: 'Night Procession',\n seed: 8,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#060612' },\n { at: 0.8, color: '#101024' },\n { at: 1, color: '#1a1428' },\n ],\n drift: { period: 30000, amount: 0.08 },\n },\n layers: [\n {\n key: 'stars',\n count: 90,\n sprite: { kind: 'circle', radius: [0.0006, 0.0016], color: '#f0ead8', soft: true },\n motion: { type: 'static' },\n region: { y: [0, 0.6] },\n alpha: [0.25, 0.6],\n pulse: { amp: 0.15, period: 5000 },\n },\n {\n key: 'lanterns',\n count: 9,\n sprite: {\n kind: 'rect',\n width: [0.012, 0.02],\n aspect: [1.3, 1.7],\n color: '#ffb347',\n colors: ['#ffb347', '#ff8c69', '#ffd97a'],\n colorWeights: [3, 1, 2],\n },\n motion: {\n type: 'path',\n points: [\n { x: 0.12, y: 0.72 },\n { x: 0.38, y: 0.58 },\n { x: 0.62, y: 0.78 },\n { x: 0.88, y: 0.62 },\n { x: 0.62, y: 0.5 },\n { x: 0.38, y: 0.72 },\n ],\n duration: 36000,\n curve: 'smooth',\n closed: true,\n scatter: 0.02,\n },\n alpha: [0.65, 0.9],\n pulse: { amp: 0.15, period: 2600 },\n life: { enter: 4000, fade: 2500 },\n trail: { length: 1200, fade: 1 },\n },\n {\n key: 'bearer',\n count: 1,\n sprite: { kind: 'circle', radius: [0.014, 0.014], color: '#ffe9b0', soft: true },\n motion: { type: 'wander', speed: [0.008, 0.012], meander: 0.08 },\n alpha: [0.8, 0.8],\n blend: 'lighter',\n life: { enter: 4000, fade: 2500 },\n },\n {\n key: 'moths',\n count: 7,\n sprite: { kind: 'ring', radius: [0.002, 0.005], color: '#d8f6ff', width: 0.001 },\n motion: { type: 'orbit', speed: [20, 55], radius: [0.03, 0.09], center: { layer: 'bearer' } },\n alpha: [0.3, 0.7],\n life: { enter: 7000, fade: 2000 },\n trail: { length: 600 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/** Rain: dense text streaks falling straight down over a near-black sky. */\nexport const RAIN_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'rain',\n label: 'Rain',\n seed: 7,\n motionIntensity: 'moderate',\n background: { type: 'solid', color: '#05070a' },\n layers: [\n {\n count: 140,\n sprite: { kind: 'text', strings: ['│'], color: '#9fd0ff' },\n size: [0.01111, 0.02407],\n motion: { type: 'drift', angle: 90, speed: [0.4815, 0.8333] },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Relay Board — a six-row status chart in five layers instead of twenty-five.\n * One `list` of labels, one `list` of `bar`s whose lengths are the numbers,\n * one `list` of readouts, a title block, and a slow dust field behind so the\n * board reads as a live wall, not a document. Steer `bars.sprite.values` and the\n * bars glide to the new figures; the labels never move.\n */\nexport const RELAY_BOARD_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'relay-board',\n label: 'Relay Board',\n seed: 9,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#05070d' },\n { at: 1, color: '#0a0d18' },\n ],\n },\n layers: [\n {\n key: 'dust',\n count: 40,\n sprite: { kind: 'circle', radius: [0.0008, 0.0016], color: '#22344a', soft: true },\n alpha: [0.2, 0.45],\n blend: 'lighter',\n motion: { type: 'wander', speed: [0.001, 0.003] },\n },\n {\n key: 'title',\n count: 1,\n sprite: { kind: 'textBlock', text: 'RELAY LINKS — UPLINK MARGIN', maxWidth: 0.6, fontSize: 0.028, color: '#9fb4c9' },\n motion: { type: 'static' },\n position: { x: 0.12, y: 0.16 },\n },\n {\n key: 'labels',\n count: 6,\n sprite: { kind: 'text', strings: ['VIREO-9', 'TIDE', 'ORRERY', 'COMET', 'LANTERN', 'SAKURA'], font: 'bold monospace', align: 'left', color: '#e6e8ef' },\n size: [0.024, 0.024],\n motion: { type: 'static' },\n position: { x: 0.12, y: 0.3 },\n layout: { type: 'list', gap: 0.075 },\n },\n {\n key: 'bars',\n count: 6,\n sprite: {\n kind: 'bar',\n values: [82, 64, 91, 37, 58, 73],\n max: 100,\n length: 0.5,\n thickness: 0.02,\n color: '#17e8c8',\n colors: ['#17e8c8', '#35d0ff', '#ffd93b', '#ff6ad5', '#ad8cff', '#17e8c8'],\n },\n alpha: [0.85, 0.85],\n motion: { type: 'static' },\n position: { x: 0.3, y: 0.3 },\n layout: { type: 'list', gap: 0.075 },\n },\n {\n key: 'readouts',\n count: 6,\n sprite: { kind: 'text', strings: ['82%', '64%', '91%', '37%', '58%', '73%'], font: 'monospace', align: 'left', color: '#9fb4c9' },\n size: [0.02, 0.02],\n motion: { type: 'static' },\n position: { x: 0.86, y: 0.3 },\n layout: { type: 'list', gap: 0.075 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Sakura Drift: cherry-blossom petals carried on a spring twilight breeze.\n * Glow-up pass (v1-ceiling features): petals ride `wander` harmonics with shared\n * `coherence` so gusts move the whole fall together, `spin` tumbles the glyphs,\n * faint `streak` wind-lines cross the frame, the blossom-glow backdrop shimmers\n * as a traveling `pulse.wave`, and dusk fireflies wander the lower field. The\n * ground is a warm plum earth blended out of the sunset (no more abrupt dark\n * band), with slow background `drift` keeping the sky alive.\n */\nexport const SAKURA_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'sakura',\n label: 'Sakura Drift',\n seed: 314,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#1b1d38' },\n { at: 0.45, color: '#3a2645' },\n { at: 0.78, color: '#7d3d4e' },\n { at: 0.92, color: '#4a2438' },\n { at: 1, color: '#1c1018' },\n ],\n drift: { period: 35000, amount: 0.08 },\n },\n layers: [\n {\n key: 'blossom-glow',\n count: 60,\n sprite: {\n kind: 'circle',\n radius: [0.0005556, 0.001481],\n color: '#ffe3ec',\n soft: true,\n },\n alpha: [0.3, 0.9],\n blend: 'lighter',\n region: { y: [0, 0.72] },\n // Shimmer travels across the sky instead of orbs twinkling independently.\n pulse: { amp: 0.22, period: 4000, wave: { wavelength: 0.45, angle: 10 } },\n motion: { type: 'drift', speed: [0.0002778, 0.001111], bob: 0.0009259 },\n },\n {\n key: 'petals-far',\n count: 28,\n sprite: { kind: 'emoji', glyphs: ['🌸'] },\n size: [0.01204, 0.01852],\n alpha: [0.5, 0.8],\n spin: 16,\n motion: {\n type: 'wander',\n speed: [0.011, 0.024],\n angle: 100,\n meander: 0.025,\n coherence: 0.35,\n },\n },\n {\n key: 'petals-mid',\n count: 18,\n sprite: { kind: 'emoji', glyphs: ['🌸'] },\n size: [0.01852, 0.02963],\n alpha: [0.7, 0.95],\n spin: 24,\n motion: {\n type: 'wander',\n speed: [0.022, 0.041],\n angle: 100,\n meander: 0.045,\n coherence: 0.35,\n },\n },\n {\n key: 'petals-near',\n count: 10,\n sprite: { kind: 'emoji', glyphs: ['🌸'] },\n size: [0.03148, 0.05],\n alpha: [0.85, 1],\n spin: 32,\n motion: {\n type: 'wander',\n speed: [0.039, 0.063],\n angle: 100,\n meander: 0.07,\n coherence: 0.35,\n },\n },\n {\n key: 'gusts',\n count: 7,\n sprite: {\n kind: 'streak',\n length: [0.02, 0.045],\n width: 0.0012,\n color: '#ffd9e6',\n },\n alpha: [0.1, 0.22],\n blend: 'lighter',\n motion: { type: 'drift', speed: [0.09, 0.14], angle: 100 },\n },\n {\n key: 'fireflies',\n count: 6,\n sprite: {\n kind: 'circle',\n radius: [0.0009, 0.002],\n color: '#ffe9a8',\n soft: true,\n },\n alpha: [0.15, 0.5],\n blend: 'lighter',\n region: { y: [0.6, 0.9] },\n pulse: { amp: 0.3, period: 2800 },\n motion: { type: 'wander', speed: [0.004, 0.01], meander: 0.05 },\n },\n {\n key: 'fallen-petals',\n count: 16,\n sprite: {\n kind: 'circle',\n radius: [0.001389, 0.003704],\n color: '#ff9bb5',\n soft: true,\n },\n alpha: [0.1, 0.3],\n blend: 'lighter',\n region: { y: [0.9, 1] },\n // Settled petals catch the last light in a slow wave along the ground.\n pulse: { amp: 0.15, period: 3200, wave: { wavelength: 0.3, angle: 0 } },\n motion: {\n type: 'drift',\n speed: [0.0002778, 0.001389],\n angle: 180,\n bob: 0.0009259,\n },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/** Snowfall: three depth layers of white circles drifting down with horizontal bob. */\nexport const SNOWFALL_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'snowfall',\n label: 'Snowfall',\n seed: 12,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#0a1628' },\n { at: 0.7, color: '#0d1f3c' },\n { at: 1, color: '#121212' },\n ],\n },\n layers: [\n {\n count: 50,\n sprite: { kind: 'circle', radius: [0.0009259, 0.002315], color: '#8899aa' },\n motion: { type: 'drift', angle: 90, speed: [0.01389, 0.03704], bob: 0.002778 },\n },\n {\n count: 35,\n sprite: { kind: 'circle', radius: [0.001852, 0.004167], color: '#c0cdd8' },\n motion: { type: 'drift', angle: 85, speed: [0.03241, 0.07407], bob: 0.005556 },\n },\n {\n count: 15,\n sprite: { kind: 'circle', radius: [0.003241, 0.006481], color: '#e8eff5' },\n motion: { type: 'drift', angle: 82, speed: [0.05093, 0.1111], bob: 0.009259 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Thermal Field: the `field` background — seeded, domain-warped value noise\n * posterised into six riso inks (`quantize: 6`, one hard band per level) and\n * drifting once every forty seconds, so the contours crawl like a weather\n * chart. The foreground is deliberately almost nothing: a handful of pale\n * motes screened over the bands, so the ground IS the piece. A house\n * `thermal` look; the same field with `quantize: 0` is a smooth aura. A\n * `finish` of grain and dither screens the whole frame like a riso print.\n */\nexport const THERMAL_FIELD_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'thermal-field',\n label: 'Thermal Field',\n seed: 71,\n motionIntensity: 'calm',\n // The riso print: grain at half strength, a light dither screen — the\n // finish that makes the flat inks read as paper rather than pixels.\n finish: { grain: 0.5, dither: 0.3 },\n background: {\n type: 'field',\n scale: 2.2,\n octaves: 3,\n warp: 0.4,\n quantize: 6,\n bands: ['#1b1a3a', '#0078bf', '#00a99d', '#ffe800', '#ff6c2f', '#ff48b0'],\n drift: { period: 40000, amount: 0.3 },\n },\n layers: [\n {\n key: 'motes',\n count: 14,\n sprite: { kind: 'circle', radius: [0.012, 0.028], color: '#fff6e0', soft: true },\n motion: { type: 'wander', speed: [0.003, 0.008], meander: 0.04, coherence: 0.3 },\n alpha: [0.18, 0.4],\n blend: 'screen',\n pulse: { amp: 0.15, period: 9000 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Warp Tunnel: showcases `warp` motion (perspective depth — size/alpha/speed scale\n * with 1/z), `streak` sprites oriented along the analytic heading, `colorWeights`\n * (mostly white stars, occasional blue/amber), and light `ghosting` for smear.\n */\nexport const WARP_TUNNEL_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'warp-tunnel',\n label: 'Warp Tunnel',\n seed: 1701,\n motionIntensity: 'energetic',\n ghosting: 0.55,\n background: { type: 'solid', color: '#020208' },\n layers: [\n {\n key: 'far-stars',\n count: 150,\n sprite: {\n kind: 'streak',\n length: [0.008, 0.02],\n width: 0.0015,\n color: '#cfd8ff',\n colors: ['#cfd8ff', '#ffffff', '#8ab4ff', '#ffd9a0'],\n colorWeights: [5, 3, 1.5, 0.5],\n },\n motion: { type: 'warp', speed: [0.06, 0.16] },\n alpha: [0.5, 0.9],\n blend: 'lighter',\n },\n {\n key: 'near-stars',\n count: 50,\n sprite: {\n kind: 'streak',\n length: [0.025, 0.06],\n width: 0.0025,\n color: '#ffffff',\n colors: ['#ffffff', '#a8c8ff'],\n colorWeights: [3, 1],\n },\n motion: { type: 'warp', speed: [0.3, 0.55] },\n alpha: [0.7, 1],\n blend: 'lighter',\n },\n {\n key: 'core-glow',\n count: 1,\n sprite: { kind: 'circle', radius: [0.06, 0.06], color: '#3a4a8f', soft: true },\n motion: { type: 'static' },\n position: { x: 0.5, y: 0.5 },\n alpha: [0.35, 0.35],\n pulse: { amp: 0.15, period: 5000 },\n blend: 'lighter',\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Typed Cue — textBlock.reveal, both moods.\n * Two self-typing captions over near-black. The upper one types at ten\n * graphemes a second with a blinking caret (`mode: 'typewriter'` — the classic\n * terminal reveal; `speed` makes progress a pure function of scene time, so\n * every viewer types the same line on the same clock from its own mount). The\n * lower one arrives as a wave of overlapping fades (`mode: 'glyphFade'`,\n * `fade: 0.4` — each glyph ramps in over 40% of the progress window, which\n * reads as a soft dissolve rather than typing) and carries no caret. Both\n * blocks declare `opacity` so the path is steerable, and layout always runs on\n * the FULL text — reveal only masks glyphs, so lines never reflow mid-type.\n *\n * Trap, documented in the playbook and true here too: at t = 0 a self-typing\n * block has typed nothing, so `previewScene` at the default instant looks\n * empty — preview at t ≥ 10 s to see the words. To swap the line live, glide\n * `reveal.progress` to 0, step the `text`, glide back (one `setTrack` call).\n *\n * The scan band is the one non-text layer, and it is load-bearing twice over:\n * a screensaver of two static text blocks is a document, not a screensaver\n * (`text-heavy`), and the band gives the words something to sit on — a slow\n * refresh sweep passing under the type. Note the units: `perceiveScene` takes\n * `t` in MILLISECONDS while the MCP `previewScene` tool takes seconds (the\n * worker converts); passing seconds to the library reads as a block that\n * never finishes typing.\n */\nexport const TYPED_CUE_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"typed-cue\",\n label: \"Typed Cue\",\n seed: 19,\n motionIntensity: \"calm\",\n background: { type: \"solid\", color: \"#050608\" },\n layers: [\n {\n key: \"scan\",\n count: 1,\n sprite: { kind: \"rect\", width: [1, 1], aspect: [0.02, 0.02], color: \"#16241f\", feather: 0.9 },\n motion: { type: \"drift\", speed: [0.014, 0.014], angle: 90 },\n alpha: [0.5, 0.5],\n blend: \"screen\",\n },\n {\n key: \"headline\",\n count: 1,\n sprite: {\n kind: \"textBlock\",\n text: \"THE SCREEN IS AWAKE.\\nWORDS ARRIVE ON THEIR OWN CLOCK.\",\n maxWidth: 0.84,\n fontSize: 0.03,\n lineHeight: 1.5,\n align: \"left\",\n anchor: \"top-left\",\n font: \"bold monospace\",\n color: \"#e6e8ef\",\n opacity: 0.94,\n reveal: {\n progress: 1,\n mode: \"typewriter\",\n speed: 10,\n caret: { blink: 1.1, color: \"#e6e8ef\" },\n },\n },\n motion: { type: \"static\" },\n position: { x: 0.08, y: 0.16 },\n alpha: [0.95, 0.95],\n },\n {\n key: \"aside\",\n count: 1,\n sprite: {\n kind: \"textBlock\",\n text: \"and leaves the same way —\\na dissolve, not a delete.\",\n maxWidth: 0.5,\n fontSize: 0.022,\n lineHeight: 1.5,\n align: \"left\",\n anchor: \"bottom-right\",\n font: \"monospace\",\n color: \"#8f96a3\",\n opacity: 0.85,\n reveal: { progress: 1, mode: \"glyphFade\", speed: 6, fade: 0.4 },\n },\n motion: { type: \"static\" },\n position: { x: 0.92, y: 0.86 },\n alpha: [0.9, 0.9],\n },\n ],\n};\n","import type { SaverSpec } from '../types';\nimport type { IdleSequence } from '../types';\nimport { AQUARIUM_SPEC } from './aquarium';\nimport { AURORA_SPEC } from './aurora';\nimport { COMETS_SPEC } from './comets';\nimport { CONSTELLATION_SPEC } from './constellation';\nimport { DASHBOARD_SPEC } from './dev-dashboard';\nimport { SPARSE_NIGHT_SPEC } from './sparse-night';\nimport { SIGNAL_BOARD_SPEC } from './signal-board';\nimport { PHASE_DUET_SPEC } from './phase-duet';\nimport { WEB_WORK_SPEC } from './web-work';\nimport { SHARD_FALL_SPEC } from './shard-fall';\nimport { MURMUR_SPEC } from './murmur';\nimport { THREE_MOVEMENTS_SEQUENCE } from './three-movements';\nimport { FACETS_SPEC } from './facets';\nimport { HAIKU_SPEC } from './haiku';\nimport { LANTERNS_SPEC } from './lanterns';\nimport { LOBBY_TALK_SPEC } from './lobby-talk';\nimport { MATRIX_RAIN_SPEC } from './matrix-rain';\nimport { NOSTALGHIA_CANDLE_SPEC } from './nostalghia-candle';\nimport { POLYGONS_SPEC } from './polygons';\nimport { ORRERY_SPEC } from './orrery';\nimport { PINGS_SPEC } from './pings';\nimport { PROCESSION_SPEC } from './procession';\nimport { RAIN_SPEC } from './rain';\nimport { RELAY_BOARD_SPEC } from './relay-board';\nimport { SAKURA_SPEC } from './sakura';\nimport { SNOWFALL_SPEC } from './snowfall';\nimport { THERMAL_FIELD_SPEC } from './thermal-field';\nimport { WARP_TUNNEL_SPEC } from './warp-tunnel';\nimport { TYPED_CUE_SPEC } from './typed-cue';\n\nexport { AQUARIUM_SPEC } from './aquarium';\nexport { COMETS_SPEC } from './comets';\nexport { CONSTELLATION_SPEC } from './constellation';\nexport { RAIN_SPEC } from './rain';\nexport { SNOWFALL_SPEC } from './snowfall';\nexport { LANTERNS_SPEC } from './lanterns';\nexport { LOBBY_TALK_SPEC } from './lobby-talk';\nexport { SAKURA_SPEC } from './sakura';\nexport { DASHBOARD_SPEC } from './dev-dashboard';\nexport { HAIKU_SPEC } from './haiku';\nexport { ORRERY_SPEC } from './orrery';\nexport { AURORA_SPEC } from './aurora';\nexport { MATRIX_RAIN_SPEC } from './matrix-rain';\nexport { NOSTALGHIA_CANDLE_SPEC } from './nostalghia-candle';\nexport { PINGS_SPEC } from './pings';\nexport { FACETS_SPEC } from './facets';\nexport { RELAY_BOARD_SPEC } from './relay-board';\nexport { POLYGONS_SPEC } from './polygons';\nexport { PROCESSION_SPEC } from './procession';\nexport { WARP_TUNNEL_SPEC } from './warp-tunnel';\nexport { THERMAL_FIELD_SPEC } from './thermal-field';\nexport { SPARSE_NIGHT_SPEC } from './sparse-night';\nexport { TYPED_CUE_SPEC } from './typed-cue';\nexport { SIGNAL_BOARD_SPEC } from './signal-board';\nexport { PHASE_DUET_SPEC } from './phase-duet';\nexport { WEB_WORK_SPEC } from './web-work';\nexport { SHARD_FALL_SPEC } from './shard-fall';\nexport { MURMUR_SPEC } from './murmur';\nexport { THREE_MOVEMENTS_SEQUENCE } from './three-movements';\n\n/** Catalog entry for a bundled schema example. */\nexport interface SchemaExample {\n id: string;\n label: string;\n spec: SaverSpec;\n}\n\n/** Ordered catalog of bundled schema examples. Add new specs as standalone files, then register here. */\nexport const SCHEMA_EXAMPLES: readonly SchemaExample[] = [\n { id: 'aquarium', label: 'Aquarium', spec: AQUARIUM_SPEC },\n { id: 'rain', label: 'Rain', spec: RAIN_SPEC },\n { id: 'snowfall', label: 'Snowfall', spec: SNOWFALL_SPEC },\n { id: 'lanterns', label: 'Night Lanterns', spec: LANTERNS_SPEC },\n { id: 'sakura', label: 'Sakura Drift', spec: SAKURA_SPEC },\n { id: 'dev-dashboard', label: 'Control Center', spec: DASHBOARD_SPEC },\n { id: 'orrery', label: 'Orrery', spec: ORRERY_SPEC },\n { id: 'constellation', label: 'Constellation', spec: CONSTELLATION_SPEC },\n { id: 'comets', label: 'Comet Shower', spec: COMETS_SPEC },\n { id: 'aurora', label: 'Aurora', spec: AURORA_SPEC },\n { id: 'warp-tunnel', label: 'Warp Tunnel', spec: WARP_TUNNEL_SPEC },\n { id: 'polygons', label: 'Polygons', spec: POLYGONS_SPEC },\n { id: 'matrix-rain', label: 'Matrix Rain', spec: MATRIX_RAIN_SPEC },\n { id: 'procession', label: 'Night Procession', spec: PROCESSION_SPEC },\n { id: 'nostalghia-candle', label: \"Nostalghia's Candle\", spec: NOSTALGHIA_CANDLE_SPEC },\n { id: 'haiku', label: 'Haiku', spec: HAIKU_SPEC },\n { id: 'pings', label: 'Pings', spec: PINGS_SPEC },\n { id: 'facets', label: 'Facets', spec: FACETS_SPEC },\n { id: 'relay-board', label: 'Relay Board', spec: RELAY_BOARD_SPEC },\n { id: 'lobby-talk', label: 'Lobby Talk', spec: LOBBY_TALK_SPEC },\n { id: 'thermal-field', label: 'Thermal Field', spec: THERMAL_FIELD_SPEC },\n { id: 'sparse-night', label: 'Sparse Night', spec: SPARSE_NIGHT_SPEC },\n { id: 'typed-cue', label: 'Typed Cue', spec: TYPED_CUE_SPEC },\n { id: 'signal-board', label: 'Signal Board', spec: SIGNAL_BOARD_SPEC },\n { id: 'phase-duet', label: 'Phase Duet', spec: PHASE_DUET_SPEC },\n { id: 'web-work', label: 'Web Work', spec: WEB_WORK_SPEC },\n { id: 'shard-fall', label: 'Shard Fall', spec: SHARD_FALL_SPEC },\n { id: 'murmur', label: 'Murmur', spec: MURMUR_SPEC },\n] as const;\n\n/** Catalog entry for a bundled idle-sequence example. */\nexport interface SequenceExample {\n id: string;\n label: string;\n sequence: IdleSequence;\n}\n\n/**\n * Ordered catalog of bundled idle-sequence examples.\n *\n * Deliberately separate from SCHEMA_EXAMPLES: that catalog is typed\n * `SaverSpec[]` and its consumers (manifests, batch compile, the MCP examples\n * resource) rely on that. A sequence is a different top-level format, so it\n * gets its own list rather than widening theirs.\n */\nexport const EXAMPLE_SEQUENCES: readonly SequenceExample[] = [\n { id: 'three-movements', label: 'Three Movements', sequence: THREE_MOVEMENTS_SEQUENCE },\n];\n\n/** All example specs in catalog order (tests, batch compile). */\nexport const EXAMPLE_SPECS: SaverSpec[] = SCHEMA_EXAMPLES.map((e) => e.spec);\n\n/** Lookup by saver id. */\nexport const EXAMPLE_BY_ID: Readonly<Record<string, SaverSpec>> = Object.fromEntries(\n SCHEMA_EXAMPLES.map((e) => [e.id, e.spec]),\n);\n"],"mappings":"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","names":["isObj","HEX","ease","ease","catmullRom","y","x","clamp01","smoothstep","clamp01","clamp01","groupOf","wrap","unitScale","createRng","acc","createRng","createRng","s","sizePx","createRng","createRng","createRng"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/steer.ts","../src/sequence.ts","../src/timeline.ts","../src/shapes.ts","../src/validate.ts","../src/simulate.ts","../src/compile.ts","../src/paint.ts","../src/field.ts","../src/finish.ts","../src/trail.ts","../src/advise.ts","../src/luma.ts","../src/cohesion.ts","../src/perceive.ts","../src/describe.ts","../src/examples/aquarium.ts","../src/examples/aurora.ts","../src/examples/comets.ts","../src/examples/constellation.ts","../src/examples/dev-dashboard.ts","../src/examples/sparse-night.ts","../src/examples/signal-board.ts","../src/examples/phase-duet.ts","../src/examples/web-work.ts","../src/examples/shard-fall.ts","../src/examples/murmur.ts","../src/examples/three-movements.ts","../src/examples/facets.ts","../src/examples/haiku.ts","../src/examples/lanterns.ts","../src/examples/lobby-talk.ts","../src/examples/matrix-rain.ts","../src/examples/nostalghia-candle.ts","../src/examples/polygons.ts","../src/examples/orrery.ts","../src/examples/pings.ts","../src/examples/procession.ts","../src/examples/rain.ts","../src/examples/relay-board.ts","../src/examples/sakura.ts","../src/examples/snowfall.ts","../src/examples/thermal-field.ts","../src/examples/warp-tunnel.ts","../src/examples/typed-cue.ts","../src/examples/index.ts"],"sourcesContent":["/**\n * Declarative, agent-authorable saver format. A `SaverSpec` describes a saver as DATA\n * (no code), which `compileSaver` turns into a seeded, deterministic, flash-safe\n * SaverPlugin. It models the \"drifting sprite field\" family that covers most classic\n * savers (fish, toasters, DVD, rain, messages): a static background plus one or more\n * layers of entities that move.\n *\n * SAFETY INVARIANT: there is deliberately NO full-field strobe/flash primitive — the\n * background is static and entities are bounded sprites — so a compiled spec cannot\n * produce photosensitive flashing by construction (proven by sampling a compiled spec\n * through @idle-screens/validator).\n */\nexport const SCHEMA_VERSION = 1 as const;\n\nexport interface SaverSpec {\n schemaVersion: 1;\n id: string;\n label: string;\n /** Deterministic seed; falls back to the host's SaverContext.seed. */\n seed?: number;\n background?: BackgroundSpec;\n layers: LayerSpec[];\n motionIntensity?: 'calm' | 'moderate' | 'energetic';\n /**\n * Declared density intent. `sparse` says the emptiness is the point (one\n * mark on a dark ground, long silences): `adviseSpec` withholds\n * `sparse-scene`, and scorers that gate on coverage should read this before\n * calling a faithful scene broken. `dense` withholds `dense-scene` the same\n * way. Either declaration is checked against the measured coverage and a\n * `density-mismatch` advisory fires when the scene contradicts it. Omitted\n * means `normal`. A hint only — it changes no pixel.\n */\n density?: 'sparse' | 'normal' | 'dense';\n /**\n * Frame persistence (0..1, capped at LIMITS.maxGhosting). Instead of fully clearing,\n * each frame the background is painted at reduced alpha so moving entities leave\n * decaying after-images (Mystify smears, long-exposure light). Inherently\n * flash-safe: ghosting can only smooth luminance changes, never sharpen them.\n * `renderFrame(t)` stays deterministic for seeks via a fixed-step warm-up replay.\n */\n ghosting?: number;\n /**\n * The print finish — grain and a dither screen composited over the\n * finished frame as the last step of every render. See `FinishSpec`.\n * Absent ⇒ the frame is presented exactly as drawn.\n */\n finish?: FinishSpec;\n /**\n * Authored keyframes on the scene's own clock — see `Timeline`. Absent ⇒\n * the scene is exactly what it was before the field existed. **Native:**\n * ignored ⇒ the base spec (author it as the piece's rest state).\n */\n timeline?: Timeline;\n /** Named layer groups — see `LayerGroup`. Absent ⇒ no layer is grouped (today's behaviour). */\n groups?: Record<string, LayerGroup>;\n /** Dimensional unit system. 'viewport' (default) = all sizes/speeds/distances are fractions of min(w,h). */\n units?: 'viewport' | 'px';\n /**\n * Resolution at which this spec was designed. Density scaling kicks in above this\n * threshold: entity counts scale by min(w,h) / referenceViewport. Default: 1080.\n * Set to your design resolution so a spec authored at 4K doesn't over-densify.\n */\n referenceViewport?: number;\n}\n\n/**\n * A print finish over the finished frame: `grain` (0..1) screens a seeded\n * zero-mean noise tile at up to 35 % alpha; `dither` (0..1) screens an 8×8\n * ordered Bayer tile at up to 25 % — a stylistic screen, not per-pixel\n * dithering of the image. Both composite with a symmetric blend (`overlay`)\n * so the frame's mean luminance is unchanged: flash-safe by construction,\n * and invisible to `luminanceGrid`. The grain tile is generated once per\n * mount from the spec seed and sits still; `animate: true` steps its offset\n * deterministically from the frame's time bucket (12 Hz), never randomly —\n * ignored on the `basic` / `minimal` capability tiers (static tile). The\n * finish is applied on a presentation canvas, never fed back into\n * `ghosting`'s persistence. `grain` and `dither` are numeric paint paths\n * (`finish.grain`) and glide.\n */\nexport interface FinishSpec {\n grain?: number;\n dither?: number;\n animate?: boolean;\n}\n\nexport type BackgroundSpec =\n | { type: 'solid'; color: string }\n | { type: 'gradient'; stops: GradientStop[]; band?: BandSpec; drift?: BackgroundDrift }\n | FieldBackground;\n\n/**\n * A scalar-field background: seeded, warped value noise quantised into\n * `bands` — thermal maps, contour terrain, sonar landmasses, riso washes.\n * Pure in `(x, y, t, seed)`: the renderer paints it as a low-res raster\n * (short side 96 px; 48 on the `basic` / `minimal` tiers) scaled to the\n * canvas, recomputed once per 100 ms bucket while drifting and once ever\n * otherwise, and the perception grid samples the same function directly.\n * The sampler uses its own hash, never the entity RNG, so adding a field to\n * a spec leaves every entity where it was.\n */\nexport interface FieldBackground {\n type: 'field';\n /** Noise features across the short side, 0.5..8 (LIMITS.minFieldScale / maxFieldScale). */\n scale: number;\n /** Octaves of detail, integer 1..4 (default 2). */\n octaves?: number;\n /** Domain-warp amount 0..1 (default 0) — folds round blobs into smeared contours. */\n warp?: number;\n /**\n * Levels to posterise the field into, integer 2..8, or 0 for smooth\n * interpolation between bands (Aura, Mist). Default `bands.length`: one\n * hard band per level.\n */\n quantize?: number;\n /** 2..8 hex colours, darkest-to-lightest or whatever ramp the look wants. */\n bands: string[];\n /** Slow domain travel — the field's \"animate\". Period floored at 10 s (flash guard). */\n drift?: FieldDrift;\n /** Field seed; defaults to the spec seed. Independent of the entity stream. */\n seed?: number;\n}\n\n/** Slow travel of a field's sample domain: a circle of radius `amount` feature units per `period`. */\nexport interface FieldDrift {\n /** Full loop period in ms. Floor: LIMITS.minDriftPeriod (10 s) — the flash guard. */\n period: number;\n /** Radius of the domain travel in feature units, 0..1. Default 0.3. */\n amount?: number;\n}\n\n/** A vertical gradient stop (`at` 0 = top, 1 = bottom). */\nexport interface GradientStop {\n at: number;\n color: string;\n}\n\n/** An optional solid band at the bottom (e.g. an aquarium seafloor). */\nexport interface BandSpec {\n color: string;\n /** Band height — px or a viewport fraction, per the spec's `units`. */\n height: number;\n}\n\n/** Slow oscillation of gradient stop positions — makes the background feel alive. */\nexport interface BackgroundDrift {\n /** Full cycle period in ms. Floor: LIMITS.minDriftPeriod (10 s). */\n period: number;\n /** How far stops shift (fraction of the 0..1 range). Default 0.15, max 0.3. */\n amount?: number;\n}\n\n/**\n * A paint-level transform applied to a whole layer at draw time, about the\n * viewport centre: translate by (`x`, `y`) in `min(w, h)` units, rotate by\n * `rotate` degrees, scale by `scale` (× `scaleX` horizontally — `scaleX`\n * toward 0 reads as a turn about the vertical axis). Kept out of the\n * structural signature, so it glides under steering, a `timeline` key or a\n * `morph` — a camera for timed pieces, a slow drift for ambient ones. Every\n * field optional; an empty transform is the identity. **Native:** ignored ⇒\n * identity.\n */\nexport interface LayerTransform {\n x?: number;\n y?: number;\n scale?: number;\n scaleX?: number;\n rotate?: number;\n /**\n * What `scale` / `scaleX` / `rotate` turn about. `'viewport'` (default) is\n * the viewport centre — a camera move. `'anchor'` is the layer's own\n * `position` point (with `dx`/`dy`; for a `list`/`table` layout, the block's\n * anchor; without `position`, the centre of its `region`) — a slam word\n * punches in place, on every aspect. Group transforms always turn about the\n * viewport centre. **Native:** ignored with the rest of `transform`.\n */\n origin?: 'viewport' | 'anchor';\n}\n\n/**\n * A named set of layers painted through one shared `transform` and\n * `opacity` (`SaverSpec.groups`, joined by `LayerSpec.group`): the group's\n * transform wraps each member's own (it turns about the viewport centre, a\n * camera), and its opacity multiplies theirs. Paint — outside the structural\n * signature — so a steer (`groups.<name>.transform.scale`), a `timeline` key\n * or a `morph` glides a whole multi-layer subject as one thing. **Native:**\n * ignored ⇒ identity, opacity 1.\n */\nexport interface LayerGroup {\n transform?: LayerTransform;\n opacity?: number;\n}\n\n/** One authored key of a `Timeline`: at scene time `t` (ms), glide `path` to `value` over `dur` ms. */\nexport interface TimelineKey {\n /** Scene time in ms (the instance's own clock — a sequence segment's `localT`). */\n t: number;\n /** A steering path (`layers.0.sprite.color`, `key.sprite.color`, `background.stops.1.color`, …). It must already exist on the spec, as for `setParam`. */\n path: string;\n /** The target value; the key must still validate when applied. */\n value: unknown;\n /** Default `smooth`. */\n ease?: 'step' | 'linear' | 'smooth';\n /** Glide length in ms, starting at `t`. Default 1000 (as live steering); 0 = a cut. */\n dur?: number;\n}\n\n/**\n * Authored change on the scene's own clock — keyframes. A scene without a\n * timeline is unchanged (ambient, today's behaviour); with one, each key\n * glides its path at its time, and the scene can loop. Distinct from the\n * channel's live `track`, whose `t` is a wall-clock stamp: live steering still\n * layers on top, and a steer on a path the timeline animates holds until that\n * path's next key.\n */\nexport interface Timeline {\n /** Repeat every `duration` ms. A looping path's value before its first key is its last key's value (the loop wraps). */\n loop?: boolean;\n /** Loop length in ms; required with `loop`, and at least the latest key's `t`. */\n duration?: number;\n keys: TimelineKey[];\n}\n\nexport interface LayerSpec {\n count: number;\n sprite: SpriteSpec;\n /** Sprite size range in px (font size for emoji/text; ignored for circle). */\n size?: [number, number];\n motion: MotionSpec;\n /** Wrap around the opposite edge when leaving the viewport. Default true. */\n wrap?: boolean;\n /** Flip the sprite horizontally to face its heading. Default false. */\n flip?: boolean;\n /** Per-entity opacity range, both 0..1. Default [1,1]. */\n alpha?: [number, number];\n /**\n * Compositing for this layer. 'lighter' = additive (glow stacking); 'screen' =\n * gentler additive for pale backgrounds; 'multiply' = darkening (shadows,\n * silhouettes). Default source-over. None of these can strobe.\n */\n blend?: 'lighter' | 'screen' | 'multiply';\n /**\n * Fractional spawn window (0 = left/top, 1 = right/bottom). Constrains where\n * entities are PLACED, not where they may travel. Default full viewport.\n */\n region?: { x?: [number, number]; y?: [number, number] };\n /**\n * Sinusoidal opacity breathing. SAFETY: amp is capped (LIMITS.maxPulseAmp),\n * period has a floor (LIMITS.minPulsePeriod — max 2 Hz), and every entity gets\n * its own seeded phase, so a layer can never strobe in unison. Effective alpha\n * is clamped to 0..1.\n *\n * `wave` derives each entity's phase from its spawn position instead of a seeded\n * draw, turning independent breathing into a traveling wave across the field\n * (ripples, wind through grass). `wavelength` is dimensional (px or viewport\n * units); `angle` is the propagation direction in degrees (0 = rightward,\n * default 0). Still flash-safe: neighbors are out of phase by construction.\n */\n pulse?: { amp: number; period: number; wave?: { wavelength: number; angle?: number } };\n /**\n * Per-entity rotation speed in degrees/sec (positive = clockwise).\n * Each entity gets a seeded starting angle. Composes with any motion type.\n * A scalar applies one speed to every entity; a `[min, max]` range gives each\n * entity a seeded speed within the range (like `speed`/`alpha`) — confetti,\n * tumbling debris, foliage. Existing scalar specs are unaffected (the range\n * form draws one extra seeded value, only when present).\n */\n spin?: number | [number, number];\n /**\n * Static per-entity rotation in degrees (positive = clockwise), ±360. A\n * scalar turns every entity the same way; a `[min, max]` range gives each\n * entity a seeded angle — thrown blades, scattered glyphs, a tilted grid.\n * Composes with `spin` (added to its seeded start angle). Note that `spin:\n * [0, 0]` does NOT do this: a zero spin speed renders at angle 0, its\n * seeded phase unused. Structural (baked into entities). The range form\n * draws one seeded value per entity, only when declared, so existing\n * specs keep identical streams.\n */\n rotate?: number | [number, number];\n /**\n * Sinusoidal size breathing, parallel to `pulse` for opacity. `amp` is a\n * fraction of base size (0.3 = ±30 %). `period` in ms with the same\n * flash-safety floor as pulse. Per-entity seeded phase.\n */\n grow?: { amp: number; period: number };\n /**\n * Addressable name for this layer. Enables `setParam` to use `key.field` paths\n * instead of `layers.N.field` indices. Also makes specs self-documenting.\n */\n key?: string;\n /**\n * Exact fractional position {x, y} for a single entity (0 = left/top, 1 = right/bottom).\n * Only valid when `count` is 1 — or, with a `list` / `table` layout, as the\n * top-left anchor of the whole block. Overrides `region` scatter placement.\n */\n position?: {\n x: number;\n y: number;\n /**\n * An offset from `x`/`y` in `min(w, h)` units (px under `units: 'px'`).\n * `x`/`y` are fractions of width and height while every size is a fraction\n * of `min(w, h)`, so parts placed at computed fractions only register at\n * the aspect they were computed for; anchor on a shared fraction (the\n * centre is the only aspect-safe one) and offset in size units instead.\n * Placement, like `x`/`y` (structural). Absent ⇒ 0. **Native:** tvOS\n * ignores the offset until it reads the field.\n */\n dx?: number;\n dy?: number;\n };\n /**\n * Paint-level layer opacity, 0..1 (default 1): multiplies the per-entity\n * `alpha` and the `life` envelope at draw time. Unlike `alpha` (a range baked\n * into every entity at build), it is **paint** — kept out of the structural\n * signature — so `setParam`, a `timeline` key or a sequence `morph` glides it\n * instead of re-seeding the layer. **Native:** ignored ⇒ 1.\n */\n opacity?: number;\n /** Paint-level transform of the whole layer — see `LayerTransform`. */\n transform?: LayerTransform;\n /** The name of a `SaverSpec.groups` entry this layer is painted through (see `LayerGroup`). */\n group?: string;\n /**\n * Inter-entity links. `mode` picks the wiring:\n * - 'nearest' (default): each entity's k nearest neighbors within maxDist.\n * - 'chain': entities connected in order (0-1-2-…) — Mystify polygons, string\n * art. Ignores k/maxDist; `closed` joins the last entity back to the first.\n * - 'random': a fixed golden-ratio-stride wiring (k partners per entity,\n * deterministic, no RNG draws) — breaks the crystalline k-nearest look.\n * `falloff` fades link alpha with distance/maxDist, killing pop-in at the cutoff.\n * `k` and `maxDist` are required for 'nearest' and 'random'; 'chain' needs\n * neither, except `maxDist` when `falloff` is set (it is the fade distance).\n * Capped at LIMITS.maxLinksK. Layer count must be <= LIMITS.maxLinkLayerCount when set.\n */\n links?: {\n k?: number;\n maxDist?: number;\n color?: string;\n alpha?: number;\n width?: number;\n mode?: 'nearest' | 'chain' | 'random';\n falloff?: boolean;\n closed?: boolean;\n };\n /**\n * Afterglow trail behind moving entities. Samples past positions analytically\n * (no state, fully deterministic). `length` in ms, `fade` 0..1 (default 1 = full fade).\n */\n trail?: { length: number; fade?: number };\n /**\n * Grid placement instead of random scatter: entities fill cells row-major within\n * `region`. `columns` defaults to an aspect-fit square-ish grid; `jitter` (0..1,\n * scalar or per-axis) offsets each entity within its cell by a seeded fraction of\n * the cell size — `{ y: 1 }` keeps columns crisp while scattering vertically\n * (Matrix rain). Unlocks column effects, LED walls, mosaics, uniform dot fields.\n */\n layout?:\n | { type: 'grid'; columns?: number; jitter?: number | { x?: number; y?: number } }\n /**\n * Data layouts — entities in READING ORDER, no scatter. `list` stacks them\n * in one column `gap` apart (viewport units of min(w,h), default 0.06);\n * `table` fills `columns` row-major with `gap` `{x, y}` (one number = both).\n * Text and emoji sprites take `strings[i]` / `glyphs[i]` in order instead of\n * a seeded pick, and palette `colors[i]` likewise, so N labels or N bars are\n * ONE layer. `position` (with any count) is the block's top-left anchor;\n * without it the block is centred in `region`.\n */\n | { type: 'list'; gap?: number }\n | { type: 'table'; columns: number; gap?: number | { x?: number; y?: number } };\n /**\n * Layer lifecycle for act structure — a pure function of t, no state. Alpha is 0\n * before `enter` (ms), ramps up over `fade` ms (default 1000), holds at 1, then\n * ramps down starting at `exit`. Entities are skipped entirely while at alpha 0.\n */\n life?: { enter?: number; exit?: number; fade?: number };\n /**\n * Sparse events — marks that appear, expand and fade in place, one at a time,\n * with long silences between (the \"one ping\" primitive). Each entity is dark\n * except for a window of `life` ms that recurs every `every` ms at a\n * per-entity offset: `jitter` 1 (default) scatters the offsets (a fixed\n * low-discrepancy sequence — not seeded, so declaring `emit` disturbs no\n * other draw and the same spec times its events identically under every\n * seed), 0 spreads the entities evenly across the period — a metronome, one\n * event at a time as long as `life ≤ every / count`.\n * Inside a window the entity fades in over the first quarter and out over\n * the rest; `grow` scales its size from `grow[0]` to `grow[1]` across the\n * window — expansion rather than travel. A pure function of t. Flash safety:\n * `every` ≥ 1000 ms and `life` ≥ 500 ms, so no entity fires more than once a\n * second and never as a hard cut. Composes with `pulse`, `life`, `trail` and\n * every motion; with `motion.ease` the eased travel restarts on every event.\n */\n emit?: { every: number; life: number; jitter?: number; grow?: [number, number] };\n /**\n * Phase-lock. Replaces the seeded per-entity phases of `pulse`, `grow` and\n * `cycle` with one shared phase (`phase` in turns, 0..1, default 0) and runs\n * those three at `rate` × scene time (default 1). Two layers declaring the\n * same clock breathe in step; different phases give a fixed offset (call and\n * response). `pulse.wave` still adds its position-derived phase on top, so a\n * clocked wave stays a wave. Because a clocked layer moves in unison, its\n * `pulse`/`grow` periods must satisfy `period / rate ≥ 1000 ms` (1 Hz).\n */\n clock?: { phase?: number; rate?: number };\n}\n\n/**\n * Closed-form velocity easing for `drift`, `rise` and `wander`. `settle`\n * starts at the entity's speed and decelerates to rest with time constant\n * `tau` ms — it travels `speed × tau` and stops, a mark flung and coming to\n * rest. `buoyant` starts at rest and approaches the speed over `tau` — a\n * bubble reaching terminal velocity. Position stays an analytic function of\n * t (no integration state). With `emit`, the eased travel restarts from the\n * spawn point on every event. For `wander` only the base velocity eases —\n * the harmonic meander keeps breathing, so a settled wanderer hovers rather\n * than freezes.\n */\nexport interface MotionEase {\n type: 'settle' | 'buoyant';\n tau: number;\n}\n\nexport type SpriteSpec =\n | { kind: 'emoji'; glyphs: string[]; cycle?: CycleSpec }\n | {\n kind: 'text';\n strings: string[];\n color?: string;\n font?: string;\n align?: 'left' | 'center' | 'right';\n baseline?: 'top' | 'middle' | 'bottom';\n maxWidth?: number;\n cycle?: CycleSpec;\n /** See `TextRole`. Absent ⇒ no legibility advisories, no pixel change. */\n role?: TextRole;\n }\n /** `soft` renders a radial falloff (glow orb) instead of a hard disc.\n * `colorWeights` (same length as `colors`) biases the seeded per-entity pick —\n * \"mostly cool tones, occasional ember\" without duplicating entries. */\n | { kind: 'circle'; radius: [number, number]; color: string; soft?: boolean; colors?: string[]; colorWeights?: number[] }\n /** Unfilled circle (bubbles, portals, sonar pings). `width` = stroke width. */\n | { kind: 'ring'; radius: [number, number]; color: string; width?: number; colors?: string[]; colorWeights?: number[] }\n /**\n * A line segment oriented along the entity's instantaneous heading (derived\n * analytically from its motion) with a faded tail — rain that reads as rain,\n * shooting stars, warp stars. `length` is the segment length range; `width` the\n * stroke width.\n */\n | { kind: 'streak'; length: [number, number]; color: string; width?: number; colors?: string[]; colorWeights?: number[] }\n /**\n * Axis-aligned rectangle (rotates with `spin`). `width` is the horizontal size\n * range; `aspect` the height/width ratio range (default [1,1] = squares).\n * `feather` (0..1) softens the edges: that fraction of the half-size fades\n * out toward the border — Rothko's soft-edged block at 0.5–0.8.\n * Mondrian blocks, confetti, city lights.\n */\n | { kind: 'rect'; width: [number, number]; aspect?: [number, number]; color: string; feather?: number; colors?: string[]; colorWeights?: number[] }\n /**\n * A data bar. Entity i draws a bar `length × values[i] / max` long (viewport\n * units of min(w,h)), `thickness` thick, growing from its position toward\n * `direction` (default 'right'). `values` are PAINT — steer\n * `layers.N.sprite.values` and the bars glide; `max` defaults to the largest\n * value. Pair with a `list` layout: a chart is one layer, labels another.\n */\n | {\n kind: 'bar';\n values: number[];\n length: number;\n thickness: number;\n color: string;\n max?: number;\n direction?: 'right' | 'left' | 'up' | 'down';\n colors?: string[];\n colorWeights?: number[];\n }\n /**\n * Regular or custom polygon. `sides` (3..12, default 6) draws a regular\n * n-gon of the seeded `radius` (circumradius), point up; `points` (3..24\n * unit coordinates in −1..1, scaled by the radius) draws any facet — a\n * Picasso shard, a Kandinsky triangle, a Mondrian plane. `soft` feathers\n * the fill from the centre like a soft circle. Rotates with `spin`.\n */\n | { kind: 'polygon'; radius: [number, number]; color: string; sides?: number; points?: Array<[number, number]>; path?: string; fillRule?: 'auto' | 'nonzero' | 'evenodd'; fill?: boolean; gradient?: PathGradient; stroke?: PathStroke; parts?: PathPart[]; span?: 'box' | 'width' | 'height' | 'screen'; origin?: [number, number]; soft?: boolean; colors?: string[]; colorWeights?: number[] }\n /**\n * A freehand mark: a path through `points` (2..24 unit coordinates in\n * −1..1, scaled by the seeded `length`) stroked `width` wide with round\n * joins. `curve: 'smooth'` (default) runs a Catmull-Rom spline through the\n * points, `'linear'` a polyline. `taper` thins the mark to almost nothing at\n * both ends — a brush stroke rather than a line. `orient` turns the path's\n * +x along the entity's heading (like `streak`). Rotates with `spin`. Van\n * Gogh's stroke, Hokusai's contour, O'Keeffe's petal, Basquiat's scrawl.\n */\n | {\n kind: 'stroke';\n length: [number, number];\n points: Array<[number, number]>;\n color: string;\n width?: number;\n curve?: 'smooth' | 'linear';\n taper?: boolean;\n orient?: boolean;\n colors?: string[];\n colorWeights?: number[];\n }\n /**\n * Multi-line text block with deterministic line-breaking. Unlike `text` (one\n * string drawn as a single fillText call), `textBlock` wraps `text` within\n * `maxWidth` using a fixed metrics table so line breaks are identical across\n * platforms (same seed → same frames). All dimensions are viewport-fraction\n * (of `min(w,h)`), not px — addresses the absolute-font-size inconsistency.\n * Use with `count: 1`, `motion: { type: 'static' }`, and `position`.\n */\n | {\n kind: 'textBlock';\n text: string;\n /** Wrap width as a fraction of `min(w,h)` (up to 2.0 — `text-off-screen` catches overflow). */\n maxWidth: number;\n fontSize: number;\n lineHeight?: number;\n /** Moves the painted lines inside the wrap width (ragged edge); never the block. */\n align?: 'left' | 'center' | 'right';\n color?: string;\n reveal?: TextRevealSpec;\n /**\n * Which point of the rendered text (widest line × lines·lineHeight, as\n * `align` lays it out) `position` names. Absent: today's behaviour —\n * `position` is the top-left of the `maxWidth` layout box. With\n * `'center'` the block is centred at `position` on every aspect ratio.\n * Placement, so it is in the structural signature.\n */\n anchor?: TextBlockAnchor;\n /**\n * CSS font family and/or weight/style only (`\"bold monospace\"`,\n * `\"300 'Inter', sans-serif\"`). A size inside it is rejected —\n * `fontSize` owns size. Absent: `system-ui, sans-serif`.\n */\n font?: string;\n /**\n * 0..1 multiplier on the block's paint alpha (default 1). Paint, not\n * carpentry: excluded from the structural signature, so steering it\n * with `dur` glides the block in or out without a rebuild. Declare it\n * (`\"opacity\": 1`) to make the path steerable.\n */\n opacity?: number;\n /** See `TextRole`. Absent ⇒ no legibility advisories, no pixel change. */\n role?: TextRole;\n };\n\n/**\n * What a text layer is *for* — a declaration, not a pixel. `read` says the\n * words must be readable from across the room and opts the layer into\n * `adviseSpec`'s legibility advisories (`text-legibility`, `text-safe-area`).\n * `atmosphere` says the text is texture (a haiku fading in a corner, dim\n * labels on a wall board) and is the same as absent: silent. Changes no\n * pixel anywhere, on any client; never part of the structural signature.\n */\nexport type TextRole = 'read' | 'atmosphere';\n\n/** Compass points of a `textBlock`'s rendered box that `position` may name. */\nexport type TextBlockAnchor =\n | 'top-left' | 'top' | 'top-right'\n | 'left' | 'center' | 'right'\n | 'bottom-left' | 'bottom' | 'bottom-right';\n\n/**\n * Animated typing/deleting for `textBlock`. Layout always runs on the FULL\n * text — reveal only masks which glyphs are painted, so lines never reflow\n * and the block's box never changes size. `progress` is a numeric paint\n * param (excluded from the structural signature), so steering it with\n * `dur`/`ease` animates typing client-side in one call; gliding it back to 0\n * deletes. With center/right `align`, the revealing line stays anchored to\n * its alignment as it types (only left-aligned text reads as a classic\n * typewriter).\n */\nexport interface TextRevealSpec {\n /**\n * 0..1 fraction of the text revealed (default 1 = fully shown). Quantized\n * by `mode`. Steerable paint — glide it to animate typing or deleting.\n */\n progress?: number;\n /**\n * Reveal granularity: per-grapheme (default), per-word, per-line, or\n * `glyphFade` — each glyph fades in over a staggered alpha ramp instead of\n * appearing whole (the caption look). Still a pure function of `progress`.\n */\n mode?: 'typewriter' | 'word' | 'line' | 'glyphFade';\n /**\n * Self-typing rate in graphemes/second from scene start (media time). The\n * effective progress is `min(progress, speed·t/total)` — so a steered\n * `progress` can hold or delete even while `speed` is set. 0 = off.\n */\n speed?: number;\n /**\n * Caret at the reveal frontier. `true` for defaults, or configure blink\n * rate (Hz, full cycles/sec, capped at 3 for flash safety) and color.\n * Blink is a square wave of `t` — deterministic like everything else.\n */\n caret?: boolean | { blink?: number; color?: string };\n /**\n * `glyphFade` only: each glyph's fade window as a fraction of progress\n * (0 exclusive to 1, default 0.15). Small = soft typewriter; large = a\n * wave of overlapping fades. Ignored by the other modes.\n */\n fade?: number;\n}\n\n/** Rotate through sprite variants over time. Each entity offsets by its seeded phase. */\nexport interface CycleSpec {\n period: number;\n}\n\nexport type MotionSpec =\n /**\n * Drift at a per-entity speed picked from `speed` (px/sec) along `angle` degrees\n * (0 = right, 90 = down; default 0). `bidirectional` randomly flips horizontal\n * direction per entity (e.g. fish swimming both ways); `bob` adds a small vertical\n * wobble amplitude (px). Covers horizontal fields, diagonals (toasters) and rain\n * (angle 90).\n */\n | { type: 'drift'; speed: [number, number]; angle?: number; bidirectional?: boolean; bob?: number; ease?: MotionEase }\n /** Rise upward (px/sec) with an optional horizontal sway amplitude (px) — bubbles. */\n | { type: 'rise'; speed: [number, number]; sway?: number; ease?: MotionEase }\n /** Bounce diagonally at a per-entity speed, reflecting off the edges (px/sec). */\n | { type: 'bounce'; speed: [number, number] }\n /** Entity stays exactly where placed. No movement. Use with `position` for pinned elements. */\n | { type: 'static' }\n /**\n * Orbit around a center point. Each entity gets a seeded radius from `radius`\n * and a seeded phase. `speed` is angular velocity in degrees/sec. `center` is\n * fractional {x, y} (default {0.5, 0.5} = viewport center) — or\n * `{ layer: key }` to orbit a single-entity parent layer (moons around a\n * wandering planet). Strictly one level deep: the parent may not itself\n * orbit a layer, and must have `count: 1`.\n */\n | { type: 'orbit'; speed: [number, number]; radius: [number, number]; center?: { x: number; y: number } | { layer: string } }\n /**\n * Organic harmonic drift — the analytic flow field. Each entity moves at a base\n * velocity from `speed` plus 3 seeded sine octaves per axis, producing flowing\n * curved paths (Flurry streams, aurora, jellyfish) with zero simulation state.\n * `angle` fixes the base heading in degrees (omit for a seeded heading per\n * entity); `meander` scales the harmonic amplitude (dimensional, default 0.05\n * viewport units); `coherence` (0..1) blends every entity's harmonics toward a\n * shared layer-level set — at 1 the field undulates in unison (fake flocking).\n */\n | { type: 'wander'; speed: [number, number]; angle?: number; meander?: number; coherence?: number; ease?: MotionEase }\n /**\n * Perspective starfield: entities live on a depth axis and stream toward the\n * viewer, projected as `screen = center + offset / z`. Size and alpha scale\n * with 1/z (small and faint at the far plane, large and fast up close), and z\n * wraps — the honest warp tunnel. `speed` is in depth-units/sec\n * (1 = full near-to-far span per second, capped at LIMITS.maxWarpSpeed).\n */\n | { type: 'warp'; speed: [number, number]; center?: { x: number; y: number } }\n /**\n * Choreographed spline motion: entities traverse `points` (fractional {x,y})\n * over `duration` ms. `curve: 'smooth'` (default) uses Catmull-Rom through the\n * points; 'linear' uses straight segments. `closed` (default true) loops the\n * path; open paths ping-pong. Each entity gets a seeded phase offset along the\n * path, and `scatter` (dimensional) adds a seeded per-entity offset so shared\n * paths don't stack. Figure-eights, sweeping arcs, patrol routes.\n */\n | {\n type: 'path';\n points: Array<{ x: number; y: number }>;\n duration: number;\n curve?: 'linear' | 'smooth';\n closed?: boolean;\n scatter?: number;\n };\n\n/** A validation problem, pointing at a JSON path within the spec. */\nexport interface SpecError {\n path: string;\n message: string;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n errors: SpecError[];\n /** Non-blocking warnings about unknown/misplaced properties or likely authoring mistakes. */\n warnings?: SpecWarning[];\n}\n\n/** An advisory warning (non-blocking). Returned by `adviseSpec`. */\nexport interface SpecWarning {\n path: string;\n code: string;\n message: string;\n /**\n * Viewport-fraction boxes (`x`, `y`, `w`, `h` of `width`/`height`) the\n * warning is about — `text-overlap` carries the two text boxes so an agent\n * can move one without re-deriving the layout. Present only where a\n * warning has geometry to report.\n */\n boxes?: WarningBox[];\n}\n\n/** A rectangle in viewport fractions (x/w of width, y/h of height). */\nexport interface WarningBox {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/** Perf/safety caps enforced by `validateSpec`. */\nexport const LIMITS = {\n maxPerLayer: 400,\n maxTotal: 800,\n maxLayers: 36,\n maxSpeed: 4000, // px/sec — bounds motion so nothing teleports\n maxPulseAmp: 0.5, // opacity breathing amplitude cap\n minPulsePeriod: 500, // ms — caps pulse at 2 Hz (WCAG flash threshold is 3 Hz)\n maxSpin: 360, // degrees/sec — one full revolution per second\n maxRotate: 360, // degrees — static per-entity rotation, one turn either way\n maxGrowAmp: 0.8, // size breathing amplitude cap (fraction of base size)\n maxOrbitSpeed: 180, // degrees/sec — half a revolution per second\n maxLinksK: 8,\n maxLinkLayerCount: 200,\n minCyclePeriod: 500, // ms — same flash-safety floor as pulse\n referenceViewport: 1080, // for validating viewport-unit dimensional caps\n maxTrailLength: 5000, // ms — cap trail duration\n maxTrailSamples: 24, // dots per trail\n minDriftPeriod: 10000, // ms — background drift floor (10 s), gradient and field alike\n maxDriftAmount: 0.3, // fraction of gradient stop shift\n minFieldScale: 0.5, // features per short side — below this the field is one flat blob\n maxFieldScale: 8, // above this a 96 px raster cell spans more than one feature\n maxFieldOctaves: 4,\n minFieldBands: 2,\n maxFieldBands: 8,\n maxFieldQuantize: 8,\n maxFieldDriftAmount: 1, // feature units of domain travel\n maxGhosting: 0.95, // frame persistence cap — bounds the seek warm-up replay\n maxGhostReplayFrames: 120, // fixed-step frames replayed on a non-contiguous seek\n maxMeander: 500, // px — wander harmonic amplitude cap (viewport cap: /referenceViewport)\n maxWarpSpeed: 1.5, // depth-units/sec — full near-to-far span in ~0.7 s at max\n minPathPoints: 2,\n maxPathPoints: 24,\n minPathDuration: 2000, // ms — a path lap can't be faster than this\n maxGridColumns: 100,\n maxTextBlockLength: 2000,\n minTextBlockFontSize: 0.01,\n maxTextBlockFontSize: 0.2,\n maxTextBlockMaxWidth: 2.0, // of min(w,h) — wider than the frame is legal; text-off-screen reports the overflow\n maxRevealSpeed: 120, // graphemes/sec — faster than any readable typing\n maxCaretBlinkHz: 3, // full blink cycles/sec — WCAG 2.3.1 flash-safety cap\n maxSegments: 24,\n minSegmentDuration: 1000, // ms — flash-safety floor: segment cuts are luminance transitions\n maxTransitionDur: 5000,\n minTransitionDur: 200,\n minEmitEvery: 1000, // ms — at most one event per second per entity (flash safety)\n maxTimelineKeys: 256,\n minTimelineKeyInterval: 200, // ms — distinct key times on one path (flash safety; the timeline design's floor)\n maxTimelineKeyDur: 30000, // ms — one key's glide\n maxTimelineDuration: 86400000, // ms — a looping timeline's lap (a day)\n maxLayerTransformOffset: 2, // min(w,h) units — transform x/y and position dx/dy\n maxLayerTransformOffsetPx: 17280, // px, under `units: 'px'` — twice the largest referenceViewport\n maxLayerTransformScale: 8,\n maxLayerTransformRotate: 3600, // degrees\n maxGroups: 16,\n maxEmitEvery: 600000, // ms — ten minutes; longer silences than that are `life.enter`\n minEmitLife: 500, // ms — an event is a smooth envelope, never a cut\n maxEmitGrow: 8, // × base size across an event window\n minClockedPeriod: 1000, // ms — a `clock`ed layer breathes in unison, so 1 Hz not 2\n minClockRate: 0.1,\n maxClockRate: 4,\n defaultListGap: 0.06, // viewport units between list/table cells (40 px in px specs)\n defaultListGapPx: 40,\n minPolygonSides: 3,\n maxPolygonSides: 12,\n maxShapePoints: 24, // polygon.points / stroke.points\n minEaseTau: 100, // ms\n maxEaseTau: 120000, // ms\n} as const;\n\n// ---------------------------------------------------------------------------\n// Sequence envelope — multi-segment timeline over unmodified SaverSpecs\n// ---------------------------------------------------------------------------\n\nexport type SequenceTransition =\n | { type: 'cut' }\n /**\n * Interpolate numbers and hex colours into the next (structurally\n * identical) segment over `dur` ms. Strings step on the first frame —\n * unless `text: 'crossfade'`, which draws each `text` / `textBlock` layer\n * whose string(s) differ twice for the window: the outgoing string at\n * `1 − k`, the incoming at `k` (k = the morph's eased progress). `'dip'`\n * draws the same two passes one after the other instead — the outgoing\n * words fade out over the first half, the incoming fade in over the second —\n * so the two strings never overlap. Default `'step'`, today's behaviour,\n * byte for byte.\n */\n | { type: 'morph'; dur: number; text?: 'step' | 'crossfade' | 'dip' }\n /**\n * Cross-fade into the next segment over `dur` ms: the outgoing segment\n * stays alive on its own canvas and is composited over the incoming one\n * at `1 − easeSmooth(localT / dur)`. Works between unlike segments (no\n * structural requirement). Hosts on the `basic`/`minimal` capability tier\n * render it as `cut` (see `SequenceMountContext.capabilityTier`).\n */\n | { type: 'fade'; dur: number };\n\nexport interface SequenceSegment {\n key: string;\n scene: SaverSpec;\n /** Segment duration in ms. Only the final segment may omit this (holds until input). */\n duration?: number;\n /** How the segment advances: 'auto' (timer), 'input' (external event), 'either'. */\n advance?: 'auto' | 'input' | 'either';\n transition?: SequenceTransition;\n}\n\nexport interface IdleSequence {\n format: 'idle-sequence';\n schemaVersion: 1;\n id: string;\n label: string;\n seed?: number;\n loop: boolean;\n /**\n * What the sequence clock is anchored to. `mount` (default — today's\n * behaviour): every viewer starts at T = 0 when it mounts, so a joiner sees\n * segment 0 (pre-roll semantics). `epoch`: a viewer handed `sequenceBaseT`\n * on its mount context (the host's `Date.now() − epoch`) starts its clock\n * there, so every screen in a room shows the same segment — a late joiner\n * lands mid-loop. `advance: 'input'` holds stay armed under either mode.\n */\n sync?: 'mount' | 'epoch';\n /**\n * Honour a `morph` declared on the last segment at the loop wrap (the lap\n * morphs back into segment 0 instead of cutting). Opt-in: without it a\n * last-segment morph stays a cut at the wrap, as every stored sequence\n * expects. Takes effect only when the whole loop is one morph chain (every\n * segment morphs into the next, and the last is a structural twin of the\n * first) — so every lap reuses the same child and seed; otherwise it is a\n * cut and the validator says why. Needs `loop: true`.\n */\n wrapMorph?: boolean;\n /**\n * A scene drawn under every segment on the sequence's **global** clock —\n * the ground that does not reset at a boundary or under a `sequence.segment`\n * steer. Segments render over it transparently (their `background` and\n * `ghosting` are ignored; the bed may declare its own). Its entities count\n * toward the perf cap together with the largest segment's, since the two\n * are live at once. Steer it with `bed.<path>`. Absent ⇒ every segment\n * paints its own ground, exactly as before the field existed.\n */\n bed?: SaverSpec;\n /**\n * A print finish applied once per composed frame — over bed, segment and\n * any fade together, on the sequence's presentation canvas. Overrides\n * every segment's own `finish` while set; absent, the active segment's\n * `finish` applies when it declares one (a bed's is ignored — the bed is\n * ground, finish the sequence). Children never apply their own.\n */\n finish?: FinishSpec;\n segments: SequenceSegment[];\n}\n\n/**\n * A gradient fill for a path polygon, in the path's own −1..1 unit box (so it\n * scales and rotates with the drawing). Overrides `color` for the fill;\n * `color` stays what perception and palettes read when no gradient is known.\n */\nexport type PathGradient =\n | { type: 'linear'; from: [number, number]; to: [number, number]; stops: PathGradientStop[]; units?: 'box' | 'part' }\n | { type: 'radial'; center: [number, number]; radius: number; focus?: [number, number]; stops: PathGradientStop[]; units?: 'box' | 'part' };\nexport interface PathGradientStop { at: number; color: string; opacity?: number }\n\n/** An outline drawn along every subpath of a path polygon (open ones too). `width` is in unit-box units. */\nexport interface PathStroke { color: string; width: number; opacity?: number; join?: 'round' | 'miter' | 'bevel'; cap?: 'round' | 'butt' | 'square' }\n\n/**\n * One piece of a multi-colour path drawing (`polygon.parts`), drawn back to\n * front in the drawing's unit box: its own outline, colour (default: the\n * sprite's), gradient, stroke and opacity. A gradient with `units: 'part'`\n * reads its coordinates in this part's own bounding box mapped to −1..1, so\n * one gradient spec shades each piece on its own.\n */\nexport interface PathPart {\n path: string;\n color?: string;\n fillRule?: 'auto' | 'nonzero' | 'evenodd';\n fill?: boolean;\n gradient?: PathGradient;\n stroke?: PathStroke;\n opacity?: number;\n}\n","/**\n * Pure helpers for LIVE steering of compiled specs (setParam / applyTrack).\n * A track's deltas address spec fields by dot-path (\"layers.0.count\",\n * \"background.stops.1.color\") or layer key (\"fireflies.count\"). Steering\n * changes existing values only — unknown paths are ignored (the server\n * validates and rejects them; the runtime stays lenient).\n */\nimport { LIMITS, type IdleSequence, type SaverSpec, type SpriteSpec } from './types';\n// Cycle (validate.ts imports structuralSignature from here) is safe: neither\n// module touches the other's exports at load time, only inside functions.\nimport { ignoredPropertyPaths } from './validate';\n\ninterface PathTarget {\n parent: Record<string, unknown> | unknown[];\n key: string | number;\n}\n\nconst UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\nconst STEERABLE_ROOT_KEYS = new Set(['ghosting', 'referenceViewport', 'finish', 'groups']);\n\n/** Resolve a dot-path (key-aware) to its parent + final key; null if absent. */\nexport function resolveSpecPath(spec: unknown, path: string): PathTarget | null {\n if (!spec || typeof spec !== 'object' || !path) return null;\n const parts = path.split('.');\n if (parts.some((p) => UNSAFE_KEYS.has(p))) return null;\n const s = spec as { layers?: Array<Record<string, unknown>> };\n if (parts[0] !== 'layers' && parts[0] !== 'background' && Array.isArray(s.layers)) {\n // A layer's own key wins over a root field of the same name — a layer\n // named \"ghosting\" or \"referenceViewport\" must still resolve to itself,\n // not get shadowed by the identically-named root scalar.\n const idx = s.layers.findIndex((l) => l && l.key === parts[0]);\n if (idx !== -1) {\n parts.splice(0, 1, 'layers', String(idx));\n } else if (!STEERABLE_ROOT_KEYS.has(parts[0]!)) {\n return null;\n }\n }\n // Group membership and a transform's `origin` are enums that can only step\n // — a steer or key on them would jump — so they are not steer targets.\n if (parts[0] === 'layers' && parts.length === 3 && parts[2] === 'group') return null;\n if (parts.length >= 2 && parts[parts.length - 1] === 'origin' && parts[parts.length - 2] === 'transform') return null;\n let node: unknown = spec;\n for (let i = 0; i < parts.length - 1; i++) {\n if (node === null || typeof node !== 'object') return null;\n node = (node as Record<string, unknown>)[parts[i]!];\n }\n if (node === null || typeof node !== 'object') return null;\n const last = parts[parts.length - 1]!;\n const key: string | number = Array.isArray(node) ? Number(last) : last;\n const exists = Array.isArray(node)\n ? Number.isInteger(key as number) && (key as number) >= 0 && (key as number) < node.length\n : last in (node as Record<string, unknown>);\n return exists ? { parent: node as PathTarget['parent'], key } : null;\n}\n\n/**\n * The index form of a key-aware dot-path (`fireflies.sprite.color` →\n * `layers.3.sprite.color`), or null when it does not resolve. Two paths that\n * address the same field compare equal after this — how a live steer finds\n * out whether a `timeline` key animates the field it touches.\n */\nexport function canonicalSpecPath(spec: unknown, path: string): string | null {\n if (!resolveSpecPath(spec, path)) return null;\n const parts = path.split('.');\n const s = spec as { layers?: Array<Record<string, unknown>> };\n if (parts[0] !== 'layers' && parts[0] !== 'background' && Array.isArray(s.layers)) {\n const idx = s.layers.findIndex((l) => l && l.key === parts[0]);\n if (idx !== -1) parts.splice(0, 1, 'layers', String(idx));\n }\n return parts.join('.');\n}\n\n/** Read the value at a dot-path, or undefined when it does not resolve. */\nexport function readSpecPath(spec: unknown, path: string): unknown {\n const loc = resolveSpecPath(spec, path);\n return loc ? (loc.parent as Record<string | number, unknown>)[loc.key] : undefined;\n}\n\nconst TRANSFORM_IDENTITY: Record<string, number> = { x: 0, y: 0, scale: 1, scaleX: 1, rotate: 0 };\n\n/** Two layer `transform` objects with each one's missing fields filled with the identity, so a glide between them never steps (inputs returned as-is otherwise). */\nfunction alignTransform(a: unknown, b: unknown): [unknown, unknown] {\n const isObj = (v: unknown): v is Record<string, unknown> => !!v && typeof v === 'object' && !Array.isArray(v);\n if (!isObj(a) || !isObj(b)) return [a, b];\n let fa: Record<string, unknown> | null = null;\n let fb: Record<string, unknown> | null = null;\n for (const key of new Set([...Object.keys(a), ...Object.keys(b)])) {\n const id = TRANSFORM_IDENTITY[key];\n if (id === undefined) continue;\n if (a[key] === undefined) (fa ??= { ...a })[key] = id;\n if (b[key] === undefined) (fb ??= { ...b })[key] = id;\n }\n return [fa ?? a, fb ?? b];\n}\n\n/**\n * When only one end of a spec lerp declares a layer's paint `opacity` or\n * `transform`, give the other end the identity value (opacity 1, x/y/rotate 0,\n * scale/scaleX 1) so the lerp glides from how the layer actually looks\n * instead of stepping. Returns the inputs themselves when no layer differs —\n * every spec without these fields lerps exactly as it always has.\n */\nfunction alignPaintFields(a: unknown, b: unknown): [unknown, unknown] {\n const la = (a as { layers?: unknown[] } | null)?.layers;\n const lb = (b as { layers?: unknown[] } | null)?.layers;\n if (!Array.isArray(la) || !Array.isArray(lb)) return [a, b];\n let outA: unknown[] | null = null;\n let outB: unknown[] | null = null;\n const n = Math.min(la.length, lb.length);\n for (let i = 0; i < n; i++) {\n const x = la[i] as Record<string, unknown> | null;\n const y = lb[i] as Record<string, unknown> | null;\n if (!x || !y || typeof x !== 'object' || typeof y !== 'object') continue;\n let nx = x;\n let ny = y;\n // A layer that joins or leaves a group keeps the membership through the\n // lerp; the group branch below gives the end without that group an\n // identity entry, so the group's paint glides instead of dropping.\n if ((x.group === undefined) !== (y.group === undefined)) {\n if (x.group === undefined) nx = { ...nx, group: y.group };\n else ny = { ...ny, group: x.group };\n }\n if ((x.opacity === undefined) !== (y.opacity === undefined)) {\n if (x.opacity === undefined) nx = { ...nx, opacity: 1 };\n else ny = { ...ny, opacity: 1 };\n }\n const tx = x.transform as Record<string, unknown> | undefined;\n const ty = y.transform as Record<string, unknown> | undefined;\n if (tx || ty) {\n const fx: Record<string, unknown> = { ...(tx ?? {}) };\n const fy: Record<string, unknown> = { ...(ty ?? {}) };\n let changed = !tx || !ty;\n for (const key of new Set([...Object.keys(fx), ...Object.keys(fy)])) {\n const id = TRANSFORM_IDENTITY[key];\n if (id === undefined) continue;\n if (fx[key] === undefined) { fx[key] = id; changed = true; }\n if (fy[key] === undefined) { fy[key] = id; changed = true; }\n }\n if (changed) { nx = { ...nx, transform: fx }; ny = { ...ny, transform: fy }; }\n }\n if (nx !== x) (outA ??= la.slice())[i] = nx;\n if (ny !== y) (outB ??= lb.slice())[i] = ny;\n }\n let ra: unknown = outA ? { ...(a as object), layers: outA } : a;\n let rb: unknown = outB ? { ...(b as object), layers: outB } : b;\n // Groups: a group present on only one end glides from the identity (no\n // transform, opacity 1); so does a group opacity set on one end only.\n const ga = (a as { groups?: Record<string, Record<string, unknown>> }).groups;\n const gb = (b as { groups?: Record<string, Record<string, unknown>> }).groups;\n if (ga || gb) {\n const na: Record<string, Record<string, unknown>> = { ...(ga ?? {}) };\n const nb: Record<string, Record<string, unknown>> = { ...(gb ?? {}) };\n let changed = !ga || !gb;\n for (const name of new Set([...Object.keys(na), ...Object.keys(nb)])) {\n const x = na[name] ?? {};\n const y = nb[name] ?? {};\n if (!na[name] || !nb[name]) changed = true;\n let nx = x;\n let ny = y;\n if ((x.opacity === undefined) !== (y.opacity === undefined)) {\n if (x.opacity === undefined) nx = { ...nx, opacity: 1 };\n else ny = { ...ny, opacity: 1 };\n changed = true;\n }\n if (!x.transform !== !y.transform) {\n if (!x.transform) nx = { ...nx, transform: {} };\n else ny = { ...ny, transform: {} };\n changed = true;\n }\n na[name] = nx;\n nb[name] = ny;\n }\n if (changed) {\n ra = { ...(ra as object), groups: na };\n rb = { ...(rb as object), groups: nb };\n }\n }\n return [ra, rb];\n}\n\n/** A steering delta as carried on a channel control-track. */\nexport interface SteerDelta {\n t: number;\n path: string;\n value: unknown;\n ease?: string;\n dur?: number;\n}\n\n/** Apply deltas to a deep copy of the spec (last-wins, target values). */\nexport function applyDeltasToSpec(spec: SaverSpec, deltas: SteerDelta[]): SaverSpec {\n const copy = JSON.parse(JSON.stringify(spec)) as SaverSpec;\n for (const d of deltas) {\n const loc = resolveSpecPath(copy, d.path);\n if (loc) (loc.parent as Record<string | number, unknown>)[loc.key] = d.value;\n }\n return copy;\n}\n\nconst HEX = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;\n\nfunction hexToRgb(hex: string): [number, number, number] {\n const h = hex.length === 4 ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex;\n const n = parseInt(h.slice(1), 16);\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\n\nfunction lerpHex(a: string, b: string, k: number): string {\n const ca = hexToRgb(a);\n const cb = hexToRgb(b);\n const mix = ca.map((v, i) => Math.round(v + (cb[i]! - v) * k));\n return `#${mix.map((v) => v.toString(16).padStart(2, '0')).join('')}`;\n}\n\n/**\n * Interpolate between two structurally-similar specs at progress k (0..1).\n * Numbers lerp, hex colours lerp per channel, everything else steps to the\n * target immediately (k > 0). Layer counts, and a field background's\n * `octaves` / `quantize`, round to whole values.\n */\nexport function lerpSpec(from: SaverSpec, to: SaverSpec, k: number): SaverSpec {\n const kk = Math.max(0, Math.min(1, k));\n const out = lerpValue(from, to, kk, true) as SaverSpec;\n return out;\n}\n\n/**\n * The walk behind `lerpSpec`, for any value: numbers lerp, hex colours lerp\n * per channel, equal-length arrays and objects recurse, everything else steps\n * to the target at k > 0 (`count` rounds). At a spec's root a `timeline` steps\n * too — two timelines' key times must never blend. No existing spec carries a\n * timeline, so every stored morph and glide is unchanged.\n */\nexport function lerpValue(from: unknown, to: unknown, k: number, specRoot = false, rootKey?: string): unknown {\n if (specRoot) [from, to] = alignPaintFields(from, to);\n if (rootKey === 'transform') [from, to] = alignTransform(from, to);\n const kk = Math.max(0, Math.min(1, k));\n const walk = (a: unknown, b: unknown, key?: string | number, root = false): unknown => {\n if (typeof a === 'number' && typeof b === 'number') {\n const v = a + (b - a) * kk;\n if (key === 'count') return Math.max(1, Math.round(v));\n // A field background's level counts are integers (X477): a glide steps\n // through whole levels, as the painter already reads them. `quantize`\n // below 1.5 is smooth (0) — never the invalid 1 — matching `fieldRgb`,\n // which paints any level count under 2 as the smooth ramp.\n if (key === 'octaves') return Math.round(v);\n if (key === 'quantize') { const q = Math.round(v); return q < 2 ? 0 : q; }\n return v;\n }\n if (typeof a === 'string' && typeof b === 'string' && HEX.test(a) && HEX.test(b)) {\n return lerpHex(a, b, kk);\n }\n if (key === 'path' && typeof a === 'string' && typeof b === 'string' && a !== b) {\n // Two SVG paths with the same commands (Lottie's rule: same letters,\n // same number count) morph number by number; otherwise they step.\n const m = lerpPathD(a, b, kk);\n if (m !== null) return m;\n }\n if (Array.isArray(a) && Array.isArray(b) && a.length === b.length) {\n return b.map((bv, i) => walk(a[i], bv, i));\n }\n if (a && b && typeof a === 'object' && typeof b === 'object' && !Array.isArray(a) && !Array.isArray(b)) {\n const out: Record<string, unknown> = {};\n for (const kName of Object.keys(b as Record<string, unknown>)) {\n const av = (a as Record<string, unknown>)[kName];\n const bv = (b as Record<string, unknown>)[kName];\n out[kName] = root && kName === 'timeline' ? (kk > 0 ? bv : av) : kName === 'transform' ? walk(...alignTransform(av, bv), kName) : walk(av, bv, kName);\n }\n return out;\n }\n return kk > 0 ? b : a; // non-interpolable → step to target\n };\n return walk(from, to, rootKey, specRoot);\n}\n\nconst PATH_TOKEN = /[a-zA-Z]|[-+]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][-+]?\\d+)?/g;\n\n/**\n * Interpolate two SVG path d strings that share their structure — the same\n * command letters in the same order and the same count of numbers — by\n * lerping every number; null when they differ in structure (the morph then\n * steps). Arc flags (0/1) round, so a half-way arc stays a valid arc.\n */\nexport function lerpPathD(a: string, b: string, k: number): string | null {\n const ta = a.match(PATH_TOKEN) ?? [];\n const tb = b.match(PATH_TOKEN) ?? [];\n if (ta.length !== tb.length) return null;\n const out: string[] = [];\n let cmd = '';\n let argIndex = 0;\n for (let i = 0; i < ta.length; i++) {\n const x = ta[i]!, y = tb[i]!;\n const isCmdA = /^[a-zA-Z]$/.test(x), isCmdB = /^[a-zA-Z]$/.test(y);\n if (isCmdA !== isCmdB) return null;\n if (isCmdA) {\n if (x !== y) return null;\n cmd = x.toUpperCase();\n argIndex = 0;\n out.push(x);\n continue;\n }\n const va = Number(x), vb = Number(y);\n const flag = cmd === 'A' && (argIndex % 7 === 3 || argIndex % 7 === 4);\n argIndex++;\n const v = va + (vb - va) * k;\n out.push(flag ? String(Math.round(v)) : String(+v.toFixed(5)));\n }\n return out.join(' ');\n}\n\n/**\n * The string(s) a text layer paints — `strings` of a `text` sprite, `text`\n * of a `textBlock` — or null for every other sprite.\n */\nexport function textStringsOf(sprite: SpriteSpec): string[] | null {\n if (sprite.kind === 'text') return sprite.strings;\n if (sprite.kind === 'textBlock') return [sprite.text];\n return null;\n}\n\n/**\n * Whether the text layer at index `i` paints different words in `a` and\n * `b` — the layers a morph `text: 'crossfade'` draws twice. False for\n * non-text layers and when the strings match.\n */\nexport function textStringsDiffer(a: SaverSpec, b: SaverSpec, i: number): boolean {\n const sa = a.layers[i]?.sprite;\n const sb = b.layers[i]?.sprite;\n if (!sa || !sb) return false;\n const ta = textStringsOf(sa);\n const tb = textStringsOf(sb);\n if (!ta || !tb) return false;\n return ta.length !== tb.length || ta.some((s, j) => s !== tb[j]);\n}\n\n/**\n * True when a morph from `a` to `b` has nothing to interpolate: the two specs\n * differ, yet every difference is a value lerpSpec steps (strings such as\n * `textBlock.text`, mismatched arrays) rather than a number or hex colour it\n * glides. Such a morph looks exactly like a cut. Identical specs return\n * false: a no-op morph is continuity, not a cut. Under `textCrossfade`\n * (the transition declared `text: 'crossfade'`) differing text is something\n * to morph — the words cross-fade — so such twins return false too.\n *\n * Walks `a`/`b` directly rather than sampling `lerpSpec(a, b, 0.5)`: two hex\n * colours a single 8-bit step apart (`#000000` → `#010101`) round their\n * midpoint to the target channel-for-channel, which would make a genuine\n * (if subtle) colour glide look identical to a step. `id`/`label`/\n * `schemaVersion`/layer `key` are identification metadata, never rendered\n * (excluded from `structuralSignature`/`steerablePaths` for the same reason)\n * — a segment pair that differs only there renders identically and is not a\n * morph at all.\n */\nconst NON_RENDERED_KEYS = new Set(['id', 'label', 'schemaVersion', 'key']);\n\nexport function morphNothingMorphable(a: SaverSpec, b: SaverSpec, opts: { textCrossfade?: boolean } = {}): boolean {\n if (opts.textCrossfade && a.layers.some((_, i) => textStringsDiffer(a, b, i))) return false;\n let hasDiff = false;\n let hasGlide = false;\n const walk = (x: unknown, y: unknown, key?: string): void => {\n if (key !== undefined && NON_RENDERED_KEYS.has(key)) return;\n if (x === y) return;\n if (typeof x === 'number' && typeof y === 'number') {\n hasDiff = true;\n hasGlide = true;\n return;\n }\n if (typeof x === 'string' && typeof y === 'string' && HEX.test(x) && HEX.test(y)) {\n const ca = hexToRgb(x);\n const cb = hexToRgb(y);\n if (ca.some((v, i) => v !== cb[i])) {\n hasDiff = true;\n hasGlide = true;\n }\n // else: same colour under a different spelling (case, 3- vs 6-digit) — a no-op, not a difference.\n return;\n }\n if (Array.isArray(x) && Array.isArray(y) && x.length === y.length) {\n for (let i = 0; i < y.length; i++) walk(x[i], y[i]);\n return;\n }\n if (x && y && typeof x === 'object' && typeof y === 'object' && !Array.isArray(x) && !Array.isArray(y)) {\n const keys = new Set([...Object.keys(x as Record<string, unknown>), ...Object.keys(y as Record<string, unknown>)]);\n for (const k of keys) {\n walk((x as Record<string, unknown>)[k], (y as Record<string, unknown>)[k], k);\n }\n return;\n }\n hasDiff = true; // non-interpolable → steps to target\n };\n walk(a, b);\n return hasDiff && !hasGlide;\n}\n\n/**\n * Enumerate all steerable leaf paths in a (resolved) spec. Returns dot-paths\n * like \"layers.0.count\", \"background.stops.1.color\", \"background.bands.2\", etc. Metadata fields\n * (id, label, schemaVersion, seed, units, kind, type, key) are excluded —\n * they describe structure, not tuneable values.\n *\n * Properties the validator flags as unknown or misplaced (e.g. `angle` on a\n * gradient background, `blend` inside a sprite) are excluded too: the\n * renderer never reads them, so advertising them invites a steer that\n * silently does nothing. Same source of truth as validateSpec's\n * \"will be ignored\" warnings (`ignoredPropertyPaths`).\n *\n * Layer keys are NOT substituted: paths always use numeric indices.\n * Consumers can map to key-based paths via resolveSpecPath if needed.\n */\nexport function steerablePaths(spec: unknown): string[] {\n if (!spec || typeof spec !== 'object') return [];\n // `group` (membership) and `origin` are enums that step, not knobs; the\n // `timeline` is authored structure, not a steer target (resolveSpecPath\n // refuses it), so none of them are advertised.\n const SKIP = new Set(['kind', 'type', 'key', 'schemaVersion', 'id', 'label', 'seed', 'units', 'motionIntensity', 'mode', 'curve', 'layer', 'group', 'origin']);\n const SKIP_ROOT = new Set(['timeline']);\n // `bands` (a field background's palette) is indexed like `stops`, so\n // `background.bands.2` is a hex paint path that glides.\n const INDEXED = new Set(['layers', 'stops', 'bands', 'parts']);\n // Mirror resolveSpecPath's layer-key precedence: a root field named the\n // same as a layer's key resolves to that layer, not the scalar, so don't\n // advertise a root path we can't actually deliver a delta to.\n const layers = (spec as { layers?: unknown }).layers;\n const shadowedRootKeys = new Set(\n Array.isArray(layers)\n ? layers\n .map((l) => (l && typeof l === 'object' ? (l as Record<string, unknown>).key : undefined))\n .filter((k): k is string => typeof k === 'string' && STEERABLE_ROOT_KEYS.has(k))\n : [],\n );\n const out: string[] = [];\n const walk = (node: unknown, prefix: string, key: string): void => {\n if (Array.isArray(node) && INDEXED.has(key)) {\n node.forEach((child, i) => walk(child, `${prefix}.${i}`, ''));\n return;\n }\n if (Array.isArray(node)) {\n if (prefix) out.push(prefix);\n return;\n }\n if (node && typeof node === 'object') {\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n // Group names are user-chosen: a group called `label` is still a group.\n if (SKIP.has(k) && prefix !== 'groups') continue;\n if (!prefix && (shadowedRootKeys.has(k) || SKIP_ROOT.has(k))) continue;\n walk(v, prefix ? `${prefix}.${k}` : k, k);\n }\n return;\n }\n if (prefix) out.push(prefix);\n };\n walk(spec, '', '');\n const ignored = ignoredPropertyPaths(spec);\n if (ignored.length === 0) return out;\n return out.filter((p) => !ignored.some((ig) => p === ig || p.startsWith(`${ig}.`)));\n}\n\n/**\n * Every path a sequence accepts on its track: `sequence.segment` (the\n * clicker), the bed's paths under the `bed.` prefix, and the union of every\n * segment's paths (a segment path lands on whichever segment owns it — see\n * `SequenceInstance.applyTrack`). Deduplicated, numeric layer indices as in\n * `steerablePaths`.\n */\nexport function sequenceSteerablePaths(seq: IdleSequence): string[] {\n const out = new Set<string>(['sequence.segment']);\n if (seq.bed) for (const p of steerablePaths(seq.bed)) out.add(`bed.${p}`);\n for (const seg of seq.segments) for (const p of steerablePaths(seg.scene)) out.add(p);\n return [...out];\n}\n\n/** Smooth (ease-in-out) progress curve used for glides. */\nexport function easeSmooth(k: number): number {\n const c = Math.max(0, Math.min(1, k));\n return c * c * (3 - 2 * c);\n}\n\n/**\n * Fields that require re-seeding entities when they change (placement/motion\n * are baked at build time). Colour/alpha/pulse-only changes redraw in place.\n */\nexport function structuralSignature(spec: SaverSpec): string {\n return JSON.stringify([\n spec.units,\n // Normalized against the same default every renderer uses — an omitted\n // referenceViewport and an explicit 1080 render identically, so they must\n // hash identically or a same-sizing morph gets rejected as structural.\n spec.referenceViewport ?? LIMITS.referenceViewport,\n spec.layers.map((l) => {\n const s = l.sprite as Record<string, unknown>;\n return [\n l.count,\n l.size,\n l.region,\n l.position,\n l.motion,\n l.wrap,\n l.flip,\n l.alpha,\n l.pulse,\n l.spin,\n l.grow,\n l.layout,\n l.emit,\n l.clock,\n l.sprite.kind,\n // Dimensional draws baked into entities: radius (circle/ring), length\n // (streak), width+aspect (rect), palette pick (all shaped sprites).\n s.radius,\n s.length,\n l.sprite.kind === 'rect' ? [s.width, s.aspect] : l.sprite.kind === 'bar' ? [s.length, s.thickness] : undefined,\n Array.isArray(s.colors) ? s.colors.length : undefined,\n s.colorWeights,\n l.sprite.kind === 'emoji'\n ? [l.sprite.glyphs.length, l.sprite.cycle?.period]\n : l.sprite.kind === 'text'\n ? [l.sprite.strings.length, l.sprite.cycle?.period]\n : l.sprite.kind === 'textBlock'\n // `anchor` is placement (in); `font`/`opacity`/`text` are paint\n // (out — opacity must glide). Appended only when set so every\n // existing spec's signature string is byte-identical.\n ? (l.sprite.anchor ? [l.sprite.fontSize, l.sprite.anchor] : [l.sprite.fontSize])\n : undefined,\n // Static rotation is baked into entities (a range draws a seeded\n // angle). Appended only when set — same rule as `anchor` above.\n ...(l.rotate !== undefined ? [l.rotate] : []),\n ];\n }),\n ]);\n}\n","import { structuralSignature } from './steer';\nimport { LIMITS, type IdleSequence, type SequenceTransition } from './types';\n\nexport interface ResolvedSegment {\n index: number;\n localT: number;\n /** Cumulative start time of this segment in the global timeline. */\n startT: number;\n /**\n * Present (true) when the timeline has run past this segment's duration but\n * the segment has `advance: 'input'` and no input has released it yet — the\n * scene keeps animating (`localT` keeps growing) while the show waits for\n * the presenter.\n */\n held?: true;\n}\n\nexport interface ResolveOptions {\n /**\n * Segments below this index have been released by input: a `sequence.segment`\n * steer to index `n` counts as the presenter clicking past every hold before\n * `n`. `SequenceInstance` maintains this; callers resolving a bare timeline\n * leave it at 0, so every `advance: 'input'` hold is honoured.\n */\n releasedBelow?: number;\n}\n\n/** Global start time of segment `index` — the prefix sum of the durations before it. */\nexport function segmentStart(seq: IdleSequence, index: number): number {\n let t = 0;\n const n = Math.max(0, Math.min(index, seq.segments.length - 1));\n for (let i = 0; i < n; i++) t += seq.segments[i]!.duration ?? 0;\n return t;\n}\n\n/**\n * Map global time T to (segmentIndex, localT) via prefix sums of durations.\n * Segments are half-open: [start, start+duration). The final segment may omit\n * duration, in which case it holds indefinitely (T past the last timed segment\n * always resolves to the final one).\n *\n * `advance: 'input'` makes a timed segment hold at its end instead of yielding\n * to the next one — the clicker. `auto` (default) and `either` advance on the\n * timer. A hold is released by a `sequence.segment` steer (see\n * `ResolveOptions.releasedBelow`); the held scene keeps its clock running, so\n * `localT` grows past `duration` rather than freezing.\n *\n * With `loop: true`, T wraps modulo the total duration of all segments — but\n * only once every hold on the current lap has been released; after a wrap\n * every hold is armed again. If the final segment has no duration, looping is\n * over the timed prefix only — the durationless tail is unreachable in loop\n * mode (validated elsewhere).\n */\nexport function resolveSegment(seq: IdleSequence, T: number, opts: ResolveOptions = {}): ResolvedSegment {\n const { segments, loop } = seq;\n if (segments.length === 0) return { index: 0, localT: 0, startT: 0 };\n\n let totalTimed = 0;\n for (const seg of segments) {\n if (seg.duration != null) totalTimed += seg.duration;\n else break;\n }\n\n const t0 = Math.max(0, T);\n\n // Walk the timed prefix once; null means the clock ran off the end.\n const walk = (t: number, releasedBelow: number): ResolvedSegment | null => {\n let cumulative = 0;\n for (let i = 0; i < segments.length; i++) {\n const seg = segments[i]!;\n if (seg.duration == null) {\n // A durationless tail holds forever — except in loop mode, where it\n // is unreachable and the clock wraps instead.\n return loop ? null : { index: i, localT: t - cumulative, startT: cumulative };\n }\n if (t < cumulative + seg.duration) {\n return { index: i, localT: t - cumulative, startT: cumulative };\n }\n if (seg.advance === 'input' && i >= releasedBelow) {\n return { index: i, localT: t - cumulative, startT: cumulative, held: true };\n }\n cumulative += seg.duration;\n }\n return null;\n };\n\n const first = walk(t0, opts.releasedBelow ?? 0);\n if (first) return first;\n\n if (loop && totalTimed > 0) {\n // A fresh lap, with every hold armed again. Always modulo: subtracting\n // one lap (`t0 - totalTimed`) leaves later laps (T ≥ 2×totalTimed) still\n // past the end of the loop, so a released clock lands on the last hold\n // with a growing localT instead of wrapping.\n const wrapped = walk(t0 % totalTimed, 0);\n if (wrapped) return wrapped;\n }\n\n const last = segments.length - 1;\n const lastStart = totalTimed - (segments[last]!.duration ?? 0);\n return { index: last, localT: t0 - lastStart, startT: lastStart };\n}\n\n// ---------------------------------------------------------------------------\n// Render seeds — shared by SequenceInstance (compile.ts) and\n// perceiveSequenceFrame (perceive.ts), so both derive the same seed from the\n// same sequence. Kept in one place after two review rounds found the\n// perception side had drifted from the renderer's exact derivation.\n// ---------------------------------------------------------------------------\n\n/** Whether the boundary from `from` to `from + 1` morphs: same scene structure, `morph` transition. */\nexport function canMorph(seq: IdleSequence, from: number): boolean {\n const seg = seq.segments[from];\n if (!seg || seg.transition?.type !== 'morph') return false;\n const next = seq.segments[from + 1];\n if (!next) return false;\n return structuralSignature(seg.scene) === structuralSignature(next.scene);\n}\n\n/**\n * Walk back through consecutive `morph` boundaries to the chain's origin. A\n * morph-chained segment's entities are never re-seeded at the boundary —\n * they're the same stream continued from wherever the chain started — so its\n * actual render seed (see `segmentRenderSeed`) is always the chain root's,\n * never its own index's.\n */\nexport function morphChainRoot(seq: IdleSequence, index: number): number {\n let i = index;\n while (i > 0 && canMorph(seq, i - 1)) i--;\n return i;\n}\n\n/**\n * Whether a looping sequence's wrap (last segment → segment 0) plays the last\n * segment's `morph`. Opt-in via `wrapMorph: true`, and only when the whole lap\n * is one morph chain — every boundary morphs and the last segment is a\n * structural twin of segment 0 — so the wrap keeps the chain root's seed and\n * entity placement and nothing pops. Otherwise the wrap is the hard cut it has\n * always been (the validator warns when `wrapMorph` asks for one it can't do).\n */\nexport function canWrapMorph(seq: IdleSequence): boolean {\n if (seq.wrapMorph !== true || seq.loop !== true) return false;\n const last = seq.segments.length - 1;\n if (last < 1) return false;\n const seg = seq.segments[last]!;\n if (seg.transition?.type !== 'morph' || seg.duration == null) return false;\n if (morphChainRoot(seq, last) !== 0) return false;\n return structuralSignature(seg.scene) === structuralSignature(seq.segments[0]!.scene);\n}\n\n/** `SpecInstance`'s seed normalization: 0 is falsy, so a valid `seed: 0` lands on 1. */\nexport function normalizeSeed(seed: number): number {\n return (seed >>> 0) || 1;\n}\n\n/**\n * The seed segment `index`'s entities actually render with — its chain\n * root's own seed, else `seq.seed + ` the chain root's index, normalized\n * exactly like `SpecInstance`. `undefined` when neither is set: the same\n * \"unknowable ahead of time\" case a bare `SaverSpec` has via `ctx.seed`,\n * which callers fall back to their own default for (as `perceiveScene` does).\n */\nexport function segmentRenderSeed(seq: IdleSequence, index: number): number | undefined {\n const root = morphChainRoot(seq, index);\n const scene = seq.segments[root]?.scene;\n if (!scene) return undefined;\n const raw = scene.seed ?? (seq.seed !== undefined ? seq.seed + root : undefined);\n return raw === undefined ? undefined : normalizeSeed(raw);\n}\n\n/**\n * The seed the bed's entities actually render with — its own seed, else\n * `seq.seed + LIMITS.maxSegments` (past every segment's `seq.seed + index`,\n * so a bed and segment 0 never share a stream), normalized like\n * `SpecInstance`. `undefined` when there's no bed or no derivable seed.\n */\nexport function bedRenderSeed(seq: IdleSequence): number | undefined {\n if (!seq.bed) return undefined;\n const raw = seq.bed.seed ?? (seq.seed !== undefined ? seq.seed + LIMITS.maxSegments : undefined);\n return raw === undefined ? undefined : normalizeSeed(raw);\n}\n\n/**\n * Whether any scene in the sequence — the sequence itself or any segment —\n * declares a `finish`. Mirrors `SequenceInstance`'s construction-time check:\n * a finish anywhere allocates the presentation pass for the instance's whole\n * lifetime, so this is also what `sequenceSwapCompatible` must agree on\n * before and after a swap.\n */\nexport function sequenceWantsFinish(seq: IdleSequence): boolean {\n return seq.finish !== undefined || seq.segments.some((s) => s.scene.finish !== undefined);\n}\n\n/**\n * Whether a republished sequence can be swapped into a live\n * `SequenceInstance` in place of `prev` without a remount\n * (`SequenceInstance.hotSwapSequence`). True only when every part of the\n * running instance that is fixed at mount — or that a running clock is\n * measured against — is unchanged:\n *\n * - the same number of segments;\n * - every segment's scene is a structural twin (`structuralSignature`) of\n * its counterpart, so the live child's entities survive a `hotSwapSpec`;\n * - the same render seed per segment (`segmentRenderSeed`) — a child's seed\n * is fixed at construction, so a changed seed could only take effect at\n * the next boundary, leaving the room half-swapped;\n * - a `bed` on both sides or neither, structural twins with the same seed\n * when present;\n * - the same top-level `seq.seed`, compared normalized (like the mount-time\n * seed itself) so a change of an exact multiple of 2^32 isn't flagged —\n * but ONLY when either side has a sequence-level `finish`: that's the one\n * place `seq.seed` reaches rendering on its own (`frameFinishSeed` uses the\n * instance's mount-time seed for a sequence-level finish's grain, which a\n * swap cannot update). Without a sequence-level `finish`, every consumer of\n * `seq.seed` is a `segmentRenderSeed`/`bedRenderSeed` fallback, and those\n * are already compared per segment and for the bed below — so when every\n * segment and the bed carry their own seed, `seq.seed` is dead weight and\n * changing it is free;\n * - the same finish presence (`sequenceWantsFinish`) — the presentation\n * pass is allocated once at construction, so a swap that adds or removes\n * every `finish` in the sequence cannot (de)allocate it;\n * - the same `loop` and `sync` (absent `sync` is `'mount'`);\n * - the same `duration`, `advance` (absent is `'auto'`) and `transition`\n * (absent is `cut`; `text` on a morph defaults to `'step'`) on every\n * segment. Durations move segment boundaries under a clock that keeps\n * running, and `clockOffset`/`releasedBelow` on the instance are measured\n * in that timeline — so a timing edit is a remount for now.\n *\n * Paint stays free: colours, words, `background`, `ghosting`, ids and\n * labels, segment keys. Layer `alpha` is a per-entity range baked at build\n * time (like `size`), so it is already covered by the structural twin check\n * above and is not free — an alpha-only edit correctly falls back to a\n * remount. Mirrors idle-server's `sequenceSignaturesEqual` precondition and\n * adds the timing terms.\n */\nexport function sequenceSwapCompatible(prev: IdleSequence, next: IdleSequence): boolean {\n if (prev.segments.length !== next.segments.length) return false;\n // seq.seed only reaches rendering directly through a sequence-level finish\n // (frameFinishSeed); otherwise segmentRenderSeed/bedRenderSeed below already\n // cover every way it can matter, so it's pinned only when one side has one.\n if (prev.finish !== undefined || next.finish !== undefined) {\n if ((prev.seed === undefined) !== (next.seed === undefined)) return false;\n if (prev.seed !== undefined && next.seed !== undefined && normalizeSeed(prev.seed) !== normalizeSeed(next.seed)) return false;\n }\n if (sequenceWantsFinish(prev) !== sequenceWantsFinish(next)) return false;\n if (prev.loop !== next.loop) return false;\n if ((prev.sync ?? 'mount') !== (next.sync ?? 'mount')) return false;\n if (!!prev.bed !== !!next.bed) return false;\n if (prev.bed && next.bed) {\n if (structuralSignature(prev.bed) !== structuralSignature(next.bed)) return false;\n if (bedRenderSeed(prev) !== bedRenderSeed(next)) return false;\n }\n for (let i = 0; i < prev.segments.length; i++) {\n const a = prev.segments[i]!;\n const b = next.segments[i]!;\n if (a.duration !== b.duration) return false;\n if ((a.advance ?? 'auto') !== (b.advance ?? 'auto')) return false;\n if (transitionKey(a.transition) !== transitionKey(b.transition)) return false;\n if (structuralSignature(a.scene) !== structuralSignature(b.scene)) return false;\n if (segmentRenderSeed(prev, i) !== segmentRenderSeed(next, i)) return false;\n }\n return true;\n}\n\n/** A transition's shape with its defaults filled in, so `undefined` and `{ type: 'cut' }` compare equal. */\nfunction transitionKey(tr: SequenceTransition | undefined): string {\n if (!tr || tr.type === 'cut') return 'cut';\n if (tr.type === 'morph') return `morph:${tr.dur}:${tr.text ?? 'step'}`;\n return `fade:${tr.dur}`;\n}\n","/**\n * `timeline` — authored keyframes on a scene's own clock.\n *\n * Everything here is a pure function of `(spec, t)`: resolving a scene at a\n * time never depends on what was rendered before, so a timeline scene is as\n * seekable and frame-addressable as any other (ghosting warm-up replays call\n * `resolveTimelineAt` at each replay frame's own time). A spec without a\n * `timeline` is returned untouched, which is what keeps every existing scene\n * byte-identical.\n *\n * Semantics:\n * - Keys address the same dot-paths as live steering; a path must already\n * exist on the spec (a key cannot create a field).\n * - A key glides from wherever its path is at `t` to `value` over `dur` ms\n * (default 1000, the live-steering default; 0 is a cut), eased `smooth`\n * unless it says otherwise. Overlapping glides are fine: the later one\n * starts from the earlier one's in-flight value.\n * - Without `loop`, a path holds the base spec's value before its first key.\n * - With `loop`, time wraps every `duration` ms and a path's value before its\n * first key is its LAST key's value — the lap is one closed cycle, and lap 1\n * looks exactly like lap 7 (the value depends only on `t mod duration`).\n */\nimport type { SaverSpec, Timeline, TimelineKey } from './types';\nimport { applyDeltasToSpec, canonicalSpecPath, easeSmooth, lerpValue, readSpecPath } from './steer';\n\n/** Default glide length for a key without `dur` — the same as a live steer's. */\nexport const DEFAULT_KEY_DUR = 1000;\n\ntype Tracks = Map<string, TimelineKey[]>;\nconst tracksCache = new WeakMap<Timeline, { spec: SaverSpec; tracks: Tracks }>();\n\n/** The spec without its `timeline` (a shallow copy — the layers are shared, never mutated). */\nexport function withoutTimeline(spec: SaverSpec): SaverSpec {\n if (!spec.timeline) return spec;\n const rest: Partial<SaverSpec> = { ...spec };\n delete rest.timeline;\n return rest as SaverSpec;\n}\n\n/**\n * The spec's keys grouped by the field they animate (index-form path), each\n * group sorted by time (stable, so equal times keep authored order and the\n * later one wins). Keys whose path does not resolve are dropped — the\n * validator rejects them, and the runtime stays lenient like steering.\n */\nexport function timelineTracks(spec: SaverSpec): Tracks {\n const tl = spec.timeline;\n if (!tl) return new Map();\n const hit = tracksCache.get(tl);\n if (hit && hit.spec === spec) return hit.tracks;\n const base = withoutTimeline(spec);\n const tracks: Tracks = new Map();\n for (const k of tl.keys ?? []) {\n const cp = canonicalSpecPath(base, k.path);\n if (!cp) continue;\n const list = tracks.get(cp) ?? [];\n list.push(k);\n tracks.set(cp, list);\n }\n for (const list of tracks.values()) list.sort((a, b) => a.t - b.t);\n tracksCache.set(tl, { spec, tracks });\n return tracks;\n}\n\n/** Scene time folded into the timeline's own clock: `t mod duration` under `loop`, else `t`. */\nexport function timelineLocalTime(tl: Timeline, t: number): number {\n const d = tl.duration ?? 0;\n if (tl.loop && d > 0) return ((t % d) + d) % d;\n return t;\n}\n\nfunction ease(k: TimelineKey, x: number): number {\n const c = x <= 0 ? 0 : x >= 1 ? 1 : x;\n if (k.ease === 'step') return c >= 1 ? 1 : 0;\n if (k.ease === 'linear') return c;\n return easeSmooth(c);\n}\n\n/** One path's value at timeline-local time `tt`, starting from `start`. */\nfunction evalTrack(keys: TimelineKey[], start: unknown, tt: number, leaf?: string): unknown {\n let from = start;\n let key: TimelineKey | null = null;\n const at = (tau: number): unknown => {\n if (!key) return from;\n const dur = key.dur ?? DEFAULT_KEY_DUR;\n if (dur <= 0 || tau >= key.t + dur) return key.value;\n return lerpValue(from, key.value, ease(key, (tau - key.t) / dur), false, leaf);\n };\n for (const k of keys) {\n if (k.t > tt) break;\n from = at(k.t);\n key = k;\n }\n return at(tt);\n}\n\n/**\n * The scene at time `t` with every key applied — and without its `timeline`,\n * so the result can be rendered, perceived, lerped or steered like any plain\n * spec. A spec without a timeline comes back as the same object.\n */\nexport function resolveTimelineAt(spec: SaverSpec, t: number): SaverSpec {\n const tl = spec.timeline;\n if (!tl) return spec;\n const base = withoutTimeline(spec);\n const tracks = timelineTracks(spec);\n if (tracks.size === 0) return base;\n const tt = timelineLocalTime(tl, t);\n const deltas: Array<{ t: number; path: string; value: unknown }> = [];\n for (const [path, keys] of tracks) {\n const start = tl.loop ? keys[keys.length - 1]!.value : readSpecPath(base, path);\n deltas.push({ t: 0, path, value: evalTrack(keys, start, tt, path.slice(path.lastIndexOf('.') + 1)) });\n }\n return applyDeltasToSpec(base, deltas);\n}\n\n/**\n * When the timeline next takes a path back: the scene time of that path's\n * next key after `t`, and that key's glide length — or null when no key will\n * ever touch it again (no key on the path, or a non-looping timeline past its\n * last key). A live steer on the path holds until `at`, then glides back to\n * the timeline over `dur`.\n */\nexport function nextKeyAfter(spec: SaverSpec, path: string, t: number): { at: number; dur: number } | null {\n const tl = spec.timeline;\n if (!tl) return null;\n const cp = canonicalSpecPath(withoutTimeline(spec), path);\n const keys = cp ? timelineTracks(spec).get(cp) : undefined;\n if (!keys || keys.length === 0) return null;\n const tt = timelineLocalTime(tl, t);\n const next = keys.find((k) => k.t > tt);\n if (next) return { at: t + (next.t - tt), dur: next.dur ?? DEFAULT_KEY_DUR };\n if (tl.loop && (tl.duration ?? 0) > 0) {\n const first = keys[0]!;\n return { at: t + (tl.duration! - tt) + first.t, dur: first.dur ?? DEFAULT_KEY_DUR };\n }\n return null;\n}\n\n/**\n * Scene times (timeline-local; within one lap under `loop`) where the keys'\n * combined state is worth checking: time 0, and every key's start, end and\n * glide quarter-points. Two keys can each be valid alone and invalid together\n * (a `clock.rate` and a `pulse.period` the flash floor bounds as a ratio), so\n * validation samples the composed scene here. `dense: false` keeps only the\n * starts and ends, for the per-steer check a live viewer runs. Capped (evenly\n * subsampled) so a 256-key timeline stays cheap to check.\n */\nexport function timelineSampleTimes(spec: SaverSpec, dense = true, cap = 120, only?: (path: string) => boolean): number[] {\n const tl = spec.timeline;\n if (!tl) return [];\n const d = tl.duration ?? 0;\n const fold = (t: number): number => (tl.loop && d > 0 ? ((t % d) + d) % d : t);\n // Every key's start and end is always checked (≤ 2 × 256): a settled state\n // must never be thinned away — the last key's end is the state a scene\n // stays in. Only the in-glide quarter-points share a budget (`cap`).\n // `only` limits the keys to those on matching (index-form) paths.\n const bounds = new Set<number>([0]);\n const extras = new Set<number>();\n const keys: TimelineKey[] = [];\n for (const [path, list] of timelineTracks(spec)) if (!only || only(path)) keys.push(...list);\n for (const k of keys) {\n if (!Number.isFinite(k.t)) continue;\n const dur = k.dur ?? DEFAULT_KEY_DUR;\n bounds.add(fold(k.t));\n bounds.add(fold(k.t + dur));\n if (dense) for (const f of [0.25, 0.5, 0.75]) extras.add(fold(k.t + dur * f));\n }\n let extra = [...extras].filter((t) => !bounds.has(t)).sort((a, b) => a - b);\n if (extra.length > cap) {\n const step = extra.length / cap;\n extra = Array.from({ length: cap }, (_, i) => extra[Math.floor(i * step)]!);\n }\n return [...new Set([...bounds, ...extra])].filter(Number.isFinite).sort((a, b) => a - b);\n}\n\n/** The absolute scene times at or after `now` where `timelineSampleTimes` fall — the next lap's occurrences under `loop`. */\nexport function timelineSampleTimesAfter(spec: SaverSpec, now: number, dense = false, only?: (path: string) => boolean): number[] {\n const tl = spec.timeline;\n if (!tl) return [];\n const local = timelineSampleTimes(spec, dense, 120, only);\n const d = tl.duration ?? 0;\n if (tl.loop && d > 0) {\n const phase = ((now % d) + d) % d;\n return local.map((s) => now + (((s - phase) % d) + d) % d).sort((a, b) => a - b);\n }\n return local.filter((s) => s > now);\n}\n","/**\n * Shape glyph geometry — pure, renderer-free, shared by the compiler (what to\n * stroke/fill), perception (how much ink that is) and advise. Everything is\n * computed from the sprite spec + the entity's seeded size, so the canvas and\n * the analytic model agree by construction.\n *\n * Unit coordinates: `polygon.points` and `stroke.points` live in a −1..1 box\n * that is scaled by the entity's half-size (circumradius for polygons, half of\n * `length` for strokes), so the seeded size range is the glyph's bounding\n * diameter — the same rule `circle.radius` / `streak.length` already follow.\n */\nimport type { PathGradient, PathPart, PathStroke, SpriteSpec } from './types';\n\nexport type ShapedSprite = Extract<SpriteSpec, { kind: 'circle' | 'ring' | 'streak' | 'rect' | 'polygon' | 'stroke' | 'bar' }>;\nexport type BarSprite = Extract<SpriteSpec, { kind: 'bar' }>;\nexport type PolygonSprite = Extract<SpriteSpec, { kind: 'polygon' }>;\nexport type StrokeSprite = Extract<SpriteSpec, { kind: 'stroke' }>;\n\n/** Every sprite that paints with `color` / `colors[]` (as opposed to glyphs). */\nexport function isShapedSprite(s: SpriteSpec): s is ShapedSprite {\n return s.kind === 'circle' || s.kind === 'ring' || s.kind === 'streak' || s.kind === 'rect' || s.kind === 'polygon' || s.kind === 'stroke' || s.kind === 'bar';\n}\n\n/** 0..1 fill of bar `index`: `values[i] / max`, `max` defaulting to the largest value. Read at paint time so steered values glide. */\nexport function barFraction(s: BarSprite, index: number): number {\n const n = s.values.length;\n if (n === 0) return 0;\n const v = s.values[((index % n) + n) % n] ?? 0;\n const max = s.max ?? s.values.reduce((m, x) => Math.max(m, x), 0);\n if (!(max > 0)) return 0;\n return Math.max(0, Math.min(1, v / max));\n}\n\n/** Box of a bar `len` long and `thick` thick growing from (0,0) toward `direction`: centre + half extents, px. */\nexport function barBox(direction: NonNullable<BarSprite['direction']>, len: number, thick: number): { cx: number; cy: number; halfX: number; halfY: number } {\n switch (direction) {\n case 'left': return { cx: -len / 2, cy: 0, halfX: len / 2, halfY: thick / 2 };\n case 'up': return { cx: 0, cy: -len / 2, halfX: thick / 2, halfY: len / 2 };\n case 'down': return { cx: 0, cy: len / 2, halfX: thick / 2, halfY: len / 2 };\n default: return { cx: len / 2, cy: 0, halfX: len / 2, halfY: thick / 2 };\n }\n}\n\nexport const DEFAULT_POLYGON_SIDES = 6;\n/** Minimum samples along a stroke path; grows with the control-point count (6 per segment). */\nexport const STROKE_SAMPLES = 24;\n\n/** Polygon vertices centred on (0,0), unrotated, circumradius `radius` px. Regular n-gons point up. */\nexport function polygonPoints(s: PolygonSprite, radius: number): Array<{ x: number; y: number }> {\n if (isPathPolygon(s)) {\n const unit = flattenSprite(s);\n if (unit.points.length >= 3) return unit.points.map(([x, y]) => ({ x: x * radius, y: y * radius }));\n }\n if (s.points && s.points.length >= 3) {\n return s.points.map(([x, y]) => ({ x: x * radius, y: y * radius }));\n }\n const n = Math.max(3, Math.round(s.sides ?? DEFAULT_POLYGON_SIDES));\n const out: Array<{ x: number; y: number }> = [];\n for (let k = 0; k < n; k++) {\n const a = -Math.PI / 2 + (2 * Math.PI * k) / n;\n out.push({ x: Math.cos(a) * radius, y: Math.sin(a) * radius });\n }\n return out;\n}\n\n/**\n * Signed-area magnitude of a polygon (shoelace), px². Exact for simple\n * polygons; a self-intersecting outline (a bow-tie) has lobes of opposite\n * winding that cancel here while the canvas's nonzero fill paints both, so\n * perception under-reports such glyphs. Author facets as simple polygons.\n */\nexport function polygonArea(pts: Array<{ x: number; y: number }>): number {\n let a = 0;\n for (let i = 0; i < pts.length; i++) {\n const p = pts[i]!;\n const q = pts[(i + 1) % pts.length]!;\n a += p.x * q.y - q.x * p.y;\n }\n return Math.abs(a) / 2;\n}\n\n/**\n * Fraction of the circumscribed disc a polygon fills — the perception weight of\n * a SMALL polygon splat. Polygons spanning more than a few grid cells are\n * rasterized by their real outline instead (`luminanceGrid`).\n */\nexport function polygonFill(s: PolygonSprite, radius: number): number {\n if (radius <= 0) return 0;\n const disc = Math.PI * radius * radius;\n return Math.min(1, polygonArea(polygonPoints(s, radius)) / disc);\n}\n\nfunction catmullRom(p0: number, p1: number, p2: number, p3: number, u: number): number {\n const u2 = u * u;\n const u3 = u2 * u;\n return 0.5 * (2 * p1 + (-p0 + p2) * u + (2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 + (-p0 + 3 * p1 - 3 * p2 + p3) * u3);\n}\n\n/**\n * The stroke's path, sampled: `n` points (default STROKE_SAMPLES) centred on\n * (0,0) and scaled so the unit box spans `halfSize` px each way. `curve:\n * 'smooth'` (default) is an open Catmull-Rom through the control points with\n * clamped ends; `'linear'` samples the polyline. Two control points give a\n * straight segment either way.\n */\nexport function strokeSamples(s: StrokeSprite, halfSize: number, n?: number): Array<{ x: number; y: number }> {\n const pts = s.points.map(([x, y]) => ({ x: x * halfSize, y: y * halfSize }));\n const m = pts.length;\n if (m < 2) return pts;\n const smooth = s.curve !== 'linear' && m >= 3;\n const segs = m - 1;\n // Enough samples that every spline segment gets interior points — a\n // 24-point stroke must not collapse to its control polyline.\n n = n ?? Math.max(STROKE_SAMPLES, segs * 6 + 1);\n const at = (k: number): { x: number; y: number } => pts[Math.max(0, Math.min(m - 1, k))]!;\n const out: Array<{ x: number; y: number }> = [];\n for (let i = 0; i < n; i++) {\n const u = (i / (n - 1)) * segs;\n const seg = Math.min(segs - 1, Math.floor(u));\n const local = u - seg;\n const p1 = at(seg);\n const p2 = at(seg + 1);\n if (!smooth) {\n out.push({ x: p1.x + (p2.x - p1.x) * local, y: p1.y + (p2.y - p1.y) * local });\n } else {\n const p0 = at(seg - 1);\n const p3 = at(seg + 2);\n out.push({ x: catmullRom(p0.x, p1.x, p2.x, p3.x, local), y: catmullRom(p0.y, p1.y, p2.y, p3.y, local) });\n }\n }\n return out;\n}\n\n/** Total length of a sampled path, px. */\nexport function pathLength(pts: Array<{ x: number; y: number }>): number {\n let l = 0;\n for (let i = 1; i < pts.length; i++) {\n const dx = pts[i]!.x - pts[i - 1]!.x;\n const dy = pts[i]!.y - pts[i - 1]!.y;\n l += Math.sqrt(dx * dx + dy * dy);\n }\n return l;\n}\n\n/**\n * Taper profile along a stroke, 0..1 of the way along: a brush mark that\n * thins to (almost) nothing at both ends. Floored so a stroke never vanishes\n * mid-mark on a coarse display.\n */\nexport function strokeTaper(u: number): number {\n return Math.max(0.15, Math.sin(Math.PI * Math.max(0, Math.min(1, u))));\n}\n\n/** Stroke width in px for a sprite, with the same default rule as `ring`/`streak`. */\nexport function strokeWidthPx(s: { width?: number }, scale: number): number {\n return Math.max(0.5, (s.width ?? (scale === 1 ? 2 : 0.002)) * scale);\n}\n\n/**\n * A feathered rect's opacity at normalised box coordinates `(u, v)` (0..1\n * across its width and height): a separable linear ramp, `featherRamp(u) ×\n * featherRamp(v)`, where `feather` of the half-size fades out on every side.\n * Smooth by construction — no nested fills, so no bands (X383) — and its\n * integral is exactly the `(1 − feather/2)²` perception weighs a feathered\n * rect's splat by.\n */\nexport function featherRamp(u: number, feather: number): number {\n const band = Math.max(0, Math.min(1, feather)) / 2; // fraction of the full width, per side\n const d = Math.min(u, 1 - u);\n if (band <= 0) return d >= 0 ? 1 : 0;\n return Math.max(0, Math.min(1, d / band));\n}\n\n/** Side of the square alpha mask a feathered rect is painted from (stretched to the rect, smoothed). */\nexport const FEATHER_MASK_SIZE = 128;\n\n/**\n * The two sides of a ribbon through `pts` with half-width `half[i]` at point\n * i: each point offset along its joint's bisector normal (mitred so a corner\n * keeps its width, the miter capped at 2×). `left` is the +normal side\n * (−ty, tx). Shared by the tapered stroke outline and the trail ribbon.\n */\nexport function ribbonSides(pts: Array<{ x: number; y: number }>, half: readonly number[]): { left: Array<{ x: number; y: number }>; right: Array<{ x: number; y: number }> } {\n const n = pts.length;\n const left: Array<{ x: number; y: number }> = [];\n const right: Array<{ x: number; y: number }> = [];\n if (n < 2) return { left, right };\n const dir = (a: { x: number; y: number }, b: { x: number; y: number }): { x: number; y: number } => {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const l = Math.hypot(dx, dy);\n return l > 1e-9 ? { x: dx / l, y: dy / l } : { x: 1, y: 0 };\n };\n for (let i = 0; i < n; i++) {\n const tIn = i > 0 ? dir(pts[i - 1]!, pts[i]!) : dir(pts[0]!, pts[1]!);\n const tOut = i < n - 1 ? dir(pts[i]!, pts[i + 1]!) : tIn;\n let tx = tIn.x + tOut.x;\n let ty = tIn.y + tOut.y;\n const tl = Math.hypot(tx, ty);\n if (tl < 1e-9) { tx = tOut.x; ty = tOut.y; } else { tx /= tl; ty /= tl; }\n const hw = half[i]! / Math.max(0.5, tx * tOut.x + ty * tOut.y);\n const p = pts[i]!;\n left.push({ x: p.x - ty * hw, y: p.y + tx * hw });\n right.push({ x: p.x + ty * hw, y: p.y - tx * hw });\n }\n return { left, right };\n}\n\n/**\n * A tapered stroke's filled outline (X386): the sampled path offset by ±half\n * its tapered width on each side, with round end caps, as one closed polygon.\n * Filling it once paints every pixel once — the per-segment strokes it\n * replaces overlapped at every joint, and a translucent mark showed each\n * overlap as a bead. Widths: `lw × strokeTaper(i / (n − 1))` at sample i,\n * floored at 0.5 px. Joints are mitred (the offset scaled by 1/cos of the\n * half-turn, capped at 2×) so a polyline corner keeps its width.\n */\nexport function strokeOutline(pts: Array<{ x: number; y: number }>, lw: number, taper = true): Array<{ x: number; y: number }> {\n const n = pts.length;\n if (n < 2) return [];\n const half = (i: number): number => Math.max(0.5, taper ? lw * strokeTaper(i / (n - 1)) : lw) / 2;\n const dir = (a: { x: number; y: number }, b: { x: number; y: number }): { x: number; y: number } => {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const l = Math.hypot(dx, dy);\n return l > 1e-9 ? { x: dx / l, y: dy / l } : { x: 1, y: 0 };\n };\n const { left, right } = ribbonSides(pts, Array.from({ length: n }, (_, i) => half(i)));\n // Round caps: half circles about each end, from one side to the other.\n const cap = (c: { x: number; y: number }, r: number, from: number): Array<{ x: number; y: number }> => {\n const out: Array<{ x: number; y: number }> = [];\n const steps = 6;\n for (let k = 1; k < steps; k++) {\n const a = from - (Math.PI * k) / steps; // clockwise in screen terms: left side → right side\n out.push({ x: c.x + Math.cos(a) * r, y: c.y + Math.sin(a) * r });\n }\n return out;\n };\n const endT = dir(pts[n - 2]!, pts[n - 1]!);\n const startT = dir(pts[0]!, pts[1]!);\n // Left is +normal (−ty, tx), at heading + 90°. The end cap sweeps from the\n // left side through the heading to the right side; the start cap from the\n // right side back round to the left.\n const endA = Math.atan2(endT.y, endT.x) + Math.PI / 2;\n const startA = Math.atan2(startT.y, startT.x) - Math.PI / 2;\n return [\n ...left,\n ...cap(pts[n - 1]!, half(n - 1), endA),\n ...right.reverse(),\n ...cap(pts[0]!, half(0), startA),\n ];\n}\n\n// ---------------------------------------------------------------------------\n// polygon.path — an SVG path `d` string in the −1..1 unit box, flattened once\n// into the polygon's outline. Every consumer (canvas, perception, advise,\n// cohesion) reads polygonPoints(), so a path sprite is a polygon everywhere.\n// ---------------------------------------------------------------------------\n\n/** Most outline points one flattened path may produce. */\nexport const MAX_PATH_POINTS = 4096;\n/**\n * Scene budget for path outlines: Σ over path layers of flattened points ×\n * entity count — the vertices the canvas fills per frame. Detail spends it\n * wherever the drawing needs it, rather than a fixed allowance per layer.\n */\nexport const MAX_SCENE_PATH_POINTS = 16384;\n/** Flattening tolerance, unit-box units: a chord never strays further than this from its curve (≈0.27 px for a full-box glyph at radius 0.5 on 1080p, ≈0.5 px on 4K). */\nconst PATH_TOLERANCE = 0.0005;\n\nexport interface FlattenedPath {\n /** One closed ring: subpaths joined by zero-width bridges, inner ones wound as holes. */\n points: Array<[number, number]>;\n subpaths: number;\n /** Every subpath as drawn (simplified, no bridges), for strokes: open unless it ended in Z. */\n lines: Array<{ points: Array<[number, number]>; closed: boolean }>;\n /** Parse error, if the string is not a usable path. */\n error?: string;\n}\n\n/**\n * How a path's subpaths combine. `auto` (default): containment decides which\n * subpaths are holes (see joinRings) — for authors who never think about\n * winding. `nonzero` / `evenodd`: SVG's own fill rules, honouring the winding\n * as drawn — for pasted SVG, and for a deliberate same-colour shape that sits\n * inside another (auto would read it as a hole).\n */\nexport type PathFillRule = 'auto' | 'nonzero' | 'evenodd';\n\n// Keyed by the d string itself (one map per rule): V8 caches a string's hash\n// on the string, so a frame that hands back the same path string looks it up\n// in O(1) — a `${rule}|${d}` key would re-hash a 60 kB string every call.\nconst pathCache = { auto: new Map<string, FlattenedPath>(), nonzero: new Map<string, FlattenedPath>(), evenodd: new Map<string, FlattenedPath>() };\n\nexport function flattenPath(d: string, rule: PathFillRule = 'auto'): FlattenedPath {\n const cache = pathCache[rule] ?? pathCache.auto;\n const hit = cache.get(d);\n if (hit) return hit;\n let out: FlattenedPath;\n try {\n const parsed = parseAndFlatten(d);\n const rings = parsed.rings.map(simplifyRing).filter((r) => r.length >= 3);\n const lines = parsed.lines.map((l) => ({ points: l.closed ? simplifyRing(l.points) : simplifyLine(l.points), closed: l.closed }));\n out = { points: rule === 'auto' ? joinRings(rings) : bridge(rings), subpaths: rings.length, lines };\n } catch (e) {\n out = { points: [], subpaths: 0, lines: [], error: e instanceof Error ? e.message : String(e) };\n }\n if (cache.size > 256) cache.clear();\n cache.set(d, out);\n return out;\n}\n\nconst spriteFlat = new WeakMap<object, { d: string; rule: PathFillRule; flat: FlattenedPath }>();\n/**\n * flattenPath for a polygon sprite, memoised on the sprite object: every\n * frame asks for the same outline, and hashing a 60,000-character path\n * string as a Map key each time cost more than drawing it.\n */\nexport function flattenSprite(s: PolygonSprite): FlattenedPath {\n // A multi-part drawing's outline is its filled parts together (bbox, area,\n // small-entity perception); parts draw and perceive individually elsewhere.\n const d = s.parts ? s.parts.filter((p) => p.fill !== false).map((p) => p.path).join(' ') : s.path ?? '';\n const rule = s.parts ? 'auto' : s.fillRule ?? 'auto';\n const hit = spriteFlat.get(s);\n if (hit && hit.d === d && hit.rule === rule) return hit.flat;\n const flat = flattenPath(d, rule);\n spriteFlat.set(s, { d, rule, flat });\n return flat;\n}\n\n/** The canvas fill rule for a polygon: evenodd only for a path that asks for it. */\nexport function polygonFillRule(s: PolygonSprite): 'nonzero' | 'evenodd' {\n return typeof s.path === 'string' && s.fillRule === 'evenodd' ? 'evenodd' : 'nonzero';\n}\n\n/** A polygon drawn from SVG paths: one `path`, or a multi-colour drawing of `parts`. */\nexport function isPathPolygon(s: SpriteSpec): boolean {\n return s.kind === 'polygon' && (typeof s.path === 'string' || Array.isArray(s.parts));\n}\n\n/** One drawable piece of a path polygon, resolved: its outline, paint and part-space box. */\nexport interface ResolvedPart {\n flat: FlattenedPath;\n /** Its own colour, or null to use the entity's (sprite colour / palette pick). */\n color: string | null;\n fill: boolean;\n rule: 'nonzero' | 'evenodd';\n gradient?: PathGradient;\n stroke?: PathStroke;\n opacity: number;\n /** The fill's bounding box in the unit box (centre + half extents) — the space of `gradient.units: 'part'`. */\n box: { cx: number; cy: number; hw: number; hh: number };\n}\n\nconst spriteParts = new WeakMap<object, { key: unknown; parts: ResolvedPart[] }>();\n\n/**\n * A path polygon as an ordered list of parts, back to front. A single\n * `path` is a drawing of one part (its colour the entity's), so the renderer,\n * perception and the budget treat both forms one way. Memoised per sprite.\n */\nexport function pathParts(s: PolygonSprite): ResolvedPart[] {\n const key = s.parts ?? s.path;\n const hit = spriteParts.get(s);\n if (hit && hit.key === key) return hit.parts;\n const src: Array<PathPart & { color?: string }> = s.parts ?? (typeof s.path === 'string'\n ? [{ path: s.path, fillRule: s.fillRule, fill: s.fill, gradient: s.gradient, stroke: s.stroke }]\n : []);\n const parts = src.map((p): ResolvedPart => {\n const flat = flattenPath(p.path, p.fillRule ?? 'auto');\n return {\n flat,\n color: s.parts ? p.color ?? null : null,\n fill: p.fill !== false,\n rule: p.fillRule === 'evenodd' ? 'evenodd' : 'nonzero',\n gradient: p.gradient,\n stroke: p.stroke,\n opacity: p.opacity ?? 1,\n box: boxOfFlat(flat),\n };\n });\n spriteParts.set(s, { key, parts });\n return parts;\n}\n\n/**\n * How a path drawing's −1..1 unit box lands on screen, in px: scale per axis\n * (sx, sy) and the unit-box point (ox, oy) that sits at the entity position.\n * span 'box' (default): uniform, the entity radius r on both axes — the\n * classic square box sized by the short side;\n * 'width': x spans the full screen width (sx = w/2), y keeps r — skylines,\n * hills and ground bands that must reach both side edges on any aspect;\n * 'height': y spans the full height, x keeps r;\n * 'screen': both — a frame or wash that hugs every edge.\n * `origin` [ox, oy] picks the anchored point: [0, 1] with position y = 1 sets\n * the drawing's bottom on the screen's bottom edge. Strokes keep the uniform\n * r for their width, so stretching never fattens an outline sideways.\n */\nexport function pathFrame(s: PolygonSprite, r: number, w: number, h: number): { sx: number; sy: number; ox: number; oy: number; uniform: boolean } {\n const span = s.span ?? 'box';\n const sx = span === 'width' || span === 'screen' ? w / 2 : r;\n const sy = span === 'height' || span === 'screen' ? h / 2 : r;\n const [ox, oy] = s.origin ?? [0, 0];\n return { sx, sy, ox, oy, uniform: sx === sy };\n}\n\nconst flatBoxes = new WeakMap<FlattenedPath, ResolvedPart['box']>();\n/** A flattened path's bounding box (centre + half extents), memoised on the (cached) flattening. */\nfunction boxOfFlat(flat: FlattenedPath): ResolvedPart['box'] {\n const hit = flatBoxes.get(flat);\n if (hit) return hit;\n let x0 = Infinity, x1 = -Infinity, y0 = Infinity, y1 = -Infinity;\n for (const [x, y] of flat.points.length ? flat.points : flat.lines.flatMap((l) => l.points)) {\n x0 = Math.min(x0, x); x1 = Math.max(x1, x); y0 = Math.min(y0, y); y1 = Math.max(y1, y);\n }\n if (!Number.isFinite(x0)) { x0 = -1; x1 = 1; y0 = -1; y1 = 1; }\n const box = { cx: (x0 + x1) / 2, cy: (y0 + y1) / 2, hw: Math.max((x1 - x0) / 2, 1e-6), hh: Math.max((y1 - y0) / 2, 1e-6) };\n flatBoxes.set(flat, box);\n return box;\n}\n\nconst pathIds = new Map<string, number>();\nlet pathSeq = 0;\nconst paintSigs = new WeakMap<object, string>();\n/**\n * A content signature for a path polygon's appearance: every field, with each\n * d string replaced by an interned id. Two sprite objects that draw the same\n * thing share it — a glide or a timeline hands the renderer a new object every\n * frame, so the caches key on this, never on object identity. Memoised per\n * object: specs are treated as immutable (steers and glides always build new\n * objects), so a sprite must never be edited in place after it is drawn.\n */\nexport function pathPaintSig(s: PolygonSprite): string {\n const hit = paintSigs.get(s);\n if (hit !== undefined) return hit;\n const sig = JSON.stringify(s, (k, v) => {\n if (k !== 'path' || typeof v !== 'string') return v;\n let id = pathIds.get(v);\n if (id === undefined) {\n if (pathIds.size > 4096) pathIds.clear(); // ids keep counting up, so a cleared table never reuses one\n id = ++pathSeq;\n pathIds.set(v, id);\n }\n return `#${id}`;\n });\n paintSigs.set(s, sig);\n return sig;\n}\n\n/** A unit-box point in a gradient's own space: the drawing box, or (units 'part') the part's box mapped to −1..1. */\nexport function gradientSpace(part: ResolvedPart, u: number, v: number): [number, number] {\n if (part.gradient?.units !== 'part') return [u, v];\n return [(u - part.box.cx) / part.box.hw, (v - part.box.cy) / part.box.hh];\n}\n\ntype Pt = [number, number];\n\nfunction segmentsFor(chord: number, curvature: number): number {\n // Error of a chord on a curve with control-polygon deviation `curvature` ~ curvature / (4 n²).\n const n = Math.ceil(Math.sqrt(Math.max(curvature, chord * 0.05) / (4 * PATH_TOLERANCE)));\n return Math.max(2, Math.min(64, n));\n}\n\nfunction parseAndFlatten(d: string): { rings: Pt[][]; lines: Array<{ points: Pt[]; closed: boolean }> } {\n const tokens = d.match(/[a-zA-Z]|[-+]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][-+]?\\d+)?/g) ?? [];\n let i = 0;\n const num = (): number => {\n const t = tokens[i++];\n if (t === undefined || /^[a-zA-Z]$/.test(t)) throw new Error('expected a number');\n return Number(t);\n };\n const flag = (): number => {\n // Arc flags may be written without separators (\"a1 1 0 011 1\"); the tokenizer keeps \"011\" whole.\n const t = tokens[i];\n if (t !== undefined && /^[01]{2,}/.test(t)) {\n tokens[i] = t.slice(1);\n return Number(t[0]);\n }\n return num();\n };\n const rings: Pt[][] = [];\n let ring: Pt[] = [];\n let cx = 0, cy = 0, sx = 0, sy = 0;\n let lastCtrl: Pt | null = null; // reflected by S/T\n let lastCmd = '';\n const push = (x: number, y: number): void => { ring.push([x, y]); cx = x; cy = y; };\n const lines: Array<{ points: Pt[]; closed: boolean }> = [];\n const close = (closed = false): void => {\n if (ring.length >= 2) lines.push({ points: ring.slice(), closed });\n if (ring.length >= 3) rings.push(ring);\n ring = [];\n };\n const cubic = (x1: number, y1: number, x2: number, y2: number, x: number, y: number): void => {\n const dev = Math.hypot(x1 - cx, y1 - cy) + Math.hypot(x2 - x1, y2 - y1) + Math.hypot(x - x2, y - y2) - Math.hypot(x - cx, y - cy);\n const n = segmentsFor(Math.hypot(x - cx, y - cy), dev * 4);\n const x0 = cx, y0 = cy;\n for (let k = 1; k <= n; k++) {\n const t = k / n, u = 1 - t;\n push(u * u * u * x0 + 3 * u * u * t * x1 + 3 * u * t * t * x2 + t * t * t * x,\n u * u * u * y0 + 3 * u * u * t * y1 + 3 * u * t * t * y2 + t * t * t * y);\n }\n lastCtrl = [x2, y2];\n };\n const quad = (x1: number, y1: number, x: number, y: number): void => {\n const dev = Math.hypot(x1 - cx, y1 - cy) + Math.hypot(x - x1, y - y1) - Math.hypot(x - cx, y - cy);\n const n = segmentsFor(Math.hypot(x - cx, y - cy), dev * 4);\n const x0 = cx, y0 = cy;\n for (let k = 1; k <= n; k++) {\n const t = k / n, u = 1 - t;\n push(u * u * x0 + 2 * u * t * x1 + t * t * x, u * u * y0 + 2 * u * t * y1 + t * t * y);\n }\n lastCtrl = [x1, y1];\n };\n const arc = (rx: number, ry: number, phiDeg: number, large: number, sweep: number, x: number, y: number): void => {\n // SVG endpoint → centre parameterisation (SVG 1.1 F.6.5).\n const x0 = cx, y0 = cy;\n if (rx === 0 || ry === 0 || (x0 === x && y0 === y)) { push(x, y); return; }\n rx = Math.abs(rx); ry = Math.abs(ry);\n const phi = (phiDeg * Math.PI) / 180, cp = Math.cos(phi), sp = Math.sin(phi);\n const dx = (x0 - x) / 2, dy = (y0 - y) / 2;\n const x1p = cp * dx + sp * dy, y1p = -sp * dx + cp * dy;\n const lam = (x1p * x1p) / (rx * rx) + (y1p * y1p) / (ry * ry);\n if (lam > 1) { rx *= Math.sqrt(lam); ry *= Math.sqrt(lam); }\n const num2 = rx * rx * ry * ry - rx * rx * y1p * y1p - ry * ry * x1p * x1p;\n const den = rx * rx * y1p * y1p + ry * ry * x1p * x1p;\n let co = Math.sqrt(Math.max(0, num2 / den));\n if (large === sweep) co = -co;\n const cxp = (co * rx * y1p) / ry, cyp = (-co * ry * x1p) / rx;\n const ccx = cp * cxp - sp * cyp + (x0 + x) / 2, ccy = sp * cxp + cp * cyp + (y0 + y) / 2;\n const ang = (ux: number, uy: number, vx: number, vy: number): number => Math.atan2(ux * vy - uy * vx, ux * vx + uy * vy);\n const t1 = ang(1, 0, (x1p - cxp) / rx, (y1p - cyp) / ry);\n let dt = ang((x1p - cxp) / rx, (y1p - cyp) / ry, (-x1p - cxp) / rx, (-y1p - cyp) / ry);\n if (!sweep && dt > 0) dt -= 2 * Math.PI;\n if (sweep && dt < 0) dt += 2 * Math.PI;\n const r = Math.max(rx, ry);\n const n = Math.max(2, Math.min(96, Math.ceil(Math.abs(dt) / (2 * Math.acos(Math.max(0, 1 - PATH_TOLERANCE / r))))));\n for (let k = 1; k <= n; k++) {\n const t = t1 + (dt * k) / n;\n const ex = rx * Math.cos(t), ey = ry * Math.sin(t);\n push(cp * ex - sp * ey + ccx, sp * ex + cp * ey + ccy);\n }\n };\n while (i < tokens.length) {\n let cmd = tokens[i]!;\n if (/^[a-zA-Z]$/.test(cmd)) i++;\n else if (lastCmd) cmd = lastCmd === 'M' ? 'L' : lastCmd === 'm' ? 'l' : lastCmd; // implicit repeat\n else throw new Error('path must start with M');\n const rel = cmd === cmd.toLowerCase() && cmd !== 'z' ? true : false;\n const ox = rel ? cx : 0, oy = rel ? cy : 0;\n const C = cmd.toUpperCase();\n const prevCmd = lastCmd.toUpperCase();\n if (C !== 'S' && C !== 'T') lastCtrl = null;\n switch (C) {\n case 'M': {\n close();\n const x = num() + ox, y = num() + oy;\n push(x, y); sx = x; sy = y;\n break;\n }\n case 'L': push(num() + ox, num() + oy); break;\n case 'H': push(num() + ox, cy); break;\n case 'V': push(cx, num() + oy); break;\n case 'C': { const a = num() + ox, b = num() + oy, c = num() + ox, e = num() + oy; cubic(a, b, c, e, num() + ox, num() + oy); break; }\n case 'S': {\n const r: Pt = lastCtrl && (prevCmd === 'C' || prevCmd === 'S') ? [2 * cx - lastCtrl[0], 2 * cy - lastCtrl[1]] : [cx, cy];\n const c = num() + ox, e = num() + oy;\n cubic(r[0], r[1], c, e, num() + ox, num() + oy);\n break;\n }\n case 'Q': { const a = num() + ox, b = num() + oy; quad(a, b, num() + ox, num() + oy); break; }\n case 'T': {\n const r: Pt = lastCtrl && (prevCmd === 'Q' || prevCmd === 'T') ? [2 * cx - lastCtrl[0], 2 * cy - lastCtrl[1]] : [cx, cy];\n quad(r[0], r[1], num() + ox, num() + oy);\n break;\n }\n case 'A': { const rx = num(), ry = num(), ph = num(), la = flag(), sw = flag(); arc(rx, ry, ph, la, sw, num() + ox, num() + oy); break; }\n case 'Z': cx = sx; cy = sy; close(true); break;\n default: throw new Error(`unsupported path command '${cmd}'`);\n }\n lastCmd = cmd;\n }\n close();\n for (const r of rings) {\n // Drop a closing point that repeats the start.\n const a = r[0]!, b = r[r.length - 1]!;\n if (Math.hypot(a[0] - b[0], a[1] - b[1]) < 1e-9) r.pop();\n }\n for (const l of lines) {\n const a = l.points[0]!, b = l.points[l.points.length - 1]!;\n if (l.closed && l.points.length > 2 && Math.hypot(a[0] - b[0], a[1] - b[1]) < 1e-9) l.points.pop();\n }\n return { rings, lines };\n}\n\n/** Douglas–Peucker on an open polyline at the flattening tolerance. */\nfunction simplifyLine(r: Pt[]): Pt[] {\n if (r.length <= 2) return r;\n const keep = new Uint8Array(r.length);\n keep[0] = 1; keep[r.length - 1] = 1;\n const stack: Array<[number, number]> = [[0, r.length - 1]];\n while (stack.length) {\n const [a, b] = stack.pop()!;\n const A = r[a]!, B = r[b]!;\n const dx = B[0] - A[0], dy = B[1] - A[1], len = Math.hypot(dx, dy);\n let best = -1, bd = 0;\n for (let k = a + 1; k < b; k++) {\n const P = r[k]!;\n const d = len > 1e-12 ? Math.abs(dx * (A[1] - P[1]) - dy * (A[0] - P[0])) / len : Math.hypot(P[0] - A[0], P[1] - A[1]);\n if (d > bd) { bd = d; best = k; }\n }\n if (best >= 0 && bd > PATH_TOLERANCE) { keep[best] = 1; stack.push([a, best], [best, b]); }\n }\n return r.filter((_, k) => keep[k] === 1);\n}\n\n/**\n * Douglas–Peucker on a closed ring at the flattening tolerance: drops points\n * that sit on (or within PATH_TOLERANCE of) the line through their neighbours,\n * so a hand-sampled polyline costs only the points that change its outline.\n */\nfunction simplifyRing(r: Pt[]): Pt[] {\n if (r.length <= 4) return r;\n // Split the ring at vertex 0 and the vertex farthest from it; simplify both halves.\n let far = 0, fd = -1;\n for (let k = 1; k < r.length; k++) {\n const d = (r[k]![0] - r[0]![0]) ** 2 + (r[k]![1] - r[0]![1]) ** 2;\n if (d > fd) { fd = d; far = k; }\n }\n const keep = new Uint8Array(r.length);\n keep[0] = 1; keep[far] = 1;\n const at = (k: number): Pt => r[k % r.length]!;\n const stack: Array<[number, number]> = [[0, far], [far, r.length]];\n while (stack.length) {\n const [a, b] = stack.pop()!;\n const A = at(a), B = at(b);\n const dx = B[0] - A[0], dy = B[1] - A[1], len = Math.hypot(dx, dy);\n let best = -1, bd = 0;\n for (let k = a + 1; k < b; k++) {\n const P = at(k);\n const d = len > 1e-12 ? Math.abs(dx * (A[1] - P[1]) - dy * (A[0] - P[0])) / len : Math.hypot(P[0] - A[0], P[1] - A[1]);\n if (d > bd) { bd = d; best = k; }\n }\n if (best >= 0 && bd > PATH_TOLERANCE) {\n keep[best % r.length] = 1;\n stack.push([a, best], [best, b]);\n }\n }\n return r.filter((_, k) => keep[k] === 1);\n}\n\nfunction signedArea(r: Pt[]): number {\n let a = 0;\n for (let k = 0; k < r.length; k++) {\n const p = r[k]!, q = r[(k + 1) % r.length]!;\n a += p[0] * q[1] - q[0] * p[1];\n }\n return a / 2;\n}\n\nfunction inside(pt: Pt, r: Pt[]): boolean {\n let c = false;\n for (let k = 0, j = r.length - 1; k < r.length; j = k++) {\n const a = r[k]!, b = r[j]!;\n if ((a[1] > pt[1]) !== (b[1] > pt[1]) && pt[0] < ((b[0] - a[0]) * (pt[1] - a[1])) / (b[1] - a[1]) + a[0]) c = !c;\n }\n return c;\n}\n\n/** Every vertex of `sub` inside `r` (bbox first): `sub` is nested in `r`, not merely overlapping it. */\nfunction containsRing(r: Pt[], rb: Box, sub: Pt[], sb: Box): boolean {\n if (sb.x0 < rb.x0 || sb.x1 > rb.x1 || sb.y0 < rb.y0 || sb.y1 > rb.y1) return false;\n for (const p of sub) if (!inside(p, r)) return false;\n return true;\n}\n\ninterface Box { x0: number; x1: number; y0: number; y1: number }\nfunction boxOf(r: Pt[]): Box {\n const b = { x0: Infinity, x1: -Infinity, y0: Infinity, y1: -Infinity };\n for (const [x, y] of r) { b.x0 = Math.min(b.x0, x); b.x1 = Math.max(b.x1, x); b.y0 = Math.min(b.y0, y); b.y1 = Math.max(b.y1, y); }\n return b;\n}\n\n/**\n * Subpaths → one ring the nonzero fill paints as the author meant, whatever\n * direction each was drawn in or which came first. Containment decides\n * (every vertex inside, not just one):\n * - a subpath inside nothing is solid;\n * - inside a filled region (its smallest container is filled), a hole;\n * - inside a hole, solid again (an island: a pupil in an eye-spot ring);\n * - one that only partly overlaps another stays solid and merges with it\n * (a vein crossing a vein, a leaflet over its stem), never cutting it.\n * Each subpath gets a winding multiplicity m so the net winding just inside\n * it is exactly 1 (filled) or 0 (empty), counting every container — so a\n * window through two overlapping walls is wound −2 and still opens. A ring\n * with |m| > 1 is traced |m| times; m = 0 drops it. Pieces join the ring so\n * far by zero-width bridges at the closest vertex pair: the \"retrace the\n * hole\" trick FORMAT.md teaches by hand, done by the compiler.\n */\nfunction joinRings(rings: Pt[][]): Pt[] {\n if (rings.length === 0) return [];\n const boxes = rings.map(boxOf);\n const areas = rings.map((r) => Math.abs(signedArea(r)));\n // Largest first, so every container is decided before what it contains.\n const order = rings.map((_, i) => i).sort((p, q) => areas[q]! - areas[p]!);\n const mult = new Array<number>(rings.length).fill(0);\n const net = new Array<number>(rings.length).fill(0);\n const done: number[] = [];\n for (const n of order) {\n const containers = done.filter((m) => areas[m]! > areas[n]! && containsRing(rings[m]!, boxes[m]!, rings[n]!, boxes[n]!));\n const around = containers.reduce((sum, m) => sum + mult[m]!, 0);\n let want = 1;\n if (containers.length) {\n const parent = containers.reduce((p, m) => (areas[m]! < areas[p]! ? m : p));\n want = net[parent] !== 0 ? 0 : 1;\n }\n net[n] = want;\n mult[n] = want - around;\n done.push(n);\n }\n const traced: Pt[][] = [];\n const trace = (r: Pt[], m: number): void => {\n const o = Math.sign(signedArea(r)) === Math.sign(m) ? r : r.slice().reverse();\n for (let k = 0; k < Math.abs(m); k++) traced.push(o);\n };\n for (let n = 0; n < rings.length; n++) {\n if (mult[n] !== 0) trace(rings[n]!, mult[n]!);\n }\n // In auto a hole is a stencil cut-out through the whole layer. A solid that\n // only partly crosses a hole (a window across the seam where a tower's top\n // overlaps its base; a spoke across a ring's opening) is cancelled where it\n // covers the hole: add (solid ∩ hole) wound against it. Exact for a convex\n // hole (windows, ovals, circles); a concave hole cuts only what contains it.\n // For each solid, the holes it partly crosses; only the OUTERMOST of those\n // cut it — a hole inside another hole is already in the cut region, and\n // cutting twice would wind the solid back to −1 (visible again).\n const holes = rings.map((_, n) => n).filter((n) => net[n] === 0 && mult[n] !== 0 && isConvex(rings[n]!));\n for (let m = 0; m < rings.length; m++) {\n if (mult[m]! <= 0) continue;\n const bm = boxes[m]!;\n const crossing = holes.filter((n) => {\n const bn = boxes[n]!;\n if (n === m || bm.x1 <= bn.x0 || bm.x0 >= bn.x1 || bm.y1 <= bn.y0 || bm.y0 >= bn.y1) return false;\n return !containsRing(rings[m]!, bm, rings[n]!, bn) && !containsRing(rings[n]!, bn, rings[m]!, bm);\n });\n for (const n of crossing) {\n if (crossing.some((o) => o !== n && areas[o]! > areas[n]! && containsRing(rings[o]!, boxes[o]!, rings[n]!, boxes[n]!))) continue;\n const piece = clipToConvex(rings[m]!, rings[n]!);\n if (piece.length >= 3 && Math.abs(signedArea(piece)) > 1e-9) trace(piece, -mult[m]!);\n }\n }\n return bridge(traced);\n}\n\nfunction isConvex(r: Pt[]): boolean {\n let sign = 0;\n for (let k = 0; k < r.length; k++) {\n const a = r[k]!, b = r[(k + 1) % r.length]!, c = r[(k + 2) % r.length]!;\n const z = (b[0] - a[0]) * (c[1] - b[1]) - (b[1] - a[1]) * (c[0] - b[0]);\n if (Math.abs(z) < 1e-12) continue;\n if (sign === 0) sign = Math.sign(z);\n else if (Math.sign(z) !== sign) return false;\n }\n return true;\n}\n\n/** Sutherland–Hodgman: `subject` clipped to the convex polygon `clip`. */\nfunction clipToConvex(subject: Pt[], clip: Pt[]): Pt[] {\n const o = Math.sign(signedArea(clip)) || 1;\n let out = subject;\n for (let k = 0; k < clip.length && out.length; k++) {\n const a = clip[k]!, b = clip[(k + 1) % clip.length]!;\n const side = (p: Pt): number => o * ((b[0] - a[0]) * (p[1] - a[1]) - (b[1] - a[1]) * (p[0] - a[0]));\n const cut = (p: Pt, q: Pt): Pt => { const sp = side(p), sq = side(q), t = sp / (sp - sq); return [p[0] + (q[0] - p[0]) * t, p[1] + (q[1] - p[1]) * t]; };\n const next: Pt[] = [];\n for (let i = 0; i < out.length; i++) {\n const p = out[i]!, q = out[(i + 1) % out.length]!;\n const pin = side(p) >= 0, qin = side(q) >= 0;\n if (pin) next.push(p);\n if (pin !== qin) next.push(cut(p, q));\n }\n out = next;\n }\n return out;\n}\n\n/** Join rings into one by zero-width bridges at the closest vertex pairs; windings kept as given. */\nfunction bridge(rings: Pt[][]): Pt[] {\n if (rings.length === 0) return [];\n let ring = rings[0]!.slice();\n for (let n = 1; n < rings.length; n++) {\n const sub = rings[n]!;\n let bi = 0, bj = 0, best = Infinity;\n for (let a = 0; a < ring.length; a++) {\n for (let b = 0; b < sub.length; b++) {\n const dd = (ring[a]![0] - sub[b]![0]) ** 2 + (ring[a]![1] - sub[b]![1]) ** 2;\n if (dd < best) { best = dd; bi = a; bj = b; }\n }\n }\n const rot = sub.slice(bj).concat(sub.slice(0, bj));\n ring = ring.slice(0, bi + 1).concat(rot, [rot[0]!, ring[bi]!], ring.slice(bi + 1));\n }\n return ring;\n}\n\n/** Points a path polygon draws per frame: every part's fill ring (when filled) plus its stroked lines. */\nexport function pathPointCount(s: PolygonSprite): number {\n let n = 0;\n for (const p of pathParts(s)) {\n if (p.fill) n += p.flat.points.length;\n if (p.stroke) for (const l of p.flat.lines) n += l.points.length;\n }\n return n;\n}\n\n/**\n * Per-frame drawing cost of a path polygon in \"flat fill point\" units: a\n * gradient fill costs about twice a flat one, a stroked point about three\n * times. The render-once cache decides by cost, so a lightly-pointed but\n * shaded and inked drawing still earns its bitmap.\n */\nexport function pathDrawCost(s: PolygonSprite): number {\n let c = 0;\n for (const p of pathParts(s)) {\n if (p.fill) c += p.flat.points.length * (p.gradient ? 2 : 1);\n if (p.stroke) for (const l of p.flat.lines) c += l.points.length * 3;\n }\n return c;\n}\n\n/**\n * A part's stroke as thin quads (one per segment, `width` unit-box units\n * wide), scaled by `radius` px and centred on (0,0): what perception\n * rasterises for a stroke. Joints overlap a little; perception clamps.\n */\nexport function partStrokeQuads(part: ResolvedPart, radius: number): Array<Array<{ x: number; y: number }>> {\n if (!part.stroke) return [];\n const hw = (part.stroke.width * radius) / 2;\n const out: Array<Array<{ x: number; y: number }>> = [];\n for (const l of part.flat.lines) {\n const pts = l.points;\n const n = l.closed ? pts.length : pts.length - 1;\n for (let i = 0; i < n; i++) {\n const a = pts[i]!, b = pts[(i + 1) % pts.length]!;\n const ax = a[0] * radius, ay = a[1] * radius, bx = b[0] * radius, by = b[1] * radius;\n const dx = bx - ax, dy = by - ay, len = Math.hypot(dx, dy) || 1;\n const nx = (-dy / len) * hw, ny = (dx / len) * hw;\n out.push([{ x: ax + nx, y: ay + ny }, { x: bx + nx, y: by + ny }, { x: bx - nx, y: by - ny }, { x: ax - nx, y: ay - ny }]);\n }\n }\n return out;\n}\n\n/** Every part's stroke quads together (see partStrokeQuads). */\nexport function pathStrokeQuads(s: PolygonSprite, radius: number): Array<Array<{ x: number; y: number }>> {\n return pathParts(s).flatMap((p) => partStrokeQuads(p, radius));\n}\n","import { LIMITS, SCHEMA_VERSION, type IdleSequence, type SaverSpec, type SpecError, type SpecWarning, type ValidationResult } from './types';\nimport { applyDeltasToSpec, canonicalSpecPath, morphNothingMorphable, readSpecPath, structuralSignature } from './steer';\nimport { canWrapMorph, morphChainRoot } from './sequence';\nimport { DEFAULT_KEY_DUR, resolveTimelineAt, timelineSampleTimes, timelineTracks, withoutTimeline } from './timeline';\nimport { MAX_PATH_POINTS, MAX_SCENE_PATH_POINTS, flattenPath, type PathFillRule } from './shapes';\n\nconst HEX = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;\nconst isObj = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null && !Array.isArray(v);\nconst isStr = (v: unknown): v is string => typeof v === 'string';\nconst isNum = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v);\nconst isRange = (v: unknown): v is [number, number] =>\n Array.isArray(v) && v.length === 2 && isNum(v[0]) && isNum(v[1]) && v[0] <= v[1];\n\n// Known properties at each level — used to detect unknown/misplaced fields\nconst KNOWN_TOP = new Set(['schemaVersion', 'id', 'label', 'seed', 'motionIntensity', 'density', 'units', 'referenceViewport', 'background', 'layers', 'ghosting', 'finish', 'timeline', 'groups']);\nconst KNOWN_FINISH = new Set(['grain', 'dither', 'animate']);\nconst KNOWN_LAYER = new Set([\n 'count', 'sprite', 'motion', 'size', 'wrap', 'flip', 'alpha', 'blend',\n 'region', 'pulse', 'spin', 'grow', 'key', 'position', 'trail', 'links',\n 'layout', 'life', 'emit', 'clock', 'rotate', 'opacity', 'transform', 'group',\n]);\nconst KNOWN_TRANSFORM = new Set(['x', 'y', 'scale', 'scaleX', 'rotate', 'origin']);\nconst KNOWN_GROUP = new Set(['transform', 'opacity']);\nconst GROUP_NAME = /^[A-Za-z][A-Za-z0-9_-]{0,31}$/;\nconst KNOWN_POSITION = new Set(['x', 'y', 'dx', 'dy']);\nconst KNOWN_TIMELINE = new Set(['loop', 'duration', 'keys']);\nconst KNOWN_TIMELINE_KEY = new Set(['t', 'path', 'value', 'ease', 'dur']);\nconst KNOWN_CIRCLE = new Set(['kind', 'radius', 'color', 'soft', 'colors', 'colorWeights']);\nconst KNOWN_RING = new Set(['kind', 'radius', 'color', 'width', 'colors', 'colorWeights']);\nconst KNOWN_STREAK = new Set(['kind', 'length', 'color', 'width', 'colors', 'colorWeights']);\nconst KNOWN_RECT = new Set(['kind', 'width', 'aspect', 'color', 'feather', 'colors', 'colorWeights']);\nconst KNOWN_BAR = new Set(['kind', 'values', 'length', 'thickness', 'color', 'max', 'direction', 'colors', 'colorWeights']);\nconst KNOWN_PATH_PART = new Set(['path', 'color', 'fillRule', 'fill', 'gradient', 'stroke', 'opacity']);\nconst KNOWN_POLYGON = new Set(['kind', 'radius', 'color', 'sides', 'points', 'path', 'fillRule', 'fill', 'gradient', 'stroke', 'parts', 'span', 'origin', 'soft', 'colors', 'colorWeights']);\nconst KNOWN_STROKE = new Set(['kind', 'length', 'points', 'color', 'width', 'curve', 'taper', 'orient', 'colors', 'colorWeights']);\nconst KNOWN_EMOJI = new Set(['kind', 'glyphs', 'cycle']);\nconst KNOWN_TEXT = new Set(['kind', 'strings', 'color', 'font', 'align', 'baseline', 'maxWidth', 'cycle', 'role']);\nconst KNOWN_TEXT_BLOCK = new Set(['kind', 'text', 'maxWidth', 'fontSize', 'lineHeight', 'align', 'color', 'reveal', 'anchor', 'font', 'opacity', 'role']);\nconst TEXT_ROLES = new Set(['read', 'atmosphere']);\nconst TEXT_BLOCK_ANCHORS = new Set(['top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right']);\n/**\n * A CSS length inside a textBlock `font` — size belongs to `fontSize`. No\n * trailing boundary check: a `\\b`-based (or lookahead-based) version misses\n * \"50% monospace\" (`%` isn't a word character, so there is no boundary after\n * it when the next char is whitespace) and \"14pxmonospace\" (glued straight\n * onto the family name, so the word boundary between two word characters\n * passes it through). The leading `\\d` immediately before the unit is enough\n * to identify an embedded size regardless of what follows it.\n */\nconst FONT_SIZE_RE = /\\d(?:px|pt|pc|em|rem|ex|ch|vw|vh|vmin|vmax|%)/i;\nconst KNOWN_REVEAL = new Set(['progress', 'mode', 'speed', 'caret', 'fade']);\nconst KNOWN_REVEAL_CARET = new Set(['blink', 'color']);\nconst KNOWN_DRIFT = new Set(['type', 'speed', 'angle', 'bidirectional', 'bob', 'ease']);\nconst KNOWN_RISE = new Set(['type', 'speed', 'sway', 'ease']);\nconst KNOWN_BOUNCE = new Set(['type', 'speed']);\nconst KNOWN_STATIC = new Set(['type']);\nconst KNOWN_ORBIT = new Set(['type', 'speed', 'radius', 'center']);\nconst KNOWN_WANDER = new Set(['type', 'speed', 'angle', 'meander', 'coherence', 'ease']);\nconst KNOWN_WARP = new Set(['type', 'speed', 'center']);\nconst KNOWN_PATH = new Set(['type', 'points', 'duration', 'curve', 'closed', 'scatter']);\nconst KNOWN_BG_SOLID = new Set(['type', 'color']);\nconst KNOWN_BG_GRADIENT = new Set(['type', 'stops', 'band', 'drift']);\nconst KNOWN_BG_FIELD = new Set(['type', 'scale', 'octaves', 'warp', 'quantize', 'bands', 'drift', 'seed']);\nconst KNOWN_FIELD_DRIFT = new Set(['period', 'amount']);\n\n// Layer-level properties that models commonly misplace inside sprite\nconst LAYER_PROPS_ON_SPRITE = new Set(['blend', 'trail', 'alpha', 'pulse', 'spin', 'grow', 'region', 'links', 'flip', 'wrap', 'key', 'emit', 'clock', 'life', 'layout', 'rotate']);\n\nfunction unknownKeys(obj: Record<string, unknown>, known: Set<string>): string[] {\n return Object.keys(obj).filter((k) => !known.has(k));\n}\n\n/**\n * The unit a spec's dimensional values are written in, for error messages.\n * Mirrors the compiler: anything but an explicit `units: 'px'` is viewport\n * units (fractions of min(width, height)), so a message must not say \"px\"\n * to an author who never opted into px.\n */\nfunction dimUnit(spec: unknown): string {\n return isObj(spec) && spec.units === 'px' ? 'px' : 'fractions of min(width, height)';\n}\n\n/**\n * Bound and unit for a layer offset (`transform.x`/`y`, `position.dx`/`dy`):\n * ±2 in min(w, h) units, or px under `units: 'px'` — where the renderer reads\n * the same numbers as pixels.\n */\nfunction offsetBound(spec: unknown): [number, string] {\n return isObj(spec) && spec.units === 'px'\n ? [LIMITS.maxLayerTransformOffsetPx, 'px']\n : [LIMITS.maxLayerTransformOffset, 'min(w, h) units'];\n}\n\n/** \"must be a [min,max] range of positive <unit>\" — unit-aware (see dimUnit). */\nfunction rangeMsg(spec: unknown, note?: string): string {\n return `must be a [min,max] range of positive ${dimUnit(spec)}${note ? ` (${note})` : ''}`;\n}\n\n/**\n * A scalar-only positive number (ring/streak/stroke `width`, bar `length`,\n * links `maxDist`, …). A [min,max] range here is the common slip — most size\n * fields ARE ranges — and reporting \"must be > 0\" for `[0.003, 0.006]`\n * (whose values are all > 0) sends the author hunting for the wrong bug.\n */\nfunction positiveScalar(v: unknown, path: string, err: (p: string, m: string) => void, msg = 'must be > 0'): void {\n if (Array.isArray(v)) err(path, 'must be a single number > 0, not a [min,max] range');\n else if (!isNum(v) || v <= 0) err(path, msg);\n}\n\n/**\n * Validate an untrusted (agent- or JSON-authored) spec structurally + semantically.\n * Returns typed errors and warnings; never throws. `compileSaver` refuses to run an invalid spec.\n *\n * Warnings are non-blocking advisories about unknown/misplaced properties and\n * near-zero speeds. They don't prevent compilation but indicate likely authoring mistakes.\n */\n/**\n * Normalize: if a sprite has `colors[]` but no `color`, default `color` to\n * `colors[0]`. Author intent is unambiguous (pick from the palette), and\n * requiring both is a known footgun (F3). Mutates the spec in place — the\n * added field is always correct.\n */\nfunction normalizeColors(spec: unknown): void {\n if (!isObj(spec) || !Array.isArray(spec.layers)) return;\n for (const layer of spec.layers) {\n if (!isObj(layer)) continue;\n const sprite = (layer as Record<string, unknown>).sprite;\n if (!isObj(sprite)) continue;\n const sp = sprite as Record<string, unknown>;\n if (Array.isArray(sp.colors) && sp.colors.length > 0 && sp.color === undefined) {\n sp.color = sp.colors[0];\n }\n }\n}\n\nexport function validateSpec(spec: unknown): ValidationResult {\n normalizeColors(spec);\n return validateSpecCore(spec);\n}\n\n/**\n * Dot-paths (numeric layer indices, as `steerablePaths` spells them) of every\n * property the validator flags as unknown or misplaced — i.e. fields the\n * renderer never reads, so steering them does nothing. Pure: unlike\n * `validateSpec` it never normalises colours into the caller's spec.\n */\nexport function ignoredPropertyPaths(spec: unknown): string[] {\n if (!isObj(spec)) return [];\n return (validateSpecCore(spec).warnings ?? [])\n .filter((w) => w.code === 'unknown-property' || w.code === 'misplaced-property')\n .map((w) => w.path.replace(/\\[(\\d+)\\]/g, '.$1'));\n}\n\n/**\n * Validity of only the parts of a spec that `paths` (index-form dot-paths,\n * as `canonicalSpecPath` spells them) live in: each touched layer, the\n * background, the finish — plus the cross-layer entity cap. A layer's rules\n * (the `clock`/`pulse`/`grow` flash floors, `emit`, orbit parents) are all\n * judged inside that layer, so a change confined to layer N can only break\n * layer N or the total. Any other top-level path falls back to the full\n * `validateSpec`. For the timeline's composed-state checks, which run at every\n * key boundary and on every live steer: the whole-spec check costs a\n * full validation per sample, this one a layer or two.\n */\nexport function validateSpecPaths(spec: SaverSpec, paths: Iterable<string>): boolean {\n const layers = new Set<number>();\n let background = false;\n let finish = false;\n let groups = false;\n for (const p of paths) {\n // A layer's `key`, `count` or `motion` is what another layer's orbit\n // parent refers to — a change there can break a layer it doesn't live in.\n if (/^layers\\.\\d+(\\.(key|count|motion)(\\.|$)|$)/.test(p)) return validateSpec(spec).valid;\n // Replacing `groups` whole can drop a name a member still references.\n if (p === 'groups') return validateSpec(spec).valid;\n const [head, idx] = p.split('.');\n if (head === 'layers' && idx !== undefined && /^\\d+$/.test(idx)) layers.add(Number(idx));\n else if (head === 'background') background = true;\n else if (head === 'finish') finish = true;\n else if (head === 'groups') groups = true;\n else return validateSpec(spec).valid;\n }\n let ok = true;\n const err = (): void => { ok = false; };\n const warn: WarnFn = () => undefined;\n if (!Array.isArray(spec.layers)) return false;\n for (const i of layers) {\n const layer = spec.layers[i];\n if (layer === undefined) return false;\n validateLayer(layer, `layers[${i}]`, err, warn, spec);\n // The one spec-level rule a layer change can break: textBlock sizes are\n // viewport fractions, so `units: 'px'` rejects a textBlock layer (see\n // validateSpecCore).\n if (spec.units === 'px' && isObj(layer) && isObj(layer.sprite) && layer.sprite.kind === 'textBlock') ok = false;\n }\n if (background && spec.background !== undefined) validateBackground(spec.background, err, warn);\n if (finish && spec.finish !== undefined) validateFinish(spec.finish, 'finish', err, warn);\n // A group's paint cannot break a member layer's rules — only the group itself.\n if (groups && spec.groups !== undefined) validateGroups(spec.groups, err, warn, spec);\n if (layers.size > 0) {\n const total = spec.layers.reduce((n, l) => n + (isObj(l) && isNum(l.count) ? l.count : 0), 0);\n if (total > LIMITS.maxTotal) ok = false;\n }\n return ok;\n}\n\nfunction validateSpecCore(spec: unknown): ValidationResult {\n const errors: SpecError[] = [];\n const warnings: SpecWarning[] = [];\n const err = (path: string, message: string): void => void errors.push({ path, message });\n const warn = (path: string, code: string, message: string): void => void warnings.push({ path, code, message });\n\n if (!isObj(spec)) return { valid: false, errors: [{ path: '', message: 'spec must be an object' }], warnings: [] };\n\n if (spec.schemaVersion !== SCHEMA_VERSION) err('schemaVersion', `must be ${SCHEMA_VERSION}`);\n if (!isStr(spec.id) || spec.id.trim() === '') err('id', 'must be a non-empty string');\n if (!isStr(spec.label) || spec.label.trim() === '') err('label', 'must be a non-empty string');\n if (spec.seed !== undefined && !isNum(spec.seed)) err('seed', 'must be a number');\n if (spec.motionIntensity !== undefined && !['calm', 'moderate', 'energetic'].includes(spec.motionIntensity as string)) {\n err('motionIntensity', 'must be calm | moderate | energetic');\n }\n if (spec.density !== undefined && !['sparse', 'normal', 'dense'].includes(spec.density as string)) {\n err('density', 'must be sparse | normal | dense');\n }\n if (spec.units !== undefined && spec.units !== 'px' && spec.units !== 'viewport') {\n err('units', \"must be 'px' | 'viewport'\");\n }\n if (spec.units === 'px' && Array.isArray(spec.layers)) {\n for (const l of spec.layers) {\n if (isObj(l) && isObj((l as Record<string, unknown>).sprite) && ((l as Record<string, unknown>).sprite as Record<string, unknown>).kind === 'textBlock') {\n err('units', \"textBlock dimensions are viewport fractions — units: 'px' is not supported with textBlock sprites\");\n break;\n }\n }\n }\n if (spec.referenceViewport !== undefined) {\n if (!isNum(spec.referenceViewport) || spec.referenceViewport < 100 || spec.referenceViewport > 8640) {\n err('referenceViewport', 'must be a number between 100 and 8640');\n }\n }\n if (spec.ghosting !== undefined && (!isNum(spec.ghosting) || spec.ghosting < 0 || spec.ghosting > LIMITS.maxGhosting)) {\n err('ghosting', `must be a number 0..${LIMITS.maxGhosting}`);\n }\n\n for (const k of unknownKeys(spec, KNOWN_TOP)) {\n warn(k, 'unknown-property', `unknown top-level property '${k}' — will be ignored`);\n }\n\n if (spec.background !== undefined) validateBackground(spec.background, err, warn);\n if (spec.finish !== undefined) validateFinish(spec.finish, 'finish', err, warn);\n if (spec.groups !== undefined) validateGroups(spec.groups, err, warn, spec);\n\n if (!Array.isArray(spec.layers) || spec.layers.length === 0) {\n err('layers', 'must be a non-empty array');\n } else {\n if (spec.layers.length > LIMITS.maxLayers) err('layers', `at most ${LIMITS.maxLayers} layers`);\n {\n let pathPoints = 0;\n for (const l of spec.layers as Array<Record<string, unknown>>) {\n const sp = isObj(l) ? (l.sprite as Record<string, unknown> | undefined) : undefined;\n if (!sp || sp.kind !== 'polygon') continue;\n const pieces = Array.isArray(sp.parts) ? (sp.parts as unknown[]) : typeof sp.path === 'string' ? [sp] : [];\n const n = typeof l.count === 'number' && l.count > 0 ? l.count : 1;\n for (const pc of pieces) {\n if (!isObj(pc) || typeof pc.path !== 'string') continue;\n const fl = flattenPath(pc.path, (pc.fillRule as PathFillRule | undefined) ?? 'auto');\n pathPoints += ((pc.fill === false ? 0 : fl.points.length) + (isObj(pc.stroke) ? fl.lines.reduce((m, x) => m + x.points.length, 0) : 0)) * n;\n }\n }\n if (pathPoints > MAX_SCENE_PATH_POINTS) {\n err('layers', `path outlines total ${pathPoints} points (flattened points × count); the scene budget is ${MAX_SCENE_PATH_POINTS}`);\n }\n }\n let total = 0;\n spec.layers.forEach((layer, i) => {\n total += isObj(layer) && isNum(layer.count) ? layer.count : 0;\n validateLayer(layer, `layers[${i}]`, err, warn, spec);\n });\n if (total > LIMITS.maxTotal) err('layers', `total entities ${total} exceeds cap ${LIMITS.maxTotal}`);\n }\n\n // Keys are checked against the base spec, so only once the base is valid.\n if (spec.timeline !== undefined && errors.length === 0) validateTimeline(spec as unknown as SaverSpec, err, warn);\n\n return { valid: errors.length === 0, errors, warnings };\n}\n\n/** A paint `transform` (a layer's, or a group's — `anchorOk: false` forbids `origin: 'anchor'`). */\nfunction validateTransform(tf: unknown, path: string, err: (p: string, m: string) => void, warn: WarnFn, spec: unknown, anchorOk: boolean): void {\n if (!isObj(tf)) return err(path, 'must be an object {x?, y?, scale?, scaleX?, rotate?, origin?}');\n for (const k of unknownKeys(tf, KNOWN_TRANSFORM)) warn(`${path}.${k}`, 'unknown-property', `unknown transform property '${k}' — will be ignored`);\n const [off, unit] = offsetBound(spec);\n const sc = LIMITS.maxLayerTransformScale;\n for (const axis of ['x', 'y'] as const) {\n if (tf[axis] !== undefined && (!isNum(tf[axis]) || Math.abs(tf[axis] as number) > off)) err(`${path}.${axis}`, `must be a number within ±${off} (${unit})`);\n }\n if (tf.scale !== undefined && (!isNum(tf.scale) || tf.scale < 0 || tf.scale > sc)) err(`${path}.scale`, `must be a number 0..${sc}`);\n if (tf.scaleX !== undefined && (!isNum(tf.scaleX) || Math.abs(tf.scaleX) > sc)) err(`${path}.scaleX`, `must be a number within ±${sc} (negative mirrors)`);\n if (tf.rotate !== undefined && (!isNum(tf.rotate) || Math.abs(tf.rotate) > LIMITS.maxLayerTransformRotate)) {\n err(`${path}.rotate`, `must be a number of degrees within ±${LIMITS.maxLayerTransformRotate}`);\n }\n if (tf.origin !== undefined) {\n if (tf.origin !== 'viewport' && tf.origin !== 'anchor') err(`${path}.origin`, \"must be 'viewport' | 'anchor'\");\n else if (tf.origin === 'anchor' && !anchorOk) err(`${path}.origin`, \"a group transform always turns about the viewport centre — 'anchor' is for a layer's own transform\");\n }\n}\n\n/** `groups`: named paint sets — see `LayerGroup`. */\nfunction validateGroups(groups: unknown, err: (p: string, m: string) => void, warn: WarnFn, spec: unknown): void {\n if (!isObj(groups)) return err('groups', 'must be an object of named groups {name: {transform?, opacity?}}');\n const names = Object.keys(groups);\n if (names.length > LIMITS.maxGroups) err('groups', `at most ${LIMITS.maxGroups} groups`);\n for (const name of names) {\n const p = `groups.${name}`;\n if (!GROUP_NAME.test(name)) err(p, 'group names are 1–32 letters, digits, - or _, starting with a letter');\n const g = groups[name];\n if (!isObj(g)) { err(p, 'must be an object {transform?, opacity?}'); continue; }\n for (const k of unknownKeys(g, KNOWN_GROUP)) warn(`${p}.${k}`, 'unknown-property', `unknown group property '${k}' — will be ignored`);\n if (g.opacity !== undefined && (!isNum(g.opacity) || g.opacity < 0 || g.opacity > 1)) err(`${p}.opacity`, 'must be a number 0..1');\n if (g.transform !== undefined) validateTransform(g.transform, `${p}.transform`, err, warn, spec, false);\n }\n}\n\n/**\n * `timeline`: each key's path must already exist on the spec (as for\n * `setParam`) and the spec must still validate with the key's value applied.\n * Distinct key times on one path sit at least `minTimelineKeyInterval` apart\n * (across the wrap too, under `loop`) — the flash-safety floor that replaces a\n * sequence's 1 s segment minimum for change inside a scene.\n */\nfunction validateTimeline(spec: SaverSpec, errOuter: (p: string, m: string) => void, warn: WarnFn): void {\n let failed = false;\n const err = (p: string, m: string): void => { failed = true; errOuter(p, m); };\n const tl = spec.timeline as unknown;\n if (!isObj(tl)) return err('timeline', 'must be an object {loop?, duration?, keys}');\n for (const k of unknownKeys(tl, KNOWN_TIMELINE)) warn(`timeline.${k}`, 'unknown-property', `unknown timeline property '${k}' — will be ignored`);\n if (tl.loop !== undefined && typeof tl.loop !== 'boolean') err('timeline.loop', 'must be a boolean');\n if (tl.duration !== undefined && (!isNum(tl.duration) || tl.duration <= 0 || tl.duration > LIMITS.maxTimelineDuration)) {\n err('timeline.duration', `must be a number of ms, 0 < duration <= ${LIMITS.maxTimelineDuration}`);\n }\n if (tl.loop === true && tl.duration === undefined) err('timeline.duration', 'loop: true needs a duration (the lap length in ms)');\n if (!Array.isArray(tl.keys) || tl.keys.length === 0) return err('timeline.keys', 'must be a non-empty array');\n if (tl.keys.length > LIMITS.maxTimelineKeys) return err('timeline.keys', `at most ${LIMITS.maxTimelineKeys} keys`);\n\n const base = withoutTimeline(spec);\n const baseSig = structuralSignature(base);\n const times = new Map<string, number[]>();\n let latest = 0;\n tl.keys.forEach((key, i) => {\n const p = `timeline.keys[${i}]`;\n if (!isObj(key)) return err(p, 'must be an object {t, path, value, ease?, dur?}');\n for (const k of unknownKeys(key, KNOWN_TIMELINE_KEY)) warn(`${p}.${k}`, 'unknown-property', `unknown key property '${k}' — will be ignored`);\n let ok = true;\n if (!isNum(key.t) || key.t < 0) { err(`${p}.t`, 'must be a number of ms >= 0'); ok = false; }\n if (key.ease !== undefined && key.ease !== 'step' && key.ease !== 'linear' && key.ease !== 'smooth') err(`${p}.ease`, \"must be 'step' | 'linear' | 'smooth'\");\n if (key.dur !== undefined && (!isNum(key.dur) || key.dur < 0 || key.dur > LIMITS.maxTimelineKeyDur)) {\n err(`${p}.dur`, `must be a number of ms, 0..${LIMITS.maxTimelineKeyDur}`);\n }\n if (!('value' in key)) { err(`${p}.value`, 'is required'); ok = false; }\n const cp = isStr(key.path) ? canonicalSpecPath(base, key.path) : null;\n if (!isStr(key.path) || key.path.trim() === '') { err(`${p}.path`, 'must be a non-empty dot-path'); ok = false; }\n else if (/\\.group$/.test(key.path) || /\\.transform\\.origin$/.test(key.path)) {\n err(`${p}.path`, `'${key.path}' is an enum that can only step — group membership and a transform's origin are fixed per scene`);\n ok = false;\n }\n else if (!cp) { err(`${p}.path`, `'${key.path}' does not resolve on the spec — a key can only animate a field the spec already has`); ok = false; }\n else if (cp === 'timeline' || cp.startsWith('timeline.') || cp === 'schemaVersion' || cp === 'id' || cp === 'label' || cp === 'seed') {\n err(`${p}.path`, `'${key.path}' is not animatable`);\n ok = false;\n }\n if (!ok || !cp) return;\n const t = key.t as number;\n latest = Math.max(latest, t);\n const applied = applyDeltasToSpec(base, [{ t: 0, path: cp, value: key.value }]);\n // The base is valid, so only the part the key changes can break; the full\n // validation runs just to name the failure.\n const r = validateSpecPaths(applied, [cp]) ? { valid: true, errors: [] as SpecError[] } : validateSpec(applied);\n if (!r.valid) {\n for (const e of r.errors) err(`${p}.value`, `applied at '${key.path}' → ${e.path || '<root>'}: ${e.message}`);\n return;\n }\n // `origin` is an enum: a whole-`transform` key that changes it switches\n // the pivot on the key's first frame — a jump, not a glide.\n if (isObj(key.value) && cp.endsWith('transform')) {\n const before = readSpecPath(base, cp);\n const o0 = isObj(before) ? before.origin ?? 'viewport' : 'viewport';\n const o1 = (key.value as Record<string, unknown>).origin ?? 'viewport';\n if (o0 !== o1) warn(`${p}.value`, 'timeline-origin-steps', `this key changes the transform's origin (${String(o0)} → ${String(o1)}): the pivot switches on the key's first frame, so the layer jumps — keep one origin per layer`);\n }\n if (structuralSignature(applied) !== baseSig) {\n warn(`${p}.path`, 'timeline-structural-key', `'${key.path}' is structural (placement, count, motion, size…): the scene rebuilds at this key and entities re-seed — a pop, not a glide. Animate paint (colour, opacity, transform, polygon points) instead`);\n }\n const list = times.get(cp) ?? [];\n list.push(t);\n times.set(cp, list);\n const dur = isNum(key.dur) ? key.dur : DEFAULT_KEY_DUR;\n if (tl.loop === true && isNum(tl.duration) && t + dur > tl.duration) {\n warn(`${p}.dur`, 'timeline-glide-overruns-lap', `this key's glide ends at ${t + dur} ms, after the ${tl.duration} ms lap — the wrap cuts it short`);\n }\n });\n if (tl.loop === true && isNum(tl.duration) && latest >= tl.duration) {\n err('timeline.duration', `must be greater than the latest key's t (${latest} ms) under loop`);\n }\n const minGap = LIMITS.minTimelineKeyInterval;\n for (const [path, list] of times) {\n const distinct = [...new Set(list)].sort((a, b) => a - b);\n for (let i = 1; i < distinct.length; i++) {\n if (distinct[i]! - distinct[i - 1]! < minGap) {\n err('timeline.keys', `keys on '${path}' at ${distinct[i - 1]} and ${distinct[i]} ms are closer than ${minGap} ms (flash safety)`);\n }\n }\n if (tl.loop === true && isNum(tl.duration) && distinct.length > 1) {\n const wrapGap = tl.duration - distinct[distinct.length - 1]! + distinct[0]!;\n if (wrapGap < minGap) err('timeline.keys', `keys on '${path}' at ${distinct[distinct.length - 1]} ms and ${distinct[0]} ms (next lap) are closer than ${minGap} ms across the loop wrap (flash safety)`);\n }\n }\n // Each key was checked applied alone; keys that are each valid can still\n // combine into an invalid scene (a `clock.rate` and a `pulse.period` share\n // one flash-safety floor). Check the composed scene where it can change:\n // every key's start, end and glide quarter-points.\n if (failed) return;\n // Every key boundary, plus up to 120 in-glide points: this runs at every\n // mount, so the glide sampling is budgeted — the settled states are not.\n const keyed = [...timelineTracks(spec).keys()];\n const seen = new Set<string>();\n for (const t of timelineSampleTimes(spec, true, 120)) {\n const r = resolveTimelineAt(spec, t);\n // Only the keyed values change between samples: skip a state already judged.\n const state = JSON.stringify(keyed.map((p) => readSpecPath(r, p)));\n if (seen.has(state)) continue;\n seen.add(state);\n if (validateSpecPaths(r, keyed)) continue;\n const e = validateSpec(r).errors[0];\n err('timeline', `at t = ${Math.round(t)} ms the keys combine into an invalid scene — ${e ? `${e.path || '<root>'}: ${e.message}` : 'invalid'}`);\n return;\n }\n}\n\nfunction color(v: unknown, path: string, err: (p: string, m: string) => void): void {\n if (!isStr(v) || !HEX.test(v)) err(path, 'must be a hex colour like #0a3a52');\n}\n\ntype WarnFn = (path: string, code: string, message: string) => void;\n\n/**\n * A `finish` block (spec- or sequence-level). `grain` / `dither` are bounded\n * to 0..1: at 1 they composite at their fixed maximum alphas (35 % / 25 %),\n * which is as strong as a zero-mean screen can be before it reads as the\n * subject; both stay mean-luminance-neutral at every value, so nothing here\n * is a flash bound — the finish cannot flash at any setting.\n */\nfunction validateFinish(f: unknown, path: string, err: (p: string, m: string) => void, warn: WarnFn): void {\n if (!isObj(f)) return err(path, 'must be an object');\n for (const k of ['grain', 'dither'] as const) {\n if (f[k] !== undefined && (!isNum(f[k]) || (f[k] as number) < 0 || (f[k] as number) > 1)) err(`${path}.${k}`, 'must be a number 0..1');\n }\n if (f.animate !== undefined && typeof f.animate !== 'boolean') err(`${path}.animate`, 'must be a boolean');\n for (const k of unknownKeys(f, KNOWN_FINISH)) {\n warn(`${path}.${k}`, 'unknown-property', `unknown finish property '${k}' — will be ignored`);\n }\n}\n\nfunction validateBackground(bg: unknown, err: (p: string, m: string) => void, warn: WarnFn): void {\n if (!isObj(bg)) return err('background', 'must be an object');\n if (bg.type === 'solid') {\n color(bg.color, 'background.color', err);\n for (const k of unknownKeys(bg, KNOWN_BG_SOLID)) {\n warn(`background.${k}`, 'unknown-property', `unknown background property '${k}' — will be ignored`);\n }\n } else if (bg.type === 'gradient') {\n if (!Array.isArray(bg.stops) || bg.stops.length < 2) {\n err('background.stops', 'gradient needs at least 2 stops');\n } else {\n bg.stops.forEach((s, i) => {\n if (!isObj(s) || !isNum(s.at) || s.at < 0 || s.at > 1) err(`background.stops[${i}].at`, 'must be 0..1');\n color(isObj(s) ? s.color : undefined, `background.stops[${i}].color`, err);\n });\n }\n if (bg.drift !== undefined) {\n if (!isObj(bg.drift)) err('background.drift', 'must be an object');\n else {\n if (!isNum(bg.drift.period) || bg.drift.period < LIMITS.minDriftPeriod) {\n err('background.drift.period', `must be >= ${LIMITS.minDriftPeriod} ms`);\n }\n if (bg.drift.amount !== undefined && (!isNum(bg.drift.amount) || bg.drift.amount <= 0 || bg.drift.amount > LIMITS.maxDriftAmount)) {\n err('background.drift.amount', `must be > 0 and <= ${LIMITS.maxDriftAmount}`);\n }\n }\n }\n if (bg.band !== undefined) {\n if (!isObj(bg.band)) err('background.band', 'must be an object');\n else {\n color(bg.band.color, 'background.band.color', err);\n positiveScalar(bg.band.height, 'background.band.height', err);\n }\n }\n for (const k of unknownKeys(bg, KNOWN_BG_GRADIENT)) {\n warn(`background.${k}`, 'unknown-property', `unknown background property '${k}' — will be ignored`);\n }\n } else if (bg.type === 'field') {\n validateFieldBackground(bg, err, warn);\n } else {\n err('background.type', 'must be solid | gradient | field');\n }\n}\n\n/**\n * A `field` background. Every bound here is a rendering or safety limit:\n * `scale` is capped so a raster cell never spans more than a feature (the\n * upscaled raster would alias), `octaves` so a 96×54 raster stays cheap to\n * recompute ten times a second, and `drift.period` is floored at\n * LIMITS.minDriftPeriod — the same 10 s guard the gradient's drift carries —\n * because the drift is the ONLY way a field changes over time: with the\n * domain travelling a bounded circle once per period, no point of the field\n * can change faster than that, so a field can never strobe.\n */\nfunction validateFieldBackground(bg: Record<string, unknown>, err: (p: string, m: string) => void, warn: WarnFn): void {\n if (!isNum(bg.scale) || bg.scale < LIMITS.minFieldScale || bg.scale > LIMITS.maxFieldScale) {\n err('background.scale', `must be a number ${LIMITS.minFieldScale}..${LIMITS.maxFieldScale} (features across the short side)`);\n }\n if (bg.octaves !== undefined && (!isNum(bg.octaves) || !Number.isInteger(bg.octaves) || bg.octaves < 1 || bg.octaves > LIMITS.maxFieldOctaves)) {\n err('background.octaves', `must be an integer 1..${LIMITS.maxFieldOctaves}`);\n }\n if (bg.warp !== undefined && (!isNum(bg.warp) || bg.warp < 0 || bg.warp > 1)) {\n err('background.warp', 'must be a number 0..1');\n }\n if (bg.quantize !== undefined && (!isNum(bg.quantize) || !Number.isInteger(bg.quantize) || bg.quantize < 0 || bg.quantize === 1 || bg.quantize > LIMITS.maxFieldQuantize)) {\n err('background.quantize', `must be 0 (smooth) or an integer 2..${LIMITS.maxFieldQuantize}`);\n }\n if (!Array.isArray(bg.bands) || bg.bands.length < LIMITS.minFieldBands || bg.bands.length > LIMITS.maxFieldBands) {\n err('background.bands', `must be ${LIMITS.minFieldBands}..${LIMITS.maxFieldBands} hex colours`);\n } else {\n // Indexed, not forEach: forEach skips holes in a sparse array, which\n // would let a hole through validation and crash the renderer later on\n // an undefined colour.\n for (let i = 0; i < bg.bands.length; i++) color(bg.bands[i], `background.bands[${i}]`, err);\n }\n if (bg.drift !== undefined) {\n if (!isObj(bg.drift)) err('background.drift', 'must be an object');\n else {\n if (!isNum(bg.drift.period) || bg.drift.period < LIMITS.minDriftPeriod) {\n err('background.drift.period', `must be >= ${LIMITS.minDriftPeriod} ms`);\n }\n if (bg.drift.amount !== undefined && (!isNum(bg.drift.amount) || bg.drift.amount < 0 || bg.drift.amount > LIMITS.maxFieldDriftAmount)) {\n err('background.drift.amount', `must be a number 0..${LIMITS.maxFieldDriftAmount}`);\n }\n for (const k of unknownKeys(bg.drift, KNOWN_FIELD_DRIFT)) {\n warn(`background.drift.${k}`, 'unknown-property', `unknown drift property '${k}' — will be ignored`);\n }\n }\n }\n if (bg.seed !== undefined && !isNum(bg.seed)) err('background.seed', 'must be a number');\n for (const k of unknownKeys(bg, KNOWN_BG_FIELD)) {\n warn(`background.${k}`, 'unknown-property', `unknown background property '${k}' — will be ignored`);\n }\n}\n\nfunction validateLayer(layer: unknown, path: string, err: (p: string, m: string) => void, warn: WarnFn, spec?: unknown): void {\n if (!isObj(layer)) return err(path, 'must be an object');\n\n for (const k of unknownKeys(layer, KNOWN_LAYER)) {\n if (k === 'id') {\n warn(`${path}.id`, 'misplaced-property', `'id' is not a layer property — did you mean 'key'? Use 'key' to name a layer`);\n } else if (k === 'depth') {\n warn(`${path}.depth`, 'unknown-property', `'depth' is not a layer property — use motion type 'warp' for true perspective depth, or fake parallax with size/speed/alpha across layers`);\n } else {\n warn(`${path}.${k}`, 'unknown-property', `unknown layer property '${k}' — will be ignored`);\n }\n }\n if (!isNum(layer.count) || !Number.isInteger(layer.count) || layer.count < 1) {\n err(`${path}.count`, 'must be a positive integer');\n } else if (layer.count > LIMITS.maxPerLayer) {\n err(`${path}.count`, `at most ${LIMITS.maxPerLayer} per layer`);\n }\n if (layer.size !== undefined && (!isRange(layer.size) || layer.size[0] <= 0)) {\n err(`${path}.size`, rangeMsg(spec));\n }\n if (layer.wrap !== undefined && typeof layer.wrap !== 'boolean') err(`${path}.wrap`, 'must be a boolean');\n if (layer.flip !== undefined && typeof layer.flip !== 'boolean') err(`${path}.flip`, 'must be a boolean');\n\n if (layer.alpha !== undefined && (!isRange(layer.alpha) || layer.alpha[0] < 0 || layer.alpha[1] > 1)) {\n err(`${path}.alpha`, 'must be a [min,max] range within 0..1');\n }\n if (layer.blend !== undefined && !['lighter', 'screen', 'multiply'].includes(layer.blend as string)) {\n err(`${path}.blend`, \"must be 'lighter' | 'screen' | 'multiply' when set\");\n }\n if (layer.key !== undefined && (!isStr(layer.key) || layer.key.trim() === '')) {\n err(`${path}.key`, 'must be a non-empty string');\n }\n if (layer.opacity !== undefined && (!isNum(layer.opacity) || layer.opacity < 0 || layer.opacity > 1)) {\n err(`${path}.opacity`, 'must be a number 0..1');\n }\n if (layer.transform !== undefined) validateTransform(layer.transform, `${path}.transform`, err, warn, spec, true);\n if (layer.group !== undefined) {\n const groups = isObj(spec) && isObj(spec.groups) ? spec.groups : undefined;\n if (!isStr(layer.group)) err(`${path}.group`, 'must be the name of a `groups` entry');\n else if (!groups || !Object.prototype.hasOwnProperty.call(groups, layer.group) || !isObj(groups[layer.group])) err(`${path}.group`, `'${layer.group}' is not in \\`groups\\` — declare it there first`);\n }\n if (layer.position !== undefined) {\n if (!isObj(layer.position) || !isNum(layer.position.x) || !isNum(layer.position.y)) {\n err(`${path}.position`, 'must be {x, y} with numbers 0..1');\n } else {\n if (layer.position.x < 0 || layer.position.x > 1) err(`${path}.position.x`, 'must be 0..1');\n if (layer.position.y < 0 || layer.position.y > 1) err(`${path}.position.y`, 'must be 0..1');\n const [off, unit] = offsetBound(spec);\n for (const axis of ['dx', 'dy'] as const) {\n const v = layer.position[axis];\n if (v !== undefined && (!isNum(v) || Math.abs(v) > off)) {\n err(`${path}.position.${axis}`, `must be a number within ±${off} (${unit})`);\n }\n }\n for (const k of unknownKeys(layer.position, KNOWN_POSITION)) warn(`${path}.position.${k}`, 'unknown-property', `unknown position property '${k}' — will be ignored`);\n const dataLayout = isObj(layer.layout) && (layer.layout.type === 'list' || layer.layout.type === 'table');\n if (isNum(layer.count) && layer.count !== 1 && !dataLayout) {\n err(`${path}.position`, \"position requires count: 1 — or a layout of type 'list' / 'table', where it anchors the whole block\");\n }\n }\n }\n if (layer.region !== undefined) {\n if (!isObj(layer.region)) err(`${path}.region`, 'must be an object');\n else {\n for (const axis of ['x', 'y'] as const) {\n const r = layer.region[axis];\n if (r !== undefined && (!isRange(r) || r[0] < 0 || r[1] > 1)) {\n err(`${path}.region.${axis}`, 'must be a [min,max] range within 0..1');\n }\n }\n }\n }\n if (layer.pulse !== undefined) {\n if (!isObj(layer.pulse)) err(`${path}.pulse`, 'must be an object');\n else {\n if (!isNum(layer.pulse.amp) || layer.pulse.amp <= 0 || layer.pulse.amp > LIMITS.maxPulseAmp) {\n err(`${path}.pulse.amp`, `must be within 0..${LIMITS.maxPulseAmp}`);\n }\n if (!isNum(layer.pulse.period) || layer.pulse.period < LIMITS.minPulsePeriod) {\n err(`${path}.pulse.period`, `must be >= ${LIMITS.minPulsePeriod} ms (flash-safety floor)`);\n }\n if (layer.pulse.wave !== undefined) {\n if (!isObj(layer.pulse.wave)) err(`${path}.pulse.wave`, 'must be an object');\n else {\n if (!isNum(layer.pulse.wave.wavelength) || layer.pulse.wave.wavelength <= 0) {\n err(`${path}.pulse.wave.wavelength`, 'must be > 0 (px or viewport-units)');\n }\n if (layer.pulse.wave.angle !== undefined && !isNum(layer.pulse.wave.angle)) {\n err(`${path}.pulse.wave.angle`, 'must be a number (degrees)');\n }\n }\n }\n }\n }\n if (layer.spin !== undefined) {\n if (isRange(layer.spin)) {\n if (Math.abs(layer.spin[0]) > LIMITS.maxSpin || Math.abs(layer.spin[1]) > LIMITS.maxSpin) {\n err(`${path}.spin`, `each end of the range must be within ±${LIMITS.maxSpin} deg/sec`);\n }\n } else if (!isNum(layer.spin)) {\n err(`${path}.spin`, 'must be a number or a [min,max] range (degrees/sec)');\n } else if (Math.abs(layer.spin) > LIMITS.maxSpin) {\n err(`${path}.spin`, `must be within ±${LIMITS.maxSpin} deg/sec`);\n }\n }\n if (layer.rotate !== undefined) {\n if (isRange(layer.rotate)) {\n if (Math.abs(layer.rotate[0]) > LIMITS.maxRotate || Math.abs(layer.rotate[1]) > LIMITS.maxRotate) {\n err(`${path}.rotate`, `each end of the range must be within ±${LIMITS.maxRotate} degrees`);\n }\n } else if (!isNum(layer.rotate)) {\n err(`${path}.rotate`, 'must be a number or a [min,max] range (degrees)');\n } else if (Math.abs(layer.rotate) > LIMITS.maxRotate) {\n err(`${path}.rotate`, `must be within ±${LIMITS.maxRotate} degrees`);\n }\n }\n if (layer.grow !== undefined) {\n if (!isObj(layer.grow)) err(`${path}.grow`, 'must be an object');\n else {\n if (!isNum(layer.grow.amp) || layer.grow.amp <= 0 || layer.grow.amp > LIMITS.maxGrowAmp) {\n err(`${path}.grow.amp`, `must be within 0..${LIMITS.maxGrowAmp}`);\n }\n if (!isNum(layer.grow.period) || layer.grow.period < LIMITS.minPulsePeriod) {\n err(`${path}.grow.period`, `must be >= ${LIMITS.minPulsePeriod} ms (flash-safety floor)`);\n }\n }\n }\n\n if (layer.links !== undefined) {\n if (!isObj(layer.links)) err(`${path}.links`, 'must be an object');\n else {\n // A chain wires entities in order, so it reads neither `k` nor `maxDist`\n // — except `maxDist` as the fade distance under `falloff: true`. Both\n // are still checked when present (X541).\n const chain = layer.links.mode === 'chain';\n if (!chain || layer.links.k !== undefined) {\n if (!isNum(layer.links.k) || !Number.isInteger(layer.links.k) || layer.links.k < 1 || layer.links.k > LIMITS.maxLinksK) {\n err(`${path}.links.k`, `must be an integer 1..${LIMITS.maxLinksK}`);\n }\n }\n if (!chain || layer.links.maxDist !== undefined || layer.links.falloff === true) {\n positiveScalar(\n layer.links.maxDist,\n `${path}.links.maxDist`,\n err,\n chain && layer.links.maxDist === undefined ? 'is required (> 0) when a chain sets falloff: true — it is the fade distance' : undefined,\n );\n }\n if (layer.links.color !== undefined) color(layer.links.color, `${path}.links.color`, err);\n if (layer.links.alpha !== undefined && (!isNum(layer.links.alpha) || layer.links.alpha < 0 || layer.links.alpha > 1)) {\n err(`${path}.links.alpha`, 'must be 0..1');\n }\n if (layer.links.width !== undefined) positiveScalar(layer.links.width, `${path}.links.width`, err);\n if (layer.links.mode !== undefined && !['nearest', 'chain', 'random'].includes(layer.links.mode as string)) {\n err(`${path}.links.mode`, \"must be 'nearest' | 'chain' | 'random'\");\n }\n if (layer.links.falloff !== undefined && typeof layer.links.falloff !== 'boolean') {\n err(`${path}.links.falloff`, 'must be a boolean');\n }\n if (layer.links.closed !== undefined && typeof layer.links.closed !== 'boolean') {\n err(`${path}.links.closed`, 'must be a boolean');\n }\n if (isNum(layer.count) && layer.count > LIMITS.maxLinkLayerCount) {\n err(`${path}.links`, `layer count must be <= ${LIMITS.maxLinkLayerCount} when links is set`);\n }\n }\n }\n\n if (layer.layout !== undefined) {\n if (isObj(layer.layout) && (layer.layout.type === 'list' || layer.layout.type === 'table')) {\n const lay = layer.layout;\n if (lay.type === 'table' && (!isNum(lay.columns) || !Number.isInteger(lay.columns) || lay.columns < 1 || lay.columns > LIMITS.maxGridColumns)) {\n err(`${path}.layout.columns`, `must be an integer 1..${LIMITS.maxGridColumns}`);\n }\n const gapOk = (v: unknown): boolean => isNum(v) && v > 0;\n if (lay.gap !== undefined) {\n if (isNum(lay.gap)) {\n if (!gapOk(lay.gap)) err(`${path}.layout.gap`, 'must be > 0 (viewport units of min(w,h), or px)');\n } else if (lay.type === 'table' && isObj(lay.gap)) {\n if (lay.gap.x !== undefined && !gapOk(lay.gap.x)) err(`${path}.layout.gap.x`, 'must be > 0');\n if (lay.gap.y !== undefined && !gapOk(lay.gap.y)) err(`${path}.layout.gap.y`, 'must be > 0');\n for (const k of unknownKeys(lay.gap, new Set(['x', 'y']))) {\n warn(`${path}.layout.gap.${k}`, 'unknown-property', `unknown gap property '${k}' — will be ignored`);\n }\n } else {\n err(`${path}.layout.gap`, lay.type === 'table' ? 'must be a number > 0 or { x?, y? }' : 'must be a number > 0');\n }\n }\n for (const k of unknownKeys(lay, new Set(lay.type === 'list' ? ['type', 'gap'] : ['type', 'columns', 'gap']))) {\n warn(`${path}.layout.${k}`, 'unknown-property', `unknown layout property '${k}' — will be ignored`);\n }\n // A data layout reads variants in order: N labels want N strings.\n const sp = layer.sprite;\n if (isObj(sp) && isNum(layer.count)) {\n const variants = sp.kind === 'text' && Array.isArray(sp.strings) ? sp.strings.length\n : sp.kind === 'emoji' && Array.isArray(sp.glyphs) ? sp.glyphs.length\n : sp.kind === 'bar' && Array.isArray(sp.values) ? sp.values.length : null;\n if (variants !== null && variants !== layer.count) {\n warn(`${path}.count`, 'list-length-mismatch', `count is ${layer.count} but the sprite carries ${variants} ${sp.kind === 'bar' ? 'values' : 'variants'} — a ${lay.type} layout reads them in order, so they cycle or go unused`);\n }\n }\n } else if (!isObj(layer.layout) || layer.layout.type !== 'grid') {\n err(`${path}.layout`, \"must be an object with type: 'grid' | 'list' | 'table'\");\n } else {\n if (layer.layout.columns !== undefined && (!isNum(layer.layout.columns) || !Number.isInteger(layer.layout.columns) || layer.layout.columns < 1 || layer.layout.columns > LIMITS.maxGridColumns)) {\n err(`${path}.layout.columns`, `must be an integer 1..${LIMITS.maxGridColumns}`);\n }\n const jit = layer.layout.jitter;\n if (jit !== undefined) {\n const jitterOk = (v: unknown): boolean => isNum(v) && v >= 0 && v <= 1;\n if (isNum(jit)) {\n if (!jitterOk(jit)) err(`${path}.layout.jitter`, 'must be 0..1');\n } else if (isObj(jit)) {\n if (jit.x !== undefined && !jitterOk(jit.x)) err(`${path}.layout.jitter.x`, 'must be 0..1');\n if (jit.y !== undefined && !jitterOk(jit.y)) err(`${path}.layout.jitter.y`, 'must be 0..1');\n } else {\n err(`${path}.layout.jitter`, 'must be a number 0..1 or { x?, y? }');\n }\n }\n if (layer.position !== undefined) {\n warn(`${path}.layout`, 'layout-with-position', 'position overrides layout for the single entity — layout has no effect');\n }\n }\n }\n\n if (layer.life !== undefined) {\n if (!isObj(layer.life)) err(`${path}.life`, 'must be an object');\n else {\n if (layer.life.enter !== undefined && (!isNum(layer.life.enter) || layer.life.enter < 0)) {\n err(`${path}.life.enter`, 'must be >= 0 (ms)');\n }\n if (layer.life.exit !== undefined && (!isNum(layer.life.exit) || layer.life.exit < 0)) {\n err(`${path}.life.exit`, 'must be >= 0 (ms)');\n }\n if (isNum(layer.life.enter) && isNum(layer.life.exit) && layer.life.exit <= layer.life.enter) {\n err(`${path}.life.exit`, 'must be greater than life.enter');\n }\n if (layer.life.fade !== undefined && (!isNum(layer.life.fade) || layer.life.fade < 0)) {\n err(`${path}.life.fade`, 'must be >= 0 (ms)');\n }\n }\n }\n\n if (layer.trail !== undefined) {\n if (!isObj(layer.trail)) err(`${path}.trail`, 'must be an object');\n else {\n if (!isNum(layer.trail.length) || layer.trail.length <= 0 || layer.trail.length > LIMITS.maxTrailLength) {\n err(`${path}.trail.length`, `must be > 0 and <= ${LIMITS.maxTrailLength} ms`);\n }\n if (layer.trail.fade !== undefined && (!isNum(layer.trail.fade) || layer.trail.fade < 0 || layer.trail.fade > 1)) {\n err(`${path}.trail.fade`, 'must be 0..1');\n }\n }\n }\n\n if (layer.emit !== undefined) {\n if (!isObj(layer.emit)) err(`${path}.emit`, 'must be an object { every, life, jitter?, grow? }');\n else {\n const em = layer.emit;\n if (!isNum(em.every) || em.every < LIMITS.minEmitEvery || em.every > LIMITS.maxEmitEvery) {\n err(`${path}.emit.every`, `must be ${LIMITS.minEmitEvery}..${LIMITS.maxEmitEvery} ms (at most one event per second per entity)`);\n }\n if (!isNum(em.life) || em.life < LIMITS.minEmitLife) {\n err(`${path}.emit.life`, `must be >= ${LIMITS.minEmitLife} ms (an event is a smooth envelope, never a cut)`);\n } else if (isNum(em.every) && em.life > em.every) {\n err(`${path}.emit.life`, 'must be <= emit.every (the visible window cannot outlast its period)');\n }\n if (em.jitter !== undefined && (!isNum(em.jitter) || em.jitter < 0 || em.jitter > 1)) {\n err(`${path}.emit.jitter`, 'must be 0..1 (0 = evenly staggered, 1 = scattered by a fixed sequence)');\n }\n if (em.grow !== undefined) {\n if (!Array.isArray(em.grow) || em.grow.length !== 2 || !isNum(em.grow[0]) || !isNum(em.grow[1])) {\n err(`${path}.emit.grow`, 'must be [from, to] size multipliers');\n } else if (em.grow[0] < 0 || em.grow[1] < 0 || em.grow[0] > LIMITS.maxEmitGrow || em.grow[1] > LIMITS.maxEmitGrow) {\n err(`${path}.emit.grow`, `each multiplier must be 0..${LIMITS.maxEmitGrow}`);\n }\n }\n // jitter 0 promises one event at a time; that only holds while a window\n // is shorter than the stagger between entities.\n if (em.jitter === 0 && isNum(em.every) && isNum(em.life) && isNum(layer.count) && layer.count > 1 && em.life > em.every / layer.count) {\n warn(`${path}.emit.life`, 'emit-overlap', `jitter 0 staggers ${layer.count} entities ${(em.every / layer.count).toFixed(0)} ms apart but each stays lit ${em.life} ms — windows overlap, so more than one event is visible at a time. Shorten life or lengthen every`);\n }\n for (const k of unknownKeys(em, new Set(['every', 'life', 'jitter', 'grow']))) {\n warn(`${path}.emit.${k}`, 'unknown-property', `unknown emit property '${k}' — will be ignored`);\n }\n }\n }\n if (layer.clock !== undefined) {\n if (!isObj(layer.clock)) err(`${path}.clock`, 'must be an object { phase?, rate? }');\n else {\n const ck = layer.clock;\n if (ck.phase !== undefined && (!isNum(ck.phase) || ck.phase < 0 || ck.phase > 1)) {\n err(`${path}.clock.phase`, 'must be 0..1 (turns)');\n }\n const rate = ck.rate === undefined ? 1 : ck.rate;\n if (!isNum(rate) || rate < LIMITS.minClockRate || rate > LIMITS.maxClockRate) {\n err(`${path}.clock.rate`, `must be ${LIMITS.minClockRate}..${LIMITS.maxClockRate}`);\n } else {\n // A clocked layer pulses in unison — every entity at once — so the\n // per-entity-phase defence is gone and the period floor doubles.\n const floor = LIMITS.minClockedPeriod * rate;\n if (isObj(layer.pulse) && isNum(layer.pulse.period) && layer.pulse.period < floor) {\n err(`${path}.pulse.period`, `must be >= ${floor} ms when the layer has a clock (period / rate >= ${LIMITS.minClockedPeriod} — the whole layer breathes in unison)`);\n }\n if (isObj(layer.grow) && isNum(layer.grow.period) && layer.grow.period < floor) {\n err(`${path}.grow.period`, `must be >= ${floor} ms when the layer has a clock (period / rate >= ${LIMITS.minClockedPeriod})`);\n }\n const sp = layer.sprite;\n if (isObj(sp) && isObj(sp.cycle) && isNum(sp.cycle.period) && sp.cycle.period < floor) {\n err(`${path}.sprite.cycle.period`, `must be >= ${floor} ms when the layer has a clock (period / rate >= ${LIMITS.minClockedPeriod})`);\n }\n }\n for (const k of unknownKeys(ck, new Set(['phase', 'rate']))) {\n warn(`${path}.clock.${k}`, 'unknown-property', `unknown clock property '${k}' — will be ignored`);\n }\n }\n }\n validateSprite(layer.sprite, `${path}.sprite`, err, warn, spec);\n validateMotion(layer.motion, `${path}.motion`, err, warn, spec);\n}\n\nfunction validateSprite(sprite: unknown, path: string, err: (p: string, m: string) => void, warn: WarnFn, spec?: unknown): void {\n if (!isObj(sprite)) return err(path, 'must be an object');\n\n let knownSet: Set<string>;\n if (sprite.kind === 'emoji') {\n knownSet = KNOWN_EMOJI;\n if (!Array.isArray(sprite.glyphs) || sprite.glyphs.length === 0 || !sprite.glyphs.every(isStr)) {\n err(`${path}.glyphs`, 'must be a non-empty array of strings');\n }\n validateCycle(sprite, path, err);\n } else if (sprite.kind === 'text') {\n knownSet = KNOWN_TEXT;\n if (!Array.isArray(sprite.strings) || sprite.strings.length === 0 || !sprite.strings.every(isStr)) {\n err(`${path}.strings`, 'must be a non-empty array of strings');\n }\n if (sprite.color !== undefined) color(sprite.color, `${path}.color`, err);\n if (sprite.font !== undefined && !isStr(sprite.font)) {\n err(`${path}.font`, 'must be a string');\n }\n if (sprite.align !== undefined && !['left', 'center', 'right'].includes(sprite.align as string)) {\n err(`${path}.align`, 'must be left | center | right');\n }\n if (sprite.baseline !== undefined && !['top', 'middle', 'bottom'].includes(sprite.baseline as string)) {\n err(`${path}.baseline`, 'must be top | middle | bottom');\n }\n if (sprite.maxWidth !== undefined) positiveScalar(sprite.maxWidth, `${path}.maxWidth`, err, 'must be a positive number');\n validateTextRole(sprite, path, err);\n validateCycle(sprite, path, err);\n } else if (sprite.kind === 'circle') {\n knownSet = KNOWN_CIRCLE;\n if (!isRange(sprite.radius) || sprite.radius[0] <= 0) err(`${path}.radius`, rangeMsg(spec));\n color(sprite.color, `${path}.color`, err);\n if (sprite.soft !== undefined && typeof sprite.soft !== 'boolean') err(`${path}.soft`, 'must be a boolean');\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'ring') {\n knownSet = KNOWN_RING;\n if (!isRange(sprite.radius) || sprite.radius[0] <= 0) err(`${path}.radius`, rangeMsg(spec));\n color(sprite.color, `${path}.color`, err);\n if (sprite.width !== undefined) positiveScalar(sprite.width, `${path}.width`, err);\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'streak') {\n knownSet = KNOWN_STREAK;\n if (!isRange(sprite.length) || sprite.length[0] <= 0) err(`${path}.length`, rangeMsg(spec));\n color(sprite.color, `${path}.color`, err);\n if (sprite.width !== undefined) positiveScalar(sprite.width, `${path}.width`, err);\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'rect') {\n knownSet = KNOWN_RECT;\n if (!isRange(sprite.width) || sprite.width[0] <= 0) err(`${path}.width`, rangeMsg(spec));\n if (sprite.aspect !== undefined && (!isRange(sprite.aspect) || sprite.aspect[0] <= 0)) {\n err(`${path}.aspect`, 'must be a [min,max] range of positive height/width ratios');\n }\n if (sprite.feather !== undefined && (!isNum(sprite.feather) || sprite.feather < 0 || sprite.feather > 1)) {\n err(`${path}.feather`, 'must be 0..1 (fraction of the half-size that fades out)');\n }\n color(sprite.color, `${path}.color`, err);\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'bar') {\n knownSet = KNOWN_BAR;\n if (!Array.isArray(sprite.values) || sprite.values.length === 0 || sprite.values.length > LIMITS.maxPerLayer || !sprite.values.every((v) => isNum(v) && v >= 0)) {\n err(`${path}.values`, `must be 1..${LIMITS.maxPerLayer} numbers >= 0`);\n }\n positiveScalar(sprite.length, `${path}.length`, err, 'must be > 0 (full-scale bar length)');\n positiveScalar(sprite.thickness, `${path}.thickness`, err);\n if (sprite.max !== undefined) positiveScalar(sprite.max, `${path}.max`, err);\n if (sprite.direction !== undefined && !['right', 'left', 'up', 'down'].includes(sprite.direction as string)) {\n err(`${path}.direction`, \"must be 'right' | 'left' | 'up' | 'down'\");\n }\n color(sprite.color, `${path}.color`, err);\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'polygon') {\n knownSet = KNOWN_POLYGON;\n if (!isRange(sprite.radius) || sprite.radius[0] <= 0) err(`${path}.radius`, rangeMsg(spec, 'circumradius'));\n if (sprite.sides !== undefined && sprite.points !== undefined) {\n err(`${path}.sides`, 'use sides (a regular polygon) or points (a custom one), not both');\n }\n if (sprite.sides !== undefined && (!isNum(sprite.sides) || !Number.isInteger(sprite.sides) || sprite.sides < LIMITS.minPolygonSides || sprite.sides > LIMITS.maxPolygonSides)) {\n err(`${path}.sides`, `must be an integer ${LIMITS.minPolygonSides}..${LIMITS.maxPolygonSides}`);\n }\n if (sprite.points !== undefined) validateShapePoints(sprite.points, `${path}.points`, 3, err);\n if (sprite.parts !== undefined) {\n // A multi-colour drawing: paint lives on each part, never on the sprite.\n for (const k of ['path', 'points', 'sides', 'gradient', 'stroke', 'fill', 'fillRule'] as const) {\n if (sprite[k] !== undefined) err(`${path}.${k}`, `with parts, put ${k} on each part (or drop parts)`);\n }\n if (!Array.isArray(sprite.parts) || sprite.parts.length === 0 || sprite.parts.length > MAX_PATH_PARTS) {\n err(`${path}.parts`, `must be 1..${MAX_PATH_PARTS} parts, each { path, color?, gradient?, stroke?, fill?, fillRule?, opacity? }`);\n } else {\n sprite.parts.forEach((part: unknown, i: number) => {\n const pp = `${path}.parts[${i}]`;\n if (!isObj(part)) return err(pp, 'must be { path, color?, gradient?, stroke?, fill?, fillRule?, opacity? }');\n validatePathPiece(part, pp, err, warn);\n if (part.color !== undefined) color(part.color, `${pp}.color`, err);\n if (part.opacity !== undefined && (!isNum(part.opacity) || part.opacity < 0 || part.opacity > 1)) err(`${pp}.opacity`, 'must be 0..1');\n for (const k of unknownKeys(part, KNOWN_PATH_PART)) warn(`${pp}.${k}`, 'unknown-property', `unknown part property '${k}' — will be ignored`);\n });\n }\n } else if (sprite.path !== undefined) {\n if (sprite.points !== undefined || sprite.sides !== undefined) err(`${path}.path`, 'use path, points or sides, not more than one');\n validatePathPiece(sprite, path, err, warn);\n } else {\n for (const k of ['gradient', 'stroke', 'fill'] as const) if (sprite[k] !== undefined) err(`${path}.${k}`, `${k} applies only to a polygon with a path (or parts)`);\n if (sprite.fillRule !== undefined) warn(`${path}.fillRule`, 'unknown-property', 'fillRule applies only to a path — ignored');\n }\n if (sprite.span !== undefined || sprite.origin !== undefined) {\n if (sprite.path === undefined && sprite.parts === undefined) err(`${path}.span`, 'span and origin apply only to a polygon with a path (or parts)');\n if (sprite.span !== undefined && !['box', 'width', 'height', 'screen'].includes(sprite.span as string)) err(`${path}.span`, \"must be 'box' | 'width' | 'height' | 'screen'\");\n if (sprite.origin !== undefined && !(Array.isArray(sprite.origin) && sprite.origin.length === 2 && sprite.origin.every((v: unknown) => isNum(v) && Math.abs(v) <= 1))) err(`${path}.origin`, 'must be [x, y] in the unit box (-1..1): the point placed at the position');\n }\n if (sprite.soft !== undefined && typeof sprite.soft !== 'boolean') err(`${path}.soft`, 'must be a boolean');\n color(sprite.color, `${path}.color`, err);\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'stroke') {\n knownSet = KNOWN_STROKE;\n if (!isRange(sprite.length) || sprite.length[0] <= 0) err(`${path}.length`, rangeMsg(spec, \"the mark's bounding size\"));\n validateShapePoints(sprite.points, `${path}.points`, 2, err);\n if (sprite.width !== undefined) positiveScalar(sprite.width, `${path}.width`, err);\n if (sprite.curve !== undefined && sprite.curve !== 'smooth' && sprite.curve !== 'linear') err(`${path}.curve`, \"must be 'smooth' | 'linear'\");\n if (sprite.taper !== undefined && typeof sprite.taper !== 'boolean') err(`${path}.taper`, 'must be a boolean');\n if (sprite.orient !== undefined && typeof sprite.orient !== 'boolean') err(`${path}.orient`, 'must be a boolean');\n color(sprite.color, `${path}.color`, err);\n validatePalette(sprite, path, err);\n } else if (sprite.kind === 'textBlock') {\n knownSet = KNOWN_TEXT_BLOCK;\n if (typeof sprite.text !== 'string' || sprite.text.length === 0) {\n err(`${path}.text`, 'must be a non-empty string');\n } else if (sprite.text.length > LIMITS.maxTextBlockLength) {\n err(`${path}.text`, `must be at most ${LIMITS.maxTextBlockLength} characters`);\n }\n if (Array.isArray(sprite.maxWidth)) {\n err(`${path}.maxWidth`, 'must be a single number (viewport fraction), not a [min,max] range');\n } else if (!isNum(sprite.maxWidth) || sprite.maxWidth <= 0 || sprite.maxWidth > LIMITS.maxTextBlockMaxWidth) {\n err(`${path}.maxWidth`, `must be a positive number up to ${LIMITS.maxTextBlockMaxWidth} (viewport fraction)`);\n }\n if (Array.isArray(sprite.fontSize)) {\n err(`${path}.fontSize`, 'must be a single number (viewport fraction), not a [min,max] range');\n } else if (!isNum(sprite.fontSize) || sprite.fontSize < LIMITS.minTextBlockFontSize || sprite.fontSize > LIMITS.maxTextBlockFontSize) {\n err(`${path}.fontSize`, `must be between ${LIMITS.minTextBlockFontSize} and ${LIMITS.maxTextBlockFontSize} (viewport fraction)`);\n }\n if (sprite.lineHeight !== undefined && (!isNum(sprite.lineHeight) || sprite.lineHeight < 0.5 || sprite.lineHeight > 4)) {\n err(`${path}.lineHeight`, 'must be between 0.5 and 4 (multiplier)');\n }\n if (sprite.align !== undefined && !['left', 'center', 'right'].includes(sprite.align as string)) {\n err(`${path}.align`, \"must be 'left' | 'center' | 'right'\");\n }\n if (sprite.color !== undefined) color(sprite.color, `${path}.color`, err);\n if (sprite.anchor !== undefined && !TEXT_BLOCK_ANCHORS.has(sprite.anchor as string)) {\n err(`${path}.anchor`, \"must be 'top-left' | 'top' | 'top-right' | 'left' | 'center' | 'right' | 'bottom-left' | 'bottom' | 'bottom-right'\");\n }\n if (sprite.font !== undefined) {\n if (!isStr(sprite.font) || sprite.font.trim() === '') {\n err(`${path}.font`, 'must be a non-empty string (family and/or weight)');\n } else if (FONT_SIZE_RE.test(sprite.font)) {\n err(`${path}.font`, 'must name a family and/or weight only — fontSize owns the size');\n }\n }\n if (sprite.opacity !== undefined && (!isNum(sprite.opacity) || sprite.opacity < 0 || sprite.opacity > 1)) {\n err(`${path}.opacity`, 'must be a number between 0 and 1');\n }\n validateTextRole(sprite, path, err);\n if (sprite.reveal !== undefined) {\n const rv = sprite.reveal as Record<string, unknown>;\n if (typeof rv !== 'object' || rv === null || Array.isArray(rv)) {\n err(`${path}.reveal`, 'must be an object');\n } else {\n for (const k of Object.keys(rv)) {\n if (!KNOWN_REVEAL.has(k)) err(`${path}.reveal.${k}`, 'unknown reveal field');\n }\n if (rv.progress !== undefined && (!isNum(rv.progress) || rv.progress < 0 || rv.progress > 1)) {\n err(`${path}.reveal.progress`, 'must be a number between 0 and 1');\n }\n if (rv.mode !== undefined && !['typewriter', 'word', 'line', 'glyphFade'].includes(rv.mode as string)) {\n err(`${path}.reveal.mode`, \"must be 'typewriter' | 'word' | 'line' | 'glyphFade'\");\n }\n if (rv.fade !== undefined && (!isNum(rv.fade) || rv.fade <= 0 || rv.fade > 1)) {\n err(`${path}.reveal.fade`, 'must be between 0 (exclusive) and 1 (fraction of progress)');\n }\n if (rv.speed !== undefined && (!isNum(rv.speed) || rv.speed < 0 || rv.speed > LIMITS.maxRevealSpeed)) {\n err(`${path}.reveal.speed`, `must be between 0 and ${LIMITS.maxRevealSpeed} (graphemes/sec)`);\n }\n if (rv.caret !== undefined && typeof rv.caret !== 'boolean') {\n const caret = rv.caret as Record<string, unknown>;\n if (typeof caret !== 'object' || caret === null || Array.isArray(caret)) {\n err(`${path}.reveal.caret`, 'must be a boolean or an object');\n } else {\n for (const k of Object.keys(caret)) {\n if (!KNOWN_REVEAL_CARET.has(k)) err(`${path}.reveal.caret.${k}`, 'unknown caret field');\n }\n if (caret.blink !== undefined && (!isNum(caret.blink) || caret.blink <= 0 || caret.blink > LIMITS.maxCaretBlinkHz)) {\n err(`${path}.reveal.caret.blink`, `must be between 0 (exclusive) and ${LIMITS.maxCaretBlinkHz} Hz (flash safety)`);\n }\n if (caret.color !== undefined) color(caret.color, `${path}.reveal.caret.color`, err);\n }\n }\n }\n }\n } else {\n err(`${path}.kind`, 'must be emoji | text | circle | ring | streak | rect | bar | polygon | stroke | textBlock');\n return;\n }\n\n for (const k of unknownKeys(sprite, knownSet)) {\n if (LAYER_PROPS_ON_SPRITE.has(k)) {\n warn(`${path}.${k}`, 'misplaced-property', `'${k}' belongs on the layer, not inside sprite — move it up one level`);\n } else {\n warn(`${path}.${k}`, 'unknown-property', `unknown sprite property '${k}' — will be ignored`);\n }\n }\n}\n\n/** Shared colors[] + colorWeights[] validation for circle/ring/streak/rect sprites. */\nfunction validatePalette(sprite: Record<string, unknown>, path: string, err: (p: string, m: string) => void): void {\n if (sprite.colors !== undefined) {\n if (!Array.isArray(sprite.colors) || sprite.colors.length === 0) {\n err(`${path}.colors`, 'must be a non-empty array of hex colours');\n } else {\n sprite.colors.forEach((c: unknown, ci: number) => color(c, `${path}.colors[${ci}]`, err));\n }\n }\n if (sprite.colorWeights !== undefined) {\n if (!Array.isArray(sprite.colors)) {\n err(`${path}.colorWeights`, 'requires colors to be set');\n } else if (!Array.isArray(sprite.colorWeights) || sprite.colorWeights.length !== sprite.colors.length) {\n err(`${path}.colorWeights`, 'must be an array the same length as colors');\n } else if (!sprite.colorWeights.every((v: unknown) => isNum(v) && v >= 0) || !sprite.colorWeights.some((v: unknown) => isNum(v) && v > 0)) {\n err(`${path}.colorWeights`, 'weights must be >= 0 with at least one > 0');\n }\n }\n}\n\n/** `role` on `text` / `textBlock`: a declaration of intent, one of two words. */\nfunction validateTextRole(sprite: Record<string, unknown>, path: string, err: (p: string, m: string) => void): void {\n if (sprite.role !== undefined && !TEXT_ROLES.has(sprite.role as string)) {\n err(`${path}.role`, \"must be 'read' | 'atmosphere'\");\n }\n}\n\nfunction validateCycle(sprite: Record<string, unknown>, path: string, err: (p: string, m: string) => void): void {\n if (sprite.cycle === undefined) return;\n if (!isObj(sprite.cycle)) return err(`${path}.cycle`, 'must be an object');\n if (!isNum(sprite.cycle.period) || sprite.cycle.period < LIMITS.minCyclePeriod) {\n err(`${path}.cycle.period`, `must be >= ${LIMITS.minCyclePeriod} ms (flash-safety floor)`);\n }\n}\n\nfunction validateMotion(motion: unknown, path: string, err: (p: string, m: string) => void, warn: WarnFn, spec?: unknown): void {\n if (!isObj(motion)) return err(path, 'must be an object');\n const isViewport = !isObj(spec) || (spec as Record<string, unknown>).units !== 'px';\n const refVp = isObj(spec) && isNum((spec as Record<string, unknown>).referenceViewport) ? (spec as Record<string, unknown>).referenceViewport as number : LIMITS.referenceViewport;\n const speedCap = isViewport ? LIMITS.maxSpeed / refVp : LIMITS.maxSpeed;\n const speedOk = (v: unknown, p: string): void => {\n if (!isRange(v)) err(p, 'must be a [min,max] range');\n else if (v[0] < 0) err(p, 'speed lower bound must be >= 0');\n else if (v[1] > speedCap) err(p, `speed exceeds cap ${isViewport ? speedCap.toFixed(2) + ' viewport-units/sec' : LIMITS.maxSpeed + ' px/sec'}`);\n };\n\n let knownSet: Set<string>;\n if (motion.type === 'drift') {\n knownSet = KNOWN_DRIFT;\n speedOk(motion.speed, `${path}.speed`);\n if (motion.angle !== undefined && !isNum(motion.angle)) err(`${path}.angle`, 'must be a number (degrees)');\n if (motion.bidirectional !== undefined && typeof motion.bidirectional !== 'boolean') err(`${path}.bidirectional`, 'must be a boolean');\n if (motion.bob !== undefined && !isNum(motion.bob)) err(`${path}.bob`, 'must be a number');\n validateEase(motion.ease, `${path}.ease`, err, warn);\n if (isRange(motion.speed) && motion.speed[1] < 1 && !isViewport) {\n warn(`${path}.speed`, 'near-zero-speed', `max speed is ${motion.speed[1]} px/sec — entities will appear frozen. Typical range: 10–200 px/sec`);\n }\n } else if (motion.type === 'rise') {\n knownSet = KNOWN_RISE;\n speedOk(motion.speed, `${path}.speed`);\n if (motion.sway !== undefined && !isNum(motion.sway)) err(`${path}.sway`, 'must be a number');\n validateEase(motion.ease, `${path}.ease`, err, warn);\n if (isRange(motion.speed) && motion.speed[1] < 1 && !isViewport) {\n warn(`${path}.speed`, 'near-zero-speed', `max speed is ${motion.speed[1]} px/sec — entities will appear frozen. Typical range: 5–80 px/sec`);\n }\n } else if (motion.type === 'bounce') {\n knownSet = KNOWN_BOUNCE;\n speedOk(motion.speed, `${path}.speed`);\n if (isRange(motion.speed) && motion.speed[1] < 1 && !isViewport) {\n warn(`${path}.speed`, 'near-zero-speed', `max speed is ${motion.speed[1]} px/sec — entities will appear frozen. Typical range: 20–150 px/sec`);\n }\n } else if (motion.type === 'static') {\n knownSet = KNOWN_STATIC;\n } else if (motion.type === 'orbit') {\n knownSet = KNOWN_ORBIT;\n if (!isRange(motion.speed)) err(`${path}.speed`, 'must be a [min,max] range');\n else {\n if (Math.abs(motion.speed[0]) > LIMITS.maxOrbitSpeed || Math.abs(motion.speed[1]) > LIMITS.maxOrbitSpeed) err(`${path}.speed`, `orbit speed exceeds cap ${LIMITS.maxOrbitSpeed} deg/sec`);\n if (Math.max(Math.abs(motion.speed[0]), Math.abs(motion.speed[1])) < 1) {\n warn(`${path}.speed`, 'near-zero-speed', `orbit speed is near zero — entities will appear frozen. Typical range: 5–60 deg/sec`);\n }\n }\n if (!isRange(motion.radius) || motion.radius[0] <= 0) err(`${path}.radius`, rangeMsg(spec));\n if (motion.center !== undefined) {\n if (!isObj(motion.center)) {\n err(`${path}.center`, 'must be {x, y} (0..1) or { layer: key }');\n } else if ('layer' in motion.center) {\n if (!isStr(motion.center.layer) || motion.center.layer.trim() === '') {\n err(`${path}.center.layer`, 'must be a non-empty layer key');\n } else if (isObj(spec) && Array.isArray((spec as Record<string, unknown>).layers)) {\n // Scene-graph lite: parent must exist, be a single entity, and not itself\n // orbit a layer (strictly one level deep — keeps positionAt analytic).\n const layers = (spec as { layers: unknown[] }).layers;\n const parent = layers.find((l) => isObj(l) && l.key === (motion.center as { layer: string }).layer) as Record<string, unknown> | undefined;\n if (!parent) {\n err(`${path}.center.layer`, `no layer with key '${motion.center.layer}'`);\n } else {\n if (parent.count !== 1) err(`${path}.center.layer`, 'parent layer must have count: 1');\n const pm = parent.motion;\n if (isObj(pm) && pm.type === 'orbit' && isObj(pm.center) && 'layer' in pm.center) {\n err(`${path}.center.layer`, 'parent may not itself orbit a layer (one level deep only)');\n }\n }\n }\n } else if (!isNum(motion.center.x) || !isNum(motion.center.y)) {\n err(`${path}.center`, 'must be {x, y} with numbers 0..1');\n } else {\n if (motion.center.x < 0 || motion.center.x > 1) err(`${path}.center.x`, 'must be 0..1');\n if (motion.center.y < 0 || motion.center.y > 1) err(`${path}.center.y`, 'must be 0..1');\n }\n }\n } else if (motion.type === 'wander') {\n knownSet = KNOWN_WANDER;\n validateEase(motion.ease, `${path}.ease`, err, warn);\n speedOk(motion.speed, `${path}.speed`);\n if (motion.angle !== undefined && !isNum(motion.angle)) err(`${path}.angle`, 'must be a number (degrees)');\n const meanderCap = isViewport ? LIMITS.maxMeander / refVp : LIMITS.maxMeander;\n if (motion.meander !== undefined && (!isNum(motion.meander) || motion.meander <= 0 || motion.meander > meanderCap)) {\n err(`${path}.meander`, `must be > 0 and <= ${isViewport ? meanderCap.toFixed(3) + ' viewport-units' : LIMITS.maxMeander + ' px'}`);\n }\n if (motion.coherence !== undefined && (!isNum(motion.coherence) || motion.coherence < 0 || motion.coherence > 1)) {\n err(`${path}.coherence`, 'must be 0..1');\n }\n } else if (motion.type === 'warp') {\n knownSet = KNOWN_WARP;\n if (!isRange(motion.speed) || motion.speed[0] < 0) err(`${path}.speed`, 'must be a [min,max] range >= 0 (depth-units/sec)');\n else if (motion.speed[1] > LIMITS.maxWarpSpeed) err(`${path}.speed`, `warp speed exceeds cap ${LIMITS.maxWarpSpeed} depth-units/sec`);\n if (motion.center !== undefined) {\n if (!isObj(motion.center) || !isNum(motion.center.x) || !isNum(motion.center.y)) {\n err(`${path}.center`, 'must be {x, y} with numbers 0..1');\n } else {\n if (motion.center.x < 0 || motion.center.x > 1) err(`${path}.center.x`, 'must be 0..1');\n if (motion.center.y < 0 || motion.center.y > 1) err(`${path}.center.y`, 'must be 0..1');\n }\n }\n } else if (motion.type === 'path') {\n knownSet = KNOWN_PATH;\n if (!Array.isArray(motion.points) || motion.points.length < LIMITS.minPathPoints || motion.points.length > LIMITS.maxPathPoints) {\n err(`${path}.points`, `must be an array of ${LIMITS.minPathPoints}..${LIMITS.maxPathPoints} points`);\n } else {\n motion.points.forEach((p: unknown, pi: number) => {\n if (!isObj(p) || !isNum(p.x) || !isNum(p.y) || p.x < 0 || p.x > 1 || p.y < 0 || p.y > 1) {\n err(`${path}.points[${pi}]`, 'must be {x, y} with numbers 0..1');\n }\n });\n }\n if (!isNum(motion.duration) || motion.duration < LIMITS.minPathDuration) {\n err(`${path}.duration`, `must be >= ${LIMITS.minPathDuration} ms`);\n }\n if (motion.curve !== undefined && motion.curve !== 'linear' && motion.curve !== 'smooth') {\n err(`${path}.curve`, \"must be 'linear' | 'smooth'\");\n }\n if (motion.closed !== undefined && typeof motion.closed !== 'boolean') err(`${path}.closed`, 'must be a boolean');\n const scatterCap = isViewport ? LIMITS.maxMeander / refVp : LIMITS.maxMeander;\n if (motion.scatter !== undefined && (!isNum(motion.scatter) || motion.scatter <= 0 || motion.scatter > scatterCap)) {\n err(`${path}.scatter`, `must be > 0 and <= ${isViewport ? scatterCap.toFixed(3) + ' viewport-units' : LIMITS.maxMeander + ' px'}`);\n }\n } else {\n err(`${path}.type`, 'must be drift | rise | bounce | static | orbit | wander | warp | path');\n return;\n }\n\n for (const k of unknownKeys(motion, knownSet)) {\n warn(`${path}.${k}`, 'unknown-property', `unknown motion property '${k}' — will be ignored`);\n }\n}\n\nconst isPair = (v: unknown, lim = 2): boolean => Array.isArray(v) && v.length === 2 && isNum(v[0]) && isNum(v[1]) && Math.abs(v[0]) <= lim && Math.abs(v[1]) <= lim;\n\n/** Most parts one multi-colour path drawing may have. */\nconst MAX_PATH_PARTS = 256;\n\n/** A path piece — a path polygon itself, or one of its parts: the d string, fill, fill rule, gradient, stroke. */\nfunction validatePathPiece(piece: Record<string, unknown>, path: string, err: (p: string, m: string) => void, warn: WarnFn): void {\n if (typeof piece.path !== 'string' || piece.path.length === 0 || piece.path.length > 65536) {\n err(`${path}.path`, 'must be an SVG path d string (1..65536 chars) in the -1..1 unit box');\n } else {\n const flat = flattenPath(piece.path, (piece.fillRule as PathFillRule | undefined) ?? 'auto');\n const filled = piece.fill !== false;\n if (flat.error) err(`${path}.path`, `not a usable path: ${flat.error}`);\n else if (filled && flat.points.length < 3) err(`${path}.path`, 'must enclose an area (at least 3 points), or set fill: false and a stroke for line art');\n else if (!filled && flat.lines.length === 0) err(`${path}.path`, 'must draw at least one line (2+ points)');\n else if (flat.points.length > MAX_PATH_POINTS) err(`${path}.path`, `flattens to ${flat.points.length} points; at most ${MAX_PATH_POINTS}`);\n else if ([...flat.points, ...flat.lines.flatMap((l) => l.points)].some(([x, y]) => Math.abs(x) > 1.0001 || Math.abs(y) > 1.0001)) err(`${path}.path`, 'must stay inside the -1..1 unit box (curves included)');\n }\n if (piece.fill !== undefined && typeof piece.fill !== 'boolean') err(`${path}.fill`, 'must be a boolean');\n if (piece.fill === false && piece.stroke === undefined) err(`${path}.fill`, 'fill: false draws nothing without a stroke');\n if (piece.gradient !== undefined) validatePathGradient(piece.gradient, `${path}.gradient`, err);\n if (piece.stroke !== undefined) validatePathStroke(piece.stroke, `${path}.stroke`, err);\n if (piece.fillRule !== undefined && !['auto', 'nonzero', 'evenodd'].includes(piece.fillRule as string)) err(`${path}.fillRule`, \"must be 'auto' | 'nonzero' | 'evenodd'\");\n void warn;\n}\n\n/** A path gradient: linear {from, to} or radial {center, radius, focus?}, 2..8 stops, in unit-box coordinates. */\nfunction validatePathGradient(g: unknown, path: string, err: (p: string, m: string) => void): void {\n if (!isObj(g)) return err(path, \"must be { type: 'linear', from, to, stops } or { type: 'radial', center, radius, stops }\");\n if (g.type === 'linear') {\n if (!isPair(g.from)) err(`${path}.from`, 'must be [x, y] in unit-box coordinates (-2..2)');\n if (!isPair(g.to)) err(`${path}.to`, 'must be [x, y] in unit-box coordinates (-2..2)');\n } else if (g.type === 'radial') {\n if (!isPair(g.center)) err(`${path}.center`, 'must be [x, y] in unit-box coordinates (-2..2)');\n if (!isNum(g.radius) || g.radius <= 0 || g.radius > 4) err(`${path}.radius`, 'must be > 0 and <= 4 (unit-box units)');\n if (g.focus !== undefined && !isPair(g.focus)) err(`${path}.focus`, 'must be [x, y] in unit-box coordinates (-2..2)');\n } else {\n return err(`${path}.type`, \"must be 'linear' | 'radial'\");\n }\n if (g.units !== undefined && g.units !== 'box' && g.units !== 'part') err(`${path}.units`, \"must be 'box' (the drawing's unit box, default) | 'part' (the part's own box, -1..1)\");\n if (!Array.isArray(g.stops) || g.stops.length < 2 || g.stops.length > 8) return err(`${path}.stops`, 'must be 2..8 stops');\n let last = -Infinity;\n g.stops.forEach((st: unknown, i: number) => {\n if (!isObj(st)) return err(`${path}.stops[${i}]`, 'must be { at, color, opacity? }');\n if (!isNum(st.at) || st.at < 0 || st.at > 1 || st.at < last) err(`${path}.stops[${i}].at`, 'must be 0..1, not decreasing');\n else last = st.at;\n color(st.color, `${path}.stops[${i}].color`, err);\n if (st.opacity !== undefined && (!isNum(st.opacity) || st.opacity < 0 || st.opacity > 1)) err(`${path}.stops[${i}].opacity`, 'must be 0..1');\n });\n}\n\n/** A path stroke: colour, width in unit-box units, optional opacity / join / cap. */\nfunction validatePathStroke(st: unknown, path: string, err: (p: string, m: string) => void): void {\n if (!isObj(st)) return err(path, \"must be { color, width, opacity?, join?, cap? }\");\n color(st.color, `${path}.color`, err);\n if (!isNum(st.width) || st.width <= 0 || st.width > 0.5) err(`${path}.width`, 'must be > 0 and <= 0.5 (unit-box units: 0.01 is 1% of the drawing\\'s half-size)');\n if (st.opacity !== undefined && (!isNum(st.opacity) || st.opacity < 0 || st.opacity > 1)) err(`${path}.opacity`, 'must be 0..1');\n if (st.join !== undefined && !['round', 'miter', 'bevel'].includes(st.join as string)) err(`${path}.join`, \"must be 'round' | 'miter' | 'bevel'\");\n if (st.cap !== undefined && !['round', 'butt', 'square'].includes(st.cap as string)) err(`${path}.cap`, \"must be 'round' | 'butt' | 'square'\");\n}\n\n/** `points` for polygon/stroke: 2..24 (or 3..24) unit pairs inside the −1..1 box. */\nfunction validateShapePoints(points: unknown, path: string, min: number, err: (p: string, m: string) => void): void {\n if (!Array.isArray(points) || points.length < min || points.length > LIMITS.maxShapePoints) {\n return err(path, `must be ${min}..${LIMITS.maxShapePoints} [x, y] pairs in unit coordinates (-1..1)`);\n }\n for (let i = 0; i < points.length; i++) {\n const pt: unknown = points[i]; // by index, so a sparse array's holes are rejected too\n if (!Array.isArray(pt) || pt.length !== 2 || !isNum(pt[0]) || !isNum(pt[1]) || Math.abs(pt[0]) > 1 || Math.abs(pt[1]) > 1) {\n err(`${path}[${i}]`, 'must be an [x, y] pair with each coordinate in -1..1');\n }\n }\n}\n\nfunction validateEase(ease: unknown, path: string, err: (p: string, m: string) => void, warn: WarnFn): void {\n if (ease === undefined) return;\n if (!isObj(ease)) return err(path, \"must be an object { type: 'settle' | 'buoyant', tau }\");\n if (ease.type !== 'settle' && ease.type !== 'buoyant') err(`${path}.type`, \"must be 'settle' | 'buoyant'\");\n if (!isNum(ease.tau) || ease.tau < LIMITS.minEaseTau || ease.tau > LIMITS.maxEaseTau) {\n err(`${path}.tau`, `must be ${LIMITS.minEaseTau}..${LIMITS.maxEaseTau} ms`);\n }\n for (const k of unknownKeys(ease, new Set(['type', 'tau']))) {\n warn(`${path}.${k}`, 'unknown-property', `unknown ease property '${k}' — will be ignored`);\n }\n}\n\n/** Narrowing helper: validate + cast. Throws with a joined message when invalid. */\nexport function assertValidSpec(spec: unknown): SaverSpec {\n const r = validateSpec(spec);\n if (!r.valid) {\n throw new Error(`invalid saver spec:\\n${r.errors.map((e) => ` ${e.path || '<root>'}: ${e.message}`).join('\\n')}`);\n }\n return spec as SaverSpec;\n}\n\n/**\n * Validate a sequence envelope. Each segment's `scene` goes through `validateSpec`;\n * sequence-level rules (segment count, duration floors, key uniqueness, transition\n * bounds) are checked here.\n */\nexport function validateSequence(seq: unknown): ValidationResult {\n // Normalize each segment's scene (F3: colors-without-color auto-default)\n if (isObj(seq) && Array.isArray(seq.segments)) {\n for (const seg of seq.segments) {\n if (isObj(seg) && isObj((seg as Record<string, unknown>).scene)) {\n normalizeColors((seg as Record<string, unknown>).scene);\n }\n }\n }\n if (isObj(seq) && isObj(seq.bed)) normalizeColors(seq.bed);\n const errors: SpecError[] = [];\n const warnings: SpecWarning[] = [];\n const err = (path: string, message: string): void => void errors.push({ path, message });\n\n if (!isObj(seq)) return { valid: false, errors: [{ path: '', message: 'sequence must be an object' }], warnings: [] };\n\n if (seq.format !== 'idle-sequence') err('format', \"must be 'idle-sequence'\");\n if (seq.schemaVersion !== SCHEMA_VERSION) err('schemaVersion', `must be ${SCHEMA_VERSION}`);\n if (!isStr(seq.id) || seq.id.trim() === '') err('id', 'must be a non-empty string');\n if (!isStr(seq.label) || seq.label.trim() === '') err('label', 'must be a non-empty string');\n if (seq.seed !== undefined && !isNum(seq.seed)) err('seed', 'must be a number');\n if (typeof seq.loop !== 'boolean') err('loop', 'must be a boolean');\n if (seq.sync !== undefined && seq.sync !== 'mount' && seq.sync !== 'epoch') err('sync', \"must be 'mount' | 'epoch'\");\n if (seq.wrapMorph !== undefined && typeof seq.wrapMorph !== 'boolean') err('wrapMorph', 'must be a boolean');\n if (seq.finish !== undefined) validateFinish(seq.finish, 'finish', err, (p, code, message) => void warnings.push({ path: p, code, message }));\n\n if (!Array.isArray(seq.segments) || seq.segments.length === 0) {\n err('segments', 'must be a non-empty array');\n return { valid: false, errors, warnings };\n }\n\n if (seq.segments.length > LIMITS.maxSegments) {\n err('segments', `at most ${LIMITS.maxSegments} segments`);\n }\n\n const keys = new Set<string>();\n let hasDurationless = false;\n\n for (let i = 0; i < seq.segments.length; i++) {\n const s = seq.segments[i];\n const p = `segments[${i}]`;\n if (!isObj(s)) { err(p, 'must be an object'); continue; }\n\n if (!isStr(s.key) || s.key.trim() === '') {\n err(`${p}.key`, 'must be a non-empty string');\n } else if (keys.has(s.key as string)) {\n err(`${p}.key`, `duplicate key '${s.key}'`);\n } else {\n keys.add(s.key as string);\n }\n\n if (s.duration !== undefined) {\n if (hasDurationless) {\n err(`${p}.duration`, 'a segment after a durationless segment may not have a duration');\n }\n if (!isNum(s.duration) || s.duration < LIMITS.minSegmentDuration) {\n err(`${p}.duration`, `must be >= ${LIMITS.minSegmentDuration} ms`);\n }\n } else {\n if (i < seq.segments.length - 1) {\n err(`${p}.duration`, 'only the final segment may omit duration');\n }\n hasDurationless = true;\n }\n\n if (s.advance !== undefined && !['auto', 'input', 'either'].includes(s.advance as string)) {\n err(`${p}.advance`, \"must be 'auto' | 'input' | 'either'\");\n }\n\n if (s.transition !== undefined) {\n if (!isObj(s.transition)) {\n err(`${p}.transition`, 'must be an object');\n } else if (s.transition.type === 'morph' || s.transition.type === 'fade') {\n if (!isNum(s.transition.dur) || s.transition.dur < LIMITS.minTransitionDur || s.transition.dur > LIMITS.maxTransitionDur) {\n err(`${p}.transition.dur`, `must be a number between ${LIMITS.minTransitionDur} and ${LIMITS.maxTransitionDur}`);\n }\n } else if (s.transition.type !== 'cut') {\n err(`${p}.transition.type`, \"must be 'cut', 'morph' or 'fade'\");\n }\n if (isObj(s.transition) && s.transition.text !== undefined) {\n if (s.transition.type !== 'morph') {\n err(`${p}.transition.text`, 'is a morph option (fade already cross-fades whole frames; cut has no window)');\n } else if (s.transition.text !== 'step' && s.transition.text !== 'crossfade' && s.transition.text !== 'dip') {\n err(`${p}.transition.text`, \"must be 'step' | 'crossfade' | 'dip'\");\n }\n }\n }\n\n if (isObj(s.scene)) {\n const sceneResult = validateSpec(s.scene);\n for (const e of sceneResult.errors) errors.push({ path: `${p}.scene.${e.path}`, message: e.message });\n if (sceneResult.warnings) {\n for (const w of sceneResult.warnings) warnings.push({ path: `${p}.scene.${w.path}`, code: w.code, message: w.message });\n }\n } else {\n err(`${p}.scene`, 'must be a valid SaverSpec object');\n }\n }\n\n if (seq.loop === true && hasDurationless) {\n err('loop', 'loop: true requires all segments to have a duration');\n }\n\n // The bed: a full SaverSpec, live alongside whichever segment is up.\n if (seq.bed !== undefined) {\n if (!isObj(seq.bed)) {\n err('bed', 'must be a SaverSpec object');\n } else {\n const bedResult = validateSpec(seq.bed);\n for (const e of bedResult.errors) errors.push({ path: `bed.${e.path}`, message: e.message });\n for (const w of bedResult.warnings ?? []) warnings.push({ path: `bed.${w.path}`, code: w.code, message: w.message });\n if (bedResult.valid) {\n const entityTotal = (spec: unknown): number =>\n isObj(spec) && Array.isArray(spec.layers)\n ? spec.layers.reduce<number>((n, l) => n + (isObj(l) && isNum(l.count) ? l.count : 0), 0)\n : 0;\n const bedTotal = entityTotal(seq.bed);\n const largest = seq.segments.reduce<number>((m, s) => Math.max(m, isObj(s) ? entityTotal(s.scene) : 0), 0);\n if (bedTotal + largest > LIMITS.maxTotal) {\n err('bed', `bed entities ${bedTotal} + largest segment ${largest} = ${bedTotal + largest} exceeds cap ${LIMITS.maxTotal} (the two are live at once)`);\n }\n // The bed owns the ground: a segment background is never painted over it.\n seq.segments.forEach((s, i) => {\n if (isObj(s) && isObj(s.scene) && s.scene.background !== undefined) {\n warnings.push({\n path: `segments[${i}].scene.background`,\n code: 'bed-hides-segment-background',\n message: `segment ${i} declares a background but the sequence has a bed — segments render transparently over the bed, so this background is never painted`,\n });\n }\n });\n }\n }\n }\n\n // Warn when morph is requested but signatures differ (will fall back to cut)\n if (errors.length === 0 && Array.isArray(seq.segments)) {\n for (let i = 0; i < seq.segments.length; i++) {\n const s = seq.segments[i];\n if (!isObj(s) || !isObj(s.transition) || s.transition.type !== 'morph') continue;\n const next = seq.segments[i + 1];\n if (!next || !isObj(next) || !isObj(s.scene) || !isObj(next.scene)) continue;\n const sigA = structuralSignature(s.scene as unknown as SaverSpec);\n const sigB = structuralSignature((next as Record<string, unknown>).scene as unknown as SaverSpec);\n if (sigA !== sigB) {\n warnings.push({\n path: `segments[${i}].transition`,\n code: 'morph-structural-mismatch',\n message: `segments ${i}→${i + 1} differ structurally: morph will fall back to cut`,\n });\n } else if (s.scene.timeline === undefined && (next as Record<string, unknown> & { scene: Record<string, unknown> }).scene.timeline === undefined\n && morphNothingMorphable(s.scene as unknown as SaverSpec, (next as Record<string, unknown>).scene as unknown as SaverSpec, { textCrossfade: s.transition.text === 'crossfade' || s.transition.text === 'dip' })) {\n // Structural twins whose only differences are values lerpSpec steps\n // (strings — textBlock.text above all). The morph runs, but every\n // frame of it shows segment i+1: it reads as a cut. A warning, never\n // an error, so every stored sequence stays valid.\n warnings.push({\n path: `segments[${i}].transition`,\n code: 'morph-nothing-morphable',\n message: `segments ${i}→${i + 1} differ only in values morph cannot interpolate (strings such as textBlock.text step on the first frame): the morph will look like a cut — fade text via colour or reveal.progress`,\n });\n }\n }\n }\n\n // `wrapMorph`: say why the wrap will still be a cut, when it will.\n if (errors.length === 0 && seq.wrapMorph === true) {\n const sq = seq as unknown as IdleSequence;\n const last = sq.segments.length - 1;\n const lastTr = sq.segments[last]?.transition;\n let why: string | null = null;\n if (sq.loop !== true) why = 'the sequence does not loop';\n else if (last < 1) why = 'there is only one segment';\n else if (lastTr?.type !== 'morph') why = 'the last segment declares no morph transition';\n else if (structuralSignature(sq.segments[last]!.scene) !== structuralSignature(sq.segments[0]!.scene)) why = `segment ${last} and segment 0 differ structurally`;\n else if (morphChainRoot(sq, last) !== 0) why = `the lap is not one morph chain (segment ${morphChainRoot(sq, last)} starts a new chain), so the wrap would jump seeds`;\n if (why || !canWrapMorph(sq)) {\n warnings.push({ path: 'wrapMorph', code: 'wrap-morph-inactive', message: `wrapMorph has no effect: ${why ?? 'the wrap cannot morph'} — the wrap stays a cut` });\n }\n }\n\n return { valid: errors.length === 0, errors, warnings };\n}\n\nexport function assertValidSequence(seq: unknown): IdleSequence {\n const r = validateSequence(seq);\n if (!r.valid) {\n throw new Error(`invalid sequence:\\n${r.errors.map((e) => ` ${e.path || '<root>'}: ${e.message}`).join('\\n')}`);\n }\n return seq as IdleSequence;\n}\n","import type { Rng } from '@idle-screens/core';\nimport type { CycleSpec, LayerSpec, SaverSpec, SpriteSpec, TextBlockAnchor } from './types';\nimport { LIMITS } from './types';\nimport { isShapedSprite } from './shapes';\n\n/**\n * The two scale factors every entity builder must agree on, computed in ONE\n * place. `scale` turns viewport-unit dimensions into px (1 for `units: \"px\"`,\n * min(w,h) otherwise — the default is viewport, so an omitted `units` scales);\n * `countScale` thins or thickens scatter density against `referenceViewport`\n * and is clamped so the projected total never exceeds LIMITS.maxTotal.\n *\n * Four callers (compile, perceive, advise, describe) each carried their own\n * copy of this arithmetic and they drifted twice: describeScene inverted the\n * units default and built every shipped example at scale 1 (F48), and\n * advise/describe skipped the maxTotal clamp so above ~4.6K they measured a\n * scene the renderer never draws — and because the RNG stream is shared across\n * layers, one early layer's different count shifts every later layer's\n * positions too (F49).\n */\nexport function entityScales(spec: SaverSpec, w: number, h: number): { scale: number; countScale: number } {\n const scale = spec.units === 'px' ? 1 : Math.min(w, h);\n const refVp = spec.referenceViewport ?? LIMITS.referenceViewport;\n let countScale = scale > 1 ? Math.min(w, h) / refVp : 1;\n if (countScale > 1) {\n const rawTotal = spec.layers.reduce((s, l) => s + Math.round(l.count * countScale), 0);\n if (rawTotal > LIMITS.maxTotal) countScale *= LIMITS.maxTotal / rawTotal;\n }\n return { scale, countScale };\n}\n\n/** Near plane for warp motion. z lives in [WARP_NEAR, 1]; screen scale is 1/z. */\nexport const WARP_NEAR = 0.08;\n/** Cap on the 1/z size multiplier so near stars don't blow out. */\nexport const WARP_MAX_SCALE = 8;\n\n/** One axis-pair of seeded harmonic octaves for wander motion (amps px, freqs rad/ms). */\nexport interface WanderOsc {\n ax: number[];\n fx: number[];\n phx: number[];\n ay: number[];\n fy: number[];\n phy: number[];\n}\n\n/** A seeded entity: initial state + resolved velocity. `positionAt` is a pure function\n * of this + time, so the rAF loop and renderFrame(t) produce identical results.\n * IMPORTANT (determinism/compat): fields for newer features are OPTIONAL and only\n * set when the feature is declared, so older specs snapshot byte-identically. */\nexport interface Entity {\n x0: number;\n y0: number;\n size: number;\n spriteIndex: number;\n phase: number;\n vx: number; // px/sec\n vy: number; // px/sec\n bob: number; // vertical bob / horizontal sway amplitude (px)\n motion: 'drift' | 'rise' | 'bounce' | 'static' | 'orbit' | 'wander' | 'warp' | 'path';\n headingLeft: boolean;\n alpha: number; // resolved base opacity (default 1)\n pulseAmp: number; // opacity breathing amplitude (0 = none)\n pulsePeriod: number; // ms\n pulsePhase: number;\n spinSpeed: number; // degrees/sec (0 = no rotation)\n spinPhase: number; // seeded starting angle (radians)\n growAmp: number; // size breathing amplitude as fraction (0 = none)\n growPeriod: number; // ms\n growPhase: number;\n orbitR: number; // orbit radius (px, 0 = not orbiting)\n orbitCx: number; // orbit center x (px)\n orbitCy: number; // orbit center y (px)\n colorIndex: number; // index into sprite colors[] (-1 = use sprite.color)\n cyclePeriod: number; // ms (0 = no cycling)\n /** Rect sprite second dimension (height px), or bar thickness. Only set for rect / bar sprites. */\n size2?: number;\n /** Reading-order index into `bar.values`. Only set for bar sprites. */\n barIndex?: number;\n /** Placed by a list/table layout: variants cycle from the ordered base index, in step. Only set for data layouts. */\n ordered?: true;\n /** Orbit parent layer key (motion.center = { layer }). Center resolved at render time. */\n orbitParent?: string;\n /** Present only when the layer explicitly disables edge wrapping. */\n wrapDisabled?: true;\n /** Harmonic drift params. Only set for wander motion. */\n wander?: { own: WanderOsc; shared: WanderOsc; coherence: number; margin: number };\n /** Depth-axis params. Only set for warp motion. */\n warp?: { ux: number; uy: number; z0: number; vz: number; cx: number; cy: number };\n /** Sparse-event window. Only set when `layer.emit` is declared. `phase` ms offset. */\n emit?: { every: number; life: number; phase: number; growFrom: number; growTo: number };\n /** Shared-clock time multiplier for pulse/grow/cycle. Only set when `layer.clock` is declared. */\n clockRate?: number;\n /** Shared cycle phase (radians). Only set when `layer.clock` is declared. */\n cyclePhase?: number;\n /** Velocity easing. Only set when the motion declares `ease`. */\n ease?: { type: 'settle' | 'buoyant'; tau: number };\n /** Static rotation (radians), added to any spin. Only set when `layer.rotate` is declared. */\n rotate?: number;\n /** Spline params (pts in px, shared per layer). Only set for path motion. */\n path?: {\n pts: Array<{ x: number; y: number }>;\n duration: number;\n closed: boolean;\n smooth: boolean;\n phase: number; // 0..1 offset along the path\n offX: number; // per-entity scatter (px)\n offY: number;\n };\n}\n\nexport interface Placed {\n x: number;\n y: number;\n flip: boolean;\n}\n\nexport function spriteVariants(sprite: SpriteSpec): number {\n if (sprite.kind === 'emoji') return sprite.glyphs.length;\n if (sprite.kind === 'text') return sprite.strings.length;\n return 1;\n}\n\nconst OCT_AMP = [1, 0.5, 0.25];\nconst OCT_PERIOD: Array<[number, number]> = [\n [6000, 14000],\n [3000, 7000],\n [1500, 4000],\n];\n\n/** Draw one set of 3 harmonic octaves per axis (18 rng draws). `amp` in px. */\nfunction drawOsc(rng: Rng, amp: number): WanderOsc {\n const osc: WanderOsc = { ax: [], fx: [], phx: [], ay: [], fy: [], phy: [] };\n for (let i = 0; i < 3; i++) {\n osc.ax.push(amp * OCT_AMP[i]! * rng.range(0.6, 1.4));\n osc.fx.push((2 * Math.PI) / rng.range(OCT_PERIOD[i]![0], OCT_PERIOD[i]![1]));\n osc.phx.push(rng.range(0, Math.PI * 2));\n }\n for (let i = 0; i < 3; i++) {\n osc.ay.push(amp * OCT_AMP[i]! * rng.range(0.6, 1.4));\n osc.fy.push((2 * Math.PI) / rng.range(OCT_PERIOD[i]![0], OCT_PERIOD[i]![1]));\n osc.phy.push(rng.range(0, Math.PI * 2));\n }\n return osc;\n}\n\nconst GOLDEN = 0.6180339887498949;\n\n/**\n * Per-entity sparse-event parameters. NO rng draws: the scattered offset is a\n * fixed low-discrepancy (golden-ratio) sequence over the entity index, so\n * declaring `emit` never disturbs this layer's — or any later layer's —\n * seeded stream, and the same spec times its events identically under every\n * seed (event timing is composition, like a grid, not scatter). `jitter`\n * blends an even stagger (entity i at i/n of the period — a metronome) with\n * that scattered offset.\n */\nfunction emitParams(\n emit: NonNullable<LayerSpec['emit']>,\n i: number,\n n: number,\n): NonNullable<Entity['emit']> {\n const every = emit.every;\n const jitter = Math.max(0, Math.min(1, emit.jitter ?? 1));\n const scattered = (((i + 0.5) * GOLDEN) % 1) * every;\n const even = (i / Math.max(1, n)) * every;\n const phase = ((even * (1 - jitter) + scattered * jitter) % every + every) % every;\n return {\n every,\n life: Math.min(emit.life, every),\n phase,\n growFrom: emit.grow?.[0] ?? 1,\n growTo: emit.grow?.[1] ?? 1,\n };\n}\n\n/** Weighted index pick from a single uniform draw. Weights are validated positive. */\nfunction weightedIndex(u: number, weights: number[]): number {\n const total = weights.reduce((a, b) => a + b, 0);\n let acc = 0;\n for (let i = 0; i < weights.length; i++) {\n acc += weights[i]! / total;\n if (u < acc) return i;\n }\n return weights.length - 1;\n}\n\n/** Deterministically place a layer's entities using the seeded RNG (never Math.random).\n * `scale` multiplies every dimensional draw (default 1). Used for viewport units.\n * `countScale` multiplies entity count for density-aware scaling (default 1). */\nexport function buildEntities(layer: LayerSpec, rng: Rng, w: number, h: number, scale = 1, countScale = 1): Entity[] {\n // Grid layers are EXEMPT from count scaling. A grid is an exact lattice —\n // columns × rows, authored cell by cell — and scaling its count doesn't thin\n // it like a scatter field, it TRUNCATES it row-major: the last cells simply\n // never spawn. Found live (Entablature, 2026-08-14): on a viewport at\n // countScale ≈ 0.67, an 18-column single-row grid rendered 12 cells and died\n // at two-thirds width, while the analytic perception path (countScale 1)\n // showed it full-width — a renderer-vs-perception split that burned four\n // publishes to isolate. Upscaling is equally wrong: it invents phantom cells\n // beyond the authored lattice. Grid cost is already bounded by maxPerLayer.\n const effectiveCount = countScale === 1 || layer.layout !== undefined\n ? layer.count\n : Math.max(1, Math.min(\n Math.round(layer.count * countScale),\n layer.links ? LIMITS.maxLinkLayerCount : LIMITS.maxPerLayer,\n ));\n // Defaults are authored as their 1080p-equivalent viewport fractions. Using\n // the legacy px defaults directly would multiply 20..40 by the viewport.\n const defaultSize = scale === 1\n ? [20, 40] as const\n : [20 / LIMITS.referenceViewport, 40 / LIMITS.referenceViewport] as const;\n const [smin, smax] = layer.size ?? defaultSize;\n const variants = spriteVariants(layer.sprite);\n const sprite = layer.sprite;\n const spriteColors = isShapedSprite(sprite) ? sprite.colors : undefined;\n const colorWeights = isShapedSprite(sprite) ? sprite.colorWeights : undefined;\n const colorsLen = spriteColors?.length ?? 0;\n const cycle: CycleSpec | undefined = (sprite.kind === 'emoji' || sprite.kind === 'text') ? sprite.cycle : undefined;\n\n // Layer-level draws for new motion types happen BEFORE the entity loop, guarded by\n // the motion type so pre-existing specs keep bit-identical entity streams.\n const mSpec = layer.motion;\n let sharedOsc: WanderOsc | null = null;\n let meanderPx = 0;\n if (mSpec.type === 'wander') {\n meanderPx = (mSpec.meander ?? (scale === 1 ? 60 : 0.05)) * scale;\n sharedOsc = drawOsc(rng, meanderPx);\n }\n let pathPts: Array<{ x: number; y: number }> | null = null;\n if (mSpec.type === 'path') {\n pathPts = mSpec.points.map((p) => ({ x: p.x * w, y: p.y * h }));\n }\n const ease = (mSpec.type === 'drift' || mSpec.type === 'rise' || mSpec.type === 'wander') ? mSpec.ease : undefined;\n const clockPhase = layer.clock ? ((layer.clock.phase ?? 0) % 1) * Math.PI * 2 : 0;\n\n // Grid layout geometry (pure — no draws).\n const layout = layer.layout;\n // Data layouts (list / table): reading order from an anchor, no scatter.\n const ordered = layout?.type === 'list' || layout?.type === 'table';\n let gapX = 0;\n let gapY = 0;\n let listX0 = 0;\n let listY0 = 0;\n let listCols = 1;\n if (layout?.type === 'list' || layout?.type === 'table') {\n const dflt = scale === 1 ? LIMITS.defaultListGapPx : LIMITS.defaultListGap;\n const g = layout.gap ?? dflt;\n gapX = (typeof g === 'number' ? g : g.x ?? dflt) * scale;\n gapY = (typeof g === 'number' ? g : g.y ?? dflt) * scale;\n listCols = layout.type === 'list' ? 1 : Math.max(1, Math.round(layout.columns));\n const rows = Math.max(1, Math.ceil(effectiveCount / listCols));\n if (layer.position) {\n listX0 = layer.position.x * w;\n listY0 = layer.position.y * h;\n // `dx`/`dy`: an offset in min(w,h) units (#71). Only added when set, so\n // every existing anchor is the same float it always was.\n if (layer.position.dx) listX0 += layer.position.dx * scale;\n if (layer.position.dy) listY0 += layer.position.dy * scale;\n } else {\n const [rx0, rx1] = layer.region?.x ?? [0, 1];\n const [ry0, ry1] = layer.region?.y ?? [0, 1];\n listX0 = ((rx0 + rx1) / 2) * w - ((listCols - 1) * gapX) / 2;\n listY0 = ((ry0 + ry1) / 2) * h - ((rows - 1) * gapY) / 2;\n }\n }\n let gridCols = 0;\n let cellW = 0;\n let cellH = 0;\n let gridX0 = 0;\n let gridY0 = 0;\n if (layout?.type === 'grid') {\n const [rx0, rx1] = layer.region?.x ?? [0, 1];\n const [ry0, ry1] = layer.region?.y ?? [0, 1];\n const gw = Math.max(1, (rx1 - rx0) * w);\n const gh = Math.max(1, (ry1 - ry0) * h);\n gridCols = Math.min(\n layout.columns ?? Math.max(1, Math.round(Math.sqrt(effectiveCount * (gw / gh)))),\n LIMITS.maxGridColumns,\n );\n const gridRows = Math.max(1, Math.ceil(effectiveCount / gridCols));\n cellW = gw / gridCols;\n cellH = gh / gridRows;\n gridX0 = rx0 * w;\n gridY0 = ry0 * h;\n }\n\n const out: Entity[] = [];\n for (let i = 0; i < effectiveCount; i++) {\n const size =\n sprite.kind === 'textBlock'\n ? sprite.fontSize * scale\n : sprite.kind === 'circle' || sprite.kind === 'ring' || sprite.kind === 'polygon'\n ? rng.range(sprite.radius[0], sprite.radius[1]) * 2 * scale\n : sprite.kind === 'streak' || sprite.kind === 'stroke'\n ? rng.range(sprite.length[0], sprite.length[1]) * scale\n : sprite.kind === 'rect'\n ? rng.range(sprite.width[0], sprite.width[1]) * scale\n : sprite.kind === 'bar'\n ? sprite.length * scale\n : rng.range(smin, smax) * scale;\n // Guarded extra draw: only rect sprites with an aspect range consume it.\n const size2 = sprite.kind === 'rect'\n ? size * (sprite.aspect ? rng.range(sprite.aspect[0], sprite.aspect[1]) : 1)\n : sprite.kind === 'bar'\n ? sprite.thickness * scale\n : undefined;\n\n let vx = 0;\n let vy = 0;\n let bob = 0;\n let motion: Entity['motion'] = 'drift';\n let warpParams: Entity['warp'];\n let pathPhase = 0;\n let pathOffX = 0;\n let pathOffY = 0;\n const m = layer.motion;\n if (m.type === 'static') {\n motion = 'static';\n } else if (m.type === 'drift') {\n const s = rng.range(m.speed[0], m.speed[1]) * scale;\n let angle = ((m.angle ?? 0) * Math.PI) / 180;\n if (m.bidirectional && rng.next() < 0.5) angle = Math.PI - angle;\n vx = s * Math.cos(angle);\n vy = s * Math.sin(angle);\n bob = (m.bob ?? 0) * scale;\n } else if (m.type === 'rise') {\n motion = 'rise';\n vy = -rng.range(m.speed[0], m.speed[1]) * scale; // upward\n bob = (m.sway ?? 0) * scale;\n } else if (m.type === 'bounce') {\n motion = 'bounce';\n const s = rng.range(m.speed[0], m.speed[1]) * scale;\n const a = rng.range(0, Math.PI * 2);\n vx = s * Math.cos(a);\n vy = s * Math.sin(a);\n } else if (m.type === 'orbit') {\n motion = 'orbit';\n vx = rng.range(m.speed[0], m.speed[1]); // angular speed in deg/sec, stored in vx (not scaled)\n } else if (m.type === 'wander') {\n motion = 'wander';\n const s = rng.range(m.speed[0], m.speed[1]) * scale;\n const heading = m.angle !== undefined ? (m.angle * Math.PI) / 180 : rng.range(0, Math.PI * 2);\n vx = s * Math.cos(heading);\n vy = s * Math.sin(heading);\n } else if (m.type === 'warp') {\n motion = 'warp';\n const vz = rng.range(m.speed[0], m.speed[1]); // depth-units/sec (not scaled)\n const theta = rng.range(0, Math.PI * 2);\n const r = rng.range(0.15, 1); // radial offset in the projection plane\n warpParams = {\n ux: Math.cos(theta) * r,\n uy: Math.sin(theta) * r,\n z0: rng.range(WARP_NEAR, 1),\n vz,\n cx: (m.center?.x ?? 0.5) * w,\n cy: (m.center?.y ?? 0.5) * h,\n };\n } else if (m.type === 'path') {\n motion = 'path';\n pathPhase = rng.next();\n if (m.scatter) {\n pathOffX = rng.range(-1, 1) * m.scatter * scale;\n pathOffY = rng.range(-1, 1) * m.scatter * scale;\n }\n }\n\n let x0: number;\n let y0: number;\n if (layer.position && layer.count === 1) {\n x0 = layer.position.x * w;\n y0 = layer.position.y * h;\n if (layer.position.dx) x0 += layer.position.dx * scale;\n if (layer.position.dy) y0 += layer.position.dy * scale;\n } else if (layout?.type === 'list' || layout?.type === 'table') {\n // Reading order from the anchor. Burn the two scatter draws so toggling a\n // data layout on or off leaves the rest of this layer's stream intact.\n rng.next();\n rng.next();\n x0 = listX0 + (i % listCols) * gapX;\n y0 = listY0 + Math.floor(i / listCols) * gapY;\n } else if (layout?.type === 'grid') {\n // Grid cells row-major; same 2-draw budget as scatter so toggling layout\n // shifts only THIS layer's stream (layout is structural — rebuild anyway).\n const col = i % gridCols;\n const row = Math.floor(i / gridCols);\n const j = layout.jitter ?? 0;\n const jx = typeof j === 'number' ? j : j.x ?? 0;\n const jy = typeof j === 'number' ? j : j.y ?? 0;\n x0 = gridX0 + (col + 0.5) * cellW + rng.range(-0.5, 0.5) * jx * cellW;\n y0 = gridY0 + (row + 0.5) * cellH + rng.range(-0.5, 0.5) * jy * cellH;\n } else {\n // Spawn window defaults to the full viewport. IMPORTANT (determinism/compat):\n // optional features must only consume EXTRA rng draws when declared, so specs\n // written before a feature existed keep bit-identical entity streams.\n const [rx0, rx1] = layer.region?.x ?? [0, 1];\n const [ry0, ry1] = layer.region?.y ?? [0, 1];\n x0 = rng.range(rx0 * w, rx1 * w);\n y0 = rng.range(ry0 * h, ry1 * h);\n }\n\n const orbitParent = m.type === 'orbit' && m.center && 'layer' in m.center ? m.center.layer : undefined;\n\n out.push({\n x0,\n y0,\n size,\n // Data layouts read variants in order — strings[i] beside bar i. The\n // seeded draw is still consumed so a layout is placement only: toggling\n // list/table never disturbs the layer's alpha, pulse or spin stream.\n spriteIndex: variants > 1 ? (ordered ? (rng.int(0, variants - 1), i % variants) : rng.int(0, variants - 1)) : 0,\n phase: rng.range(0, Math.PI * 2),\n vx,\n vy,\n bob,\n motion,\n headingLeft: vx < 0,\n alpha: layer.alpha ? rng.range(layer.alpha[0], layer.alpha[1]) : 1,\n pulseAmp: layer.pulse?.amp ?? 0,\n pulsePeriod: layer.pulse?.period ?? 1000,\n pulsePhase: layer.pulse ? rng.range(0, Math.PI * 2) : 0,\n // New draws AFTER pulsePhase — guarded so existing specs keep identical streams.\n // Scalar spin: no draw here, one phase draw below (unchanged). Range spin\n // (new): one seeded speed draw here, then the phase draw — array form is new\n // so the extra draw can't perturb any existing spec's entity stream.\n spinSpeed:\n typeof layer.spin === 'number'\n ? (layer.spin * Math.PI) / 180 // deg/sec → rad/sec\n : Array.isArray(layer.spin)\n ? (rng.range(layer.spin[0], layer.spin[1]) * Math.PI) / 180\n : 0,\n spinPhase: layer.spin ? rng.range(0, Math.PI * 2) : 0,\n growAmp: layer.grow?.amp ?? 0,\n growPeriod: layer.grow?.period ?? 1000,\n growPhase: layer.grow ? rng.range(0, Math.PI * 2) : 0,\n orbitR: m.type === 'orbit' ? rng.range(m.radius[0], m.radius[1]) * scale : 0,\n orbitCx: m.type === 'orbit' && !orbitParent ? ((m.center as { x?: number } | undefined)?.x ?? 0.5) * w : 0,\n orbitCy: m.type === 'orbit' && !orbitParent ? ((m.center as { y?: number } | undefined)?.y ?? 0.5) * h : 0,\n // New draws AFTER orbit — guarded so existing specs keep identical streams.\n colorIndex: colorsLen > 0\n ? (colorWeights && colorWeights.length === colorsLen\n ? weightedIndex(rng.next(), colorWeights)\n : ordered\n ? (rng.int(0, colorsLen - 1), i % colorsLen) // data layouts: palette in reading order; draw burned for stream parity\n : rng.int(0, colorsLen - 1))\n : -1,\n cyclePeriod: cycle ? cycle.period : 0,\n // Optional feature fields last (guarded draws inside — wander draws 18 here).\n ...(size2 !== undefined ? { size2 } : {}),\n ...(sprite.kind === 'bar' ? { barIndex: i } : {}),\n ...(ordered ? { ordered: true as const } : {}),\n ...(orbitParent ? { orbitParent } : {}),\n ...(layer.wrap === false ? { wrapDisabled: true as const } : {}),\n ...(m.type === 'wander'\n ? {\n wander: {\n own: drawOsc(rng, meanderPx),\n shared: sharedOsc!,\n coherence: Math.max(0, Math.min(1, m.coherence ?? 0)),\n margin: meanderPx * (OCT_AMP[0]! + OCT_AMP[1]! + OCT_AMP[2]!) * 1.4,\n },\n }\n : {}),\n ...(warpParams ? { warp: warpParams } : {}),\n ...(m.type === 'path' && pathPts\n ? {\n path: {\n pts: pathPts,\n duration: m.duration,\n closed: m.closed !== false,\n smooth: m.curve !== 'linear',\n phase: pathPhase,\n offX: pathOffX,\n offY: pathOffY,\n },\n }\n : {}),\n // Time-structure fields (2026-09): ease draws nothing; emit's one draw\n // per entity happens in a pass AFTER this loop (see below).\n ...(ease ? { ease: { type: ease.type, tau: ease.tau } } : {}),\n // Static rotation (2026-09-10): a scalar draws nothing; the range form\n // draws one value here, last, only when declared.\n ...(typeof layer.rotate === 'number'\n ? { rotate: (layer.rotate * Math.PI) / 180 }\n : Array.isArray(layer.rotate)\n ? { rotate: (rng.range(layer.rotate[0], layer.rotate[1]) * Math.PI) / 180 }\n : {}),\n });\n\n if (layer.clock) {\n // Phase-lock: the seeded pulse/grow phases were drawn above (stream\n // stays put); the shared phase replaces them here. Cycle gets its own\n // field — `phase` also drives bob/sway/orbit, which must stay per-entity.\n const ent = out[out.length - 1]!;\n ent.pulsePhase = clockPhase;\n ent.growPhase = clockPhase;\n ent.cyclePhase = clockPhase;\n ent.clockRate = layer.clock.rate ?? 1;\n }\n if (layer.pulse?.wave) {\n // Position-derived phase: sin(ωt + phase) becomes a traveling wave along\n // `angle`. Patched AFTER the push so the seeded pulsePhase draw stays in its\n // historical stream position (toggling wave must not shift other draws).\n // A clock's phase offsets the wave rather than flattening it.\n const wl = Math.max(1e-6, layer.pulse.wave.wavelength * scale);\n const ang = ((layer.pulse.wave.angle ?? 0) * Math.PI) / 180;\n out[out.length - 1]!.pulsePhase = clockPhase - ((x0 * Math.cos(ang) + y0 * Math.sin(ang)) / wl) * Math.PI * 2;\n }\n }\n if (layer.emit) {\n // Assigned after the loop and without any rng draw (see emitParams), so\n // toggling `emit` rearranges nothing — not this layer, not the ones after.\n for (let i = 0; i < out.length; i++) out[i]!.emit = emitParams(layer.emit, i, out.length);\n }\n return out;\n}\n\n/** Depth of a warp entity at time t: wraps from far (1) to near (WARP_NEAR). Pure. */\nfunction warpZ(e: Entity, t: number): number {\n const wp = e.warp!;\n return wrap(wp.z0 - wp.vz * (t / 1000), WARP_NEAR, 1);\n}\n\nfunction smoothstep(x: number): number {\n const c = x < 0 ? 0 : x > 1 ? 1 : x;\n return c * c * (3 - 2 * c);\n}\n\n/** Fraction of an emit window spent fading in; the rest fades out. */\nconst EMIT_ATTACK = 0.25;\n\n/**\n * Where entity `e` sits in its current emit window at time `t`: 0..1 across\n * the visible `life` ms, or null while dark (or when the layer has no `emit`).\n * Pure — the window index is `floor((t - phase) / every)`, no state.\n */\nexport function emitWindow(e: Entity, t: number): number | null {\n const em = e.emit;\n if (!em) return null;\n const local = (((t - em.phase) % em.every) + em.every) % em.every;\n return local < em.life ? local / em.life : null;\n}\n\n/** Alpha envelope across an emit window: fast smooth attack, slow smooth decay. */\nexport function emitEnvelope(u: number): number {\n if (u < 0 || u >= 1) return 0;\n return u < EMIT_ATTACK ? smoothstep(u / EMIT_ATTACK) : 1 - smoothstep((u - EMIT_ATTACK) / (1 - EMIT_ATTACK));\n}\n\n/** Scene time as the layer's clock sees it (pulse/grow/cycle only). */\nfunction clockTime(e: Entity, t: number): number {\n return e.clockRate ? t * e.clockRate : t;\n}\n\n/**\n * Seconds of travel at time `t` for the velocity-integral motions. Identity\n * without `ease`. `settle`: τ(1 − e^(−t/τ)) — decelerates to rest having\n * travelled speed·τ. `buoyant`: t − τ(1 − e^(−t/τ)) — from rest to terminal\n * speed. With `emit`, t is window-local so every event restarts the travel.\n */\nfunction motionSeconds(e: Entity, t: number): number {\n if (!e.ease) return t / 1000;\n let tl = t;\n if (e.emit) tl = (((t - e.emit.phase) % e.emit.every) + e.emit.every) % e.emit.every;\n const tau = e.ease.tau;\n const k = 1 - Math.exp(-tl / tau);\n return (e.ease.type === 'settle' ? tau * k : tl - tau * k) / 1000;\n}\n\n/** Analytic opacity of an entity at logical time `t` (ms). Pure, clamped to 0..1. */\nexport function alphaAt(e: Entity, t: number): number {\n let a = e.alpha;\n if (e.pulseAmp) a = e.alpha + e.pulseAmp * Math.sin((clockTime(e, t) * 2 * Math.PI) / e.pulsePeriod + e.pulsePhase);\n if (e.motion === 'warp') {\n // Fade in over the first 20% of depth after respawning at the far plane,\n // masking the wrap pop-in.\n const z = warpZ(e, t);\n a *= Math.max(0, Math.min(1, (1 - z) / 0.2));\n }\n if (e.emit) {\n const u = emitWindow(e, t);\n a = u === null ? 0 : a * emitEnvelope(u);\n }\n return a < 0 ? 0 : a > 1 ? 1 : a;\n}\n\n/** Analytic size multiplier at time `t` (ms). Pure, clamped to > 0. */\nexport function sizeAt(e: Entity, t: number): number {\n let s = e.size;\n if (e.growAmp) s = e.size * (1 + e.growAmp * Math.sin((clockTime(e, t) * 2 * Math.PI) / e.growPeriod + e.growPhase));\n if (e.motion === 'warp') s *= Math.min(1 / warpZ(e, t), WARP_MAX_SCALE);\n if (e.emit && (e.emit.growFrom !== 1 || e.emit.growTo !== 1)) {\n const u = emitWindow(e, t);\n if (u !== null) s *= e.emit.growFrom + (e.emit.growTo - e.emit.growFrom) * u;\n }\n return s > 0 ? s : 0.1;\n}\n\n/**\n * Analytic rotation angle at time `t` (ms) in radians. Pure. A static\n * `rotate` is the base; a spinning entity adds its seeded start angle and\n * speed × t on top. With neither, 0 — and with `spin: [0, 0]` also 0: a zero\n * spin speed never rotates, so its seeded phase is not applied (that is what\n * `rotate` is for).\n */\nexport function rotationAt(e: Entity, t: number): number {\n const base = e.rotate ?? 0;\n if (!e.spinSpeed) return base;\n return base + e.spinPhase + e.spinSpeed * (t / 1000);\n}\n\n/** Layer lifecycle alpha multiplier at time `t` (ms). Pure. 1 when `life` is unset. */\nexport function lifeAlphaAt(life: { enter?: number; exit?: number; fade?: number } | undefined, t: number): number {\n if (!life) return 1;\n const fade = life.fade ?? 1000;\n let a = 1;\n if (life.enter !== undefined) {\n if (t < life.enter) return 0;\n a = fade > 0 ? Math.min(1, (t - life.enter) / fade) : 1;\n }\n if (life.exit !== undefined && t >= life.exit) {\n a *= fade > 0 ? Math.max(0, 1 - (t - life.exit) / fade) : 0;\n }\n return a;\n}\n\nfunction wrap(v: number, min: number, max: number): number {\n const range = max - min;\n return ((((v - min) % range) + range) % range) + min;\n}\n\nfunction reflect(v: number, min: number, max: number): number {\n const range = max - min;\n if (range <= 0) return min;\n const period = 2 * range;\n const p = (((v - min) % period) + period) % period;\n return min + (p < range ? p : period - p);\n}\n\nfunction catmullRom(p0: number, p1: number, p2: number, p3: number, u: number): number {\n const u2 = u * u;\n const u3 = u2 * u;\n return 0.5 * (2 * p1 + (-p0 + p2) * u + (2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 + (-p0 + 3 * p1 - 3 * p2 + p3) * u3);\n}\n\nfunction pathPosition(e: Entity, t: number): { x: number; y: number } {\n const p = e.path!;\n const n = p.pts.length;\n let s = ((t / p.duration) + p.phase) % 1;\n if (s < 0) s += 1;\n if (!p.closed) {\n // Ping-pong so open paths reverse smoothly instead of teleporting.\n const pp = s * 2;\n s = pp < 1 ? pp : 2 - pp;\n }\n const segs = p.closed ? n : n - 1;\n const u = Math.min(s * segs, segs - 1e-9);\n const i = Math.floor(u);\n const local = u - i;\n const at = (k: number): { x: number; y: number } =>\n p.closed ? p.pts[((k % n) + n) % n]! : p.pts[Math.max(0, Math.min(n - 1, k))]!;\n const p1 = at(i);\n const p2 = at(i + 1);\n if (!p.smooth) {\n return {\n x: p1.x + (p2.x - p1.x) * local + p.offX,\n y: p1.y + (p2.y - p1.y) * local + p.offY,\n };\n }\n const p0 = at(i - 1);\n const p3 = at(i + 2);\n return {\n x: catmullRom(p0.x, p1.x, p2.x, p3.x, local) + p.offX,\n y: catmullRom(p0.y, p1.y, p2.y, p3.y, local) + p.offY,\n };\n}\n\n/** Analytic position of an entity at logical time `t` (ms). Pure & deterministic. */\nexport function positionAt(e: Entity, t: number, w: number, h: number): Placed {\n if (e.motion === 'static') return { x: e.x0, y: e.y0, flip: false };\n if (e.motion === 'orbit') {\n const angle = e.phase + (e.vx * Math.PI / 180) * (t / 1000);\n return {\n x: e.orbitCx + e.orbitR * Math.cos(angle),\n y: e.orbitCy + e.orbitR * Math.sin(angle),\n flip: false,\n };\n }\n if (e.motion === 'warp') {\n const wp = e.warp!;\n const persp = 1 / warpZ(e, t);\n const halfMin = Math.min(w, h) / 2;\n return {\n x: wp.cx + wp.ux * halfMin * persp,\n y: wp.cy + wp.uy * halfMin * persp,\n flip: false,\n };\n }\n if (e.motion === 'path') {\n const pos = pathPosition(e, t);\n return { x: pos.x, y: pos.y, flip: false };\n }\n const dt = motionSeconds(e, t);\n const m = e.size;\n if (e.motion === 'bounce') {\n return {\n x: reflect(e.x0 + e.vx * dt, m / 2, w - m / 2),\n y: reflect(e.y0 + e.vy * dt, m / 2, h - m / 2),\n flip: false,\n };\n }\n if (e.motion === 'rise') {\n const y = e.y0 + e.vy * dt;\n return {\n x: e.x0 + (e.bob ? e.bob * Math.sin(t / 700 + e.phase) : 0),\n y: e.wrapDisabled ? y : wrap(y, -m, h + m),\n flip: false,\n };\n }\n if (e.motion === 'wander') {\n const wp = e.wander!;\n const c = wp.coherence;\n let hx = 0;\n let hy = 0;\n for (let i = 0; i < 3; i++) {\n if (c < 1) {\n hx += (1 - c) * wp.own.ax[i]! * Math.sin(wp.own.fx[i]! * t + wp.own.phx[i]!);\n hy += (1 - c) * wp.own.ay[i]! * Math.sin(wp.own.fy[i]! * t + wp.own.phy[i]!);\n }\n if (c > 0) {\n hx += c * wp.shared.ax[i]! * Math.sin(wp.shared.fx[i]! * t + wp.shared.phx[i]!);\n hy += c * wp.shared.ay[i]! * Math.sin(wp.shared.fy[i]! * t + wp.shared.phy[i]!);\n }\n }\n const margin = m + wp.margin;\n const x = e.x0 + e.vx * dt + hx;\n const y = e.y0 + e.vy * dt + hy;\n return {\n x: e.wrapDisabled ? x : wrap(x, -margin, w + margin),\n y: e.wrapDisabled ? y : wrap(y, -margin, h + margin),\n flip: e.headingLeft,\n };\n }\n // drift\n const rawX = e.x0 + e.vx * dt;\n const x = e.wrapDisabled ? rawX : wrap(rawX, -m, w + m);\n const rawY = e.y0 + e.vy * dt;\n let y = e.vy !== 0 && !e.wrapDisabled ? wrap(rawY, -m, h + m) : rawY;\n if (e.bob) y += e.bob * Math.sin(t / 500 + e.phase);\n return { x, y, flip: e.headingLeft };\n}\n\n/**\n * Analytic heading (radians) at time `t`, from a finite difference of positionAt.\n * Used to orient streak sprites. Returns null across a wrap seam (position jump\n * larger than half the viewport) — callers should skip orientation that frame.\n */\nexport function headingAt(e: Entity, t: number, w: number, h: number): number | null {\n const dtMs = 32;\n const t1 = t < dtMs ? t + dtMs : t;\n const t0 = t1 - dtMs;\n const a = positionAt(e, t0, w, h);\n const b = positionAt(e, t1, w, h);\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n if (Math.abs(dx) > w / 2 || Math.abs(dy) > h / 2) return null;\n if (dx === 0 && dy === 0) return null;\n return Math.atan2(dy, dx);\n}\n\n/** Time-varying sprite index for text/emoji cycling. Returns static index when cyclePeriod is 0. */\nexport function spriteIndexAt(e: Entity, t: number, variants: number): number {\n if (!e.cyclePeriod || variants <= 1) return e.spriteIndex;\n // Under a data layout the rows keep their reading order and advance in\n // step — a marquee — instead of each entity cycling from its own phase.\n if (e.ordered) return (e.spriteIndex + Math.floor(clockTime(e, t) / e.cyclePeriod)) % variants;\n return Math.floor(clockTime(e, t) / e.cyclePeriod + (e.cyclePhase ?? e.phase) / (2 * Math.PI)) % variants;\n}\n\n/** An inter-entity link edge with its (wrap-aware) distance, for falloff alpha. */\nexport interface LinkEdge {\n i: number;\n j: number;\n dist: number;\n}\n\nfunction wrapDist(\n pi: { x: number; y: number },\n pj: { x: number; y: number },\n doWrap: boolean,\n w: number,\n h: number,\n): number {\n let dx = pj.x - pi.x;\n let dy = pj.y - pi.y;\n if (doWrap) {\n if (Math.abs(dx) > w / 2) dx = dx > 0 ? dx - w : dx + w;\n if (Math.abs(dy) > h / 2) dy = dy > 0 ? dy - h : dy + h;\n }\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n/**\n * `links.maxDist` in px at `scale` (px per spec unit), or `Infinity` when it is\n * absent — a chain needs no cutoff. Callers apply `falloff` only to a finite\n * value, so an absent `maxDist` can never put NaN into an alpha.\n */\nexport function linkMaxDistPx(links: { maxDist?: number }, scale: number): number {\n return links.maxDist === undefined ? Infinity : links.maxDist * scale;\n}\n\n/**\n * Edge list for a layer's `links`, dispatching on mode:\n * 'nearest' (default) k-nearest within maxDist; 'chain' sequential order\n * (Mystify — ignores k/maxDist, `closed` joins last to first); 'random' a fixed\n * golden-ratio-stride wiring filtered by maxDist (deterministic, no RNG draws).\n * An absent `k` reads as 1 and an absent `maxDist` (`Infinity` from\n * `linkMaxDistPx`) as no cutoff; the validator requires both outside chain mode.\n */\nexport function linkEdges(\n links: { k?: number; maxDist?: number; mode?: 'nearest' | 'chain' | 'random'; closed?: boolean },\n positions: Array<{ x: number; y: number }>,\n maxDistPx: number,\n doWrap: boolean,\n w: number,\n h: number,\n): LinkEdge[] {\n const n = positions.length;\n const mode = links.mode ?? 'nearest';\n const k = links.k ?? 1;\n if (mode === 'chain') {\n const out: LinkEdge[] = [];\n for (let i = 0; i < n - 1; i++) {\n out.push({ i, j: i + 1, dist: wrapDist(positions[i]!, positions[i + 1]!, doWrap, w, h) });\n }\n if (links.closed && n > 2) out.push({ i: n - 1, j: 0, dist: wrapDist(positions[n - 1]!, positions[0]!, doWrap, w, h) });\n return out;\n }\n if (mode === 'random') {\n const stride = Math.max(1, Math.round(n * 0.381966)); // golden-ratio conjugate — spreads partners\n const edges = new Set<string>();\n const out: LinkEdge[] = [];\n for (let i = 0; i < n; i++) {\n for (let mIdx = 1; mIdx <= k; mIdx++) {\n const j = (i + mIdx * stride) % n;\n if (j === i) continue;\n const dist = wrapDist(positions[i]!, positions[j]!, doWrap, w, h);\n if (dist > maxDistPx) continue;\n const key = `${Math.min(i, j)}:${Math.max(i, j)}`;\n if (!edges.has(key)) {\n edges.add(key);\n out.push({ i: Math.min(i, j), j: Math.max(i, j), dist });\n }\n }\n }\n return out;\n }\n return linkPairs(positions, k, maxDistPx, doWrap, w, h).map(([i, j]) => ({\n i,\n j,\n dist: wrapDist(positions[i]!, positions[j]!, doWrap, w, h),\n }));\n}\n\n/** K-nearest-neighbor edge list. Deterministic tie-break: (dist, index).\n * When `doWrap` is true, uses toroidal distance so links don't streak across wrap seams. */\nexport function linkPairs(\n positions: Array<{ x: number; y: number }>,\n k: number,\n maxDist: number,\n doWrap: boolean,\n w: number,\n h: number,\n): Array<[number, number]> {\n const n = positions.length;\n const edges = new Set<string>();\n const out: Array<[number, number]> = [];\n\n for (let i = 0; i < n; i++) {\n const pi = positions[i]!;\n const neighbors: Array<{ dist: number; j: number }> = [];\n for (let j = 0; j < n; j++) {\n if (i === j) continue;\n const pj = positions[j]!;\n let dx = pj.x - pi.x;\n let dy = pj.y - pi.y;\n if (doWrap) {\n if (Math.abs(dx) > w / 2) dx = dx > 0 ? dx - w : dx + w;\n if (Math.abs(dy) > h / 2) dy = dy > 0 ? dy - h : dy + h;\n }\n const dist = Math.sqrt(dx * dx + dy * dy);\n if (dist <= maxDist) neighbors.push({ dist, j });\n }\n neighbors.sort((a, b) => a.dist - b.dist || a.j - b.j);\n for (let ni = 0; ni < Math.min(k, neighbors.length); ni++) {\n const j = neighbors[ni]!.j;\n const lo = Math.min(i, j);\n const hi = Math.max(i, j);\n const key = `${lo}:${hi}`;\n if (!edges.has(key)) {\n edges.add(key);\n out.push([lo, hi]);\n }\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Deterministic text-block line breaking\n// ---------------------------------------------------------------------------\n\nconst CHAR_NARROW = new Set('iIljtf1!|.,;:\\'\"()[]{}');\nconst CHAR_WIDE = new Set('mwMWGOQD@%');\n\n/**\n * Which advance table the line-breaker uses. `proportional` is the\n * character-class table below (the default, and the only table until\n * `textBlock.font` existed); `mono` is a uniform 0.6 em advance — the classic\n * monospace cell (Courier, Menlo, SF Mono all sit within a percent of it).\n */\nexport type TextMetricsClass = 'proportional' | 'mono';\n\nconst MONO_FAMILY_RE = /\\b(?:ui-)?mono(?:space)?\\b|courier|menlo|monaco|sfmono|consolas|inconsolata|fira\\s*code|source\\s*code|jetbrains|ibm\\s*plex\\s*mono|roboto\\s*mono/i;\n\n/**\n * Metrics class for a `textBlock.font` string: `mono` when the family names\n * a monospace face (the generic `monospace`, or a well-known fixed-pitch\n * family), else `proportional`. Absent font ⇒ proportional, as before.\n */\nexport function textMetricsClassFor(font?: string): TextMetricsClass {\n return font && MONO_FAMILY_RE.test(font) ? 'mono' : 'proportional';\n}\n\nconst MONO_ADVANCE_EM = 0.6;\n\n/**\n * Approximate glyph width as a fraction of em. Uses character-class buckets\n * so line breaks are identical across platforms (no measureText). The average\n * across Latin text lands near 0.55, close to perceive.ts's 0.62 heuristic\n * but with per-class refinement. Under `mono` every glyph (space included)\n * advances the same cell.\n */\nfunction charWidthEm(ch: string, metrics: TextMetricsClass = 'proportional'): number {\n if (metrics === 'mono') return MONO_ADVANCE_EM;\n if (ch === ' ' || ch === '\\t') return 0.3;\n if (CHAR_NARROW.has(ch)) return 0.35;\n if (CHAR_WIDE.has(ch)) return 0.72;\n return 0.55;\n}\n\n/**\n * Em-width of a string under the same character-class table `breakTextBlock`\n * uses. `mono` counts grapheme clusters, not UTF-16 code units — an emoji or\n * combining/ZWJ sequence is one advance-width cell, matching what's painted,\n * not one cell per surrogate half or combining mark.\n */\nexport function textWidthEm(str: string, metrics: TextMetricsClass = 'proportional'): number {\n if (metrics === 'mono') return graphemeClusters(str).length * MONO_ADVANCE_EM;\n let w = 0;\n for (let i = 0; i < str.length; i++) w += charWidthEm(str[i]!, metrics);\n return w;\n}\n\nexport interface TextBlockLine {\n text: string;\n widthEm: number;\n}\n\n/**\n * Break `text` into lines that fit within `maxWidthEm` em-widths. Splits on\n * whitespace; a single word wider than the limit gets its own line unbroken.\n * Explicit `\\n` always forces a break. Pure, deterministic, no canvas needed.\n */\nexport function breakTextBlock(text: string, maxWidthEm: number, metrics: TextMetricsClass = 'proportional'): TextBlockLine[] {\n const paragraphs = text.split('\\n');\n const lines: TextBlockLine[] = [];\n\n for (const para of paragraphs) {\n if (para.length === 0) {\n lines.push({ text: '', widthEm: 0 });\n continue;\n }\n const words = para.split(/\\s+/).filter((w) => w.length > 0);\n if (words.length === 0) {\n lines.push({ text: '', widthEm: 0 });\n continue;\n }\n\n let lineText = words[0]!;\n let lineW = textWidthEm(lineText, metrics);\n const spaceW = charWidthEm(' ', metrics);\n\n for (let i = 1; i < words.length; i++) {\n const word = words[i]!;\n const wordW = textWidthEm(word, metrics);\n if (lineW + spaceW + wordW <= maxWidthEm) {\n lineText += ' ' + word;\n lineW += spaceW + wordW;\n } else {\n lines.push({ text: lineText, widthEm: lineW });\n lineText = word;\n lineW = wordW;\n }\n }\n lines.push({ text: lineText, widthEm: lineW });\n }\n\n return lines;\n}\n\n/**\n * Where an anchored textBlock's layout origin sits relative to `position`:\n * the (dx, dy) to ADD to `position` so that the named point of the rendered\n * text lands on it. The rendered box is the widest line wide (placed inside\n * the `maxWidth` box by `align`) and `lines × lineHeight` tall — so `anchor`\n * says where the block sits and `align` only shapes its ragged edge. Absent\n * anchor ⇒ (0, 0): `position` stays the layout box's top-left, exactly as\n * before the field existed. Renderer, perception and advisories all call\n * this, so their boxes agree by construction.\n */\nexport function textBlockAnchorOffset(\n s: { anchor?: TextBlockAnchor; align?: 'left' | 'center' | 'right' },\n maxWPx: number,\n maxLineW: number,\n totalH: number,\n): { dx: number; dy: number } {\n if (!s.anchor) return { dx: 0, dy: 0 };\n const ax = s.anchor.endsWith('left') ? 0 : s.anchor.endsWith('right') ? 1 : 0.5;\n const ay = s.anchor.startsWith('top') ? 0 : s.anchor.startsWith('bottom') ? 1 : 0.5;\n // Ink left edge relative to the layout origin, as `align` places it.\n const inkX0 = s.align === 'center' ? (maxWPx - maxLineW) / 2 : s.align === 'right' ? maxWPx - maxLineW : 0;\n return { dx: -(inkX0 + ax * maxLineW), dy: -(ay * totalH) };\n}\n\n// ---------------------------------------------------------------------------\n// Deterministic text reveal (textBlock `reveal` — typing/deleting)\n// ---------------------------------------------------------------------------\n\n// Combining/attaching code points that must never be painted without their\n// base: combining diacritics, variation selectors, skin-tone modifiers,\n// keycap. Deliberately a fixed table rather than Intl.Segmenter, which is\n// not required to segment identically across engines — same philosophy (and\n// same determinism reason) as the charWidthEm buckets above.\nfunction isClusterExtend(cp: number): boolean {\n return (\n (cp >= 0x0300 && cp <= 0x036f) || // combining diacritics\n (cp >= 0x1ab0 && cp <= 0x1aff) ||\n (cp >= 0x20d0 && cp <= 0x20ff) ||\n (cp >= 0xfe00 && cp <= 0xfe0f) || // variation selectors\n (cp >= 0x1f3fb && cp <= 0x1f3ff) || // skin tones\n cp === 0x20e3 // combining enclosing keycap\n );\n}\n\nfunction isRegionalIndicator(cp: number): boolean {\n return cp >= 0x1f1e6 && cp <= 0x1f1ff;\n}\n\nconst ZWJ = 0x200d;\n\n/**\n * Split a string into paint-safe grapheme clusters: surrogate pairs stay\n * whole, combining marks / variation selectors / skin tones attach to their\n * base, ZWJ joins sequences (emoji families), regional indicators pair up\n * (flags). Deterministic across engines by construction.\n */\nexport function graphemeClusters(text: string): string[] {\n const out: string[] = [];\n let i = 0;\n while (i < text.length) {\n const cp = text.codePointAt(i)!;\n let end = i + (cp > 0xffff ? 2 : 1);\n // Flag pair: two regional indicators form one cluster.\n if (isRegionalIndicator(cp) && end < text.length) {\n const next = text.codePointAt(end)!;\n if (isRegionalIndicator(next)) end += next > 0xffff ? 2 : 1;\n }\n // Attach extenders and ZWJ-joined sequences.\n while (end < text.length) {\n const next = text.codePointAt(end)!;\n if (isClusterExtend(next)) {\n end += next > 0xffff ? 2 : 1;\n } else if (next === ZWJ && end + 1 < text.length) {\n const after = text.codePointAt(end + 1)!;\n end += 1 + (after > 0xffff ? 2 : 1);\n } else {\n break;\n }\n }\n out.push(text.slice(i, end));\n i = end;\n }\n return out;\n}\n\nexport interface TextRevealInput {\n progress?: number;\n mode?: 'typewriter' | 'word' | 'line' | 'glyphFade';\n speed?: number;\n fade?: number;\n}\n\nexport interface RevealState {\n /** Effective 0..1 progress after combining authored progress and speed at t. */\n progress: number;\n /** Number of fully visible lines. */\n fullLines: number;\n /** Grapheme-safe visible prefix of the next line ('' when none). */\n partialText: string;\n /** Caret anchor: line index and the visible prefix on that line. */\n caretLine: number;\n caretPrefix: string;\n /**\n * `glyphFade` mode only: per-line per-grapheme alpha (0..1), indexed\n * parallel to `graphemeClusters(lines[i].text)`. Alphas only decrease in\n * reading order, so a renderer may stop at the first zero.\n */\n glyphAlphas?: number[][];\n}\n\n/**\n * Resolve which glyphs of a broken textBlock are visible at time `tMs`.\n * Pure function of (lines, reveal, tMs) — the renderer paints exactly this,\n * and perceive models exactly this, so agents and pixels agree. `speed` is\n * graphemes/sec regardless of mode; mode only quantizes the frontier.\n */\nexport function revealState(lines: TextBlockLine[], reveal: TextRevealInput, tMs: number): RevealState {\n const lineClusters = lines.map((l) => graphemeClusters(l.text));\n const totalGraphemes = lineClusters.reduce((n, c) => n + c.length, 0);\n\n const authored = Math.max(0, Math.min(1, reveal.progress ?? 1));\n const speed = reveal.speed ?? 0;\n const timed = speed > 0 && totalGraphemes > 0 ? Math.min(1, (speed * tMs) / 1000 / totalGraphemes) : 1;\n const progress = Math.min(authored, timed);\n\n const mode = reveal.mode ?? 'typewriter';\n let fullLines = 0;\n let partialText = '';\n\n // glyphFade: glyph g starts fading at (g/total)·(1−fade) and ramps to\n // opaque over a `fade`-wide window of progress, so every glyph is 0 at\n // progress 0 and 1 at progress 1. The frontier below (shared with\n // typewriter) still anchors the caret. Pure paint, like everything here.\n let glyphAlphas: number[][] | undefined;\n if (mode === 'glyphFade') {\n // The 0.01 floor is defensive only — validation already enforces the\n // public contract fade ∈ (0, 1] (FORMAT.md). It exists so direct callers\n // that skip validateSpec can't make the divide below infinite, not to\n // remap legal values: anything ≥ 0.01 passes through untouched.\n const f = Math.min(1, Math.max(0.01, reveal.fade ?? 0.15));\n let g = 0;\n glyphAlphas = lineClusters.map((clusters) =>\n clusters.map(() => {\n const start = totalGraphemes > 0 ? (g++ / totalGraphemes) * (1 - f) : 0;\n return Math.max(0, Math.min(1, (progress - start) / f));\n }),\n );\n }\n\n if (mode === 'line') {\n fullLines = Math.round(progress * lines.length);\n } else if (mode === 'word') {\n const lineWords = lines.map((l) => (l.text.length === 0 ? [] : l.text.split(' ')));\n const totalWords = lineWords.reduce((n, ws) => n + ws.length, 0);\n let remaining = Math.round(progress * totalWords);\n for (const ws of lineWords) {\n if (remaining >= ws.length) {\n remaining -= ws.length;\n fullLines++;\n // A zero-word (empty) line is \"full\" for free; keep consuming.\n continue;\n }\n if (remaining > 0) partialText = ws.slice(0, remaining).join(' ');\n break;\n }\n } else {\n let remaining = Math.round(progress * totalGraphemes);\n for (const clusters of lineClusters) {\n if (remaining >= clusters.length) {\n remaining -= clusters.length;\n fullLines++;\n continue;\n }\n if (remaining > 0) partialText = clusters.slice(0, remaining).join('');\n break;\n }\n }\n\n // Caret sits at the reveal frontier: end of the partial line, else end of\n // the last full line, else the start of the block.\n let caretLine: number;\n let caretPrefix: string;\n if (partialText.length > 0) {\n caretLine = fullLines;\n caretPrefix = partialText;\n } else if (fullLines > 0) {\n caretLine = fullLines - 1;\n caretPrefix = lines[fullLines - 1]!.text;\n } else {\n caretLine = 0;\n caretPrefix = '';\n }\n\n return { progress, fullLines, partialText, caretLine, caretPrefix, glyphAlphas };\n}\n","import {\n createRng,\n type ControlTrack,\n type ParamDelta,\n type SaverContext,\n type SaverInstance,\n type SaverManifest,\n type SaverPlugin,\n} from '@idle-screens/core';\nimport { assertValidSpec, assertValidSequence, validateSpec, validateSpecPaths } from './validate';\nimport { alphaAt, breakTextBlock, buildEntities, entityScales, graphemeClusters, headingAt, lifeAlphaAt, linkEdges, linkMaxDistPx, positionAt, revealState, rotationAt, sizeAt, spriteIndexAt, textBlockAnchorOffset, textMetricsClassFor, type Entity } from './simulate';\nimport {\n applyDeltasToSpec,\n canonicalSpecPath,\n easeSmooth,\n lerpSpec,\n lerpValue,\n readSpecPath,\n resolveSpecPath,\n structuralSignature,\n textStringsDiffer,\n type SteerDelta,\n} from './steer';\nimport { transformOrigin } from './paint';\nimport { nextKeyAfter, resolveTimelineAt, timelineSampleTimesAfter } from './timeline';\nimport type { FieldBackground, IdleSequence, LayerSpec, LayerTransform, PathGradient, SaverSpec, SpriteSpec } from './types';\nimport { LIMITS } from './types';\nimport { FIELD_RASTER_SHORT_SIDE, FIELD_RASTER_SHORT_SIDE_LOW, fieldRgbAt, fieldSampleTime } from './field';\nimport { createFinishPass, createSceneCanvas, presentWithFinish, type FinishPass } from './finish';\nimport { canMorph, canWrapMorph, morphChainRoot, normalizeSeed, resolveSegment, segmentRenderSeed, segmentStart, sequenceSwapCompatible, sequenceWantsFinish } from './sequence';\nimport { FEATHER_MASK_SIZE, barBox, barFraction, featherRamp, isPathPolygon, isShapedSprite, pathDrawCost, pathFrame, pathPaintSig, pathParts, polygonFillRule, polygonPoints, ribbonSides, strokeOutline, strokeSamples, strokeWidthPx, type PolygonSprite } from './shapes';\nimport { trailEchoes, trailFillBudget } from './trail';\n\nconst DEFAULT_STEER_DUR = 1000;\n\n/**\n * Apply steering deltas to a spec one at a time, keeping each only if its\n * path resolves on this spec AND the result validates. This is the routing\n * rule for a sequence's retained track: a key path (`bars.sprite.values`) lands on\n * whichever segment owns the key and is a no-op on the others, and one delta\n * that is out of bounds for a given segment does not take the rest down with\n * it. Returns `spec` itself (same reference) when nothing applied, so callers\n * can skip work — and so a sequence with no track is byte-identical.\n */\nfunction applyRetainedDeltas(spec: SaverSpec, deltas: Iterable<SteerDelta>): SaverSpec {\n let out = spec;\n for (const d of deltas) {\n if (!resolveSpecPath(out, d.path)) continue;\n const next = applyDeltasToSpec(out, [d]);\n if (validateSpec(next).valid) out = next;\n }\n return out;\n}\n\n/** Expand #rgb/#rrggbb to an rgba() string — needed for gradient stops with alpha. */\nfunction hexToRgba(hex: string, alpha: number): string {\n const h = hex.length === 4 ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex;\n const n = parseInt(h.slice(1), 16);\n return `rgba(${(n >> 16) & 255},${(n >> 8) & 255},${n & 255},${alpha})`;\n}\n\nconst FONT_PREFIX_RE = /^((?:(?:italic|oblique|bold|bolder|lighter|normal|\\d{3})\\s+)+)/;\n\n/**\n * Matches the size token in a CSS font shorthand (\"bold 26px monospace\").\n *\n * The digit runs are bounded on purpose. This ran as `(\\d*\\.?\\d+)px`, where\n * `\\d*` and `\\d+` can split the same digit run many ways, so a long run that\n * never reaches \"px\" makes the engine retry every split at every start\n * position. `sprite.font` comes straight from an authored SaverSpec, so that\n * input is reachable by anyone who can publish a scene: 1 000 digits took\n * 600 ms and 5 000 took 62 SECONDS, which is a denial of service rather than\n * a slow path. Bounding each run makes the work per start position constant —\n * 200 000 chars now costs about 4 ms.\n *\n * The bounds are far past anything real: no CSS font size needs more than\n * five integer digits or four decimals. `.5px` still parses via the second\n * branch.\n */\nconst FONT_PX_RE = /(\\d{1,5}(?:\\.\\d{1,4})?|\\.\\d{1,4})px/;\n\n/**\n * Rescale an explicit px size inside a font shorthand.\n *\n * A spec in the default `viewport` units expresses every other dimension as a\n * fraction of `min(w, h)`, so a font pinned to absolute pixels is the one thing\n * that does NOT adapt: `bold 26px monospace` renders 26px whether the canvas is\n * 1920 or 320 wide, which is how the dashboard's text came to overlap itself at\n * thumbnail size. Scaling it by `min(w, h) / referenceViewport` makes it behave\n * like the rest of the spec. Specs that opt into `units: 'px'` are asking for\n * absolute sizes and are left alone.\n */\nfunction scaleFontPx(font: string, factor: number): string {\n if (factor === 1) return font;\n return font.replace(FONT_PX_RE, (_m, n: string) => `${(Number(n) * factor).toFixed(2)}px`);\n}\n\n/** Build a valid CSS font shorthand: weight/style tokens must precede the size. */\nfunction composeFontShorthand(sz: number, font: string): string {\n const m = FONT_PREFIX_RE.exec(font);\n if (m) return `${m[1].trim()} ${sz}px ${font.slice(m[0].length)}`;\n return `${sz}px ${font}`;\n}\n\n/** Derive a manifest so a compiled spec composes with @idle-screens/capabilities. */\nexport function manifestFor(spec: SaverSpec): SaverManifest {\n const total = spec.layers.reduce((n, l) => n + l.count, 0);\n const costTier = total < 30 ? 'idle' : total < 150 ? 'low' : total < 400 ? 'medium' : 'high';\n return {\n id: spec.id,\n label: spec.label,\n // Declarative specs are closed-form by construction: every entity is a\n // pure function of (seed, t), which is the whole point of the format.\n timeModel: 'closed-form',\n passthrough: false,\n minBackend: 'canvas2d',\n costTier,\n motionIntensity: spec.motionIntensity ?? 'moderate',\n reducedMotionFallback: 'static',\n // Flash-safe by construction: static background + bounded sprites, no strobe\n // primitive. Proven by sampling a compiled spec through @idle-screens/validator.\n a11y: { flashSafe: true },\n workerReady: true,\n };\n}\n\ninterface Built {\n layer: LayerSpec;\n entities: Entity[];\n}\n\n/**\n * Internal, per-layer: paint the layer twice for a window — the `outgoing`\n * sprite (the same sprite with the previous words) at `1 − k`, the layer's\n * own sprite at `k`. Set by a `SequenceInstance` for the `text` / `textBlock`\n * layers of a morph declared `text: 'crossfade'`; never from a spec field.\n * Only text sprites are ever drawn this way.\n */\ninterface LayerPaintOverride {\n outgoing: SpriteSpec;\n k: number;\n /**\n * `crossfade` (absent): outgoing at `1 − k` over incoming at `k`, both\n * strings on screen mid-morph. `dip`: outgoing fades out over the first\n * half, incoming fades in over the second — never two strings at once.\n */\n mode?: 'crossfade' | 'dip';\n}\n\n/** One draw's paint override: which sprite to paint, and an alpha multiplier on top of the entity's own. */\ninterface PaintPass {\n sprite?: SpriteSpec;\n alpha: number;\n}\n\n/**\n * The device's compute tier (`computeTier` from `@idle-screens/capabilities`;\n * the string union is repeated here so schema does not depend on that\n * package). Hosts pass it on the mount context; a compiled scene reads it to\n * step down work that a `basic` / `minimal` device cannot afford.\n */\nexport type CapabilityTier = 'minimal' | 'basic' | 'standard' | 'high';\n\n/**\n * Mount context for a compiled spec. A plain `SaverContext` works — every\n * field here is optional. `capabilityTier` `basic` / `minimal` halves a\n * `field` background's raster resolution (48 px short side instead of 96).\n * Absent ⇒ full resolution.\n */\nexport interface SpecMountContext extends SaverContext {\n capabilityTier?: CapabilityTier;\n}\n\n/**\n * A `field` background's cached raster: the field sampled once per cell at\n * the bucketed time, kept until the bucket, the config or the canvas size\n * changes. Drawing a frame is one `drawImage` of this, scaled to the canvas.\n */\ninterface FieldRaster {\n canvas: HTMLCanvasElement | OffscreenCanvas;\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\n cols: number;\n rows: number;\n /** `JSON.stringify` of the config plus dims plus the sample time it was painted for. */\n key: string;\n}\n\n/** Per-instance options a host (today: `SequenceInstance`) sets; a plain compileSaver mount sets none. */\ninterface SpecInstanceOptions {\n /** See `SpecMountContext.capabilityTier`. */\n capabilityTier?: CapabilityTier;\n /**\n * The host presents the frame and applies any `finish` itself (a\n * `SequenceInstance` does, once per composed frame), so this instance\n * never opens a presentation pass of its own — its spec's `finish` is the\n * host's to honour. A plain compileSaver mount presents itself.\n */\n hostPresents?: boolean;\n /**\n * Draw over whatever is already on the surface: `drawBackground` is skipped,\n * the frame is not cleared to a colour, and `ghosting` is ignored (a smear\n * needs an opaque ground to decay into — the surface owner may declare its\n * own). The instance never clears the surface either; the owner does.\n * A sequence's segment children over a `bed` render this way.\n */\n transparent?: boolean;\n /**\n * Skip the constructor's own eager paused-mount paint. For a transparent\n * instance whose owner is about to call `renderFrame` again immediately\n * with paint overrides already set (a morph chain-root child, mounted\n * mid-morph) — the constructor's plain paint would otherwise leave a\n * stray full-opacity frame on the shared surface underneath, which a\n * partial-alpha override pass (`text: 'crossfade'`) then composites over\n * rather than replaces.\n */\n skipInitialPaint?: boolean;\n}\n\nconst clamp01 = (v: number): number => (v <= 0 ? 0 : v >= 1 ? 1 : v);\n\n/** A live steer held on a timeline scene — see `SpecInstance.overrides`. */\ninterface TimelineOverride {\n /** The path's last segment — lets a whole-`transform` glide fill identity fields (see `lerpValue`). */\n leaf: string;\n from: unknown;\n to: unknown;\n t0: number;\n dur: number;\n until: number;\n outDur: number;\n}\nconst EXPIRED = Symbol('expired');\n\n/** An override's glide-in value at scene time `t` (before `until`). */\nfunction overrideHeldAt(o: TimelineOverride, t: number): unknown {\n const k = o.dur > 0 ? easeSmooth(clamp01((t - o.t0) / o.dur)) : 1;\n return k >= 1 ? o.to : lerpValue(o.from, o.to, k, false, o.leaf);\n}\n\n/**\n * An override's value at scene time `t`: glide in, hold, glide back to the\n * timeline, then expire. The glide back starts from wherever the glide in\n * had reached at `until` — a key that lands mid-glide takes the path back\n * from there, not from the steer's target (which would be a jump).\n */\nfunction overrideValueAt(o: TimelineOverride, t: number, timelineValue: () => unknown): unknown {\n if (t < o.until) return overrideHeldAt(o, t);\n if (o.outDur > 0 && t < o.until + o.outDur) return lerpValue(overrideHeldAt(o, o.until), timelineValue(), easeSmooth((t - o.until) / o.outDur), false, o.leaf);\n return EXPIRED;\n}\n\n/** A steer's identity across re-sends: the server's stamp and the value (see `SpecInstance.seenSteers`). */\nconst steerId = (d: SteerDelta): string => `${d.t}|${JSON.stringify(d.value)}`;\n\n/** Arm one steer on a timeline scene at scene time `now` — the steering rule: held until the path's next key, or sticky when no key will touch it. */\nfunction armOverride(authored: SaverSpec, path: string, from: unknown, to: unknown, now: number, glide: number): TimelineOverride {\n const next = nextKeyAfter(authored, path, now);\n return { leaf: path.slice(path.lastIndexOf('.') + 1), from, to, t0: now, dur: glide, until: next ? next.at : Number.POSITIVE_INFINITY, outDur: next ? next.dur : 0 };\n}\n\n/**\n * `resolved` (a timeline resolved at `t`) with the live overrides layered on.\n * `expired` collects the paths whose override has run out, so an owner can\n * drop them; nothing is mutated here.\n */\nfunction applyOverridesAt(resolved: SaverSpec, overrides: ReadonlyMap<string, TimelineOverride>, t: number, expired?: string[]): SaverSpec {\n if (overrides.size === 0) return resolved;\n const deltas: SteerDelta[] = [];\n for (const [path, o] of overrides) {\n const v = overrideValueAt(o, t, () => readSpecPath(resolved, path));\n if (v === EXPIRED) { expired?.push(path); continue; }\n deltas.push({ t: 0, path, value: v });\n }\n return deltas.length > 0 ? applyDeltasToSpec(resolved, deltas) : resolved;\n}\n\n/**\n * Whether a timeline scene stays valid with these overrides on it — now, and\n * at every key boundary still ahead (a sticky steer outlives the keys, and\n * two values each valid alone can break a flash-safety ratio together).\n */\nfunction overridesStayValid(authored: SaverSpec, overrides: ReadonlyMap<string, TimelineOverride>, now: number): boolean {\n // Only the layers (or background/finish) the overrides live in can be broken\n // by them — the timeline alone was validated with the spec — so judge just\n // those, and only at states not already judged.\n const paths = [...overrides.keys()];\n if (paths.length === 0) return true;\n const groupOf = (p: string): string => p.split('.').slice(0, p.startsWith('layers.') ? 2 : 1).join('.');\n const groups = [...new Set(paths.map(groupOf))];\n // The keys that can combine with these steers are those in the same\n // groups (or any, when a steer falls back to the full check).\n const full = paths.some((p) => /^layers\\.\\d+(\\.(key|count|motion)(\\.|$)|$)/.test(p) || p === 'groups' || !/^(layers|background|finish|groups)(\\.|$)/.test(p));\n const only = full ? undefined : (p: string): boolean => groups.includes(groupOf(p));\n const seen = new Set<string>();\n for (const t of [now, ...timelineSampleTimesAfter(authored, now, false, only)]) {\n const held = new Map<string, TimelineOverride>();\n // Judge each override at its held value (the glide-back runs between two valid values).\n for (const [p, o] of overrides) if (t < o.until) held.set(p, { ...o, t0: Number.NEGATIVE_INFINITY });\n const r = applyOverridesAt(resolveTimelineAt(authored, t), held, t);\n const state = JSON.stringify(groups.map((g) => readSpecPath(r, g))) + '|' + [...held.keys()].join(',');\n if (seen.has(state)) continue;\n seen.add(state);\n if (!validateSpecPaths(r, paths)) return false;\n }\n return true;\n}\n\ntype PathFrameT = { sx: number; sy: number; ox: number; oy: number; uniform: boolean };\n\n/** Path polygons with at least this many outline points draw from a render-once bitmap. */\nconst PATH_BLIT_MIN_POINTS = 128;\n/** A run of static path layers earns a full-frame plate only past this many outline points — below it, the plate copy costs more than the fills it saves. */\nconst PLATE_MIN_POINTS = 2500;\n/** Distinct bitmaps one path sprite may hold before it is judged \"changing\" and flushed. */\nconst PATH_BLIT_PER_SPRITE = 8;\n/** Distinct drawings (by content) the path caches remember at once. */\nconst PATH_SLOT_MAX = 96;\n/** Colour × size-step bitmaps one drawing may hold in the moving-sprite cache. */\nconst PATH_SPRITE_PER_SPRITE = 96;\n/** Largest moving-sprite bitmap (device px): beyond it a resampled (and maybe rotated) copy costs more than the fills — big moving drawings draw directly. */\nconst PATH_SPRITE_MAX_PIXELS = 512 * 512;\n/** Outline points per million device pixels a bitmap must carry to beat a direct fill: big simple shapes (a skyline wall) fill faster than they blit. */\nconst PATH_BLIT_MIN_DENSITY = 1500;\n/** Device pixels all path bitmaps together may hold (~64 MB of RGBA). */\nconst PATH_BLIT_MAX_PIXELS = 16_000_000;\n\n/** A Path2D of polylines (unit coordinates), closing the closed ones. */\nfunction ringPath2D(lines: Array<{ points: Array<[number, number]>; closed: boolean }>): Path2D {\n const p2 = new Path2D();\n for (const l of lines) {\n if (l.points.length < 2) continue;\n p2.moveTo(l.points[0]![0], l.points[0]![1]);\n for (let i = 1; i < l.points.length; i++) p2.lineTo(l.points[i]![0], l.points[i]![1]);\n if (l.closed) p2.closePath();\n }\n return p2;\n}\n\n/** The same polylines traced on the context's current path (no Path2D). */\nfunction traceLines(g: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, lines: Array<{ points: Array<[number, number]>; closed: boolean }>): void {\n g.beginPath();\n for (const l of lines) {\n if (l.points.length < 2) continue;\n g.moveTo(l.points[0]![0], l.points[0]![1]);\n for (let i = 1; i < l.points.length; i++) g.lineTo(l.points[i]![0], l.points[i]![1]);\n if (l.closed) g.closePath();\n }\n}\n\n/** A path gradient as a canvas gradient in unit-box coordinates (the caller has scaled by the radius). */\nfunction pathGradientFill(g: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, gr: PathGradient): CanvasGradient {\n const grad = gr.type === 'linear'\n ? g.createLinearGradient(gr.from[0], gr.from[1], gr.to[0], gr.to[1])\n : g.createRadialGradient((gr.focus ?? gr.center)[0], (gr.focus ?? gr.center)[1], 0, gr.center[0], gr.center[1], gr.radius);\n for (const st of gr.stops) grad.addColorStop(st.at, st.opacity === undefined ? st.color : hexToRgba(st.color, st.opacity));\n return grad;\n}\n\n/** The soft-sprite radial gradient (1 → 0.75 at 0.35 r → 0 at r), centred on the entity. */\nfunction softFill(g: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, color: string, r: number): CanvasGradient {\n const grad = g.createRadialGradient(0, 0, 0, 0, 0, r);\n grad.addColorStop(0, color);\n grad.addColorStop(0.35, hexToRgba(color, 0.75));\n grad.addColorStop(1, hexToRgba(color, 0));\n return grad;\n}\n\ntype Canvas2D = { canvas: HTMLCanvasElement | OffscreenCanvas; ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D };\n/** One entity's pre-rendered feathered rect: the rotated white mask, and its tint. */\ninterface FeatherBlit {\n shapeKey: string;\n w: number;\n h: number;\n white: Canvas2D;\n tint: Canvas2D;\n tintKey: string;\n tintAt: number;\n /** Phase offset for the first re-tint, spreading a layer's re-tints over frames. */\n stagger?: number;\n /** The shape key seen most recently, and the paintSeq it was first seen at. */\n seenKey: string;\n seenAt: number;\n}\n\nclass SpecInstance implements SaverInstance {\n private readonly canvas: HTMLCanvasElement | OffscreenCanvas;\n private readonly ownsCanvas: boolean;\n private readonly transparent: boolean;\n private readonly ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\n private readonly saverCtx: SaverContext;\n private readonly seed: number;\n private w: number;\n private h: number;\n private layers: Built[] = [];\n private frameId: number | null = null;\n private paused = false;\n private startT = 0;\n private baseT = 0; // elapsed logical time carried across pause/resume\n private lastT = 0;\n /** Last time painted — detects non-contiguous seeks for the ghosting warm-up replay. */\n private lastRenderT = Number.NEGATIVE_INFINITY;\n\n /** The spec currently being rendered (base spec + any applied steering). */\n private effSpec: SaverSpec;\n /** Active glide between two resolved specs (live setParam/applyTrack). */\n private transition: { from: SaverSpec; to: SaverSpec; startT: number; dur: number } | null = null;\n private lastStructural = '';\n /** See `LayerPaintOverride`; null (the default, and every plain mount) draws every layer once. */\n private paintOverrides: ReadonlyMap<number, LayerPaintOverride> | null = null;\n /**\n * The authored spec when it carries a `timeline` (null for every other\n * scene — which then never enters the timeline path). Each painted frame\n * resolves it at that frame's own time, so ghosting's warm-up replay and\n * any seek see the timeline exactly where it was.\n */\n private authored: SaverSpec | null = null;\n /**\n * Live steers on a timeline scene, by index-form path. A steer on a path no\n * key animates holds forever (sticky, exactly as on a scene without a\n * timeline); on an animated path it holds `until` that path's next key,\n * then glides back to the timeline over `outDur`.\n */\n private overrides: Map<string, TimelineOverride> = new Map();\n /**\n * The last registered steer per path, as `t|value`. A host re-sends the\n * whole channel track on every steer (idle-server broadcasts the full track\n * so viewers converge), and a steer's `t` is the server's stamp — stable\n * across re-sends. Without this, an unrelated later steer would re-arm a\n * hold the timeline had already taken back. Keyed by path (not by the full\n * `path|t|value` history) so a long-running instance re-steered thousands\n * of times doesn't accumulate an unbounded set — only the most recent id\n * per path can ever recur.\n */\n private seenSteers = new Map<string, string>();\n /** Raster short side for a `field` background — halved on the low tiers. */\n private readonly fieldShortSide: number;\n /** The `field` background's cached raster; null until a field is first painted. */\n private field: FieldRaster | null = null;\n private readonly featherWhite = new Map<number, HTMLCanvasElement | OffscreenCanvas>();\n /** Per-entity pre-rendered feathered rects (see `blitFeather`), and the device pixels they hold. */\n private readonly featherBlits = new WeakMap<Entity, FeatherBlit>();\n private featherBlitPx = 0;\n private featherBlitN = 0;\n private paintSeq = 0;\n /** Per layer: ribbon area painted this frame (px²), and whether its trails ribbon (see ribbonAllowed). */\n private readonly ribbonBudget = new WeakMap<Built, { seq: number; area: number; ribbon: boolean }>();\n /**\n * Render-once cache for path polygons (polygon.path). A detailed drawing is\n * rasterised once per (colour, device size, rotation, sub-pixel offset)\n * into its own bitmap and copied 1:1 at a whole-pixel offset every frame\n * after — so a static 7,000-point drawing costs a blit, not a re-fill.\n * Keyed by the sprite object, so a steer or republish (a new spec object)\n * starts clean. A drawing whose key keeps changing (spinning, trailing,\n * growing) stops being cached and draws from a reused Path2D instead.\n */\n private readonly pathBlits = new Map<string, { entries: Map<string, { canvas: HTMLCanvasElement | OffscreenCanvas; x0: number; y0: number; px: number }>; flushes: number; off: boolean; parts2d?: Array<{ fill?: Path2D | null; fillPart?: Path2D | null; stroke?: Path2D | null }>; sprite?: boolean }>();\n /** Test/bench switch: `globalThis.__idleNoPathCache = true` before compiling draws every path directly. */\n private readonly noPathCache = (globalThis as { __idleNoPathCache?: boolean }).__idleNoPathCache === true;\n /** Device pixels held by every pathBlits bitmap — capped so a TV never pays more than PATH_BLIT_MAX_PIXELS of memory. */\n private pathBlitPixels = 0;\n private readonly featherTints = new Map<string, { canvas: HTMLCanvasElement | OffscreenCanvas; ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D }>();\n /**\n * The presentation pass when this instance applies a `finish`: the\n * visible canvas plus the cached screen tiles. When set, `this.canvas` is\n * an offscreen SCENE canvas — the surface every layer (and `ghosting`'s\n * persistence) draws into — and each frame ends by copying it to the\n * visible canvas and screening the finish over the copy. The finish thus\n * never enters the persistence loop. Null (every plain mount without a\n * finish, every sequence child) draws straight onto the visible canvas,\n * exactly as before the field existed.\n */\n private finishPass: FinishPass | null = null;\n /** False on the `basic`/`minimal` tiers — `finish.animate` renders as a static tile. */\n private readonly animateFinish: boolean;\n\n constructor(\n private readonly spec: SaverSpec,\n ctx: SaverContext,\n opts: SpecInstanceOptions = {},\n ) {\n this.effSpec = spec;\n if (spec.timeline) {\n this.authored = spec;\n this.effSpec = resolveTimelineAt(spec, 0);\n }\n this.saverCtx = ctx;\n this.transparent = opts.transparent === true;\n const tier = opts.capabilityTier;\n this.fieldShortSide = tier === 'basic' || tier === 'minimal' ? FIELD_RASTER_SHORT_SIDE_LOW : FIELD_RASTER_SHORT_SIDE;\n this.animateFinish = tier !== 'basic' && tier !== 'minimal';\n this.seed = normalizeSeed(spec.seed ?? ctx.seed);\n let canvas: HTMLCanvasElement | OffscreenCanvas;\n if (ctx.surface) {\n canvas = ctx.surface;\n this.ownsCanvas = false;\n } else {\n const el = document.createElement('canvas');\n el.style.cssText = 'display:block;width:100%;height:100%';\n el.setAttribute('aria-hidden', 'true');\n ctx.host.appendChild(el);\n canvas = el;\n this.ownsCanvas = true;\n }\n if (spec.finish !== undefined && !this.transparent && !opts.hostPresents) {\n // Present through a pass: the visible canvas becomes the pass's, and\n // the scene draws offscreen. Decided once, from the mounted spec — a\n // steer can only change a `finish` that already exists.\n const pass = createFinishPass(canvas, this.seed);\n if (pass) {\n this.finishPass = pass;\n canvas = createSceneCanvas(ctx.width, ctx.height);\n }\n }\n this.canvas = canvas;\n // Transparent instances (a bed's own offscreen fade canvas) never paint a\n // background, so their cleared/unpainted pixels must stay actually\n // transparent for `composite()`'s drawImage to blend only the ink onto\n // the bed — an opaque (alpha: false) context turns those pixels solid\n // black instead. Opaque instances keep alpha: false (unchanged).\n const c2d = canvas.getContext('2d', { alpha: this.transparent }) as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;\n if (!c2d) throw new Error('schema saver: no 2d context');\n this.ctx = c2d;\n\n this.w = ctx.width;\n this.h = ctx.height;\n this.sizeCanvas();\n this.rebuild();\n\n this.paused = ctx.reducedMotion;\n if (this.paused) {\n if (!opts.skipInitialPaint) this.renderFrame(0, this.seed);\n } else {\n this.start();\n }\n }\n\n /** Viewport factor for absolute px sizes — 1 for `units: 'px'` specs. */\n private fontScale(): number {\n if (this.effSpec.units === 'px') return 1;\n return Math.min(this.w, this.h) / (this.effSpec.referenceViewport ?? LIMITS.referenceViewport);\n }\n\n private sizeCanvas(): void {\n const dpr = Math.min(this.saverCtx.dpr, 2);\n // Assign only on a real change: writing `width`/`height` wipes a canvas\n // even when the value is the same, and a sequence child shares its\n // parent's surface — a segment mounting over a `bed` used to erase the\n // bed painted a moment earlier, one black frame at every cut. A fresh\n // canvas is blank anyway, and every frame repaints (or, after a resize,\n // the ghosting warm-up below replays from a full clear).\n const cw = Math.max(1, Math.round(this.w * dpr));\n const ch = Math.max(1, Math.round(this.h * dpr));\n if (this.canvas.width !== cw) this.canvas.width = cw;\n if (this.canvas.height !== ch) this.canvas.height = ch;\n this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n if (this.finishPass) {\n // The visible canvas mirrors the scene canvas, same size and transform.\n if (this.finishPass.canvas.width !== cw) this.finishPass.canvas.width = cw;\n if (this.finishPass.canvas.height !== ch) this.finishPass.canvas.height = ch;\n this.finishPass.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n }\n // Resizing clears the canvas — force a ghosting warm-up on the next frame.\n this.lastRenderT = Number.NEGATIVE_INFINITY;\n }\n\n /** (Re)seed and place all entities — deterministic for the seed + viewport. */\n private rebuild(): void {\n const rng = createRng(this.seed);\n const { scale, countScale } = entityScales(this.effSpec, this.w, this.h);\n this.layers = this.effSpec.layers.map((layer) => ({ layer, entities: buildEntities(layer, rng, this.w, this.h, scale, countScale) }));\n this.lastStructural = structuralSignature(this.effSpec);\n }\n\n private start(): void {\n if (this.frameId !== null || typeof requestAnimationFrame === 'undefined') return;\n this.startT = 0;\n this.frameId = requestAnimationFrame((now) => this.loop(now));\n }\n\n private stop(): void {\n if (this.frameId !== null) {\n cancelAnimationFrame(this.frameId);\n this.frameId = null;\n }\n // Freeze elapsed time so resume continues the scene instead of restarting at t=0.\n this.baseT = this.lastT;\n }\n\n private loop(now: number): void {\n this.frameId = requestAnimationFrame((n) => this.loop(n));\n if (this.startT === 0) this.startT = now;\n this.lastT = now - this.startT + this.baseT;\n this.renderFrame(this.lastT, this.seed);\n }\n\n private drawBackground(t: number): void {\n const { ctx, w, h } = this;\n const bg = this.effSpec.background;\n if (!bg || bg.type === 'solid') {\n ctx.fillStyle = bg?.color ?? '#05050a';\n ctx.fillRect(0, 0, w, h);\n return;\n }\n if (bg.type === 'field') {\n this.drawField(bg, t);\n return;\n }\n const g = ctx.createLinearGradient(0, 0, 0, h);\n const drift = bg.drift;\n for (let i = 0; i < bg.stops.length; i++) {\n const s = bg.stops[i]!;\n let at = s.at;\n if (drift) {\n const amount = drift.amount ?? 0.15;\n const phase = (i / bg.stops.length) * Math.PI * 2;\n at = Math.max(0, Math.min(1, at + amount * Math.sin((t * 2 * Math.PI) / drift.period + phase)));\n }\n g.addColorStop(at, s.color);\n }\n ctx.fillStyle = g;\n ctx.fillRect(0, 0, w, h);\n if (bg.band) {\n ctx.fillStyle = bg.band.color;\n const bh = bg.band.height * (this.effSpec.units === 'px' ? 1 : Math.min(w, h));\n ctx.fillRect(0, h - bh, w, bh);\n }\n }\n\n /**\n * Paint a `field` background: sample the field into a low-res raster (short\n * side `fieldShortSide`, the long side by aspect) and draw it scaled to the\n * canvas — nearest-neighbour for quantised bands so contours stay crisp,\n * smoothed for `quantize: 0`. The raster is recomputed only when its key\n * changes: the config (steering glides it), the canvas size, or — while\n * drifting — the 100 ms bucket `t` falls in (`fieldSampleTime`); a static\n * field is sampled exactly once per mount. `luminanceGrid` samples the same\n * function at the same bucketed time, so perception and paint agree.\n */\n private drawField(bg: FieldBackground, t: number): void {\n const { ctx, w, h } = this;\n const short = Math.max(1, Math.min(w, h));\n const cols = Math.max(1, Math.round((this.fieldShortSide * w) / short));\n const rows = Math.max(1, Math.round((this.fieldShortSide * h) / short));\n const ft = fieldSampleTime(bg, t);\n // `w`x`h`, not just the rounded `cols`x`rows`: a resize that changes the\n // aspect ratio without moving the rounded raster size would otherwise\n // reuse a raster sampled for the old aspect ratio.\n const key = `${JSON.stringify(bg)}|${w}x${h}|${cols}x${rows}|${ft}`;\n let raster = this.field;\n if (!raster || raster.key !== key) {\n if (!raster || raster.cols !== cols || raster.rows !== rows) {\n const canvas: HTMLCanvasElement | OffscreenCanvas = typeof document !== 'undefined'\n ? document.createElement('canvas')\n : new OffscreenCanvas(cols, rows);\n canvas.width = cols;\n canvas.height = rows;\n const rctx = canvas.getContext('2d') as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;\n if (!rctx) return;\n raster = { canvas, ctx: rctx, cols, rows, key: '' };\n }\n const img = raster.ctx.createImageData(cols, rows);\n const data = img.data;\n const seed = this.seed;\n let i = 0;\n for (let r = 0; r < rows; r++) {\n // Cell centres in short-side units — the same normalisation perceive uses.\n const v = ((r + 0.5) * h) / rows / short;\n for (let c = 0; c < cols; c++) {\n const u = ((c + 0.5) * w) / cols / short;\n const rgb = fieldRgbAt(u, v, ft, bg, seed);\n data[i++] = rgb[0];\n data[i++] = rgb[1];\n data[i++] = rgb[2];\n data[i++] = 255;\n }\n }\n raster.ctx.putImageData(img, 0, 0);\n raster.key = key;\n this.field = raster;\n }\n const smooth = Math.round(bg.quantize ?? bg.bands.length) < 2;\n const prev = ctx.imageSmoothingEnabled;\n ctx.imageSmoothingEnabled = smooth;\n ctx.drawImage(raster.canvas, 0, 0, w, h);\n ctx.imageSmoothingEnabled = prev;\n }\n\n /** Position with parent-orbit resolution: a layer-parented orbit entity's\n * positionAt is an offset around (0,0); add the parent's own analytic position. */\n private entityPos(e: Entity, t: number, parentE: Entity | null): { x: number; y: number; flip: boolean } {\n const p = positionAt(e, t, this.w, this.h);\n if (parentE && e.orbitParent) {\n const pp = positionAt(parentE, t, this.w, this.h);\n p.x += pp.x;\n p.y += pp.y;\n }\n return p;\n }\n\n /** Resolve the single parent entity for a layer-parented orbit layer (or null). */\n private parentEntityFor(built: Built): Entity | null {\n const m = built.layer.motion;\n if (m.type !== 'orbit' || !m.center || !('layer' in m.center)) return null;\n const key = m.center.layer;\n const parent = this.layers.find((b) => b.layer.key === key);\n return parent?.entities[0] ?? null;\n }\n\n private drawTrail(built: Built, e: Entity, t: number, lifeA: number, parentE: Entity | null): void {\n const trail = built.layer.trail;\n if (!trail) return;\n const { ctx, w, h } = this;\n const headAlpha = alphaAt(e, t) * lifeA;\n const headSize = sizeAt(e, t);\n const sprite = built.layer.sprite;\n const shaped = isShapedSprite(sprite) && sprite.kind !== 'circle';\n const isSoft = sprite.kind === 'circle' && !!sprite.soft;\n const hardCircle = sprite.kind === 'circle' && !sprite.soft;\n const ribbon = hardCircle && this.ribbonAllowed(built);\n const posAt = (pt: number): { x: number; y: number } => this.entityPos(e, pt, parentE);\n // Only soft discs (and glyph trails) are gap-filled: a hard circle's\n // echoes are joined into a ribbon, and a shape's echoes stay at their\n // time samples — so neither draws more than the 24 echoes it always did.\n const fill = shaped || hardCircle ? 0 : trailFillBudget(built.entities.length);\n const echoes = trailEchoes(trail, t, headAlpha, headSize, posAt, w, h, built.layer.wrap !== false, fill, 0, built.layer.blend === 'lighter');\n if (echoes.length === 0) return;\n const head = posAt(t);\n if (hardCircle) {\n // The area this trail's ribbon covers (whether or not it is drawn as one), for the layer's ribbon budget.\n const rb = this.ribbonBudget.get(built)!;\n let prev = head;\n let r0 = headSize / 2;\n for (const ec of echoes) {\n rb.area += Math.hypot(ec.x - prev.x, ec.y - prev.y) * (r0 + ec.r);\n prev = ec;\n r0 = ec.r;\n }\n }\n // A shaped sprite's afterglow is echoes of its own shape (X387: a polygon\n // or stroke used to trail fat discs), at the echo's own time — so a\n // spinning or heading-oriented mark echoes the way it was turned then.\n if (shaped) {\n for (const ec of echoes) this.drawEntity(built, e, ec.t, 1, parentE, undefined, { x: ec.x, y: ec.y, size: ec.r * 2, alpha: ec.alpha });\n return;\n }\n const resolvedColor = isShapedSprite(sprite)\n ? (sprite.colors?.[e.colorIndex] ?? sprite.color)\n : sprite.kind === 'text' || sprite.kind === 'textBlock' ? (sprite.color ?? '#e6e8ef') : '#e6e8ef';\n if (ribbon) {\n // X469: one continuous ribbon from the head back through every echo,\n // tapering with the echoes' radii — each span a quad between two\n // shared cross-sections, so nothing overlaps (no beads under a blend)\n // and a fast mover draws a line, not dots, for the same 24 fills.\n // Spans whose alphas sit within 4 % of the head's are merged into one\n // fill, so a gently fading trail costs a handful of fills, not 24.\n // Each span is subdivided at its own times (≤ ~12 px chords, ≤ 8 per\n // span) so a curving path stays a curve, not 24 straight chords; the\n // extra points are vertices, not fills.\n const pts: Array<{ x: number; y: number }> = [head];\n const radii: number[] = [headSize / 2];\n const alphas: number[] = [headAlpha];\n let prevT = t;\n for (const ec of echoes) {\n const p0 = pts[pts.length - 1]!;\n const r0 = radii[radii.length - 1]!;\n const a0 = alphas[alphas.length - 1]!;\n const sub = Math.max(1, Math.min(8, Math.ceil(Math.hypot(ec.x - p0.x, ec.y - p0.y) / 12)));\n for (let j = 1; j < sub; j++) {\n const f = j / sub;\n pts.push(posAt(prevT + (ec.t - prevT) * f));\n radii.push(r0 + (ec.r - r0) * f);\n alphas.push(a0 + (ec.alpha - a0) * f);\n }\n pts.push(ec);\n radii.push(ec.r);\n alphas.push(ec.alpha);\n prevT = ec.t;\n }\n const { left, right } = ribbonSides(pts, radii);\n ctx.fillStyle = resolvedColor;\n const tol = Math.max(0.004, headAlpha * 0.04);\n let from = 0; // first cross-section of the current chunk\n while (from < pts.length - 1) {\n const a0 = alphas[from + 1]!;\n let to = from + 1;\n let sum = a0;\n while (to < pts.length - 1 && Math.abs(alphas[to + 1]! - a0) <= tol) { sum += alphas[to + 1]!; to++; }\n ctx.globalAlpha = sum / (to - from);\n ctx.beginPath();\n ctx.moveTo(left[from]!.x, left[from]!.y);\n for (let i = from + 1; i <= to; i++) ctx.lineTo(left[i]!.x, left[i]!.y);\n for (let i = to; i >= from; i--) ctx.lineTo(right[i]!.x, right[i]!.y);\n ctx.closePath();\n ctx.fill();\n from = to;\n }\n return;\n }\n for (const ec of echoes) {\n ctx.globalAlpha = ec.alpha;\n if (isSoft) {\n const g = ctx.createRadialGradient(ec.x, ec.y, 0, ec.x, ec.y, ec.r);\n g.addColorStop(0, resolvedColor);\n g.addColorStop(0.35, hexToRgba(resolvedColor, 0.75));\n g.addColorStop(1, hexToRgba(resolvedColor, 0));\n ctx.fillStyle = g;\n } else {\n ctx.fillStyle = resolvedColor;\n }\n ctx.beginPath();\n ctx.arc(ec.x, ec.y, ec.r, 0, Math.PI * 2);\n ctx.fill();\n }\n }\n\n /**\n * Whether this layer's hard-circle trails draw as ribbons this frame. A\n * ribbon paints its trail's whole length, so a layer of many fast, long\n * trails can paint far more pixels than its dots did — under `lighter` on\n * a CPU rasteriser that was 2.4× the frame time (60 trails, 3 s, 0.4/s).\n * Past a tenth of the viewport's area in ribbon (measured on the\n * previous frame) the layer falls back to the time-sample discs it always\n * drew; it returns to ribbons below 70 % of that, so a layer near the line\n * does not flicker between the two.\n */\n private ribbonAllowed(built: Built): boolean {\n let rb = this.ribbonBudget.get(built);\n if (!rb) {\n rb = { seq: this.paintSeq, area: 0, ribbon: true };\n this.ribbonBudget.set(built, rb);\n }\n if (rb.seq !== this.paintSeq) {\n const budget = 0.1 * this.w * this.h;\n if (rb.ribbon && rb.area > budget) rb.ribbon = false;\n else if (!rb.ribbon && rb.area < 0.7 * budget) rb.ribbon = true;\n rb.seq = this.paintSeq;\n rb.area = 0;\n }\n return rb.ribbon;\n }\n\n /** A fresh 2D canvas (DOM or Offscreen), or null where none can be made. */\n /**\n * A drawing's cache slot, keyed by what it draws (pathPaintSig), not by the\n * sprite object — glides and timelines replace that object every frame.\n * Least-recently-used slots are evicted past PATH_SLOT_MAX, and their\n * bitmaps' pixels returned to the budget.\n */\n private pathSlot(sprite: PolygonSprite) {\n const sig = pathPaintSig(sprite);\n let slot = this.pathBlits.get(sig);\n if (slot) {\n this.pathBlits.delete(sig);\n this.pathBlits.set(sig, slot);\n return slot;\n }\n if (this.pathBlits.size >= PATH_SLOT_MAX) {\n const [oldSig, old] = this.pathBlits.entries().next().value!;\n for (const ent of old.entries.values()) this.pathBlitPixels -= ent.px;\n this.pathBlits.delete(oldSig);\n }\n slot = { entries: new Map(), flushes: 0, off: false };\n this.pathBlits.set(sig, slot);\n return slot;\n }\n\n /**\n * Whether a layer's path drawing looks the same as last frame — the caches\n * serve only steady drawings; one that is gliding (colour, gradient, shape)\n * draws directly until it settles, instead of rasterising a bitmap a frame.\n */\n // Keyed by the layer's place in the scene, never the per-layer record: a\n // scene that animates a baked field (alpha, size) rebuilds every record\n // every frame, and a drawing beside it is still steady.\n private readonly pathSteady = new Map<number, { sig: string; seq: number; steady: boolean }>();\n private drawingSteady(built: Built, sprite: PolygonSprite): boolean {\n const sig = pathPaintSig(sprite);\n const li = this.layers.indexOf(built);\n const prev = this.pathSteady.get(li);\n if (prev && prev.seq === this.paintSeq && prev.sig === sig) return prev.steady;\n const steady = prev !== undefined && prev.sig === sig;\n this.pathSteady.set(li, { sig, seq: this.paintSeq, steady });\n return steady;\n }\n\n /**\n * Draw a path polygon in its own unit box: the caller has moved to the\n * entity and rotated; this scales by r. Parts paint back to front (a single\n * `path` is one part). Each fill is its gradient (drawing-box coordinates,\n * or with units 'part' the part's own box, filled under that box's\n * transform so a radial reads as the part's ellipse), the soft radial\n * falloff, or flat colour; each stroke traces the part's subpaths as drawn,\n * width in unit-box units. Outlines are Path2Ds built once per sprite.\n */\n private drawPathUnit(g: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, sprite: PolygonSprite, color: string, fr: PathFrameT, r: number): void {\n const slot = this.pathSlot(sprite);\n const parts = pathParts(sprite);\n if (!slot.parts2d) slot.parts2d = parts.map(() => ({}));\n // The frame: origin to the entity position, then per-axis scale (span).\n if (fr.ox || fr.oy) g.translate(-fr.ox * fr.sx, -fr.oy * fr.sy);\n g.scale(fr.sx, fr.sy);\n const a0 = g.globalAlpha;\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i]!;\n const cache = slot.parts2d[i]!;\n const pc = part.color ?? color;\n if (part.fill && part.flat.points.length >= 3) {\n g.globalAlpha = a0 * part.opacity;\n if (part.gradient?.units === 'part') {\n // Fill in part space: the gradient's −1..1 is the part's box.\n const { cx, cy, hw, hh } = part.box;\n if (cache.fillPart === undefined) {\n cache.fillPart = typeof Path2D === 'undefined' ? null : ringPath2D([{ points: part.flat.points.map(([x, y]) => [(x - cx) / hw, (y - cy) / hh] as [number, number]), closed: true }]);\n }\n g.save();\n g.transform(hw, 0, 0, hh, cx, cy);\n g.fillStyle = pathGradientFill(g, part.gradient);\n if (cache.fillPart) g.fill(cache.fillPart, part.rule);\n else { traceLines(g, [{ points: part.flat.points.map(([x, y]) => [(x - cx) / hw, (y - cy) / hh] as [number, number]), closed: true }]); g.fill(part.rule); }\n g.restore();\n } else {\n g.fillStyle = part.gradient ? pathGradientFill(g, part.gradient) : sprite.soft && !sprite.parts ? softFill(g, pc, 1) : pc;\n if (cache.fill === undefined) cache.fill = typeof Path2D === 'undefined' ? null : ringPath2D([{ points: part.flat.points, closed: true }]);\n if (cache.fill) g.fill(cache.fill, part.rule);\n else { traceLines(g, [{ points: part.flat.points, closed: true }]); g.fill(part.rule); }\n }\n }\n const st = part.stroke;\n if (st && part.flat.lines.length) {\n g.globalAlpha = a0 * part.opacity * (st.opacity ?? 1);\n g.strokeStyle = st.color;\n g.lineJoin = st.join ?? 'round';\n g.lineCap = st.cap ?? 'round';\n if (fr.uniform) {\n // Width is in unit-box units of the uniform scale r.\n g.lineWidth = (st.width * r) / fr.sx;\n if (cache.stroke === undefined) cache.stroke = typeof Path2D === 'undefined' ? null : ringPath2D(part.flat.lines);\n if (cache.stroke) g.stroke(cache.stroke);\n else { traceLines(g, part.flat.lines); g.stroke(); }\n } else {\n // A stretched drawing: stroke the stretched outline in unscaled space,\n // so the line keeps one width instead of fattening along the long axis.\n const scaled = part.flat.lines.map((l) => ({ closed: l.closed, points: l.points.map(([x, y]) => [x * fr.sx, y * fr.sy] as [number, number]) }));\n g.save();\n g.scale(1 / fr.sx, 1 / fr.sy);\n g.lineWidth = st.width * r;\n traceLines(g, scaled);\n g.stroke();\n g.restore();\n }\n }\n }\n g.globalAlpha = a0;\n }\n\n /**\n * Draw a path polygon from its render-once bitmap. False when it cannot be\n * blitted exactly — a rotated or skewed layer transform, a bitmap past the\n * memory cap, a drawing too sparse for its area, or one that keeps\n * changing — and the caller draws it directly.\n */\n private blitPath(sprite: PolygonSprite, p: { x: number; y: number }, r: number, rot: number, color: string, fr: PathFrameT): boolean {\n const ctx = this.ctx;\n const slot = this.pathSlot(sprite);\n if (slot.off) return false;\n if (slot.sprite) return this.spriteBlit(sprite, slot, p, r, rot, color, fr);\n const m = ctx.getTransform();\n // 1:1 copies need an axis-aligned, uniform transform (dpr, layer translate/scale);\n // anything else (a rotated or skewed layer) goes straight to the sprite cache.\n if (Math.abs(m.b) > 1e-9 || Math.abs(m.c) > 1e-9 || Math.abs(m.a - m.d) > 1e-9 || !(m.a > 0)) {\n slot.sprite = true;\n return this.spriteBlit(sprite, slot, p, r, rot, color, fr);\n }\n const k = m.a;\n const dx = k * p.x + m.e;\n const dy = k * p.y + m.f;\n const ix = Math.floor(dx);\n const iy = Math.floor(dy);\n const fx = Math.round((dx - ix) * 8) / 8;\n const fy = Math.round((dy - iy) * 8) / 8;\n const key = `${color}|${(r * k).toFixed(3)}|${(fr.sx * k).toFixed(3)}|${(fr.sy * k).toFixed(3)}|${fr.ox},${fr.oy}|${rot.toFixed(5)}|${fx}|${fy}`;\n let hit = slot.entries.get(key);\n if (!hit) {\n if (slot.entries.size >= PATH_BLIT_PER_SPRITE) {\n for (const old of slot.entries.values()) this.pathBlitPixels -= old.px;\n slot.entries.clear();\n // The key keeps changing (moving, spinning, growing): exact copies cannot\n // keep up, so this drawing switches to the moving-sprite cache.\n if (++slot.flushes > 1) { slot.sprite = true; slot.flushes = 0; return this.spriteBlit(sprite, slot, p, r, rot, color, fr); }\n }\n const c = Math.cos(rot);\n const sn = Math.sin(rot);\n const s = r * k;\n let x0 = Infinity, x1 = -Infinity, y0 = Infinity, y1 = -Infinity;\n const grow = (u: [number, number]): void => {\n const ux = (u[0] - fr.ox) * fr.sx * k, uy = (u[1] - fr.oy) * fr.sy * k;\n const x = ux * c - uy * sn;\n const y = ux * sn + uy * c;\n if (x < x0) x0 = x; if (x > x1) x1 = x; if (y < y0) y0 = y; if (y > y1) y1 = y;\n };\n let sw = 0;\n for (const part of pathParts(sprite)) {\n if (part.fill) for (const u of part.flat.points) grow(u);\n if (part.stroke) { sw = Math.max(sw, part.stroke.width); for (const l of part.flat.lines) for (const u of l.points) grow(u); }\n }\n const pad = 2 + Math.ceil(sw * s);\n const bx = Math.floor(fx + x0) - pad;\n const by = Math.floor(fy + y0) - pad;\n const w = Math.ceil(fx + x1) - bx + pad;\n const h = Math.ceil(fy + y1) - by + pad;\n if (!(w > 0 && h > 0) || !Number.isFinite(w + h)) return false;\n if (pathDrawCost(sprite) / ((w * h) / 1e6) < PATH_BLIT_MIN_DENSITY) { slot.off = true; return false; }\n if (this.pathBlitPixels + w * h > PATH_BLIT_MAX_PIXELS) return false;\n const made = this.makeCanvas(1);\n if (!made) return false;\n made.canvas.width = w;\n made.canvas.height = h;\n const g = made.ctx;\n g.setTransform(k, 0, 0, k, fx - bx, fy - by);\n if (rot) g.rotate(rot);\n this.drawPathUnit(g, sprite, color, fr, r);\n hit = { canvas: made.canvas, x0: bx, y0: by, px: w * h };\n this.pathBlitPixels += hit.px;\n slot.entries.set(key, hit);\n }\n ctx.save();\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.drawImage(hit.canvas, ix + hit.x0, iy + hit.y0);\n ctx.restore();\n return true;\n }\n\n /**\n * The moving-sprite cache: for a drawing whose exact key keeps changing. It\n * is rasterised once per colour, UNROTATED, at a device radius rounded UP to\n * the next 1/8-octave step (so it is only ever shrunk, never enlarged), then\n * drawn every frame at its true sub-pixel position, rotation and size under\n * the context's own transform, with smoothing. Not pixel-exact like the\n * still cache (edges resample by well under a pixel), but a 7-part drifting\n * balloon costs one image draw instead of seven fills and strokes.\n */\n private spriteBlit(sprite: PolygonSprite, slot: NonNullable<ReturnType<typeof this.pathBlits.get>>, p: { x: number; y: number }, r: number, rot: number, color: string, fr: PathFrameT): boolean {\n const ctx = this.ctx;\n // Sprites are for uniform, box-sized drawings (particles); a stretched one draws directly.\n if (!fr.uniform || fr.sx !== r) return false;\n const m = ctx.getTransform();\n const k = Math.sqrt(Math.abs(m.a * m.d - m.b * m.c));\n const s = r * k;\n if (!(s >= 1)) return false;\n const bucket = 2 ** (Math.ceil(Math.log2(s) * 8) / 8);\n const key = `S|${color}|${bucket.toFixed(3)}`;\n let hit = slot.entries.get(key);\n if (!hit) {\n if (slot.entries.size >= PATH_SPRITE_PER_SPRITE) {\n for (const old of slot.entries.values()) this.pathBlitPixels -= old.px;\n slot.entries.clear();\n if (++slot.flushes > 2) { slot.off = true; return false; }\n }\n let x0 = Infinity, x1 = -Infinity, y0 = Infinity, y1 = -Infinity, sw = 0;\n const grow = (u: [number, number]): void => { if (u[0] < x0) x0 = u[0]; if (u[0] > x1) x1 = u[0]; if (u[1] < y0) y0 = u[1]; if (u[1] > y1) y1 = u[1]; };\n for (const part of pathParts(sprite)) {\n if (part.fill) for (const u of part.flat.points) grow([u[0] - fr.ox, u[1] - fr.oy]);\n if (part.stroke) { sw = Math.max(sw, part.stroke.width); for (const l of part.flat.lines) for (const u of l.points) grow([u[0] - fr.ox, u[1] - fr.oy]); }\n }\n const pad = 2 + Math.ceil(sw * bucket);\n const ox = Math.ceil(-x0 * bucket) + pad;\n const oy = Math.ceil(-y0 * bucket) + pad;\n const w = ox + Math.ceil(x1 * bucket) + pad;\n const h = oy + Math.ceil(y1 * bucket) + pad;\n if (!(w > 0 && h > 0) || !Number.isFinite(w + h)) return false;\n if (w * h > PATH_SPRITE_MAX_PIXELS) { slot.off = true; return false; }\n if (this.pathBlitPixels + w * h > PATH_BLIT_MAX_PIXELS) return false;\n const made = this.makeCanvas(1);\n if (!made) return false;\n made.canvas.width = w;\n made.canvas.height = h;\n made.ctx.setTransform(1, 0, 0, 1, ox, oy);\n this.drawPathUnit(made.ctx, sprite, color, { sx: bucket, sy: bucket, ox: fr.ox, oy: fr.oy, uniform: true }, bucket);\n // x0/y0 hold the bitmap's origin offset (px from the drawing's centre) at `bucket` scale.\n hit = { canvas: made.canvas, x0: ox, y0: oy, px: w * h };\n this.pathBlitPixels += hit.px;\n slot.entries.set(key, hit);\n }\n const u = r / bucket; // user units per bitmap pixel\n ctx.save();\n ctx.translate(p.x, p.y);\n if (rot) ctx.rotate(rot);\n ctx.imageSmoothingEnabled = true;\n ctx.drawImage(hit.canvas, -hit.x0 * u, -hit.y0 * u, hit.canvas.width * u, hit.canvas.height * u);\n ctx.restore();\n return true;\n }\n\n private makeCanvas(n: number): { canvas: HTMLCanvasElement | OffscreenCanvas; ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D } | null {\n try {\n const canvas = typeof document !== 'undefined' ? document.createElement('canvas') : new OffscreenCanvas(n, n);\n canvas.width = n;\n canvas.height = n;\n const c = canvas.getContext('2d') as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;\n return c ? { canvas, ctx: c } : null;\n } catch {\n return null;\n }\n }\n\n /**\n * A feathered rect from a per-entity bitmap of it, pre-rendered at device\n * resolution with its rotation baked in, copied 1:1 at a whole-pixel\n * offset. A smooth falloff is a sampled image draw — on a CPU rasteriser\n * (a Raspberry Pi wall) ~3× the six flat fills it replaced, ~10× when\n * rotated and stretched — while a 1:1 integer copy costs about one flat\n * fill. The bitmap is rebuilt only when the rect's size, rotation or\n * feather changes (in device pixels, to a quarter pixel / 0.06°), and\n * re-tinted (one copy + one flat fill) only when its colour changes, so a\n * drifting block or a colour glide stays cheap. A rect whose shape\n * changes every frame (`grow`, `spin`), a canvas under a rotating or\n * mirroring transform, or a scene past the 8 Mpx cache budget draws the\n * stretched mask directly instead. Returns false when it did not draw.\n */\n private blitFeather(e: Entity, p: { x: number; y: number }, sz: number, rh: number, rot: number, color: string, feather: number): boolean {\n const ctx = this.ctx;\n const m = typeof ctx.getTransform === 'function' ? ctx.getTransform() : null;\n if (!m || m.b !== 0 || m.c !== 0 || m.a <= 0 || m.d <= 0) return false;\n const cos = Math.abs(Math.cos(rot));\n const sin = Math.abs(Math.sin(rot));\n const bw = Math.ceil((cos * sz + sin * rh) * m.a) + 2;\n const bh = Math.ceil((sin * sz + cos * rh) * m.d) + 2;\n const shapeKey = `${feather}|${Math.round(sz * m.a * 4)}|${Math.round(rh * m.d * 4)}|${Math.round(rot * 1000)}|${bw}x${bh}`;\n let b = this.featherBlits.get(e);\n if (!b || b.shapeKey !== shapeKey) {\n // A shape that changed since the previous frame is animating: draw it\n // directly rather than rebuild a bitmap every frame. Rebuild once it\n // has held still for a frame (or on first sight, so a static rect is\n // cached from its first paint).\n if (b) {\n if (b.seenKey !== shapeKey) { b.seenKey = shapeKey; b.seenAt = this.paintSeq; }\n if (b.seenAt === this.paintSeq) return false;\n }\n const px = bw * bh;\n const reuse = b && b.w === bw && b.h === bh;\n if (!reuse && this.featherBlitPx + px - (b ? b.w * b.h : 0) > 8_000_000) return false;\n const white = this.featherWhite.get(feather);\n if (!white) return false; // featherMask builds it; it ran just before this\n const wc = reuse ? b!.white : this.makeCanvas(1);\n const tc = reuse ? b!.tint : this.makeCanvas(1);\n if (!wc || !tc) return false;\n if (!reuse) {\n wc.canvas.width = bw; wc.canvas.height = bh;\n tc.canvas.width = bw; tc.canvas.height = bh;\n this.featherBlitPx += px - (b ? b.w * b.h : 0);\n }\n const w2 = wc.ctx;\n w2.setTransform(1, 0, 0, 1, 0, 0);\n w2.clearRect(0, 0, bw, bh);\n w2.translate(bw / 2, bh / 2);\n w2.scale(m.a, m.d);\n if (rot) w2.rotate(rot);\n w2.imageSmoothingEnabled = true;\n w2.drawImage(white, -sz / 2, -rh / 2, sz, rh);\n w2.setTransform(1, 0, 0, 1, 0, 0);\n b = { shapeKey, w: bw, h: bh, white: wc, tint: tc, tintKey: '', tintAt: 0, stagger: this.featherBlitN++ % 8, seenKey: shapeKey, seenAt: this.paintSeq };\n this.featherBlits.set(e, b);\n }\n // Re-tint on a colour change — at most every 8th frame mid-glide (a\n // ≤ 133 ms colour lag on a glide that takes seconds), immediately for a\n // new bitmap; entities are staggered across those 8 frames so a layer's\n // re-tints never land on one frame together.\n if (b.tintKey !== color && (b.tintKey === '' || this.paintSeq - b.tintAt >= 8)) {\n const t2 = b.tint.ctx;\n t2.setTransform(1, 0, 0, 1, 0, 0);\n t2.globalCompositeOperation = 'copy';\n t2.drawImage(b.white.canvas, 0, 0);\n t2.globalCompositeOperation = 'source-in';\n t2.fillStyle = color;\n t2.fillRect(0, 0, b.w, b.h);\n t2.globalCompositeOperation = 'source-over';\n b.tintKey = color;\n b.tintAt = this.paintSeq - (b.stagger ?? 0);\n b.stagger = 0;\n }\n const cx = m.a * p.x + m.e;\n const cy = m.d * p.y + m.f;\n ctx.save();\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.drawImage(b.tint.canvas, Math.round(cx - b.w / 2), Math.round(cy - b.h / 2));\n ctx.restore();\n return true;\n }\n\n /**\n * A feathered rect's mask in `color`: FEATHER_MASK_SIZE² texels of\n * `featherRamp(u) × featherRamp(v)`, drawn stretched to the rect with\n * smoothing on, so the falloff is continuous at any size (X383).\n *\n * The ramp itself is built ONCE per feather (a white alpha mask, the only\n * per-pixel work). A colour is a cheap tint of it — clear, draw the mask,\n * `source-in` fill — into a pooled canvas, cached per colour × feather.\n * A colour glide or a palette larger than the pool re-tints a pooled\n * canvas (three GPU draws) rather than rebuilding pixels in JS.\n */\n private featherMask(color: string, feather: number): HTMLCanvasElement | OffscreenCanvas | null {\n const key = `${color}|${feather}`;\n const hit = this.featherTints.get(key);\n if (hit) {\n // Most recently used last, so eviction takes the stalest tint.\n this.featherTints.delete(key);\n this.featherTints.set(key, hit);\n return hit.canvas;\n }\n const N = FEATHER_MASK_SIZE;\n let white = this.featherWhite.get(feather);\n if (!white) {\n const made = this.makeCanvas(N);\n if (!made) return null;\n const img = made.ctx.createImageData(N, N);\n const data = img.data;\n const ramp: number[] = [];\n for (let i = 0; i < N; i++) ramp.push(featherRamp((i + 0.5) / N, feather));\n let o = 0;\n for (let y = 0; y < N; y++) {\n const ry = ramp[y]!;\n for (let x = 0; x < N; x++) {\n data[o++] = 255;\n data[o++] = 255;\n data[o++] = 255;\n data[o++] = Math.round(255 * ry * ramp[x]!);\n }\n }\n made.ctx.putImageData(img, 0, 0);\n if (this.featherWhite.size >= 8) this.featherWhite.delete(this.featherWhite.keys().next().value!);\n white = made.canvas;\n this.featherWhite.set(feather, white);\n }\n let slot: { canvas: HTMLCanvasElement | OffscreenCanvas; ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D } | null = null;\n if (this.featherTints.size >= 48) {\n const oldest = this.featherTints.keys().next().value!;\n slot = this.featherTints.get(oldest)!;\n this.featherTints.delete(oldest);\n } else {\n slot = this.makeCanvas(N);\n if (!slot) return null;\n }\n const tctx = slot.ctx;\n tctx.globalCompositeOperation = 'copy';\n tctx.drawImage(white, 0, 0);\n tctx.globalCompositeOperation = 'source-in';\n tctx.fillStyle = color;\n tctx.fillRect(0, 0, N, N);\n tctx.globalCompositeOperation = 'source-over';\n this.featherTints.set(key, slot);\n return slot.canvas;\n }\n\n /**\n * Paint one entity at time `t`. `echo` paints a trail echo instead: the\n * entity as it was at `t` (rotation, heading, values), but at the echo's\n * position, size and alpha.\n */\n private drawEntity(built: Built, e: Entity, t: number, lifeA: number, parentE: Entity | null, paint?: PaintPass, echo?: { x: number; y: number; size: number; alpha: number }): void {\n const { ctx } = this;\n const p = echo ? { x: echo.x, y: echo.y, flip: false } : this.entityPos(e, t, parentE);\n const sprite = paint?.sprite ?? built.layer.sprite;\n const sz = echo ? echo.size : sizeAt(e, t);\n const rot = rotationAt(e, t);\n const unitScale = this.effSpec.units === 'px' ? 1 : Math.min(this.w, this.h);\n ctx.globalAlpha = echo ? echo.alpha : alphaAt(e, t) * lifeA * (paint?.alpha ?? 1);\n if (sprite.kind === 'ring') {\n const r = sz / 2;\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n ctx.strokeStyle = resolvedColor;\n ctx.lineWidth = Math.max(0.5, (sprite.width ?? (unitScale === 1 ? 2 : 0.002)) * unitScale);\n ctx.beginPath();\n ctx.arc(p.x, p.y, r, 0, Math.PI * 2);\n ctx.stroke();\n return;\n }\n if (sprite.kind === 'streak') {\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n const heading = (headingAt(e, t, this.w, this.h) ?? 0) + rot;\n const tailX = p.x - Math.cos(heading) * sz;\n const tailY = p.y - Math.sin(heading) * sz;\n const g = ctx.createLinearGradient(tailX, tailY, p.x, p.y);\n g.addColorStop(0, hexToRgba(resolvedColor, 0));\n g.addColorStop(1, resolvedColor);\n ctx.strokeStyle = g;\n ctx.lineWidth = Math.max(0.5, (sprite.width ?? (unitScale === 1 ? 2 : 0.002)) * unitScale);\n ctx.lineCap = 'round';\n ctx.beginPath();\n ctx.moveTo(tailX, tailY);\n ctx.lineTo(p.x, p.y);\n ctx.stroke();\n return;\n }\n if (sprite.kind === 'rect') {\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n const rh = e.size2 !== undefined\n ? e.size2 * (e.size > 0 ? sz / e.size : 1) // grow/warp scale height with width\n : sz;\n const feather = sprite.feather ?? 0;\n const mask = feather > 0 ? this.featherMask(resolvedColor, feather) : null;\n // Drawn from its cached, pre-rotated bitmap when it can be (see blitFeather).\n if (mask && this.blitFeather(e, p, sz, rh, rot, resolvedColor, feather)) return;\n ctx.save();\n ctx.translate(p.x, p.y);\n if (rot) ctx.rotate(rot);\n ctx.fillStyle = resolvedColor;\n if (mask) {\n // Soft edge (X383): one draw of a smooth alpha mask stretched to the\n // rect — the falloff is continuous, and a single draw composites\n // under every blend the way a hard rect does.\n const prevSmooth = ctx.imageSmoothingEnabled;\n ctx.imageSmoothingEnabled = true;\n ctx.drawImage(mask, -sz / 2, -rh / 2, sz, rh);\n ctx.imageSmoothingEnabled = prevSmooth;\n } else {\n ctx.fillRect(-sz / 2, -rh / 2, sz, rh);\n }\n ctx.restore();\n return;\n }\n if (sprite.kind === 'bar') {\n const len = sz * barFraction(sprite, e.barIndex ?? 0);\n if (len <= 0) return;\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n const th = e.size2 !== undefined ? e.size2 * (e.size > 0 ? sz / e.size : 1) : sz * 0.2;\n const box = barBox(sprite.direction ?? 'right', len, th);\n ctx.save();\n ctx.translate(p.x, p.y);\n if (rot) ctx.rotate(rot);\n ctx.fillStyle = resolvedColor;\n ctx.fillRect(box.cx - box.halfX, box.cy - box.halfY, box.halfX * 2, box.halfY * 2);\n ctx.restore();\n return;\n }\n if (sprite.kind === 'polygon') {\n const r = sz / 2;\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n if (isPathPolygon(sprite)) {\n const fr = pathFrame(sprite, r, this.w, this.h);\n if (pathDrawCost(sprite) >= PATH_BLIT_MIN_POINTS && !this.noPathCache && this.drawingSteady(built, sprite) && this.blitPath(sprite, p, r, rot, resolvedColor, fr)) return;\n ctx.save();\n ctx.translate(p.x, p.y);\n if (rot) ctx.rotate(rot);\n if (r > 0 && fr.sx > 0 && fr.sy > 0) this.drawPathUnit(ctx, sprite, resolvedColor, fr, r);\n ctx.restore();\n return;\n }\n ctx.save();\n ctx.translate(p.x, p.y);\n if (rot) ctx.rotate(rot);\n ctx.fillStyle = sprite.soft ? softFill(ctx, resolvedColor, r) : resolvedColor;\n const pts = polygonPoints(sprite, r);\n ctx.beginPath();\n ctx.moveTo(pts[0]!.x, pts[0]!.y);\n for (let i = 1; i < pts.length; i++) ctx.lineTo(pts[i]!.x, pts[i]!.y);\n ctx.closePath();\n ctx.fill(polygonFillRule(sprite));\n ctx.restore();\n return;\n }\n if (sprite.kind === 'stroke') {\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n const pts = strokeSamples(sprite, sz / 2);\n const lw = strokeWidthPx(sprite, unitScale);\n ctx.save();\n ctx.translate(p.x, p.y);\n let angle = rot;\n if (sprite.orient) angle += headingAt(e, t, this.w, this.h) ?? 0;\n if (angle) ctx.rotate(angle);\n ctx.strokeStyle = resolvedColor;\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n if (sprite.taper) {\n // A brush mark (X386): its tapered outline, filled once — so a\n // translucent stroke composites as one mark instead of beading at\n // every overlapping segment joint.\n const outline = strokeOutline(pts, lw);\n ctx.fillStyle = resolvedColor;\n ctx.beginPath();\n ctx.moveTo(outline[0]!.x, outline[0]!.y);\n for (let i = 1; i < outline.length; i++) ctx.lineTo(outline[i]!.x, outline[i]!.y);\n ctx.closePath();\n ctx.fill();\n } else {\n ctx.lineWidth = lw;\n ctx.beginPath();\n ctx.moveTo(pts[0]!.x, pts[0]!.y);\n for (let i = 1; i < pts.length; i++) ctx.lineTo(pts[i]!.x, pts[i]!.y);\n ctx.stroke();\n }\n ctx.restore();\n return;\n }\n if (sprite.kind === 'circle') {\n const r = sz / 2;\n const resolvedColor = sprite.colors?.[e.colorIndex] ?? sprite.color;\n ctx.save();\n if (rot) {\n ctx.translate(p.x, p.y);\n ctx.rotate(rot);\n ctx.translate(-p.x, -p.y);\n }\n if (sprite.soft) {\n const g = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, r);\n g.addColorStop(0, resolvedColor);\n g.addColorStop(0.35, hexToRgba(resolvedColor, 0.75));\n g.addColorStop(1, hexToRgba(resolvedColor, 0));\n ctx.fillStyle = g;\n } else {\n ctx.fillStyle = resolvedColor;\n }\n ctx.beginPath();\n ctx.arc(p.x, p.y, r, 0, Math.PI * 2);\n ctx.fill();\n ctx.restore();\n return;\n }\n if (sprite.kind === 'textBlock') {\n const unitScale = Math.min(this.w, this.h);\n const fsPx = sprite.fontSize * unitScale;\n const lh = (sprite.lineHeight ?? 1.4) * fsPx;\n const maxWPx = sprite.maxWidth * unitScale;\n const maxWEm = maxWPx / fsPx;\n const lines = breakTextBlock(sprite.text, maxWEm, textMetricsClassFor(sprite.font));\n const align = sprite.align ?? 'left';\n // Reveal masks glyphs; layout above always ran on the full text, so\n // lines never reflow while typing.\n const reveal = sprite.reveal;\n const rs = reveal ? revealState(lines, reveal, t) : null;\n const fullLines = rs ? rs.fullLines : lines.length;\n ctx.save();\n ctx.translate(p.x, p.y);\n if (rot) ctx.rotate(rot);\n if (sprite.anchor) {\n // `position` names a point of the rendered text, not the layout box's\n // top-left. Offset after line-breaking so the block's real extent\n // (widest line × lines) is what gets anchored; rotation stays about\n // the anchor point. Same arithmetic as perceive/advise (simulate.ts).\n const maxLineW = lines.reduce((m, l) => Math.max(m, l.widthEm), 0) * fsPx;\n const { dx, dy } = textBlockAnchorOffset(sprite, maxWPx, maxLineW, lines.length * lh);\n if (dx !== 0 || dy !== 0) ctx.translate(dx, dy);\n }\n // Paint-level alpha for the block only (layer `alpha` is baked per entity).\n if (sprite.opacity !== undefined) ctx.globalAlpha *= sprite.opacity;\n ctx.font = sprite.font ? composeFontShorthand(fsPx, sprite.font) : `${fsPx}px system-ui, sans-serif`;\n ctx.fillStyle = sprite.color ?? '#e6e8ef';\n ctx.textBaseline = 'top';\n ctx.textAlign = align;\n const xOff = align === 'center' ? maxWPx / 2 : align === 'right' ? maxWPx : 0;\n if (rs?.glyphAlphas) {\n // glyphFade: the contiguous fully-opaque leading run draws as ONE\n // fillText — a single draw forms ligatures and pair kerning exactly\n // like the un-revealed path (pixel parity once fully revealed), and it\n // drops the O(n²) per-frame prefix re-measure for glyphs that have\n // finished fading. Only the fading tail draws glyph-by-glyph, each at\n // its full-line prefix advance. measureText is paint-only (the caret's\n // trick) — positions come from the platform's real glyph widths, never\n // the em table, and depend only on the fixed prefix, so glyphs never\n // shift as they fade.\n ctx.textAlign = 'left';\n const baseAlpha = ctx.globalAlpha;\n for (let li = 0; li < lines.length; li++) {\n const alphas = rs.glyphAlphas[li] ?? [];\n if (alphas.length > 0 && alphas[0]! <= 0) break;\n const clusters = graphemeClusters(lines[li]!.text);\n const lw = ctx.measureText(lines[li]!.text).width;\n const x0 = align === 'center' ? (maxWPx - lw) / 2 : align === 'right' ? maxWPx - lw : 0;\n let opaque = 0;\n while (opaque < clusters.length && (alphas[opaque] ?? 0) >= 1) opaque++;\n let prefix = '';\n if (opaque > 0) {\n prefix = clusters.slice(0, opaque).join('');\n ctx.globalAlpha = baseAlpha;\n ctx.fillText(prefix, x0, li * lh);\n }\n for (let gi = opaque; gi < clusters.length; gi++) {\n const a = alphas[gi] ?? 0;\n if (a <= 0) break; // alphas only fall in reading order\n ctx.globalAlpha = baseAlpha * a;\n ctx.fillText(clusters[gi]!, x0 + ctx.measureText(prefix).width, li * lh);\n prefix += clusters[gi]!;\n }\n }\n ctx.globalAlpha = baseAlpha;\n } else {\n for (let li = 0; li < fullLines; li++) {\n ctx.fillText(lines[li]!.text, xOff, li * lh);\n }\n if (rs && rs.partialText.length > 0) {\n ctx.fillText(rs.partialText, xOff, fullLines * lh);\n }\n }\n if (rs && reveal!.caret) {\n const cfg = reveal!.caret === true ? {} : reveal!.caret;\n const hz = Math.min(3, cfg.blink ?? 1.2);\n const on = hz <= 0 || Math.floor((t / 1000) * hz * 2) % 2 === 0;\n if (on) {\n // measureText is paint-only here: it positions the caret against the\n // platform's real glyph widths but never influences layout, which\n // stays on the fixed metrics table.\n const pw = ctx.measureText(rs.caretPrefix).width;\n const cx = align === 'center' ? xOff + pw / 2 : align === 'right' ? xOff : pw;\n ctx.fillStyle = cfg.color ?? sprite.color ?? '#e6e8ef';\n ctx.fillRect(cx + fsPx * 0.06, rs.caretLine * lh, Math.max(1, fsPx * 0.08), fsPx);\n }\n }\n ctx.restore();\n return;\n }\n ctx.save();\n ctx.translate(p.x, p.y);\n if (rot) ctx.rotate(rot);\n if (p.flip && built.layer.flip) ctx.scale(-1, 1);\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n if (sprite.kind === 'emoji') {\n const idx = spriteIndexAt(e, t, sprite.glyphs.length);\n ctx.font = `${sz}px serif`;\n ctx.fillText(sprite.glyphs[idx] ?? sprite.glyphs[0]!, 0, 0);\n } else {\n ctx.textAlign = sprite.align ?? 'center';\n ctx.textBaseline = sprite.baseline ?? 'middle';\n // A full CSS shorthand (contains a px size) is used verbatim; a family/weight\n // only ('bold monospace') composes with the seeded per-entity size.\n ctx.font = sprite.font\n ? (FONT_PX_RE.test(sprite.font)\n ? scaleFontPx(sprite.font, this.fontScale())\n : composeFontShorthand(sz, sprite.font))\n : `${sz}px system-ui, sans-serif`;\n ctx.fillStyle = sprite.color ?? '#e6e8ef';\n const idx = spriteIndexAt(e, t, sprite.strings.length);\n const text = sprite.strings[idx] ?? sprite.strings[0]!;\n const mw = sprite.maxWidth ? sprite.maxWidth * (this.effSpec.units === 'px' ? 1 : Math.min(this.w, this.h)) : undefined;\n if (mw) ctx.fillText(text, 0, 0, mw);\n else ctx.fillText(text, 0, 0);\n }\n ctx.restore();\n }\n\n /** Advance any live steering glide; rebuild entities on structural change. */\n private stepTransition(t: number): void {\n const tr = this.transition;\n if (!tr) return;\n const k = tr.dur <= 0 ? 1 : (t - tr.startT) / tr.dur;\n this.effSpec = k >= 1 ? tr.to : lerpSpec(tr.from, tr.to, easeSmooth(k));\n if (k >= 1) this.transition = null;\n // Placement/motion fields are baked into entities at build time; rebuild\n // (deterministic — same seed → same stream) only when those change.\n const sig = structuralSignature(this.effSpec);\n if (sig !== this.lastStructural) this.rebuild();\n else this.layers.forEach((b, i) => { b.layer = this.effSpec.layers[i] ?? b.layer; });\n }\n\n /**\n * Live steering: glide from what's currently rendered to the track's target\n * state (deltas applied last-wins). Duration = the longest delta `dur`.\n */\n applyTrack(track: ControlTrack): void {\n const deltas = (track?.deltas ?? []) as unknown as SteerDelta[];\n if (this.authored) {\n const glide = deltas.length ? deltas.reduce((m, d) => Math.max(m, d.dur ?? DEFAULT_STEER_DUR), 0) : DEFAULT_STEER_DUR;\n if (!this.overrideAuthored(deltas, this.paused ? 0 : glide)) return;\n if (this.paused) this.renderFrame(this.sceneNow(), this.seed);\n return;\n }\n const target = applyDeltasToSpec(this.effSpec, deltas);\n if (!validateSpec(target).valid) return;\n const dur = deltas.length\n ? deltas.reduce((m, d) => Math.max(m, d.dur ?? DEFAULT_STEER_DUR), 0)\n : DEFAULT_STEER_DUR;\n this.transition = {\n from: JSON.parse(JSON.stringify(this.effSpec)) as SaverSpec,\n to: target,\n startT: this.lastT,\n dur,\n };\n if (this.paused) {\n // No frames will run the glide — jump straight to the target.\n this.transition = null;\n this.effSpec = target;\n if (structuralSignature(this.effSpec) !== this.lastStructural) this.rebuild();\n else this.layers.forEach((b, i) => { b.layer = this.effSpec.layers[i] ?? b.layer; });\n this.renderFrame(this.lastT, this.seed);\n }\n }\n\n /**\n * Apply steering deltas immediately: no glide, no frame painted. Each delta\n * is routed by `applyRetainedDeltas` (unresolvable or invalid ones are\n * skipped on this spec alone). `SequenceInstance` uses this to hand a\n * freshly created child the track the sequence has retained, so a steer\n * made while another segment was active lands on the segment that owns the\n * path. Not painting matters: a child is created inside the parent's\n * renderFrame, and a stray t=0 paint here would make the real frame that\n * follows look \"contiguous\" to the ghosting warm-up — but the constructor\n * already painted ONE stray t=0 frame of the pre-steer spec (SpecInstance's\n * own mount does an immediate render when paused, which every sequence\n * child is), so `lastRenderT` must be reset too: otherwise, with `ghosting`\n * on, the real frame that follows still finds itself \"contiguous\" with\n * that stray paint and composites over it at partial alpha, briefly\n * showing a ghost of the un-steered scene.\n */\n applyDeltasNow(deltas: Iterable<SteerDelta>): void {\n if (this.authored) {\n // Retained steers land under the timeline's steering rule — as one\n // batch when they validate together (one composed check), else per\n // delta, skipping any that don't (as `applyRetainedDeltas` does).\n const all = [...deltas];\n if (!this.overrideAuthored(all, 0)) for (const d of all) this.overrideAuthored([d], 0);\n this.transition = null;\n this.lastRenderT = Number.NEGATIVE_INFINITY;\n return;\n }\n const next = applyRetainedDeltas(this.effSpec, deltas);\n if (next === this.effSpec) return;\n this.transition = null;\n this.lastRenderT = Number.NEGATIVE_INFINITY;\n this.effSpec = next;\n if (structuralSignature(this.effSpec) !== this.lastStructural) this.rebuild();\n else this.layers.forEach((b, i) => { b.layer = this.effSpec.layers[i] ?? b.layer; });\n }\n\n private drawLinks(built: Built, t: number, lifeA: number, parentE: Entity | null): void {\n const { links } = built.layer;\n if (!links) return;\n const { ctx } = this;\n // Toroidal link drawing only makes sense for motions that actually wrap —\n // bounce/orbit/path entities never cross an edge, so a \"nearest image\" line\n // would cut across the screen.\n const motionWraps = ['drift', 'rise', 'wander'].includes(built.layer.motion.type);\n const wrap = built.layer.wrap !== false && motionWraps;\n const positions = built.entities.map((e) => this.entityPos(e, t, parentE));\n const unitScale = this.effSpec.units === 'px' ? 1 : Math.min(this.w, this.h);\n const maxDistPx = linkMaxDistPx(links, unitScale);\n const edges = linkEdges(links, positions, maxDistPx, wrap, this.w, this.h);\n const defaultWidth = unitScale === 1 ? 1 : 1 / LIMITS.referenceViewport;\n const lw = (links.width ?? defaultWidth) * unitScale;\n ctx.lineWidth = lw;\n ctx.lineCap = 'butt'; // streak sprites set 'round'; reset so link ends stay crisp\n\n for (const { i, j, dist } of edges) {\n const pi = positions[i]!;\n const pj = positions[j]!;\n const ei = built.entities[i]!;\n let resolvedColor = links.color;\n if (!resolvedColor) {\n const sprite = built.layer.sprite;\n if (isShapedSprite(sprite)) {\n resolvedColor = sprite.colors?.[ei.colorIndex] ?? sprite.color;\n } else resolvedColor = '#e6e8ef';\n }\n let a = links.alpha ?? alphaAt(ei, t);\n if (links.falloff && Number.isFinite(maxDistPx)) a *= Math.max(0, 1 - dist / maxDistPx);\n ctx.globalAlpha = a * lifeA;\n ctx.strokeStyle = resolvedColor;\n // Draw toward nearest image of pj (avoids full-canvas streaks at wrap seams)\n let dx = pj.x - pi.x;\n let dy = pj.y - pi.y;\n if (wrap) {\n if (Math.abs(dx) > this.w / 2) dx = dx > 0 ? dx - this.w : dx + this.w;\n if (Math.abs(dy) > this.h / 2) dy = dy > 0 ? dy - this.h : dy + this.h;\n }\n ctx.beginPath();\n ctx.moveTo(pi.x, pi.y);\n ctx.lineTo(pi.x + dx, pi.y + dy);\n ctx.stroke();\n }\n }\n\n /** Paint one composite pass at time t. `bgAlpha` < 1 leaves the previous frame\n * showing through — the ghosting smear. */\n private paintFrame(t: number, bgAlpha: number): void {\n const { ctx } = this;\n this.paintSeq++;\n if (this.authored) this.resolveAuthored(t);\n if (!this.transparent) {\n ctx.globalAlpha = bgAlpha;\n ctx.globalCompositeOperation = 'source-over';\n this.drawBackground(t);\n }\n ctx.globalAlpha = 1;\n const n = this.layers.length;\n for (let li = 0; li < n; li++) {\n // A run of unchanging drawing layers paints from one composited plate.\n if (!this.noPathCache && this.plateable(li, t)) {\n let j = li;\n while (j + 1 < n && this.plateable(j + 1, t)) j++;\n if (j > li && this.runPoints(li, j) >= PLATE_MIN_POINTS && this.paintPlate(li, j, t)) { li = j; continue; }\n }\n this.paintLayer(li, t);\n }\n ctx.globalAlpha = 1;\n ctx.globalCompositeOperation = 'source-over';\n }\n\n /** Paint layer `li` at time t onto this.ctx (the scene canvas, or a plate being rebuilt). */\n private paintLayer(li: number, t: number): void {\n const { ctx } = this;\n const built = this.layers[li]!;\n const opacity = built.layer.opacity;\n // A grouped layer paints through its group too (`groups`): opacity\n // multiplies, the group's transform wraps the layer's own. Ungrouped\n // layers take exactly the path they always have.\n const group = built.layer.group === undefined ? undefined : this.effSpec.groups?.[built.layer.group];\n let lifeA = opacity === undefined ? lifeAlphaAt(built.layer.life, t) : lifeAlphaAt(built.layer.life, t) * clamp01(opacity);\n if (group?.opacity !== undefined) lifeA *= clamp01(group.opacity);\n if (lifeA <= 0) return;\n const parentE = this.parentEntityFor(built);\n const tf = built.layer.transform;\n const gtf = group?.transform;\n if (tf || gtf) {\n ctx.save();\n if (gtf) this.applyLayerTransform(gtf, null);\n if (tf) this.applyLayerTransform(tf, built.layer);\n }\n ctx.globalCompositeOperation = built.layer.blend ?? 'source-over';\n this.drawLinks(built, t, lifeA, parentE);\n const override = this.paintOverrides?.get(li) ?? null;\n for (const e of built.entities) {\n this.drawTrail(built, e, t, lifeA, parentE);\n if (override === null) {\n this.drawEntity(built, e, t, lifeA, parentE);\n continue;\n }\n // A text cross-fade: the previous words fading out under the new\n // ones fading in. Either pass at alpha 0 is skipped, so k = 0 and\n // k = 1 each cost exactly one draw, like a plain frame.\n const [aOut, aIn] = override.mode === 'dip'\n ? [Math.max(0, 1 - 2 * override.k), Math.max(0, 2 * override.k - 1)]\n : [1 - override.k, override.k];\n if (aOut > 0) this.drawEntity(built, e, t, lifeA, parentE, { sprite: override.outgoing, alpha: aOut });\n if (aIn > 0) this.drawEntity(built, e, t, lifeA, parentE, { alpha: aIn });\n }\n if (tf || gtf) ctx.restore();\n }\n\n /**\n * Static plates. Consecutive path-polygon layers painted source-over, with\n * no trails, links or text overrides, are composited into ONE full-frame\n * bitmap and copied once per frame while nothing they draw has changed —\n * the change test is the drawn values themselves (each entity's position,\n * size, rotation, alpha and colour, the layer's life alpha and transforms),\n * so anything animated simply repaints its plate that frame. Source-over is\n * associative, so the plate over the frame equals the layers over it.\n */\n private readonly plates = new Map<number, { canvas: HTMLCanvasElement | OffscreenCanvas; ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D; end: number; sig: string; box: { x: number; y: number; w: number; h: number }; frameW: number; frameH: number }>();\n\n /** Outline points a run of path layers fills per frame (points × entities). */\n private runPoints(a: number, b: number): number {\n let n = 0;\n for (let li = a; li <= b; li++) {\n const built = this.layers[li]!;\n const sp = built.layer.sprite;\n if (sp.kind === 'polygon' && isPathPolygon(sp)) n += pathDrawCost(sp) * built.entities.length;\n }\n return n;\n }\n\n /** Last drawn-value signature per layer, for plate stability. */\n private readonly layerSigs = new Map<number, string>();\n\n /**\n * A layer joins a plate only if it can (path polygon, source-over, no\n * trails/links/text override) AND nothing it draws changed since the last\n * frame — so a pulsing or moving layer splits the run and paints live, while\n * the static layers around it keep their plates.\n */\n private plateable(li: number, t: number): boolean {\n const built = this.layers[li]!;\n const l = built.layer;\n const sp = l.sprite;\n if (!isPathPolygon(sp)) return false;\n if ((l.blend ?? 'source-over') !== 'source-over') return false;\n if (l.trail || l.links || this.paintOverrides?.has(li)) return false;\n if (built.entities.length > 64) return false;\n const sig = this.layerSig(li, t);\n const prev = this.layerSigs.get(li);\n this.layerSigs.set(li, sig);\n return prev === sig;\n }\n\n private layerSig(li: number, t: number): string {\n const built = this.layers[li]!;\n const group = built.layer.group === undefined ? undefined : this.effSpec.groups?.[built.layer.group];\n const opacity = built.layer.opacity;\n let lifeA = opacity === undefined ? lifeAlphaAt(built.layer.life, t) : lifeAlphaAt(built.layer.life, t) * clamp01(opacity);\n if (group?.opacity !== undefined) lifeA *= clamp01(group.opacity);\n let sig = `${pathPaintSig(built.layer.sprite as PolygonSprite)}:${lifeA.toFixed(4)}:${JSON.stringify(built.layer.transform ?? null)}:${JSON.stringify(group?.transform ?? null)}`;\n const parentE = this.parentEntityFor(built);\n for (const e of built.entities) {\n const p = this.entityPos(e, t, parentE);\n sig += `|${p.x.toFixed(2)},${p.y.toFixed(2)},${sizeAt(e, t).toFixed(3)},${rotationAt(e, t).toFixed(5)},${alphaAt(e, t).toFixed(4)},${e.colorIndex}`;\n }\n return sig;\n }\n\n private plateSig(a: number, b: number): string {\n let sig = `${a}-${b}`;\n for (let li = a; li <= b; li++) sig += `#${this.layerSigs.get(li)}`;\n return sig;\n }\n\n /** Max |point| of a path polygon's unit outline (its reach as a fraction of the entity radius). */\n private readonly pathReach = new WeakMap<object, number>();\n private reachOf(sp: PolygonSprite): number {\n let r = this.pathReach.get(sp);\n if (r === undefined) {\n r = 0;\n let sw = 0;\n for (const part of pathParts(sp)) {\n for (const [x, y] of part.flat.points) r = Math.max(r, Math.hypot(x, y));\n for (const l of part.flat.lines) for (const [x, y] of l.points) r = Math.max(r, Math.hypot(x, y));\n if (part.stroke) sw = Math.max(sw, part.stroke.width);\n }\n r += sw;\n this.pathReach.set(sp, r || 1);\n }\n return r || 1;\n }\n\n /**\n * Device-pixel box a run of layers can paint into, or null for \"the whole\n * frame\" (a layer/group transform moves things in ways this does not model).\n */\n private runBox(a: number, b: number, t: number): { x: number; y: number; w: number; h: number } | null {\n const m = this.ctx.getTransform();\n if (Math.abs(m.b) > 1e-9 || Math.abs(m.c) > 1e-9) return null;\n let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;\n for (let li = a; li <= b; li++) {\n const built = this.layers[li]!;\n const group = built.layer.group === undefined ? undefined : this.effSpec.groups?.[built.layer.group];\n if (built.layer.transform || group?.transform) return null;\n const reach = this.reachOf(built.layer.sprite as PolygonSprite);\n const parentE = this.parentEntityFor(built);\n for (const e of built.entities) {\n const p = this.entityPos(e, t, parentE);\n const sp = built.layer.sprite as PolygonSprite;\n const fr = pathFrame(sp, sizeAt(e, t) / 2, this.w, this.h);\n const ext = Math.max(fr.sx, fr.sy) * (reach + Math.hypot(fr.ox, fr.oy));\n x0 = Math.min(x0, p.x - ext); x1 = Math.max(x1, p.x + ext);\n y0 = Math.min(y0, p.y - ext); y1 = Math.max(y1, p.y + ext);\n }\n }\n const W = this.canvas.width, H = this.canvas.height;\n const bx = Math.max(0, Math.floor(m.a * x0 + m.e) - 2);\n const by = Math.max(0, Math.floor(m.d * y0 + m.f) - 2);\n const bw = Math.min(W, Math.ceil(m.a * x1 + m.e) + 2) - bx;\n const bh = Math.min(H, Math.ceil(m.d * y1 + m.f) + 2) - by;\n return bw > 0 && bh > 0 ? { x: bx, y: by, w: bw, h: bh } : { x: 0, y: 0, w: 0, h: 0 };\n }\n\n /** Paint layers a..b from their plate, rebuilding it if anything drawn changed. False = paint them normally. */\n private paintPlate(a: number, b: number, t: number): boolean {\n const sig = this.plateSig(a, b);\n let plate = this.plates.get(a);\n if (!plate || plate.sig !== sig || plate.end !== b || plate.frameW !== this.canvas.width || plate.frameH !== this.canvas.height) {\n const box = this.runBox(a, b, t) ?? { x: 0, y: 0, w: this.canvas.width, h: this.canvas.height };\n if (!plate) {\n if (this.plates.size >= 4) this.plates.delete(this.plates.keys().next().value!);\n const made = this.makeCanvas(1);\n if (!made) return false;\n plate = { ...made, end: b, sig: '', box, frameW: 0, frameH: 0 };\n this.plates.set(a, plate);\n }\n plate.box = box;\n plate.frameW = this.canvas.width;\n plate.frameH = this.canvas.height;\n if (box.w === 0 || box.h === 0) { plate.sig = sig; plate.end = b; return true; }\n if (plate.canvas.width !== box.w) plate.canvas.width = box.w;\n if (plate.canvas.height !== box.h) plate.canvas.height = box.h;\n const pc = plate.ctx;\n pc.setTransform(1, 0, 0, 1, 0, 0);\n pc.globalAlpha = 1;\n pc.globalCompositeOperation = 'source-over';\n pc.clearRect(0, 0, box.w, box.h);\n const m = this.ctx.getTransform();\n pc.setTransform(m.a, m.b, m.c, m.d, m.e - box.x, m.f - box.y);\n const self = this as unknown as { ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D };\n const main = self.ctx;\n self.ctx = pc;\n try {\n for (let li = a; li <= b; li++) this.paintLayer(li, t);\n } finally {\n self.ctx = main;\n }\n plate.sig = sig;\n plate.end = b;\n }\n if (plate.box.w === 0 || plate.box.h === 0) return true;\n const ctx = this.ctx;\n ctx.save();\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.globalAlpha = 1;\n ctx.globalCompositeOperation = 'source-over';\n ctx.drawImage(plate.canvas, plate.box.x, plate.box.y);\n ctx.restore();\n return true;\n }\n\n /**\n * A `transform`, in min(w,h) units (px under `units: 'px'`), about the\n * viewport centre — or, with `origin: 'anchor'`, about `layer`'s own anchor\n * (a group's transform passes no layer: always the viewport centre).\n */\n private applyLayerTransform(tf: LayerTransform, layer: LayerSpec | null): void {\n const { ctx, w, h } = this;\n const unit = this.effSpec.units === 'px' ? 1 : Math.min(w, h);\n const { x: cx, y: cy } = transformOrigin(tf, layer, w, h, unit);\n ctx.translate(cx + (tf.x ?? 0) * unit, cy + (tf.y ?? 0) * unit);\n if (tf.rotate) ctx.rotate((tf.rotate * Math.PI) / 180);\n const s = tf.scale ?? 1;\n ctx.scale(s * (tf.scaleX ?? 1), s);\n ctx.translate(-cx, -cy);\n }\n\n /** Scene time for a timeline decision: the last painted frame's, else the loop clock's. */\n private sceneNow(): number {\n return this.lastRenderT !== Number.NEGATIVE_INFINITY ? this.lastRenderT : this.lastT;\n }\n\n /** Resolve the authored timeline at `t`, layer the live overrides on top, and adopt the result. */\n private resolveAuthored(t: number): void {\n const expired: string[] = [];\n const spec = applyOverridesAt(resolveTimelineAt(this.authored!, t), this.overrides, t, expired);\n for (const p of expired) this.overrides.delete(p);\n this.effSpec = spec;\n const sig = structuralSignature(spec);\n if (sig !== this.lastStructural) this.rebuild();\n else this.layers.forEach((b, i) => { b.layer = spec.layers[i] ?? b.layer; });\n }\n\n /** Register live steers on a timeline scene under the steering rule (see `overrides`). */\n private overrideAuthored(deltas: readonly SteerDelta[], glide: number): boolean {\n const now = this.sceneNow();\n const shown = this.effSpec;\n // One steer per field: a re-sent track can carry several deltas that\n // address the same field (an appended track, key- and index-form paths),\n // and only the last is the steer — otherwise each re-send would flip the\n // dedup id below and re-arm a hold the timeline already took back.\n const latest = new Map<string, SteerDelta>();\n for (const d of deltas) {\n const path = canonicalSpecPath(shown, d.path);\n if (!path) continue;\n latest.delete(path);\n latest.set(path, d);\n }\n const next = new Map(this.overrides);\n const armed: Array<[string, string]> = [];\n for (const [path, d] of latest) {\n const id = steerId(d);\n if (this.seenSteers.get(path) === id) continue;\n armed.push([path, id]);\n next.set(path, armOverride(this.authored!, path, glide > 0 ? readSpecPath(shown, path) : d.value, d.value, now, glide));\n }\n if (armed.length === 0) return true;\n // Validate the scene as it will actually be — every live override, now\n // and at each key still ahead — not the new deltas alone.\n if (!overridesStayValid(this.authored!, next, now)) return false;\n for (const [p, id] of armed) this.seenSteers.set(p, id);\n this.overrides = next;\n return true;\n }\n\n /** A copy of the live overrides — a sequence carries them into a morph's outgoing endpoint. */\n timelineOverrides(): Map<string, TimelineOverride> | null {\n return this.authored ? new Map(this.overrides) : null;\n }\n\n /** A copy of which server steers this child already applied, per field (see `seenSteers`). */\n timelineSeen(): Map<string, string> {\n return new Map(this.seenSteers);\n }\n\n /** The spec painted by the last frame (timeline and overrides resolved). */\n presentedSpec(): SaverSpec {\n return this.effSpec;\n }\n\n /**\n * Deterministic, frame-addressable render (shared by the rAF loop).\n *\n * With `ghosting` set, contiguous frames composite over the previous frame with a\n * refresh-rate-normalized fade. A non-contiguous seek (pause render, e2e frame\n * addressing) replays a bounded fixed-step warm-up from a full clear, so the\n * accumulated smear at time t is identical on every run — the determinism proof\n * survives statefulness because the \"state\" is reconstructed from pure history.\n */\n renderFrame(t: number, _seed: number): void {\n this.stepTransition(t);\n const g = this.transparent ? 0 : (this.effSpec.ghosting ?? 0);\n if (g > 0) {\n const dt = 1000 / 60;\n const contiguous = this.lastRenderT !== Number.NEGATIVE_INFINITY\n && t > this.lastRenderT\n && t - this.lastRenderT <= 250;\n if (contiguous) {\n this.paintFrame(t, 1 - Math.pow(g, (t - this.lastRenderT) / dt));\n } else {\n const k = Math.min(Math.ceil(Math.log(1 / 255) / Math.log(g)), LIMITS.maxGhostReplayFrames);\n const t0 = Math.max(0, t - k * dt);\n this.paintFrame(t0, 1);\n for (let ft = t0 + dt; ft < t - dt / 2; ft += dt) this.paintFrame(ft, 1 - g);\n if (t > t0) this.paintFrame(t, 1 - g);\n }\n } else {\n this.paintFrame(t, 1);\n }\n this.lastRenderT = t;\n // Presentation, last of all: the finished scene (ghosting included) is\n // copied to the visible canvas and the finish screened over the copy —\n // after persistence has done its work, and never into it.\n if (this.finishPass) presentWithFinish(this.finishPass, this.canvas, this.w, this.h, t, this.effSpec.finish, this.animateFinish);\n }\n\n setPaused(paused: boolean): void {\n this.paused = paused;\n if (paused) {\n this.stop();\n } else {\n this.start();\n }\n }\n\n resize(width: number, height: number, dpr?: number): void {\n this.w = width;\n this.h = height;\n if (dpr !== undefined) this.saverCtx.dpr = dpr;\n this.sizeCanvas();\n this.rebuild();\n if (this.paused) this.renderFrame(0, this.seed);\n }\n\n /**\n * Replace the rendered spec without triggering a transition glide.\n * Checks structural signature — use `hotSwapPaint` only when the caller\n * already knows the signature is unchanged.\n */\n hotSwapSpec(spec: SaverSpec): void {\n this.adoptAuthored(spec);\n if (this.authored) { this.resolveAuthored(this.sceneNow()); return; }\n this.effSpec = spec;\n const sig = structuralSignature(this.effSpec);\n if (sig !== this.lastStructural) this.rebuild();\n else this.layers.forEach((b, i) => { b.layer = this.effSpec.layers[i] ?? b.layer; });\n }\n\n /**\n * Track whether `spec` carries a timeline. Live overrides belong to the\n * scene they were made on: a different spec (a new publish, a sequence's\n * re-steered segment, a morph frame) drops them, as a plain hot-swap\n * replaces `effSpec` wholesale; the host re-sends the live track.\n */\n private adoptAuthored(spec: SaverSpec, keepSteers = false): void {\n const next = spec.timeline ? spec : null;\n if (next !== this.authored && !(keepSteers && next && this.authored)) {\n this.overrides.clear();\n this.seenSteers.clear();\n }\n this.authored = next;\n }\n\n /**\n * A sequence's hot swap of a timeline segment: the new scene replaces the\n * old, but the live steers (and which server steers were already applied)\n * carry over — a steer the timeline already took back stays taken back —\n * and only a steer this child has never seen is armed, now. Frame\n * continuity is kept, so ghosting trails do not restart.\n */\n hotSwapKeepingSteers(spec: SaverSpec, retained: Iterable<SteerDelta>): void {\n if (!spec.timeline) {\n this.hotSwapSpec(spec);\n return;\n }\n if (!this.authored) {\n // The swap adds a timeline: the old scene carried the retained steers\n // baked in, the new one takes them as live steers from here.\n this.hotSwapSpec(spec);\n this.applyDeltasNow(retained);\n return;\n }\n this.adoptAuthored(spec, true);\n for (const d of retained) this.overrideAuthored([d], 0);\n this.resolveAuthored(this.sceneNow());\n }\n\n /** Arm a steer made while a sequence was mid-morph, on the outgoing end's override set, at that end's scene time. */\n static armInto(authored: SaverSpec, overrides: Map<string, TimelineOverride>, seen: Map<string, string>, deltas: readonly SteerDelta[], now: number): void {\n const at = resolveTimelineAt(authored, now);\n // As `overrideAuthored`: the last delta per field is the steer, and a\n // re-sent one (the host re-broadcasts the whole track) is not re-armed.\n const latest = new Map<string, SteerDelta>();\n for (const d of deltas) {\n const path = canonicalSpecPath(at, d.path);\n if (!path) continue;\n latest.delete(path);\n latest.set(path, d);\n }\n for (const [path, d] of latest) {\n const id = steerId(d);\n if (seen.get(path) === id) continue;\n const trial = new Map(overrides).set(path, armOverride(authored, path, d.value, d.value, now, 0));\n if (overridesStayValid(authored, trial, now)) {\n overrides.set(path, trial.get(path)!);\n seen.set(path, id);\n }\n }\n }\n\n /** Paint-only hot-swap: skips structuralSignature (caller guarantees match). */\n hotSwapPaint(spec: SaverSpec): void {\n this.adoptAuthored(spec);\n if (this.authored) { this.resolveAuthored(this.sceneNow()); return; }\n this.effSpec = spec;\n this.layers.forEach((b, i) => { b.layer = this.effSpec.layers[i] ?? b.layer; });\n }\n\n /**\n * Internal (see `LayerPaintOverride`): draw the listed layers twice —\n * outgoing sprite at `1 − k`, own sprite at `k` — until cleared with\n * `null`. Keyed by layer index. A `SequenceInstance` sets it per morph\n * frame under `text: 'crossfade'`; nothing else does.\n */\n setLayerPaintOverrides(overrides: ReadonlyMap<number, LayerPaintOverride> | null): void {\n this.paintOverrides = overrides && overrides.size > 0 ? overrides : null;\n }\n\n dispose(): void {\n this.stop();\n this.field = null; // the raster canvas was never attached; dropping the reference frees it\n // With a finish, the visible canvas is the pass's and `this.canvas` is\n // the offscreen scene (never attached) — drop the pass and its tiles.\n const visible = this.finishPass?.canvas ?? this.canvas;\n this.finishPass = null;\n if (this.ownsCanvas && typeof HTMLCanvasElement !== 'undefined' && visible instanceof HTMLCanvasElement) visible.remove();\n }\n}\n\n/**\n * Compile a declarative spec into a runnable SaverPlugin. Throws if the spec is invalid\n * (so an agent-authored spec is validated before it can run). The result is seeded,\n * deterministic, `renderFrame(t,seed)`-addressable, and flash-safe by construction.\n */\nexport function compileSaver(spec: unknown): SaverPlugin {\n const valid = assertValidSpec(spec);\n return {\n manifest: manifestFor(valid),\n mount: (ctx: SaverContext) => new SpecInstance(valid, ctx, { capabilityTier: (ctx as SpecMountContext).capabilityTier }),\n spec: valid,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Sequence — multi-segment timeline compiled as a single SaverPlugin\n// ---------------------------------------------------------------------------\n\n/**\n * Mount context for a compiled sequence. A plain `SaverContext` works — the\n * clock starts at 0, as every SaverPlugin's does. `sequenceBaseT` is read\n * only when the sequence declares `sync: 'epoch'`; hosts pass the shared\n * clock's elapsed ms (idlescreens.com: `Date.now() − scene.epoch`) so every\n * viewer of that sequence resolves the same segment.\n */\nexport interface SequenceMountContext extends SpecMountContext {\n /** ms already elapsed on the shared sequence clock. Ignored unless `sync: 'epoch'`. */\n sequenceBaseT?: number;\n /**\n * See `SpecMountContext.capabilityTier`. A `fade` transition keeps two\n * segments live for `dur`, which `basic` (canvas2d only) and `minimal`\n * cannot afford: on those tiers fade renders as `cut`. The tier is also\n * handed to every child and the bed (a `field` background's raster steps\n * down with it). Absent ⇒ fade enabled, full resolution.\n */\n capabilityTier?: CapabilityTier;\n}\n\n/** A segment child on a canvas of its own, composited onto the shared surface during a `fade`. */\ninterface OffscreenChild {\n index: number;\n child: SpecInstance;\n canvas: HTMLCanvasElement | OffscreenCanvas;\n}\n\n/** `bed.<path>` routes a steer to the sequence's bed when one exists. */\nconst BED_PREFIX = 'bed.';\n\n/**\n * What `compileSequence().mount()` returns: a `SaverInstance` that can also\n * take a republished sequence in place. Hosts feature-detect it with\n * `hasHotSwapSequence` (an older engine's instance simply lacks the method)\n * and fall through to a remount when it returns `false`.\n */\nexport interface SequenceSaverInstance extends SaverInstance {\n renderFrame(t: number, seed: number): void;\n applyTrack(track: ControlTrack): void;\n /**\n * Swap `next` in for the running sequence without remounting, when the\n * two are `sequenceSwapCompatible`: every live segment child (and the bed)\n * hot-swaps to its new scene, the clock, the active segment, every\n * released hold and the retained track stay exactly where they were, and\n * the next frame resolves to the same `(segment, localT)` as if nothing\n * had happened — a mid-show caption fix that does not send the room back\n * to segment 0. Returns `false` and changes nothing when the sequences are\n * not compatible (a structural or timing edit); the host remounts then.\n */\n hotSwapSequence(next: IdleSequence): boolean;\n}\n\n/** `compileSequence`'s plugin: `mount` is typed to the sequence instance and `spec` to the validated sequence. */\nexport interface SequenceSaverPlugin extends SaverPlugin {\n mount(ctx: SequenceMountContext): SequenceSaverInstance;\n spec: IdleSequence;\n}\n\n/** Feature-detect `hotSwapSequence` on any mounted instance (false for a plain scene, or a sequence from an older engine). */\nexport function hasHotSwapSequence(inst: SaverInstance): inst is SequenceSaverInstance {\n return typeof (inst as { hotSwapSequence?: unknown }).hotSwapSequence === 'function';\n}\n\nclass SequenceInstance implements SequenceSaverInstance {\n /** Replaced wholesale by `hotSwapSequence`; every per-segment lookup (`segmentStart`, `canMorph`, `childScene`) reads it live, so there are no derived tables to refresh. */\n private seq: IdleSequence;\n private readonly childCtx: SaverContext;\n private readonly canvas: HTMLCanvasElement | null;\n private readonly children: (SpecInstance | null)[];\n private activeIndex = -1;\n private paused = false;\n /**\n * When a morph is active, the child at `morphFromIndex` renders with a\n * lerped spec. The child stays keyed to the *outgoing* segment's slot so\n * its seed (and entity placement) is continuous.\n */\n private morphFromIndex = -1;\n private readonly seed: number;\n private frameId: number | null = null;\n private startT = 0;\n private baseT = 0;\n private lastT = 0;\n /** The T most recently passed to renderFrame — the clock a steer displaces. */\n private renderedT = 0;\n /**\n * The clicker's two pieces of state. `clockOffset` is added to every T so\n * a `sequence.segment` steer lands the timeline at the target segment's\n * start and STAYS there as the wall clock keeps ticking — the steer moves\n * the clock instead of fighting it. `releasedBelow` records that the steer\n * counts as the presenter clicking past every `advance: 'input'` hold\n * before the target (see `resolveSegment`).\n */\n private clockOffset = 0;\n private releasedBelow = 0;\n /**\n * Set by a `sequence.segment` steer that targets segment 0 under `loop:\n * true`: the steer resets the clock to segment 0's own start (localT 0),\n * so `renderFrame`'s wrap check (which compares the raw, ever-increasing\n * clock against `timedTotal()`) can no longer recognize the jump as a\n * wrap. This flag lets the clicker's jump to 0 still count as one, so the\n * last segment's fade plays instead of a hard cut. Cleared once the wrap\n * window (if any) has passed.\n */\n private pendingWrapFade = false;\n /** The morph in progress: its ends, and the override sets each end resolves with (see `morphEndpoint`). */\n private morphEnds: { from: number; to: number; outT: number; out: Map<string, TimelineOverride> | null; seenOut: Map<string, string>; in: Map<string, TimelineOverride> | null } | null = null;\n /**\n * Every non-`sequence.segment` delta this instance has been handed, last\n * wins per path, merged across `applyTrack` calls. Children are created\n * lazily and disposed on every segment switch, so a steer forwarded only\n * to the active child would evaporate at the next boundary — and a steer\n * to a path only a *later* segment owns (`bars.sprite.values` while the title\n * slide is up) would land nowhere. Re-applied to every child on creation\n * and folded into the morph endpoints; each child keeps the deltas that\n * resolve on it (see `applyRetainedDeltas`).\n */\n private readonly retainedDeltas = new Map<string, SteerDelta>();\n /**\n * Every `bed.<path>` delta (prefix stripped, last wins per path). The bed\n * is never re-created, so these are applied to it once on arrival — the\n * map exists only so `hotSwapSequence` can put a steered bed colour back\n * after the bed takes its republished scene. Absent a swap it is never read.\n */\n private readonly retainedBedDeltas = new Map<string, SteerDelta>();\n /** The outgoing segment while a `fade` runs; null otherwise. */\n private fading: OffscreenChild | null = null;\n /**\n * The incoming segment while a `fade` runs over a `bed`. Children over a\n * bed are transparent, so a cross-fade needs both of them on canvases of\n * their own — the incoming composited at k, the outgoing at 1 − k. Without\n * a bed the incoming paints its own opaque ground on the shared surface and\n * this stays null.\n */\n private fadingIn: OffscreenChild | null = null;\n /** False on the `basic`/`minimal` capability tiers — fade renders as cut. */\n private readonly fadeEnabled: boolean;\n /** The mount's tier, handed to every child and the bed. */\n private readonly capabilityTier: CapabilityTier | undefined;\n /**\n * The sequence's presentation pass when it — or any segment — declares a\n * `finish`: children and the bed draw into an offscreen scene canvas\n * (`childCtx.surface`), and every frame ends by copying it to the visible\n * surface with the finish screened over the copy — once per composed\n * frame, bed + segment + fade together. Null when no finish is declared\n * anywhere: children draw straight onto the visible surface, as before.\n */\n private readonly finishPass: FinishPass | null = null;\n /** False on the `basic`/`minimal` tiers — `finish.animate` renders as a static tile. */\n private readonly animateFinish: boolean;\n /**\n * The sequence's `bed`: one scene on the shared surface, drawn first every\n * frame at the sequence clock — WITHOUT `clockOffset`, so a\n * `sequence.segment` steer rewinds the segment and never the bed — and never\n * re-created. Segments render over it transparently. Null when absent.\n */\n private readonly bed: SpecInstance | null;\n\n constructor(seq: IdleSequence, ctx: SequenceMountContext) {\n this.seq = seq;\n const { sequenceBaseT, capabilityTier, ...plainCtx } = ctx;\n this.capabilityTier = capabilityTier;\n this.fadeEnabled = capabilityTier !== 'basic' && capabilityTier !== 'minimal';\n // `sync: 'epoch'`: seed the clock from the host's shared time, the same\n // way `baseT` carries SpecInstance's clock across pause/resume — the first\n // frame renders at `baseT`, not 0. Absent/`mount` ignores the hint and T\n // starts at 0 exactly as before the field existed. Holds are untouched:\n // `releasedBelow` stays 0, so a late joiner whose clock is past an\n // unreleased `advance: 'input'` hold lands ON the held segment.\n if (seq.sync === 'epoch' && typeof sequenceBaseT === 'number' && Number.isFinite(sequenceBaseT)) {\n this.baseT = Math.max(0, sequenceBaseT);\n this.lastT = this.baseT;\n this.renderedT = this.baseT;\n }\n\n let surface = ctx.surface ?? null;\n let canvas: HTMLCanvasElement | null = null;\n if (!surface && typeof document !== 'undefined') {\n canvas = document.createElement('canvas');\n canvas.style.cssText = 'display:block;width:100%;height:100%';\n canvas.setAttribute('aria-hidden', 'true');\n ctx.host.appendChild(canvas);\n surface = canvas;\n }\n this.canvas = canvas;\n\n // Prefer the sequence's own seed (same precedence SpecInstance uses for\n // scene.seed ?? ctx.seed). Children still resolve per-segment via childSeed.\n this.seed = ((seq.seed ?? ctx.seed ?? 0) >>> 0) || 1;\n this.animateFinish = capabilityTier !== 'basic' && capabilityTier !== 'minimal';\n // A finish anywhere in the sequence moves the children onto an offscreen\n // scene canvas for the sequence's lifetime; which finish applies is\n // decided per frame (see `frameFinish`).\n if (sequenceWantsFinish(seq) && surface) {\n const pass = createFinishPass(surface, this.seed);\n if (pass) {\n this.finishPass = pass;\n surface = createSceneCanvas(ctx.width, ctx.height);\n }\n }\n // Children are always parent-driven: reducedMotion:true keeps SpecInstance\n // from starting its own rAF. SequenceInstance.loop is the only clock.\n // `hostPresents`: a child's own `finish` is this instance's to apply.\n this.childCtx = { ...plainCtx, surface: surface!, reducedMotion: true };\n this.sizeVisible();\n this.children = new Array(seq.segments.length).fill(null) as (SpecInstance | null)[];\n if (seq.bed) {\n this.bed = new SpecInstance(this.bedScene(seq.bed), this.childCtx, { capabilityTier, hostPresents: true });\n this.bed.setPaused(true);\n } else {\n this.bed = null;\n }\n this.paused = ctx.reducedMotion;\n if (this.paused) this.renderFrame(this.baseT, this.seed);\n else this.start();\n }\n\n private childSeed(index: number, fallback: number): number {\n return this.seq.segments[index]!.scene.seed ?? this.seq.seed ?? fallback;\n }\n\n /**\n * The bed's seed follows the segment rule (own seed, else the sequence seed)\n * but offset by `maxSegments`, past every segment's `seed + index`, so a bed\n * and segment 0 never share an entity stream and adding a segment does not\n * re-seat the bed.\n */\n private bedScene(bed: SaverSpec): SaverSpec {\n if (bed.seed != null) return bed;\n if (this.seq.seed != null) return { ...bed, seed: this.seq.seed + LIMITS.maxSegments };\n return bed;\n }\n\n private childScene(index: number): SaverSpec {\n const seg = this.seq.segments[index]!;\n if (seg.scene.seed != null) return seg.scene;\n if (this.seq.seed != null) return { ...seg.scene, seed: this.seq.seed + index };\n return seg.scene;\n }\n\n /** Whether the boundary from `from` to `from+1` should morph. */\n private canMorph(from: number): boolean {\n return canMorph(this.seq, from);\n }\n\n /** Walk back through consecutive morph boundaries to find the chain origin. */\n private morphChainRoot(index: number): number {\n return morphChainRoot(this.seq, index);\n }\n\n private morphDur(from: number): number {\n const tr = this.seq.segments[from]?.transition;\n return tr?.type === 'morph' ? tr.dur : 0;\n }\n\n /** Whether the morph out of `from` paints its text in two passes — `crossfade` or `dip` (default `step`: strings switch at k > 0). */\n private morphTextCrossfades(from: number): boolean {\n const tr = this.seq.segments[from]?.transition;\n return tr?.type === 'morph' && (tr.text === 'crossfade' || tr.text === 'dip');\n }\n\n /** The morph out of `from`'s two-pass text mode, for `crossfadeOverrides`. */\n private morphTextMode(from: number): 'crossfade' | 'dip' {\n const tr = this.seq.segments[from]?.transition;\n return tr?.type === 'morph' && tr.text === 'dip' ? 'dip' : 'crossfade';\n }\n\n /**\n * The paint overrides for one crossfade frame: every text layer whose\n * words differ between the outgoing and incoming specs, painting the\n * outgoing words (in the lerped frame's paint — colour and alpha glide as\n * usual) at `1 − k` under the incoming at `k`. Null when nothing differs,\n * so a crossfade between same-worded twins is a plain morph frame.\n */\n private crossfadeOverrides(specA: SaverSpec, specB: SaverSpec, lerped: SaverSpec, k: number, mode: 'crossfade' | 'dip' = 'crossfade'): Map<number, LayerPaintOverride> | null {\n let map: Map<number, LayerPaintOverride> | null = null;\n for (let i = 0; i < lerped.layers.length; i++) {\n if (!textStringsDiffer(specA, specB, i)) continue;\n const from = specA.layers[i]!.sprite;\n const now = lerped.layers[i]!.sprite;\n const outgoing: SpriteSpec = from.kind === 'text' && now.kind === 'text'\n ? { ...now, strings: from.strings }\n : from.kind === 'textBlock' && now.kind === 'textBlock'\n ? { ...now, text: from.text }\n : now;\n if (outgoing === now) continue;\n // `mode` is only written for `dip`, so a crossfade override is the\n // exact object it has always been.\n (map ??= new Map()).set(i, mode === 'dip' ? { outgoing, k, mode } : { outgoing, k });\n }\n return map;\n }\n\n /** Length of the fade out of segment `from`, or 0 (no fade, or a tier that plays it as cut). */\n private fadeDur(from: number): number {\n const tr = this.seq.segments[from]?.transition;\n return this.fadeEnabled && tr?.type === 'fade' ? tr.dur : 0;\n }\n\n /** Sum of every timed segment — the lap length under `loop: true`. */\n private timedTotal(): number {\n const last = this.seq.segments.length - 1;\n return segmentStart(this.seq, last) + (this.seq.segments[last]!.duration ?? 0);\n }\n\n private releaseFading(): void {\n if (this.fading) {\n this.fading.child.dispose();\n this.fading = null;\n }\n if (this.fadingIn) {\n this.fadingIn.child.dispose();\n this.fadingIn = null;\n }\n }\n\n /**\n * A segment child on a canvas of its own. Like a morph it mounts on its\n * chain root's scene and seed (so its entities are the ones the viewer was\n * watching) and hot-swaps to the segment's spec; the retained track is\n * applied last. Transparent over a bed, opaque otherwise.\n */\n private offscreenChild(index: number, root: number): OffscreenChild {\n const canvas: HTMLCanvasElement | OffscreenCanvas = typeof document !== 'undefined'\n ? document.createElement('canvas')\n : new OffscreenCanvas(Math.max(1, this.childCtx.width), Math.max(1, this.childCtx.height));\n const child = new SpecInstance(this.childScene(root), { ...this.childCtx, surface: canvas }, { transparent: this.bed !== null, capabilityTier: this.capabilityTier, hostPresents: true });\n child.setPaused(true);\n if (root !== index) child.hotSwapSpec(this.childScene(index));\n if (this.retainedDeltas.size > 0) child.applyDeltasNow(this.retainedDeltas.values());\n return { index, child, canvas };\n }\n\n /** Render an offscreen child; a transparent one never clears, so its owner does here. */\n private renderOffscreen(oc: OffscreenChild, t: number, seed: number): void {\n if (this.bed) {\n const c = oc.canvas.getContext('2d') as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;\n c?.clearRect(0, 0, this.childCtx.width, this.childCtx.height);\n }\n oc.child.renderFrame(t, seed);\n }\n\n /** Draw an offscreen canvas onto the shared surface at `alpha`. */\n private composite(canvas: HTMLCanvasElement | OffscreenCanvas, alpha: number): void {\n const main = this.childCtx.surface?.getContext('2d') as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null | undefined;\n if (!main) return;\n main.save();\n main.globalAlpha = alpha;\n main.globalCompositeOperation = 'source-over';\n main.drawImage(canvas, 0, 0, this.childCtx.width, this.childCtx.height);\n main.restore();\n }\n\n /**\n * Render the outgoing segment `from` of a live fade onto its own canvas. It\n * keeps animating at `duration(from) + localT` (it does not freeze — and if\n * it was an `advance: 'input'` hold it resumes from its duration, not from\n * wherever the hold had reached). Two live segments for `dur` only; the\n * outgoing one is disposed when the fade ends.\n */\n private renderOutgoing(from: number, localT: number, seed: number): OffscreenChild {\n if (this.fading && this.fading.index !== from) {\n this.fading.child.dispose();\n this.fading = null;\n }\n if (!this.fading) this.fading = this.offscreenChild(from, this.morphChainRoot(from));\n const outDur = this.seq.segments[from]!.duration ?? 0;\n this.renderOffscreen(this.fading, outDur + localT, this.childSeed(this.morphChainRoot(from), seed));\n return this.fading;\n }\n\n /**\n * One end of a morph at segment time `t`. A scene without a timeline is its\n * steered scene, as always. With a timeline, the retained track follows the\n * same rule a child applies (held until the path's next key, sticky\n * otherwise): the outgoing end uses its child's live overrides when the\n * morph began from one, and otherwise — like the incoming end, whose child\n * does not exist yet — arms the retained steers at segment time 0, as a\n * freshly mounted child would.\n */\n private morphEndpoint(index: number, t: number, side: 'out' | 'in'): SaverSpec {\n const scene = this.childScene(index);\n if (!scene.timeline) return this.steeredScene(scene);\n const ends = this.morphEnds;\n if (ends && side === 'out') ends.outT = t;\n let ov = side === 'out' ? ends?.out ?? null : ends?.in ?? null;\n if (!ov) {\n ov = this.armRetained(scene, side === 'out' ? ends?.seenOut : undefined);\n if (ends) { if (side === 'out') ends.out = ov; else ends.in = ov; }\n }\n return applyOverridesAt(resolveTimelineAt(scene, t), ov, t);\n }\n\n /** The retained steers that resolve (and validate) on a timeline scene, armed at segment time 0. */\n private armRetained(scene: SaverSpec, seen?: Map<string, string>): Map<string, TimelineOverride> {\n const out = new Map<string, TimelineOverride>();\n if (this.retainedDeltas.size === 0) return out;\n const at0 = resolveTimelineAt(scene, 0);\n for (const d of this.retainedDeltas.values()) {\n const path = canonicalSpecPath(at0, d.path);\n if (!path) continue;\n const trial = new Map(out).set(path, armOverride(scene, path, d.value, d.value, 0, 0));\n if (overridesStayValid(scene, trial, 0)) {\n out.set(path, trial.get(path)!);\n seen?.set(path, steerId(d));\n }\n }\n return out;\n }\n\n /** A segment's scene with the retained track applied — `scene` itself when nothing resolves on it. */\n private steeredScene(scene: SaverSpec): SaverSpec {\n return this.retainedDeltas.size === 0 ? scene : applyRetainedDeltas(scene, this.retainedDeltas.values());\n }\n\n /**\n * The child for segment `index`, created paused on the shared surface if\n * the slot is empty. `rootScene` (a morph chain's root) mounts the child\n * with the root's scene so its seed and entity placement are continuous\n * with the chain, then hot-swaps to the segment's own spec. Either way the\n * retained track is applied last, so a steer made while another segment\n * was up is already in effect on this child's first frame. `skipInitialPaint`\n * is for a caller (the morph branch) that is about to render a real frame,\n * paint overrides included, in this same call — see `SpecInstanceOptions`.\n */\n private ensureChild(index: number, rootScene?: SaverSpec, skipInitialPaint?: boolean): SpecInstance {\n if (index < 0 || index >= this.seq.segments.length) index = 0;\n let child = this.children[index];\n if (!child) {\n // Over a bed the child is transparent ink on the shared surface, and\n // every caller renders the real frame right after this — so its\n // constructor paint (t = 0) would only leave a stray frame of ink under\n // it. Transparent children ignore ghosting, so skipping it changes no\n // warm-up. Without a bed the opaque child repaints its ground over it.\n child = new SpecInstance(rootScene ?? this.childScene(index), this.childCtx, { transparent: this.bed !== null, skipInitialPaint: skipInitialPaint || this.bed !== null, capabilityTier: this.capabilityTier, hostPresents: true });\n this.children[index] = child;\n // Belt-and-suspenders: never let a child self-drive, even if childCtx\n // reducedMotion is ever relaxed.\n child.setPaused(true);\n if (rootScene) child.hotSwapSpec(this.childScene(index));\n if (this.retainedDeltas.size > 0) child.applyDeltasNow(this.retainedDeltas.values());\n }\n return child;\n }\n\n private releaseChild(index: number): void {\n const child = this.children[index];\n if (child) {\n child.dispose();\n this.children[index] = null;\n }\n }\n\n private start(): void {\n if (this.frameId !== null || typeof requestAnimationFrame === 'undefined') return;\n this.startT = 0;\n this.frameId = requestAnimationFrame((now) => this.loop(now));\n }\n\n private stop(): void {\n if (this.frameId !== null) {\n cancelAnimationFrame(this.frameId);\n this.frameId = null;\n }\n this.baseT = this.lastT;\n }\n\n private loop(now: number): void {\n this.frameId = requestAnimationFrame((n) => this.loop(n));\n if (this.startT === 0) this.startT = now;\n this.lastT = now - this.startT + this.baseT;\n this.renderFrame(this.lastT, this.seed);\n }\n\n /**\n * With a presentation pass, size the visible surface like a child sizes\n * the scene canvas (children never touch the visible surface then).\n */\n private sizeVisible(): void {\n const fp = this.finishPass;\n if (!fp) return;\n const dpr = Math.min(this.childCtx.dpr, 2);\n fp.canvas.width = Math.max(1, Math.round(this.childCtx.width * dpr));\n fp.canvas.height = Math.max(1, Math.round(this.childCtx.height * dpr));\n fp.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n }\n\n /**\n * The finish this frame applies: the sequence's own overrides; else the\n * active segment's (the incoming one during a fade) — read through\n * `steeredScene` so a retained steer to `finish.grain`/`finish.dither`\n * takes effect immediately instead of the authored value; a bed's is\n * ignored.\n */\n private frameFinish(): SaverSpec['finish'] {\n if (this.seq.finish !== undefined) return this.seq.finish;\n if (this.activeIndex < 0) return undefined;\n const scene = this.childScene(this.activeIndex);\n if (scene.timeline) {\n // A timeline may key `finish.*`: read what the rendering child painted\n // (its chain-root slot mid-morph), not the authored base.\n const live = (this.fadingIn?.index === this.activeIndex ? this.fadingIn.child : null)\n ?? this.children[this.activeIndex] ?? this.children[this.morphChainRoot(this.activeIndex)];\n if (live) return live.presentedSpec().finish;\n }\n return this.steeredScene(scene).finish;\n }\n\n /**\n * The seed `frameFinish()`'s grain resolves against — the sequence's own\n * for a sequence-level finish, else the active segment's actual render\n * seed (`segmentRenderSeed`: chain-root-aware and normalized exactly like\n * `SpecInstance`, so it agrees with what that segment's entities render\n * with, morph or not).\n */\n private frameFinishSeed(): number {\n if (this.seq.finish !== undefined) return this.seed;\n if (this.activeIndex < 0) return this.seed;\n return segmentRenderSeed(this.seq, this.activeIndex) ?? this.seed;\n }\n\n renderFrame(T: number, seed: number): void {\n this.renderScene(T, seed);\n // Once per composed frame, after bed, segment and any fade composite.\n if (this.finishPass) {\n presentWithFinish(this.finishPass, this.childCtx.surface!, this.childCtx.width, this.childCtx.height, T, this.frameFinish(), this.animateFinish, this.frameFinishSeed());\n }\n }\n\n private renderScene(T: number, seed: number): void {\n this.renderedT = T;\n const resolved = resolveSegment(this.seq, T + this.clockOffset, { releasedBelow: this.releasedBelow });\n const { index, localT } = resolved;\n\n // The bed is the ground: painted first, on the global clock. `T` here is\n // the sequence clock before `clockOffset`, so the clicker never rewinds it.\n this.bed?.renderFrame(T, this.seq.bed?.seed ?? this.seq.seed ?? seed);\n\n // A fade comes from the previous segment in the list — or, under\n // `loop: true`, from the last segment when the lap wraps to 0, so the\n // last segment's `fade` is the wrap's transition. Cut and morph paths\n // are untouched: fadeDur is 0 for them.\n const lastIdx = this.seq.segments.length - 1;\n const wrapped = this.seq.loop && index === 0 && lastIdx > 0\n && (T + this.clockOffset >= this.timedTotal() || this.pendingWrapFade);\n\n // Check if the *previous* segment has a morph into this one — or, with\n // `wrapMorph` on a loop that is one morph chain, whether the last\n // segment morphs into segment 0 at the wrap (`canWrapMorph`). Without\n // `wrapMorph` the wrap stays the hard cut it has always been.\n // Only on a natural lap wrap: a clicker jump to segment 0 (`pendingWrapFade`)\n // arrives from wherever the presenter was, not from the last segment, so\n // it cuts — morphing from the last segment would flash a frame of it.\n const naturalWrap = this.seq.loop && index === 0 && lastIdx > 0 && T + this.clockOffset >= this.timedTotal();\n const prevIdx = index > 0 ? index - 1 : -1;\n const morphFrom = prevIdx >= 0 ? prevIdx : naturalWrap && canWrapMorph(this.seq) ? lastIdx : -1;\n const morphActive = morphFrom >= 0\n && (morphFrom === prevIdx ? this.canMorph(prevIdx) : true)\n && localT < this.morphDur(morphFrom);\n const fadeFrom = prevIdx >= 0 ? prevIdx : wrapped ? lastIdx : -1;\n const fadeActive = fadeFrom >= 0 && localT < this.fadeDur(fadeFrom);\n if (!fadeActive && this.fading) this.releaseFading();\n // The flag only needs to survive the frames still inside the wrap fade\n // window; once that ends (or the clock moves off segment 0) it has done\n // its job.\n if (this.pendingWrapFade && (index !== 0 || !fadeActive)) this.pendingWrapFade = false;\n\n if (morphActive) {\n // Morph in progress: keep the child keyed to the chain root\n // (preserves its seed/entity placement through chained morphs).\n const chainRoot = this.morphChainRoot(index);\n if (this.morphFromIndex !== morphFrom || this.morphEnds?.to !== index) {\n // A new morph: carry the outgoing segment's live steers (held/expired\n // per the timeline rule, on its own clock) into the lerp, before its\n // child is released or hot-swapped to the lerped frame.\n const outChild = this.children[morphFrom];\n this.morphEnds = { from: morphFrom, to: index, outT: 0, out: outChild?.timelineOverrides() ?? null, seenOut: outChild?.timelineSeen() ?? new Map(), in: null };\n }\n this.morphFromIndex = morphFrom;\n this.activeIndex = index;\n\n // Release all children except the chain root's slot\n for (let i = 0; i < this.children.length; i++) {\n if (i !== chainRoot) this.releaseChild(i);\n }\n\n // A fresh mount here is about to be repainted for real a few lines\n // down (hotSwapPaint + overrides + renderFrame) within this same call.\n // Only `text: 'crossfade'` needs the constructor's own paint skipped —\n // its partial-alpha passes would otherwise composite over a stray\n // full-opacity frame underneath; `step` (the common case) is left to\n // paint at construction as it always has, so a fresh mount's ghosting\n // contiguity (`lastRenderT`) is unaffected.\n const child = this.ensureChild(chainRoot, undefined, this.morphTextCrossfades(morphFrom));\n const dur = this.morphDur(morphFrom);\n const k = easeSmooth(localT / dur);\n // The lerp endpoints carry the retained track, so without this a\n // steered colour would vanish for `dur` and snap back when the morph\n // finalises. `canMorph` only guarantees specA/specB share structure\n // BEFORE the retained set is applied — a structural delta (`layers.0.\n // count`, a motion change) could validate on one endpoint and not the\n // other, or change both identically but differ from what this child\n // was last built with. hotSwapSpec (not hotSwapPaint) re-checks the\n // signature every frame and rebuilds when it moved, so a structural\n // steer actually takes effect instead of leaving stale entities.\n //\n // A segment with a `timeline` is resolved on its own clock first — the\n // outgoing one at its end (its duration + localT, so a looping\n // timeline keeps cycling through the morph), the incoming at localT —\n // and the timeline-free results are lerped. Without timelines\n // resolveTimelineAt returns its argument, so this is the old frame.\n const outDur = this.seq.segments[morphFrom]!.duration ?? 0;\n const specA = this.morphEndpoint(morphFrom, outDur + localT, 'out');\n const specB = this.morphEndpoint(index, localT, 'in');\n const lerped = lerpSpec(specA, specB, k);\n child.hotSwapSpec(lerped);\n // Default (`step`): no overrides, the frame is what it always was —\n // strings already switched inside `lerped` at k > 0.\n child.setLayerPaintOverrides(this.morphTextCrossfades(morphFrom) ? this.crossfadeOverrides(specA, specB, lerped, k, this.morphTextMode(morphFrom)) : null);\n child.renderFrame(localT, this.childSeed(chainRoot, seed));\n } else {\n // No morph (or morph complete). If we were morphing, finalize.\n if (this.morphFromIndex >= 0) {\n // Morph just completed — release the chain-root child.\n const oldRoot = this.morphChainRoot(this.morphFromIndex);\n this.releaseChild(oldRoot);\n if (oldRoot !== this.morphFromIndex) this.releaseChild(this.morphFromIndex);\n this.morphFromIndex = -1;\n this.morphEnds = null;\n }\n\n if (index !== this.activeIndex) {\n for (let i = 0; i < this.children.length; i++) {\n if (i !== index) this.releaseChild(i);\n }\n this.activeIndex = index;\n }\n\n // Determine the effective seed: if this segment was reached via a\n // morph chain, use the chain-root's seed so entity placement is\n // continuous across all morphed segments and seeks match playthrough.\n const chainRoot = this.morphChainRoot(index);\n const useMorphSeed = chainRoot < index;\n const effSeed = useMorphSeed ? this.childSeed(chainRoot, seed) : this.childSeed(index, seed);\n\n if (fadeActive && this.bed) {\n // Over a bed both segments are transparent ink, so both go to canvases\n // of their own: incoming at k, outgoing over it at 1 − k. The incoming\n // moves to the shared surface (via ensureChild) once the fade ends.\n const k = easeSmooth(localT / this.fadeDur(fadeFrom));\n if (this.fadingIn && this.fadingIn.index !== index) {\n this.fadingIn.child.dispose();\n this.fadingIn = null;\n }\n if (!this.fadingIn) this.fadingIn = this.offscreenChild(index, useMorphSeed ? chainRoot : index);\n this.renderOffscreen(this.fadingIn, localT, effSeed);\n const out = this.renderOutgoing(fadeFrom, localT, seed);\n this.composite(this.fadingIn.canvas, k);\n this.composite(out.canvas, 1 - k);\n return;\n }\n\n // If using morph seed, mount the child with the chain root's scene+seed\n // but immediately hot-swap to the current segment's spec.\n const child = useMorphSeed ? this.ensureChild(index, this.childScene(chainRoot)) : this.ensureChild(index);\n child.renderFrame(localT, effSeed);\n if (fadeActive) {\n // The outgoing segment on its own canvas over the incoming frame at\n // 1 − easeSmooth(k): the incoming's opaque ground fades in beneath it.\n const out = this.renderOutgoing(fadeFrom, localT, seed);\n this.composite(out.canvas, 1 - easeSmooth(localT / this.fadeDur(fadeFrom)));\n }\n }\n }\n\n setPaused(paused: boolean): void {\n this.paused = paused;\n if (paused) this.stop();\n else this.start();\n // Do NOT forward pause=false to children — that would start SpecInstance\n // rAF loops alongside SequenceInstance.loop (double clock, wrong localT).\n // Children stay paused; the parent loop is the sole driver.\n for (const child of this.children) {\n child?.setPaused(true);\n }\n this.fading?.child.setPaused(true);\n this.fadingIn?.child.setPaused(true);\n this.bed?.setPaused(true);\n }\n\n resize(width: number, height: number, dpr?: number): void {\n // Children are created lazily (first rAF tick, segment switches, morph\n // finalization), so the new size must outlive the children that exist right\n // now. Without this, a resize while a slot is empty is forgotten and the\n // next child mounts at the stale mount-time size — a viewer that mounted\n // in a hidden/unpainted tab (width 0) stays a 1×1 canvas forever, and a\n // segment cut after any resize snaps back to the old dimensions.\n this.childCtx.width = width;\n this.childCtx.height = height;\n if (dpr !== undefined) this.childCtx.dpr = dpr;\n this.sizeVisible();\n for (const child of this.children) {\n child?.resize(width, height, dpr);\n }\n this.fading?.child.resize(width, height, dpr);\n this.fadingIn?.child.resize(width, height, dpr);\n this.bed?.resize(width, height, dpr);\n }\n\n applyTrack(track: ControlTrack): void {\n const all = (track?.deltas ?? []) as unknown as SteerDelta[];\n // `bed.<path>` goes to the bed with the prefix stripped — only when a bed\n // exists; otherwise the path reaches the segments as today (a layer keyed\n // `bed` keeps working).\n const isBedPath = (d: SteerDelta): boolean => this.bed !== null && typeof d.path === 'string' && d.path.startsWith(BED_PREFIX);\n const bedDeltas = all.filter(isBedPath).map((d) => ({ ...d, path: d.path.slice(BED_PREFIX.length) }));\n if (bedDeltas.length > 0) {\n for (const d of bedDeltas) this.retainedBedDeltas.set(d.path, d);\n this.bed!.applyTrack({ ...track, deltas: bedDeltas as unknown as ParamDelta[] });\n }\n const deltas = all.filter((d) => !isBedPath(d));\n // Retain first: a `sequence.segment` steer in the same track creates the\n // target child inside renderFrame below, and it must see these deltas.\n for (const d of deltas) {\n if (d.path !== 'sequence.segment' && typeof d.path === 'string') this.retainedDeltas.set(d.path, d);\n }\n const segDelta = deltas.find((d) => d.path === 'sequence.segment');\n let switchedSegment = false;\n if (segDelta !== undefined && typeof segDelta.value === 'number') {\n const idx = Math.max(0, Math.min(this.seq.segments.length - 1, Math.round(segDelta.value as number)));\n // A steer to segment 0 under loop is the clicker doing the same jump\n // the wall clock does on a natural lap wrap — it should trigger the\n // last segment's fade the same way (see `pendingWrapFade`).\n this.pendingWrapFade = this.seq.loop && idx === 0 && this.seq.segments.length > 1;\n // Displace the clock so T + offset == the target segment's start: the\n // segment begins at localT 0 (its `life.enter` build replays) and the\n // next animation frame resolves to the same segment instead of snapping\n // back to whatever the wall clock said. The steer also releases every\n // `advance: 'input'` hold before the target; holds at and after it stay\n // armed, so steering backwards re-arms the ones in between.\n this.clockOffset = segmentStart(this.seq, idx) - this.renderedT;\n this.releasedBelow = idx;\n this.renderFrame(this.renderedT, this.seed);\n switchedSegment = true;\n }\n\n const childDeltas = deltas.filter((d) => d.path !== 'sequence.segment');\n if (childDeltas.length > 0) {\n if (this.morphFromIndex >= 0) {\n // Mid-morph, the rendered child lives at the chain-root slot, not\n // `children[activeIndex]` — forwarding a child.applyTrack() there\n // would silently no-op AND get overwritten by the morph's own\n // hotSwapSpec on the very next frame regardless, so a transition\n // glide on this path can't coexist with the morph's own cross-fade.\n // The delta is already retained above, so a re-render is all that's\n // needed to reach it via steeredScene: it takes effect this frame,\n // immediately rather than gliding over its own `dur`. Skip only when\n // the segDelta branch above already re-rendered with these deltas\n // retained.\n // Timeline ends resolve through `morphEnds`: arm the new steer on the\n // outgoing set at its current time, and re-arm the incoming side.\n const ends = this.morphEnds;\n if (ends) {\n const outScene = this.childScene(ends.from);\n if (ends.out && outScene.timeline) SpecInstance.armInto(outScene, ends.out, ends.seenOut, childDeltas, ends.outT);\n ends.in = null;\n }\n if (!switchedSegment) this.renderFrame(this.renderedT, this.seed);\n } else if (this.activeIndex >= 0) {\n // Not mid-morph: the active child still gets the track directly, as\n // before retention — a steer to a path it owns glides on this call\n // rather than snapping at the next boundary.\n const child = this.children[this.activeIndex];\n child?.applyTrack({ ...track, deltas: childDeltas as unknown as ParamDelta[] });\n }\n // The outgoing segment during a fade — and, over a bed, the incoming\n // one too, since both are standalone offscreen SpecInstances, not\n // `this.children` — would otherwise freeze at whatever they last\n // rendered instead of picking up a mid-fade steer like the active\n // child does. Independent of the morph/active branching above: fade\n // and morph are mutually exclusive per-frame states.\n this.fading?.child.applyTrack({ ...track, deltas: childDeltas as unknown as ParamDelta[] });\n this.fadingIn?.child.applyTrack({ ...track, deltas: childDeltas as unknown as ParamDelta[] });\n }\n }\n\n /**\n * See `SequenceSaverInstance.hotSwapSequence`. Nothing that positions the\n * show is touched: `clockOffset`, `releasedBelow`, `activeIndex`,\n * `morphFromIndex`, `pendingWrapFade`, `renderedT` and the retained deltas\n * all keep their values, and the timing terms `sequenceSwapCompatible`\n * pins (durations, advance, transitions, loop) are the same on both sides,\n * so `resolveSegment` at the next frame lands where it would have anyway.\n * Each live child takes its new scene with the retained track re-applied\n * (`steeredScene` — the same routing a fresh child gets), so steered paint\n * survives the swap; `hotSwapSpec` keeps the entities (the signatures\n * match) and does not reset ghosting contiguity, so a drifting entity is\n * where it was 1 ms ago. Children are always paused, so none of them has a\n * glide in flight for the swap to interrupt (`SpecInstance.applyTrack`\n * snaps when paused). A morph in progress is untouched here: its chain-root\n * child is re-lerped from the new endpoints on the very next frame.\n */\n hotSwapSequence(next: IdleSequence): boolean {\n if (!sequenceSwapCompatible(this.seq, next)) return false;\n this.seq = next;\n // Routed like a child's retained set (`applyRetainedDeltas`, not\n // `applyDeltasNow`): the latter resets ghosting contiguity, and the bed's\n // trails must not restart on a swap.\n if (this.bed && next.bed) this.bed.hotSwapSpec(applyRetainedDeltas(this.bedScene(next.bed), this.retainedBedDeltas.values()));\n const swap = (child: SpecInstance | null | undefined, index: number): void => {\n if (!child) return;\n const scene = this.childScene(index);\n if (!scene.timeline) { child.hotSwapSpec(this.steeredScene(scene)); return; }\n // A timeline child keeps its live steers across the swap (the steering\n // rule), rather than having them baked into its base (which would make\n // a steer on an animated path sticky) or re-armed from scratch (which\n // would bring back one the timeline already took back).\n child.hotSwapKeepingSteers(scene, this.retainedDeltas.values());\n };\n for (let i = 0; i < this.children.length; i++) swap(this.children[i], i);\n if (this.fading) swap(this.fading.child, this.fading.index);\n if (this.fadingIn) swap(this.fadingIn.child, this.fadingIn.index);\n this.morphEnds = null;\n // A paused instance (reducedMotion, or a sleeping host) has no next frame\n // to paint the new words with; a running one repaints on its own tick.\n if (this.paused) this.renderFrame(this.renderedT, this.seed);\n return true;\n }\n\n dispose(): void {\n this.stop();\n this.releaseFading();\n for (let i = 0; i < this.children.length; i++) {\n this.releaseChild(i);\n }\n this.bed?.dispose();\n if (this.finishPass) {\n // The scene canvas was never attached; the pass's visible canvas is\n // `this.canvas` (removed below) or the host's surface.\n this.finishPass.grain = null;\n this.finishPass.dither = null;\n }\n if (this.canvas) this.canvas.remove();\n }\n}\n\nfunction sequenceManifest(seq: IdleSequence): SaverManifest {\n const maxSegment = seq.segments.reduce((max, s) => {\n const t = s.scene.layers.reduce((n, l) => n + l.count, 0);\n return Math.max(max, t);\n }, 0);\n // A bed is live alongside whichever segment is up, so it costs on top of the largest.\n const bedTotal = seq.bed ? seq.bed.layers.reduce((n, l) => n + l.count, 0) : 0;\n const maxTotal = bedTotal + maxSegment;\n const costTier = maxTotal < 30 ? 'idle' : maxTotal < 150 ? 'low' : maxTotal < 400 ? 'medium' : 'high';\n return {\n id: seq.id,\n label: seq.label,\n timeModel: 'closed-form',\n passthrough: false,\n minBackend: 'canvas2d',\n costTier,\n motionIntensity: 'moderate',\n reducedMotionFallback: 'static',\n a11y: { flashSafe: true },\n workerReady: false,\n };\n}\n\nexport function compileSequence(spec: unknown): SequenceSaverPlugin {\n const valid = assertValidSequence(spec);\n return {\n manifest: sequenceManifest(valid),\n mount: (ctx: SequenceMountContext) => new SequenceInstance(valid, ctx),\n spec: valid,\n };\n}\n","/**\n * Analytic models of the paint-level layer fields — `transform` (with its\n * `origin`), `opacity`, and the `groups` a layer paints through — shared by\n * the renderer's maths, perception and the advisories. Internal, not\n * exported from the package. They mirror SpecInstance's draw-time canvas\n * transform: a member of a group is drawn through G·L, where L is the layer's\n * own transform (about its origin) and G the group's (about the viewport\n * centre), so a point p lands at G(L(p)).\n */\nimport type { LayerGroup, LayerSpec, LayerTransform, SaverSpec } from './types';\n\nexport interface Pt { x: number; y: number }\n\n/**\n * A layer's own anchor in px: its `position` point (plus `dx`/`dy`; for a\n * `list`/`table` layout the block's anchor), else the centre of its `region`,\n * else the viewport centre.\n */\nexport function layerAnchor(layer: LayerSpec, w: number, h: number, unit: number): Pt {\n const p = layer.position;\n if (p) return { x: p.x * w + (p.dx ?? 0) * unit, y: p.y * h + (p.dy ?? 0) * unit };\n const rx = layer.region?.x ?? [0, 1];\n const ry = layer.region?.y ?? [0, 1];\n return { x: ((rx[0] + rx[1]) / 2) * w, y: ((ry[0] + ry[1]) / 2) * h };\n}\n\n/** What a layer transform turns about, in px: the viewport centre, or (`origin: 'anchor'`) the layer's anchor. */\nexport function transformOrigin(tf: LayerTransform, layer: LayerSpec | null, w: number, h: number, unit: number): Pt {\n return tf.origin === 'anchor' && layer ? layerAnchor(layer, w, h, unit) : { x: w / 2, y: h / 2 };\n}\n\n/**\n * Where a transform puts a point: about `origin` (default the viewport\n * centre), offsets in min(w,h) units (px under `units: 'px'`). Sprites are not\n * rotated here; the maps model ink, not glyph angle.\n */\nexport function transformPoint(tf: LayerTransform, p: Pt, w: number, h: number, unit: number, origin: Pt = { x: w / 2, y: h / 2 }): Pt {\n const s = tf.scale ?? 1;\n const sx = s * (tf.scaleX ?? 1);\n let x = (p.x - origin.x) * sx;\n let y = (p.y - origin.y) * s;\n if (tf.rotate) {\n const r = (tf.rotate * Math.PI) / 180;\n const c = Math.cos(r);\n const n = Math.sin(r);\n [x, y] = [x * c - y * n, x * n + y * c];\n }\n return { x: x + origin.x + (tf.x ?? 0) * unit, y: y + origin.y + (tf.y ?? 0) * unit };\n}\n\n/** A transform's linear size factor (the geometric mean of its two axes' scales). */\nexport function transformSize(tf: LayerTransform | undefined): number {\n if (!tf) return 1;\n const s = tf.scale ?? 1;\n return s * Math.sqrt(Math.abs(tf.scaleX ?? 1));\n}\n\n/** The group a layer paints through, if it names one that exists. */\nexport function groupOf(spec: SaverSpec, layer: LayerSpec): LayerGroup | undefined {\n return layer.group === undefined ? undefined : spec.groups?.[layer.group];\n}\n\nconst clamp01 = (v: number): number => (v <= 0 ? 0 : v >= 1 ? 1 : v);\n\n/** A layer's paint opacity as a multiplier: its own `opacity` × its group's (1 when unset). */\nexport function paintOpacity(spec: SaverSpec, layer: LayerSpec): number {\n const own = layer.opacity === undefined ? 1 : clamp01(layer.opacity);\n const g = groupOf(spec, layer);\n return g?.opacity === undefined ? own : own * clamp01(g.opacity);\n}\n\n/** Back-compat alias: a layer's own paint opacity (no group). */\nexport const layerOpacity = (layer: LayerSpec): number => (layer.opacity === undefined ? 1 : clamp01(layer.opacity));\n\n/** The combined linear size factor of a layer's own and its group's transforms. */\nexport function paintSize(spec: SaverSpec, layer: LayerSpec): number {\n return transformSize(layer.transform) * transformSize(groupOf(spec, layer)?.transform);\n}\n\n/**\n * The point map a layer is painted through — its own transform about its\n * origin, then its group's about the viewport centre — or null when neither\n * is set (the caller keeps the untouched path).\n */\nexport function paintMap(spec: SaverSpec, layer: LayerSpec, w: number, h: number, unit: number): ((p: Pt) => Pt) | null {\n const tf = layer.transform;\n const gtf = groupOf(spec, layer)?.transform;\n if (!tf && !gtf) return null;\n const o = tf ? transformOrigin(tf, layer, w, h, unit) : null;\n return (p) => {\n const q = tf ? transformPoint(tf, p, w, h, unit, o!) : p;\n return gtf ? transformPoint(gtf, q, w, h, unit) : q;\n };\n}\n\n/** The axis-aligned box a mapped rectangle covers (its four corners through `map`). */\nexport function mapBox(map: (p: Pt) => Pt, box: { x0: number; y0: number; x1: number; y1: number }): { x0: number; y0: number; x1: number; y1: number } {\n const pts = [[box.x0, box.y0], [box.x1, box.y0], [box.x0, box.y1], [box.x1, box.y1]].map(([x, y]) => map({ x: x!, y: y! }));\n return {\n x0: Math.min(...pts.map((p) => p.x)),\n y0: Math.min(...pts.map((p) => p.y)),\n x1: Math.max(...pts.map((p) => p.x)),\n y1: Math.max(...pts.map((p) => p.y)),\n };\n}\n\n/** Back-compat: the box a layer transform (about the viewport centre) covers. */\nexport function transformBox(tf: LayerTransform, box: { x0: number; y0: number; x1: number; y1: number }, w: number, h: number, unit: number): { x0: number; y0: number; x1: number; y1: number } {\n return mapBox((p) => transformPoint(tf, p, w, h, unit), box);\n}\n","/**\n * The `field` background sampler — seeded, dependency-free value noise that\n * is a PURE function of `(u, v, t, config, seed)`.\n *\n * Why it is its own module, and why it never touches the entity RNG: a\n * background must be able to change without re-seating a single entity. The\n * sampler hashes an integer lattice with its own mixing function, so a spec\n * that adds (or steers) a field keeps the exact `buildEntities` stream it\n * had before — `field.test.ts` asserts it. Because the value at any point is\n * closed-form, the renderer (a low-res raster, upscaled) and the perception\n * grid (`luminanceGrid`) sample the SAME function and agree by construction;\n * that is the analytic guarantee FORMAT.md states for the field.\n *\n * Coordinates: `u`, `v` are in short-side units — `xPx / min(w, h)`,\n * `yPx / min(w, h)` — so `scale` reads as \"features across the short side\"\n * on every aspect ratio, and a 16:9 frame simply shows more of the same field\n * than a square one does. Callers on both sides normalise the same way.\n */\nimport type { FieldBackground } from './types';\n\nconst TWO_PI = Math.PI * 2;\n\n/** Cache bucket for a drifting field: the raster is recomputed at most this often. */\nexport const FIELD_BUCKET_MS = 100;\n/** Raster short side (px) the renderer paints the field at, then upscales. */\nexport const FIELD_RASTER_SHORT_SIDE = 96;\n/** Raster short side on the `basic` / `minimal` capability tiers. */\nexport const FIELD_RASTER_SHORT_SIDE_LOW = 48;\n/** How far (in feature units) `warp: 1` displaces the sample domain. */\nconst WARP_GAIN = 2;\n/** Radius (in feature units) of the slow domain circle at `drift.amount: 1`. */\nconst DRIFT_GAIN = 1;\n/** Default `drift.amount`. */\nexport const FIELD_DRIFT_DEFAULT_AMOUNT = 0.3;\n/**\n * Contrast stretch per octave count. Bilinear value noise (and more so an\n * octave sum) crowds around 0.5, so evenly spaced band thresholds would give\n * the middle bands almost everything. Each factor rescales the raw value so\n * its spread approaches a uniform 0..1 (σ 0.26–0.30 with ≤ 11 % of samples\n * clamped to an end band, a six-band histogram within 11–22 % per band);\n * measured over 4·10⁵ samples per octave count, symmetric about 0.5.\n */\nconst CONTRAST: readonly number[] = [1, 1.45, 1.8, 1.95, 2.0];\n\nconst clamp01 = (v: number): number => (v < 0 ? 0 : v > 1 ? 1 : v);\n\n/**\n * Integer-lattice hash → 0..1. Every product goes through `Math.imul` so the\n * arithmetic stays in int32 and the result is identical on every platform\n * (a float multiply of large ints would drift by ULPs across engines).\n */\nexport function latticeHash(ix: number, iy: number, seed: number): number {\n let h = Math.imul(ix | 0, 0x27d4eb2d) ^ Math.imul(iy | 0, 0x165667b1) ^ Math.imul(seed | 0, 0x9e3779b1);\n h = Math.imul(h ^ (h >>> 15), 0x85ebca6b);\n h = Math.imul(h ^ (h >>> 13), 0xc2b2ae35);\n h ^= h >>> 16;\n return (h >>> 0) / 4294967296;\n}\n\nconst smoothstep = (k: number): number => k * k * (3 - 2 * k);\n\n/** One octave of smooth value noise at (x, y), 0..1. */\nfunction valueNoise(x: number, y: number, seed: number): number {\n const x0 = Math.floor(x);\n const y0 = Math.floor(y);\n const fx = smoothstep(x - x0);\n const fy = smoothstep(y - y0);\n const a = latticeHash(x0, y0, seed);\n const b = latticeHash(x0 + 1, y0, seed);\n const c = latticeHash(x0, y0 + 1, seed);\n const d = latticeHash(x0 + 1, y0 + 1, seed);\n const top = a + (b - a) * fx;\n const bottom = c + (d - c) * fx;\n return top + (bottom - top) * fy;\n}\n\n/** Fractal sum of `octaves` value-noise octaves (amplitude halves, frequency doubles), normalised to 0..1. */\nfunction fbm(x: number, y: number, seed: number, octaves: number): number {\n let sum = 0;\n let amp = 1;\n let norm = 0;\n let f = 1;\n for (let i = 0; i < octaves; i++) {\n // Each octave samples a shifted lattice with its own seed so octave\n // boundaries never line up into a visible grid.\n sum += amp * valueNoise(x * f + i * 17.3, y * f + i * 31.7, seed + i * 101);\n norm += amp;\n amp *= 0.5;\n f *= 2;\n }\n return sum / norm;\n}\n\n/** The clamped, rounded octave count a config resolves to (steering may glide it through fractions). */\nexport function fieldOctaves(cfg: Pick<FieldBackground, 'octaves'>): number {\n const o = Math.round(cfg.octaves ?? 2);\n return o < 1 ? 1 : o > 4 ? 4 : o;\n}\n\n/**\n * The time the field is sampled at for scene time `t`: with `drift` at a\n * nonzero `amount`, the start of the 100 ms bucket `t` falls in (the renderer\n * recomputes its raster once per bucket and holds it, so the perception grid\n * samples the same instant); without `drift`, or with `drift.amount: 0` (the\n * domain never moves), the field is static and the answer is always 0 — so a\n * legally-static drift config isn't rebucketed, and re-rastered, ten times a\n * second for nothing.\n */\nexport function fieldSampleTime(cfg: Pick<FieldBackground, 'drift'>, t: number): number {\n return cfg.drift && cfg.drift.amount !== 0 ? Math.floor(t / FIELD_BUCKET_MS) * FIELD_BUCKET_MS : 0;\n}\n\n/**\n * The scalar field at short-side coordinates `(u, v)` and time `t` (ms),\n * 0..1. `seed` is the spec's seed; `cfg.seed` overrides it. Pure — no state,\n * no RNG stream, so the same inputs give the same value in every call on\n * every platform.\n */\nexport function fieldAt(u: number, v: number, t: number, cfg: FieldBackground, seed: number): number {\n const scale = cfg.scale;\n const octaves = fieldOctaves(cfg);\n const s = (cfg.seed ?? seed) >>> 0;\n let x = u * scale;\n let y = v * scale;\n const drift = cfg.drift;\n if (drift) {\n // The sample domain travels a slow circle of radius `amount` feature\n // units: the field loops exactly every `period`, no pixel ever jumps, and\n // the fastest any point can change is bounded by amount / period — which\n // the validator floors at 10 s, so a field can never flash.\n const phase = (TWO_PI * t) / drift.period;\n const r = (drift.amount ?? FIELD_DRIFT_DEFAULT_AMOUNT) * DRIFT_GAIN;\n x += r * Math.sin(phase);\n y += r * Math.cos(phase);\n }\n const warp = cfg.warp ?? 0;\n if (warp > 0) {\n // Domain warp: displace the sample point by a second, independent field.\n // Turns round noise blobs into the smeared, folded contours of a thermal\n // map or a weather chart.\n const qx = fbm(x + 5.2, y + 1.3, s + 7919, octaves) - 0.5;\n const qy = fbm(x + 1.7, y + 9.2, s + 104729, octaves) - 0.5;\n x += warp * WARP_GAIN * qx;\n y += warp * WARP_GAIN * qy;\n }\n const raw = fbm(x, y, s, octaves);\n return clamp01(0.5 + (raw - 0.5) * CONTRAST[octaves]!);\n}\n\n/** `#rgb` / `#rrggbb` → integer channels 0..255. Malformed input reads as mid grey. */\nexport function hexToRgb255(hex: string): [number, number, number] {\n const h = hex.length === 4 ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex;\n const n = /^#[0-9a-f]{6}$/i.test(h) ? parseInt(h.slice(1), 16) : NaN;\n if (Number.isNaN(n)) return [128, 128, 128];\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\n\n/** Perceptual luma (0..1) of integer RGB — the same weights `hexLuma` uses, so a band's luma matches its hex's. */\nexport function rgb255Luma(rgb: readonly [number, number, number]): number {\n return (0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2]) / 255;\n}\n\n/**\n * The colour a field value paints: `quantize ≥ 2` posterises the value into\n * that many levels and reads each level off the `bands` ramp (`quantize ===\n * bands.length`, the default, is exactly one band per level — hard, crisp\n * contours); `quantize: 0` interpolates the ramp smoothly (Aura, Mist). A\n * steered `quantize` gliding through fractions rounds to the nearest level\n * count. Integer channels, so a quantised band is byte-exact its hex.\n */\nexport function fieldRgb(value: number, bands: readonly string[], quantize: number | undefined): [number, number, number] {\n const n = bands.length;\n const q = Math.round(quantize ?? n);\n let f: number; // position along the ramp, 0..n-1\n if (q >= 2) {\n const level = Math.min(q - 1, Math.floor(clamp01(value) * q));\n f = (level * (n - 1)) / (q - 1); // multiply first: q === n gives an exact integer\n } else {\n f = clamp01(value) * (n - 1);\n }\n const i = Math.min(n - 2, Math.floor(f));\n const k = f - i;\n const a = hexToRgb255(bands[i]!);\n if (k === 0) return a;\n const b = hexToRgb255(bands[i + 1]!);\n return [\n Math.round(a[0] + (b[0] - a[0]) * k),\n Math.round(a[1] + (b[1] - a[1]) * k),\n Math.round(a[2] + (b[2] - a[2]) * k),\n ];\n}\n\n/** The painted colour at short-side coordinates `(u, v)`: `fieldRgb(fieldAt(...))`. */\nexport function fieldRgbAt(u: number, v: number, t: number, cfg: FieldBackground, seed: number): [number, number, number] {\n return fieldRgb(fieldAt(u, v, t, cfg, seed), cfg.bands, cfg.quantize);\n}\n","/**\n * The print `finish` — grain and a dither screen composited over a finished\n * frame as the LAST step of a render, after every layer and after ghosting\n * has done its work.\n *\n * Two rules make it flash-safe and deterministic:\n *\n * 1. **Zero-mean, bounded.** The grain tile is noise centred on mid grey and\n * the dither tile is an ordered Bayer matrix whose mean is mid grey; both\n * are composited with a symmetric blend (`overlay`, falling back to\n * `soft-light`, then `multiply`) at a small alpha, so the frame's mean\n * luminance is unchanged — a finish can neither brighten nor darken a\n * wall, and the analytic `luminanceGrid` ignores it entirely.\n * 2. **Seeded, never `Math.random`.** The grain tile is generated once per\n * mount from the spec seed with the same lattice hash the field uses. Its\n * offset is fixed for the mount; with `animate: true` it steps\n * deterministically from the frame's time bucket (12 Hz), so two viewers\n * at the same `t` show the same grain, and a seek is exact.\n *\n * The persistence rule: the finish is applied on a *presentation* canvas,\n * never on the canvas `ghosting` decays into — see `presentWithFinish`. Fed\n * back into the persistence loop, a static tile would reinforce itself every\n * frame into mud.\n */\nimport { latticeHash } from './field';\nimport type { FinishSpec } from './types';\n\n/** Grain tile side (px). Repeats across the frame. */\nexport const GRAIN_TILE = 256;\n/** Ordered-dither tile side (px): an 8×8 Bayer matrix. */\nexport const DITHER_TILE = 8;\n/** Composite alpha at `grain: 1`. */\nexport const GRAIN_ALPHA = 0.35;\n/** Composite alpha at `dither: 1`. */\nexport const DITHER_ALPHA = 0.25;\n/** Offset step rate under `animate: true`. */\nexport const FINISH_ANIMATE_HZ = 12;\n\nconst clamp01 = (v: number): number => (v < 0 ? 0 : v > 1 ? 1 : v);\n\n/** The clamped strengths a spec's finish resolves to (0 when absent). */\nexport function finishStrength(f: FinishSpec | undefined): { grain: number; dither: number } {\n return { grain: clamp01(f?.grain ?? 0), dither: clamp01(f?.dither ?? 0) };\n}\n\n/**\n * RGBA pixels of the grain tile for `seed`: zero-mean grey noise (the sum of\n * two lattice hashes — a triangular distribution, softer than uniform —\n * centred on 128), alpha 255. Pure; the same seed gives the same tile on\n * every platform.\n */\nexport function grainTilePixels(seed: number): Uint8ClampedArray {\n const px = new Uint8ClampedArray(GRAIN_TILE * GRAIN_TILE * 4);\n const s = seed >>> 0;\n let i = 0;\n for (let y = 0; y < GRAIN_TILE; y++) {\n for (let x = 0; x < GRAIN_TILE; x++) {\n const v = (latticeHash(x, y, s) + latticeHash(x, y, s + 0x5bd1e995)) / 2;\n const g = Math.round(128 + (v - 0.5) * 255);\n px[i++] = g;\n px[i++] = g;\n px[i++] = g;\n px[i++] = 255;\n }\n }\n return px;\n}\n\n/** The 8×8 Bayer ordered-dither matrix (values 0..63, recursively built). */\nexport function bayerMatrix(): number[][] {\n let m: number[][] = [[0]];\n for (let n = 1; n < DITHER_TILE; n *= 2) {\n const next: number[][] = [];\n for (let y = 0; y < n * 2; y++) {\n const row: number[] = [];\n for (let x = 0; x < n * 2; x++) {\n const base = m[y % n]![x % n]! * 4;\n const quadrant = (y >= n ? 2 : 0) + (x >= n ? 1 : 0);\n row.push(base + [0, 2, 3, 1][quadrant]!);\n }\n next.push(row);\n }\n m = next;\n }\n return m;\n}\n\n/**\n * RGBA pixels of the dither tile: the Bayer matrix as grey levels\n * `(v + 0.5) / 64 × 255`, so the tile's mean is mid grey (zero-mean under a\n * symmetric blend). A stylistic screen — it is composited at low alpha, not\n * used to threshold the image per pixel.\n */\nexport function bayerTilePixels(): Uint8ClampedArray {\n const m = bayerMatrix();\n const px = new Uint8ClampedArray(DITHER_TILE * DITHER_TILE * 4);\n let i = 0;\n for (let y = 0; y < DITHER_TILE; y++) {\n for (let x = 0; x < DITHER_TILE; x++) {\n const g = Math.round(((m[y]![x]! + 0.5) / (DITHER_TILE * DITHER_TILE)) * 255);\n px[i++] = g;\n px[i++] = g;\n px[i++] = g;\n px[i++] = 255;\n }\n }\n return px;\n}\n\n/**\n * Where the grain tile sits for scene time `t`: fixed at the origin unless\n * `animate`, in which case it steps to a seeded offset (0..255 per axis)\n * once per 1/12 s bucket — a pure function of `(t, seed)`.\n */\nexport function grainOffset(t: number, seed: number, animate: boolean): { x: number; y: number } {\n if (!animate) return { x: 0, y: 0 };\n const bucket = Math.floor((t * FINISH_ANIMATE_HZ) / 1000);\n const s = seed >>> 0;\n return {\n x: Math.floor(latticeHash(bucket, 1, s) * GRAIN_TILE),\n y: Math.floor(latticeHash(bucket, 2, s) * GRAIN_TILE),\n };\n}\n\nexport type ScreenOp = 'overlay' | 'soft-light' | 'multiply';\n\n/**\n * The symmetric blend the finish composites with. `overlay` is what every\n * shipping canvas2d implements; the readback detect exists for the odd\n * context that rejects it (an assignment the context does not support leaves\n * the previous value in place).\n */\nexport function pickScreenOp(ctx: { globalCompositeOperation: string }): ScreenOp {\n const prev = ctx.globalCompositeOperation;\n let op: ScreenOp = 'multiply';\n for (const candidate of ['overlay', 'soft-light'] as const) {\n ctx.globalCompositeOperation = candidate;\n if (ctx.globalCompositeOperation === candidate) {\n op = candidate;\n break;\n }\n }\n ctx.globalCompositeOperation = prev;\n return op;\n}\n\ntype Canvas2D = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\ntype AnyCanvas = HTMLCanvasElement | OffscreenCanvas;\n\n/**\n * A presentation pass: the visible canvas and the tiles (as repeat\n * patterns, created lazily and cached — patterns are bound to the context\n * that made them). Owned by the instance that presents; the scene itself is\n * drawn on a separate canvas that this pass copies from.\n */\nexport interface FinishPass {\n canvas: AnyCanvas;\n ctx: Canvas2D;\n op: ScreenOp;\n grain: CanvasPattern | null;\n dither: CanvasPattern | null;\n /** Seed the grain tile was generated for. */\n seed: number;\n}\n\n/** A canvas of `size`² px carrying `pixels`, or null where ImageData is unavailable. */\nfunction tileCanvas(size: number, pixels: Uint8ClampedArray): AnyCanvas | null {\n const canvas: AnyCanvas = typeof document !== 'undefined' ? document.createElement('canvas') : new OffscreenCanvas(size, size);\n canvas.width = size;\n canvas.height = size;\n const ctx = canvas.getContext('2d') as Canvas2D | null;\n if (!ctx || typeof ctx.createImageData !== 'function') return null;\n const img = ctx.createImageData(size, size);\n img.data.set(pixels);\n ctx.putImageData(img, 0, 0);\n return canvas;\n}\n\n/** Open a presentation pass on `visible`; null if it has no 2d context. */\nexport function createFinishPass(visible: AnyCanvas, seed: number): FinishPass | null {\n const ctx = visible.getContext('2d', { alpha: false }) as Canvas2D | null;\n if (!ctx) return null;\n return { canvas: visible, ctx, op: pickScreenOp(ctx), grain: null, dither: null, seed };\n}\n\n/** A fresh scene canvas for the instance to draw into (never attached to the DOM). */\nexport function createSceneCanvas(width: number, height: number): AnyCanvas {\n if (typeof document === 'undefined') return new OffscreenCanvas(Math.max(1, width), Math.max(1, height));\n const canvas = document.createElement('canvas');\n canvas.width = Math.max(1, width);\n canvas.height = Math.max(1, height);\n return canvas;\n}\n\nfunction pattern(fp: FinishPass, size: number, pixels: Uint8ClampedArray): CanvasPattern | null {\n const tile = tileCanvas(size, pixels);\n if (!tile || typeof fp.ctx.createPattern !== 'function') return null;\n return fp.ctx.createPattern(tile as CanvasImageSource, 'repeat');\n}\n\n/**\n * Copy `scene` onto the pass's canvas and screen the finish over it:\n * grain at `grain × 0.35` (tile offset per `grainOffset`), then dither at\n * `dither × 0.25`, both with the pass's blend op and no image smoothing (a\n * crisp screen). With nothing to apply it is a plain copy. `w`/`h` are the\n * logical size the context transform maps to the canvas. `seed` is the\n * effective seed the *current* finish resolves to — a sequence with a\n * segment-level finish can present a different seed per frame (one segment\n * to the next); it defaults to the pass's own seed, so a single-scene\n * caller (whose seed never changes) can omit it. The cached grain pattern\n * is rebuilt whenever the seed changes.\n */\nexport function presentWithFinish(\n fp: FinishPass,\n scene: AnyCanvas,\n w: number,\n h: number,\n t: number,\n finish: FinishSpec | undefined,\n animateAllowed: boolean,\n seed: number = fp.seed,\n): void {\n const p = fp.ctx;\n p.globalAlpha = 1;\n p.globalCompositeOperation = 'source-over';\n p.drawImage(scene as CanvasImageSource, 0, 0, w, h);\n // Same normalization SpecInstance applies to every seed it renders with\n // (0 is falsy, so a valid `seed: 0` lands on 1) — callers may pass a raw,\n // un-normalized seed, and the comparison below needs both sides in the\n // same space or a `seed: 0` scene would never match `fp.seed`.\n const normalizedSeed = (seed >>> 0) || 1;\n if (normalizedSeed !== fp.seed) {\n fp.seed = normalizedSeed;\n fp.grain = null;\n }\n const { grain, dither } = finishStrength(finish);\n if (grain > 0) {\n fp.grain ??= pattern(fp, GRAIN_TILE, grainTilePixels(fp.seed));\n if (fp.grain) screen(fp, fp.grain, grain * GRAIN_ALPHA, grainOffset(t, fp.seed, animateAllowed && finish?.animate === true), w, h);\n }\n if (dither > 0) {\n fp.dither ??= pattern(fp, DITHER_TILE, bayerTilePixels());\n if (fp.dither) screen(fp, fp.dither, dither * DITHER_ALPHA, { x: 0, y: 0 }, w, h);\n }\n}\n\nfunction screen(fp: FinishPass, pat: CanvasPattern, alpha: number, off: { x: number; y: number }, w: number, h: number): void {\n const p = fp.ctx;\n p.save();\n p.globalCompositeOperation = fp.op;\n p.globalAlpha = alpha;\n p.imageSmoothingEnabled = false;\n p.fillStyle = pat;\n // The pattern's origin follows the transform: shift it by the offset and\n // fill the same frame rectangle from there.\n p.translate(-off.x, -off.y);\n p.fillRect(off.x, off.y, w, h);\n p.restore();\n}\n","/**\n * `trail` sampling — pure, shared by the renderer (`drawTrail`) and\n * perception (`splatTrail`), so the afterglow the wall paints and the one the\n * luminance grid counts are the same echoes.\n *\n * A trail is `n` echoes of the entity at past times (`length / 50` of them,\n * at most `LIMITS.maxTrailSamples`), each fainter (`fade`) and smaller (to\n * 30 % at the tail). A slow mover's echoes overlap into a smear; a fast one's\n * fell apart into separate dots (X469: a 5 s trail on a path circle was 24\n * dots 208 ms apart). The renderer joins a hard circle's echoes into one\n * ribbon (`ribbonSides`), which needs no extra echoes; for soft discs, and\n * for perception, wherever two neighbouring echoes sit further apart than\n * the echo's radius, echoes are added between them — at their own\n * interpolated times, so they follow the curve — until neighbours are at\n * most a radius apart, within a small per-layer budget (`trailFillBudget`). A trail whose echoes already touch gets no\n * extras: every such trail draws exactly what it drew before.\n *\n * A filled span stands in for the one echo it replaces, so its echoes share\n * that echo's ink: each one's alpha is scaled so the ~2r/spacing discs that\n * overlap any point of the ribbon add up to the single echo's alpha (summed\n * under `lighter`, composited otherwise). Without that, a fast additive dot\n * saturated to white along its ribbon instead of keeping its colour and fade.\n */\nimport { LIMITS } from './types';\n\nexport interface TrailEcho {\n /** Scene time of the echo, ms. */\n t: number;\n x: number;\n y: number;\n /** How far back along the trail, 0 (head) .. 1 (tail). */\n k: number;\n alpha: number;\n /** Echo radius in px (the head's half-size, shrinking to 30 % at the tail). */\n r: number;\n}\n\nexport interface TrailSpec {\n length: number;\n fade?: number;\n}\n\n/**\n * Most extra (gap-filling) echoes one entity may add per frame. The layer\n * shares 240 (ten entities' worth of the 24 time samples), at most 48 per\n * entity, however fast it moves — sized against frame time on a Raspberry\n * Pi-class (4× throttled CPU) wall: `comets` stays within ~20 % of its\n * pre-fill cost.\n */\nexport function trailFillBudget(layerCount: number): number {\n return Math.max(4, Math.min(48, Math.floor(240 / Math.max(1, layerCount))));\n}\n\n/**\n * The echoes behind an entity at scene time `t`, head first. `posAt` is the\n * entity's position at any time; `headAlpha` / `headSize` its alpha and size\n * now. Sampling stops at a wrap seam (a jump of more than half the viewport),\n * at the clock's start, or where an echo would be invisible (`alpha ≤\n * minAlpha`, radius < 0.2 px). `fillBudget` caps the gap-filling echoes.\n */\nexport function trailEchoes(\n trail: TrailSpec,\n t: number,\n headAlpha: number,\n headSize: number,\n posAt: (t: number) => { x: number; y: number },\n w: number,\n h: number,\n wrap: boolean,\n fillBudget: number,\n minAlpha = 0,\n additive = false,\n): TrailEcho[] {\n const fade = trail.fade ?? 1;\n const n = Math.min(Math.ceil(trail.length / 50), LIMITS.maxTrailSamples);\n const alphaAtK = (k: number): number => headAlpha * (1 - k * fade);\n const radiusAtK = (k: number): number => (headSize / 2) * (1 - k * 0.7);\n const jumps = (a: { x: number; y: number }, b: { x: number; y: number }): boolean =>\n wrap && (Math.abs(b.x - a.x) > w / 2 || Math.abs(b.y - a.y) > h / 2);\n\n const head = posAt(t);\n const base: TrailEcho[] = [];\n let prev = head;\n for (let s = 1; s <= n; s++) {\n const k = s / n;\n const pastT = t - k * trail.length;\n if (pastT < 0) break;\n const pos = posAt(pastT);\n if (jumps(prev, pos)) break;\n prev = pos;\n const a = alphaAtK(k);\n if (a <= minAlpha) break;\n const r = radiusAtK(k);\n if (r < 0.2) break;\n base.push({ t: pastT, x: pos.x, y: pos.y, k, alpha: a, r });\n }\n if (base.length === 0) return base;\n\n // Gap fill: how many echoes each span (head → echo 1, echo 1 → 2, …) needs.\n const need: number[] = [];\n let total = 0;\n for (let i = 0; i < base.length; i++) {\n const a = i === 0 ? head : base[i - 1]!;\n const b = base[i]!;\n const d = Math.hypot(b.x - a.x, b.y - a.y);\n const m = d > b.r ? Math.ceil(d / b.r) - 1 : 0;\n need.push(m);\n total += m;\n }\n if (total === 0) return base;\n const scale = total > fillBudget ? fillBudget / total : 1;\n\n const out: TrailEcho[] = [];\n let last = head;\n for (let i = 0; i < base.length; i++) {\n const b = base[i]!;\n const m = Math.floor(need[i]! * scale);\n if (m === 0) {\n out.push(b);\n last = b;\n continue;\n }\n const a = i === 0 ? head : base[i - 1]!;\n const spacing = Math.hypot(b.x - a.x, b.y - a.y) / (m + 1);\n // Share of the replaced echo's ink each of the span's echoes carries.\n const share = (alpha: number, r: number): number => {\n const k = Math.min(1, spacing / (2 * r));\n return additive ? alpha * k : 1 - Math.pow(1 - Math.min(1, alpha), k);\n };\n const t0 = i === 0 ? t : base[i - 1]!.t;\n const k0 = i === 0 ? 0 : base[i - 1]!.k;\n for (let j = 1; j <= m; j++) {\n const f = j / (m + 1);\n const tt = t0 + (b.t - t0) * f;\n const k = k0 + (b.k - k0) * f;\n const pos = posAt(tt);\n if (jumps(last, pos)) continue;\n last = pos;\n const r = radiusAtK(k);\n out.push({ t: tt, x: pos.x, y: pos.y, k, alpha: share(alphaAtK(k), r), r });\n }\n out.push({ ...b, alpha: share(b.alpha, b.r) });\n last = b;\n }\n return out;\n}\n","import { createRng } from '@idle-screens/core';\nimport { additivePlate, backgroundLuma, backgroundRgb, backgroundRgbAt, colourSeparation, hexLuma, hexRgb, legibilityRatio, relativeLuminance, sourceOverPlate, spriteHex, type Rgb } from './luma';\nimport { COHESION_T, cohesionOf, seamsWorthWarning } from './cohesion';\nimport { barFraction, polygonArea, polygonPoints } from './shapes';\nimport { breakTextBlock, buildEntities, entityScales, linkEdges, linkMaxDistPx, linkPairs, positionAt, textBlockAnchorOffset, textMetricsClassFor, textWidthEm, WARP_MAX_SCALE, type Entity } from './simulate';\nimport { morphNothingMorphable, structuralSignature } from './steer';\nimport { luminanceGrid } from './perceive';\nimport { groupOf, mapBox, paintMap, paintOpacity, paintSize } from './paint';\nimport { resolveTimelineAt, timelineTracks } from './timeline';\nimport { LIMITS, type IdleSequence, type LayerSpec, type SaverSpec, type SpecWarning, type WarningBox } from './types';\n\n/**\n * Minimum RGB-space colour distance (see `colourSeparation`) between a layer\n * and its background before the layer stops reading as a distinct thing.\n *\n * Calibrated against real specs rather than picked: a layer painted the literal\n * background hex measures 0.000, a near-background dark-on-dark layer ~0.036,\n * while every one of the 15 shipped examples and all 150 style-eval screens\n * clear it except the genuinely-flawed ones. Note this is a *colour* distance —\n * a Seurat-style gold-on-grey field separates by 0.39 here but only 0.013 in\n * luma, which is exactly why the measure is not luminance-based.\n */\nconst LOW_CONTRAST_FLOOR = 0.05;\n\n/**\n * A spec that declares `density: 'sparse'` is promising a mostly-empty frame.\n * Above this alpha-weighted coverage the promise is broken (2 % of the frame\n * is a comfortable field, not restraint — `lanterns` measures ~1.5 %).\n */\nconst SPARSE_DECLARED_MAX_COVERAGE = 0.02;\n\n/**\n * WCAG AA floor for body text. Only layers that declare `role: 'read'` are\n * measured against it — atmospheric text is texture, not copy, and the\n * shipped examples paint it at 2–3:1 on purpose.\n */\nconst READ_LEGIBILITY_FLOOR = 4.5;\n\n/** A `role: 'read'` box closer than this to any edge is in the overscan / bezel zone. */\nconst READ_SAFE_AREA = 0.05;\n\n/**\n * Alpha-weighted area (in viewport-areas) that additive `lighter`/`screen`\n * layers stack onto the frame before the analytic model is warned that it can\n * no longer see what it is measuring. The analytic luminance/dominance model\n * sums glow splats with no saturation ceiling, so a stack that clips to white\n * on a real canvas reports tame numbers and zero advisories (F35 — a\n * 250-entity white/cream `lighter` stack came back coverage 0.25, meanLuminance\n * 0.25, advisories []). Measured: the brightest shipped examples (`aurora`,\n * `warp-tunnel`) sit at 0.1, the recommended \"80 tiny soft circles at alpha\n * 0.2\" atmosphere at 0.0, and that stack at 2.0 — so 1.0 is an order of\n * magnitude above anything shipped and still half of the known blowout.\n */\nconst ADDITIVE_INK_CEILING = 1.0;\n\n/** True when a region window is butted against an edge on the given axis and\n * is a band rather than the whole axis — the shape of a deliberate anchor\n * (a skyline along the bottom, a ceiling of stars along the top). */\nfunction edgeAnchored(range: [number, number] | undefined): boolean {\n if (!range) return false;\n const [a, b] = range;\n return (a <= 0.02 || b >= 0.98) && b - a <= 0.6;\n}\n\n/**\n * Non-blocking advisory warnings for a valid spec. Does NOT replace validateSpec —\n * call advise only on specs that have already passed validation.\n */\nexport function adviseSpec(\n spec: SaverSpec,\n viewport = { width: 1920, height: 1080 },\n /**\n * Sample point. `perceiveScene` forwards its own `t`/`seed` so the advisories\n * describe the same scene its other channels do — without them a caller\n * perceiving at t = 30 s would get `form` for that instant beside an\n * `overlap-seams` advisory computed for a different one.\n *\n * `backgroundSeed` is separate from `seed` because a sequence's\n * `inkOverBed` (the segment's ink layers judged against the bed's\n * background — see `perceiveSequenceFrame`) mixes two scenes with\n * potentially different seeds: `seed` drives the ink layers' own entity\n * stream, `backgroundSeed` samples the bed's field. Defaults to `seed` —\n * every other caller has one scene and one seed for both.\n */\n opts: { t?: number; seed?: number; backgroundSeed?: number } = {},\n): SpecWarning[] {\n // Which layers never show in this scene — paint opacity (the layer's own ×\n // its group's) 0 at every key boundary of its timeline, or simply 0 without\n // one. A timed piece keeps every prop in every act and hides the unused\n // ones; judging those would bury the real advisories. Without `opacity` or\n // `groups` no layer is hidden and every check below runs as it always has.\n const hidden = hiddenLayers(spec);\n // A `timeline` resolves at the sample time; without one this is `spec` itself.\n spec = resolveTimelineAt(spec, opts.t ?? COHESION_T);\n const warnings: SpecWarning[] = [];\n const w = viewport.width;\n const h = viewport.height;\n const { scale, countScale } = entityScales(spec, w, h);\n const rng = createRng(opts.seed ?? spec.seed ?? 42);\n const allEntities = spec.layers.map((l) => buildEntities(l, rng, w, h, scale, countScale));\n\n // Do overlapping layers actually merge? Computed once from the entities we\n // already built; the advisory below fires only on the case where the author\n // clearly wanted one shape and the paint settings defeat it.\n const cohesion = cohesionOf(\n spec.layers.map((layer, i) => ({ layer, entities: allEntities[i]! })),\n opts.t ?? COHESION_T, w, h,\n );\n\n let totalEntities = 0;\n let textLayerCount = 0;\n let motionLayerCount = 0;\n\n for (let li = 0; li < spec.layers.length; li++) {\n if (hidden?.[li]) continue;\n const layer = spec.layers[li]!;\n const entities = allEntities[li]!;\n totalEntities += entities.length;\n\n const isText = layer.sprite.kind === 'text' || layer.sprite.kind === 'textBlock';\n const isStaticText = isText && layer.motion.type === 'static';\n if (isStaticText) textLayerCount++;\n if (layer.motion.type !== 'static') motionLayerCount++;\n\n const coh = cohesion[li]!;\n if (seamsWorthWarning(layer, coh, entities.length)) {\n // A soft or feathered edge has no edge to paint: overlaps pool into\n // smooth lumps, which is a cloud or a haze, not a seam. Measured live\n // (X423): the hard-edged control showed every overlap as an outline,\n // the soft storm showed none. What soft cannot do is make ONE solid\n // shape — say that, and leave clouds to the author.\n const s = layer.sprite;\n const softEdged = ((s.kind === 'circle' || s.kind === 'polygon') && s.soft) || (s.kind === 'rect' && !!s.feather);\n warnings.push({\n path: `layers[${li}]`,\n code: 'overlap-seams',\n message: softEdged\n ? `entities bury ${Math.round((coh.overlap ?? 0) * 100)}% of each other's outlines, but ${coh.seamCause}: `\n + 'overlaps pool into soft lumps rather than one solid silhouette (no hard edges — a cloud, smoke or haze reads well this way). '\n + 'If this layer is meant to be ONE solid shape, make it one flat colour at alpha 1, hard-edged, with no blend and no pulse.'\n : `entities bury ${Math.round((coh.overlap ?? 0) * 100)}% of each other's outlines, so this layer is drawn as one shape — `\n + `but ${coh.seamCause}, so every overlap paints a visible edge and it will read as a pile of sprites instead. `\n + 'A layer merges into a single silhouette only when it is one flat colour at alpha 1, hard-edged, with no blend and no pulse.',\n });\n }\n\n if (layer.trail && layer.motion.type === 'static') {\n warnings.push({\n path: `layers[${li}].trail`,\n code: 'trail-on-static',\n message: 'trail has no effect on static entities — they have no past positions to draw',\n });\n }\n\n // A spinning streak has an orientation of its own (a rotor, a clock hand),\n // so \"no heading\" is not a problem for it (F34.5).\n if ((layer.sprite.kind === 'streak' || (layer.sprite.kind === 'stroke' && layer.sprite.orient)) && layer.motion.type === 'static' && !layer.spin) {\n warnings.push({\n path: `layers[${li}].sprite`,\n code: 'streak-on-static',\n message: `${layer.sprite.kind === 'streak' ? 'streak sprites orient' : 'an oriented stroke turns'} along the motion heading — static entities have none, so the heading contributes nothing and it renders at angle 0`,\n });\n }\n\n if (layer.motion.type === 'wander' && layer.motion.coherence === 1 && entities.length >= 20) {\n warnings.push({\n path: `layers[${li}].motion.coherence`,\n code: 'full-coherence',\n message: 'coherence 1 makes every entity share identical harmonics — the layer moves as a rigid sheet. 0.5–0.8 reads as schooling',\n });\n }\n\n if (layer.sprite.kind === 'circle') {\n const maxR = entities.reduce((m, e) => Math.max(m, e.size / 2), 0);\n const maxAlpha = entities.reduce((m, e) => Math.max(m, e.alpha), 0);\n if (maxR * maxAlpha < 0.05) {\n warnings.push({\n path: `layers[${li}]`,\n code: 'invisible-layer',\n message: `layer's max visible radius (${maxR.toFixed(1)}px × ${maxAlpha.toFixed(2)} alpha) is below perceptual floor`,\n });\n }\n }\n\n // Colour separation: a layer painted the same brightness as the plate\n // behind it is invisible no matter how big or opaque it is. `invisible-layer`\n // above only measures radius × alpha, so a full-strength layer in a\n // background-matched colour passes every other check in this file.\n if (entities.length > 0 && layer.sprite.kind !== 'emoji') {\n // Judge against the plate the layer actually sits on: a gradient is\n // sampled across the layer's vertical extent (its region window, or its\n // pinned position), not averaged over a sky the layer never touches. A\n // layer is visible if it separates ANYWHERE in that extent (F19).\n const [y0, y1] = layer.position ? [layer.position.y, layer.position.y] : (layer.region?.y ?? [0, 1]);\n const plates = [y0, (y0 + y1) / 2, y1].map((y) => {\n const rgb = backgroundRgbAt(spec, y * h, h, scale, undefined, undefined, opts.backgroundSeed ?? opts.seed, opts.t ?? COHESION_T);\n return { rgb, luma: 0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b };\n });\n // A palette layer is visible if ANY of its colours separates — flag only\n // when every colour it can paint with disappears into the plate.\n const seps = entities.map((e) => {\n const hex = spriteHex(layer, e);\n if (hex === null) return Infinity;\n const ink = { rgb: hexRgb(hex), luma: hexLuma(hex) };\n const sep = Math.max(...plates.map((bg) => colourSeparation(layer, ink, bg)));\n if (sep >= LOW_CONTRAST_FLOOR || layer.blend === 'lighter' || layer.blend === 'screen') return sep;\n // Close to the page colour — but the page may not be what is behind\n // it. A dark key plate on an opaque yellow panel is judged against the\n // panel, which is what the eye (and perception's dominance) sees (X388).\n const under = groundUnder(spec, allEntities, li, hidden, positionAt(e, 0, w, h), w, h);\n return under ? colourSeparation(layer, ink, under) : sep;\n });\n const best = Math.max(...seps);\n if (best < LOW_CONTRAST_FLOOR) {\n const additive = layer.blend === 'lighter' || layer.blend === 'screen';\n warnings.push({\n path: `layers[${li}].sprite`,\n code: 'low-contrast-layer',\n message: additive\n ? `additive layer adds almost no light (luma ${best.toFixed(3)}) — a \"lighter\"/\"screen\" layer is only as visible as it is bright`\n : `layer colour is within ${best.toFixed(3)} of the background, or of the solid layer under it (floor ${LOW_CONTRAST_FLOOR}) — it will read as background, not as content`,\n });\n }\n }\n\n }\n\n // Alpha-weighted pixel coverage: how much of the viewport is \"visibly filled\"\n let totalCoverage = 0;\n let additiveInk = 0;\n for (let li = 0; li < spec.layers.length; li++) {\n if (hidden?.[li]) continue;\n const layer = spec.layers[li]!;\n const entities = allEntities[li]!;\n // Paint opacity weighs coverage like alpha does (unset ⇒ exactly as before).\n const paintA = layer.opacity === undefined && layer.group === undefined ? 1 : paintOpacity(spec, layer);\n // A layer/group transform scales what is painted, so it scales the area\n // too — the text boxes below already land where the transform puts them,\n // and coverage must judge the same picture (X418: a word zoomed 8× read\n // as both \"the scene is empty\" and \"the text runs 33 000 px off-screen\").\n const map = paintMap(spec, layer, w, h, scale);\n const areaScale = map ? paintSize(spec, layer) ** 2 : 1;\n const additive = layer.blend === 'lighter' || layer.blend === 'screen';\n for (const e of entities) {\n const r = e.size / 2;\n let pixArea: number;\n if (layer.sprite.kind === 'circle') {\n pixArea = Math.PI * r * r;\n } else if (layer.sprite.kind === 'polygon') {\n // The outline's own area, not its bounding square (4r²) — a flat band\n // or ridge fills a fraction of that.\n pixArea = polygonArea(polygonPoints(layer.sprite, r));\n } else if (layer.sprite.kind === 'bar') {\n pixArea = e.size * barFraction(layer.sprite, e.barIndex ?? 0) * (e.size2 ?? e.size * 0.2);\n } else if (layer.sprite.kind === 'textBlock') {\n const fsPx = layer.sprite.fontSize * scale;\n const lh = (layer.sprite.lineHeight ?? 1.4) * fsPx;\n const maxWPx = layer.sprite.maxWidth * scale;\n const lines = breakTextBlock(layer.sprite.text, maxWPx / fsPx, textMetricsClassFor(layer.sprite.font));\n pixArea = maxWPx * lines.length * lh * 0.55 * (layer.sprite.opacity ?? 1);\n } else if (layer.sprite.kind === 'text') {\n // The renderer's own box (a px `font` wins over the seeded size), at\n // the ~55 % ink fill a textBlock line is credited with.\n const b = textBoxAt(layer.sprite, e, positionAt(e, 0, w, h), spec, w, h);\n pixArea = (b.x1 - b.x0) * (b.y1 - b.y0) * 0.55;\n } else {\n pixArea = e.size * e.size; // emoji: approximate as square of its size\n }\n // Scaled by the transform, and never more than the frame it lands in.\n if (areaScale !== 1) pixArea *= areaScale;\n if (pixArea > w * h) pixArea = w * h;\n // Sparse-event layers are lit only for `life` of every `every` ms, at a\n // mean envelope of ~½, and at a mean grown size — judge their coverage\n // by that duty, not by whichever instant we happen to sample.\n let duty = 1;\n if (layer.emit) {\n // Area scales with size², so the time-mean over a linear size ramp\n // a→b is mean(f²) = (a² + ab + b²) / 3, not mean(f)².\n const [ga, gb] = layer.emit.grow ?? [1, 1];\n const g2 = (ga * ga + ga * gb + gb * gb) / 3;\n duty = (Math.min(layer.emit.life, layer.emit.every) / layer.emit.every) * 0.5 * g2;\n }\n const ink = paintA === 1 ? (pixArea * e.alpha * duty) / (w * h) : (pixArea * e.alpha * duty * paintA) / (w * h);\n totalCoverage += ink;\n if (additive) additiveInk += ink;\n }\n // Link lines are visual coverage too (for Mystify-style scenes they ARE the scene).\n if (layer.links) {\n const positions = entities.map((e) => positionAt(e, 0, w, h));\n const edges = linkEdges(layer.links, positions, linkMaxDistPx(layer.links, scale), layer.wrap !== false, w, h);\n const defaultWidth = scale === 1 ? 1 : 1 / LIMITS.referenceViewport;\n const lwPx = (layer.links.width ?? defaultWidth) * scale;\n const la = layer.links.alpha ?? 1;\n for (const edge of edges) totalCoverage += paintA === 1 ? (edge.dist * lwPx * la) / (w * h) : (edge.dist * lwPx * la * paintA) / (w * h);\n }\n }\n\n // A declared `density` is read before either density advisory fires — and\n // then checked against the measurement, so the declaration cannot be used\n // to silence a scene that is empty by accident rather than by intent.\n const density = spec.density ?? 'normal';\n const wouldBeSparse = totalCoverage < 0.0005 && spec.layers.length > 0;\n if (wouldBeSparse && density !== 'sparse') {\n warnings.push({\n path: 'layers',\n code: 'sparse-scene',\n message: `alpha-weighted coverage is ${(totalCoverage * 100).toFixed(4)}% — scene will look empty on most displays`,\n });\n }\n\n if (additiveInk > ADDITIVE_INK_CEILING) {\n warnings.push({\n path: 'layers',\n code: 'additive-saturation',\n message: `\"lighter\"/\"screen\" layers stack ${additiveInk.toFixed(1)}× the frame's area in alpha-weighted light — overlapping additive sprites clip to white on a real canvas, and the analytic perception model sums them without a ceiling so its coverage/luminance/dominance numbers cannot see it. Thin the count, lower alpha (summed additive alpha at any point ≲ 0.5), or drop blend on the densest layer`,\n });\n }\n\n if (totalEntities > 500 && density !== 'dense') {\n warnings.push({\n path: 'layers',\n code: 'dense-scene',\n message: `${totalEntities} entities — scene may feel crowded and hurt performance on low-end devices`,\n });\n }\n\n if (density === 'sparse' && totalCoverage > SPARSE_DECLARED_MAX_COVERAGE) {\n warnings.push({\n path: 'density',\n code: 'density-mismatch',\n message: `declared sparse but alpha-weighted coverage is ${(totalCoverage * 100).toFixed(2)}% — either the declaration or the scene is wrong`,\n });\n } else if (density === 'dense' && wouldBeSparse) {\n warnings.push({\n path: 'density',\n code: 'density-mismatch',\n message: `declared dense but alpha-weighted coverage is ${(totalCoverage * 100).toFixed(4)}% — the scene will look empty`,\n });\n }\n\n if (spec.layers.length > 0 && textLayerCount > 0 && motionLayerCount === 0) {\n const textRatio = textLayerCount / spec.layers.length;\n if (textRatio >= 0.8) {\n warnings.push({\n path: 'layers',\n code: 'text-heavy',\n message: 'most layers are static text — reads as a document, not a screensaver',\n });\n }\n }\n\n // Link starvation: links layer where few edges actually form.\n // Chain mode always forms its edges — only distance-gated modes can starve.\n for (let li = 0; li < spec.layers.length; li++) {\n if (hidden?.[li]) continue;\n const layer = spec.layers[li]!;\n if (!layer.links || layer.links.mode === 'chain') continue;\n const entities = allEntities[li]!;\n const positions = entities.map((e) => positionAt(e, 0, w, h));\n const k = layer.links.k ?? 1;\n const pairs = linkPairs(positions, k, linkMaxDistPx(layer.links, scale), layer.wrap !== false, w, h);\n const maxPossible = Math.min(entities.length * k, entities.length * (entities.length - 1) / 2);\n if (maxPossible > 0 && pairs.length / maxPossible < 0.1) {\n warnings.push({\n path: `layers[${li}].links`,\n code: 'link-starvation',\n message: `only ${pairs.length}/${maxPossible} possible edges formed — raise count or widen links.maxDist`,\n });\n }\n }\n\n // Motion variety: all entities in a layer have nearly identical velocity\n for (let li = 0; li < spec.layers.length; li++) {\n if (hidden?.[li]) continue;\n const layer = spec.layers[li]!;\n if (layer.motion.type === 'static') continue;\n const entities = allEntities[li]!;\n if (entities.length < 3) continue;\n const speeds = entities.map((e) => Math.sqrt(e.vx * e.vx + e.vy * e.vy));\n const mean = speeds.reduce((a, b) => a + b, 0) / speeds.length;\n if (mean === 0) continue;\n const maxDev = Math.max(...speeds.map((s) => Math.abs(s - mean)));\n if (maxDev / mean < 0.05) {\n warnings.push({\n path: `layers[${li}].motion`,\n code: 'uniform-motion',\n message: 'all entities move at nearly identical speed — widen the speed range for visual variety',\n });\n }\n }\n\n // Composition balance: entities clustered in one region. Motions that sweep the\n // whole viewport (bounce, warp, path) have transient spawn positions that say\n // nothing about composition — exclude them from the centroid.\n const composed = spec.layers\n .map((l, li) => ({ l, li, ents: allEntities[li]! }))\n .filter(({ li }) => !hidden?.[li])\n .filter(({ l }) => !['bounce', 'warp', 'path'].includes(l.motion.type))\n // Layer-parented orbits position relative to their parent (resolved at render\n // time) — their raw positionAt is an offset around (0,0), not a screen position.\n .filter(({ l }) => !(l.motion.type === 'orbit' && l.motion.center && 'layer' in l.motion.center));\n const composedCount = composed.reduce((s, c) => s + c.ents.length, 0);\n if (composedCount >= 8) {\n const positions = composed.flatMap(({ ents }) => ents.map((e) => positionAt(e, 0, w, h)));\n const px = positions.reduce((s, p) => s + p.x, 0) / positions.length / w;\n const py = positions.reduce((s, p) => s + p.y, 0) / positions.length / h;\n // A skyline sits low on purpose. When the offset is along ONE axis and most\n // of the composed entities come from layers whose region is butted against\n // an edge on that axis, the offset is the composition, not a mistake (F20).\n const offX = Math.abs(px - 0.5);\n const offY = Math.abs(py - 0.5);\n const anchoredOn = (axis: 'x' | 'y'): number =>\n composed.reduce((n, { l, ents }) => n + (edgeAnchored(l.region?.[axis]) ? ents.length : 0), 0) / composedCount;\n const intentional =\n (offY > 0.2 && offX <= 0.2 && anchoredOn('y') >= 0.5) ||\n (offX > 0.2 && offY <= 0.2 && anchoredOn('x') >= 0.5);\n if ((offX > 0.2 || offY > 0.2) && !intentional) {\n // Where the entities are is only a suspicion; where the ink is decides.\n // Confirmed on the same luminance grid — the same rule, cells weighted\n // by how far they sit from the background — that perception reports\n // beside it, so the two can no longer disagree in one response (X384:\n // 24 overlapping slivers in one half outweighed a full-height stripe in\n // the other, 0.73 counted vs 0.58 seen). It can only silence the head\n // count, never add a warning, and costs a grid only when it fires.\n const grid = luminanceGrid({ ...spec, layers: composed.map(({ l }) => l) }, { viewport: { width: w, height: h }, t: opts.t ?? COHESION_T, seed: opts.seed });\n const c = grid.centroid;\n if (c && (Math.abs(c.x - 0.5) > 0.2 || Math.abs(c.y - 0.5) > 0.2)) {\n warnings.push({\n path: 'layers',\n code: 'off-center',\n message: `centroid at (${c.x.toFixed(2)}, ${c.y.toFixed(2)}) — composition is heavily offset from center`,\n });\n }\n }\n }\n\n // Spatial text: the one layout bug an author without eyes makes most and\n // cannot detect — a caption that runs off the frame, a title painted over a\n // body. Only static text is judged (moving text has no fixed box). Boxes use\n // the character-class width table the textBlock line-breaker uses, so the\n // estimate is the renderer's own idea of the text, not a separate guess.\n const textBoxes: TextBoxAt[] = [];\n for (let li = 0; li < spec.layers.length; li++) {\n if (hidden?.[li]) continue;\n const layer = spec.layers[li]!;\n const s = layer.sprite;\n if (layer.motion.type !== 'static') continue;\n if (s.kind !== 'text' && s.kind !== 'textBlock') continue;\n const label = layer.key ? `\\`${layer.key}\\`` : `layers[${li}]`;\n for (const e of allEntities[li]!) {\n const p = positionAt(e, 0, w, h);\n const raw = s.kind === 'textBlock' ? textBlockBoxAt(s, p, w, h) : textBoxAt(s, e, p, spec, w, h);\n // A layer `transform` moves (and scales) the painted text: judge the box where it lands.\n const map = paintMap(spec, layer, w, h, scale);\n const box = map ? { ...raw, ...mapBox(map, raw) } : raw;\n // What the layer guarantees it paints, worst case: base alpha minus its\n // pulse trough (ignoring `emit`'s on/off envelope — a mark's on-screen\n // duty cycle is a readability question, not an ink-colour one; sampling\n // at `t = 0` would otherwise flag every emitting layer as invisible)\n // times a textBlock's own `opacity` — so faint or invisible\n // `role: 'read'` text can't hide behind an unmeasured alpha.\n const baseAlpha = Math.max(0, Math.min(1, e.alpha - e.pulseAmp)) * (s.kind === 'textBlock' ? (s.opacity ?? 1) : 1);\n const alpha = layer.opacity === undefined && layer.group === undefined ? baseAlpha : baseAlpha * paintOpacity(spec, layer);\n const str = s.kind === 'textBlock' ? s.text : (s.strings[e.spriteIndex] ?? s.strings[0] ?? '');\n textBoxes.push({ li, label, alpha, str, ...box, rawW: raw.x1 - raw.x0, rawH: raw.y1 - raw.y0 });\n }\n }\n const asFraction = (b: Pick<Box, 'x0' | 'y0' | 'x1' | 'y1'>): WarningBox => ({\n x: +(b.x0 / w).toFixed(4),\n y: +(b.y0 / h).toFixed(4),\n w: +((b.x1 - b.x0) / w).toFixed(4),\n h: +((b.y1 - b.y0) / h).toFixed(4),\n });\n\n // Off-screen: any edge past the viewport by more than 1% of that dimension\n // (the width table is approximate; a hairline overhang is not a finding).\n const tolX = w * 0.01;\n const tolY = h * 0.01;\n const offFlagged = new Set<number>();\n for (const b of textBoxes) {\n if (offFlagged.has(b.li)) continue;\n const edges: string[] = [];\n if (b.x0 < -tolX) edges.push(`left edge by ~${Math.round(-b.x0)}px`);\n if (b.x1 > w + tolX) edges.push(`right edge by ~${Math.round(b.x1 - w)}px`);\n if (b.y0 < -tolY) edges.push(`top edge by ~${Math.round(-b.y0)}px`);\n if (b.y1 > h + tolY) edges.push(`bottom edge by ~${Math.round(b.y1 - h)}px`);\n if (edges.length === 0) continue;\n offFlagged.add(b.li);\n warnings.push({\n path: `layers[${b.li}]`,\n code: 'text-off-screen',\n message: `${b.label} text runs off the ${edges.join(' and the ')} at ${w}×${h} — move position, or shrink fontSize / maxWidth`,\n });\n }\n\n // Overlap: two different static text layers whose boxes share more than 10%\n // of the smaller box. Reported once per layer pair, on the earlier layer.\n const pairFlagged = new Set<string>();\n for (let i = 0; i < textBoxes.length; i++) {\n for (let j = i + 1; j < textBoxes.length; j++) {\n const a = textBoxes[i]!;\n const b = textBoxes[j]!;\n if (a.li === b.li) continue;\n const pair = `${Math.min(a.li, b.li)}:${Math.max(a.li, b.li)}`;\n if (pairFlagged.has(pair)) continue;\n const ix = Math.min(a.x1, b.x1) - Math.max(a.x0, b.x0);\n const iy = Math.min(a.y1, b.y1) - Math.max(a.y0, b.y0);\n if (ix <= 0 || iy <= 0) continue;\n const smaller = Math.min((a.x1 - a.x0) * (a.y1 - a.y0), (b.x1 - b.x0) * (b.y1 - b.y0));\n if (smaller <= 0) continue;\n const share = (ix * iy) / smaller;\n if (share <= 0.1) continue;\n if (isOutlineStack(a, b)) continue;\n pairFlagged.add(pair);\n const [first, second] = a.li < b.li ? [a, b] : [b, a];\n warnings.push({\n path: `layers[${first.li}]`,\n code: 'text-overlap',\n message: `${first.label} and ${second.label} text boxes overlap (~${Math.round(share * 100)}% of the smaller one) — they will paint over each other; move one or shrink it`,\n // The two boxes, so an agent can move one without re-deriving the\n // layout. Additive: the message is unchanged.\n boxes: [asFraction(first), asFraction(second)],\n });\n }\n }\n\n // Cells of ONE list/table layer painting over each other (X214). A data\n // layout's `gap` is the pitch between cell anchors, not the space between\n // cells, so a label wider than the column pitch runs into its neighbour.\n // Only data layouts are judged: scattered text in one layer overlapping is\n // texture, not a layout bug. Same 10%-of-the-smaller-box rule as above.\n const cellFlagged = new Set<number>();\n for (let i = 0; i < textBoxes.length; i++) {\n const a = textBoxes[i]!;\n if (cellFlagged.has(a.li)) continue;\n const layer = spec.layers[a.li]!;\n const layout = layer.layout;\n if (layout?.type !== 'list' && layout?.type !== 'table') continue;\n for (let j = i + 1; j < textBoxes.length; j++) {\n const b = textBoxes[j]!;\n if (b.li !== a.li) continue;\n const ix = Math.min(a.x1, b.x1) - Math.max(a.x0, b.x0);\n const iy = Math.min(a.y1, b.y1) - Math.max(a.y0, b.y0);\n if (ix <= 0 || iy <= 0) continue;\n const smaller = Math.min((a.x1 - a.x0) * (a.y1 - a.y0), (b.x1 - b.x0) * (b.y1 - b.y0));\n if (smaller <= 0 || (ix * iy) / smaller <= 0.1) continue;\n cellFlagged.add(a.li);\n const cells = textBoxes.filter((x) => x.li === a.li);\n const dflt = scale === 1 ? LIMITS.defaultListGapPx : LIMITS.defaultListGap;\n const g = layout.gap ?? dflt;\n const gx = typeof g === 'number' ? g : g.x ?? dflt;\n const gy = typeof g === 'number' ? g : g.y ?? dflt;\n const cols = layout.type === 'list' ? 1 : Math.max(1, Math.round(layout.columns));\n const unitPx = (v: number): number => (scale === 1 ? v : v * scale);\n const fromPx = (px: number): number => (scale === 1 ? Math.ceil(px) : Math.ceil((px / scale) * 100) / 100);\n const maxW = cells.reduce((m, c) => Math.max(m, c.rawW), 0);\n const maxH = cells.reduce((m, c) => Math.max(m, c.rawH), 0);\n const fixes: string[] = [];\n const across = cols > 1 && maxW > unitPx(gx);\n if (across) fixes.push(`its labels are up to ~${Math.round(maxW)}px wide against a ${Math.round(unitPx(gx))}px column pitch (gap${typeof g === 'number' ? '' : '.x'} ${gx}) — raise gap${typeof g === 'number' ? '' : '.x'} to ≥ ${fromPx(maxW * 1.1)}`);\n if (!across || maxH > unitPx(gy)) fixes.push(`rows are ~${Math.round(maxH)}px tall against a ${Math.round(unitPx(gy))}px row pitch (gap${typeof g === 'number' ? '' : '.y'} ${gy}) — raise gap${typeof g === 'number' ? '' : '.y'} to ≥ ${fromPx(maxH * 1.1)}`);\n warnings.push({\n path: `layers[${a.li}].layout.gap`,\n code: 'layout-text-overlap',\n message: `${a.label} cells overlap at ${w}×${h}: a ${layout.type}'s \\`gap\\` is the pitch between cell anchors, not the space between cells; ${fixes.join('; and ')}, or shrink the text`,\n boxes: [asFraction(a), asFraction(b)],\n });\n break;\n }\n }\n\n // Legibility, for text that declared it must be read (`role: 'read'`).\n // Everything below is opt-in: a layer without the role is never measured,\n // so the atmospheric text the examples paint at 2–3:1 stays silent.\n const readFlagged = new Set<number>();\n for (const b of textBoxes) {\n if (readFlagged.has(b.li)) continue;\n const layer = spec.layers[b.li]!;\n const s = layer.sprite;\n if ((s.kind !== 'text' && s.kind !== 'textBlock') || s.role !== 'read') continue;\n // Every box of the layer (a `list` of labels is several), worst one wins.\n const boxes = textBoxes.filter((x) => x.li === b.li);\n readFlagged.add(b.li);\n\n const ink = hexRgb(s.color ?? '#e6e8ef');\n // What the layer actually paints over `base`, at its own alpha and blend —\n // a `role: 'read'` label at low opacity, or under `lighter`/`screen`/\n // `multiply`, is not free to hide behind a source-over assumption.\n const textPlate = (base: Rgb, alpha: number): Rgb => {\n if (layer.blend === 'lighter' || layer.blend === 'screen') return additivePlate(base, ink, alpha, layer.blend);\n if (layer.blend === 'multiply') {\n return {\n r: base.r * (1 - alpha + ink.r * alpha),\n g: base.g * (1 - alpha + ink.g * alpha),\n b: base.b * (1 - alpha + ink.b * alpha),\n };\n }\n return sourceOverPlate(base, ink, alpha);\n };\n let worst: { ground: number; plate: number; plateLabel: string | null } | null = null;\n for (const box of boxes) {\n const cy = (box.y0 + box.y1) / 2;\n const cx = (box.x0 + box.x1) / 2;\n const groundRgb = backgroundRgbAt(spec, cy, h, scale, cx, w, opts.backgroundSeed ?? opts.seed, opts.t ?? COHESION_T);\n const ground = legibilityRatio(textPlate(groundRgb, box.alpha), groundRgb);\n const lit = brightestAdditivePlate(spec, allEntities, groundRgb, box, w, h);\n const plate = lit ? legibilityRatio(textPlate(lit.rgb, box.alpha), lit.rgb) : Infinity;\n if (!worst || Math.min(ground, plate) < Math.min(worst.ground, worst.plate)) {\n worst = { ground, plate, plateLabel: lit?.label ?? null };\n }\n }\n if (worst && Math.min(worst.ground, worst.plate) < READ_LEGIBILITY_FLOOR) {\n const under = worst.plateLabel\n ? ` and ${worst.plate.toFixed(1)}:1 under ${worst.plateLabel} at its brightest`\n : '';\n warnings.push({\n path: `layers[${b.li}].sprite`,\n code: 'text-legibility',\n message: `${b.label} is declared role: 'read' but its colour reads at ${worst.ground.toFixed(1)}:1 against the background at the box centre${under} — below ${READ_LEGIBILITY_FLOOR}:1; brighten the text, darken the ground under it, or declare role: 'atmosphere' if it is texture`,\n });\n }\n\n // Safe area: readable text that sits in the outer 5 % of the frame lands\n // in the bezel / overscan zone on a real display.\n const edges: string[] = [];\n const x0 = Math.min(...boxes.map((x) => x.x0));\n const x1 = Math.max(...boxes.map((x) => x.x1));\n const y0 = Math.min(...boxes.map((x) => x.y0));\n const y1 = Math.max(...boxes.map((x) => x.y1));\n if (x0 < w * READ_SAFE_AREA) edges.push('left');\n if (x1 > w * (1 - READ_SAFE_AREA)) edges.push('right');\n if (y0 < h * READ_SAFE_AREA) edges.push('top');\n if (y1 > h * (1 - READ_SAFE_AREA)) edges.push('bottom');\n if (edges.length > 0) {\n warnings.push({\n path: `layers[${b.li}]`,\n code: 'text-safe-area',\n message: `${b.label} is declared role: 'read' but its box is within ${READ_SAFE_AREA * 100}% of the ${edges.join(' and ')} edge${edges.length === 1 ? '' : 's'} at ${w}×${h} — displays crop and bezels hide that zone; move it inward`,\n boxes: [asFraction({ x0, y0, x1, y1 })],\n });\n }\n }\n\n return warnings;\n}\n\n/**\n * The brightest ground a `role: 'read'` box can find itself on: for every\n * additive layer (`lighter` / `screen`) whose entities can reach the box and\n * are big enough to sit under a glyph, the brightest per-entity plate — its\n * own colour composited at its own peak alpha (base + pulse), never a\n * different entity's alpha borrowed onto it. Reach is judged at rest: a\n * static entity is its disc at `t = 0`; an orbit is its centre ± radius;\n * every travelling motion can be anywhere. The disc's diameter is the\n * entity's largest possible rendered extent — grow breathing, a rect/bar's\n * second dimension (thickness/aspect height can exceed the primary size),\n * and the peak scale warp/emit reach over their lifecycle — so a mote that\n * balloons under a line is not dismissed as dust because it starts small.\n */\nfunction brightestAdditivePlate(\n spec: SaverSpec,\n allEntities: Entity[][],\n ground: Rgb,\n box: TextBoxAt,\n w: number,\n h: number,\n): { rgb: Rgb; label: string } | null {\n let best: { rgb: Rgb; label: string; lum: number } | null = null;\n for (let lj = 0; lj < spec.layers.length; lj++) {\n const layer = spec.layers[lj]!;\n const blend = layer.blend;\n if (blend !== 'lighter' && blend !== 'screen') continue;\n if (lj === box.li) continue;\n const entities = allEntities[lj]!;\n // Only a layer that is actually moved at draw time (its own or its\n // group's transform) may reach anywhere; opacity alone moves nothing.\n const moved = layer.transform !== undefined || groupOf(spec, layer)?.transform !== undefined;\n for (const e of entities) {\n const hex = spriteHex(layer, e);\n if (hex === null) continue;\n const growScale = (e.motion === 'warp' ? WARP_MAX_SCALE : 1) * (e.emit ? Math.max(e.emit.growFrom, e.emit.growTo) : 1);\n const maxDim = Math.max(e.size, e.size2 ?? 0) * (1 + e.growAmp) * growScale;\n if (maxDim < box.fs) continue;\n // A transformed layer is moved at draw time: treat it like a moving one (it may reach anywhere).\n if (!moved && !entityReachesBox(e, maxDim / 2, box, w, h)) continue;\n const a = layer.opacity === undefined && layer.group === undefined ? Math.min(1, e.alpha + e.pulseAmp) : Math.min(1, e.alpha + e.pulseAmp) * paintOpacity(spec, layer);\n if (a <= 0) continue;\n const plate = additivePlate(ground, hexRgb(hex), a, blend);\n const lum = relativeLuminance(plate);\n if (!best || lum > best.lum) {\n best = { rgb: plate, label: layer.key ? `\\`${layer.key}\\`` : `layers[${lj}]`, lum };\n }\n }\n }\n return best ? { rgb: best.rgb, label: best.label } : null;\n}\n\n/**\n * What an earlier layer has painted at `pt` (t = 0), composited over the\n * page colour, or null when nothing solid sits there. Conservative on\n * purpose: only static, transform-free, normal-blend, hard-edged shapes\n * count, with exact containment for circles, axis-aligned (or quarter-turned)\n * rects and unrotated polygons — so the low-contrast check can only be\n * talked out of firing by a plate that is really there.\n */\nfunction groundUnder(\n spec: SaverSpec,\n allEntities: Entity[][],\n li: number,\n hidden: boolean[] | null,\n pt: { x: number; y: number },\n w: number,\n h: number,\n): { rgb: Rgb; luma: number } | null {\n let plate: Rgb = backgroundRgb(spec);\n let covered = false;\n for (let lj = 0; lj < li; lj++) {\n if (hidden?.[lj]) continue;\n const layer = spec.layers[lj]!;\n const sp = layer.sprite;\n if (layer.motion.type !== 'static' || layer.blend !== undefined || layer.transform !== undefined || groupOf(spec, layer)?.transform !== undefined) continue;\n if ((sp.kind === 'circle' || sp.kind === 'polygon') && sp.soft) continue;\n if (sp.kind !== 'circle' && sp.kind !== 'rect' && sp.kind !== 'polygon') continue;\n const a = layer.opacity === undefined && layer.group === undefined ? 1 : paintOpacity(spec, layer);\n for (const e of allEntities[lj]!) {\n if (e.spinSpeed !== 0 || e.alpha * a <= 0) continue;\n const hex = spriteHex(layer, e);\n if (hex === null) continue;\n const c = positionAt(e, 0, w, h);\n const dx = pt.x - c.x;\n const dy = pt.y - c.y;\n let inside = false;\n if (sp.kind === 'circle') inside = Math.hypot(dx, dy) <= e.size / 2;\n else if (sp.kind === 'rect') {\n const rot = ((e.rotate ?? 0) % Math.PI + Math.PI) % Math.PI;\n const quarter = Math.abs(rot - Math.PI / 2) < 0.01;\n if (rot > 0.01 && rot < Math.PI - 0.01 && !quarter) continue;\n const hx = (quarter ? (e.size2 ?? e.size) : e.size) / 2;\n const hy = (quarter ? e.size : (e.size2 ?? e.size)) / 2;\n inside = Math.abs(dx) <= hx && Math.abs(dy) <= hy;\n } else {\n if (e.rotate) continue;\n inside = pointInPolygon(dx, dy, polygonPoints(sp, e.size / 2));\n }\n if (!inside) continue;\n plate = sourceOverPlate(plate, hexRgb(hex), Math.min(1, e.alpha * a));\n covered = true;\n }\n }\n return covered ? { rgb: plate, luma: 0.2126 * plate.r + 0.7152 * plate.g + 0.0722 * plate.b } : null;\n}\n\nfunction pointInPolygon(x: number, y: number, pts: Array<{ x: number; y: number }>): boolean {\n let inside = false;\n for (let i = 0, j = pts.length - 1; i < pts.length; j = i++) {\n const a = pts[i]!;\n const b = pts[j]!;\n if ((a.y > y) !== (b.y > y) && x < ((b.x - a.x) * (y - a.y)) / (b.y - a.y) + a.x) inside = !inside;\n }\n return inside;\n}\n\n/** Whether an entity's disc of half-extent `r` can overlap `box` (see `brightestAdditivePlate`). */\nfunction entityReachesBox(e: Entity, r: number, box: TextBoxAt, w: number, h: number): boolean {\n if (e.motion === 'static') {\n const p = positionAt(e, 0, w, h);\n return p.x + r > box.x0 && p.x - r < box.x1 && p.y + r > box.y0 && p.y - r < box.y1;\n }\n if (e.motion === 'orbit' && !e.orbitParent) {\n const span = e.orbitR + r;\n return e.orbitCx + span > box.x0 && e.orbitCx - span < box.x1 && e.orbitCy + span > box.y0 && e.orbitCy - span < box.y1;\n }\n return true;\n}\n\n/**\n * The outline / drop-shadow idiom (X416): the SAME string painted twice at the\n * same size, nudged a few px — a dark copy under the fill. That is one title,\n * not two labels colliding. \"A few px\" is judged against the glyph height, so\n * it holds at every viewport: centres within 15 % of it, sizes within 10 %.\n */\nconst OUTLINE_STACK_OFFSET = 0.15;\n\nfunction isOutlineStack(a: TextBoxAt, b: TextBoxAt): boolean {\n if (a.str !== b.str || a.str.trim() === '') return false;\n const fs = Math.min(a.fs, b.fs);\n if (fs <= 0 || Math.abs(a.fs - b.fs) > 0.1 * Math.max(a.fs, b.fs)) return false;\n const dx = (a.x0 + a.x1) / 2 - (b.x0 + b.x1) / 2;\n const dy = (a.y0 + a.y1) / 2 - (b.y0 + b.y1) / 2;\n return Math.hypot(dx, dy) <= OUTLINE_STACK_OFFSET * fs;\n}\n\ninterface TextBoxAt {\n li: number;\n label: string;\n /** The painted string — two boxes of one string offset a hair are an outline, not a clash. */\n str: string;\n /**\n * Worst case, not \"at rest\": base alpha minus its pulse trough (never the\n * `emit` envelope, whose on/off duty cycle is excluded on purpose) times a\n * textBlock's own `opacity`.\n */\n alpha: number;\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n /** Glyph height in px — what an additive layer must out-size to sit under a line. */\n fs: number;\n /** The box's size before the layer `transform` — in the units a layout `gap` is measured in. */\n rawW: number;\n rawH: number;\n}\n\ntype Box = Pick<TextBoxAt, 'x0' | 'y0' | 'x1' | 'y1' | 'fs'>;\n\n/**\n * Box of one `text` entity, mirroring the renderer: a `font` with a px size is\n * used verbatim (scaled by the same viewport/reference ratio the renderer\n * applies), otherwise the seeded per-entity size; `align`/`baseline` move the\n * anchor; `maxWidth` is a hard cap because `fillText(text, x, y, maxWidth)`\n * squeezes the glyphs to fit.\n */\nfunction textBoxAt(\n s: Extract<LayerSpec['sprite'], { kind: 'text' }>,\n e: Entity,\n p: { x: number; y: number },\n spec: SaverSpec,\n w: number,\n h: number,\n): Box {\n const m = s.font ? /(\\d{1,5}(?:\\.\\d{1,4})?|\\.\\d{1,4})px/.exec(s.font) : null;\n const fontScale = spec.units === 'px' ? 1 : Math.min(w, h) / (spec.referenceViewport ?? LIMITS.referenceViewport);\n const fh = m ? Number(m[1]) * fontScale : e.size;\n const str = s.strings[e.spriteIndex] ?? s.strings[0] ?? '';\n let fw = textWidthEm(str) * fh;\n if (s.maxWidth) fw = Math.min(fw, s.maxWidth * (spec.units === 'px' ? 1 : Math.min(w, h)));\n const align = s.align ?? 'center';\n const baseline = s.baseline ?? 'middle';\n const x0 = align === 'left' ? p.x : align === 'right' ? p.x - fw : p.x - fw / 2;\n const y0 = baseline === 'top' ? p.y : baseline === 'bottom' ? p.y - fh : p.y - fh / 2;\n return { x0, y0, x1: x0 + fw, y1: y0 + fh, fs: fh };\n}\n\n/**\n * Box of a `textBlock`, mirroring the renderer: `position` is the block's\n * top-left, lines break with `breakTextBlock`, `align` moves the painted lines\n * inside the `maxWidth` box (not the box itself).\n */\nfunction textBlockBoxAt(\n s: Extract<LayerSpec['sprite'], { kind: 'textBlock' }>,\n p: { x: number; y: number },\n w: number,\n h: number,\n): Box {\n const unit = Math.min(w, h);\n const fsPx = s.fontSize * unit;\n const lh = (s.lineHeight ?? 1.4) * fsPx;\n const maxWPx = s.maxWidth * unit;\n const lines = breakTextBlock(s.text, maxWPx / fsPx, textMetricsClassFor(s.font));\n const maxLineW = lines.reduce((mx, l) => Math.max(mx, l.widthEm), 0) * fsPx;\n const totalH = lines.length * lh;\n const align = s.align ?? 'left';\n const x0 = align === 'center' ? p.x + (maxWPx - maxLineW) / 2 : align === 'right' ? p.x + maxWPx - maxLineW : p.x;\n // Anchor moves the whole block the same way the renderer does (0,0 when absent).\n const { dx, dy } = textBlockAnchorOffset(s, maxWPx, maxLineW, totalH);\n return { x0: x0 + dx, y0: p.y + dy, x1: x0 + dx + maxLineW, y1: p.y + dy + totalH, fs: fsPx };\n}\n\n/**\n * Per layer, whether it never shows: its own `opacity`, or its group's, is\n * pinned to 0 — 0 in the base scene and every `timeline` key on that path\n * (and no whole-object key above it) sets 0 too. A glide between zeros stays\n * at zero, so this is exact at every instant, not just at key boundaries,\n * and costs no timeline resolution. Membership is fixed per scene (not\n * steerable or keyable), so a group's pin covers its members. Null when no\n * layer uses `opacity` or `groups` (nothing can be hidden — the common case).\n */\nfunction hiddenLayers(spec: SaverSpec): boolean[] | null {\n if (!spec.groups && !spec.layers.some((l) => l.opacity !== undefined)) return null;\n const tracks = spec.timeline ? timelineTracks(spec) : null;\n const pinnedZero = (path: string, base: unknown, ancestors: string[]): boolean => {\n if (base !== 0) return false;\n if (!tracks) return true;\n for (const [p, keys] of tracks) {\n if (p === path && keys.some((k) => k.value !== 0)) return false;\n if (ancestors.includes(p)) return false; // a whole-object key could set anything\n }\n return true;\n };\n const out = spec.layers.map((l, i) => {\n const lp = `layers.${i}`;\n if (pinnedZero(`${lp}.opacity`, l.opacity, ['layers', lp])) return true;\n const g = l.group !== undefined && spec.groups && Object.prototype.hasOwnProperty.call(spec.groups, l.group) ? spec.groups[l.group] : undefined;\n return !!g && pinnedZero(`groups.${l.group}.opacity`, g.opacity, ['groups', `groups.${l.group}`]);\n });\n return out.some(Boolean) ? out : null;\n}\n\n/**\n * Non-blocking advisory warnings for a validated sequence envelope.\n * Checks cross-segment luminance jumps at boundaries and per-segment advisories.\n */\nexport function adviseSequence(\n seq: IdleSequence,\n viewport = { width: 1920, height: 1080 },\n): SpecWarning[] {\n const warnings: SpecWarning[] = [];\n\n for (let i = 0; i < seq.segments.length; i++) {\n const seg = seq.segments[i]!;\n // A timed segment changes as it plays, so its advisories describe ONE\n // stated moment of it — never a moment past its end. The default sample\n // (COHESION_T, 5 s) used to land beyond a 2 s segment and judge its\n // timeline's final frame while the request asked about another (X418).\n const timed = !!seg.scene.timeline && seg.duration !== undefined;\n const tSample = timed ? Math.min(COHESION_T, seg.duration!) : undefined;\n const segWarnings = adviseSpec(seg.scene, viewport, tSample === undefined ? {} : { t: tSample });\n const at = tSample === undefined ? '' : ` (judged ${(tSample / 1000).toFixed(1)} s into this ${(seg.duration! / 1000).toFixed(1)} s segment)`;\n for (const w of segWarnings) {\n warnings.push({ path: `segments[${i}].scene.${w.path}`, code: w.code, message: w.message + at, boxes: w.boxes });\n }\n }\n\n // Informational, once per sequence: a fade costs two live segments for\n // `dur`, which the lowest tiers cannot afford, so they play it as a cut.\n // A `fade` on the last segment only ever runs under `loop: true` (it's the\n // wrap's transition into segment 0) — without loop there is no next\n // segment for it to transition into, so it never executes and should not\n // be counted.\n const fadeBound = seq.loop ? seq.segments.length : seq.segments.length - 1;\n const fades = seq.segments.slice(0, fadeBound).filter((s) => s.transition?.type === 'fade').length;\n if (fades > 0) {\n const first = seq.segments.slice(0, fadeBound).findIndex((s) => s.transition?.type === 'fade');\n warnings.push({\n path: `segments[${first}].transition`,\n code: 'fade-degrades-on-low-tier',\n message: `informational: ${fades} fade transition${fades === 1 ? '' : 's'} declared — viewers on the 'basic' or 'minimal' capability tier render fade as cut (two live segments for dur is over that budget); the show still plays`,\n });\n }\n\n for (let i = 0; i < seq.segments.length - 1; i++) {\n const tr = seq.segments[i]!.transition;\n // The ground each side of the cut actually shows: the outgoing segment at\n // its end, the incoming at its start (a timeline may end on a different\n // colour than it began; without one these are the scenes themselves).\n // A declared `fade` is the documented remedy — the jump is ramped over\n // `dur`, not cut — so it is not raised there (low tiers that play the\n // fade as a cut are covered by `fade-degrades-on-low-tier`).\n const lumaA = backgroundLuma(resolveTimelineAt(seq.segments[i]!.scene, seq.segments[i]!.duration ?? 0));\n const lumaB = backgroundLuma(resolveTimelineAt(seq.segments[i + 1]!.scene, 0));\n const delta = Math.abs(lumaA - lumaB);\n if (delta > 0.5 && tr?.type !== 'fade') {\n warnings.push({\n path: `segments[${i}]`,\n code: 'boundary-luminance-jump',\n message: `background luminance jumps ${delta.toFixed(2)} at boundary ${i}→${i + 1} — may flash on cut; declare transition: { type: 'fade', dur } on segments[${i}] to ramp it`,\n });\n }\n\n if (tr?.type === 'morph') {\n const sigA = structuralSignature(seq.segments[i]!.scene);\n const sigB = structuralSignature(seq.segments[i + 1]!.scene);\n if (sigA !== sigB) {\n warnings.push({\n path: `segments[${i}].transition`,\n code: 'morph-structural-mismatch',\n message: `segments ${i}→${i + 1} differ structurally: morph will fall back to cut`,\n });\n } else if (!seq.segments[i]!.scene.timeline && !seq.segments[i + 1]!.scene.timeline\n && morphNothingMorphable(seq.segments[i]!.scene, seq.segments[i + 1]!.scene, { textCrossfade: tr.text === 'crossfade' || tr.text === 'dip' })) {\n warnings.push({\n path: `segments[${i}].transition`,\n code: 'morph-nothing-morphable',\n message: `segments ${i}→${i + 1} differ only in values morph cannot interpolate (strings such as textBlock.text step on the first frame): the morph will look like a cut — fade text via colour or reveal.progress`,\n });\n }\n }\n }\n\n return warnings;\n}\n","/**\n * Shared luminance helpers.\n *\n * These live in their own module because both `perceive` (which ranks layers by\n * visual weight) and `advise` (which warns about layers that can't be seen)\n * need the same notion of \"how bright is this thing\" — and `perceive` already\n * imports `advise`, so the dependency can only run one way.\n */\n\nimport type { Entity } from './simulate';\nimport { isPathPolygon, isShapedSprite, pathParts, polygonArea } from './shapes';\nimport { fieldRgb, fieldRgbAt, fieldSampleTime, hexToRgb255, rgb255Luma } from './field';\nimport type { FieldBackground, LayerSpec, SaverSpec } from './types';\n\n/**\n * The distinct 0..255 RGB colours a field background actually paints: one\n * per quantize level, not the raw `bands` declarations — `quantize` short of\n * `bands.length` never lands on every band (a `quantize: 2` field only ever\n * paints its two end levels, however many bands are declared). `quantize: 0`\n * (smooth) interpolates continuously through every band, so declaration\n * averaging is representative there.\n */\nfunction fieldRenderedRgbs(bg: FieldBackground): Array<readonly [number, number, number]> {\n const n = bg.bands.length;\n const q = Math.round(bg.quantize ?? n);\n if (q < 2) return bg.bands.map((hex) => hexToRgb255(hex));\n const out: Array<readonly [number, number, number]> = [];\n for (let level = 0; level < q; level++) out.push(fieldRgb((level + 0.5) / q, bg.bands, q));\n return out;\n}\n\n/** Perceptual luma (0..1) of a hex colour. */\nexport function hexLuma(hex: string): number {\n const h = hex.length === 4 ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex;\n const n = parseInt(h.slice(1), 16);\n if (Number.isNaN(n)) return 0.7;\n const r = ((n >> 16) & 255) / 255;\n const g = ((n >> 8) & 255) / 255;\n const b = (n & 255) / 255;\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\nexport function spriteLuma(layer: LayerSpec, e: Entity): number {\n const s = layer.sprite;\n if (s.kind === 'polygon' && isPathPolygon(s)) {\n // A path drawing reads as its parts' paint, weighted by each part's\n // area: a gradient by its mean stop (opacity-weighted toward the part's\n // colour), a stroke-only part by its stroke.\n const base = s.colors?.[e.colorIndex] ?? s.color;\n let sum = 0, wsum = 0;\n for (const part of pathParts(s)) {\n const pc = hexLuma(part.color ?? base);\n let l: number;\n if (!part.fill) l = part.stroke ? hexLuma(part.stroke.color) : pc;\n else if (part.gradient) {\n let g = 0;\n for (const st of part.gradient.stops) { const o = st.opacity ?? 1; g += hexLuma(st.color) * o + pc * (1 - o); }\n l = g / part.gradient.stops.length;\n } else l = pc;\n const w = Math.max(1e-4, part.fill ? polygonArea(part.flat.points.map(([x, y]) => ({ x, y }))) : part.box.hw * part.box.hh * 0.1) * part.opacity;\n sum += l * w; wsum += w;\n }\n if (wsum > 0) return sum / wsum;\n }\n if (isShapedSprite(s)) {\n return hexLuma(s.colors?.[e.colorIndex] ?? s.color);\n }\n if (s.kind === 'text' || s.kind === 'textBlock') return hexLuma(s.color ?? '#e6e8ef');\n return 0.75; // emoji: mid-bright approximation\n}\n\n/** The hex a given entity actually paints with, or null for glyph sprites. */\nexport function spriteHex(layer: LayerSpec, e: Entity): string | null {\n const s = layer.sprite;\n if (isShapedSprite(s)) {\n return s.colors?.[e.colorIndex] ?? s.color;\n }\n if (s.kind === 'text' || s.kind === 'textBlock') return s.color ?? '#e6e8ef';\n return null; // emoji carry their own palette\n}\n\n/**\n * Mean luma of the background plate a layer is drawn against. A gradient\n * averages its stops; a field averages the colours it actually renders\n * (`fieldRenderedRgbs` — one per quantize level, not every declared band).\n */\nexport function backgroundLuma(spec: SaverSpec): number {\n const bg = spec.background;\n if (!bg || bg.type === 'solid') return hexLuma(bg?.color ?? '#05050a');\n if (bg.type === 'field') {\n const rgbs = fieldRenderedRgbs(bg);\n return rgbs.reduce((s, c) => s + rgb255Luma(c), 0) / rgbs.length;\n }\n return bg.stops.reduce((s, st) => s + hexLuma(st.color), 0) / bg.stops.length;\n}\n\n/** Unpack a hex colour to 0..1 RGB. */\nexport function hexRgb(hex: string): { r: number; g: number; b: number } {\n const h = hex.length === 4 ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex;\n const n = parseInt(h.slice(1), 16);\n if (Number.isNaN(n)) return { r: 0.7, g: 0.7, b: 0.7 };\n return { r: ((n >> 16) & 255) / 255, g: ((n >> 8) & 255) / 255, b: (n & 255) / 255 };\n}\n\n/** Mean RGB of the background plate — a field averages the colours it\n * actually renders (`fieldRenderedRgbs`), like `backgroundLuma`. */\nexport function backgroundRgb(spec: SaverSpec): { r: number; g: number; b: number } {\n const bg = spec.background;\n if (!bg || bg.type === 'solid') return hexRgb(bg?.color ?? '#05050a');\n if (bg.type === 'field') {\n const rgbs = fieldRenderedRgbs(bg);\n const acc = rgbs.reduce((s, c) => ({ r: s.r + c[0], g: s.g + c[1], b: s.b + c[2] }), { r: 0, g: 0, b: 0 });\n return { r: acc.r / rgbs.length / 255, g: acc.g / rgbs.length / 255, b: acc.b / rgbs.length / 255 };\n }\n const colours = bg.stops.map((st) => st.color);\n const acc = colours.reduce(\n (s, hex) => {\n const c = hexRgb(hex);\n return { r: s.r + c.r, g: s.g + c.g, b: s.b + c.b };\n },\n { r: 0, g: 0, b: 0 },\n );\n const n = colours.length || 1;\n return { r: acc.r / n, g: acc.g / n, b: acc.b / n };\n}\n\n/**\n * How far a layer's colour separates from its background, ignoring alpha and\n * geometry — purely \"can this be told apart from the plate behind it\".\n *\n * **This is a colour distance, not a luminance one, and that distinction is\n * load-bearing.** Equal-luminance/contrasting-hue is a real technique, not a\n * mistake: a Seurat-style field of golden `#e8c060` dots over a pale grey-blue\n * plate differs by 0.013 in luma and is perfectly visible, because the\n * separation lives entirely in hue. A luma-only test flags exactly the\n * pointillist screens it should leave alone.\n *\n * Additive blends are a different question again. Under `lighter`/`screen` the\n * sprite ADDS light, so a colour matching the background is still visible (it\n * doubles it); what makes such a layer vanish is having little light to add —\n * which genuinely is a luminance question.\n *\n * Alpha and radius are deliberately excluded — `invisible-layer` already owns\n * that axis, and the schema actively recommends faint atmospheric layers\n * (\"80 tiny soft circles at alpha 0.2\"), which must not be flagged here.\n */\nexport function colourSeparation(\n layer: LayerSpec,\n sprite: { rgb: { r: number; g: number; b: number }; luma: number },\n bg: { rgb: { r: number; g: number; b: number }; luma: number },\n): number {\n if (layer.blend === 'lighter' || layer.blend === 'screen') return sprite.luma;\n const dr = sprite.rgb.r - bg.rgb.r;\n const dg = sprite.rgb.g - bg.rgb.g;\n const db = sprite.rgb.b - bg.rgb.b;\n // Euclidean in RGB, normalised so 1 = black-to-white. Crude next to CIEDE2000\n // but it separates hue from value, which is the whole point here.\n return Math.sqrt((dr * dr + dg * dg + db * db) / 3);\n}\n\n// ---------------------------------------------------------------------------\n// Legibility — WCAG 2.x relative luminance and the ratio between two colours.\n// Used only by layers that declare `role: 'read'`; `hexLuma` above stays the\n// perceptual (gamma-space) weight the perception grid is built on.\n// ---------------------------------------------------------------------------\n\nexport type Rgb = { r: number; g: number; b: number };\n\n/** sRGB channel (0..1) → linear light, per WCAG 2.x. */\nfunction srgbToLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n}\n\n/** WCAG relative luminance (0..1, linear light) of a 0..1 RGB triple. */\nexport function relativeLuminance(rgb: Rgb): number {\n return 0.2126 * srgbToLinear(rgb.r) + 0.7152 * srgbToLinear(rgb.g) + 0.0722 * srgbToLinear(rgb.b);\n}\n\n/**\n * WCAG legibility ratio (1..21) between two colours, order-free:\n * `(L_lighter + 0.05) / (L_darker + 0.05)`. 4.5 is the AA floor for body\n * text; 3 for large text.\n */\nexport function legibilityRatio(a: Rgb, b: Rgb): number {\n const la = relativeLuminance(a);\n const lb = relativeLuminance(b);\n const hi = Math.max(la, lb);\n const lo = Math.min(la, lb);\n return (hi + 0.05) / (lo + 0.05);\n}\n\n/**\n * The background colour under one point, `yPx` down a `h`-tall viewport:\n * a solid is itself; a gradient is its stops interpolated in sRGB at their\n * rest positions (`drift` moves them ±`amount` over time — the rest position\n * is the mean); a `band` wins where the point falls inside it. `unit` is the\n * spec's dimensional unit (1 for `px`, `min(w,h)` otherwise), for the band.\n * A field is sampled at the point at scene time `t` (bucketed like the\n * renderer and `luminanceGrid`, default 0 — a drifting field's rest) when\n * `xPx`/`w` are given, else it reads as its mean band, like the gradient.\n * `seed` is the effective seed the caller is perceiving with (`opts.seed ??\n * spec.seed`) — pass it through rather than defaulting to `spec.seed` here,\n * or a caller perceiving a specific seed samples the wrong field.\n */\nexport function backgroundRgbAt(spec: SaverSpec, yPx: number, h: number, unit: number, xPx?: number, w?: number, seed?: number, t = 0): Rgb {\n const bg = spec.background;\n if (!bg || bg.type === 'solid') return hexRgb(bg?.color ?? '#05050a');\n if (bg.type === 'field') {\n if (xPx === undefined || w === undefined) return backgroundRgb(spec);\n const short = Math.max(1, Math.min(w, h));\n const ft = fieldSampleTime(bg, t);\n const c = fieldRgbAt(xPx / short, yPx / short, ft, bg, seed ?? spec.seed ?? 42);\n return { r: c[0] / 255, g: c[1] / 255, b: c[2] / 255 };\n }\n if (bg.band) {\n const bh = bg.band.height * unit;\n if (yPx >= h - bh) return hexRgb(bg.band.color);\n }\n const stops = [...bg.stops].sort((a, b) => a.at - b.at);\n const y = h > 0 ? Math.max(0, Math.min(1, yPx / h)) : 0;\n const first = stops[0]!;\n const last = stops[stops.length - 1]!;\n if (y <= first.at) return hexRgb(first.color);\n if (y >= last.at) return hexRgb(last.color);\n for (let i = 1; i < stops.length; i++) {\n const a = stops[i - 1]!;\n const b = stops[i]!;\n if (y > b.at) continue;\n const span = b.at - a.at;\n const k = span > 0 ? (y - a.at) / span : 1;\n const ca = hexRgb(a.color);\n const cb = hexRgb(b.color);\n return { r: ca.r + (cb.r - ca.r) * k, g: ca.g + (cb.g - ca.g) * k, b: ca.b + (cb.b - ca.b) * k };\n }\n return hexRgb(last.color);\n}\n\n/**\n * Standard alpha (source-over) composite of `colour` at `alpha` over `ground` —\n * what a translucent or faint layer actually paints, rather than its\n * configured colour at full strength. Used so a `role: 'read'` text at low\n * alpha (or a `textBlock` with `opacity < 1`) is measured for what it really\n * puts on screen, not the undiluted ink colour.\n */\nexport function sourceOverPlate(ground: Rgb, colour: Rgb, alpha: number): Rgb {\n return {\n r: ground.r + (colour.r - ground.r) * alpha,\n g: ground.g + (colour.g - ground.g) * alpha,\n b: ground.b + (colour.b - ground.b) * alpha,\n };\n}\n\n/**\n * The plate an additive layer leaves behind it at full strength: `colour ×\n * alpha` added to the ground (`lighter`), or screened onto it (`screen`).\n * Per channel, clamped to 1 — the same arithmetic the canvas applies, minus\n * the soft falloff (the centre of a soft disc is at full strength).\n */\nexport function additivePlate(ground: Rgb, colour: Rgb, alpha: number, blend: 'lighter' | 'screen'): Rgb {\n const mix = (g: number, c: number): number => {\n const v = c * alpha;\n return blend === 'lighter' ? Math.min(1, g + v) : 1 - (1 - g) * (1 - v);\n };\n return { r: mix(ground.r, colour.r), g: mix(ground.g, colour.g), b: mix(ground.b, colour.b) };\n}\n","/**\n * Layer cohesion — does a layer read as ONE form, or as N separate marks?\n *\n * The gap this closes: every other perception channel reports a heavily\n * overlapping layer identically whether its sprites merge into a silhouette or\n * stay legible as individual discs. Luminance, coverage, dominance and the\n * braille map are all blind to it, because they measure ink, not edges. An\n * agent drawing a *shape* out of sprites therefore cannot tell success from\n * failure without publishing and looking at real pixels.\n *\n * Two independent facts decide it, so both are reported:\n *\n * - `overlap` — geometry. What fraction of a typical entity's outline is buried\n * inside a sibling. Scattered fields sit near 0; a deliberate mass sits high.\n * - `seamless` — paint. Whether an overlap between two of this layer's entities\n * paints as an invisible join. Only a hard-edged, fully opaque, single-colour,\n * un-blended layer merges; anything else shows every internal edge.\n *\n * Both are analytic, deterministic and renderer-free, like the rest of\n * `perceive.ts`.\n */\n\nimport { polygonArea, polygonPoints } from './shapes';\nimport { lifeAlphaAt, positionAt, rotationAt, sizeAt, type Entity } from './simulate';\nimport type { LayerSpec } from './types';\n\n/**\n * Above this mean covered-outline fraction a layer is treated as *trying* to be\n * one form rather than a field of marks.\n *\n * Calibrated against the shipped examples rather than picked. Measured across\n * all 42 fillable layers in `src/examples/`, the particle fields top out at\n * 0.154 (`facets/planes`; snowfall, lanterns and constellation are all 0.000,\n * `comets/stars` 0.001, `aquarium` 0.015, `procession/lanterns` 0.087), while\n * a layer authored as a silhouette — circles packed several times over their\n * own area, the idiom that draws a wave or a mountain — measures 0.79 to 0.85.\n * `aurora`'s wander curtains are the one shipped layer in the upper band, at\n * 0.892, and they are a deliberate overlapping wash. Nothing sits between\n * 0.154 and 0.786, so the exact threshold is not delicate.\n */\nconst MERGE_FLOOR = 0.35;\n\n/**\n * Below this base opacity a heavily overlapping layer is an atmospheric wash by\n * intent — the playbook's own advice is a field of soft circles at alpha ~0.2 —\n * and its visible internal edges are the effect, not a defect. The advisory\n * stays silent there; the numbers are still reported.\n */\nconst WASH_ALPHA_MAX = 0.45;\n\n/**\n * Sample time for a spec-level cohesion read, matching `perceiveScene`'s own\n * default so the advisory and the reported numbers agree on the usual call.\n * Past all typical `life.enter` staging; `grow` has had time to breathe.\n */\nexport const COHESION_T = 5000;\n\n/** Outline samples per entity. 24 resolves a half-covered circle to ~4 %. */\nconst OUTLINE_SAMPLES = 24;\n\n/**\n * Cap on the entities whose outlines are traced. Above this the measured set is\n * a deterministic stride through the layer (every k-th entity); coverage is\n * still tested against *every* sibling, so the estimate stays unbiased.\n */\nconst MAX_TRACED = 240;\n\n/** What a layer will read as on the wall. */\nexport type CohesionRead =\n /** Entities merge into a single silhouette — the layer draws a shape. */\n | 'mass'\n /** Entities overlap heavily but every overlap paints a visible edge. */\n | 'seamed'\n /** Entities stand alone — a field of marks, which most layers are. */\n | 'marks';\n\nexport interface LayerCohesion {\n layerIndex: number;\n key: string | undefined;\n /**\n * Mean fraction of an entity's outline covered by a same-layer sibling, 0..1.\n * `null` for sprite kinds where a merged silhouette is not a meaningful idea\n * (lines, glyphs and text: ring, streak, stroke, bar, emoji, text, textBlock).\n */\n overlap: number | null;\n /** Do this layer's overlaps paint as invisible joins? */\n seamless: boolean;\n /** Why not, when not — the field to act on. `null` when seamless. */\n seamCause: string | null;\n /** The verdict. `null` when `overlap` is null. */\n reads: CohesionRead | null;\n}\n\n// ---------------------------------------------------------------------------\n// Geometry\n// ---------------------------------------------------------------------------\n\ninterface Shape {\n cx: number;\n cy: number;\n /** Bounding radius, for the pairwise prefilter. */\n br: number;\n /** Enclosed area in px². Zero means the sprite paints nothing — collinear\n * polygon vertices reach here with a nonzero bounding radius. */\n area: number;\n contains(x: number, y: number): boolean;\n outline(n: number): Array<{ x: number; y: number }>;\n}\n\n/**\n * Outline samples are stepped this far INSIDE their own shape, as a fraction of\n * its bounding radius, before being tested. The question asked is then \"is the\n * ink just inside my edge also covered?\" rather than \"is a point exactly on my\n * edge inside a sibling?\".\n *\n * Exact-boundary tests are degenerate in both directions: coincident circles\n * sample every point exactly on the sibling's rim, and a polygon point lying on\n * a horizontal edge fails the ray-cast's `(a.y > y) !== (b.y > y)` test — two\n * flat rects sharing a y therefore reported their buried long edges as exposed.\n *\n * The step follows the edge's inward NORMAL, not the direction of the entity\n * centre: a concave polygon can have its centre outside its own filled area, so\n * a centre-directed nudge would push samples across the concavity and out of\n * the shape. Relative, so it holds at any viewport scale, and four orders of\n * magnitude below a pixel for any real sprite.\n */\nconst EDGE_INSET = 1e-4;\n\nfunction circleShape(cx: number, cy: number, r: number): Shape {\n return {\n cx, cy, br: r, area: Math.PI * r * r,\n contains: (x, y) => (x - cx) * (x - cx) + (y - cy) * (y - cy) < r * r,\n outline: (n) => Array.from({ length: n }, (_, i) => {\n const a = (i / n) * Math.PI * 2;\n const inner = r * (1 - EDGE_INSET); // inward normal of a circle is its radius\n return { x: cx + inner * Math.cos(a), y: cy + inner * Math.sin(a) };\n }),\n };\n}\n\n/** A convex or concave polygon given by absolute vertices. */\nfunction polyShape(cx: number, cy: number, raw: Array<{ x: number; y: number }>): Shape | null {\n // Drop consecutive coincident vertices up front. A zero-length edge has no\n // normal to step along, and leaving one in would emit a sample sitting\n // exactly on the boundary — the degeneracy EDGE_INSET exists to avoid.\n const abs = raw.filter((p, i) => {\n const q = raw[(i + 1) % raw.length]!;\n return Math.hypot(q.x - p.x, q.y - p.y) > 0;\n });\n // Fewer than three distinct vertices encloses no area — the renderer fills\n // nothing, so there is no silhouette to ask about.\n if (abs.length < 3) return null;\n\n let br = 0;\n for (const p of abs) br = Math.max(br, Math.hypot(p.x - cx, p.y - cy));\n const inside = (x: number, y: number): boolean => {\n let hit = false;\n for (let i = 0, j = abs.length - 1; i < abs.length; j = i++) {\n const a = abs[i]!;\n const b = abs[j]!;\n if ((a.y > y) !== (b.y > y) && x < ((b.x - a.x) * (y - a.y)) / (b.y - a.y) + a.x) hit = !hit;\n }\n return hit;\n };\n const seg = abs.map((p, i) => {\n const q = abs[(i + 1) % abs.length]!;\n return Math.hypot(q.x - p.x, q.y - p.y);\n });\n const perimeter = seg.reduce((a, b) => a + b, 0);\n // A shape thinner than the nominal inset would have BOTH normal candidates\n // overshoot it, so the step is bounded by the shortest edge as well as by\n // the bounding radius.\n const shortest = Math.min(...seg);\n const step = Math.min(br * EDGE_INSET, shortest * 0.25);\n const area = polygonArea(abs);\n if (!(area > 0)) return null; // collinear vertices enclose nothing\n return {\n cx, cy, br, area,\n contains: inside,\n /**\n * `n` points spread along the perimeter by ARC LENGTH, not one share per\n * edge — a long skinny rectangle has two edges carrying almost all of its\n * perimeter, and an equal-per-edge split would report a fully buried long\n * side as only a quarter covered. Each point is then stepped along its\n * edge's inward normal, whichever of the two candidates lands inside.\n */\n outline: (n) => {\n if (!(perimeter > 0)) return [];\n const out: Array<{ x: number; y: number }> = [];\n for (let i = 0; i < n; i++) {\n let d = (i / n) * perimeter;\n let k = 0;\n while (k < seg.length - 1 && d > seg[k]!) { d -= seg[k]!; k++; }\n const a = abs[k]!;\n const b = abs[(k + 1) % abs.length]!;\n const len = seg[k]!;\n const f = d / len;\n const px = a.x + (b.x - a.x) * f;\n const py = a.y + (b.y - a.y) * f;\n const ux = (b.x - a.x) / len;\n const uy = (b.y - a.y) / len;\n // Back off until a candidate lands inside: a sliver thinner than even\n // the bounded step still gets the best sample available rather than\n // one outside its own shape.\n // A sample that cannot be placed strictly inside is DROPPED rather than\n // emitted on the boundary: an exact-edge point is the degeneracy the\n // inset exists to remove, and reporting it as exposed would be a guess.\n // The caller measures the samples it got, so an unmeasurable sliver\n // reports no outline instead of a wrong one.\n for (let t = step; t > 0; t /= 8) {\n const qx1 = px - uy * t;\n const qy1 = py + ux * t;\n if (inside(qx1, qy1)) { out.push({ x: qx1, y: qy1 }); break; }\n const qx2 = px + uy * t;\n const qy2 = py - ux * t;\n if (inside(qx2, qy2)) { out.push({ x: qx2, y: qy2 }); break; }\n if (t < step * 1e-3) break;\n }\n }\n return out;\n },\n };\n}\n\nfunction rectShape(cx: number, cy: number, halfW: number, halfH: number, rot: number): Shape | null {\n const cos = Math.cos(rot);\n const sin = Math.sin(rot);\n const corner = (lx: number, ly: number) => ({ x: cx + lx * cos - ly * sin, y: cy + lx * sin + ly * cos });\n return polyShape(cx, cy, [\n corner(-halfW, -halfH), corner(halfW, -halfH), corner(halfW, halfH), corner(-halfW, halfH),\n ]);\n}\n\nfunction polygonShape(cx: number, cy: number, pts: Array<{ x: number; y: number }>, rot: number): Shape | null {\n const cos = Math.cos(rot);\n const sin = Math.sin(rot);\n return polyShape(cx, cy, pts.map((p) => ({ x: cx + p.x * cos - p.y * sin, y: cy + p.x * sin + p.y * cos })));\n}\n\n/** The shape an entity paints at `t`, or null for kinds with no fillable area. */\nfunction shapeOf(layer: LayerSpec, e: Entity, t: number, w: number, h: number): Shape | null {\n const s = layer.sprite;\n if (s.kind !== 'circle' && s.kind !== 'rect' && s.kind !== 'polygon') return null;\n const p = positionAt(e, t, w, h);\n const sz = sizeAt(e, t);\n if (!(sz > 0)) return null;\n if (s.kind === 'circle') return circleShape(p.x, p.y, sz / 2);\n const rot = rotationAt(e, t);\n if (s.kind === 'rect') {\n const h2 = e.size2 !== undefined ? e.size2 * (e.size > 0 ? sz / e.size : 1) : sz;\n return rectShape(p.x, p.y, sz / 2, h2 / 2, rot);\n }\n return polygonShape(p.x, p.y, polygonPoints(s, sz / 2), rot);\n}\n\n// ---------------------------------------------------------------------------\n// Paint: will an overlap show?\n// ---------------------------------------------------------------------------\n\n/**\n * Why this layer's overlaps paint a visible edge, or null when they vanish.\n *\n * Opacity is judged over the whole timeline, not this instant: a layer that\n * breathes with `pulse` is translucent at some point in every cycle, so its\n * seams appear even if the sampled frame happens to catch it at full alpha.\n */\nexport function seamCauseOf(layer: LayerSpec): string | null {\n const s = layer.sprite;\n if ((s.kind === 'circle' || s.kind === 'polygon') && s.soft) {\n return 'sprite.soft — radial falloff never forms a hard union';\n }\n if (s.kind === 'rect' && s.feather) {\n return 'rect.feather — a feathered edge never forms a hard union';\n }\n if (layer.blend) {\n return `blend: ${layer.blend} — overlaps composite instead of covering`;\n }\n const [lo, hi] = layer.alpha ?? [1, 1];\n if (lo < 1 || hi < 1) {\n return `alpha ${lo === hi ? lo : `${lo}..${hi}`} — every overlap paints a darker patch`;\n }\n if (layer.pulse && layer.pulse.amp > 0) {\n return 'pulse — the layer is translucent for part of every cycle';\n }\n // Only palette entries the seeded pick can actually reach count: a\n // `colorWeights` entry of 0 means that colour is never drawn, so it cannot\n // put a seam between two neighbours.\n const palette = 'colors' in s && Array.isArray(s.colors) ? s.colors : null;\n const weights = 'colorWeights' in s && Array.isArray(s.colorWeights) ? s.colorWeights : null;\n if (palette) {\n const aligned = weights !== null && weights.length === palette.length;\n const reachable = new Set(palette.filter((_, i) => !aligned || (weights![i] ?? 0) > 0));\n if (reachable.size > 1) {\n return `sprite.colors has ${reachable.size} reachable colours — neighbours of unlike colour show their join`;\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Public\n// ---------------------------------------------------------------------------\n\n/**\n * Per-layer cohesion for an already-built scene. Takes entities rather than a\n * spec so `perceiveScene` and `adviseSpec` can each pass the scene they already\n * built instead of building a third one.\n */\nexport function cohesionOf(\n layers: Array<{ layer: LayerSpec; entities: Entity[] }>,\n t: number,\n w: number,\n h: number,\n): LayerCohesion[] {\n return layers.map(({ layer, entities }, layerIndex) => {\n const seamCause = seamCauseOf(layer);\n const base: Omit<LayerCohesion, 'overlap' | 'reads'> = {\n layerIndex,\n key: layer.key,\n seamless: seamCause === null,\n seamCause,\n };\n\n // A layer staged out by `life` paints nothing at this instant, so asking\n // what it reads as has no answer — same as an unsupported sprite kind.\n if (lifeAlphaAt(layer.life, t) <= 0) return { ...base, overlap: null, reads: null };\n\n const shapes: Array<Shape | null> = entities.map((e) => shapeOf(layer, e, t, w, h));\n // A sprite that fills nothing is not a sibling: it cannot cover a\n // neighbour's outline and it must not make a lone sprite look like a pair.\n const solid = shapes.filter((x): x is Shape => x !== null && x.area > 0);\n // A single entity has no sibling to merge with, and unsupported kinds have\n // no fillable outline — in both cases the question does not apply.\n if (solid.length < 2) return { ...base, overlap: null, reads: null };\n\n const stride = Math.max(1, Math.ceil(solid.length / MAX_TRACED));\n let covered = 0;\n let traced = 0;\n for (let i = 0; i < solid.length; i += stride) {\n const self = solid[i]!;\n const pts = self.outline(OUTLINE_SAMPLES);\n if (pts.length === 0) continue; // no measurable outline; not 'exposed'\n let hit = 0;\n for (const p of pts) {\n for (let j = 0; j < solid.length; j++) {\n if (j === i) continue;\n const other = solid[j]!;\n const dx = p.x - other.cx;\n const dy = p.y - other.cy;\n if (dx * dx + dy * dy > other.br * other.br) continue; // cheap reject\n if (other.contains(p.x, p.y)) { hit++; break; }\n }\n }\n covered += hit / pts.length;\n traced++;\n }\n\n if (traced === 0) return { ...base, overlap: null, reads: null };\n const overlap = Number((covered / traced).toFixed(4));\n const reads: CohesionRead = overlap < MERGE_FLOOR ? 'marks' : seamCause === null ? 'mass' : 'seamed';\n return { ...base, overlap, reads };\n });\n}\n\n/**\n * True when a `seamed` layer is worth warning about: dense enough to be\n * deliberate, and opaque enough that it cannot be an atmospheric wash. Keeps\n * the advisory off the soft low-alpha glow fields the playbook recommends.\n */\nexport function seamsWorthWarning(layer: LayerSpec, c: LayerCohesion, entityCount: number): boolean {\n if (c.reads !== 'seamed' || entityCount < 6) return false;\n const [lo, hi] = layer.alpha ?? [1, 1];\n if ((lo + hi) / 2 < WASH_ALPHA_MAX) return false;\n return layer.blend !== 'lighter' && layer.blend !== 'screen';\n}\n","/**\n * Perception tools for non-vision agents. Everything here is computed\n * ANALYTICALLY from the spec — positions, sizes, and alphas are pure functions\n * of (seed, t), so no canvas or renderer is involved: these run in Node, are\n * fully deterministic, and are cheap enough to call in an authoring loop.\n *\n * The design premise: a text model doesn't need mimicked eyes, it needs vision\n * translated into modalities it is already strong in —\n * - a compact PICTURE it can actually read (braille luminance map: each Unicode\n * braille char encodes a 2×4 dot cell, ~8× ASCII resolution per token),\n * - 1D structure (row/column luminance profiles — the skeleton of a composition),\n * - OBJECT-level ranking (dominance: where does the eye go),\n * - RELATIVE judgement (diffScenes: \"is B better than A\" beats \"is A good\"),\n * - MOTION as numbers (per-layer displacement stats).\n */\nimport { createRng } from '@idle-screens/core';\nimport { adviseSpec } from './advise';\nimport { cohesionOf, type LayerCohesion } from './cohesion';\nimport { backgroundLuma, backgroundRgb, hexLuma, hexRgb, spriteHex, spriteLuma } from './luma';\nimport { fieldRgbAt, fieldSampleTime, rgb255Luma } from './field';\nimport { barBox, barFraction, flattenSprite, gradientSpace, isPathPolygon, pathFrame, isShapedSprite, pathLength, pathParts, polygonArea, type ResolvedPart, polygonFill, polygonFillRule, polygonPoints, strokeSamples, strokeTaper, strokeWidthPx, type PolygonSprite } from './shapes';\nimport { trailEchoes, trailFillBudget } from './trail';\nimport {\n alphaAt,\n breakTextBlock,\n buildEntities,\n headingAt,\n lifeAlphaAt,\n linkEdges,\n linkMaxDistPx,\n positionAt,\n revealState,\n rotationAt,\n sizeAt,\n textBlockAnchorOffset,\n textMetricsClassFor,\n entityScales,\n type Entity,\n} from './simulate';\nimport { bedRenderSeed, normalizeSeed, resolveSegment, segmentRenderSeed } from './sequence';\nimport { paintMap, paintOpacity, paintSize, type Pt } from './paint';\nimport { resolveTimelineAt } from './timeline';\nimport { LIMITS, type IdleSequence, type LayerSpec, type PathGradient, type SaverSpec } from './types';\n\n// ---------------------------------------------------------------------------\n// Calibration constants\n//\n// The knob that tunes how closely this analytical model matches the real\n// canvas. Kept at module level so a calibration pass has one place to look —\n// it is not a per-entity detail. (A second, GLOW_SPREAD, modelled an additive\n// halo past a soft sprite's radius; the canvas draws none, and pixel truth\n// removed it — perception-lab S1-03b, S1-07.)\n// ---------------------------------------------------------------------------\n\n/**\n * How much more visually prominent line-like ink is than the same area of fill.\n * Rings, streaks and link lines catch the eye far more than their pixel area\n * implies, so weighting dominance by raw area alone makes a bright ring lose to\n * a dim disc. Also a first-pass estimate.\n */\nconst LINE_SALIENCE = 3.5;\n\n/**\n * How many past-frame samples model the `ghosting` smear. The live renderer\n * composites every 60 fps frame with persistence `g`, so ink from m frames ago\n * survives at weight g^m; the analytic model samples that decay at GHOST_TAPS\n * points across the visible window (until weight falls below 1/255, capped at\n * LIMITS.maxGhostReplayFrames — the same bound as the renderer's seek warm-up\n * replay), each tap carrying its bracket's summed weight. More taps sharpen the\n * smear's shape; the total energy is set by `g`, not by this constant.\n */\nconst GHOST_TAPS = 12;\n\n/**\n * A polygon whose bounding diameter spans at least this many grid cells is\n * rasterized by its real outline; below it, it splats as its circumscribed\n * disc weighted by `polygonFill`, exactly as before. The two do NOT agree at\n * the boundary: the disc path lights every cell whose centre is within half a\n * cell of the rim at full weight, so it over-reports a small glyph's ink (12\n * hexagons just under 3 cells: mean deviation 0.022 against an analytic 0.014;\n * the outline gives 0.013). Circles carry the same dilation, and keeping it\n * for small polygons keeps a hexagon and a disc of one size reading alike.\n * Above the threshold the disc is materially wrong for any non-round glyph — a\n * full-width flat band reads as a circle, a ridge silhouette as a dome.\n */\nconst POLYGON_OUTLINE_CELLS = 3;\n\n/** Sub-scanlines per grid row when rasterizing a polygon outline. */\nconst POLYGON_SCANLINES = 4;\n\n// ---------------------------------------------------------------------------\n// Shared scene construction (mirrors describeScene/adviseSpec)\n// ---------------------------------------------------------------------------\n\ninterface BuiltScene {\n w: number;\n h: number;\n scale: number;\n /** Normalized exactly like `SpecInstance.seed` (0 is falsy, so it lands on 1). */\n seed: number;\n layers: Array<{ layer: LayerSpec; entities: Entity[] }>;\n byKey: Map<string, Entity[]>;\n /** Entities of layers with a paint `transform` — null (every scene without one) skips the lookup. */\n transforms: Map<Entity, (p: Pt) => Pt> | null;\n}\n\n\nexport interface PerceiveOptions {\n viewport?: { width: number; height: number };\n seed?: number;\n /** Sample time in ms. Default 5000 (past all typical life.enter staging). */\n t?: number;\n}\n\nfunction buildScene(spec: SaverSpec, opts: PerceiveOptions): BuiltScene {\n const { width: w, height: h } = opts.viewport ?? { width: 1920, height: 1080 };\n // Normalized exactly like `SpecInstance.seed` — a valid `seed: 0` lands on 1,\n // matching the renderer, and this same normalized value is reused for field\n // background sampling (see `luminanceGrid`) so both agree on one seed.\n const seed = normalizeSeed(opts.seed ?? spec.seed ?? 42);\n const { scale, countScale } = entityScales(spec, w, h);\n const rng = createRng(seed);\n const layers = spec.layers.map((layer) => ({ layer, entities: buildEntities(layer, rng, w, h, scale, countScale) }));\n const byKey = new Map<string, Entity[]>();\n for (const { layer, entities } of layers) if (layer.key) byKey.set(layer.key, entities);\n let transforms: Map<Entity, (p: Pt) => Pt> | null = null;\n for (const { layer, entities } of layers) {\n // Layer transform (about its origin) wrapped by its group's — see paint.ts.\n const map = paintMap(spec, layer, w, h, scale);\n if (!map) continue;\n transforms ??= new Map();\n for (const e of entities) transforms.set(e, map);\n }\n return { w, h, scale, seed, layers, byKey, transforms };\n}\n\n/** Position with layer-parented-orbit resolution (matches the renderer). */\nfunction posOf(scene: BuiltScene, e: Entity, t: number): { x: number; y: number } {\n const p = positionAt(e, t, scene.w, scene.h);\n if (e.orbitParent) {\n const parent = scene.byKey.get(e.orbitParent)?.[0];\n if (parent) {\n const pp = positionAt(parent, t, scene.w, scene.h);\n p.x += pp.x;\n p.y += pp.y;\n }\n }\n const map = scene.transforms?.get(e);\n return map ? map(p) : p;\n}\n\n/**\n * Text bounding box + anchor, matching the renderer's font rule: a CSS\n * shorthand containing a px size overrides the seeded per-entity size.\n * Returns the box CENTRE (accounting for align/baseline) and half-extents.\n */\n/**\n * The renderer's font scale (compile.ts fontScale): a font's own px size is\n * authored for the reference viewport and drawn at min(w, h) / reference of it.\n */\nfunction fontScaleFor(spec: SaverSpec, w: number, h: number): number {\n return spec.units === 'px' ? 1 : Math.min(w, h) / (spec.referenceViewport ?? LIMITS.referenceViewport);\n}\n\n/** Px size a text sprite draws at: its font's px × the font scale, else the entity's size. */\nfunction textFontPx(s: Extract<LayerSpec['sprite'], { kind: 'text' }>, size: number, fontScale: number): number {\n const m = s.font ? /(\\d+(?:\\.\\d+)?)px/.exec(s.font) : null;\n return m ? Number(m[1]) * fontScale : size;\n}\n\nfunction textBox(\n s: Extract<LayerSpec['sprite'], { kind: 'text' }>,\n e: Entity,\n p: { x: number; y: number },\n fontScale: number,\n unitScale: number,\n): { cx: number; cy: number; halfX: number; halfY: number } {\n const fh = textFontPx(s, e.size, fontScale);\n const str = s.strings[e.spriteIndex] ?? s.strings[0] ?? '';\n // `maxWidth` squeezes the string to fit (fillText's maxWidth), so the box does too.\n const est = Math.max(fh, 0.62 * fh * Math.min(str.length, 48));\n const fw = s.maxWidth ? Math.min(est, s.maxWidth * unitScale) : est;\n const align = s.align ?? 'center';\n const baseline = s.baseline ?? 'middle';\n return {\n cx: align === 'left' ? p.x + fw / 2 : align === 'right' ? p.x - fw / 2 : p.x,\n cy: baseline === 'top' ? p.y + fh * 0.6 : baseline === 'bottom' ? p.y - fh * 0.6 : p.y,\n halfX: fw / 2,\n halfY: fh * 0.6,\n };\n}\n\nfunction textBlockBox(\n s: Extract<LayerSpec['sprite'], { kind: 'textBlock' }>,\n _e: Entity,\n p: { x: number; y: number },\n w: number,\n h: number,\n): { cx: number; cy: number; halfX: number; halfY: number } {\n const unitScale = Math.min(w, h);\n const fsPx = s.fontSize * unitScale;\n const lh = (s.lineHeight ?? 1.4) * fsPx;\n const maxWPx = s.maxWidth * unitScale;\n const maxWEm = maxWPx / fsPx;\n const lines = breakTextBlock(s.text, maxWEm, textMetricsClassFor(s.font));\n const totalH = lines.length * lh;\n const maxLineW = lines.reduce((m, l) => Math.max(m, l.widthEm), 0) * fsPx;\n const align = s.align ?? 'left';\n const cx = align === 'center' ? p.x + maxWPx / 2\n : align === 'right' ? p.x + maxWPx - maxLineW / 2\n : p.x + maxLineW / 2;\n // Anchor moves the whole block the same way the renderer does (0,0 when absent).\n const { dx, dy } = textBlockAnchorOffset(s, maxWPx, maxLineW, totalH);\n return {\n cx: cx + dx,\n cy: p.y + totalH / 2 + dy,\n halfX: maxLineW / 2,\n halfY: totalH / 2,\n };\n}\n\n/**\n * Effective reveal fraction of a textBlock at time t (1 = fully shown).\n * Mirrors the renderer's `revealState` exactly — same line breaking, same\n * grapheme counting — so the perceived ink matches the painted ink.\n */\nfunction textBlockRevealFraction(\n s: Extract<LayerSpec['sprite'], { kind: 'textBlock' }>,\n w: number,\n h: number,\n t: number,\n): number {\n if (!s.reveal) return 1;\n const unitScale = Math.min(w, h);\n const maxWEm = (s.maxWidth * unitScale) / (s.fontSize * unitScale);\n const lines = breakTextBlock(s.text, maxWEm, textMetricsClassFor(s.font));\n const rs = revealState(lines, s.reveal, t);\n if (rs.glyphAlphas) {\n // glyphFade paints partial-alpha glyphs, so the ink fraction is the mean\n // glyph alpha, not the frontier progress.\n let sum = 0;\n let n = 0;\n for (const line of rs.glyphAlphas) for (const a of line) { sum += a; n++; }\n return n > 0 ? sum / n : 1;\n }\n return rs.progress;\n}\n\n// ---------------------------------------------------------------------------\n// Polygon outline rasterization\n// ---------------------------------------------------------------------------\n\n/**\n * Fraction of each cell in the window [c0..c1]×[r0..r1] that a polygon fills,\n * row-major within the window. Scanline with the canvas's own `nonzero` rule:\n * each sub-scanline collects signed edge crossings (half-open in y, so a\n * horizontal edge or a vertex on the line is counted once), and the spans where\n * the winding is nonzero are split exactly across the cells they cross. So\n * coverage is exact horizontally and POLYGON_SCANLINES-sampled vertically, and\n * a self-intersecting outline fills both lobes, as `ctx.fill()` does.\n */\n/** A path gradient at unit-box point (u, v): luma and opacity of the interpolated stop. */\nfunction gradientAt(gr: PathGradient, u: number, v: number): { luma: number; opacity: number } {\n let t: number;\n if (gr.type === 'linear') {\n const dx = gr.to[0] - gr.from[0], dy = gr.to[1] - gr.from[1];\n const len2 = dx * dx + dy * dy || 1;\n t = ((u - gr.from[0]) * dx + (v - gr.from[1]) * dy) / len2;\n } else {\n t = Math.hypot(u - gr.center[0], v - gr.center[1]) / gr.radius;\n }\n const st = gr.stops;\n t = Math.max(st[0]!.at, Math.min(st[st.length - 1]!.at, t));\n let k = 0;\n while (k < st.length - 2 && t > st[k + 1]!.at) k++;\n const A = st[k]!, B = st[Math.min(k + 1, st.length - 1)]!;\n const w = B.at > A.at ? (t - A.at) / (B.at - A.at) : 0;\n return { luma: hexLuma(A.color) * (1 - w) + hexLuma(B.color) * w, opacity: (A.opacity ?? 1) * (1 - w) + (B.opacity ?? 1) * w };\n}\n\nfunction polygonCellCoverage(\n pts: Array<{ x: number; y: number }>,\n cellW: number,\n cellH: number,\n c0: number,\n c1: number,\n r0: number,\n r1: number,\n evenodd = false,\n): Float64Array {\n const nc = c1 - c0 + 1;\n const cov = new Float64Array(nc * (r1 - r0 + 1));\n const xMin = c0 * cellW;\n const xMax = (c1 + 1) * cellW;\n const share = 1 / POLYGON_SCANLINES;\n const hits: Array<{ x: number; dir: number }> = [];\n const addSpan = (row: number, xa: number, xb: number): void => {\n const a = Math.max(xMin, xa);\n const b = Math.min(xMax, xb);\n if (!(b > a)) return;\n const first = Math.max(c0, Math.floor(a / cellW));\n const last = Math.min(c1, Math.floor(b / cellW));\n for (let c = first; c <= last; c++) {\n const len = Math.min(b, (c + 1) * cellW) - Math.max(a, c * cellW);\n if (len > 0) cov[row * nc + (c - c0)]! += (len / cellW) * share;\n }\n };\n for (let r = r0; r <= r1; r++) {\n for (let k = 0; k < POLYGON_SCANLINES; k++) {\n const y = (r + (k + 0.5) / POLYGON_SCANLINES) * cellH;\n hits.length = 0;\n for (let i = 0; i < pts.length; i++) {\n const p = pts[i]!;\n const q = pts[(i + 1) % pts.length]!;\n const down = p.y <= y && q.y > y;\n if (!down && !(q.y <= y && p.y > y)) continue;\n hits.push({ x: p.x + ((y - p.y) / (q.y - p.y)) * (q.x - p.x), dir: down ? 1 : -1 });\n }\n if (hits.length < 2) continue;\n hits.sort((m, n) => m.x - n.x);\n let wind = 0;\n let start = 0;\n const filled = (w: number): boolean => (evenodd ? (w & 1) !== 0 : w !== 0);\n for (const hit of hits) {\n const before = filled(wind);\n wind += hit.dir;\n const after = filled(wind);\n if (!before && after) start = hit.x;\n else if (before && !after) addSpan(r - r0, start, hit.x);\n }\n }\n }\n return cov;\n}\n\n// ---------------------------------------------------------------------------\n// Luminance grid\n// ---------------------------------------------------------------------------\n\nexport interface LuminanceGrid {\n cols: number;\n rows: number;\n /** Row-major luminance 0..1 including the background. */\n cells: number[];\n /** Per-row background luminance (what an empty scene would be). For a `field` background: each row's mean. */\n background: number[];\n /**\n * Per-cell background luminance, present only for a `field` background\n * (a solid or gradient varies by row alone, and `background` says it all).\n * Coverage, centroid and the profiles deviate from THIS, so the field's own\n * contours never count as content — a bright field is ground, not ink.\n */\n backgroundCells?: number[];\n meanLuminance: number;\n /** Fraction of cells deviating perceptibly (> 0.03) from the background. */\n coverage: number;\n /** Deviation-weighted centre of visual mass as viewport fractions, or null for a flat scene. */\n centroid: { x: number; y: number } | null;\n /** Mean deviation-from-background per row/column — 1D transects of the composition. */\n rowProfile: number[];\n colProfile: number[];\n}\n\nexport interface LuminanceGridOptions extends PerceiveOptions {\n /** Grid resolution. Defaults 80×48 (→ a 40×12 braille map). */\n cols?: number;\n rows?: number;\n}\n\n/** The canvas's soft-sprite alpha at radius fraction u: stops 1 @ 0, 0.75 @ 0.35, 0 @ 1 (compile.ts). */\nfunction softProfile(u: number): number {\n if (u <= 0) return 1;\n if (u >= 1) return 0;\n return u <= 0.35 ? 1 - (0.25 * u) / 0.35 : 0.75 * (1 - (u - 0.35) / 0.65);\n}\n\n/** Mean of softProfile over a disc's area, ∫₀¹ softProfile(u)·2u du. */\nconst SOFT_DISC_MEAN = 0.3783;\n\n/**\n * The ink (0..1 of the cell's area) that a disc — or the annulus\n * rInner ≤ |p − (cx, cy)| ≤ rOuter — lays in the cell [x0, x0+cw) × [y0, y0+ch):\n * covered area, weighted by the soft gradient when `soft`. Exact when the cell\n * is wholly outside or inside the shape, or the shape wholly inside the cell;\n * otherwise sampled over the part of the cell the shape's box overlaps, at a\n * spacing set by the radius, so a disc smaller than a cell is never stepped\n * over (perception-lab S1-09: a field of 3 px soft dots read 6× too dark).\n */\nfunction discCellInk(cx: number, cy: number, rOuter: number, rInner: number, soft: boolean, x0: number, y0: number, cw: number, ch: number): number {\n const nx = Math.max(x0, Math.min(cx, x0 + cw)) - cx;\n const ny = Math.max(y0, Math.min(cy, y0 + ch)) - cy;\n const near = Math.hypot(nx, ny);\n const fx = Math.max(Math.abs(x0 - cx), Math.abs(x0 + cw - cx));\n const fy = Math.max(Math.abs(y0 - cy), Math.abs(y0 + ch - cy));\n const far = Math.hypot(fx, fy);\n if (near >= rOuter || far <= rInner) return 0;\n if (far <= rOuter && near >= rInner) return soft ? softProfile(Math.hypot(x0 + cw / 2 - cx, y0 + ch / 2 - cy) / rOuter) : 1;\n if (cx - rOuter >= x0 && cx + rOuter <= x0 + cw && cy - rOuter >= y0 && cy + rOuter <= y0 + ch) {\n return (Math.PI * (soft ? rOuter * rOuter * SOFT_DISC_MEAN : rOuter * rOuter - rInner * rInner)) / (cw * ch);\n }\n const bx0 = Math.max(x0, cx - rOuter);\n const by0 = Math.max(y0, cy - rOuter);\n const sx = Math.min(x0 + cw, cx + rOuter) - bx0;\n const sy = Math.min(y0 + ch, cy + rOuter) - by0;\n if (sx <= 0 || sy <= 0) return 0;\n const step = Math.max(rOuter / 4, 1e-6);\n const ni = Math.max(4, Math.min(16, Math.ceil(sx / step)));\n const nj = Math.max(4, Math.min(16, Math.ceil(sy / step)));\n let ink = 0;\n for (let j = 0; j < nj; j++) {\n for (let i = 0; i < ni; i++) {\n const d = Math.hypot(bx0 + ((i + 0.5) * sx) / ni - cx, by0 + ((j + 0.5) * sy) / nj - cy);\n if (d <= rOuter && d >= rInner) ink += soft ? softProfile(d / rOuter) : 1;\n }\n }\n return ((ink / (ni * nj)) * sx * sy) / (cw * ch);\n}\n\n/**\n * Sample the spec into a coarse luminance image — analytically, no renderer.\n * Persistence is modeled, not simulated: because positions are pure functions\n * of (seed, t), `ghosting` is a decayed sum of past-frame splats (weight g^m\n * for ink m frames old, mirroring the renderer's warm-up replay) and `trail`\n * re-uses drawTrail's sampling — past positions with decaying alpha and\n * shrinking radius. Polygons larger than POLYGON_OUTLINE_CELLS are scanned by\n * their real (rotated) outline; smaller ones splat as a fill-weighted disc.\n * Remaining approximations (documented, deliberate): background drift is\n * sampled at its rest position. Good enough to perceive composition, focus,\n * balance — and now smear.\n */\nexport function luminanceGrid(spec: SaverSpec, opts: LuminanceGridOptions = {}): LuminanceGrid {\n // A `timeline` resolves at the sample time; without one this is `spec` itself.\n spec = resolveTimelineAt(spec, opts.t ?? 5000);\n const scene = buildScene(spec, opts);\n const t = opts.t ?? 5000;\n const cols = Math.max(8, Math.min(200, opts.cols ?? 80));\n const rows = Math.max(8, Math.min(200, opts.rows ?? 48));\n const { w, h, scale } = scene;\n const cellW = w / cols;\n const cellH = h / rows;\n\n // Background: vertical gradient (or solid) + optional bottom band — or a\n // field, sampled per cell with the renderer's own function at the same\n // bucketed time, so the grid's ground IS what the raster paints.\n const bg = spec.background;\n const bgRow: number[] = new Array(rows).fill(0);\n let bgCells: number[] | undefined;\n if (!bg || bg.type === 'solid') {\n bgRow.fill(hexLuma(bg?.color ?? '#05050a'));\n } else if (bg.type === 'field') {\n bgCells = new Array<number>(cols * rows);\n const short = Math.max(1, Math.min(w, h));\n const seed = scene.seed;\n const ft = fieldSampleTime(bg, t);\n for (let r = 0; r < rows; r++) {\n let rowSum = 0;\n for (let c = 0; c < cols; c++) {\n const lum = rgb255Luma(fieldRgbAt(((c + 0.5) * cellW) / short, ((r + 0.5) * cellH) / short, ft, bg, seed));\n bgCells[r * cols + c] = lum;\n rowSum += lum;\n }\n bgRow[r] = rowSum / cols;\n }\n } else {\n const stops = [...bg.stops].sort((a, b) => a.at - b.at);\n for (let r = 0; r < rows; r++) {\n const y = (r + 0.5) / rows;\n let lum: number;\n if (y <= stops[0]!.at) lum = hexLuma(stops[0]!.color);\n else if (y >= stops[stops.length - 1]!.at) lum = hexLuma(stops[stops.length - 1]!.color);\n else {\n let i = 0;\n while (i < stops.length - 1 && stops[i + 1]!.at < y) i++;\n const a = stops[i]!;\n const b = stops[i + 1]!;\n const k = b.at === a.at ? 0 : (y - a.at) / (b.at - a.at);\n lum = hexLuma(a.color) + (hexLuma(b.color) - hexLuma(a.color)) * k;\n }\n bgRow[r] = lum;\n }\n if (bg.band) {\n const bandPx = bg.band.height * (spec.units === 'px' ? 1 : Math.min(w, h));\n const fromRow = Math.max(0, Math.floor((h - bandPx) / cellH));\n for (let r = fromRow; r < rows; r++) bgRow[r] = hexLuma(bg.band.color);\n }\n }\n\n const cells = new Array<number>(cols * rows);\n for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) cells[r * cols + c] = bgCells ? bgCells[r * cols + c]! : bgRow[r]!;\n\n const compose = (idx: number, lum: number, a: number, blend: LayerSpec['blend']): void => {\n const cur = cells[idx]!;\n if (blend === 'lighter' || blend === 'screen') cells[idx] = Math.min(1, cur + lum * a);\n else if (blend === 'multiply') cells[idx] = cur * (1 - a * (1 - lum));\n else cells[idx] = cur * (1 - a) + lum * a;\n };\n\n // Afterglow behind a moving entity — the analytic mirror of the renderer's\n // drawTrail, from the same sampler (`trailEchoes`): past positions with\n // decaying alpha and shrinking radius, gap-filled where a fast mover's\n // echoes would part, stopping at wrap seams. A large polygon echoes as its\n // own outline (as the wall paints it); everything else splats a disc.\n const splatTrail = (layer: LayerSpec, e: Entity, tPass: number, lifeA: number, alphaScale: number, layerCount: number): void => {\n const trail = layer.trail;\n if (!trail) return;\n const headAlpha = alphaAt(e, tPass) * lifeA * alphaScale;\n const headSize = sizeAt(e, tPass);\n const lum = spriteLuma(layer, e);\n const soft = layer.sprite.kind === 'circle' && !!layer.sprite.soft;\n const echoes = trailEchoes(trail, tPass, headAlpha, headSize, (pt) => posOf(scene, e, pt), w, h, layer.wrap !== false,\n // As the renderer: a shape echoes at its time samples only; circles fill\n // (a hard circle's ribbon reads, on the coarse grid, as filled discs).\n isShapedSprite(layer.sprite) && layer.sprite.kind !== 'circle' ? 0 : trailFillBudget(layerCount), 0.004, layer.blend === 'lighter');\n for (const ec of echoes) {\n const a = ec.alpha;\n const rad = ec.r;\n if (layer.sprite.kind === 'polygon' && rad * 2 >= POLYGON_OUTLINE_CELLS * Math.min(cellW, cellH)) {\n splatPolygonOutline(layer, layer.sprite, e, ec, rad * 2, Math.min(1, a), lum, ec.t);\n continue;\n }\n const pos = ec;\n const c0 = Math.max(0, Math.floor((pos.x - rad) / cellW));\n const c1 = Math.min(cols - 1, Math.floor((pos.x + rad) / cellW));\n const r0 = Math.max(0, Math.floor((pos.y - rad) / cellH));\n const r1 = Math.min(rows - 1, Math.floor((pos.y + rad) / cellH));\n for (let r = r0; r <= r1; r++) {\n for (let c = c0; c <= c1; c++) {\n let wgt = 1;\n if (soft) {\n wgt = discCellInk(pos.x, pos.y, rad, 0, true, c * cellW, r * cellH, cellW, cellH);\n if (wgt <= 0) continue;\n } else {\n const d = Math.hypot((c + 0.5) * cellW - pos.x, (r + 0.5) * cellH - pos.y);\n if (d > rad + Math.min(cellW, cellH) / 2) continue;\n }\n compose(r * cols + c, lum, Math.min(1, a * wgt), layer.blend);\n }\n }\n }\n };\n\n // A polygon painted by its real outline — the renderer's path, rotated by\n // `rotationAt` about the entity — instead of its circumscribed disc. Weight\n // per cell is the fraction of it the outline fills; `soft` is the renderer's\n // radial gradient (centred on the entity, radius = circumradius) clipped to\n // that outline, additive or not — nothing reaches past it (perception-lab S1-07).\n const splatPolygonOutline = (layer: LayerSpec, s: PolygonSprite, e: Entity, p: { x: number; y: number }, sz: number, a: number, lum: number, tPass: number): void => {\n const radius = sz / 2;\n const rot = rotationAt(e, tPass);\n const cr = Math.cos(rot);\n const sr = Math.sin(rot);\n // A path drawing lands through its frame (span stretches, origin anchors);\n // everything below maps unit-box points with `mapUnit` and back with `unitAt`.\n const fr = isPathPolygon(s) ? pathFrame(s, radius, w, h) : { sx: radius, sy: radius, ox: 0, oy: 0, uniform: true };\n const mapUnit = (u: number, v: number): { x: number; y: number } => {\n const qx = (u - fr.ox) * fr.sx, qy = (v - fr.oy) * fr.sy;\n return { x: p.x + qx * cr - qy * sr, y: p.y + qx * sr + qy * cr };\n };\n const pts = isPathPolygon(s)\n ? flattenSprite(s).points.map(([u, v]) => mapUnit(u, v))\n : polygonPoints(s, radius).map((q) => ({ x: p.x + q.x * cr - q.y * sr, y: p.y + q.x * sr + q.y * cr }));\n let minX = Infinity;\n let maxX = -Infinity;\n let minY = Infinity;\n let maxY = -Infinity;\n for (const q of pts) {\n minX = Math.min(minX, q.x); maxX = Math.max(maxX, q.x);\n minY = Math.min(minY, q.y); maxY = Math.max(maxY, q.y);\n }\n // A part's stroke as px quads along its mapped lines, half-width from the uniform radius.\n const strokeQuadsPx = (part: ResolvedPart): Array<Array<{ x: number; y: number }>> => {\n if (!part.stroke) return [];\n const hw = (part.stroke.width * radius) / 2;\n const out: Array<Array<{ x: number; y: number }>> = [];\n for (const l of part.flat.lines) {\n const m = l.points.map(([u, v]) => mapUnit(u, v));\n const n = l.closed ? m.length : m.length - 1;\n for (let i = 0; i < n; i++) {\n const A = m[i]!, B = m[(i + 1) % m.length]!;\n const dx = B.x - A.x, dy = B.y - A.y, len = Math.hypot(dx, dy) || 1;\n const nx = (-dy / len) * hw, ny = (dx / len) * hw;\n out.push([{ x: A.x + nx, y: A.y + ny }, { x: B.x + nx, y: B.y + ny }, { x: B.x - nx, y: B.y - ny }, { x: A.x - nx, y: A.y - ny }]);\n }\n }\n return out;\n };\n if (isPathPolygon(s)) {\n // Strokes reach past the fill (and are all there is with fill: false).\n for (const part of pathParts(s)) for (const quad of strokeQuadsPx(part)) for (const q of quad) {\n minX = Math.min(minX, q.x); maxX = Math.max(maxX, q.x); minY = Math.min(minY, q.y); maxY = Math.max(maxY, q.y);\n }\n }\n const c0 = Math.max(0, Math.floor(minX / cellW));\n const c1 = Math.min(cols - 1, Math.floor(maxX / cellW));\n const r0 = Math.max(0, Math.floor(minY / cellH));\n const r1 = Math.min(rows - 1, Math.floor(maxY / cellH));\n if (c0 > c1 || r0 > r1) return;\n const nc = c1 - c0 + 1;\n const unitAt = (x: number, y: number): [number, number] => {\n const dx = x - p.x, dy = y - p.y;\n return [(dx * cr + dy * sr) / Math.max(fr.sx, 1e-6) + fr.ox, (-dx * sr + dy * cr) / Math.max(fr.sy, 1e-6) + fr.oy];\n };\n // Plain polygons (sides/points) keep the single-fill path below; path\n // polygons composite part by part, back to front, as the canvas paints them.\n const parts = isPathPolygon(s) ? pathParts(s) : null;\n const fillPass = (ring: Array<{ x: number; y: number }>, rule: boolean, partLum: number, partA: number, part: ResolvedPart | null): void => {\n const cov = polygonCellCoverage(ring, cellW, cellH, c0, c1, r0, r1, rule);\n for (let r = r0; r <= r1; r++) {\n for (let c = c0; c <= c1; c++) {\n const f = cov[(r - r0) * nc + (c - c0)]!;\n if (!(f > 0)) continue;\n const x = (c + 0.5) * cellW;\n const y = (r + 0.5) * cellH;\n let cl = partLum, ca = 1;\n if (part?.gradient) {\n const [u, v] = unitAt(x, y);\n const [gu, gv] = gradientSpace(part, u, v);\n const g = gradientAt(part.gradient, gu, gv);\n cl = g.luma; ca = g.opacity;\n }\n const wgt = s.soft && !parts ? f * softProfile(Math.hypot(x - p.x, y - p.y) / Math.max(radius, 1e-6)) : f;\n if (wgt > 0) compose(r * cols + c, cl, a * partA * ca * Math.min(1, wgt), layer.blend);\n }\n }\n };\n if (!parts) {\n fillPass(pts, polygonFillRule(s) === 'evenodd', lum, 1, null);\n return;\n }\n for (const part of parts) {\n const partLum = part.color ? hexLuma(part.color) : lum;\n if (part.fill && part.flat.points.length >= 3) {\n fillPass(part.flat.points.map(([u, v]) => mapUnit(u, v)), part.rule === 'evenodd', partLum, part.opacity, part);\n }\n if (part.stroke) {\n const sa = (part.stroke.opacity ?? 1) * part.opacity;\n const sl = hexLuma(part.stroke.color);\n const scov = new Float64Array(nc * (r1 - r0 + 1));\n for (const qp of strokeQuadsPx(part)) {\n let qx0 = Infinity, qx1 = -Infinity, qy0 = Infinity, qy1 = -Infinity;\n for (const q of qp) { qx0 = Math.min(qx0, q.x); qx1 = Math.max(qx1, q.x); qy0 = Math.min(qy0, q.y); qy1 = Math.max(qy1, q.y); }\n const a0 = Math.max(c0, Math.floor(qx0 / cellW)), a1 = Math.min(c1, Math.floor(qx1 / cellW));\n const b0 = Math.max(r0, Math.floor(qy0 / cellH)), b1 = Math.min(r1, Math.floor(qy1 / cellH));\n if (a0 > a1 || b0 > b1) continue;\n const qc = polygonCellCoverage(qp, cellW, cellH, a0, a1, b0, b1);\n const qn = a1 - a0 + 1;\n for (let r = b0; r <= b1; r++) for (let c = a0; c <= a1; c++) {\n const i = (r - r0) * nc + (c - c0);\n scov[i] = Math.min(1, scov[i]! + qc[(r - b0) * qn + (c - a0)]!);\n }\n }\n for (let r = r0; r <= r1; r++) for (let c = c0; c <= c1; c++) {\n const f = scov[(r - r0) * nc + (c - c0)]!;\n if (f > 0) compose(r * cols + c, sl, a * sa * f, layer.blend);\n }\n }\n }\n };\n\n // One composite pass at time tPass with all ink scaled by alphaScale — the\n // analytic mirror of the renderer's paintFrame. Ghost passes call this with\n // decayed weights; the live frame calls it with alphaScale 1.\n const splatPass = (tPass: number, alphaScale: number): void => {\n for (const { layer, entities } of scene.layers) {\n const lifeA = layer.opacity === undefined && layer.group === undefined ? lifeAlphaAt(layer.life, tPass) : lifeAlphaAt(layer.life, tPass) * paintOpacity(spec, layer);\n if (lifeA <= 0) continue;\n\n for (const e of entities) {\n splatTrail(layer, e, tPass, lifeA, alphaScale, entities.length);\n const a = Math.min(1, alphaAt(e, tPass) * lifeA) * alphaScale;\n if (a <= 0.004) continue;\n const lum = spriteLuma(layer, e);\n const p = posOf(scene, e, tPass);\n const sz = layer.transform || layer.group !== undefined ? sizeAt(e, tPass) * paintSize(spec, layer) : sizeAt(e, tPass);\n const s = layer.sprite;\n\n if (s.kind === 'polygon' && (sz >= POLYGON_OUTLINE_CELLS * Math.min(cellW, cellH) || (isPathPolygon(s) && ((s.span ?? 'box') !== 'box' || s.origin !== undefined)))) {\n splatPolygonOutline(layer, s, e, p, sz, a, lum, tPass);\n continue;\n }\n if (s.kind === 'stroke') {\n // Stamp along the sampled path, rotated like the renderer does.\n const pts = strokeSamples(s, sz / 2);\n let angle = rotationAt(e, tPass);\n if (s.orient) angle += headingAt(e, tPass, w, h) ?? 0;\n const ca = Math.cos(angle);\n const sa = Math.sin(angle);\n const lw = strokeWidthPx(s, scale);\n const stampAt = (q: { x: number; y: number }, u: number): void => {\n const x = p.x + q.x * ca - q.y * sa;\n const y = p.y + q.x * sa + q.y * ca;\n const c = Math.floor(x / cellW);\n const r = Math.floor(y / cellH);\n if (c < 0 || c >= cols || r < 0 || r >= rows) return;\n const taper = s.taper ? strokeTaper(u) : 1;\n compose(r * cols + c, lum, a * Math.min(1, (lw * taper) / cellH), layer.blend);\n };\n // Rasterize each segment at half-cell steps so a long stroke leaves a\n // continuous line of ink, not a dotted one.\n const step = Math.min(cellW, cellH) / 2;\n stampAt(pts[0]!, 0);\n for (let i = 1; i < pts.length; i++) {\n const q0 = pts[i - 1]!;\n const q1 = pts[i]!;\n const segLen = Math.hypot(q1.x - q0.x, q1.y - q0.y);\n const sub = Math.max(1, Math.ceil(segLen / step));\n for (let k = 1; k <= sub; k++) {\n const f = k / sub;\n stampAt({ x: q0.x + (q1.x - q0.x) * f, y: q0.y + (q1.y - q0.y) * f }, (i - 1 + f) / (pts.length - 1));\n }\n }\n continue;\n }\n if (s.kind === 'streak') {\n // Stamp along the segment from tail to head, like the renderer: motion\n // heading plus the entity's own resolved rotation.\n const heading = (headingAt(e, tPass, w, h) ?? 0) + rotationAt(e, tPass);\n const steps = Math.max(2, Math.ceil(sz / Math.min(cellW, cellH)));\n const wgt = Math.min(1, ((s.width ?? (scale === 1 ? 2 : 0.002)) * scale) / cellH);\n for (let i = 0; i <= steps; i++) {\n const k = i / steps;\n const x = p.x - Math.cos(heading) * sz * (1 - k);\n const y = p.y - Math.sin(heading) * sz * (1 - k);\n const c = Math.floor(x / cellW);\n const r = Math.floor(y / cellH);\n if (c < 0 || c >= cols || r < 0 || r >= rows) continue;\n compose(r * cols + c, lum, a * k * wgt, layer.blend);\n }\n continue;\n }\n\n let centerX = p.x;\n let centerY = p.y;\n let halfX = sz / 2;\n let halfY = s.kind === 'rect' ? ((e.size2 ?? sz) * (e.size > 0 ? sz / e.size : 1)) / 2 : sz / 2;\n if (s.kind === 'text') {\n const box = textBox(s, e, p, fontScaleFor(spec, w, h), scale);\n centerX = box.cx;\n centerY = box.cy;\n halfX = box.halfX;\n halfY = box.halfY;\n } else if (s.kind === 'textBlock') {\n const box = textBlockBox(s, e, p, w, h);\n centerX = box.cx;\n centerY = box.cy;\n halfX = box.halfX;\n halfY = box.halfY;\n } else if (s.kind === 'bar') {\n const len = sz * barFraction(s, e.barIndex ?? 0);\n if (len <= 0) continue;\n const th = e.size2 !== undefined ? e.size2 * (e.size > 0 ? sz / e.size : 1) : sz * 0.2;\n const box = barBox(s.direction ?? 'right', len, th);\n // The renderer rotates the bar about the entity with `spin`; rotate\n // the box's offset the same way and take the rotated box's AABB.\n const rot = rotationAt(e, tPass);\n const cr = Math.cos(rot);\n const sr = Math.sin(rot);\n centerX = p.x + box.cx * cr - box.cy * sr;\n centerY = p.y + box.cx * sr + box.cy * cr;\n halfX = Math.abs(box.halfX * cr) + Math.abs(box.halfY * sr);\n halfY = Math.abs(box.halfX * sr) + Math.abs(box.halfY * cr);\n }\n const circular = s.kind === 'circle' || s.kind === 'ring' || s.kind === 'polygon';\n const soft = (s.kind === 'circle' || s.kind === 'polygon') && !!s.soft;\n // A small polygon (under POLYGON_OUTLINE_CELLS) fills only part of its\n // disc; a feathered rect only part of its box. Scale the splat weight\n // rather than trace the outline — large polygons took the outline path.\n const shapeWeight = s.kind === 'polygon'\n ? polygonFill(s, sz / 2)\n : s.kind === 'rect' && s.feather\n ? (1 - s.feather / 2) * (1 - s.feather / 2)\n : 1;\n // The canvas draws a soft sprite as a radial gradient that ends AT its\n // radius (compile.ts), additive or not — no halo (perception-lab S1-03b).\n const c0 = Math.max(0, Math.floor((centerX - halfX) / cellW));\n const c1 = Math.min(cols - 1, Math.floor((centerX + halfX) / cellW));\n const r0 = Math.max(0, Math.floor((centerY - halfY) / cellH));\n const r1 = Math.min(rows - 1, Math.floor((centerY + halfY) / cellH));\n // Glyphs don't fill their box — ink is sparse. A revealing textBlock\n // has proportionally less ink lit.\n const inkWeight = (s.kind === 'text' || s.kind === 'emoji' || s.kind === 'textBlock' ? 0.55 : 1)\n * (s.kind === 'textBlock' ? textBlockRevealFraction(s, w, h, t) * (s.opacity ?? 1) : 1);\n // rect and bar are fillRect: the canvas paints each cell in proportion\n // to the area the box covers. Without this a 2 px scan line darkened\n // its whole 22 px grid row at full alpha, and 270 of them read as a\n // black veil (mean 0.035 where the canvas paints 0.41).\n const byArea = s.kind === 'rect' || s.kind === 'bar' || s.kind === 'text' || s.kind === 'emoji' || s.kind === 'textBlock';\n for (let r = r0; r <= r1; r++) {\n const fy = byArea ? Math.max(0, Math.min((r + 1) * cellH, centerY + halfY) - Math.max(r * cellH, centerY - halfY)) / cellH : 1;\n if (fy <= 0) continue;\n for (let c = c0; c <= c1; c++) {\n if (circular) {\n const inner = s.kind === 'ring' ? Math.max(0, halfX - (s.width ?? (scale === 1 ? 2 : 0.002)) * scale) : 0;\n // The canvas averages each cell, so a disc (or ring) that covers a\n // quarter of a cell moves that cell's mean by a quarter of its\n // contrast — light it by the ink it lays there, as rect/bar are.\n const wgt = discCellInk(centerX, centerY, halfX, inner, soft, c * cellW, r * cellH, cellW, cellH);\n if (wgt <= 0) continue;\n compose(r * cols + c, lum, a * wgt * shapeWeight, layer.blend);\n } else if (byArea) {\n const fx = Math.max(0, Math.min((c + 1) * cellW, centerX + halfX) - Math.max(c * cellW, centerX - halfX)) / cellW;\n if (fx > 0) compose(r * cols + c, lum, a * inkWeight * shapeWeight * fx * fy, layer.blend);\n } else {\n compose(r * cols + c, lum, a * inkWeight * shapeWeight, layer.blend);\n }\n }\n }\n }\n\n // Link lines are visual mass too (for chain scenes they ARE the scene).\n if (layer.links) {\n const positions = entities.map((e) => posOf(scene, e, tPass));\n const motionWraps = ['drift', 'rise', 'wander'].includes(layer.motion.type);\n const edges = linkEdges(layer.links, positions, linkMaxDistPx(layer.links, scale), layer.wrap !== false && motionWraps, w, h);\n const la = Math.min(1, (layer.links.alpha ?? 0.6) * lifeA);\n const lum = layer.links.color ? hexLuma(layer.links.color) : 0.7;\n const defaultWidth = scale === 1 ? 1 : 1 / LIMITS.referenceViewport;\n const wgt = Math.min(1, ((layer.links.width ?? defaultWidth) * scale) / cellH) * la * alphaScale;\n for (const edge of edges) {\n const pi = positions[edge.i]!;\n const pj = positions[edge.j]!;\n const steps = Math.max(1, Math.ceil(edge.dist / Math.min(cellW, cellH)));\n for (let i = 0; i <= steps; i++) {\n const k = i / steps;\n const c = Math.floor((pi.x + (pj.x - pi.x) * k) / cellW);\n const r = Math.floor((pi.y + (pj.y - pi.y) * k) / cellH);\n if (c < 0 || c >= cols || r < 0 || r >= rows) continue;\n compose(r * cols + c, lum, wgt, layer.blend);\n }\n }\n }\n }\n };\n\n // Ghosting: the renderer composites each 60 fps frame over the last with\n // persistence g, so ink from m frames ago survives at weight g^m. Sample\n // that decay across the visible window (weight ≥ 1/255, capped at the same\n // maxGhostReplayFrames bound as the renderer's seek replay), oldest first so\n // newer ink composites on top. Each tap stands in for the frames in its\n // bracket and carries their summed surviving weight (geometric sum).\n const ghost = spec.ghosting ?? 0;\n if (ghost > 0) {\n const dt = 1000 / 60;\n const windowFrames = Math.min(Math.ceil(Math.log(1 / 255) / Math.log(ghost)), LIMITS.maxGhostReplayFrames);\n const taps = Math.min(GHOST_TAPS, windowFrames);\n const spacing = windowFrames / taps;\n for (let i = taps; i >= 1; i--) {\n const tPass = t - i * spacing * dt;\n if (tPass < 0) continue;\n const bracketWeight =\n (Math.pow(ghost, (i - 1) * spacing + 1) * (1 - Math.pow(ghost, spacing))) / (1 - ghost);\n splatPass(tPass, Math.min(1, bracketWeight));\n }\n }\n splatPass(t, 1);\n\n // Deviation stats\n return finishGrid(cols, rows, cells, bgRow, bgCells);\n}\n\n/**\n * The stats every grid carries, from its cells and per-row background —\n * or, for a field, its per-cell background (`bgCells`), which deviation is\n * measured against instead so the field's own contours read as ground.\n */\nfunction finishGrid(cols: number, rows: number, cells: number[], bgRow: number[], bgCells?: number[]): LuminanceGrid {\n let sum = 0;\n let covered = 0;\n let devSum = 0;\n let cxAcc = 0;\n let cyAcc = 0;\n const rowProfile = new Array<number>(rows).fill(0);\n const colProfile = new Array<number>(cols).fill(0);\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const v = cells[r * cols + c]!;\n sum += v;\n const dev = Math.abs(v - (bgCells ? bgCells[r * cols + c]! : bgRow[r]!));\n if (dev > 0.03) covered++;\n devSum += dev;\n cxAcc += dev * (c + 0.5);\n cyAcc += dev * (r + 0.5);\n rowProfile[r]! += dev;\n colProfile[c]! += dev;\n }\n }\n for (let r = 0; r < rows; r++) rowProfile[r] = rowProfile[r]! / cols;\n for (let c = 0; c < cols; c++) colProfile[c] = colProfile[c]! / rows;\n\n return {\n cols,\n rows,\n cells,\n background: bgRow,\n ...(bgCells ? { backgroundCells: bgCells } : {}),\n meanLuminance: sum / (cols * rows),\n coverage: covered / (cols * rows),\n centroid: devSum > 1e-6 ? { x: cxAcc / devSum / cols, y: cyAcc / devSum / rows } : null,\n rowProfile,\n colProfile,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Braille rendering\n// ---------------------------------------------------------------------------\n\n// Ordered-dither thresholds for a 2×4 braille cell (spatially spread).\nconst DITHER: number[][] = [\n [0.5 / 8, 4.5 / 8],\n [2.5 / 8, 6.5 / 8],\n [1.5 / 8, 5.5 / 8],\n [3.5 / 8, 7.5 / 8],\n];\n// Braille dot bit for (row 0..3, col 0..1): dots 1-2-3-7 left, 4-5-6-8 right.\nconst DOT_BIT: number[][] = [\n [0x01, 0x08],\n [0x02, 0x10],\n [0x04, 0x20],\n [0x40, 0x80],\n];\n\n/**\n * Auto-exposure curve for a grid: most savers live in the bottom of the\n * luminance range, so cells are normalized (min → 98th percentile) with a\n * slight gamma before quantizing — like a camera exposing for the scene. Stats\n * on the grid itself stay raw.\n *\n * Shared by every renderer below, deliberately: if the curve is ever\n * recalibrated (e.g. once a calibration constant moves coverage), the braille\n * and density views must move together or they'd silently disagree about the\n * same scene.\n */\nfunction autoExpose(grid: LuminanceGrid): (v: number) => number {\n const sorted = [...grid.cells].sort((a, b) => a - b);\n const lo = sorted[0]!;\n const hi = Math.max(sorted[Math.floor(sorted.length * 0.98)]!, lo + 0.08);\n return (v: number): number => Math.pow(Math.max(0, Math.min(1, (v - lo) / (hi - lo))), 0.8);\n}\n\n/**\n * Encode a luminance grid as a braille \"image\": each output character is a 2×4\n * pixel cell, ordered-dithered so mid-tones render as dot density. A grid of\n * 80×48 becomes 12 lines of 40 chars — a picture a text model can read whole.\n */\nexport function renderBrailleMap(grid: LuminanceGrid): string {\n const expose = autoExpose(grid);\n\n const outRows: string[] = [];\n for (let br = 0; br < Math.floor(grid.rows / 4); br++) {\n let line = '';\n for (let bc = 0; bc < Math.floor(grid.cols / 2); bc++) {\n let bits = 0;\n for (let dr = 0; dr < 4; dr++) {\n for (let dc = 0; dc < 2; dc++) {\n const v = expose(grid.cells[(br * 4 + dr) * grid.cols + (bc * 2 + dc)]!);\n if (v > DITHER[dr]![dc]!) bits |= DOT_BIT[dr]![dc]!;\n }\n }\n line += String.fromCharCode(0x2800 + bits);\n }\n outRows.push(line);\n }\n return outRows.join('\\n');\n}\n\n// Density ramp, dark → bright. One char per grid cell (vs braille's 2×4), so a\n// higher-resolution grid reads as a sharper picture — the channel agents found\n// most legible for structure (rings, grids, text blocks) that braille blurs.\nconst DENSITY_RAMP = ' .:-=+*#%@';\n\n/**\n * Encode a luminance grid as a one-char-per-cell ASCII density map. Unlike the\n * braille map (compact, 2×4 dots/char) this is 1:1 with the grid, so pairing it\n * with a larger `cols`/`rows` gives a non-vision agent a genuinely higher-detail\n * read: 120×48 resolves concentric rings and text blocks braille smears into a\n * blob. Shares the braille map's auto-exposure so both views agree.\n */\nexport function renderDensityMap(grid: LuminanceGrid): string {\n const expose = autoExpose(grid);\n const ramp = DENSITY_RAMP;\n const lines: string[] = [];\n for (let r = 0; r < grid.rows; r++) {\n let line = '';\n for (let c = 0; c < grid.cols; c++) {\n const v = expose(grid.cells[r * grid.cols + c]!);\n line += ramp[Math.min(ramp.length - 1, Math.floor(v * ramp.length))]!;\n }\n lines.push(line);\n }\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Text sprite listing\n// ---------------------------------------------------------------------------\n\nexport interface TextSpriteInfo {\n layerIndex: number;\n key: string | undefined;\n /** The literal strings this layer draws (glyphs are invisible in the maps). */\n strings: string[];\n /** How many entities carry text. */\n count: number;\n /** Representative rendered glyph height in px at the sample viewport. */\n sizePx: number;\n /** For a revealing textBlock: effective 0..1 fraction shown at sample t. */\n revealed?: number;\n}\n\n/**\n * List every text layer's actual strings and rendered size. No grid resolution\n * renders glyphs legibly, so a non-vision agent otherwise can't tell whether the\n * words it wrote are on screen, how big, or whether they'll overlap. This closes\n * that blind spot analytically.\n */\nexport function textSprites(spec: SaverSpec, opts: PerceiveOptions = {}): TextSpriteInfo[] {\n spec = resolveTimelineAt(spec, opts.t ?? 5000);\n const scene = buildScene(spec, opts);\n const t = opts.t ?? 5000;\n const out: TextSpriteInfo[] = [];\n scene.layers.forEach(({ layer, entities }, layerIndex) => {\n if (layer.sprite.kind === 'textBlock') {\n const s = layer.sprite;\n const unitScale = Math.min(scene.w, scene.h);\n const sizePx = s.fontSize * unitScale;\n const info: TextSpriteInfo = { layerIndex, key: layer.key, strings: [s.text], count: entities.length, sizePx: Math.round(sizePx) };\n if (s.reveal) info.revealed = Math.round(textBlockRevealFraction(s, scene.w, scene.h, t) * 100) / 100;\n out.push(info);\n return;\n }\n if (layer.sprite.kind !== 'text') return;\n const s = layer.sprite;\n const sizePx = textFontPx(s, entities[0] ? sizeAt(entities[0], t) : 0, fontScaleFor(spec, scene.w, scene.h));\n out.push({ layerIndex, key: layer.key, strings: [...s.strings], count: entities.length, sizePx: Math.round(sizePx) });\n });\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Dominance ranking\n// ---------------------------------------------------------------------------\n\nexport interface DominanceEntry {\n rank: number;\n layerIndex: number;\n key: string | undefined;\n /** Normalized share of total visual weight, 0..1 (all entries sum to 1). */\n share: number;\n entityCount: number;\n meanLuma: number;\n factors: { area: number; contrast: number; blendBoost: number; motionBoost: number };\n}\n\n/**\n * Rank layers by estimated visual weight — where the eye goes. Weight is\n * on-screen area × alpha, scaled by contrast against the background, an\n * additive-glow boost, and a motion boost. Link lines count as area, and so\n * does persistence ink: trail ribbons and ghosting smear are modeled as swept\n * ribbons, so a comet layer is ranked by its comet, not just its head.\n */\nexport function dominanceRanking(spec: SaverSpec, opts: PerceiveOptions = {}): DominanceEntry[] {\n return rankDominance(rawDominance(spec, opts));\n}\n\ninterface RawDominance {\n layerIndex: number;\n key: string | undefined;\n weight: number;\n entityCount: number;\n meanLuma: number;\n factors: DominanceEntry['factors'];\n}\n\n/** Normalize raw weights to shares and rank — shared by a scene and a composed sequence frame. */\nfunction rankDominance(raw: RawDominance[]): DominanceEntry[] {\n const total = raw.reduce((s, r) => s + r.weight, 0) || 1;\n return raw\n .slice()\n .sort((a, b) => b.weight - a.weight)\n .map((r, i) => ({\n rank: i + 1,\n layerIndex: r.layerIndex,\n key: r.key,\n share: r.weight / total,\n entityCount: r.entityCount,\n meanLuma: r.meanLuma,\n factors: r.factors,\n }));\n}\n\n/** Per-layer un-normalized visual weight at `opts.t` — the body of dominanceRanking. */\nfunction rawDominance(spec: SaverSpec, opts: PerceiveOptions = {}): RawDominance[] {\n spec = resolveTimelineAt(spec, opts.t ?? 5000);\n const scene = buildScene(spec, opts);\n const t = opts.t ?? 5000;\n const { w, h, scale } = scene;\n\n const bgMean = backgroundLuma(spec);\n\n\n // Persistence smears every moving sprite into a ribbon of real visual mass —\n // for a comet layer the trail IS the visual event. Model both effects as\n // swept ribbons (path length × stroke width × mean surviving alpha), using\n // the straight-line displacement as a lower-bound path length and skipping\n // wrap seams. First-pass fidelity, not yet checked against pixels.\n const ghost = spec.ghosting ?? 0;\n let ghostWindowMs = 0;\n let ghostMeanW = 0;\n if (ghost > 0) {\n const dt = 1000 / 60;\n const frames = Math.min(Math.ceil(Math.log(1 / 255) / Math.log(ghost)), LIMITS.maxGhostReplayFrames);\n ghostWindowMs = frames * dt;\n ghostMeanW = (ghost * (1 - Math.pow(ghost, frames))) / (1 - ghost) / frames;\n }\n const sweptDistance = (e: Entity, spanMs: number): number => {\n const span = Math.min(spanMs, t);\n if (span <= 0) return 0;\n const p0 = posOf(scene, e, t - span);\n const p1 = posOf(scene, e, t);\n const dx = p1.x - p0.x;\n const dy = p1.y - p0.y;\n if (Math.abs(dx) > w / 2 || Math.abs(dy) > h / 2) return 0; // wrapped: ambiguous\n return Math.sqrt(dx * dx + dy * dy);\n };\n\n const raw = scene.layers.map(({ layer, entities }, layerIndex) => {\n const lifeA = layer.opacity === undefined && layer.group === undefined ? lifeAlphaAt(layer.life, t) : lifeAlphaAt(layer.life, t) * paintOpacity(spec, layer);\n const painted = layer.transform !== undefined || layer.group !== undefined;\n const areaScale = painted ? paintSize(spec, layer) ** 2 : 1;\n let area = 0;\n let lumAcc = 0;\n for (const e of entities) {\n const a = alphaAt(e, t) * lifeA;\n const sz = sizeAt(e, t);\n const s = layer.sprite;\n let entArea: number;\n if (s.kind === 'circle') entArea = Math.PI * (sz / 2) * (sz / 2);\n else if (s.kind === 'ring') entArea = Math.PI * sz * ((s.width ?? (scale === 1 ? 2 : 0.002)) * scale) * LINE_SALIENCE;\n else if (s.kind === 'streak') entArea = sz * ((s.width ?? (scale === 1 ? 2 : 0.002)) * scale) * LINE_SALIENCE;\n else if (s.kind === 'rect') {\n const h2 = e.size2 !== undefined ? e.size2 * (e.size > 0 ? sz / e.size : 1) : sz;\n const f = s.feather ? (1 - s.feather / 2) * (1 - s.feather / 2) : 1;\n entArea = sz * h2 * f;\n }\n else if (s.kind === 'polygon') entArea = polygonArea(polygonPoints(s, sz / 2));\n else if (s.kind === 'bar') {\n const th = e.size2 !== undefined ? e.size2 * (e.size > 0 ? sz / e.size : 1) : sz * 0.2;\n entArea = sz * barFraction(s, e.barIndex ?? 0) * th;\n }\n else if (s.kind === 'stroke') {\n const meanTaper = s.taper ? 0.64 : 1; // ∫ sin(πu) du = 2/π\n entArea = pathLength(strokeSamples(s, sz / 2)) * strokeWidthPx(s, scale) * meanTaper * LINE_SALIENCE;\n }\n else if (s.kind === 'text') {\n const box = textBox(s, e, { x: 0, y: 0 }, fontScaleFor(spec, w, h), scale);\n entArea = box.halfX * 2 * box.halfY * 2 * 0.55;\n } else if (s.kind === 'textBlock') {\n const box = textBlockBox(s, e, { x: 0, y: 0 }, w, h);\n entArea = box.halfX * 2 * box.halfY * 2 * 0.55 * textBlockRevealFraction(s, w, h, t) * (s.opacity ?? 1);\n } else entArea = sz * sz * 0.55; // emoji\n\n area += painted ? entArea * areaScale * a : entArea * a;\n\n // Trail ribbon: dots shrink to 0.3× and fade along the tail, so mean\n // width ≈ 0.65×size and mean alpha ≈ (1 - fade/2) of the head's.\n if (layer.trail) {\n const fade = layer.trail.fade ?? 1;\n const span = sweptDistance(e, layer.trail.length);\n area += span * sz * 0.65 * Math.max(0, 1 - fade / 2) * a;\n }\n // Ghost smear: ink from m frames back survives at g^m, so the sweep over\n // the visible window carries the window's mean surviving weight.\n if (ghost > 0) {\n area += sweptDistance(e, ghostWindowMs) * sz * ghostMeanW * a;\n }\n lumAcc += spriteLuma(layer, e);\n }\n if (layer.links && entities.length > 1) {\n const positions = entities.map((e) => posOf(scene, e, t));\n const motionWraps = ['drift', 'rise', 'wander'].includes(layer.motion.type);\n const edges = linkEdges(layer.links, positions, linkMaxDistPx(layer.links, scale), layer.wrap !== false && motionWraps, w, h);\n const la = (layer.links.alpha ?? 0.6) * lifeA;\n const defaultWidth = scale === 1 ? 1 : 1 / LIMITS.referenceViewport;\n const lw = (layer.links.width ?? defaultWidth) * scale;\n for (const edge of edges) area += edge.dist * lw * la * LINE_SALIENCE;\n }\n const meanLuma = entities.length ? lumAcc / entities.length : 0;\n const contrast = Math.abs(meanLuma - bgMean) + 0.1;\n const blendBoost = layer.blend === 'lighter' || layer.blend === 'screen' ? 1.3 : layer.blend === 'multiply' ? 1.1 : 1;\n const motionBoost = layer.motion.type === 'static' ? 1 : 1.2;\n const weight = (area / (w * h)) * contrast * blendBoost * motionBoost;\n return { layerIndex, key: layer.key, weight, entityCount: entities.length, meanLuma, factors: { area: area / (w * h), contrast, blendBoost, motionBoost } };\n });\n\n return raw;\n}\n\n// ---------------------------------------------------------------------------\n// Motion stats\n// ---------------------------------------------------------------------------\n\n/**\n * Does each layer read as one merged form or as separate marks? The one thing\n * the luminance maps cannot answer — they measure ink, not edges, so a layer\n * that merged into a silhouette and one that stayed a pile of discs look\n * identical in every other channel. See `cohesion.ts`.\n */\nexport function layerCohesion(spec: SaverSpec, opts: PerceiveOptions = {}): LayerCohesion[] {\n spec = resolveTimelineAt(spec, opts.t ?? 5000);\n const scene = buildScene(spec, opts);\n return cohesionOf(scene.layers, opts.t ?? 5000, scene.w, scene.h);\n}\n\nexport interface LayerMotionStats {\n layerIndex: number;\n key: string | undefined;\n /** Mean / max on-screen speed in px per second at the perceived size (wrap jumps excluded). */\n meanSpeed: number;\n maxSpeed: number;\n /**\n * The same speeds in **viewport units per second** — fractions of\n * min(w, h), the unit a spec's `speed` is authored in — so they do not\n * change with the size the scene is perceived at. 1.0 crosses the short side\n * of the screen every second.\n */\n meanSpeedVp: number;\n maxSpeedVp: number;\n /** meanSpeedVp above MOVING_FLOOR — the same answer at every preview size. */\n moving: boolean;\n /**\n * Direction the layer's mass is going, in screen degrees (0 = right,\n * 90 = down, 180 = left, 270 = up), or null when nothing moves. Sampling a\n * centroid over time gives the WRONG sign for a wrapping full-viewport\n * scatter, which is why this is reported directly.\n */\n heading: number | null;\n /**\n * 0 = every entity moves the same way (a conveyor — the \"screen-wipe\" the\n * schema warns about), 1 = headings cancel out (a scatter, an orbit, a\n * bounce field). |mean unit vector| inverted.\n */\n headingSpread: number | null;\n}\n\n/**\n * Below this many viewport units per second a layer reads as still (half a\n * pixel per second on a 1080 display — what the old px/s threshold of 0.5\n * meant at that one resolution).\n */\nconst MOVING_FLOOR = 0.0005;\n\n\n/**\n * Per-layer displacement between t and t+dt — choreography as numbers.\n *\n * Samples the scene at both ends of the window separately (not just each\n * entity's own position within one scene) so a `timeline`-driven layer\n * `transform` — a camera pan or zoom with every entity otherwise static —\n * registers as motion instead of vanishing between two reads of the same\n * frozen transform.\n */\nexport function motionStats(spec: SaverSpec, opts: PerceiveOptions & { dt?: number } = {}): LayerMotionStats[] {\n const t = opts.t ?? 5000;\n const dt = opts.dt ?? 500;\n const scene0 = buildScene(resolveTimelineAt(spec, t), opts);\n const scene1 = spec.timeline ? buildScene(resolveTimelineAt(spec, t + dt), opts) : scene0;\n const { w, h } = scene0;\n const unit = Math.min(w, h);\n return scene0.layers.map(({ layer, entities }, layerIndex) => {\n const entities1 = scene1.layers[layerIndex]?.entities ?? entities;\n let acc = 0;\n let max = 0;\n let n = 0;\n let ux = 0;\n let uy = 0;\n let moversN = 0;\n entities.forEach((e, i) => {\n const p0 = posOf(scene0, e, t);\n const p1 = posOf(scene1, entities1[i] ?? e, t + dt);\n const dx = p1.x - p0.x;\n const dy = p1.y - p0.y;\n if (Math.abs(dx) > w / 2 || Math.abs(dy) > h / 2) return; // wrap seam\n const dist = Math.sqrt(dx * dx + dy * dy);\n const speed = (dist / dt) * 1000;\n acc += speed;\n max = Math.max(max, speed);\n n++;\n if (dist > 0) {\n ux += dx / dist;\n uy += dy / dist;\n moversN++;\n }\n });\n const meanSpeed = n ? acc / n : 0;\n const meanSpeedVp = meanSpeed / unit;\n const maxSpeedVp = max / unit;\n const moving = meanSpeedVp > MOVING_FLOOR;\n let heading: number | null = null;\n let headingSpread: number | null = null;\n if (moving && moversN > 0) {\n const mx = ux / moversN;\n const my = uy / moversN;\n const mag = Math.sqrt(mx * mx + my * my);\n headingSpread = 1 - mag;\n heading = mag > 0.05 ? ((Math.atan2(my, mx) * 180) / Math.PI + 360) % 360 : null;\n }\n return { layerIndex, key: layer.key, meanSpeed, maxSpeed: max, meanSpeedVp, maxSpeedVp, moving, heading, headingSpread };\n });\n}\n\n// ---------------------------------------------------------------------------\n// Colour — the channel edits are usually about\n// ---------------------------------------------------------------------------\n\nexport interface SceneColour {\n /** Hue of the visible sprite mass in degrees (0 red, 120 green, 240 blue), null when unsaturated. */\n hue: number | null;\n /** HSL saturation 0..1 of the sprite mass. */\n saturation: number;\n /** red minus blue of the mean sprite colour, -1 (cold) .. 1 (warm). The \"cooler/warmer\" axis. */\n warmth: number;\n /** Mean sprite colour as hex, for a model that reads hex better than angles. */\n hex: string;\n /** The same three numbers for the background plate. */\n background: { hue: number | null; saturation: number; warmth: number; hex: string };\n}\n\nfunction rgbToHsl(c: { r: number; g: number; b: number }): { h: number | null; s: number; l: number } {\n const max = Math.max(c.r, c.g, c.b);\n const min = Math.min(c.r, c.g, c.b);\n const l = (max + min) / 2;\n const d = max - min;\n if (d < 1e-6) return { h: null, s: 0, l };\n const sat = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n let h: number;\n if (max === c.r) h = ((c.g - c.b) / d + (c.g < c.b ? 6 : 0)) * 60;\n else if (max === c.g) h = ((c.b - c.r) / d + 2) * 60;\n else h = ((c.r - c.g) / d + 4) * 60;\n return { h: sat < 0.05 ? null : h, s: sat, l };\n}\n\nfunction toHex(c: { r: number; g: number; b: number }): string {\n const q = (v: number) => Math.round(Math.max(0, Math.min(1, v)) * 255).toString(16).padStart(2, '0');\n return `#${q(c.r)}${q(c.g)}${q(c.b)}`;\n}\n\nfunction describeColour(c: { r: number; g: number; b: number }): { hue: number | null; saturation: number; warmth: number; hex: string } {\n const hsl = rgbToHsl(c);\n return { hue: hsl.h === null ? null : Math.round(hsl.h), saturation: +hsl.s.toFixed(3), warmth: +(c.r - c.b).toFixed(3), hex: toHex(c) };\n}\n\n/**\n * What colour the scene IS — the alpha × area weighted mean of every hex a\n * sprite paints with, beside the background plate. A luminance map cannot\n * carry this: a luma-matched red→cyan swap moves every other channel by\n * ~0.001 (comprehension eval 2026-07-28, P2 F3), and `meanLuminance` reads\n * plausible cool tones as *brighter* than the reds they replace, so \"make it\n * cooler\" pushed the only number an agent had in the wrong direction. Emoji\n * carry their own palette and are excluded; a scene of only emoji reports the\n * background.\n */\nexport function sceneColour(spec: SaverSpec, opts: PerceiveOptions = {}): SceneColour {\n const t = opts.t ?? 5000;\n // A timeline can animate colour: read the scene as it is at t.\n spec = resolveTimelineAt(spec, t);\n const scene = buildScene(spec, opts);\n let wr = 0;\n let wg = 0;\n let wb = 0;\n let wsum = 0;\n for (const { layer, entities } of scene.layers) {\n // Paint opacity (layer × group) weighs like alpha: a hidden prop adds no colour.\n const lifeA = lifeAlphaAt(layer.life, t) * (layer.opacity === undefined && layer.group === undefined ? 1 : paintOpacity(spec, layer));\n for (const e of entities) {\n const hex = spriteHex(layer, e);\n if (hex === null) continue;\n const sz = sizeAt(e, t);\n const weight = alphaAt(e, t) * lifeA * (layer.sprite.kind === 'circle' ? Math.PI * (sz / 2) * (sz / 2) : sz * sz);\n if (weight <= 0) continue;\n const c = hexRgb(hex);\n wr += c.r * weight;\n wg += c.g * weight;\n wb += c.b * weight;\n wsum += weight;\n }\n }\n const bg = backgroundRgb(spec);\n const sprites = wsum > 0 ? { r: wr / wsum, g: wg / wsum, b: wb / wsum } : bg;\n return { ...describeColour(sprites), background: describeColour(bg) };\n}\n\n/** Signed shortest hue difference b − a in degrees (−180..180), null when either is unsaturated. */\nfunction hueShift(a: number | null, b: number | null): number | null {\n if (a === null || b === null) return null;\n let d = b - a;\n while (d > 180) d -= 360;\n while (d < -180) d += 360;\n return Math.round(d);\n}\n\n// ---------------------------------------------------------------------------\n// Scene diff — relative sight\n// ---------------------------------------------------------------------------\n\nconst REGION_NAMES = [\n 'top-left', 'top-center', 'top-right',\n 'mid-left', 'center', 'mid-right',\n 'bottom-left', 'bottom-center', 'bottom-right',\n] as const;\n\nfunction regionMeans(grid: LuminanceGrid): number[] {\n const out = new Array<number>(9).fill(0);\n const cnt = new Array<number>(9).fill(0);\n for (let r = 0; r < grid.rows; r++) {\n for (let c = 0; c < grid.cols; c++) {\n const idx = r * grid.cols + c;\n const region = Math.min(2, Math.floor((r / grid.rows) * 3)) * 3 + Math.min(2, Math.floor((c / grid.cols) * 3));\n // A field's own contours are ground, not content (see `backgroundCells`\n // on `LuminanceGrid`): deviate against the per-cell background where\n // one exists, the same rule `finishGrid` applies to coverage/centroid.\n out[region]! += Math.abs(grid.cells[idx]! - (grid.backgroundCells ? grid.backgroundCells[idx]! : grid.background[r]!));\n cnt[region]!++;\n }\n }\n return out.map((v, i) => (cnt[i]! ? v / cnt[i]! : 0));\n}\n\nexport interface SceneDiff {\n t: number;\n coverage: { a: number; b: number; delta: number };\n meanLuminance: { a: number; b: number; delta: number };\n /** Shift of the visual-mass centroid from A to B, in viewport fractions. */\n balanceShift: { dx: number; dy: number } | null;\n /** Mean deviation-from-background per third-by-third region, with deltas. */\n regions: Array<{ region: (typeof REGION_NAMES)[number]; a: number; b: number; delta: number }>;\n /** Dominance changes, matched by layer key (falls back to index). Sorted by |share delta|. */\n dominance: Array<{ key: string; rankA: number | null; rankB: number | null; shareA: number; shareB: number }>;\n /**\n * The hue channel. `hueShift` is the signed shortest rotation A→B in\n * degrees; `warmthDelta` is the cooler/warmer axis (negative = B is cooler)\n * — read THIS for \"cooler\", not `meanLuminance`, which weights cool tones\n * brighter than the reds they replace.\n */\n colour: {\n a: SceneColour;\n b: SceneColour;\n hueShift: number | null;\n saturationDelta: number;\n warmthDelta: number;\n background: { hueShift: number | null; warmthDelta: number };\n };\n /**\n * The motion channel, in viewport units per second. `overall` is the\n * entity-weighted mean across layers; `layers` lists every layer whose speed\n * changed, largest change first. Halving every speed used to leave the diff\n * bit-identical (comprehension eval 2026-07-28, P2 F4).\n */\n motion: {\n overall: { a: number; b: number; delta: number };\n layers: Array<{ key: string; a: number; b: number; delta: number; headingA: number | null; headingB: number | null }>;\n };\n advisories: { added: string[]; removed: string[] };\n}\n\n/**\n * Compare two specs at the same time/viewport — relative perception. A text\n * model is far better at \"is B better than A\" than \"is A good\"; this returns\n * the deltas that question needs: coverage, balance, per-region visual mass,\n * dominance-rank movement, and advisory changes.\n */\nexport function diffScenes(a: SaverSpec, b: SaverSpec, opts: LuminanceGridOptions = {}): SceneDiff {\n const t = opts.t ?? 5000;\n const gridA = luminanceGrid(a, opts);\n const gridB = luminanceGrid(b, opts);\n const regsA = regionMeans(gridA);\n const regsB = regionMeans(gridB);\n const domA = dominanceRanking(a, opts);\n const domB = dominanceRanking(b, opts);\n\n const nameOf = (d: DominanceEntry): string => d.key ?? `layer-${d.layerIndex}`;\n const names = new Set<string>([...domA.map(nameOf), ...domB.map(nameOf)]);\n const dominance = [...names].map((key) => {\n const inA = domA.find((d) => nameOf(d) === key);\n const inB = domB.find((d) => nameOf(d) === key);\n return {\n key,\n rankA: inA?.rank ?? null,\n rankB: inB?.rank ?? null,\n shareA: inA?.share ?? 0,\n shareB: inB?.share ?? 0,\n };\n }).sort((x, y) => Math.abs(y.shareB - y.shareA) - Math.abs(x.shareB - x.shareA));\n\n // Advise at the diff's OWN viewport. This used to run at the 1920×1080\n // default while the caller previewed at 960×540, so the two tools disagreed\n // about the same spec's advisories (comprehension eval 2026-07-28, P3 F6).\n const vp = opts.viewport ?? { width: 1920, height: 1080 };\n const codesA = new Set(adviseSpec(a, vp).map((w) => w.code));\n const codesB = new Set(adviseSpec(b, vp).map((w) => w.code));\n\n const colA = sceneColour(a, opts);\n const colB = sceneColour(b, opts);\n const motA = motionStats(a, opts);\n const motB = motionStats(b, opts);\n const weighted = (stats: LayerMotionStats[], dom: DominanceEntry[]): number => {\n let acc = 0;\n let n = 0;\n for (const m of stats) {\n const c = dom.find((d) => d.layerIndex === m.layerIndex)?.entityCount ?? 1;\n acc += m.meanSpeedVp * c;\n n += c;\n }\n return n ? acc / n : 0;\n };\n const motNameOf = (m: LayerMotionStats): string => m.key ?? `layer-${m.layerIndex}`;\n const motionLayers = [...new Set([...motA.map(motNameOf), ...motB.map(motNameOf)])]\n .map((key) => {\n const ma = motA.find((m) => motNameOf(m) === key);\n const mb = motB.find((m) => motNameOf(m) === key);\n const va = ma?.meanSpeedVp ?? 0;\n const vb = mb?.meanSpeedVp ?? 0;\n return { key, a: va, b: vb, delta: vb - va, headingA: ma?.heading ?? null, headingB: mb?.heading ?? null };\n })\n .filter((m) => Math.abs(m.delta) > 1e-9 || m.headingA !== m.headingB)\n .sort((x, y) => Math.abs(y.delta) - Math.abs(x.delta));\n const overallA = weighted(motA, domA);\n const overallB = weighted(motB, domB);\n\n return {\n t,\n coverage: { a: gridA.coverage, b: gridB.coverage, delta: gridB.coverage - gridA.coverage },\n meanLuminance: { a: gridA.meanLuminance, b: gridB.meanLuminance, delta: gridB.meanLuminance - gridA.meanLuminance },\n balanceShift: gridA.centroid && gridB.centroid\n ? { dx: gridB.centroid.x - gridA.centroid.x, dy: gridB.centroid.y - gridA.centroid.y }\n : null,\n regions: REGION_NAMES.map((region, i) => ({ region, a: regsA[i]!, b: regsB[i]!, delta: regsB[i]! - regsA[i]! })),\n dominance,\n colour: {\n a: colA,\n b: colB,\n hueShift: hueShift(colA.hue, colB.hue),\n saturationDelta: +(colB.saturation - colA.saturation).toFixed(3),\n warmthDelta: +(colB.warmth - colA.warmth).toFixed(3),\n background: {\n hueShift: hueShift(colA.background.hue, colB.background.hue),\n warmthDelta: +(colB.background.warmth - colA.background.warmth).toFixed(3),\n },\n },\n motion: {\n overall: { a: overallA, b: overallB, delta: overallB - overallA },\n layers: motionLayers,\n },\n advisories: {\n added: [...codesB].filter((c) => !codesA.has(c)),\n removed: [...codesA].filter((c) => !codesB.has(c)),\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// One-call perception bundle\n// ---------------------------------------------------------------------------\n\nexport interface ScenePerception {\n t: number;\n /** The picture: a braille luminance map (each char = 2×4 pixels), compact. */\n braille: string;\n /**\n * A one-char-per-cell ASCII density map at the grid resolution — higher\n * fidelity than braille for structure (rings, grids, text blocks). Pair with\n * a larger `cols`/`rows` for a sharper read.\n */\n density: string;\n coverage: number;\n meanLuminance: number;\n centroid: { x: number; y: number } | null;\n rowProfile: number[];\n colProfile: number[];\n dominance: DominanceEntry[];\n motion: LayerMotionStats[];\n /** Per layer: merged silhouette, seamed overlap, or separate marks. */\n form: LayerCohesion[];\n /** What colour the scene is — hue/saturation/warmth of the sprite mass and the plate. */\n colour: SceneColour;\n /** Literal strings + sizes of any text layers (glyphs don't show in the maps). */\n text: TextSpriteInfo[];\n advisories: ReturnType<typeof adviseSpec>;\n}\n\n/**\n * Everything a non-vision agent needs to \"see\" a spec in one deterministic\n * call: the braille picture, a higher-res density map, composition transects,\n * dominance ranking, motion stats, the literal text on screen, and advisories.\n * Intended as the payload behind an MCP previewScene.\n */\nexport function perceiveScene(spec: SaverSpec, opts: LuminanceGridOptions = {}): ScenePerception {\n // motionStats gets the spec WITH its timeline: it resolves t and t + dt\n // itself, and a pre-resolved spec has no timeline left to differ between\n // them — every layer moved only by timeline keys read 0 px/s (X437).\n const timed = spec;\n spec = resolveTimelineAt(spec, opts.t ?? 5000);\n const grid = luminanceGrid(spec, opts);\n return {\n t: opts.t ?? 5000,\n braille: renderBrailleMap(grid),\n density: renderDensityMap(grid),\n coverage: grid.coverage,\n meanLuminance: grid.meanLuminance,\n centroid: grid.centroid,\n rowProfile: grid.rowProfile,\n colProfile: grid.colProfile,\n dominance: dominanceRanking(spec, opts),\n motion: motionStats(timed, opts),\n form: layerCohesion(spec, opts),\n colour: sceneColour(spec, opts),\n text: textSprites(spec, opts),\n advisories: adviseSpec(spec, opts.viewport ?? { width: 1920, height: 1080 }, { t: opts.t, seed: opts.seed }),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Sequence frames — bed + segment\n// ---------------------------------------------------------------------------\n\nexport interface SequenceFramePerception extends ScenePerception {\n /** Which segment the global time `T` resolved to, and where in it. */\n segment: { index: number; key: string; localT: number; held?: true };\n /** True when a bed was composed under the segment. */\n bed: boolean;\n}\n\nexport interface PerceiveSequenceOptions extends Omit<LuminanceGridOptions, 't'> {\n /** Holds released by the clicker so far — see `ResolveOptions.releasedBelow`. */\n releasedBelow?: number;\n}\n\n/** Prefix bed layers so they read apart from the segment's in a merged list. */\nconst bedKey = (key: string | undefined, layerIndex: number): string => `bed:${key ?? layerIndex}`;\n\n/**\n * Perceive one frame of a sequence at global time `T`: resolve the segment,\n * then — when the sequence has a `bed` — compose the bed at `T` (its clock\n * never resets) under the segment's ink at `localT`, the segment's own\n * background dropped, exactly as the renderer stacks them. The luminance maps\n * add the two grids (clamped), so coverage, centroid and the profiles are of\n * the composite; dominance ranks bed and segment layers together by their raw\n * weights, bed layers keyed `bed:<key|index>`; text, motion and form list bed\n * layers first with the same prefix. Bed and segment are assumed to share\n * `units`/`referenceViewport`, as the renderer's shared canvas assumes. The\n * bed and segment seeds come from `segmentRenderSeed`/`bedRenderSeed`\n * (`./sequence`) — the same derivation `SequenceInstance` uses, chain roots\n * and zero-seed normalization included — so the composed frame matches what\n * the renderer actually draws at `T`, not just what the raw specs would show.\n * Without a bed this is `perceiveScene(segment, localT)` plus the `segment`\n * field. Intended as the payload behind a sequence-aware previewScene.\n *\n * Two known approximations, both accepted for a coarse, cheap, renderer-free\n * tool rather than fixed here:\n * - **The transition WINDOW isn't composed.** During a live `fade` or `morph`\n * (i.e. `localT < transition.dur`) the renderer also paints the outgoing\n * (or interpolating) segment, but this only ever perceives the segment\n * `resolveSegment` resolves to — call it at a `T` outside the transition's\n * `dur` for an accurate read. (Outside that window, a morph-chained\n * segment's entities and seed ARE correct — `segmentRenderSeed` already\n * resolves the chain root.) Composing the live window properly needs the\n * same capability-tier gate `SequenceInstance` uses to decide whether\n * `fade` even plays; this analytical path has no such context.\n * - **Ink composites onto the bed by addition, not by blend mode.** This\n * matches a plain `source-over`, opaque-ink segment (the common case), but\n * a segment layer with `blend: 'multiply'`/`'screen'`/etc. or partial alpha\n * composites directionally differently on the real canvas than adding\n * luminance values ever can (`multiply` darkens; addition only brightens).\n * The per-cell grids don't retain per-layer blend/alpha to composite\n * correctly at this resolution.\n */\nexport function perceiveSequenceFrame(seq: IdleSequence, T: number, opts: PerceiveSequenceOptions = {}): SequenceFramePerception {\n const { releasedBelow, ...gridOpts } = opts;\n const r = resolveSegment(seq, T, { releasedBelow });\n const seg = seq.segments[r.index]!;\n const segment: SequenceFramePerception['segment'] = { index: r.index, key: seg.key, localT: r.localT, ...(r.held ? { held: true } : {}) };\n const segOpts: LuminanceGridOptions = { ...gridOpts, t: r.localT, seed: gridOpts.seed ?? segmentRenderSeed(seq, r.index) };\n if (!seq.bed) return { ...perceiveScene(seg.scene, segOpts), segment, bed: false };\n\n const bedOpts: LuminanceGridOptions = { ...gridOpts, t: T, seed: gridOpts.seed ?? bedRenderSeed(seq) };\n const viewport = gridOpts.viewport ?? { width: 1920, height: 1080 };\n // The segment's ink alone: a black ground contributes nothing to the sum,\n // and no ghosting — a transparent child ignores it, as the renderer does.\n const ink: SaverSpec = { ...seg.scene, background: { type: 'solid', color: '#000000' } };\n delete ink.ghosting;\n // For contrast, ink is judged against what is actually behind it: the bed.\n const inkOverBed: SaverSpec = { ...ink, background: seq.bed.background ?? { type: 'solid', color: '#05050a' } };\n\n const bedGrid = luminanceGrid(seq.bed, bedOpts);\n const inkGrid = luminanceGrid(ink, segOpts);\n const cells = bedGrid.cells.map((v, i) => Math.min(1, v + inkGrid.cells[i]!));\n const grid = finishGrid(bedGrid.cols, bedGrid.rows, cells, bedGrid.background, bedGrid.backgroundCells);\n\n const bedLayers = seq.bed.layers.length;\n const dominance = rankDominance([\n ...rawDominance(seq.bed, bedOpts).map((d) => ({ ...d, key: bedKey(d.key, d.layerIndex) })),\n ...rawDominance(inkOverBed, segOpts).map((d) => ({ ...d, layerIndex: d.layerIndex + bedLayers })),\n ]);\n const shift = <X extends { layerIndex: number }>(x: X): X => ({ ...x, layerIndex: x.layerIndex + bedLayers });\n const prefix = <X extends { layerIndex: number; key: string | undefined }>(x: X): X => ({ ...x, key: bedKey(x.key, x.layerIndex) });\n\n return {\n t: r.localT,\n braille: renderBrailleMap(grid),\n density: renderDensityMap(grid),\n coverage: grid.coverage,\n meanLuminance: grid.meanLuminance,\n centroid: grid.centroid,\n rowProfile: grid.rowProfile,\n colProfile: grid.colProfile,\n dominance,\n motion: [...motionStats(seq.bed, bedOpts).map(prefix), ...motionStats(ink, segOpts).map(shift)],\n form: [...layerCohesion(seq.bed, bedOpts).map(prefix), ...layerCohesion(ink, segOpts).map(shift)],\n text: [...textSprites(seq.bed, bedOpts).map(prefix), ...textSprites(ink, segOpts).map(shift)],\n // The segment's sprite mass over the bed's plate — what the screen shows\n // in front of the bed. The bed's own sprites are a slow constant beneath.\n colour: sceneColour(inkOverBed, segOpts),\n advisories: [\n ...adviseSpec(seq.bed, viewport, { t: T, seed: bedOpts.seed }).map((w) => ({ ...w, path: `bed.${w.path}` })),\n // inkOverBed's layers are the segment's (seed: segOpts.seed) but its\n // background is the bed's (seq.bed.background) — a field there must be\n // sampled with the bed's own seed, or a `role: 'read'` legibility\n // advisory checks terrain that isn't what's actually behind the ink.\n // `?? 42`: inkOverBed.seed is the SEGMENT's raw seed field (it's `ink`\n // spread first), so adviseSpec's own `backgroundSeed ?? seed` fallback\n // would substitute the segment's seed, not the bed's, if bedOpts.seed\n // were left undefined — 42 is the same default `luminanceGrid` (and\n // every other field seed fallback) converges on.\n ...adviseSpec(inkOverBed, viewport, { t: r.localT, seed: segOpts.seed, backgroundSeed: bedOpts.seed ?? 42 }),\n ],\n segment,\n bed: true,\n };\n}\n","import { createRng } from '@idle-screens/core';\nimport { polygonArea, polygonPoints } from './shapes';\nimport { buildEntities, entityScales, linkEdges, linkMaxDistPx, positionAt } from './simulate';\nimport type { FinishSpec, SaverSpec } from './types';\n\nexport interface LayerSnapshot {\n key: string | undefined;\n count: number;\n centroid: { x: number; y: number };\n coverage: number;\n meanAlpha: number;\n linksDrawn: number | null;\n linksExpected: number | null;\n connectedComponents: number | null;\n isolatedNodes: number | null;\n}\n\nexport interface SceneSnapshot {\n t: number;\n viewport: { w: number; h: number };\n layers: LayerSnapshot[];\n warnings: string[];\n}\n\nexport interface SceneDescription {\n /** `finish` is present only when the spec declares one — a print screen the luminance numbers do not include. */\n spec: { id: string; label: string; units: string; finish?: FinishSpec };\n snapshots: SceneSnapshot[];\n}\n\n/**\n * Deterministic scene analysis at one or more time values. Reuses `buildEntities`\n * and `linkPairs` — no render needed. Returns structured data a non-vision model\n * can use to understand what a spec looks like when rendered.\n */\nexport function describeScene(\n spec: SaverSpec,\n options: {\n viewport?: { width: number; height: number };\n seed?: number;\n times?: number[];\n } = {},\n): SceneDescription {\n const { width: w, height: h } = options.viewport ?? { width: 1920, height: 1080 };\n const seed = options.seed ?? spec.seed ?? 42;\n const times = options.times ?? [0, 5000, 15000];\n const { scale, countScale } = entityScales(spec, w, h);\n\n const rng = createRng(seed);\n const builtLayers = spec.layers.map((layer) => ({\n layer,\n entities: buildEntities(layer, rng, w, h, scale, countScale),\n }));\n\n const snapshots: SceneSnapshot[] = times.map((t) => {\n const layerSnapshots: LayerSnapshot[] = builtLayers.map(({ layer, entities }) => {\n const positions = entities.map((e) => positionAt(e, t, w, h));\n const cx = positions.length > 0 ? positions.reduce((s, p) => s + p.x, 0) / positions.length : 0;\n const cy = positions.length > 0 ? positions.reduce((s, p) => s + p.y, 0) / positions.length : 0;\n\n // Coverage: fraction of viewport area covered by entity bounding circles\n let pixArea = 0;\n for (const e of entities) {\n const r = e.size / 2;\n pixArea += layer.sprite.kind === 'circle'\n ? Math.PI * r * r\n : layer.sprite.kind === 'polygon'\n ? polygonArea(polygonPoints(layer.sprite, r))\n : e.size * e.size;\n }\n const coverage = pixArea / (w * h);\n const meanAlpha = entities.length > 0\n ? entities.reduce((s, e) => s + e.alpha, 0) / entities.length\n : 0;\n\n // Link analysis\n let linksDrawn: number | null = null;\n let linksExpected: number | null = null;\n let connectedComponents: number | null = null;\n let isolatedNodes: number | null = null;\n if (layer.links) {\n const n = entities.length;\n const pairs = linkEdges(layer.links, positions, linkMaxDistPx(layer.links, scale), layer.wrap !== false, w, h)\n .map(({ i, j }) => [i, j] as const);\n linksDrawn = pairs.length;\n // A chain wires every entity to the next whatever the distance, so its\n // expectation is the chain itself, not k-nearest.\n linksExpected = layer.links.mode === 'chain'\n ? Math.max(0, n - 1) + (layer.links.closed && n > 2 ? 1 : 0)\n : Math.min(n * (layer.links.k ?? 1), n * (n - 1) / 2);\n // Connected components via union-find\n const parent = Array.from({ length: entities.length }, (_, i) => i);\n const find = (x: number): number => {\n while (parent[x] !== x) { parent[x] = parent[parent[x]!]!; x = parent[x]!; }\n return x;\n };\n for (const [a, b] of pairs) {\n const ra = find(a); const rb = find(b);\n if (ra !== rb) parent[ra] = rb;\n }\n const roots = new Set(entities.map((_, i) => find(i)));\n connectedComponents = roots.size;\n // Isolated = nodes with zero edges\n const degree = new Uint16Array(entities.length);\n for (const [a, b] of pairs) { degree[a]!++; degree[b]!++; }\n isolatedNodes = degree.filter((d) => d === 0).length;\n }\n\n return {\n key: layer.key,\n count: entities.length,\n centroid: { x: +(cx / w).toFixed(3), y: +(cy / h).toFixed(3) },\n coverage: +coverage.toFixed(4),\n meanAlpha: +meanAlpha.toFixed(3),\n linksDrawn,\n linksExpected,\n connectedComponents,\n isolatedNodes,\n };\n });\n\n // Warnings derived from the numbers\n const warnings: string[] = [];\n for (const ls of layerSnapshots) {\n const label = ls.key ?? `layer`;\n if (ls.coverage * ls.meanAlpha < 0.0005) {\n warnings.push(`${label}: effectively invisible (coverage×alpha=${(ls.coverage * ls.meanAlpha).toFixed(5)})`);\n }\n if (ls.linksDrawn !== null && ls.linksExpected !== null && ls.linksExpected > 0) {\n const ratio = ls.linksDrawn / ls.linksExpected;\n if (ratio < 0.1) {\n warnings.push(`${label}: link starvation — ${ls.linksDrawn}/${ls.linksExpected} edges formed`);\n }\n }\n if (ls.isolatedNodes !== null && ls.count > 0 && ls.isolatedNodes / ls.count > 0.5) {\n warnings.push(`${label}: ${ls.isolatedNodes}/${ls.count} nodes isolated — graph is disconnected`);\n }\n }\n\n return { t, viewport: { w, h }, layers: layerSnapshots, warnings };\n });\n\n return {\n spec: { id: spec.id, label: spec.label, units: spec.units ?? 'viewport', ...(spec.finish ? { finish: spec.finish } : {}) },\n snapshots,\n };\n}\n","import type { SaverSpec } from '../types';\n\n/**\n * Reproduces the hand-coded Fish Aquarium saver as pure DATA — the discriminating test\n * that the schema is actually expressive: two layers (fish drifting both ways at varied\n * speeds with a bob + flip, over a gradient with a seafloor band; bubbles rising with sway).\n */\nexport const AQUARIUM_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'aquarium',\n label: 'Aquarium',\n seed: 42,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#0a3a52' },\n { at: 0.6, color: '#062534' },\n { at: 1, color: '#02141d' },\n ],\n band: { color: '#0b1a12', height: 0.02222 },\n },\n layers: [\n {\n count: 14,\n sprite: { kind: 'emoji', glyphs: ['🐟', '🐠', '🐡', '🦈', '🐙'] },\n size: [0.03148, 0.06667],\n motion: { type: 'drift', speed: [0.02778, 0.1019], bidirectional: true, bob: 0.005556 },\n flip: true,\n },\n {\n count: 22,\n sprite: { kind: 'circle', radius: [0.001852, 0.006481], color: '#c8ebff' },\n motion: { type: 'rise', speed: [0.02222, 0.07222], sway: 0.007407 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Aurora Borealis: the \"fake fluid\" recipe — showcases `wander` motion (harmonic\n * drift) with high `coherence` so the curtain undulates as one body, `pulse.wave`\n * (a traveling shimmer across the star field), weighted palettes, additive blend,\n * and `ghosting` smearing the soft glows into continuous curtains of light.\n */\nexport const AURORA_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'aurora',\n label: 'Aurora',\n seed: 66,\n motionIntensity: 'calm',\n ghosting: 0.85,\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#02030d' },\n { at: 0.65, color: '#050a18' },\n { at: 1, color: '#0a1220' },\n ],\n drift: { period: 40000, amount: 0.1 },\n },\n layers: [\n {\n key: 'stars',\n count: 110,\n sprite: { kind: 'circle', radius: [0.0005, 0.0015], color: '#e8ecff', soft: true },\n motion: { type: 'static' },\n region: { y: [0, 0.75] },\n alpha: [0.2, 0.6],\n // A slow shimmer travels across the sky instead of stars twinkling independently.\n pulse: { amp: 0.25, period: 6000, wave: { wavelength: 0.5, angle: 15 } },\n },\n {\n key: 'curtain-green',\n count: 100,\n sprite: {\n kind: 'circle',\n radius: [0.055, 0.11],\n color: '#1fd68a',\n soft: true,\n colors: ['#1fd68a', '#2ee6c8', '#4bd1ff'],\n colorWeights: [5, 2, 1],\n },\n motion: { type: 'wander', speed: [0.004, 0.012], angle: 0, meander: 0.13, coherence: 0.7 },\n region: { y: [0.1, 0.42] },\n alpha: [0.04, 0.1],\n blend: 'lighter',\n grow: { amp: 0.25, period: 9000 },\n },\n {\n key: 'curtain-violet',\n count: 60,\n sprite: {\n kind: 'circle',\n radius: [0.045, 0.09],\n color: '#8d5bff',\n soft: true,\n colors: ['#8d5bff', '#d14bff', '#ff4bd8'],\n colorWeights: [4, 1.5, 0.5],\n },\n motion: { type: 'wander', speed: [0.003, 0.01], angle: 180, meander: 0.1, coherence: 0.55 },\n region: { y: [0.04, 0.28] },\n alpha: [0.03, 0.08],\n blend: 'lighter',\n grow: { amp: 0.3, period: 12000 },\n },\n {\n key: 'fireflies',\n count: 14,\n sprite: { kind: 'circle', radius: [0.001, 0.003], color: '#b8ffe1', soft: true },\n motion: { type: 'wander', speed: [0.006, 0.02], meander: 0.06 },\n region: { y: [0.55, 0.95] },\n alpha: [0.2, 0.55],\n pulse: { amp: 0.3, period: 3500 },\n blend: 'lighter',\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Comet Shower: showcases trails (afterglow behind moving entities) and background\n * drift (gradient stops breathing slowly). Three layers: a static star field, fast\n * comets with long trails, and slow fireflies with short trails and pulse.\n */\nexport const COMETS_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'comets',\n label: 'Comet Shower',\n seed: 42,\n motionIntensity: 'moderate',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#0a0015' },\n { at: 0.5, color: '#0d1b2a' },\n { at: 1, color: '#1b0a2e' },\n ],\n drift: { period: 25000, amount: 0.12 },\n },\n layers: [\n {\n key: 'stars',\n count: 120,\n sprite: { kind: 'circle', radius: [0.000463, 0.001852], color: '#ffffff', soft: true },\n motion: { type: 'static' },\n alpha: [0.3, 0.7],\n pulse: { amp: 0.15, period: 3000 },\n },\n {\n key: 'comets',\n count: 8,\n sprite: { kind: 'circle', radius: [0.002778, 0.007407], color: '#88ccff', soft: true },\n motion: { type: 'drift', speed: [0.07407, 0.1852], angle: 225 },\n alpha: [0.7, 1],\n blend: 'lighter',\n trail: { length: 1500, fade: 1 },\n },\n {\n key: 'fireflies',\n count: 20,\n sprite: { kind: 'circle', radius: [0.001852, 0.00463], color: '#ffdd44', soft: true },\n motion: { type: 'drift', speed: [0.009259, 0.02778], bidirectional: true, bob: 0.01852 },\n alpha: [0.4, 0.8],\n pulse: { amp: 0.3, period: 2000 },\n blend: 'lighter',\n trail: { length: 800 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Constellation: drifting stars connected by faint k-nearest links. Exercises\n * colors[] (multi-hued stars), links (k-nearest neighbor lines), and cycle\n * (emoji asterisms rotate glyphs). Stars are soft circles in viewport units.\n */\nexport const CONSTELLATION_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'constellation',\n label: 'Constellation',\n seed: 73,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#020212' },\n { at: 0.5, color: '#050520' },\n { at: 1, color: '#0a0830' },\n ],\n },\n layers: [\n // Distant static stars (no links, just atmosphere)\n {\n count: 100,\n sprite: { kind: 'circle', radius: [0.0009259, 0.002778], color: '#667799', colors: ['#8899cc', '#99aadd', '#aabbee', '#7788aa'] },\n alpha: [0.2, 0.7],\n pulse: { amp: 0.2, period: 3000 },\n motion: { type: 'static' },\n },\n // Connected constellation nodes — slow drift, linked\n {\n key: 'nodes',\n count: 40,\n sprite: { kind: 'circle', radius: [0.001852, 0.00463], color: '#88aaff', colors: ['#88aaff', '#aaccff', '#ffcc88', '#ff8866'], soft: true },\n alpha: [0.5, 0.9],\n blend: 'lighter',\n motion: { type: 'drift', speed: [0.001852, 0.007407], bidirectional: true, bob: 0.002778 },\n links: { k: 3, maxDist: 0.1852, alpha: 0.15, width: 0.000463 },\n },\n // Cycling asterism markers\n {\n count: 6,\n sprite: { kind: 'emoji', glyphs: ['✦', '✧', '⋆', '∗'], cycle: { period: 2000 } },\n size: [0.01296, 0.02037],\n alpha: [0.4, 0.7],\n motion: { type: 'drift', speed: [0.0009259, 0.003704], bidirectional: true },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Control Center — VIREO-9, Trans-Lunar Relay Operations.\n *\n * A mission-control WALL BOARD, laid out the way real ops rooms lay them out:\n * framed zones with a clear reading order, one hero display (the orbital\n * plot), dense-but-calm peripheral telemetry, and a boot sequence when the\n * board comes up. The fiction: a small relay station somewhere past GEO,\n * mid-shift, tracking a five-craft fleet (named for this library's own\n * savers — the station runs our little universe).\n *\n * Composed against the validator's 36-layer ceiling deliberately — every\n * layer earns its slot. Schema exercises: grid `layout` LED wall with a\n * traveling `pulse.wave`, `orbit` motion with `trail`s and chain `links`\n * (the relay web between the fleet), `ring` orbit guides, wave-phased rect\n * meters, staged `life` boots per zone. Every reading is keyed so an agent\n * can steer the fiction live (`signal-value`, `feed-1`, `alert`, ...).\n */\nexport const DASHBOARD_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'dev-dashboard',\n label: 'Control Center',\n seed: 256,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#05070d' },\n { at: 0.55, color: '#080b14' },\n { at: 1, color: '#0a0d18' },\n ],\n },\n layers: [\n // ---- ambient: the LED wall behind everything ----\n {\n key: 'led-wall',\n count: 240,\n sprite: { kind: 'circle', radius: [0.0007, 0.0011], color: '#22344c' },\n alpha: [0.04, 0.1],\n layout: { type: 'grid', columns: 24, jitter: 0.1 },\n pulse: { amp: 0.3, period: 6200, wave: { wavelength: 0.4, angle: 24 } },\n motion: { type: 'static' },\n },\n // ---- frame chrome (boots first) ----\n {\n key: 'rule-header', count: 1,\n position: { x: 0.5, y: 0.085 },\n sprite: { kind: 'rect', width: [0.93, 0.93], aspect: [0.0012, 0.0012], color: '#24384f' },\n alpha: [0.8, 0.8],\n motion: { type: 'static' },\n life: { enter: 100, fade: 400 },\n },\n {\n key: 'rule-footer', count: 1,\n position: { x: 0.5, y: 0.915 },\n sprite: { kind: 'rect', width: [0.93, 0.93], aspect: [0.0012, 0.0012], color: '#24384f' },\n alpha: [0.8, 0.8],\n motion: { type: 'static' },\n life: { enter: 100, fade: 400 },\n },\n {\n key: 'rule-col-left', count: 1,\n position: { x: 0.265, y: 0.5 },\n sprite: { kind: 'rect', width: [0.0009, 0.0009], aspect: [620, 620], color: '#1c2c40' },\n alpha: [0.7, 0.7],\n motion: { type: 'static' },\n life: { enter: 100, fade: 400 },\n },\n {\n key: 'rule-col-right', count: 1,\n position: { x: 0.645, y: 0.5 },\n sprite: { kind: 'rect', width: [0.0009, 0.0009], aspect: [620, 620], color: '#1c2c40' },\n alpha: [0.7, 0.7],\n motion: { type: 'static' },\n life: { enter: 100, fade: 400 },\n },\n // ---- header band ----\n {\n key: 'title', count: 1,\n position: { x: 0.035, y: 0.052 },\n sprite: { kind: 'text', strings: ['VIREO-9 · TRANS-LUNAR RELAY · OPS WALL 03'], color: '#7f93ab',\n font: \"600 13px 'SF Mono', monospace\", align: 'left' },\n motion: { type: 'static' },\n life: { enter: 200, fade: 600 },\n },\n {\n key: 'clock', count: 1,\n position: { x: 0.5, y: 0.058 },\n sprite: { kind: 'text', strings: ['04:17:26 UTC'], color: '#c8d4e4',\n font: \"600 20px 'SF Mono', monospace\", align: 'center' },\n motion: { type: 'static' },\n life: { enter: 200, fade: 600 },\n },\n {\n key: 'status', count: 1,\n position: { x: 0.965, y: 0.052 },\n sprite: { kind: 'text', strings: ['● UPLINK LOCKED · WATCH C'], color: '#46d17a',\n font: \"bold 11px 'SF Mono', monospace\", align: 'right' },\n pulse: { amp: 0.18, period: 2600 },\n motion: { type: 'static' },\n life: { enter: 200, fade: 600 },\n },\n // ---- left column: arrays (boots second) ----\n {\n key: 'dish1', count: 1,\n position: { x: 0.035, y: 0.148 },\n sprite: { kind: 'text', strings: ['DSA-1 EAST AZ 214.6° EL 38.2°'], color: '#9fb2c8',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 700, fade: 600 },\n },\n {\n key: 'dish1-bars', count: 14,\n sprite: { kind: 'rect', width: [0.0038, 0.0038], aspect: [0.5, 2.6], color: '#2ee6c8' },\n alpha: [0.3, 0.65],\n layout: { type: 'grid', columns: 14 },\n region: { x: [0.035, 0.15], y: [0.183, 0.203] },\n pulse: { amp: 0.42, period: 1500, wave: { wavelength: 0.09, angle: 0 } },\n motion: { type: 'static' },\n life: { enter: 700, fade: 600 },\n },\n {\n key: 'dish2', count: 1,\n position: { x: 0.035, y: 0.243 },\n sprite: { kind: 'text', strings: ['DSA-2 WEST AZ 097.1° EL 61.7°'], color: '#9fb2c8',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 850, fade: 600 },\n },\n {\n key: 'dish2-bars', count: 14,\n sprite: { kind: 'rect', width: [0.0038, 0.0038], aspect: [0.5, 2.2], color: '#44aaff' },\n alpha: [0.3, 0.6],\n layout: { type: 'grid', columns: 14 },\n region: { x: [0.035, 0.15], y: [0.278, 0.298] },\n pulse: { amp: 0.4, period: 1900, wave: { wavelength: 0.11, angle: 0 } },\n motion: { type: 'static' },\n life: { enter: 850, fade: 600 },\n },\n {\n key: 'dish3', count: 1,\n position: { x: 0.035, y: 0.338 },\n sprite: { kind: 'text', strings: ['DSA-3 POLAR AZ 002.4° EL 12.9° △ WIND'], color: '#5d7089',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1000, fade: 600 },\n },\n {\n key: 'dish3-bars', count: 14,\n sprite: { kind: 'rect', width: [0.0038, 0.0038], aspect: [0.4, 1.1], color: '#5d7089' },\n alpha: [0.2, 0.4],\n layout: { type: 'grid', columns: 14 },\n region: { x: [0.035, 0.15], y: [0.373, 0.393] },\n pulse: { amp: 0.3, period: 2600, wave: { wavelength: 0.14, angle: 0 } },\n motion: { type: 'static' },\n life: { enter: 1000, fade: 600 },\n },\n {\n key: 'dish-leds', count: 3,\n sprite: { kind: 'circle', radius: [0.004, 0.004], color: '#46d17a' },\n alpha: [0.9, 0.9],\n layout: { type: 'grid', columns: 1 },\n region: { x: [0.238, 0.246], y: [0.15, 0.35] },\n pulse: { amp: 0.25, period: 2100 },\n motion: { type: 'static' },\n life: { enter: 1000, fade: 600 },\n },\n // carrier + doppler + station env\n {\n key: 'carrier-wave', count: 30,\n sprite: { kind: 'rect', width: [0.0032, 0.0032], aspect: [0.4, 3.6], color: '#2ee6c8' },\n alpha: [0.25, 0.6],\n layout: { type: 'grid', columns: 30 },\n region: { x: [0.035, 0.245], y: [0.47, 0.5] },\n pulse: { amp: 0.5, period: 2100, wave: { wavelength: 0.16, angle: 0 } },\n motion: { type: 'static' },\n life: { enter: 1150, fade: 600 },\n },\n {\n key: 'doppler', count: 1,\n position: { x: 0.035, y: 0.535 },\n sprite: { kind: 'text', strings: ['CARRIER X-BAND · DOPPLER +2.114 kHz · DRIFT 0.03'], color: '#9fb2c8',\n font: \"10px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1150, fade: 600 },\n },\n {\n key: 'env-line', count: 1,\n position: { x: 0.035, y: 0.6 },\n sprite: { kind: 'text', strings: ['STATION · PWR 28.1 V · THERM 312 K · GYRO NOM · PROP 81%'], color: '#5d7089',\n font: \"10px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1300, fade: 600 },\n },\n // ---- center: the orbital plot (boots third) ----\n {\n key: 'moon', count: 1,\n position: { x: 0.455, y: 0.4 },\n sprite: { kind: 'circle', radius: [0.028, 0.028], color: '#8fa3bd', soft: true },\n alpha: [0.9, 0.9],\n motion: { type: 'static' },\n life: { enter: 1200, fade: 700 },\n },\n {\n key: 'orbit-guides', count: 3,\n // All three guides pin to the plot centre; the seeded radius range\n // spreads them into concentric orbits (`position` is count:1-only).\n region: { x: [0.455, 0.455], y: [0.4, 0.4] },\n sprite: { kind: 'ring', radius: [0.075, 0.185], color: '#1e3a52', width: 0.0011 },\n alpha: [0.55, 0.55],\n motion: { type: 'static' },\n life: { enter: 1200, fade: 700 },\n },\n {\n key: 'fleet',\n count: 5,\n sprite: { kind: 'circle', radius: [0.0045, 0.0065], color: '#2ee6c8',\n colors: ['#2ee6c8', '#44aaff', '#ffd166', '#aa88ff', '#ff9f43'] },\n alpha: [0.85, 0.95],\n blend: 'lighter',\n motion: { type: 'orbit', speed: [4, 11], radius: [0.075, 0.185], center: { x: 0.455, y: 0.4 } },\n trail: { length: 9, fade: 0.75 },\n // The relay web: each craft holds a comm chain to its neighbours.\n links: { k: 2, maxDist: 0.5, color: '#2ee6c8', alpha: 0.2, width: 0.0012, mode: 'chain' },\n life: { enter: 1350, fade: 700 },\n },\n {\n key: 'fleet-legend', count: 1,\n position: { x: 0.455, y: 0.63 },\n sprite: { kind: 'text', strings: ['TRACKING 5 · KESTREL TIDE-2 LIMELIGHT CATWALK-1 SLIPSTREAM'], color: '#5d7089',\n font: \"9px 'SF Mono', monospace\", align: 'center', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1500, fade: 700 },\n },\n // pass schedule under the plot\n {\n key: 'pass-label', count: 1,\n position: { x: 0.3, y: 0.69 },\n sprite: { kind: 'text', strings: ['PASS SCHEDULE'], color: '#41536b',\n font: \"9px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1650, fade: 600 },\n },\n {\n key: 'pass-1', count: 1,\n position: { x: 0.3, y: 0.72 },\n sprite: { kind: 'text', strings: ['04:41 CATWALK-1 ACQUIRE · DSA-1 ▲ 12 MIN'], color: '#c8d4e4',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1650, fade: 600 },\n },\n {\n key: 'pass-2', count: 1,\n position: { x: 0.3, y: 0.757 },\n sprite: { kind: 'text', strings: ['05:03 TIDE-2 OCCULT EXIT · DSA-2'], color: '#7f93ab',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1750, fade: 600 },\n },\n {\n key: 'pass-3', count: 1,\n position: { x: 0.3, y: 0.794 },\n sprite: { kind: 'text', strings: ['05:47 KESTREL RANGING · DSA-1+2'], color: '#7f93ab',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1850, fade: 600 },\n },\n // ---- right column: telemetry (boots fourth) ----\n {\n key: 'signal-label', count: 1,\n position: { x: 0.665, y: 0.115 },\n sprite: { kind: 'text', strings: ['PRIMARY CARRIER · CATWALK-1'], color: '#41536b',\n font: \"9px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1700, fade: 600 },\n },\n {\n key: 'signal-value', count: 1,\n position: { x: 0.665, y: 0.14 },\n sprite: { kind: 'text', strings: ['-112.4 dBm'], color: '#ffd166',\n font: \"bold 30px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1700, fade: 600 },\n },\n {\n key: 'telemetry-row', count: 1,\n position: { x: 0.665, y: 0.215 },\n sprite: { kind: 'text', strings: ['RANGE 1.28 LS DOWNLINK 2.048 Mb/s BUFFER 38%'], color: '#9fb2c8',\n font: \"11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1800, fade: 600 },\n },\n // event log\n {\n key: 'feed-1', count: 1,\n position: { x: 0.665, y: 0.3 },\n sprite: { kind: 'text', strings: ['04:15:02 DSA-1 LOCK RE-ACQUIRED'], color: '#9fb2c8',\n font: \"10px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 1950, fade: 600 },\n },\n {\n key: 'feed-2', count: 1,\n position: { x: 0.665, y: 0.334 },\n sprite: { kind: 'text', strings: ['04:12:47 CATWALK-1 WHEEL DESAT OK'], color: '#7f93ab',\n font: \"10px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 2050, fade: 600 },\n },\n {\n key: 'feed-3', count: 1,\n position: { x: 0.665, y: 0.368 },\n sprite: { kind: 'text', strings: ['04:09:31 RANGING RESIDUAL 0.4 m'], color: '#5d7089',\n font: \"10px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 2150, fade: 600 },\n },\n // alert + relay load\n {\n key: 'alert', count: 1,\n position: { x: 0.665, y: 0.49 },\n sprite: { kind: 'text', strings: ['△ SOLAR FLUX ELEVATED — MONITORING'], color: '#ff9f43',\n font: \"bold 11px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n pulse: { amp: 0.22, period: 3400 },\n motion: { type: 'static' },\n life: { enter: 2450, fade: 600 },\n },\n {\n key: 'load-bars', count: 24,\n sprite: { kind: 'rect', width: [0.0042, 0.0042], aspect: [0.5, 3.2],\n color: '#aa88ff', colors: ['#aa88ff', '#44aaff', '#2ee6c8'], colorWeights: [2, 2, 3] },\n alpha: [0.3, 0.65],\n layout: { type: 'grid', columns: 24 },\n region: { x: [0.665, 0.965], y: [0.58, 0.615] },\n pulse: { amp: 0.45, period: 1800, wave: { wavelength: 0.12, angle: 0 } },\n motion: { type: 'static' },\n life: { enter: 2550, fade: 600 },\n },\n {\n key: 'load-note', count: 1,\n position: { x: 0.665, y: 0.65 },\n sprite: { kind: 'text', strings: ['RELAY LOAD · QUEUE 14 FRAMES · NOMINAL'], color: '#5d7089',\n font: \"10px 'SF Mono', monospace\", align: 'left', baseline: 'top' },\n motion: { type: 'static' },\n life: { enter: 2550, fade: 600 },\n },\n // ---- footer band ----\n {\n key: 'footer', count: 1,\n position: { x: 0.035, y: 0.95 },\n sprite: { kind: 'text', strings: ['NET STATE GREEN · 3 ARRAYS · 5 CARRIERS · DSN HANDOVER 23:34 · NEXT WINDOW 04:41:00'], color: '#41536b',\n font: \"9px 'SF Mono', monospace\", align: 'left' },\n motion: { type: 'static' },\n life: { enter: 2750, fade: 600 },\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Sparse Night — emptiness, declared as intent.\n * A star-grain field (radius under 0.001 — the rung FORMAT.md's ladder calls\n * texture, never the subject) over near-black, one faint linked pentagon as\n * the only figure, and a single satellite that flares for three seconds out of\n * every eighteen. Measured coverage sits around one percent, which `adviseSpec`\n * would flag as `sparse-scene` at every legal count — the spec's\n * `density: 'sparse'` declaration is the point of this example: it withholds\n * that advisory AND opts the scene into `density-mismatch` instead, so the\n * emptiness is a claim the perception API checks rather than a gap it nags\n * about. Before `density` shipped, restraint like this could not pass advise\n * clean; the one-mark house style sat at the suite floor for exactly this\n * reason.\n */\nexport const SPARSE_NIGHT_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"sparse-night\",\n label: \"Sparse Night\",\n seed: 101,\n motionIntensity: \"calm\",\n density: \"sparse\",\n background: { type: \"solid\", color: \"#02030a\" },\n layers: [\n {\n key: \"grain\",\n count: 110,\n sprite: {\n kind: \"circle\",\n radius: [0.0003, 0.0009],\n color: \"#c9d4e6\",\n },\n motion: { type: \"static\" },\n alpha: [0.05, 0.3],\n pulse: { amp: 0.08, period: 7000 },\n },\n {\n key: \"figure\",\n count: 5,\n sprite: {\n kind: \"circle\",\n radius: [0.0016, 0.0022],\n color: \"#dfe8f2\",\n },\n motion: { type: \"drift\", speed: [0.0004, 0.0009] },\n alpha: [0.4, 0.7],\n region: { x: [0.36, 0.64], y: [0.32, 0.62] },\n links: {\n k: 2,\n maxDist: 0.09,\n color: \"#7f97b8\",\n alpha: 0.16,\n width: 0.0004,\n mode: \"chain\",\n closed: true,\n },\n },\n {\n key: \"satellite\",\n count: 1,\n sprite: {\n kind: \"circle\",\n radius: [0.0024, 0.0024],\n color: \"#e8b04a\",\n soft: true,\n },\n motion: { type: \"orbit\", speed: [3, 3], radius: [0.34, 0.4] },\n alpha: [0.85, 0.85],\n blend: \"lighter\",\n emit: { every: 18000, life: 3000, jitter: 0, grow: [0.5, 1.6] },\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Signal Board — the instrument panel, laid out by the format.\n * A 3×3 table of data bars with their labels in a matching table, one\n * monospace caption, and a phosphor sweep crossing the frame every ~90\n * seconds. The teaching layer is `layout: { type: 'table', columns: 3 }`:\n * nine bars and nine labels are TWO layers, not eighteen positioned blocks —\n * entity i reads `values[i]` / `strings[i]` in reading order, and each bar\n * draws `length × values[i] / max` from its cell. `values` are paint, so\n * `setParam(\"readout.sprite.values\", [...])` glides every bar at once, which\n * is the whole point of the shape: a live readout that never re-publishes.\n */\nexport const SIGNAL_BOARD_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"signal-board\",\n label: \"Signal Board\",\n seed: 707,\n motionIntensity: \"calm\",\n background: { type: \"solid\", color: \"#0d0b08\" },\n layers: [\n {\n key: \"readout\",\n count: 9,\n sprite: {\n kind: \"bar\",\n values: [62, 38, 84, 21, 55, 91, 44, 70, 29],\n max: 100,\n // Cell pitch is the table's authored `gap` (0.07), so a full-value\n // bar must stay under that or neighboring cells' bars overlap.\n // 0.06 leaves a hairline margin.\n length: 0.06,\n thickness: 0.013,\n color: \"#ffb000\",\n direction: \"right\",\n },\n motion: { type: \"static\" },\n layout: { type: \"table\", columns: 3, gap: 0.07 },\n region: { x: [0.1, 0.9], y: [0.34, 0.78] },\n alpha: [0.5, 0.62],\n },\n {\n key: \"labels\",\n count: 9,\n sprite: {\n kind: \"text\",\n strings: [\n \"A-01\",\n \"A-02\",\n \"A-03\",\n \"B-01\",\n \"B-02\",\n \"B-03\",\n \"C-01\",\n \"C-02\",\n \"C-03\",\n ],\n color: \"#b08a3a\",\n font: \"monospace\",\n align: \"left\",\n },\n motion: { type: \"static\" },\n size: [0.011, 0.011],\n layout: { type: \"table\", columns: 3, gap: 0.07 },\n region: { x: [0.1, 0.9], y: [0.28, 0.72] },\n alpha: [0.55, 0.55],\n },\n {\n key: \"caption\",\n count: 1,\n sprite: {\n kind: \"textBlock\",\n text: \"STATION 7 — QUIET HOURS\",\n maxWidth: 0.6,\n fontSize: 0.022,\n lineHeight: 1.4,\n align: \"left\",\n anchor: \"top-left\",\n font: \"bold monospace\",\n color: \"#c8862a\",\n },\n motion: { type: \"static\" },\n position: { x: 0.1, y: 0.14 },\n alpha: [0.8, 0.8],\n },\n {\n key: \"sweep\",\n count: 1,\n sprite: {\n kind: \"stroke\",\n length: [1.4, 1.4],\n points: [\n [-1, 0],\n [1, 0],\n ],\n width: 0.0016,\n color: \"#33ff66\",\n },\n motion: { type: \"drift\", speed: [0.012, 0.012], angle: 90 },\n alpha: [0.22, 0.22],\n blend: \"screen\",\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Phase Duet — three layers on one clock.\n * A grid of sixty dots ripples as a traveling wave (`pulse.wave`), three rings\n * swell, and one soft heart breathes — and none of them drift apart, because\n * all three declare the same `clock`. `clock` is the format's answer to\n * coincidence: without it, `pulse`, `grow` and `cycle` run on per-entity\n * seeded phases, so two layers with the same period never line up (they are\n * a room full of people, not a duet). With one shared `clock: { phase: 0,\n * rate: 1 }` they breathe in step and stay there — period ÷ rate must stay\n * ≥ 1000 ms, which is why every layer here runs a 6000 ms cycle.\n */\nexport const PHASE_DUET_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"phase-duet\",\n label: \"Phase Duet\",\n seed: 88,\n motionIntensity: \"calm\",\n background: {\n type: \"gradient\",\n stops: [\n { at: 0, color: \"#0a0f1c\" },\n { at: 0.6, color: \"#101b2e\" },\n { at: 1, color: \"#07141a\" },\n ],\n },\n layers: [\n {\n key: \"ripple\",\n count: 60,\n sprite: {\n kind: \"circle\",\n radius: [0.0018, 0.003],\n color: \"#6fd3c7\",\n colors: [\"#6fd3c7\", \"#9fb8d8\"],\n colorWeights: [2, 1],\n },\n motion: { type: \"static\" },\n layout: { type: \"grid\", columns: 10, jitter: 0 },\n alpha: [0.3, 0.55],\n pulse: { amp: 0.35, period: 6000, wave: { wavelength: 0.7, angle: 25 } },\n clock: { phase: 0, rate: 1 },\n },\n {\n key: \"rings\",\n count: 3,\n sprite: {\n kind: \"ring\",\n radius: [0.05, 0.09],\n width: 0.0012,\n color: \"#6fd3c7\",\n },\n motion: { type: \"static\" },\n alpha: [0.25, 0.35],\n blend: \"lighter\",\n grow: { amp: 0.5, period: 6000 },\n clock: { phase: 0, rate: 1 },\n },\n {\n key: \"heart\",\n count: 1,\n sprite: {\n kind: \"circle\",\n radius: [0.11, 0.11],\n color: \"#9fb8d8\",\n soft: true,\n },\n motion: { type: \"static\" },\n position: { x: 0.5, y: 0.5 },\n alpha: [0.22, 0.22],\n blend: \"lighter\",\n grow: { amp: 0.25, period: 6000 },\n clock: { phase: 0, rate: 1 },\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Web Work — a randomised graph that fades with distance.\n * Forty-four drifting nodes wired `mode: 'random'` (a fixed deterministic\n * wiring, not k-nearest — the difference is topology: nearest gives\n * crystalline clusters, random gives a web that crosses itself) with\n * `falloff: true`, so an edge's alpha fades toward `maxDist` instead of\n * popping in at the cutoff. The second layer is a row of `orient: true`\n * strokes: the mark's +x axis turns to follow the entity's heading, so each\n * one reads as a wind tick rather than a stamp. Both are the difference\n * between \"lines between dots\" and a drawing.\n */\nexport const WEB_WORK_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"web-work\",\n label: \"Web Work\",\n seed: 31,\n motionIntensity: \"calm\",\n background: { type: \"solid\", color: \"#04070c\" },\n layers: [\n {\n key: \"nodes\",\n count: 44,\n sprite: {\n kind: \"circle\",\n radius: [0.0018, 0.0034],\n color: \"#8fb4d8\",\n colors: [\"#8fb4d8\", \"#c9d8e6\"],\n colorWeights: [2, 1],\n },\n motion: {\n type: \"drift\",\n speed: [0.002, 0.006],\n angle: 0,\n bidirectional: true,\n },\n alpha: [0.45, 0.8],\n links: {\n k: 3,\n maxDist: 0.3,\n color: \"#5f7f9f\",\n alpha: 0.16,\n width: 0.0005,\n mode: \"random\",\n falloff: true,\n },\n },\n {\n key: \"flags\",\n count: 22,\n sprite: {\n kind: \"stroke\",\n length: [0.02, 0.045],\n points: [\n [-1, 0.2],\n [-0.2, -0.5],\n [0.6, -0.3],\n [1, 0.1],\n ],\n width: 0.0016,\n taper: true,\n orient: true,\n color: \"#6f93b8\",\n colors: [\"#6f93b8\", \"#9fb8d8\"],\n },\n motion: {\n type: \"drift\",\n speed: [0.01, 0.03],\n angle: 0,\n bidirectional: true,\n },\n alpha: [0.3, 0.6],\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Shard Fall — tumbling shapes and a passing shadow.\n * Two features nothing else here uses. `rotate` is STATIC per-entity rotation\n * (a range seeded per entity), which is not the same as `spin: [0, 0]` — a\n * zero spin speed renders the seeded start angle as 0, so \"tilted but not\n * turning\" was previously inexpressible; here the shards are thrown at\n * `rotate: [-180, 180]` AND tumbling on their own `spin` range, so no two\n * facets agree on an angle. The shadow layer demonstrates `blend:\n * 'multiply'`: two large soft discs darkening a pale plate as they wander,\n * which is how the format does shadow and silhouette — `lighter` adds light,\n * `multiply` removes it, and neither needs a sprite that looks like darkness.\n * The polygons use `points` (unit coordinates scaled by `radius`), which are\n * paint, so two shards with the same point count will morph into each other.\n */\nexport const SHARD_FALL_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"shard-fall\",\n label: \"Shard Fall\",\n seed: 214,\n motionIntensity: \"moderate\",\n background: {\n type: \"gradient\",\n stops: [\n { at: 0, color: \"#efe6d6\" },\n { at: 0.55, color: \"#e6d6bd\" },\n { at: 1, color: \"#d9c39f\" },\n ],\n },\n layers: [\n {\n key: \"shards\",\n count: 26,\n sprite: {\n kind: \"polygon\",\n points: [\n [-1, 0.35],\n [-0.25, -1],\n [0.85, -0.4],\n [0.4, 0.9],\n ],\n radius: [0.012, 0.03],\n color: \"#b4593a\",\n colors: [\"#b4593a\", \"#7f8a5e\", \"#5a6b7d\", \"#8a5a3c\"],\n colorWeights: [2, 2, 1, 2],\n },\n motion: { type: \"drift\", speed: [0.012, 0.032], angle: 90 },\n alpha: [0.85, 0.95],\n rotate: [-180, 180],\n spin: [-35, 35],\n },\n {\n key: \"shadows\",\n count: 2,\n sprite: {\n kind: \"circle\",\n radius: [0.18, 0.22],\n color: \"#5a4a34\",\n soft: true,\n },\n motion: {\n type: \"wander\",\n speed: [0.003, 0.005],\n meander: 0.04,\n coherence: 0.6,\n },\n alpha: [0.2, 0.28],\n blend: \"multiply\",\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Murmur — a flock with no birds in it.\n * Six hundred and twenty entities: two registers of streaks (260 each) on\n * harmonic `wander` with `coherence` near 1, so each layer folds and wheels as\n * one body, and a static grain layer behind them. Nothing here\n * interacts — no entity reads another's position — which is the trick the\n * format is built on: a shared harmonic set plus a wide speed range reads as\n * a murmuration while staying a pure function of (seed, t), so it replays\n * identically and seeks instantly. `density: 'dense'` is doing real work:\n * past 500 entities `adviseSpec` raises `dense-scene`, and the declaration\n * says the crowding is the subject rather than a mistake — while still opting\n * into `density-mismatch` if the scene ever measures as empty instead.\n */\nexport const MURMUR_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"murmur\",\n label: \"Murmur\",\n seed: 512,\n motionIntensity: \"moderate\",\n density: \"dense\",\n background: {\n type: \"gradient\",\n stops: [\n { at: 0, color: \"#151a26\" },\n { at: 0.5, color: \"#232c3d\" },\n { at: 1, color: \"#3a3f52\" },\n ],\n },\n layers: [\n {\n key: \"flock-a\",\n count: 260,\n sprite: {\n kind: \"streak\",\n length: [0.004, 0.012],\n width: 0.0012,\n color: \"#c9d4e6\",\n colors: [\"#c9d4e6\", \"#8fa6c4\"],\n colorWeights: [2, 1],\n },\n motion: {\n type: \"wander\",\n speed: [0.015, 0.06],\n meander: 0.05,\n coherence: 0.95,\n },\n alpha: [0.25, 0.6],\n blend: \"screen\",\n },\n {\n // The cap is 400 per layer, so a flock above it is two registers of the\n // same body — slightly different speed and length ranges read as depth.\n key: \"flock-b\",\n count: 260,\n sprite: {\n kind: \"streak\",\n length: [0.006, 0.014],\n width: 0.0012,\n color: \"#8fa6c4\",\n colors: [\"#8fa6c4\", \"#c9d4e6\"],\n colorWeights: [2, 1],\n },\n motion: {\n type: \"wander\",\n speed: [0.02, 0.05],\n meander: 0.045,\n coherence: 0.93,\n },\n alpha: [0.2, 0.5],\n blend: \"screen\",\n },\n {\n key: \"grain\",\n count: 100,\n sprite: { kind: \"circle\", radius: [0.0005, 0.0012], color: \"#c9d4e6\" },\n motion: { type: \"static\" },\n alpha: [0.06, 0.2],\n },\n ],\n};\n","import type { IdleSequence } from \"../types\";\n\n/**\n * Three Movements — one ground, three scenes, two kinds of transition.\n *\n * The sequence envelope, exercised end to end:\n *\n * - **bed.** A drifting field with a few motes, drawn under every segment on\n * the SEQUENCE clock — it does not reset at a boundary and a\n * `sequence.segment` steer cannot rewind it. That is the fix for the\n * boundary rewind every ambient sequence suffers: put the motion that must\n * be continuous in the bed, the slide content in the segments. (Segments\n * deliberately declare no `background`: over a bed it is never painted on\n * the web, and the validator warns `bed-hides-segment-background` — the\n * native tvOS player, which ignores the bed, will show them over black\n * until it learns the field. Prefer a bed the piece can survive without.)\n * - **morph + text crossfade.** Segments 1 → 2 are structural twins differing\n * only in colour and words, so the transition can MORPH: every numeric and\n * hex value glides over 2500 ms, and because the words differ and the\n * transition declares `text: 'crossfade'`, the outgoing caption fades under\n * the incoming one instead of switching whole-frame. Without the crossfade\n * declaration the morph would still glide — colour alone gives it a\n * `hasGlide` — just with the caption stepping on the first frame instead of\n * fading; the validator only says `morph-nothing-morphable` for a pair\n * whose differences are all values morph cannot glide — strings\n * (`textBlock.text` above all), booleans, mismatched arrays — which this\n * one isn't.\n * - **fade.** Segments 2 → 3 have nothing structurally in common, so a morph\n * is impossible and a `fade` is the honest transition: the outgoing scene\n * keeps animating on its own canvas for 3000 ms while the incoming one\n * fades up. The cost is two live segments during the window, which is why\n * the lowest capability tier degrades a fade to a cut\n * (`fade-degrades-on-low-tier` — informational, and this sequence keeps the\n * fade because the web and native players both honour it).\n * - **finish.** One grain-and-dither pass over the composed frame — bed,\n * segment and any fade together — the sequence-level screen no segment can\n * override.\n *\n * The final segment carries no duration, so it holds indefinitely; `loop` is\n * therefore false (`loop: true` is incompatible with a durationless segment).\n * `sync: 'mount'` is the default and the reason a joiner always sees movement\n * one: pre-roll semantics. An `epoch` sequence would instead start every\n * viewer at the room's shared clock — right for a wall of screens, wrong for\n * a piece that should start when you look at it.\n */\nexport const THREE_MOVEMENTS_SEQUENCE: IdleSequence = {\n format: \"idle-sequence\",\n schemaVersion: 1,\n id: \"three-movements\",\n label: \"Three Movements\",\n seed: 404,\n loop: false,\n sync: \"mount\",\n finish: { grain: 0.3, dither: 0.12 },\n bed: {\n schemaVersion: 1,\n id: \"three-movements-bed\",\n label: \"Three Movements — bed\",\n background: {\n type: \"field\",\n scale: 2.0,\n octaves: 3,\n warp: 0.4,\n quantize: 0,\n bands: [\"#0a0d18\", \"#141c2e\", \"#233046\"],\n drift: { period: 60000, amount: 0.25 },\n },\n layers: [\n {\n key: \"motes\",\n count: 12,\n sprite: {\n kind: \"circle\",\n radius: [0.0012, 0.003],\n color: \"#9fb8d8\",\n soft: true,\n },\n motion: { type: \"drift\", speed: [0.002, 0.006], angle: 90 },\n alpha: [0.1, 0.25],\n },\n ],\n },\n segments: [\n {\n key: \"cold-open\",\n duration: 8000,\n transition: { type: \"morph\", dur: 2500, text: \"crossfade\" },\n scene: {\n schemaVersion: 1,\n id: \"three-movements-cold-open\",\n label: \"Cold Open\",\n seed: 11,\n layers: [\n {\n key: \"caption\",\n count: 1,\n sprite: {\n kind: \"textBlock\",\n text: \"COLD OPEN.\\nThe room before anyone arrives.\",\n maxWidth: 0.6,\n fontSize: 0.028,\n lineHeight: 1.5,\n align: \"left\",\n anchor: \"top-left\",\n font: \"monospace\",\n color: \"#9fb8d8\",\n opacity: 0.9,\n reveal: {\n progress: 1,\n mode: \"typewriter\",\n speed: 12,\n caret: { blink: 1.1 },\n },\n },\n motion: { type: \"static\" },\n position: { x: 0.1, y: 0.4 },\n alpha: [0.9, 0.9],\n },\n {\n key: \"sparks\",\n count: 30,\n sprite: {\n kind: \"circle\",\n radius: [0.0012, 0.0026],\n color: \"#c9d8e6\",\n },\n motion: { type: \"static\" },\n alpha: [0.15, 0.45],\n pulse: { amp: 0.12, period: 6000 },\n },\n ],\n },\n },\n {\n key: \"kindle\",\n duration: 9000,\n transition: { type: \"fade\", dur: 3000 },\n scene: {\n schemaVersion: 1,\n id: \"three-movements-kindle\",\n label: \"Kindle\",\n seed: 12,\n layers: [\n {\n key: \"caption\",\n count: 1,\n sprite: {\n kind: \"textBlock\",\n text: \"KINDLE.\\nOne lamp, and then another.\",\n maxWidth: 0.6,\n fontSize: 0.028,\n lineHeight: 1.5,\n align: \"left\",\n anchor: \"top-left\",\n font: \"monospace\",\n color: \"#e8b878\",\n opacity: 0.9,\n reveal: {\n progress: 1,\n mode: \"typewriter\",\n speed: 12,\n caret: { blink: 1.1 },\n },\n },\n motion: { type: \"static\" },\n position: { x: 0.1, y: 0.4 },\n alpha: [0.9, 0.9],\n },\n {\n key: \"sparks\",\n count: 30,\n sprite: {\n kind: \"circle\",\n radius: [0.0012, 0.0026],\n color: \"#e8b878\",\n },\n motion: { type: \"static\" },\n alpha: [0.15, 0.45],\n pulse: { amp: 0.12, period: 6000 },\n },\n ],\n },\n },\n {\n key: \"dusk\",\n scene: {\n schemaVersion: 1,\n id: \"three-movements-dusk\",\n label: \"Dusk\",\n seed: 13,\n layers: [\n {\n key: \"bloom\",\n count: 3,\n sprite: {\n kind: \"circle\",\n radius: [0.09, 0.14],\n color: \"#7a4a5e\",\n colors: [\"#7a4a5e\", \"#b06a4a\"],\n soft: true,\n },\n motion: {\n type: \"wander\",\n speed: [0.001, 0.002],\n meander: 0.04,\n coherence: 0.7,\n },\n alpha: [0.25, 0.4],\n blend: \"lighter\",\n grow: { amp: 0.3, period: 14000 },\n },\n {\n key: \"strokes\",\n count: 8,\n sprite: {\n kind: \"stroke\",\n length: [0.1, 0.2],\n points: [\n [-1, 0.2],\n [-0.3, -0.6],\n [0.5, -0.4],\n [1, 0.2],\n ],\n width: 0.004,\n taper: true,\n color: \"#c2447a\",\n colors: [\"#c2447a\", \"#8f2c58\"],\n },\n motion: {\n type: \"drift\",\n speed: [0.003, 0.008],\n angle: 20,\n bidirectional: true,\n },\n alpha: [0.3, 0.5],\n rotate: [-30, 30],\n },\n ],\n },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Facets — a composition in the manner of the early abstractionists: three\n * soft-edged colour planes (feathered `rect`) breathing slowly behind a field\n * of tumbling triangular facets (custom `polygon`), tapered brush arcs\n * (`stroke`) drifting across, and a few glowing hexagons (soft regular\n * `polygon`). Every glyph here is a path, not a disc — the shape family nine\n * of the fifteen style profiles asked for.\n */\nexport const FACETS_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'facets',\n label: 'Facets',\n seed: 1911,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#101626' },\n { at: 1, color: '#1c1a2e' },\n ],\n },\n layers: [\n {\n key: 'planes',\n count: 3,\n sprite: {\n kind: 'rect',\n width: [0.28, 0.42],\n aspect: [0.6, 1.4],\n color: '#b3402f',\n colors: ['#b3402f', '#c9862b', '#2d4f8a'],\n feather: 0.6,\n },\n alpha: [0.35, 0.5],\n region: { x: [0.2, 0.8], y: [0.2, 0.8] },\n motion: { type: 'wander', speed: [0.001, 0.003], meander: 0.02 },\n spin: [-2, 2],\n },\n {\n key: 'facets',\n count: 14,\n sprite: {\n kind: 'polygon',\n radius: [0.02, 0.06],\n points: [[-1, 0.9], [0.2, -1], [1, 0.4]],\n color: '#f2e8c9',\n colors: ['#f2e8c9', '#e0b53a', '#6fa8dc', '#d94f3d'],\n },\n alpha: [0.6, 0.9],\n motion: { type: 'wander', speed: [0.003, 0.008], meander: 0.03 },\n spin: [-8, 8],\n },\n {\n key: 'arcs',\n count: 12,\n sprite: {\n kind: 'stroke',\n length: [0.08, 0.18],\n points: [[-1, 0.3], [-0.5, -0.6], [0.3, -0.7], [1, 0.1]],\n width: 0.004,\n taper: true,\n color: '#f2e8c9',\n },\n alpha: [0.5, 0.8],\n motion: { type: 'drift', speed: [0.004, 0.01], angle: 20, bidirectional: true },\n spin: [-4, 4],\n },\n {\n key: 'hexes',\n count: 8,\n sprite: { kind: 'polygon', radius: [0.008, 0.016], sides: 6, color: '#e0b53a', soft: true },\n alpha: [0.5, 0.8],\n blend: 'lighter',\n motion: { type: 'wander', speed: [0.002, 0.005] },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/** Haiku: a centered text block with a slowly drifting haiku over deep indigo. */\nexport const HAIKU_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'haiku',\n label: 'Haiku',\n seed: 42,\n background: { type: 'solid', color: '#080812' },\n layers: [\n {\n count: 1,\n sprite: {\n kind: 'textBlock',\n text: 'An old silent pond\\nA frog jumps into the pond —\\nSplash! Silence again.',\n maxWidth: 0.8,\n fontSize: 0.05,\n lineHeight: 1.8,\n align: 'center',\n color: '#c8cad4',\n },\n motion: { type: 'static' },\n position: { x: 0.1, y: 0.35 },\n },\n {\n count: 30,\n sprite: { kind: 'circle', radius: [0.0005, 0.0015], color: '#3a3a5c' },\n motion: { type: 'drift', speed: [0.002, 0.006], angle: 270 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Night Lanterns (Yi Peng festival sky): depth from four correlated parallax cues —\n * closer layers are LARGER, FASTER, SWAY WIDER, and glow WARMER/BRIGHTER. v2 of this\n * composition exercises the expressive additions the first draft exposed as missing:\n * soft glow orbs + additive blend (lantern light that sums where it overlaps), bounded\n * alpha pulse with per-entity phases (breathing flames, strobe-proof by construction),\n * and spawn regions (stars only above the horizon; dim ember shimmer kept low near\n * the water line).\n */\nexport const LANTERNS_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'lanterns',\n label: 'Night Lanterns',\n seed: 88,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#04060f' },\n { at: 0.55, color: '#0b1026' },\n { at: 0.85, color: '#251731' },\n { at: 1, color: '#472518' },\n ],\n },\n layers: [\n {\n count: 60,\n sprite: { kind: 'circle', radius: [0.000463, 0.001296], color: '#8fa0c8' },\n alpha: [0.35, 1],\n region: { y: [0, 0.62] },\n motion: { type: 'drift', speed: [0.000463, 0.001852], bob: 0.0009259 },\n },\n {\n count: 36,\n sprite: {\n kind: 'circle',\n radius: [0.001389, 0.002778],\n color: '#b06a2a',\n soft: true,\n },\n alpha: [0.5, 0.9],\n blend: 'lighter',\n pulse: { amp: 0.18, period: 2800 },\n motion: { type: 'rise', speed: [0.005556, 0.01296], sway: 0.003704 },\n },\n {\n count: 14,\n sprite: {\n kind: 'circle',\n radius: [0.003241, 0.006019],\n color: '#e08a34',\n soft: true,\n },\n alpha: [0.6, 1],\n blend: 'lighter',\n pulse: { amp: 0.22, period: 3400 },\n motion: { type: 'rise', speed: [0.01481, 0.02593], sway: 0.006481 },\n },\n {\n count: 8,\n sprite: { kind: 'emoji', glyphs: ['🏮'] },\n size: [0.02407, 0.04074],\n alpha: [0.85, 1],\n motion: { type: 'rise', speed: [0.02778, 0.04444], sway: 0.009259 },\n },\n {\n count: 4,\n sprite: { kind: 'emoji', glyphs: ['🏮'] },\n size: [0.0537, 0.07778],\n motion: { type: 'rise', speed: [0.04815, 0.06852], sway: 0.01296 },\n },\n {\n count: 12,\n sprite: { kind: 'circle', radius: [0.001852, 0.00463], color: '#e08a34', soft: true },\n alpha: [0.12, 0.35],\n blend: 'lighter',\n region: { y: [0.93, 1] },\n pulse: { amp: 0.1, period: 2200 },\n motion: { type: 'drift', speed: [0.001852, 0.005556], bob: 0.001852 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Lobby Talk — one screen of a \"quarter in review\" that runs on a lobby wall\n * between meetings: a five-row adoption chart over the same slow haze and\n * dust the whole talk shares. The words are the point, so every text layer\n * declares `role: 'read'` — the opt-in that turns on `adviseSpec`'s\n * legibility advisories (`text-legibility` against the ground *and* the\n * brightest additive layer that can sit under a line, `text-safe-area` for\n * the bezel zone). Tuned to zero advisories: the haze is bright enough to\n * matter and dim enough to leave every label above 4.5:1 at its peak.\n *\n * Schema exercises: `role: 'read'` on both `textBlock` and `text`, a\n * `list`-laid chart in three layers (labels, `bar`s, readouts), additive\n * atmosphere (`lighter` soft circles with `pulse`) under readable copy.\n * Steer `bars.sprite.values` to change the numbers live.\n */\nexport const LOBBY_TALK_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'lobby-talk',\n label: 'Lobby Talk',\n seed: 1207,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#060912' },\n { at: 1, color: '#0b1224' },\n ],\n drift: { period: 40000, amount: 0.1 },\n },\n layers: [\n {\n key: 'haze',\n count: 3,\n sprite: { kind: 'circle', radius: [0.22, 0.3], soft: true, color: '#123a4a', colors: ['#123a4a', '#2a1e4a', '#0e2a3a'] },\n alpha: [0.35, 0.5],\n blend: 'lighter',\n region: { x: [0.2, 0.8], y: [0.3, 0.7] },\n motion: { type: 'wander', speed: [0.002, 0.004], meander: 0.05 },\n pulse: { amp: 0.15, period: 9000 },\n },\n {\n key: 'dust',\n count: 50,\n sprite: { kind: 'circle', radius: [0.0008, 0.0018], soft: true, color: '#7fb8c9' },\n alpha: [0.2, 0.5],\n blend: 'lighter',\n motion: { type: 'wander', speed: [0.001, 0.003] },\n },\n {\n key: 'title',\n count: 1,\n sprite: { kind: 'textBlock', text: 'Adoption by feature, % of accounts', maxWidth: 1.0, fontSize: 0.034, color: '#f2f4f8', role: 'read' },\n motion: { type: 'static' },\n position: { x: 0.12, y: 0.16 },\n },\n {\n key: 'labels',\n count: 5,\n sprite: { kind: 'text', strings: ['Onboarding', 'Search', 'Billing', 'Exports', 'Mobile'], font: 'system-ui', align: 'left', baseline: 'middle', color: '#a9b7cc', role: 'read' },\n size: [0.03, 0.03],\n motion: { type: 'static' },\n position: { x: 0.12, y: 0.32 },\n layout: { type: 'list', gap: 0.085 },\n },\n {\n key: 'bars',\n count: 5,\n sprite: {\n kind: 'bar',\n values: [82, 64, 91, 37, 58],\n max: 100,\n length: 0.42,\n thickness: 0.026,\n color: '#7fe0d2',\n colors: ['#7fe0d2', '#7fe0d2', '#ffcf7a', '#7fe0d2', '#7fe0d2'],\n },\n alpha: [0.9, 0.9],\n motion: { type: 'static' },\n position: { x: 0.33, y: 0.32 },\n layout: { type: 'list', gap: 0.085 },\n },\n {\n key: 'readouts',\n count: 5,\n sprite: { kind: 'text', strings: ['82%', '64%', '91%', '37%', '58%'], font: 'bold system-ui', align: 'left', baseline: 'middle', color: '#f2f4f8', role: 'read' },\n size: [0.03, 0.03],\n motion: { type: 'static' },\n position: { x: 0.78, y: 0.32 },\n layout: { type: 'list', gap: 0.085 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Matrix Rain: showcases `layout: grid` with per-axis jitter ({ y: 1 } keeps the\n * columns crisp while de-syncing them vertically), glyph `cycle`, and `ghosting`\n * doing the classic fading-trail work. Two depths of rain plus rare bright heads.\n */\nexport const MATRIX_RAIN_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'matrix-rain',\n label: 'Matrix Rain',\n seed: 1999,\n motionIntensity: 'moderate',\n ghosting: 0.88,\n background: { type: 'solid', color: '#010401' },\n layers: [\n {\n key: 'rain-far',\n count: 64,\n sprite: {\n kind: 'text',\n strings: ['ア', 'カ', 'サ', 'タ', 'ナ', 'ハ', 'マ', 'ヤ', 'ラ', 'ワ', '0', '1', '7', 'Z', 'X', 'K'],\n color: '#1c7a2e',\n font: 'bold monospace',\n cycle: { period: 900 },\n },\n size: [0.014, 0.02],\n layout: { type: 'grid', columns: 32, jitter: { y: 1 } },\n motion: { type: 'drift', speed: [0.06, 0.14], angle: 90 },\n alpha: [0.35, 0.6],\n },\n {\n key: 'rain-near',\n count: 40,\n sprite: {\n kind: 'text',\n strings: ['ミ', 'ネ', 'リ', 'ソ', 'ツ', 'ヌ', 'ホ', 'ユ', '3', '8', '9', 'V', 'N'],\n color: '#2ecc40',\n font: 'bold monospace',\n cycle: { period: 700 },\n },\n size: [0.022, 0.03],\n layout: { type: 'grid', columns: 20, jitter: { y: 1 } },\n motion: { type: 'drift', speed: [0.16, 0.3], angle: 90 },\n alpha: [0.6, 0.9],\n },\n {\n key: 'heads',\n count: 12,\n sprite: {\n kind: 'text',\n strings: ['ケ', 'メ', 'エ', 'ム', 'ヲ', '5', '2'],\n color: '#c8ffd4',\n font: 'bold monospace',\n cycle: { period: 500 },\n },\n size: [0.024, 0.032],\n layout: { type: 'grid', columns: 12, jitter: { y: 1 } },\n motion: { type: 'drift', speed: [0.2, 0.34], angle: 90 },\n alpha: [0.9, 1],\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Tarkovsky — Nostalghia's candle: a single point of devotion.\n * Near-black warm ground; one small warm-white flame at center with grow/pulse\n * wobble; faint smoke rising; sparse amber embers with long fading trails;\n * a wide near-invisible halo breathing on a 10s cycle. Minimalism as tension —\n * most of the screen is darkness.\n *\n * Note: `pulse.amp` is ADDED to base alpha (not multiplied), so the halo's amp\n * must stay below its base alpha or the trough clamps to fully invisible.\n */\nexport const NOSTALGHIA_CANDLE_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'nostalghia-candle',\n label: \"Nostalghia's Candle\",\n seed: 1983,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#050302' },\n { at: 0.55, color: '#0a0704' },\n { at: 1, color: '#120c08' },\n ],\n },\n layers: [\n {\n key: 'halo',\n count: 1,\n position: { x: 0.5, y: 0.52 },\n sprite: {\n kind: 'circle',\n radius: [0.11, 0.11],\n color: '#c4782a',\n soft: true,\n },\n // Base 0.04 + amp 0.02 → breathes ~0.02..0.06; never clamps to 0.\n // (pulse.amp is ADDED to alpha, not multiplied.) Kept subordinate to the flame.\n alpha: [0.04, 0.04],\n blend: 'lighter',\n pulse: { amp: 0.02, period: 10000 },\n grow: { amp: 0.08, period: 10000 },\n motion: { type: 'static' },\n },\n {\n key: 'smoke',\n count: 3,\n sprite: {\n kind: 'circle',\n radius: [0.01, 0.022],\n color: '#6a6258',\n soft: true,\n },\n alpha: [0.02, 0.04],\n blend: 'lighter',\n region: { x: [0.46, 0.54], y: [0.36, 0.48] },\n pulse: { amp: 0.015, period: 4500 },\n motion: { type: 'rise', speed: [0.002, 0.004], sway: 0.008 },\n },\n {\n key: 'flame-glow',\n count: 1,\n sprite: {\n kind: 'circle',\n radius: [0.028, 0.028],\n color: '#ffb040',\n soft: true,\n },\n alpha: [0.32, 0.32],\n blend: 'lighter',\n pulse: { amp: 0.12, period: 1400 },\n grow: { amp: 0.4, period: 1600 },\n // Tiny orbit = positional lean without drifting off-center (wander has vx).\n motion: {\n type: 'orbit',\n speed: [18, 18],\n radius: [0.003, 0.003],\n center: { x: 0.5, y: 0.52 },\n },\n },\n {\n key: 'flame-core',\n count: 1,\n sprite: {\n kind: 'circle',\n radius: [0.014, 0.014],\n color: '#fff6e0',\n soft: true,\n },\n alpha: [0.95, 0.95],\n blend: 'lighter',\n pulse: { amp: 0.25, period: 900 },\n grow: { amp: 0.55, period: 1100 },\n motion: {\n type: 'orbit',\n speed: [22, 22],\n radius: [0.0025, 0.0025],\n center: { x: 0.5, y: 0.52 },\n },\n },\n {\n key: 'embers',\n count: 7,\n sprite: {\n kind: 'circle',\n radius: [0.0018, 0.004],\n color: '#e08a34',\n soft: true,\n },\n alpha: [0.4, 0.8],\n blend: 'lighter',\n region: { x: [0.35, 0.65], y: [0.4, 0.7] },\n pulse: { amp: 0.2, period: 2200 },\n trail: { length: 2200, fade: 1 },\n motion: {\n type: 'drift',\n speed: [0.004, 0.012],\n angle: 270,\n bob: 0.008,\n },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Polygons: the classic Mystify-style bouncing-polygon saver, expressed as chain links + heavy\n * ghosting. Showcases `links.mode: 'chain'` with `closed` (vertices wired in order\n * into a polygon), `bounce` motion, and high `ghosting` (the decaying after-images\n * ARE the effect — no per-entity trail sampling involved).\n */\nexport const POLYGONS_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'polygons',\n label: 'Polygons',\n seed: 1995,\n motionIntensity: 'moderate',\n ghosting: 0.95,\n background: { type: 'solid', color: '#04040a' },\n layers: [\n {\n key: 'poly-cyan',\n count: 4,\n sprite: { kind: 'circle', radius: [0.0025, 0.0025], color: '#37e5d7' },\n motion: { type: 'bounce', speed: [0.14, 0.24] },\n wrap: false,\n alpha: [0.9, 0.9],\n links: { k: 1, maxDist: 3, mode: 'chain', closed: true, color: '#37e5d7', alpha: 0.85, width: 0.0018 },\n },\n {\n key: 'poly-magenta',\n count: 4,\n sprite: { kind: 'circle', radius: [0.0025, 0.0025], color: '#e83e9c' },\n motion: { type: 'bounce', speed: [0.1, 0.2] },\n wrap: false,\n alpha: [0.9, 0.9],\n links: { k: 1, maxDist: 3, mode: 'chain', closed: true, color: '#e83e9c', alpha: 0.85, width: 0.0018 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Orrery: a mechanical solar system. Exercises orbit motion (concentric rings\n * at different speeds), spin (planets rotate on their axes), and grow (the sun\n * pulses). Soft glow circles with additive blending create the corona and\n * planetary halos.\n */\nexport const ORRERY_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'orrery',\n label: 'Orrery',\n seed: 7,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#020210' },\n { at: 0.5, color: '#06051a' },\n { at: 1, color: '#0a0820' },\n ],\n },\n layers: [\n // Distant stars\n {\n count: 80,\n sprite: { kind: 'circle', radius: [0.0002778, 0.001111], color: '#8899cc' },\n alpha: [0.2, 0.8],\n pulse: { amp: 0.3, period: 3000 },\n motion: { type: 'static' },\n },\n // Sun corona (soft glow)\n {\n key: 'corona',\n count: 1,\n sprite: { kind: 'circle', radius: [0.05556, 0.05556], color: '#ffaa22', soft: true },\n blend: 'lighter',\n alpha: [0.6, 0.6],\n grow: { amp: 0.15, period: 4000 },\n motion: { type: 'static' },\n position: { x: 0.5, y: 0.5 },\n },\n // Sun body\n {\n key: 'sun',\n count: 1,\n sprite: { kind: 'emoji', glyphs: ['☀️'] },\n size: [0.04444, 0.04444],\n grow: { amp: 0.08, period: 4000 },\n motion: { type: 'static' },\n position: { x: 0.5, y: 0.5 },\n },\n // Inner ring — small fast planets\n {\n key: 'inner',\n count: 3,\n sprite: { kind: 'emoji', glyphs: ['🪨', '🔴', '🟠'] },\n size: [0.01481, 0.02037],\n spin: 30,\n motion: { type: 'orbit', speed: [28, 42], radius: [0.07407, 0.1111] },\n },\n // Middle ring — gas giants\n {\n key: 'middle',\n count: 2,\n sprite: { kind: 'emoji', glyphs: ['🟤', '🪐'] },\n size: [0.02593, 0.03519],\n spin: -15,\n motion: { type: 'orbit', speed: [12, 20], radius: [0.1481, 0.1852] },\n },\n // Outer ring — ice giants\n {\n key: 'outer',\n count: 2,\n sprite: { kind: 'emoji', glyphs: ['🔵', '💎'] },\n size: [0.02037, 0.02778],\n spin: 10,\n motion: { type: 'orbit', speed: [5, 10], radius: [0.2222, 0.2778] },\n },\n // Orbital dust ring (soft glow particles orbiting slowly)\n {\n count: 24,\n sprite: { kind: 'circle', radius: [0.0009259, 0.002778], color: '#ccaa66', soft: true },\n alpha: [0.15, 0.4],\n blend: 'lighter',\n pulse: { amp: 0.2, period: 2500 },\n motion: { type: 'orbit', speed: [2, 8], radius: [0.09259, 0.2963] },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Pings — almost nothing, almost never.\n * A near-black ground and one teal hue. Three rings take turns: each one\n * appears, grows sixteenfold (0.15× → 2.4× its radius) and fades over four\n * seconds, then the frame is empty until the next — `emit` with `jitter: 0`\n * spaces them evenly, one event every four seconds, and `life` is kept at\n * the stagger so no two rings are ever lit together. Underneath, a few motes rise,\n * `settle` to rest and fade on their own, longer, seeded schedule. Nothing\n * travels; everything grows and goes. The house style Fathom describes this\n * exactly and, before `emit`, could not be authored.\n */\nexport const PINGS_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'pings',\n label: 'Pings',\n seed: 7,\n motionIntensity: 'calm',\n ghosting: 0.9,\n background: { type: 'solid', color: '#03060a' },\n layers: [\n {\n key: 'ping',\n count: 3,\n sprite: { kind: 'ring', radius: [0.05, 0.05], color: '#4fb3a8', width: 0.0015 },\n alpha: [0.35, 0.35],\n blend: 'lighter',\n region: { x: [0.2, 0.8], y: [0.25, 0.75] },\n motion: { type: 'static' },\n // One ring at a time: three entities evenly staggered across 12 s.\n emit: { every: 12000, life: 4000, jitter: 0, grow: [0.15, 2.4] },\n },\n {\n key: 'motes',\n count: 14,\n sprite: { kind: 'circle', radius: [0.0012, 0.002], color: '#4fb3a8', soft: true },\n alpha: [0.1, 0.22],\n blend: 'lighter',\n // Each mote is flung upward and comes to rest within ~2.5 s of its event.\n motion: { type: 'rise', speed: [0.01, 0.02], sway: 0.004, ease: { type: 'settle', tau: 2500 } },\n emit: { every: 16000, life: 7000, grow: [0.6, 1.4] },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Night Procession: a choreographed scene. Showcases `path` motion (a smooth\n * figure-eight lantern route with scatter), layer-parented `orbit` (moths circling\n * a wandering lantern-bearer), `life` staging (stars first, the procession enters\n * at 4 s, moths at 7 s), plus `ring` and `rect` sprites.\n */\nexport const PROCESSION_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'procession',\n label: 'Night Procession',\n seed: 8,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#060612' },\n { at: 0.8, color: '#101024' },\n { at: 1, color: '#1a1428' },\n ],\n drift: { period: 30000, amount: 0.08 },\n },\n layers: [\n {\n key: 'stars',\n count: 90,\n sprite: { kind: 'circle', radius: [0.0006, 0.0016], color: '#f0ead8', soft: true },\n motion: { type: 'static' },\n region: { y: [0, 0.6] },\n alpha: [0.25, 0.6],\n pulse: { amp: 0.15, period: 5000 },\n },\n {\n key: 'lanterns',\n count: 9,\n sprite: {\n kind: 'rect',\n width: [0.012, 0.02],\n aspect: [1.3, 1.7],\n color: '#ffb347',\n colors: ['#ffb347', '#ff8c69', '#ffd97a'],\n colorWeights: [3, 1, 2],\n },\n motion: {\n type: 'path',\n points: [\n { x: 0.12, y: 0.72 },\n { x: 0.38, y: 0.58 },\n { x: 0.62, y: 0.78 },\n { x: 0.88, y: 0.62 },\n { x: 0.62, y: 0.5 },\n { x: 0.38, y: 0.72 },\n ],\n duration: 36000,\n curve: 'smooth',\n closed: true,\n scatter: 0.02,\n },\n alpha: [0.65, 0.9],\n pulse: { amp: 0.15, period: 2600 },\n life: { enter: 4000, fade: 2500 },\n trail: { length: 1200, fade: 1 },\n },\n {\n key: 'bearer',\n count: 1,\n sprite: { kind: 'circle', radius: [0.014, 0.014], color: '#ffe9b0', soft: true },\n motion: { type: 'wander', speed: [0.008, 0.012], meander: 0.08 },\n alpha: [0.8, 0.8],\n blend: 'lighter',\n life: { enter: 4000, fade: 2500 },\n },\n {\n key: 'moths',\n count: 7,\n sprite: { kind: 'ring', radius: [0.002, 0.005], color: '#d8f6ff', width: 0.001 },\n motion: { type: 'orbit', speed: [20, 55], radius: [0.03, 0.09], center: { layer: 'bearer' } },\n alpha: [0.3, 0.7],\n life: { enter: 7000, fade: 2000 },\n trail: { length: 600 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/** Rain: dense text streaks falling straight down over a near-black sky. */\nexport const RAIN_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'rain',\n label: 'Rain',\n seed: 7,\n motionIntensity: 'moderate',\n background: { type: 'solid', color: '#05070a' },\n layers: [\n {\n count: 140,\n sprite: { kind: 'text', strings: ['│'], color: '#9fd0ff' },\n size: [0.01111, 0.02407],\n motion: { type: 'drift', angle: 90, speed: [0.4815, 0.8333] },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Relay Board — a six-row status chart in five layers instead of twenty-five.\n * One `list` of labels, one `list` of `bar`s whose lengths are the numbers,\n * one `list` of readouts, a title block, and a slow dust field behind so the\n * board reads as a live wall, not a document. Steer `bars.sprite.values` and the\n * bars glide to the new figures; the labels never move.\n */\nexport const RELAY_BOARD_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'relay-board',\n label: 'Relay Board',\n seed: 9,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#05070d' },\n { at: 1, color: '#0a0d18' },\n ],\n },\n layers: [\n {\n key: 'dust',\n count: 40,\n sprite: { kind: 'circle', radius: [0.0008, 0.0016], color: '#22344a', soft: true },\n alpha: [0.2, 0.45],\n blend: 'lighter',\n motion: { type: 'wander', speed: [0.001, 0.003] },\n },\n {\n key: 'title',\n count: 1,\n sprite: { kind: 'textBlock', text: 'RELAY LINKS — UPLINK MARGIN', maxWidth: 0.6, fontSize: 0.028, color: '#9fb4c9' },\n motion: { type: 'static' },\n position: { x: 0.12, y: 0.16 },\n },\n {\n key: 'labels',\n count: 6,\n sprite: { kind: 'text', strings: ['VIREO-9', 'TIDE', 'ORRERY', 'COMET', 'LANTERN', 'SAKURA'], font: 'bold monospace', align: 'left', color: '#e6e8ef' },\n size: [0.024, 0.024],\n motion: { type: 'static' },\n position: { x: 0.12, y: 0.3 },\n layout: { type: 'list', gap: 0.075 },\n },\n {\n key: 'bars',\n count: 6,\n sprite: {\n kind: 'bar',\n values: [82, 64, 91, 37, 58, 73],\n max: 100,\n length: 0.5,\n thickness: 0.02,\n color: '#17e8c8',\n colors: ['#17e8c8', '#35d0ff', '#ffd93b', '#ff6ad5', '#ad8cff', '#17e8c8'],\n },\n alpha: [0.85, 0.85],\n motion: { type: 'static' },\n position: { x: 0.3, y: 0.3 },\n layout: { type: 'list', gap: 0.075 },\n },\n {\n key: 'readouts',\n count: 6,\n sprite: { kind: 'text', strings: ['82%', '64%', '91%', '37%', '58%', '73%'], font: 'monospace', align: 'left', color: '#9fb4c9' },\n size: [0.02, 0.02],\n motion: { type: 'static' },\n position: { x: 0.86, y: 0.3 },\n layout: { type: 'list', gap: 0.075 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Sakura Drift: cherry-blossom petals carried on a spring twilight breeze.\n * Glow-up pass (v1-ceiling features): petals ride `wander` harmonics with shared\n * `coherence` so gusts move the whole fall together, `spin` tumbles the glyphs,\n * faint `streak` wind-lines cross the frame, the blossom-glow backdrop shimmers\n * as a traveling `pulse.wave`, and dusk fireflies wander the lower field. The\n * ground is a warm plum earth blended out of the sunset (no more abrupt dark\n * band), with slow background `drift` keeping the sky alive.\n */\nexport const SAKURA_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'sakura',\n label: 'Sakura Drift',\n seed: 314,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#1b1d38' },\n { at: 0.45, color: '#3a2645' },\n { at: 0.78, color: '#7d3d4e' },\n { at: 0.92, color: '#4a2438' },\n { at: 1, color: '#1c1018' },\n ],\n drift: { period: 35000, amount: 0.08 },\n },\n layers: [\n {\n key: 'blossom-glow',\n count: 60,\n sprite: {\n kind: 'circle',\n radius: [0.0005556, 0.001481],\n color: '#ffe3ec',\n soft: true,\n },\n alpha: [0.3, 0.9],\n blend: 'lighter',\n region: { y: [0, 0.72] },\n // Shimmer travels across the sky instead of orbs twinkling independently.\n pulse: { amp: 0.22, period: 4000, wave: { wavelength: 0.45, angle: 10 } },\n motion: { type: 'drift', speed: [0.0002778, 0.001111], bob: 0.0009259 },\n },\n {\n key: 'petals-far',\n count: 28,\n sprite: { kind: 'emoji', glyphs: ['🌸'] },\n size: [0.01204, 0.01852],\n alpha: [0.5, 0.8],\n spin: 16,\n motion: {\n type: 'wander',\n speed: [0.011, 0.024],\n angle: 100,\n meander: 0.025,\n coherence: 0.35,\n },\n },\n {\n key: 'petals-mid',\n count: 18,\n sprite: { kind: 'emoji', glyphs: ['🌸'] },\n size: [0.01852, 0.02963],\n alpha: [0.7, 0.95],\n spin: 24,\n motion: {\n type: 'wander',\n speed: [0.022, 0.041],\n angle: 100,\n meander: 0.045,\n coherence: 0.35,\n },\n },\n {\n key: 'petals-near',\n count: 10,\n sprite: { kind: 'emoji', glyphs: ['🌸'] },\n size: [0.03148, 0.05],\n alpha: [0.85, 1],\n spin: 32,\n motion: {\n type: 'wander',\n speed: [0.039, 0.063],\n angle: 100,\n meander: 0.07,\n coherence: 0.35,\n },\n },\n {\n key: 'gusts',\n count: 7,\n sprite: {\n kind: 'streak',\n length: [0.02, 0.045],\n width: 0.0012,\n color: '#ffd9e6',\n },\n alpha: [0.1, 0.22],\n blend: 'lighter',\n motion: { type: 'drift', speed: [0.09, 0.14], angle: 100 },\n },\n {\n key: 'fireflies',\n count: 6,\n sprite: {\n kind: 'circle',\n radius: [0.0009, 0.002],\n color: '#ffe9a8',\n soft: true,\n },\n alpha: [0.15, 0.5],\n blend: 'lighter',\n region: { y: [0.6, 0.9] },\n pulse: { amp: 0.3, period: 2800 },\n motion: { type: 'wander', speed: [0.004, 0.01], meander: 0.05 },\n },\n {\n key: 'fallen-petals',\n count: 16,\n sprite: {\n kind: 'circle',\n radius: [0.001389, 0.003704],\n color: '#ff9bb5',\n soft: true,\n },\n alpha: [0.1, 0.3],\n blend: 'lighter',\n region: { y: [0.9, 1] },\n // Settled petals catch the last light in a slow wave along the ground.\n pulse: { amp: 0.15, period: 3200, wave: { wavelength: 0.3, angle: 0 } },\n motion: {\n type: 'drift',\n speed: [0.0002778, 0.001389],\n angle: 180,\n bob: 0.0009259,\n },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/** Snowfall: three depth layers of white circles drifting down with horizontal bob. */\nexport const SNOWFALL_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'snowfall',\n label: 'Snowfall',\n seed: 12,\n motionIntensity: 'calm',\n background: {\n type: 'gradient',\n stops: [\n { at: 0, color: '#0a1628' },\n { at: 0.7, color: '#0d1f3c' },\n { at: 1, color: '#121212' },\n ],\n },\n layers: [\n {\n count: 50,\n sprite: { kind: 'circle', radius: [0.0009259, 0.002315], color: '#8899aa' },\n motion: { type: 'drift', angle: 90, speed: [0.01389, 0.03704], bob: 0.002778 },\n },\n {\n count: 35,\n sprite: { kind: 'circle', radius: [0.001852, 0.004167], color: '#c0cdd8' },\n motion: { type: 'drift', angle: 85, speed: [0.03241, 0.07407], bob: 0.005556 },\n },\n {\n count: 15,\n sprite: { kind: 'circle', radius: [0.003241, 0.006481], color: '#e8eff5' },\n motion: { type: 'drift', angle: 82, speed: [0.05093, 0.1111], bob: 0.009259 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Thermal Field: the `field` background — seeded, domain-warped value noise\n * posterised into six riso inks (`quantize: 6`, one hard band per level) and\n * drifting once every forty seconds, so the contours crawl like a weather\n * chart. The foreground is deliberately almost nothing: a handful of pale\n * motes screened over the bands, so the ground IS the piece. A house\n * `thermal` look; the same field with `quantize: 0` is a smooth aura. A\n * `finish` of grain and dither screens the whole frame like a riso print.\n */\nexport const THERMAL_FIELD_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'thermal-field',\n label: 'Thermal Field',\n seed: 71,\n motionIntensity: 'calm',\n // The riso print: grain at half strength, a light dither screen — the\n // finish that makes the flat inks read as paper rather than pixels.\n finish: { grain: 0.5, dither: 0.3 },\n background: {\n type: 'field',\n scale: 2.2,\n octaves: 3,\n warp: 0.4,\n quantize: 6,\n bands: ['#1b1a3a', '#0078bf', '#00a99d', '#ffe800', '#ff6c2f', '#ff48b0'],\n drift: { period: 40000, amount: 0.3 },\n },\n layers: [\n {\n key: 'motes',\n count: 14,\n sprite: { kind: 'circle', radius: [0.012, 0.028], color: '#fff6e0', soft: true },\n motion: { type: 'wander', speed: [0.003, 0.008], meander: 0.04, coherence: 0.3 },\n alpha: [0.18, 0.4],\n blend: 'screen',\n pulse: { amp: 0.15, period: 9000 },\n },\n ],\n};\n","import type { SaverSpec } from '../types';\n\n/**\n * Warp Tunnel: showcases `warp` motion (perspective depth — size/alpha/speed scale\n * with 1/z), `streak` sprites oriented along the analytic heading, `colorWeights`\n * (mostly white stars, occasional blue/amber), and light `ghosting` for smear.\n */\nexport const WARP_TUNNEL_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: 'warp-tunnel',\n label: 'Warp Tunnel',\n seed: 1701,\n motionIntensity: 'energetic',\n ghosting: 0.55,\n background: { type: 'solid', color: '#020208' },\n layers: [\n {\n key: 'far-stars',\n count: 150,\n sprite: {\n kind: 'streak',\n length: [0.008, 0.02],\n width: 0.0015,\n color: '#cfd8ff',\n colors: ['#cfd8ff', '#ffffff', '#8ab4ff', '#ffd9a0'],\n colorWeights: [5, 3, 1.5, 0.5],\n },\n motion: { type: 'warp', speed: [0.06, 0.16] },\n alpha: [0.5, 0.9],\n blend: 'lighter',\n },\n {\n key: 'near-stars',\n count: 50,\n sprite: {\n kind: 'streak',\n length: [0.025, 0.06],\n width: 0.0025,\n color: '#ffffff',\n colors: ['#ffffff', '#a8c8ff'],\n colorWeights: [3, 1],\n },\n motion: { type: 'warp', speed: [0.3, 0.55] },\n alpha: [0.7, 1],\n blend: 'lighter',\n },\n {\n key: 'core-glow',\n count: 1,\n sprite: { kind: 'circle', radius: [0.06, 0.06], color: '#3a4a8f', soft: true },\n motion: { type: 'static' },\n position: { x: 0.5, y: 0.5 },\n alpha: [0.35, 0.35],\n pulse: { amp: 0.15, period: 5000 },\n blend: 'lighter',\n },\n ],\n};\n","import type { SaverSpec } from \"../types\";\n\n/**\n * Typed Cue — textBlock.reveal, both moods.\n * Two self-typing captions over near-black. The upper one types at ten\n * graphemes a second with a blinking caret (`mode: 'typewriter'` — the classic\n * terminal reveal; `speed` makes progress a pure function of scene time, so\n * every viewer types the same line on the same clock from its own mount). The\n * lower one arrives as a wave of overlapping fades (`mode: 'glyphFade'`,\n * `fade: 0.4` — each glyph ramps in over 40% of the progress window, which\n * reads as a soft dissolve rather than typing) and carries no caret. Both\n * blocks declare `opacity` so the path is steerable, and layout always runs on\n * the FULL text — reveal only masks glyphs, so lines never reflow mid-type.\n *\n * Trap, documented in the playbook and true here too: at t = 0 a self-typing\n * block has typed nothing, so `previewScene` at the default instant looks\n * empty — preview at t ≥ 10 s to see the words. To swap the line live, glide\n * `reveal.progress` to 0, step the `text`, glide back (one `setTrack` call).\n *\n * The scan band is the one non-text layer, and it is load-bearing twice over:\n * a screensaver of two static text blocks is a document, not a screensaver\n * (`text-heavy`), and the band gives the words something to sit on — a slow\n * refresh sweep passing under the type. Note the units: `perceiveScene` takes\n * `t` in MILLISECONDS while the MCP `previewScene` tool takes seconds (the\n * worker converts); passing seconds to the library reads as a block that\n * never finishes typing.\n */\nexport const TYPED_CUE_SPEC: SaverSpec = {\n schemaVersion: 1,\n id: \"typed-cue\",\n label: \"Typed Cue\",\n seed: 19,\n motionIntensity: \"calm\",\n background: { type: \"solid\", color: \"#050608\" },\n layers: [\n {\n key: \"scan\",\n count: 1,\n sprite: { kind: \"rect\", width: [1, 1], aspect: [0.02, 0.02], color: \"#16241f\", feather: 0.9 },\n motion: { type: \"drift\", speed: [0.014, 0.014], angle: 90 },\n alpha: [0.5, 0.5],\n blend: \"screen\",\n },\n {\n key: \"headline\",\n count: 1,\n sprite: {\n kind: \"textBlock\",\n text: \"THE SCREEN IS AWAKE.\\nWORDS ARRIVE ON THEIR OWN CLOCK.\",\n maxWidth: 0.84,\n fontSize: 0.03,\n lineHeight: 1.5,\n align: \"left\",\n anchor: \"top-left\",\n font: \"bold monospace\",\n color: \"#e6e8ef\",\n opacity: 0.94,\n reveal: {\n progress: 1,\n mode: \"typewriter\",\n speed: 10,\n caret: { blink: 1.1, color: \"#e6e8ef\" },\n },\n },\n motion: { type: \"static\" },\n position: { x: 0.08, y: 0.16 },\n alpha: [0.95, 0.95],\n },\n {\n key: \"aside\",\n count: 1,\n sprite: {\n kind: \"textBlock\",\n text: \"and leaves the same way —\\na dissolve, not a delete.\",\n maxWidth: 0.5,\n fontSize: 0.022,\n lineHeight: 1.5,\n align: \"left\",\n anchor: \"bottom-right\",\n font: \"monospace\",\n color: \"#8f96a3\",\n opacity: 0.85,\n reveal: { progress: 1, mode: \"glyphFade\", speed: 6, fade: 0.4 },\n },\n motion: { type: \"static\" },\n position: { x: 0.92, y: 0.86 },\n alpha: [0.9, 0.9],\n },\n ],\n};\n","import type { SaverSpec } from '../types';\nimport type { IdleSequence } from '../types';\nimport { AQUARIUM_SPEC } from './aquarium';\nimport { AURORA_SPEC } from './aurora';\nimport { COMETS_SPEC } from './comets';\nimport { CONSTELLATION_SPEC } from './constellation';\nimport { DASHBOARD_SPEC } from './dev-dashboard';\nimport { SPARSE_NIGHT_SPEC } from './sparse-night';\nimport { SIGNAL_BOARD_SPEC } from './signal-board';\nimport { PHASE_DUET_SPEC } from './phase-duet';\nimport { WEB_WORK_SPEC } from './web-work';\nimport { SHARD_FALL_SPEC } from './shard-fall';\nimport { MURMUR_SPEC } from './murmur';\nimport { THREE_MOVEMENTS_SEQUENCE } from './three-movements';\nimport { FACETS_SPEC } from './facets';\nimport { HAIKU_SPEC } from './haiku';\nimport { LANTERNS_SPEC } from './lanterns';\nimport { LOBBY_TALK_SPEC } from './lobby-talk';\nimport { MATRIX_RAIN_SPEC } from './matrix-rain';\nimport { NOSTALGHIA_CANDLE_SPEC } from './nostalghia-candle';\nimport { POLYGONS_SPEC } from './polygons';\nimport { ORRERY_SPEC } from './orrery';\nimport { PINGS_SPEC } from './pings';\nimport { PROCESSION_SPEC } from './procession';\nimport { RAIN_SPEC } from './rain';\nimport { RELAY_BOARD_SPEC } from './relay-board';\nimport { SAKURA_SPEC } from './sakura';\nimport { SNOWFALL_SPEC } from './snowfall';\nimport { THERMAL_FIELD_SPEC } from './thermal-field';\nimport { WARP_TUNNEL_SPEC } from './warp-tunnel';\nimport { TYPED_CUE_SPEC } from './typed-cue';\n\nexport { AQUARIUM_SPEC } from './aquarium';\nexport { COMETS_SPEC } from './comets';\nexport { CONSTELLATION_SPEC } from './constellation';\nexport { RAIN_SPEC } from './rain';\nexport { SNOWFALL_SPEC } from './snowfall';\nexport { LANTERNS_SPEC } from './lanterns';\nexport { LOBBY_TALK_SPEC } from './lobby-talk';\nexport { SAKURA_SPEC } from './sakura';\nexport { DASHBOARD_SPEC } from './dev-dashboard';\nexport { HAIKU_SPEC } from './haiku';\nexport { ORRERY_SPEC } from './orrery';\nexport { AURORA_SPEC } from './aurora';\nexport { MATRIX_RAIN_SPEC } from './matrix-rain';\nexport { NOSTALGHIA_CANDLE_SPEC } from './nostalghia-candle';\nexport { PINGS_SPEC } from './pings';\nexport { FACETS_SPEC } from './facets';\nexport { RELAY_BOARD_SPEC } from './relay-board';\nexport { POLYGONS_SPEC } from './polygons';\nexport { PROCESSION_SPEC } from './procession';\nexport { WARP_TUNNEL_SPEC } from './warp-tunnel';\nexport { THERMAL_FIELD_SPEC } from './thermal-field';\nexport { SPARSE_NIGHT_SPEC } from './sparse-night';\nexport { TYPED_CUE_SPEC } from './typed-cue';\nexport { SIGNAL_BOARD_SPEC } from './signal-board';\nexport { PHASE_DUET_SPEC } from './phase-duet';\nexport { WEB_WORK_SPEC } from './web-work';\nexport { SHARD_FALL_SPEC } from './shard-fall';\nexport { MURMUR_SPEC } from './murmur';\nexport { THREE_MOVEMENTS_SEQUENCE } from './three-movements';\n\n/** Catalog entry for a bundled schema example. */\nexport interface SchemaExample {\n id: string;\n label: string;\n spec: SaverSpec;\n}\n\n/** Ordered catalog of bundled schema examples. Add new specs as standalone files, then register here. */\nexport const SCHEMA_EXAMPLES: readonly SchemaExample[] = [\n { id: 'aquarium', label: 'Aquarium', spec: AQUARIUM_SPEC },\n { id: 'rain', label: 'Rain', spec: RAIN_SPEC },\n { id: 'snowfall', label: 'Snowfall', spec: SNOWFALL_SPEC },\n { id: 'lanterns', label: 'Night Lanterns', spec: LANTERNS_SPEC },\n { id: 'sakura', label: 'Sakura Drift', spec: SAKURA_SPEC },\n { id: 'dev-dashboard', label: 'Control Center', spec: DASHBOARD_SPEC },\n { id: 'orrery', label: 'Orrery', spec: ORRERY_SPEC },\n { id: 'constellation', label: 'Constellation', spec: CONSTELLATION_SPEC },\n { id: 'comets', label: 'Comet Shower', spec: COMETS_SPEC },\n { id: 'aurora', label: 'Aurora', spec: AURORA_SPEC },\n { id: 'warp-tunnel', label: 'Warp Tunnel', spec: WARP_TUNNEL_SPEC },\n { id: 'polygons', label: 'Polygons', spec: POLYGONS_SPEC },\n { id: 'matrix-rain', label: 'Matrix Rain', spec: MATRIX_RAIN_SPEC },\n { id: 'procession', label: 'Night Procession', spec: PROCESSION_SPEC },\n { id: 'nostalghia-candle', label: \"Nostalghia's Candle\", spec: NOSTALGHIA_CANDLE_SPEC },\n { id: 'haiku', label: 'Haiku', spec: HAIKU_SPEC },\n { id: 'pings', label: 'Pings', spec: PINGS_SPEC },\n { id: 'facets', label: 'Facets', spec: FACETS_SPEC },\n { id: 'relay-board', label: 'Relay Board', spec: RELAY_BOARD_SPEC },\n { id: 'lobby-talk', label: 'Lobby Talk', spec: LOBBY_TALK_SPEC },\n { id: 'thermal-field', label: 'Thermal Field', spec: THERMAL_FIELD_SPEC },\n { id: 'sparse-night', label: 'Sparse Night', spec: SPARSE_NIGHT_SPEC },\n { id: 'typed-cue', label: 'Typed Cue', spec: TYPED_CUE_SPEC },\n { id: 'signal-board', label: 'Signal Board', spec: SIGNAL_BOARD_SPEC },\n { id: 'phase-duet', label: 'Phase Duet', spec: PHASE_DUET_SPEC },\n { id: 'web-work', label: 'Web Work', spec: WEB_WORK_SPEC },\n { id: 'shard-fall', label: 'Shard Fall', spec: SHARD_FALL_SPEC },\n { id: 'murmur', label: 'Murmur', spec: MURMUR_SPEC },\n] as const;\n\n/** Catalog entry for a bundled idle-sequence example. */\nexport interface SequenceExample {\n id: string;\n label: string;\n sequence: IdleSequence;\n}\n\n/**\n * Ordered catalog of bundled idle-sequence examples.\n *\n * Deliberately separate from SCHEMA_EXAMPLES: that catalog is typed\n * `SaverSpec[]` and its consumers (manifests, batch compile, the MCP examples\n * resource) rely on that. A sequence is a different top-level format, so it\n * gets its own list rather than widening theirs.\n */\nexport const EXAMPLE_SEQUENCES: readonly SequenceExample[] = [\n { id: 'three-movements', label: 'Three Movements', sequence: THREE_MOVEMENTS_SEQUENCE },\n];\n\n/** All example specs in catalog order (tests, batch compile). */\nexport const EXAMPLE_SPECS: SaverSpec[] = SCHEMA_EXAMPLES.map((e) => e.spec);\n\n/** Lookup by saver id. */\nexport const EXAMPLE_BY_ID: Readonly<Record<string, SaverSpec>> = Object.fromEntries(\n SCHEMA_EXAMPLES.map((e) => [e.id, e.spec]),\n);\n"],"mappings":";AAYO,IAAM,iBAAiB;AAmrBvB,IAAM,SAAS;AAAA,EACpB,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AAAA;AAAA,EACV,aAAa;AAAA;AAAA,EACb,gBAAgB;AAAA;AAAA,EAChB,SAAS;AAAA;AAAA,EACT,WAAW;AAAA;AAAA,EACX,YAAY;AAAA;AAAA,EACZ,eAAe;AAAA;AAAA,EACf,WAAW;AAAA,EACX,mBAAmB;AAAA,EACnB,gBAAgB;AAAA;AAAA,EAChB,mBAAmB;AAAA;AAAA,EACnB,gBAAgB;AAAA;AAAA,EAChB,iBAAiB;AAAA;AAAA,EACjB,gBAAgB;AAAA;AAAA,EAChB,gBAAgB;AAAA;AAAA,EAChB,eAAe;AAAA;AAAA,EACf,eAAe;AAAA;AAAA,EACf,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,qBAAqB;AAAA;AAAA,EACrB,aAAa;AAAA;AAAA,EACb,sBAAsB;AAAA;AAAA,EACtB,YAAY;AAAA;AAAA,EACZ,cAAc;AAAA;AAAA,EACd,eAAe;AAAA,EACf,eAAe;AAAA,EACf,iBAAiB;AAAA;AAAA,EACjB,gBAAgB;AAAA,EAChB,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,sBAAsB;AAAA;AAAA,EACtB,gBAAgB;AAAA;AAAA,EAChB,iBAAiB;AAAA;AAAA,EACjB,aAAa;AAAA,EACb,oBAAoB;AAAA;AAAA,EACpB,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,cAAc;AAAA;AAAA,EACd,iBAAiB;AAAA,EACjB,wBAAwB;AAAA;AAAA,EACxB,mBAAmB;AAAA;AAAA,EACnB,qBAAqB;AAAA;AAAA,EACrB,yBAAyB;AAAA;AAAA,EACzB,2BAA2B;AAAA;AAAA,EAC3B,wBAAwB;AAAA,EACxB,yBAAyB;AAAA;AAAA,EACzB,WAAW;AAAA,EACX,cAAc;AAAA;AAAA,EACd,aAAa;AAAA;AAAA,EACb,aAAa;AAAA;AAAA,EACb,kBAAkB;AAAA;AAAA,EAClB,cAAc;AAAA,EACd,cAAc;AAAA,EACd,gBAAgB;AAAA;AAAA,EAChB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA;AAAA,EAChB,YAAY;AAAA;AAAA,EACZ,YAAY;AAAA;AACd;;;ACjvBA,IAAM,cAAc,oBAAI,IAAI,CAAC,aAAa,eAAe,WAAW,CAAC;AACrE,IAAM,sBAAsB,oBAAI,IAAI,CAAC,YAAY,qBAAqB,UAAU,QAAQ,CAAC;AAGlF,SAAS,gBAAgB,MAAe,MAAiC;AAC9E,MAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,CAAC,KAAM,QAAO;AACvD,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,MAAI,MAAM,KAAK,CAAC,MAAM,YAAY,IAAI,CAAC,CAAC,EAAG,QAAO;AAClD,QAAM,IAAI;AACV,MAAI,MAAM,CAAC,MAAM,YAAY,MAAM,CAAC,MAAM,gBAAgB,MAAM,QAAQ,EAAE,MAAM,GAAG;AAIjF,UAAM,MAAM,EAAE,OAAO,UAAU,CAAC,MAAM,KAAK,EAAE,QAAQ,MAAM,CAAC,CAAC;AAC7D,QAAI,QAAQ,IAAI;AACd,YAAM,OAAO,GAAG,GAAG,UAAU,OAAO,GAAG,CAAC;AAAA,IAC1C,WAAW,CAAC,oBAAoB,IAAI,MAAM,CAAC,CAAE,GAAG;AAC9C,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,MAAM,CAAC,MAAM,YAAY,MAAM,WAAW,KAAK,MAAM,CAAC,MAAM,QAAS,QAAO;AAChF,MAAI,MAAM,UAAU,KAAK,MAAM,MAAM,SAAS,CAAC,MAAM,YAAY,MAAM,MAAM,SAAS,CAAC,MAAM,YAAa,QAAO;AACjH,MAAI,OAAgB;AACpB,WAAS,IAAI,GAAG,IAAI,MAAM,SAAS,GAAG,KAAK;AACzC,QAAI,SAAS,QAAQ,OAAO,SAAS,SAAU,QAAO;AACtD,WAAQ,KAAiC,MAAM,CAAC,CAAE;AAAA,EACpD;AACA,MAAI,SAAS,QAAQ,OAAO,SAAS,SAAU,QAAO;AACtD,QAAM,OAAO,MAAM,MAAM,SAAS,CAAC;AACnC,QAAM,MAAuB,MAAM,QAAQ,IAAI,IAAI,OAAO,IAAI,IAAI;AAClE,QAAM,SAAS,MAAM,QAAQ,IAAI,IAC7B,OAAO,UAAU,GAAa,KAAM,OAAkB,KAAM,MAAiB,KAAK,SAClF,QAAS;AACb,SAAO,SAAS,EAAE,QAAQ,MAA8B,IAAI,IAAI;AAClE;AAQO,SAAS,kBAAkB,MAAe,MAA6B;AAC5E,MAAI,CAAC,gBAAgB,MAAM,IAAI,EAAG,QAAO;AACzC,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,QAAM,IAAI;AACV,MAAI,MAAM,CAAC,MAAM,YAAY,MAAM,CAAC,MAAM,gBAAgB,MAAM,QAAQ,EAAE,MAAM,GAAG;AACjF,UAAM,MAAM,EAAE,OAAO,UAAU,CAAC,MAAM,KAAK,EAAE,QAAQ,MAAM,CAAC,CAAC;AAC7D,QAAI,QAAQ,GAAI,OAAM,OAAO,GAAG,GAAG,UAAU,OAAO,GAAG,CAAC;AAAA,EAC1D;AACA,SAAO,MAAM,KAAK,GAAG;AACvB;AAGO,SAAS,aAAa,MAAe,MAAuB;AACjE,QAAM,MAAM,gBAAgB,MAAM,IAAI;AACtC,SAAO,MAAO,IAAI,OAA4C,IAAI,GAAG,IAAI;AAC3E;AAEA,IAAM,qBAA6C,EAAE,GAAG,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,EAAE;AAGhG,SAAS,eAAe,GAAY,GAAgC;AAClE,QAAMA,SAAQ,CAAC,MAA6C,CAAC,CAAC,KAAK,OAAO,MAAM,YAAY,CAAC,MAAM,QAAQ,CAAC;AAC5G,MAAI,CAACA,OAAM,CAAC,KAAK,CAACA,OAAM,CAAC,EAAG,QAAO,CAAC,GAAG,CAAC;AACxC,MAAI,KAAqC;AACzC,MAAI,KAAqC;AACzC,aAAW,OAAO,oBAAI,IAAI,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG;AACjE,UAAM,KAAK,mBAAmB,GAAG;AACjC,QAAI,OAAO,OAAW;AACtB,QAAI,EAAE,GAAG,MAAM,OAAW,EAAC,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI;AACnD,QAAI,EAAE,GAAG,MAAM,OAAW,EAAC,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI;AAAA,EACrD;AACA,SAAO,CAAC,MAAM,GAAG,MAAM,CAAC;AAC1B;AASA,SAAS,iBAAiB,GAAY,GAAgC;AACpE,QAAM,KAAM,GAAqC;AACjD,QAAM,KAAM,GAAqC;AACjD,MAAI,CAAC,MAAM,QAAQ,EAAE,KAAK,CAAC,MAAM,QAAQ,EAAE,EAAG,QAAO,CAAC,GAAG,CAAC;AAC1D,MAAI,OAAyB;AAC7B,MAAI,OAAyB;AAC7B,QAAM,IAAI,KAAK,IAAI,GAAG,QAAQ,GAAG,MAAM;AACvC,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,IAAI,GAAG,CAAC;AACd,UAAM,IAAI,GAAG,CAAC;AACd,QAAI,CAAC,KAAK,CAAC,KAAK,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU;AAChE,QAAI,KAAK;AACT,QAAI,KAAK;AAIT,QAAK,EAAE,UAAU,YAAgB,EAAE,UAAU,SAAY;AACvD,UAAI,EAAE,UAAU,OAAW,MAAK,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM;AAAA,UACnD,MAAK,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM;AAAA,IACpC;AACA,QAAK,EAAE,YAAY,YAAgB,EAAE,YAAY,SAAY;AAC3D,UAAI,EAAE,YAAY,OAAW,MAAK,EAAE,GAAG,IAAI,SAAS,EAAE;AAAA,UACjD,MAAK,EAAE,GAAG,IAAI,SAAS,EAAE;AAAA,IAChC;AACA,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,EAAE;AACb,QAAI,MAAM,IAAI;AACZ,YAAM,KAA8B,EAAE,GAAI,MAAM,CAAC,EAAG;AACpD,YAAM,KAA8B,EAAE,GAAI,MAAM,CAAC,EAAG;AACpD,UAAI,UAAU,CAAC,MAAM,CAAC;AACtB,iBAAW,OAAO,oBAAI,IAAI,CAAC,GAAG,OAAO,KAAK,EAAE,GAAG,GAAG,OAAO,KAAK,EAAE,CAAC,CAAC,GAAG;AACnE,cAAM,KAAK,mBAAmB,GAAG;AACjC,YAAI,OAAO,OAAW;AACtB,YAAI,GAAG,GAAG,MAAM,QAAW;AAAE,aAAG,GAAG,IAAI;AAAI,oBAAU;AAAA,QAAM;AAC3D,YAAI,GAAG,GAAG,MAAM,QAAW;AAAE,aAAG,GAAG,IAAI;AAAI,oBAAU;AAAA,QAAM;AAAA,MAC7D;AACA,UAAI,SAAS;AAAE,aAAK,EAAE,GAAG,IAAI,WAAW,GAAG;AAAG,aAAK,EAAE,GAAG,IAAI,WAAW,GAAG;AAAA,MAAG;AAAA,IAC/E;AACA,QAAI,OAAO,EAAG,EAAC,SAAS,GAAG,MAAM,GAAG,CAAC,IAAI;AACzC,QAAI,OAAO,EAAG,EAAC,SAAS,GAAG,MAAM,GAAG,CAAC,IAAI;AAAA,EAC3C;AACA,MAAI,KAAc,OAAO,EAAE,GAAI,GAAc,QAAQ,KAAK,IAAI;AAC9D,MAAI,KAAc,OAAO,EAAE,GAAI,GAAc,QAAQ,KAAK,IAAI;AAG9D,QAAM,KAAM,EAA2D;AACvE,QAAM,KAAM,EAA2D;AACvE,MAAI,MAAM,IAAI;AACZ,UAAM,KAA8C,EAAE,GAAI,MAAM,CAAC,EAAG;AACpE,UAAM,KAA8C,EAAE,GAAI,MAAM,CAAC,EAAG;AACpE,QAAI,UAAU,CAAC,MAAM,CAAC;AACtB,eAAW,QAAQ,oBAAI,IAAI,CAAC,GAAG,OAAO,KAAK,EAAE,GAAG,GAAG,OAAO,KAAK,EAAE,CAAC,CAAC,GAAG;AACpE,YAAM,IAAI,GAAG,IAAI,KAAK,CAAC;AACvB,YAAM,IAAI,GAAG,IAAI,KAAK,CAAC;AACvB,UAAI,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,IAAI,EAAG,WAAU;AACtC,UAAI,KAAK;AACT,UAAI,KAAK;AACT,UAAK,EAAE,YAAY,YAAgB,EAAE,YAAY,SAAY;AAC3D,YAAI,EAAE,YAAY,OAAW,MAAK,EAAE,GAAG,IAAI,SAAS,EAAE;AAAA,YACjD,MAAK,EAAE,GAAG,IAAI,SAAS,EAAE;AAC9B,kBAAU;AAAA,MACZ;AACA,UAAI,CAAC,EAAE,cAAc,CAAC,EAAE,WAAW;AACjC,YAAI,CAAC,EAAE,UAAW,MAAK,EAAE,GAAG,IAAI,WAAW,CAAC,EAAE;AAAA,YACzC,MAAK,EAAE,GAAG,IAAI,WAAW,CAAC,EAAE;AACjC,kBAAU;AAAA,MACZ;AACA,SAAG,IAAI,IAAI;AACX,SAAG,IAAI,IAAI;AAAA,IACb;AACA,QAAI,SAAS;AACX,WAAK,EAAE,GAAI,IAAe,QAAQ,GAAG;AACrC,WAAK,EAAE,GAAI,IAAe,QAAQ,GAAG;AAAA,IACvC;AAAA,EACF;AACA,SAAO,CAAC,IAAI,EAAE;AAChB;AAYO,SAAS,kBAAkB,MAAiB,QAAiC;AAClF,QAAM,OAAO,KAAK,MAAM,KAAK,UAAU,IAAI,CAAC;AAC5C,aAAW,KAAK,QAAQ;AACtB,UAAM,MAAM,gBAAgB,MAAM,EAAE,IAAI;AACxC,QAAI,IAAK,CAAC,IAAI,OAA4C,IAAI,GAAG,IAAI,EAAE;AAAA,EACzE;AACA,SAAO;AACT;AAEA,IAAM,MAAM;AAEZ,SAAS,SAAS,KAAuC;AACvD,QAAM,IAAI,IAAI,WAAW,IAAI,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK;AACzF,QAAM,IAAI,SAAS,EAAE,MAAM,CAAC,GAAG,EAAE;AACjC,SAAO,CAAE,KAAK,KAAM,KAAM,KAAK,IAAK,KAAK,IAAI,GAAG;AAClD;AAEA,SAAS,QAAQ,GAAW,GAAW,GAAmB;AACxD,QAAM,KAAK,SAAS,CAAC;AACrB,QAAM,KAAK,SAAS,CAAC;AACrB,QAAM,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,KAAK,MAAM,KAAK,GAAG,CAAC,IAAK,KAAK,CAAC,CAAC;AAC7D,SAAO,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AACrE;AAQO,SAAS,SAAS,MAAiB,IAAe,GAAsB;AAC7E,QAAM,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AACrC,QAAM,MAAM,UAAU,MAAM,IAAI,IAAI,IAAI;AACxC,SAAO;AACT;AASO,SAAS,UAAU,MAAe,IAAa,GAAW,WAAW,OAAO,SAA2B;AAC5G,MAAI,SAAU,EAAC,MAAM,EAAE,IAAI,iBAAiB,MAAM,EAAE;AACpD,MAAI,YAAY,YAAa,EAAC,MAAM,EAAE,IAAI,eAAe,MAAM,EAAE;AACjE,QAAM,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AACrC,QAAM,OAAO,CAAC,GAAY,GAAY,KAAuB,OAAO,UAAmB;AACrF,QAAI,OAAO,MAAM,YAAY,OAAO,MAAM,UAAU;AAClD,YAAM,IAAI,KAAK,IAAI,KAAK;AACxB,UAAI,QAAQ,QAAS,QAAO,KAAK,IAAI,GAAG,KAAK,MAAM,CAAC,CAAC;AAKrD,UAAI,QAAQ,UAAW,QAAO,KAAK,MAAM,CAAC;AAC1C,UAAI,QAAQ,YAAY;AAAE,cAAM,IAAI,KAAK,MAAM,CAAC;AAAG,eAAO,IAAI,IAAI,IAAI;AAAA,MAAG;AACzE,aAAO;AAAA,IACT;AACA,QAAI,OAAO,MAAM,YAAY,OAAO,MAAM,YAAY,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG;AAChF,aAAO,QAAQ,GAAG,GAAG,EAAE;AAAA,IACzB;AACA,QAAI,QAAQ,UAAU,OAAO,MAAM,YAAY,OAAO,MAAM,YAAY,MAAM,GAAG;AAG/E,YAAM,IAAI,UAAU,GAAG,GAAG,EAAE;AAC5B,UAAI,MAAM,KAAM,QAAO;AAAA,IACzB;AACA,QAAI,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ;AACjE,aAAO,EAAE,IAAI,CAAC,IAAI,MAAM,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;AAAA,IAC3C;AACA,QAAI,KAAK,KAAK,OAAO,MAAM,YAAY,OAAO,MAAM,YAAY,CAAC,MAAM,QAAQ,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,GAAG;AACtG,YAAM,MAA+B,CAAC;AACtC,iBAAW,SAAS,OAAO,KAAK,CAA4B,GAAG;AAC7D,cAAM,KAAM,EAA8B,KAAK;AAC/C,cAAM,KAAM,EAA8B,KAAK;AAC/C,YAAI,KAAK,IAAI,QAAQ,UAAU,aAAc,KAAK,IAAI,KAAK,KAAM,UAAU,cAAc,KAAK,GAAG,eAAe,IAAI,EAAE,GAAG,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK;AAAA,MACtJ;AACA,aAAO;AAAA,IACT;AACA,WAAO,KAAK,IAAI,IAAI;AAAA,EACtB;AACA,SAAO,KAAK,MAAM,IAAI,SAAS,QAAQ;AACzC;AAEA,IAAM,aAAa;AAQZ,SAAS,UAAU,GAAW,GAAW,GAA0B;AACxE,QAAM,KAAK,EAAE,MAAM,UAAU,KAAK,CAAC;AACnC,QAAM,KAAK,EAAE,MAAM,UAAU,KAAK,CAAC;AACnC,MAAI,GAAG,WAAW,GAAG,OAAQ,QAAO;AACpC,QAAM,MAAgB,CAAC;AACvB,MAAI,MAAM;AACV,MAAI,WAAW;AACf,WAAS,IAAI,GAAG,IAAI,GAAG,QAAQ,KAAK;AAClC,UAAM,IAAI,GAAG,CAAC,GAAI,IAAI,GAAG,CAAC;AAC1B,UAAM,SAAS,aAAa,KAAK,CAAC,GAAG,SAAS,aAAa,KAAK,CAAC;AACjE,QAAI,WAAW,OAAQ,QAAO;AAC9B,QAAI,QAAQ;AACV,UAAI,MAAM,EAAG,QAAO;AACpB,YAAM,EAAE,YAAY;AACpB,iBAAW;AACX,UAAI,KAAK,CAAC;AACV;AAAA,IACF;AACA,UAAM,KAAK,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC;AACnC,UAAM,OAAO,QAAQ,QAAQ,WAAW,MAAM,KAAK,WAAW,MAAM;AACpE;AACA,UAAM,IAAI,MAAM,KAAK,MAAM;AAC3B,QAAI,KAAK,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,IAAI,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;AAAA,EAC/D;AACA,SAAO,IAAI,KAAK,GAAG;AACrB;AAMO,SAAS,cAAc,QAAqC;AACjE,MAAI,OAAO,SAAS,OAAQ,QAAO,OAAO;AAC1C,MAAI,OAAO,SAAS,YAAa,QAAO,CAAC,OAAO,IAAI;AACpD,SAAO;AACT;AAOO,SAAS,kBAAkB,GAAc,GAAc,GAAoB;AAChF,QAAM,KAAK,EAAE,OAAO,CAAC,GAAG;AACxB,QAAM,KAAK,EAAE,OAAO,CAAC,GAAG;AACxB,MAAI,CAAC,MAAM,CAAC,GAAI,QAAO;AACvB,QAAM,KAAK,cAAc,EAAE;AAC3B,QAAM,KAAK,cAAc,EAAE;AAC3B,MAAI,CAAC,MAAM,CAAC,GAAI,QAAO;AACvB,SAAO,GAAG,WAAW,GAAG,UAAU,GAAG,KAAK,CAAC,GAAG,MAAM,MAAM,GAAG,CAAC,CAAC;AACjE;AAoBA,IAAM,oBAAoB,oBAAI,IAAI,CAAC,MAAM,SAAS,iBAAiB,KAAK,CAAC;AAElE,SAAS,sBAAsB,GAAc,GAAc,OAAoC,CAAC,GAAY;AACjH,MAAI,KAAK,iBAAiB,EAAE,OAAO,KAAK,CAAC,GAAG,MAAM,kBAAkB,GAAG,GAAG,CAAC,CAAC,EAAG,QAAO;AACtF,MAAI,UAAU;AACd,MAAI,WAAW;AACf,QAAM,OAAO,CAAC,GAAY,GAAY,QAAuB;AAC3D,QAAI,QAAQ,UAAa,kBAAkB,IAAI,GAAG,EAAG;AACrD,QAAI,MAAM,EAAG;AACb,QAAI,OAAO,MAAM,YAAY,OAAO,MAAM,UAAU;AAClD,gBAAU;AACV,iBAAW;AACX;AAAA,IACF;AACA,QAAI,OAAO,MAAM,YAAY,OAAO,MAAM,YAAY,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG;AAChF,YAAM,KAAK,SAAS,CAAC;AACrB,YAAM,KAAK,SAAS,CAAC;AACrB,UAAI,GAAG,KAAK,CAAC,GAAG,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG;AAClC,kBAAU;AACV,mBAAW;AAAA,MACb;AAEA;AAAA,IACF;AACA,QAAI,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ;AACjE,eAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,IAAK,MAAK,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;AAClD;AAAA,IACF;AACA,QAAI,KAAK,KAAK,OAAO,MAAM,YAAY,OAAO,MAAM,YAAY,CAAC,MAAM,QAAQ,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,GAAG;AACtG,YAAM,OAAO,oBAAI,IAAI,CAAC,GAAG,OAAO,KAAK,CAA4B,GAAG,GAAG,OAAO,KAAK,CAA4B,CAAC,CAAC;AACjH,iBAAW,KAAK,MAAM;AACpB,aAAM,EAA8B,CAAC,GAAI,EAA8B,CAAC,GAAG,CAAC;AAAA,MAC9E;AACA;AAAA,IACF;AACA,cAAU;AAAA,EACZ;AACA,OAAK,GAAG,CAAC;AACT,SAAO,WAAW,CAAC;AACrB;AAiBO,SAAS,eAAe,MAAyB;AACtD,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO,CAAC;AAI/C,QAAM,OAAO,oBAAI,IAAI,CAAC,QAAQ,QAAQ,OAAO,iBAAiB,MAAM,SAAS,QAAQ,SAAS,mBAAmB,QAAQ,SAAS,SAAS,SAAS,QAAQ,CAAC;AAC7J,QAAM,YAAY,oBAAI,IAAI,CAAC,UAAU,CAAC;AAGtC,QAAM,UAAU,oBAAI,IAAI,CAAC,UAAU,SAAS,SAAS,OAAO,CAAC;AAI7D,QAAM,SAAU,KAA8B;AAC9C,QAAM,mBAAmB,IAAI;AAAA,IAC3B,MAAM,QAAQ,MAAM,IAChB,OACG,IAAI,CAAC,MAAO,KAAK,OAAO,MAAM,WAAY,EAA8B,MAAM,MAAU,EACxF,OAAO,CAAC,MAAmB,OAAO,MAAM,YAAY,oBAAoB,IAAI,CAAC,CAAC,IACjF,CAAC;AAAA,EACP;AACA,QAAM,MAAgB,CAAC;AACvB,QAAM,OAAO,CAAC,MAAe,QAAgB,QAAsB;AACjE,QAAI,MAAM,QAAQ,IAAI,KAAK,QAAQ,IAAI,GAAG,GAAG;AAC3C,WAAK,QAAQ,CAAC,OAAO,MAAM,KAAK,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;AAC5D;AAAA,IACF;AACA,QAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,UAAI,OAAQ,KAAI,KAAK,MAAM;AAC3B;AAAA,IACF;AACA,QAAI,QAAQ,OAAO,SAAS,UAAU;AACpC,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,IAA+B,GAAG;AAEpE,YAAI,KAAK,IAAI,CAAC,KAAK,WAAW,SAAU;AACxC,YAAI,CAAC,WAAW,iBAAiB,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,GAAI;AAC9D,aAAK,GAAG,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,GAAG,CAAC;AAAA,MAC1C;AACA;AAAA,IACF;AACA,QAAI,OAAQ,KAAI,KAAK,MAAM;AAAA,EAC7B;AACA,OAAK,MAAM,IAAI,EAAE;AACjB,QAAM,UAAU,qBAAqB,IAAI;AACzC,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SAAO,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,KAAK,CAAC,OAAO,MAAM,MAAM,EAAE,WAAW,GAAG,EAAE,GAAG,CAAC,CAAC;AACpF;AASO,SAAS,uBAAuB,KAA6B;AAClE,QAAM,MAAM,oBAAI,IAAY,CAAC,kBAAkB,CAAC;AAChD,MAAI,IAAI,IAAK,YAAW,KAAK,eAAe,IAAI,GAAG,EAAG,KAAI,IAAI,OAAO,CAAC,EAAE;AACxE,aAAW,OAAO,IAAI,SAAU,YAAW,KAAK,eAAe,IAAI,KAAK,EAAG,KAAI,IAAI,CAAC;AACpF,SAAO,CAAC,GAAG,GAAG;AAChB;AAGO,SAAS,WAAW,GAAmB;AAC5C,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AACpC,SAAO,IAAI,KAAK,IAAI,IAAI;AAC1B;AAMO,SAAS,oBAAoB,MAAyB;AAC3D,SAAO,KAAK,UAAU;AAAA,IACpB,KAAK;AAAA;AAAA;AAAA;AAAA,IAIL,KAAK,qBAAqB,OAAO;AAAA,IACjC,KAAK,OAAO,IAAI,CAAC,MAAM;AACrB,YAAM,IAAI,EAAE;AACZ,aAAO;AAAA,QACL,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE,OAAO;AAAA;AAAA;AAAA,QAGT,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE,OAAO,SAAS,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,IAAI,EAAE,OAAO,SAAS,QAAQ,CAAC,EAAE,QAAQ,EAAE,SAAS,IAAI;AAAA,QACrG,MAAM,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,SAAS;AAAA,QAC5C,EAAE;AAAA,QACF,EAAE,OAAO,SAAS,UACd,CAAC,EAAE,OAAO,OAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,IAC/C,EAAE,OAAO,SAAS,SAChB,CAAC,EAAE,OAAO,QAAQ,QAAQ,EAAE,OAAO,OAAO,MAAM,IAChD,EAAE,OAAO,SAAS,cAIf,EAAE,OAAO,SAAS,CAAC,EAAE,OAAO,UAAU,EAAE,OAAO,MAAM,IAAI,CAAC,EAAE,OAAO,QAAQ,IAC5E;AAAA;AAAA;AAAA,QAGR,GAAI,EAAE,WAAW,SAAY,CAAC,EAAE,MAAM,IAAI,CAAC;AAAA,MAC7C;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;;;ACrfO,SAAS,aAAa,KAAmB,OAAuB;AACrE,MAAI,IAAI;AACR,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,IAAI,SAAS,SAAS,CAAC,CAAC;AAC9D,WAAS,IAAI,GAAG,IAAI,GAAG,IAAK,MAAK,IAAI,SAAS,CAAC,EAAG,YAAY;AAC9D,SAAO;AACT;AAoBO,SAAS,eAAe,KAAmB,GAAW,OAAuB,CAAC,GAAoB;AACvG,QAAM,EAAE,UAAU,KAAK,IAAI;AAC3B,MAAI,SAAS,WAAW,EAAG,QAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,EAAE;AAEnE,MAAI,aAAa;AACjB,aAAW,OAAO,UAAU;AAC1B,QAAI,IAAI,YAAY,KAAM,eAAc,IAAI;AAAA,QACvC;AAAA,EACP;AAEA,QAAM,KAAK,KAAK,IAAI,GAAG,CAAC;AAGxB,QAAM,OAAO,CAAC,GAAW,kBAAkD;AACzE,QAAI,aAAa;AACjB,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,YAAM,MAAM,SAAS,CAAC;AACtB,UAAI,IAAI,YAAY,MAAM;AAGxB,eAAO,OAAO,OAAO,EAAE,OAAO,GAAG,QAAQ,IAAI,YAAY,QAAQ,WAAW;AAAA,MAC9E;AACA,UAAI,IAAI,aAAa,IAAI,UAAU;AACjC,eAAO,EAAE,OAAO,GAAG,QAAQ,IAAI,YAAY,QAAQ,WAAW;AAAA,MAChE;AACA,UAAI,IAAI,YAAY,WAAW,KAAK,eAAe;AACjD,eAAO,EAAE,OAAO,GAAG,QAAQ,IAAI,YAAY,QAAQ,YAAY,MAAM,KAAK;AAAA,MAC5E;AACA,oBAAc,IAAI;AAAA,IACpB;AACA,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,KAAK,IAAI,KAAK,iBAAiB,CAAC;AAC9C,MAAI,MAAO,QAAO;AAElB,MAAI,QAAQ,aAAa,GAAG;AAK1B,UAAM,UAAU,KAAK,KAAK,YAAY,CAAC;AACvC,QAAI,QAAS,QAAO;AAAA,EACtB;AAEA,QAAM,OAAO,SAAS,SAAS;AAC/B,QAAM,YAAY,cAAc,SAAS,IAAI,EAAG,YAAY;AAC5D,SAAO,EAAE,OAAO,MAAM,QAAQ,KAAK,WAAW,QAAQ,UAAU;AAClE;AAUO,SAAS,SAAS,KAAmB,MAAuB;AACjE,QAAM,MAAM,IAAI,SAAS,IAAI;AAC7B,MAAI,CAAC,OAAO,IAAI,YAAY,SAAS,QAAS,QAAO;AACrD,QAAM,OAAO,IAAI,SAAS,OAAO,CAAC;AAClC,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,oBAAoB,IAAI,KAAK,MAAM,oBAAoB,KAAK,KAAK;AAC1E;AASO,SAAS,eAAe,KAAmB,OAAuB;AACvE,MAAI,IAAI;AACR,SAAO,IAAI,KAAK,SAAS,KAAK,IAAI,CAAC,EAAG;AACtC,SAAO;AACT;AAUO,SAAS,aAAa,KAA4B;AACvD,MAAI,IAAI,cAAc,QAAQ,IAAI,SAAS,KAAM,QAAO;AACxD,QAAM,OAAO,IAAI,SAAS,SAAS;AACnC,MAAI,OAAO,EAAG,QAAO;AACrB,QAAM,MAAM,IAAI,SAAS,IAAI;AAC7B,MAAI,IAAI,YAAY,SAAS,WAAW,IAAI,YAAY,KAAM,QAAO;AACrE,MAAI,eAAe,KAAK,IAAI,MAAM,EAAG,QAAO;AAC5C,SAAO,oBAAoB,IAAI,KAAK,MAAM,oBAAoB,IAAI,SAAS,CAAC,EAAG,KAAK;AACtF;AAGO,SAAS,cAAc,MAAsB;AAClD,SAAQ,SAAS,KAAM;AACzB;AASO,SAAS,kBAAkB,KAAmB,OAAmC;AACtF,QAAM,OAAO,eAAe,KAAK,KAAK;AACtC,QAAM,QAAQ,IAAI,SAAS,IAAI,GAAG;AAClC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,MAAM,MAAM,SAAS,IAAI,SAAS,SAAY,IAAI,OAAO,OAAO;AACtE,SAAO,QAAQ,SAAY,SAAY,cAAc,GAAG;AAC1D;AAQO,SAAS,cAAc,KAAuC;AACnE,MAAI,CAAC,IAAI,IAAK,QAAO;AACrB,QAAM,MAAM,IAAI,IAAI,SAAS,IAAI,SAAS,SAAY,IAAI,OAAO,OAAO,cAAc;AACtF,SAAO,QAAQ,SAAY,SAAY,cAAc,GAAG;AAC1D;AASO,SAAS,oBAAoB,KAA4B;AAC9D,SAAO,IAAI,WAAW,UAAa,IAAI,SAAS,KAAK,CAAC,MAAM,EAAE,MAAM,WAAW,MAAS;AAC1F;AA4CO,SAAS,uBAAuB,MAAoB,MAA6B;AACtF,MAAI,KAAK,SAAS,WAAW,KAAK,SAAS,OAAQ,QAAO;AAI1D,MAAI,KAAK,WAAW,UAAa,KAAK,WAAW,QAAW;AAC1D,QAAK,KAAK,SAAS,YAAgB,KAAK,SAAS,QAAY,QAAO;AACpE,QAAI,KAAK,SAAS,UAAa,KAAK,SAAS,UAAa,cAAc,KAAK,IAAI,MAAM,cAAc,KAAK,IAAI,EAAG,QAAO;AAAA,EAC1H;AACA,MAAI,oBAAoB,IAAI,MAAM,oBAAoB,IAAI,EAAG,QAAO;AACpE,MAAI,KAAK,SAAS,KAAK,KAAM,QAAO;AACpC,OAAK,KAAK,QAAQ,cAAc,KAAK,QAAQ,SAAU,QAAO;AAC9D,MAAI,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,KAAK,IAAK,QAAO;AACtC,MAAI,KAAK,OAAO,KAAK,KAAK;AACxB,QAAI,oBAAoB,KAAK,GAAG,MAAM,oBAAoB,KAAK,GAAG,EAAG,QAAO;AAC5E,QAAI,cAAc,IAAI,MAAM,cAAc,IAAI,EAAG,QAAO;AAAA,EAC1D;AACA,WAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC7C,UAAM,IAAI,KAAK,SAAS,CAAC;AACzB,UAAM,IAAI,KAAK,SAAS,CAAC;AACzB,QAAI,EAAE,aAAa,EAAE,SAAU,QAAO;AACtC,SAAK,EAAE,WAAW,aAAa,EAAE,WAAW,QAAS,QAAO;AAC5D,QAAI,cAAc,EAAE,UAAU,MAAM,cAAc,EAAE,UAAU,EAAG,QAAO;AACxE,QAAI,oBAAoB,EAAE,KAAK,MAAM,oBAAoB,EAAE,KAAK,EAAG,QAAO;AAC1E,QAAI,kBAAkB,MAAM,CAAC,MAAM,kBAAkB,MAAM,CAAC,EAAG,QAAO;AAAA,EACxE;AACA,SAAO;AACT;AAGA,SAAS,cAAc,IAA4C;AACjE,MAAI,CAAC,MAAM,GAAG,SAAS,MAAO,QAAO;AACrC,MAAI,GAAG,SAAS,QAAS,QAAO,SAAS,GAAG,GAAG,IAAI,GAAG,QAAQ,MAAM;AACpE,SAAO,QAAQ,GAAG,GAAG;AACvB;;;ACnPO,IAAM,kBAAkB;AAG/B,IAAM,cAAc,oBAAI,QAAuD;AAGxE,SAAS,gBAAgB,MAA4B;AAC1D,MAAI,CAAC,KAAK,SAAU,QAAO;AAC3B,QAAM,OAA2B,EAAE,GAAG,KAAK;AAC3C,SAAO,KAAK;AACZ,SAAO;AACT;AAQO,SAAS,eAAe,MAAyB;AACtD,QAAM,KAAK,KAAK;AAChB,MAAI,CAAC,GAAI,QAAO,oBAAI,IAAI;AACxB,QAAM,MAAM,YAAY,IAAI,EAAE;AAC9B,MAAI,OAAO,IAAI,SAAS,KAAM,QAAO,IAAI;AACzC,QAAM,OAAO,gBAAgB,IAAI;AACjC,QAAM,SAAiB,oBAAI,IAAI;AAC/B,aAAW,KAAK,GAAG,QAAQ,CAAC,GAAG;AAC7B,UAAM,KAAK,kBAAkB,MAAM,EAAE,IAAI;AACzC,QAAI,CAAC,GAAI;AACT,UAAM,OAAO,OAAO,IAAI,EAAE,KAAK,CAAC;AAChC,SAAK,KAAK,CAAC;AACX,WAAO,IAAI,IAAI,IAAI;AAAA,EACrB;AACA,aAAW,QAAQ,OAAO,OAAO,EAAG,MAAK,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC;AACjE,cAAY,IAAI,IAAI,EAAE,MAAM,OAAO,CAAC;AACpC,SAAO;AACT;AAGO,SAAS,kBAAkB,IAAc,GAAmB;AACjE,QAAM,IAAI,GAAG,YAAY;AACzB,MAAI,GAAG,QAAQ,IAAI,EAAG,SAAS,IAAI,IAAK,KAAK;AAC7C,SAAO;AACT;AAEA,SAAS,KAAK,GAAgB,GAAmB;AAC/C,QAAM,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI;AACpC,MAAI,EAAE,SAAS,OAAQ,QAAO,KAAK,IAAI,IAAI;AAC3C,MAAI,EAAE,SAAS,SAAU,QAAO;AAChC,SAAO,WAAW,CAAC;AACrB;AAGA,SAAS,UAAU,MAAqB,OAAgB,IAAY,MAAwB;AAC1F,MAAI,OAAO;AACX,MAAI,MAA0B;AAC9B,QAAM,KAAK,CAAC,QAAyB;AACnC,QAAI,CAAC,IAAK,QAAO;AACjB,UAAM,MAAM,IAAI,OAAO;AACvB,QAAI,OAAO,KAAK,OAAO,IAAI,IAAI,IAAK,QAAO,IAAI;AAC/C,WAAO,UAAU,MAAM,IAAI,OAAO,KAAK,MAAM,MAAM,IAAI,KAAK,GAAG,GAAG,OAAO,IAAI;AAAA,EAC/E;AACA,aAAW,KAAK,MAAM;AACpB,QAAI,EAAE,IAAI,GAAI;AACd,WAAO,GAAG,EAAE,CAAC;AACb,UAAM;AAAA,EACR;AACA,SAAO,GAAG,EAAE;AACd;AAOO,SAAS,kBAAkB,MAAiB,GAAsB;AACvE,QAAM,KAAK,KAAK;AAChB,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,OAAO,gBAAgB,IAAI;AACjC,QAAM,SAAS,eAAe,IAAI;AAClC,MAAI,OAAO,SAAS,EAAG,QAAO;AAC9B,QAAM,KAAK,kBAAkB,IAAI,CAAC;AAClC,QAAM,SAA6D,CAAC;AACpE,aAAW,CAAC,MAAM,IAAI,KAAK,QAAQ;AACjC,UAAM,QAAQ,GAAG,OAAO,KAAK,KAAK,SAAS,CAAC,EAAG,QAAQ,aAAa,MAAM,IAAI;AAC9E,WAAO,KAAK,EAAE,GAAG,GAAG,MAAM,OAAO,UAAU,MAAM,OAAO,IAAI,KAAK,MAAM,KAAK,YAAY,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC;AAAA,EACtG;AACA,SAAO,kBAAkB,MAAM,MAAM;AACvC;AASO,SAAS,aAAa,MAAiB,MAAc,GAA+C;AACzG,QAAM,KAAK,KAAK;AAChB,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,KAAK,kBAAkB,gBAAgB,IAAI,GAAG,IAAI;AACxD,QAAM,OAAO,KAAK,eAAe,IAAI,EAAE,IAAI,EAAE,IAAI;AACjD,MAAI,CAAC,QAAQ,KAAK,WAAW,EAAG,QAAO;AACvC,QAAM,KAAK,kBAAkB,IAAI,CAAC;AAClC,QAAM,OAAO,KAAK,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE;AACtC,MAAI,KAAM,QAAO,EAAE,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,OAAO,gBAAgB;AAC3E,MAAI,GAAG,SAAS,GAAG,YAAY,KAAK,GAAG;AACrC,UAAM,QAAQ,KAAK,CAAC;AACpB,WAAO,EAAE,IAAI,KAAK,GAAG,WAAY,MAAM,MAAM,GAAG,KAAK,MAAM,OAAO,gBAAgB;AAAA,EACpF;AACA,SAAO;AACT;AAWO,SAAS,oBAAoB,MAAiB,QAAQ,MAAM,MAAM,KAAK,MAA4C;AACxH,QAAM,KAAK,KAAK;AAChB,MAAI,CAAC,GAAI,QAAO,CAAC;AACjB,QAAM,IAAI,GAAG,YAAY;AACzB,QAAM,OAAO,CAAC,MAAuB,GAAG,QAAQ,IAAI,KAAM,IAAI,IAAK,KAAK,IAAI;AAK5E,QAAM,SAAS,oBAAI,IAAY,CAAC,CAAC,CAAC;AAClC,QAAM,SAAS,oBAAI,IAAY;AAC/B,QAAM,OAAsB,CAAC;AAC7B,aAAW,CAAC,MAAM,IAAI,KAAK,eAAe,IAAI,EAAG,KAAI,CAAC,QAAQ,KAAK,IAAI,EAAG,MAAK,KAAK,GAAG,IAAI;AAC3F,aAAW,KAAK,MAAM;AACpB,QAAI,CAAC,OAAO,SAAS,EAAE,CAAC,EAAG;AAC3B,UAAM,MAAM,EAAE,OAAO;AACrB,WAAO,IAAI,KAAK,EAAE,CAAC,CAAC;AACpB,WAAO,IAAI,KAAK,EAAE,IAAI,GAAG,CAAC;AAC1B,QAAI,MAAO,YAAW,KAAK,CAAC,MAAM,KAAK,IAAI,EAAG,QAAO,IAAI,KAAK,EAAE,IAAI,MAAM,CAAC,CAAC;AAAA,EAC9E;AACA,MAAI,QAAQ,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAC1E,MAAI,MAAM,SAAS,KAAK;AACtB,UAAM,OAAO,MAAM,SAAS;AAC5B,YAAQ,MAAM,KAAK,EAAE,QAAQ,IAAI,GAAG,CAAC,GAAG,MAAM,MAAM,KAAK,MAAM,IAAI,IAAI,CAAC,CAAE;AAAA,EAC5E;AACA,SAAO,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,QAAQ,GAAG,KAAK,CAAC,CAAC,EAAE,OAAO,OAAO,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACzF;AAGO,SAAS,yBAAyB,MAAiB,KAAa,QAAQ,OAAO,MAA4C;AAChI,QAAM,KAAK,KAAK;AAChB,MAAI,CAAC,GAAI,QAAO,CAAC;AACjB,QAAM,QAAQ,oBAAoB,MAAM,OAAO,KAAK,IAAI;AACxD,QAAM,IAAI,GAAG,YAAY;AACzB,MAAI,GAAG,QAAQ,IAAI,GAAG;AACpB,UAAM,SAAU,MAAM,IAAK,KAAK;AAChC,WAAO,MAAM,IAAI,CAAC,MAAM,QAAS,IAAI,SAAS,IAAK,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAAA,EACjF;AACA,SAAO,MAAM,OAAO,CAAC,MAAM,IAAI,GAAG;AACpC;;;ACxKO,SAAS,eAAe,GAAkC;AAC/D,SAAO,EAAE,SAAS,YAAY,EAAE,SAAS,UAAU,EAAE,SAAS,YAAY,EAAE,SAAS,UAAU,EAAE,SAAS,aAAa,EAAE,SAAS,YAAY,EAAE,SAAS;AAC3J;AAGO,SAAS,YAAY,GAAc,OAAuB;AAC/D,QAAM,IAAI,EAAE,OAAO;AACnB,MAAI,MAAM,EAAG,QAAO;AACpB,QAAM,IAAI,EAAE,QAAS,QAAQ,IAAK,KAAK,CAAC,KAAK;AAC7C,QAAM,MAAM,EAAE,OAAO,EAAE,OAAO,OAAO,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC;AAChE,MAAI,EAAE,MAAM,GAAI,QAAO;AACvB,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,IAAI,GAAG,CAAC;AACzC;AAGO,SAAS,OAAO,WAAgD,KAAa,OAAyE;AAC3J,UAAQ,WAAW;AAAA,IACjB,KAAK;AAAQ,aAAO,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,OAAO,MAAM,GAAG,OAAO,QAAQ,EAAE;AAAA,IAC5E,KAAK;AAAM,aAAO,EAAE,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,OAAO,QAAQ,GAAG,OAAO,MAAM,EAAE;AAAA,IAC1E,KAAK;AAAQ,aAAO,EAAE,IAAI,GAAG,IAAI,MAAM,GAAG,OAAO,QAAQ,GAAG,OAAO,MAAM,EAAE;AAAA,IAC3E;AAAS,aAAO,EAAE,IAAI,MAAM,GAAG,IAAI,GAAG,OAAO,MAAM,GAAG,OAAO,QAAQ,EAAE;AAAA,EACzE;AACF;AAEO,IAAM,wBAAwB;AAE9B,IAAM,iBAAiB;AAGvB,SAAS,cAAc,GAAkB,QAAiD;AAC/F,MAAI,cAAc,CAAC,GAAG;AACpB,UAAM,OAAO,cAAc,CAAC;AAC5B,QAAI,KAAK,OAAO,UAAU,EAAG,QAAO,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,QAAQ,GAAG,IAAI,OAAO,EAAE;AAAA,EACpG;AACA,MAAI,EAAE,UAAU,EAAE,OAAO,UAAU,GAAG;AACpC,WAAO,EAAE,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,QAAQ,GAAG,IAAI,OAAO,EAAE;AAAA,EACpE;AACA,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,SAAS,qBAAqB,CAAC;AAClE,QAAM,MAAuC,CAAC;AAC9C,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,IAAI,CAAC,KAAK,KAAK,IAAK,IAAI,KAAK,KAAK,IAAK;AAC7C,QAAI,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC,IAAI,QAAQ,GAAG,KAAK,IAAI,CAAC,IAAI,OAAO,CAAC;AAAA,EAC/D;AACA,SAAO;AACT;AAQO,SAAS,YAAY,KAA8C;AACxE,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,UAAM,IAAI,IAAI,CAAC;AACf,UAAM,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM;AAClC,SAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;AAAA,EAC3B;AACA,SAAO,KAAK,IAAI,CAAC,IAAI;AACvB;AAOO,SAAS,YAAY,GAAkB,QAAwB;AACpE,MAAI,UAAU,EAAG,QAAO;AACxB,QAAM,OAAO,KAAK,KAAK,SAAS;AAChC,SAAO,KAAK,IAAI,GAAG,YAAY,cAAc,GAAG,MAAM,CAAC,IAAI,IAAI;AACjE;AAEA,SAAS,WAAW,IAAY,IAAY,IAAY,IAAY,GAAmB;AACrF,QAAM,KAAK,IAAI;AACf,QAAM,KAAK,KAAK;AAChB,SAAO,OAAO,IAAI,MAAM,CAAC,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM,MAAM,CAAC,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM;AAChH;AASO,SAAS,cAAc,GAAiB,UAAkB,GAA6C;AAC5G,QAAM,MAAM,EAAE,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,UAAU,GAAG,IAAI,SAAS,EAAE;AAC3E,QAAM,IAAI,IAAI;AACd,MAAI,IAAI,EAAG,QAAO;AAClB,QAAM,SAAS,EAAE,UAAU,YAAY,KAAK;AAC5C,QAAM,OAAO,IAAI;AAGjB,MAAI,KAAK,KAAK,IAAI,gBAAgB,OAAO,IAAI,CAAC;AAC9C,QAAM,KAAK,CAAC,MAAwC,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;AACvF,QAAM,MAAuC,CAAC;AAC9C,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,IAAK,KAAK,IAAI,KAAM;AAC1B,UAAM,MAAM,KAAK,IAAI,OAAO,GAAG,KAAK,MAAM,CAAC,CAAC;AAC5C,UAAM,QAAQ,IAAI;AAClB,UAAM,KAAK,GAAG,GAAG;AACjB,UAAM,KAAK,GAAG,MAAM,CAAC;AACrB,QAAI,CAAC,QAAQ;AACX,UAAI,KAAK,EAAE,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,OAAO,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,MAAM,CAAC;AAAA,IAC/E,OAAO;AACL,YAAM,KAAK,GAAG,MAAM,CAAC;AACrB,YAAM,KAAK,GAAG,MAAM,CAAC;AACrB,UAAI,KAAK,EAAE,GAAG,WAAW,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,GAAG,GAAG,WAAW,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,EAAE,CAAC;AAAA,IACzG;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,WAAW,KAA8C;AACvE,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,UAAM,KAAK,IAAI,CAAC,EAAG,IAAI,IAAI,IAAI,CAAC,EAAG;AACnC,UAAM,KAAK,IAAI,CAAC,EAAG,IAAI,IAAI,IAAI,CAAC,EAAG;AACnC,SAAK,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAAA,EAClC;AACA,SAAO;AACT;AAOO,SAAS,YAAY,GAAmB;AAC7C,SAAO,KAAK,IAAI,MAAM,KAAK,IAAI,KAAK,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;AACvE;AAGO,SAAS,cAAc,GAAuB,OAAuB;AAC1E,SAAO,KAAK,IAAI,MAAM,EAAE,UAAU,UAAU,IAAI,IAAI,SAAU,KAAK;AACrE;AAUO,SAAS,YAAY,GAAW,SAAyB;AAC9D,QAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI;AACjD,QAAM,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;AAC3B,MAAI,QAAQ,EAAG,QAAO,KAAK,IAAI,IAAI;AACnC,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,IAAI,IAAI,CAAC;AAC1C;AAGO,IAAM,oBAAoB;AAQ1B,SAAS,YAAY,KAAsC,MAA4G;AAC5K,QAAM,IAAI,IAAI;AACd,QAAM,OAAwC,CAAC;AAC/C,QAAM,QAAyC,CAAC;AAChD,MAAI,IAAI,EAAG,QAAO,EAAE,MAAM,MAAM;AAChC,QAAM,MAAM,CAAC,GAA6B,MAA0D;AAClG,UAAM,KAAK,EAAE,IAAI,EAAE;AACnB,UAAM,KAAK,EAAE,IAAI,EAAE;AACnB,UAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAC3B,WAAO,IAAI,OAAO,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,EAAE,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC5D;AACA,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,MAAM,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAI,IAAI,CAAC,CAAE,IAAI,IAAI,IAAI,CAAC,GAAI,IAAI,CAAC,CAAE;AACpE,UAAM,OAAO,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,GAAI,IAAI,IAAI,CAAC,CAAE,IAAI;AACrD,QAAI,KAAK,IAAI,IAAI,KAAK;AACtB,QAAI,KAAK,IAAI,IAAI,KAAK;AACtB,UAAM,KAAK,KAAK,MAAM,IAAI,EAAE;AAC5B,QAAI,KAAK,MAAM;AAAE,WAAK,KAAK;AAAG,WAAK,KAAK;AAAA,IAAG,OAAO;AAAE,YAAM;AAAI,YAAM;AAAA,IAAI;AACxE,UAAM,KAAK,KAAK,CAAC,IAAK,KAAK,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC;AAC7D,UAAM,IAAI,IAAI,CAAC;AACf,SAAK,KAAK,EAAE,GAAG,EAAE,IAAI,KAAK,IAAI,GAAG,EAAE,IAAI,KAAK,GAAG,CAAC;AAChD,UAAM,KAAK,EAAE,GAAG,EAAE,IAAI,KAAK,IAAI,GAAG,EAAE,IAAI,KAAK,GAAG,CAAC;AAAA,EACnD;AACA,SAAO,EAAE,MAAM,MAAM;AACvB;AAWO,SAAS,cAAc,KAAsC,IAAY,QAAQ,MAAuC;AAC7H,QAAM,IAAI,IAAI;AACd,MAAI,IAAI,EAAG,QAAO,CAAC;AACnB,QAAM,OAAO,CAAC,MAAsB,KAAK,IAAI,KAAK,QAAQ,KAAK,YAAY,KAAK,IAAI,EAAE,IAAI,EAAE,IAAI;AAChG,QAAM,MAAM,CAAC,GAA6B,MAA0D;AAClG,UAAM,KAAK,EAAE,IAAI,EAAE;AACnB,UAAM,KAAK,EAAE,IAAI,EAAE;AACnB,UAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAC3B,WAAO,IAAI,OAAO,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,EAAE,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC5D;AACA,QAAM,EAAE,MAAM,MAAM,IAAI,YAAY,KAAK,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC;AAErF,QAAM,MAAM,CAAC,GAA6B,GAAW,SAAkD;AACrG,UAAM,MAAuC,CAAC;AAC9C,UAAM,QAAQ;AACd,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,YAAM,IAAI,OAAQ,KAAK,KAAK,IAAK;AACjC,UAAI,KAAK,EAAE,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC,IAAI,GAAG,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;AAAA,IACjE;AACA,WAAO;AAAA,EACT;AACA,QAAM,OAAO,IAAI,IAAI,IAAI,CAAC,GAAI,IAAI,IAAI,CAAC,CAAE;AACzC,QAAM,SAAS,IAAI,IAAI,CAAC,GAAI,IAAI,CAAC,CAAE;AAInC,QAAM,OAAO,KAAK,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK;AACpD,QAAM,SAAS,KAAK,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,KAAK,KAAK;AAC1D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG,IAAI,IAAI,IAAI,CAAC,GAAI,KAAK,IAAI,CAAC,GAAG,IAAI;AAAA,IACrC,GAAG,MAAM,QAAQ;AAAA,IACjB,GAAG,IAAI,IAAI,CAAC,GAAI,KAAK,CAAC,GAAG,MAAM;AAAA,EACjC;AACF;AASO,IAAM,kBAAkB;AAMxB,IAAM,wBAAwB;AAErC,IAAM,iBAAiB;AAwBvB,IAAM,YAAY,EAAE,MAAM,oBAAI,IAA2B,GAAG,SAAS,oBAAI,IAA2B,GAAG,SAAS,oBAAI,IAA2B,EAAE;AAE1I,SAAS,YAAY,GAAW,OAAqB,QAAuB;AACjF,QAAM,QAAQ,UAAU,IAAI,KAAK,UAAU;AAC3C,QAAM,MAAM,MAAM,IAAI,CAAC;AACvB,MAAI,IAAK,QAAO;AAChB,MAAI;AACJ,MAAI;AACF,UAAM,SAAS,gBAAgB,CAAC;AAChC,UAAM,QAAQ,OAAO,MAAM,IAAI,YAAY,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC;AACxE,UAAM,QAAQ,OAAO,MAAM,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,aAAa,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,GAAG,QAAQ,EAAE,OAAO,EAAE;AAChI,UAAM,EAAE,QAAQ,SAAS,SAAS,UAAU,KAAK,IAAI,OAAO,KAAK,GAAG,UAAU,MAAM,QAAQ,MAAM;AAAA,EACpG,SAAS,GAAG;AACV,UAAM,EAAE,QAAQ,CAAC,GAAG,UAAU,GAAG,OAAO,CAAC,GAAG,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,EAAE;AAAA,EAChG;AACA,MAAI,MAAM,OAAO,IAAK,OAAM,MAAM;AAClC,QAAM,IAAI,GAAG,GAAG;AAChB,SAAO;AACT;AAEA,IAAM,aAAa,oBAAI,QAAwE;AAMxF,SAAS,cAAc,GAAiC;AAG7D,QAAM,IAAI,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,QAAQ;AACrG,QAAM,OAAO,EAAE,QAAQ,SAAS,EAAE,YAAY;AAC9C,QAAM,MAAM,WAAW,IAAI,CAAC;AAC5B,MAAI,OAAO,IAAI,MAAM,KAAK,IAAI,SAAS,KAAM,QAAO,IAAI;AACxD,QAAM,OAAO,YAAY,GAAG,IAAI;AAChC,aAAW,IAAI,GAAG,EAAE,GAAG,MAAM,KAAK,CAAC;AACnC,SAAO;AACT;AAGO,SAAS,gBAAgB,GAAyC;AACvE,SAAO,OAAO,EAAE,SAAS,YAAY,EAAE,aAAa,YAAY,YAAY;AAC9E;AAGO,SAAS,cAAc,GAAwB;AACpD,SAAO,EAAE,SAAS,cAAc,OAAO,EAAE,SAAS,YAAY,MAAM,QAAQ,EAAE,KAAK;AACrF;AAgBA,IAAM,cAAc,oBAAI,QAAyD;AAO1E,SAAS,UAAU,GAAkC;AAC1D,QAAM,MAAM,EAAE,SAAS,EAAE;AACzB,QAAM,MAAM,YAAY,IAAI,CAAC;AAC7B,MAAI,OAAO,IAAI,QAAQ,IAAK,QAAO,IAAI;AACvC,QAAM,MAA4C,EAAE,UAAU,OAAO,EAAE,SAAS,WAC5E,CAAC,EAAE,MAAM,EAAE,MAAM,UAAU,EAAE,UAAU,MAAM,EAAE,MAAM,UAAU,EAAE,UAAU,QAAQ,EAAE,OAAO,CAAC,IAC7F,CAAC;AACL,QAAM,QAAQ,IAAI,IAAI,CAAC,MAAoB;AACzC,UAAM,OAAO,YAAY,EAAE,MAAM,EAAE,YAAY,MAAM;AACrD,WAAO;AAAA,MACL;AAAA,MACA,OAAO,EAAE,QAAQ,EAAE,SAAS,OAAO;AAAA,MACnC,MAAM,EAAE,SAAS;AAAA,MACjB,MAAM,EAAE,aAAa,YAAY,YAAY;AAAA,MAC7C,UAAU,EAAE;AAAA,MACZ,QAAQ,EAAE;AAAA,MACV,SAAS,EAAE,WAAW;AAAA,MACtB,KAAK,UAAU,IAAI;AAAA,IACrB;AAAA,EACF,CAAC;AACD,cAAY,IAAI,GAAG,EAAE,KAAK,MAAM,CAAC;AACjC,SAAO;AACT;AAeO,SAAS,UAAU,GAAkB,GAAW,GAAW,GAAiF;AACjJ,QAAM,OAAO,EAAE,QAAQ;AACvB,QAAM,KAAK,SAAS,WAAW,SAAS,WAAW,IAAI,IAAI;AAC3D,QAAM,KAAK,SAAS,YAAY,SAAS,WAAW,IAAI,IAAI;AAC5D,QAAM,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC;AAClC,SAAO,EAAE,IAAI,IAAI,IAAI,IAAI,SAAS,OAAO,GAAG;AAC9C;AAEA,IAAM,YAAY,oBAAI,QAA4C;AAElE,SAAS,UAAU,MAA0C;AAC3D,QAAM,MAAM,UAAU,IAAI,IAAI;AAC9B,MAAI,IAAK,QAAO;AAChB,MAAI,KAAK,UAAU,KAAK,WAAW,KAAK,UAAU,KAAK;AACvD,aAAW,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO,SAAS,KAAK,SAAS,KAAK,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG;AAC3F,SAAK,KAAK,IAAI,IAAI,CAAC;AAAG,SAAK,KAAK,IAAI,IAAI,CAAC;AAAG,SAAK,KAAK,IAAI,IAAI,CAAC;AAAG,SAAK,KAAK,IAAI,IAAI,CAAC;AAAA,EACvF;AACA,MAAI,CAAC,OAAO,SAAS,EAAE,GAAG;AAAE,SAAK;AAAI,SAAK;AAAG,SAAK;AAAI,SAAK;AAAA,EAAG;AAC9D,QAAM,MAAM,EAAE,KAAK,KAAK,MAAM,GAAG,KAAK,KAAK,MAAM,GAAG,IAAI,KAAK,KAAK,KAAK,MAAM,GAAG,IAAI,GAAG,IAAI,KAAK,KAAK,KAAK,MAAM,GAAG,IAAI,EAAE;AACzH,YAAU,IAAI,MAAM,GAAG;AACvB,SAAO;AACT;AAEA,IAAM,UAAU,oBAAI,IAAoB;AACxC,IAAI,UAAU;AACd,IAAM,YAAY,oBAAI,QAAwB;AASvC,SAAS,aAAa,GAA0B;AACrD,QAAM,MAAM,UAAU,IAAI,CAAC;AAC3B,MAAI,QAAQ,OAAW,QAAO;AAC9B,QAAM,MAAM,KAAK,UAAU,GAAG,CAAC,GAAG,MAAM;AACtC,QAAI,MAAM,UAAU,OAAO,MAAM,SAAU,QAAO;AAClD,QAAI,KAAK,QAAQ,IAAI,CAAC;AACtB,QAAI,OAAO,QAAW;AACpB,UAAI,QAAQ,OAAO,KAAM,SAAQ,MAAM;AACvC,WAAK,EAAE;AACP,cAAQ,IAAI,GAAG,EAAE;AAAA,IACnB;AACA,WAAO,IAAI,EAAE;AAAA,EACf,CAAC;AACD,YAAU,IAAI,GAAG,GAAG;AACpB,SAAO;AACT;AAGO,SAAS,cAAc,MAAoB,GAAW,GAA6B;AACxF,MAAI,KAAK,UAAU,UAAU,OAAQ,QAAO,CAAC,GAAG,CAAC;AACjD,SAAO,EAAE,IAAI,KAAK,IAAI,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM,KAAK,IAAI,EAAE;AAC1E;AAIA,SAAS,YAAY,OAAe,WAA2B;AAE7D,QAAM,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,IAAI,WAAW,QAAQ,IAAI,KAAK,IAAI,eAAe,CAAC;AACvF,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,CAAC;AACpC;AAEA,SAAS,gBAAgB,GAA+E;AACtG,QAAM,SAAS,EAAE,MAAM,qDAAqD,KAAK,CAAC;AAClF,MAAI,IAAI;AACR,QAAM,MAAM,MAAc;AACxB,UAAM,IAAI,OAAO,GAAG;AACpB,QAAI,MAAM,UAAa,aAAa,KAAK,CAAC,EAAG,OAAM,IAAI,MAAM,mBAAmB;AAChF,WAAO,OAAO,CAAC;AAAA,EACjB;AACA,QAAM,OAAO,MAAc;AAEzB,UAAM,IAAI,OAAO,CAAC;AAClB,QAAI,MAAM,UAAa,YAAY,KAAK,CAAC,GAAG;AAC1C,aAAO,CAAC,IAAI,EAAE,MAAM,CAAC;AACrB,aAAO,OAAO,EAAE,CAAC,CAAC;AAAA,IACpB;AACA,WAAO,IAAI;AAAA,EACb;AACA,QAAM,QAAgB,CAAC;AACvB,MAAI,OAAa,CAAC;AAClB,MAAI,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK;AACjC,MAAI,WAAsB;AAC1B,MAAI,UAAU;AACd,QAAM,OAAO,CAAC,GAAW,MAAoB;AAAE,SAAK,KAAK,CAAC,GAAG,CAAC,CAAC;AAAG,SAAK;AAAG,SAAK;AAAA,EAAG;AAClF,QAAM,QAAkD,CAAC;AACzD,QAAM,QAAQ,CAAC,SAAS,UAAgB;AACtC,QAAI,KAAK,UAAU,EAAG,OAAM,KAAK,EAAE,QAAQ,KAAK,MAAM,GAAG,OAAO,CAAC;AACjE,QAAI,KAAK,UAAU,EAAG,OAAM,KAAK,IAAI;AACrC,WAAO,CAAC;AAAA,EACV;AACA,QAAM,QAAQ,CAAC,IAAY,IAAY,IAAY,IAAY,GAAW,MAAoB;AAC5F,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,IAAI,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,IAAI,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,IAAI,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE;AAChI,UAAM,IAAI,YAAY,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,GAAG,MAAM,CAAC;AACzD,UAAM,KAAK,IAAI,KAAK;AACpB,aAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,YAAM,IAAI,IAAI,GAAG,IAAI,IAAI;AACzB;AAAA,QAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI;AAAA,QAC1E,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI;AAAA,MAAC;AAAA,IAC5E;AACA,eAAW,CAAC,IAAI,EAAE;AAAA,EACpB;AACA,QAAM,OAAO,CAAC,IAAY,IAAY,GAAW,MAAoB;AACnE,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,IAAI,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,IAAI,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE;AACjG,UAAM,IAAI,YAAY,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,GAAG,MAAM,CAAC;AACzD,UAAM,KAAK,IAAI,KAAK;AACpB,aAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,YAAM,IAAI,IAAI,GAAG,IAAI,IAAI;AACzB,WAAK,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC;AAAA,IACvF;AACA,eAAW,CAAC,IAAI,EAAE;AAAA,EACpB;AACA,QAAM,MAAM,CAAC,IAAY,IAAY,QAAgB,OAAe,OAAe,GAAW,MAAoB;AAEhH,UAAM,KAAK,IAAI,KAAK;AACpB,QAAI,OAAO,KAAK,OAAO,KAAM,OAAO,KAAK,OAAO,GAAI;AAAE,WAAK,GAAG,CAAC;AAAG;AAAA,IAAQ;AAC1E,SAAK,KAAK,IAAI,EAAE;AAAG,SAAK,KAAK,IAAI,EAAE;AACnC,UAAM,MAAO,SAAS,KAAK,KAAM,KAAK,KAAK,KAAK,IAAI,GAAG,GAAG,KAAK,KAAK,IAAI,GAAG;AAC3E,UAAM,MAAM,KAAK,KAAK,GAAG,MAAM,KAAK,KAAK;AACzC,UAAM,MAAM,KAAK,KAAK,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK;AACrD,UAAM,MAAO,MAAM,OAAQ,KAAK,MAAO,MAAM,OAAQ,KAAK;AAC1D,QAAI,MAAM,GAAG;AAAE,YAAM,KAAK,KAAK,GAAG;AAAG,YAAM,KAAK,KAAK,GAAG;AAAA,IAAG;AAC3D,UAAM,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,MAAM,MAAM,KAAK,KAAK,MAAM;AACvE,UAAM,MAAM,KAAK,KAAK,MAAM,MAAM,KAAK,KAAK,MAAM;AAClD,QAAI,KAAK,KAAK,KAAK,KAAK,IAAI,GAAG,OAAO,GAAG,CAAC;AAC1C,QAAI,UAAU,MAAO,MAAK,CAAC;AAC3B,UAAM,MAAO,KAAK,KAAK,MAAO,IAAI,MAAO,CAAC,KAAK,KAAK,MAAO;AAC3D,UAAM,MAAM,KAAK,MAAM,KAAK,OAAO,KAAK,KAAK,GAAG,MAAM,KAAK,MAAM,KAAK,OAAO,KAAK,KAAK;AACvF,UAAM,MAAM,CAAC,IAAY,IAAY,IAAY,OAAuB,KAAK,MAAM,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,EAAE;AACvH,UAAM,KAAK,IAAI,GAAG,IAAI,MAAM,OAAO,KAAK,MAAM,OAAO,EAAE;AACvD,QAAI,KAAK,KAAK,MAAM,OAAO,KAAK,MAAM,OAAO,KAAK,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,OAAO,EAAE;AACrF,QAAI,CAAC,SAAS,KAAK,EAAG,OAAM,IAAI,KAAK;AACrC,QAAI,SAAS,KAAK,EAAG,OAAM,IAAI,KAAK;AACpC,UAAM,IAAI,KAAK,IAAI,IAAI,EAAE;AACzB,UAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,IAAI,EAAE,KAAK,IAAI,KAAK,KAAK,KAAK,IAAI,GAAG,IAAI,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC;AAClH,aAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,YAAM,IAAI,KAAM,KAAK,IAAK;AAC1B,YAAM,KAAK,KAAK,KAAK,IAAI,CAAC,GAAG,KAAK,KAAK,KAAK,IAAI,CAAC;AACjD,WAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AAAA,IACvD;AAAA,EACF;AACA,SAAO,IAAI,OAAO,QAAQ;AACxB,QAAI,MAAM,OAAO,CAAC;AAClB,QAAI,aAAa,KAAK,GAAG,EAAG;AAAA,aACnB,QAAS,OAAM,YAAY,MAAM,MAAM,YAAY,MAAM,MAAM;AAAA,QACnE,OAAM,IAAI,MAAM,wBAAwB;AAC7C,UAAM,MAAM,QAAQ,IAAI,YAAY,KAAK,QAAQ,MAAM,OAAO;AAC9D,UAAM,KAAK,MAAM,KAAK,GAAG,KAAK,MAAM,KAAK;AACzC,UAAM,IAAI,IAAI,YAAY;AAC1B,UAAM,UAAU,QAAQ,YAAY;AACpC,QAAI,MAAM,OAAO,MAAM,IAAK,YAAW;AACvC,YAAQ,GAAG;AAAA,MACT,KAAK,KAAK;AACR,cAAM;AACN,cAAM,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AAClC,aAAK,GAAG,CAAC;AAAG,aAAK;AAAG,aAAK;AACzB;AAAA,MACF;AAAA,MACA,KAAK;AAAK,aAAK,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAG;AAAA,MACxC,KAAK;AAAK,aAAK,IAAI,IAAI,IAAI,EAAE;AAAG;AAAA,MAChC,KAAK;AAAK,aAAK,IAAI,IAAI,IAAI,EAAE;AAAG;AAAA,MAChC,KAAK,KAAK;AAAE,cAAM,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AAAI,cAAM,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAG;AAAA,MAAO;AAAA,MACpI,KAAK,KAAK;AACR,cAAM,IAAQ,aAAa,YAAY,OAAO,YAAY,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE;AACvH,cAAM,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AAClC,cAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAC9C;AAAA,MACF;AAAA,MACA,KAAK,KAAK;AAAE,cAAM,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AAAI,aAAK,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAG;AAAA,MAAO;AAAA,MAC7F,KAAK,KAAK;AACR,cAAM,IAAQ,aAAa,YAAY,OAAO,YAAY,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE;AACvH,aAAK,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AACvC;AAAA,MACF;AAAA,MACA,KAAK,KAAK;AAAE,cAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,KAAK,GAAG,KAAK,KAAK;AAAG,YAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAG;AAAA,MAAO;AAAA,MACxI,KAAK;AAAK,aAAK;AAAI,aAAK;AAAI,cAAM,IAAI;AAAG;AAAA,MACzC;AAAS,cAAM,IAAI,MAAM,6BAA6B,GAAG,GAAG;AAAA,IAC9D;AACA,cAAU;AAAA,EACZ;AACA,QAAM;AACN,aAAW,KAAK,OAAO;AAErB,UAAM,IAAI,EAAE,CAAC,GAAI,IAAI,EAAE,EAAE,SAAS,CAAC;AACnC,QAAI,KAAK,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,KAAM,GAAE,IAAI;AAAA,EACzD;AACA,aAAW,KAAK,OAAO;AACrB,UAAM,IAAI,EAAE,OAAO,CAAC,GAAI,IAAI,EAAE,OAAO,EAAE,OAAO,SAAS,CAAC;AACxD,QAAI,EAAE,UAAU,EAAE,OAAO,SAAS,KAAK,KAAK,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,KAAM,GAAE,OAAO,IAAI;AAAA,EACnG;AACA,SAAO,EAAE,OAAO,MAAM;AACxB;AAGA,SAAS,aAAa,GAAe;AACnC,MAAI,EAAE,UAAU,EAAG,QAAO;AAC1B,QAAM,OAAO,IAAI,WAAW,EAAE,MAAM;AACpC,OAAK,CAAC,IAAI;AAAG,OAAK,EAAE,SAAS,CAAC,IAAI;AAClC,QAAM,QAAiC,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;AACzD,SAAO,MAAM,QAAQ;AACnB,UAAM,CAAC,GAAG,CAAC,IAAI,MAAM,IAAI;AACzB,UAAM,IAAI,EAAE,CAAC,GAAI,IAAI,EAAE,CAAC;AACxB,UAAM,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,KAAK,MAAM,IAAI,EAAE;AACjE,QAAI,OAAO,IAAI,KAAK;AACpB,aAAS,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;AAC9B,YAAM,IAAI,EAAE,CAAC;AACb,YAAM,IAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AACrH,UAAI,IAAI,IAAI;AAAE,aAAK;AAAG,eAAO;AAAA,MAAG;AAAA,IAClC;AACA,QAAI,QAAQ,KAAK,KAAK,gBAAgB;AAAE,WAAK,IAAI,IAAI;AAAG,YAAM,KAAK,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;AAAA,IAAG;AAAA,EAC5F;AACA,SAAO,EAAE,OAAO,CAAC,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC;AACzC;AAOA,SAAS,aAAa,GAAe;AACnC,MAAI,EAAE,UAAU,EAAG,QAAO;AAE1B,MAAI,MAAM,GAAG,KAAK;AAClB,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,UAAM,KAAK,EAAE,CAAC,EAAG,CAAC,IAAI,EAAE,CAAC,EAAG,CAAC,MAAM,KAAK,EAAE,CAAC,EAAG,CAAC,IAAI,EAAE,CAAC,EAAG,CAAC,MAAM;AAChE,QAAI,IAAI,IAAI;AAAE,WAAK;AAAG,YAAM;AAAA,IAAG;AAAA,EACjC;AACA,QAAM,OAAO,IAAI,WAAW,EAAE,MAAM;AACpC,OAAK,CAAC,IAAI;AAAG,OAAK,GAAG,IAAI;AACzB,QAAM,KAAK,CAAC,MAAkB,EAAE,IAAI,EAAE,MAAM;AAC5C,QAAM,QAAiC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC;AACjE,SAAO,MAAM,QAAQ;AACnB,UAAM,CAAC,GAAG,CAAC,IAAI,MAAM,IAAI;AACzB,UAAM,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC;AACzB,UAAM,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,KAAK,MAAM,IAAI,EAAE;AACjE,QAAI,OAAO,IAAI,KAAK;AACpB,aAAS,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;AAC9B,YAAM,IAAI,GAAG,CAAC;AACd,YAAM,IAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AACrH,UAAI,IAAI,IAAI;AAAE,aAAK;AAAG,eAAO;AAAA,MAAG;AAAA,IAClC;AACA,QAAI,QAAQ,KAAK,KAAK,gBAAgB;AACpC,WAAK,OAAO,EAAE,MAAM,IAAI;AACxB,YAAM,KAAK,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;AAAA,IACjC;AAAA,EACF;AACA,SAAO,EAAE,OAAO,CAAC,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC;AACzC;AAEA,SAAS,WAAW,GAAiB;AACnC,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,UAAM,IAAI,EAAE,CAAC,GAAI,IAAI,GAAG,IAAI,KAAK,EAAE,MAAM;AACzC,SAAK,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;AAAA,EAC/B;AACA,SAAO,IAAI;AACb;AAEA,SAAS,OAAO,IAAQ,GAAkB;AACxC,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,EAAE,SAAS,GAAG,IAAI,EAAE,QAAQ,IAAI,KAAK;AACvD,UAAM,IAAI,EAAE,CAAC,GAAI,IAAI,EAAE,CAAC;AACxB,QAAK,EAAE,CAAC,IAAI,GAAG,CAAC,MAAQ,EAAE,CAAC,IAAI,GAAG,CAAC,KAAM,GAAG,CAAC,KAAM,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,MAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,EAAG,KAAI,CAAC;AAAA,EACjH;AACA,SAAO;AACT;AAGA,SAAS,aAAa,GAAS,IAAS,KAAW,IAAkB;AACnE,MAAI,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,GAAI,QAAO;AAC7E,aAAW,KAAK,IAAK,KAAI,CAAC,OAAO,GAAG,CAAC,EAAG,QAAO;AAC/C,SAAO;AACT;AAGA,SAAS,MAAM,GAAc;AAC3B,QAAM,IAAI,EAAE,IAAI,UAAU,IAAI,WAAW,IAAI,UAAU,IAAI,UAAU;AACrE,aAAW,CAAC,GAAG,CAAC,KAAK,GAAG;AAAE,MAAE,KAAK,KAAK,IAAI,EAAE,IAAI,CAAC;AAAG,MAAE,KAAK,KAAK,IAAI,EAAE,IAAI,CAAC;AAAG,MAAE,KAAK,KAAK,IAAI,EAAE,IAAI,CAAC;AAAG,MAAE,KAAK,KAAK,IAAI,EAAE,IAAI,CAAC;AAAA,EAAG;AAClI,SAAO;AACT;AAkBA,SAAS,UAAU,OAAqB;AACtC,MAAI,MAAM,WAAW,EAAG,QAAO,CAAC;AAChC,QAAM,QAAQ,MAAM,IAAI,KAAK;AAC7B,QAAM,QAAQ,MAAM,IAAI,CAAC,MAAM,KAAK,IAAI,WAAW,CAAC,CAAC,CAAC;AAEtD,QAAM,QAAQ,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,MAAM,CAAC,IAAK,MAAM,CAAC,CAAE;AACzE,QAAM,OAAO,IAAI,MAAc,MAAM,MAAM,EAAE,KAAK,CAAC;AACnD,QAAM,MAAM,IAAI,MAAc,MAAM,MAAM,EAAE,KAAK,CAAC;AAClD,QAAM,OAAiB,CAAC;AACxB,aAAW,KAAK,OAAO;AACrB,UAAM,aAAa,KAAK,OAAO,CAAC,MAAM,MAAM,CAAC,IAAK,MAAM,CAAC,KAAM,aAAa,MAAM,CAAC,GAAI,MAAM,CAAC,GAAI,MAAM,CAAC,GAAI,MAAM,CAAC,CAAE,CAAC;AACvH,UAAM,SAAS,WAAW,OAAO,CAAC,KAAK,MAAM,MAAM,KAAK,CAAC,GAAI,CAAC;AAC9D,QAAI,OAAO;AACX,QAAI,WAAW,QAAQ;AACrB,YAAM,SAAS,WAAW,OAAO,CAAC,GAAG,MAAO,MAAM,CAAC,IAAK,MAAM,CAAC,IAAK,IAAI,CAAE;AAC1E,aAAO,IAAI,MAAM,MAAM,IAAI,IAAI;AAAA,IACjC;AACA,QAAI,CAAC,IAAI;AACT,SAAK,CAAC,IAAI,OAAO;AACjB,SAAK,KAAK,CAAC;AAAA,EACb;AACA,QAAM,SAAiB,CAAC;AACxB,QAAM,QAAQ,CAAC,GAAS,MAAoB;AAC1C,UAAM,IAAI,KAAK,KAAK,WAAW,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,IAAI,EAAE,MAAM,EAAE,QAAQ;AAC5E,aAAS,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG,IAAK,QAAO,KAAK,CAAC;AAAA,EACrD;AACA,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,QAAI,KAAK,CAAC,MAAM,EAAG,OAAM,MAAM,CAAC,GAAI,KAAK,CAAC,CAAE;AAAA,EAC9C;AASA,QAAM,QAAQ,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,KAAK,SAAS,MAAM,CAAC,CAAE,CAAC;AACvG,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,QAAI,KAAK,CAAC,KAAM,EAAG;AACnB,UAAM,KAAK,MAAM,CAAC;AAClB,UAAM,WAAW,MAAM,OAAO,CAAC,MAAM;AACnC,YAAM,KAAK,MAAM,CAAC;AAClB,UAAI,MAAM,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,GAAI,QAAO;AAC5F,aAAO,CAAC,aAAa,MAAM,CAAC,GAAI,IAAI,MAAM,CAAC,GAAI,EAAE,KAAK,CAAC,aAAa,MAAM,CAAC,GAAI,IAAI,MAAM,CAAC,GAAI,EAAE;AAAA,IAClG,CAAC;AACD,eAAW,KAAK,UAAU;AACxB,UAAI,SAAS,KAAK,CAAC,MAAM,MAAM,KAAK,MAAM,CAAC,IAAK,MAAM,CAAC,KAAM,aAAa,MAAM,CAAC,GAAI,MAAM,CAAC,GAAI,MAAM,CAAC,GAAI,MAAM,CAAC,CAAE,CAAC,EAAG;AACxH,YAAM,QAAQ,aAAa,MAAM,CAAC,GAAI,MAAM,CAAC,CAAE;AAC/C,UAAI,MAAM,UAAU,KAAK,KAAK,IAAI,WAAW,KAAK,CAAC,IAAI,KAAM,OAAM,OAAO,CAAC,KAAK,CAAC,CAAE;AAAA,IACrF;AAAA,EACF;AACA,SAAO,OAAO,MAAM;AACtB;AAEA,SAAS,SAAS,GAAkB;AAClC,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,UAAM,IAAI,EAAE,CAAC,GAAI,IAAI,GAAG,IAAI,KAAK,EAAE,MAAM,GAAI,IAAI,GAAG,IAAI,KAAK,EAAE,MAAM;AACrE,UAAM,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;AACrE,QAAI,KAAK,IAAI,CAAC,IAAI,MAAO;AACzB,QAAI,SAAS,EAAG,QAAO,KAAK,KAAK,CAAC;AAAA,aACzB,KAAK,KAAK,CAAC,MAAM,KAAM,QAAO;AAAA,EACzC;AACA,SAAO;AACT;AAGA,SAAS,aAAa,SAAe,MAAkB;AACrD,QAAM,IAAI,KAAK,KAAK,WAAW,IAAI,CAAC,KAAK;AACzC,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,KAAK,UAAU,IAAI,QAAQ,KAAK;AAClD,UAAM,IAAI,KAAK,CAAC,GAAI,IAAI,MAAM,IAAI,KAAK,KAAK,MAAM;AAClD,UAAM,OAAO,CAAC,MAAkB,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;AAChG,UAAM,MAAM,CAAC,GAAO,MAAc;AAAE,YAAM,KAAK,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,IAAI,MAAM,KAAK;AAAK,aAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;AAAA,IAAG;AACvJ,UAAM,OAAa,CAAC;AACpB,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,YAAM,IAAI,IAAI,CAAC,GAAI,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM;AAC/C,YAAM,MAAM,KAAK,CAAC,KAAK,GAAG,MAAM,KAAK,CAAC,KAAK;AAC3C,UAAI,IAAK,MAAK,KAAK,CAAC;AACpB,UAAI,QAAQ,IAAK,MAAK,KAAK,IAAI,GAAG,CAAC,CAAC;AAAA,IACtC;AACA,UAAM;AAAA,EACR;AACA,SAAO;AACT;AAGA,SAAS,OAAO,OAAqB;AACnC,MAAI,MAAM,WAAW,EAAG,QAAO,CAAC;AAChC,MAAI,OAAO,MAAM,CAAC,EAAG,MAAM;AAC3B,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,MAAM,MAAM,CAAC;AACnB,QAAI,KAAK,GAAG,KAAK,GAAG,OAAO;AAC3B,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,eAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,cAAM,MAAM,KAAK,CAAC,EAAG,CAAC,IAAI,IAAI,CAAC,EAAG,CAAC,MAAM,KAAK,KAAK,CAAC,EAAG,CAAC,IAAI,IAAI,CAAC,EAAG,CAAC,MAAM;AAC3E,YAAI,KAAK,MAAM;AAAE,iBAAO;AAAI,eAAK;AAAG,eAAK;AAAA,QAAG;AAAA,MAC9C;AAAA,IACF;AACA,UAAM,MAAM,IAAI,MAAM,EAAE,EAAE,OAAO,IAAI,MAAM,GAAG,EAAE,CAAC;AACjD,WAAO,KAAK,MAAM,GAAG,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAI,KAAK,EAAE,CAAE,GAAG,KAAK,MAAM,KAAK,CAAC,CAAC;AAAA,EACnF;AACA,SAAO;AACT;AAkBO,SAAS,aAAa,GAA0B;AACrD,MAAI,IAAI;AACR,aAAW,KAAK,UAAU,CAAC,GAAG;AAC5B,QAAI,EAAE,KAAM,MAAK,EAAE,KAAK,OAAO,UAAU,EAAE,WAAW,IAAI;AAC1D,QAAI,EAAE,OAAQ,YAAW,KAAK,EAAE,KAAK,MAAO,MAAK,EAAE,OAAO,SAAS;AAAA,EACrE;AACA,SAAO;AACT;;;ACrzBA,IAAMC,OAAM;AACZ,IAAM,QAAQ,CAAC,MAA6C,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AACnH,IAAM,QAAQ,CAAC,MAA4B,OAAO,MAAM;AACxD,IAAM,QAAQ,CAAC,MAA4B,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC;AACrF,IAAM,UAAU,CAAC,MACf,MAAM,QAAQ,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,EAAE,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC;AAGjF,IAAM,YAAY,oBAAI,IAAI,CAAC,iBAAiB,MAAM,SAAS,QAAQ,mBAAmB,WAAW,SAAS,qBAAqB,cAAc,UAAU,YAAY,UAAU,YAAY,QAAQ,CAAC;AAClM,IAAM,eAAe,oBAAI,IAAI,CAAC,SAAS,UAAU,SAAS,CAAC;AAC3D,IAAM,cAAc,oBAAI,IAAI;AAAA,EAC1B;AAAA,EAAS;AAAA,EAAU;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAS;AAAA,EAC9D;AAAA,EAAU;AAAA,EAAS;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAO;AAAA,EAAY;AAAA,EAAS;AAAA,EAC/D;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAU;AAAA,EAAW;AAAA,EAAa;AACvE,CAAC;AACD,IAAM,kBAAkB,oBAAI,IAAI,CAAC,KAAK,KAAK,SAAS,UAAU,UAAU,QAAQ,CAAC;AACjF,IAAM,cAAc,oBAAI,IAAI,CAAC,aAAa,SAAS,CAAC;AACpD,IAAM,aAAa;AACnB,IAAM,iBAAiB,oBAAI,IAAI,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC;AACrD,IAAM,iBAAiB,oBAAI,IAAI,CAAC,QAAQ,YAAY,MAAM,CAAC;AAC3D,IAAM,qBAAqB,oBAAI,IAAI,CAAC,KAAK,QAAQ,SAAS,QAAQ,KAAK,CAAC;AACxE,IAAM,eAAe,oBAAI,IAAI,CAAC,QAAQ,UAAU,SAAS,QAAQ,UAAU,cAAc,CAAC;AAC1F,IAAM,aAAa,oBAAI,IAAI,CAAC,QAAQ,UAAU,SAAS,SAAS,UAAU,cAAc,CAAC;AACzF,IAAM,eAAe,oBAAI,IAAI,CAAC,QAAQ,UAAU,SAAS,SAAS,UAAU,cAAc,CAAC;AAC3F,IAAM,aAAa,oBAAI,IAAI,CAAC,QAAQ,SAAS,UAAU,SAAS,WAAW,UAAU,cAAc,CAAC;AACpG,IAAM,YAAY,oBAAI,IAAI,CAAC,QAAQ,UAAU,UAAU,aAAa,SAAS,OAAO,aAAa,UAAU,cAAc,CAAC;AAC1H,IAAM,kBAAkB,oBAAI,IAAI,CAAC,QAAQ,SAAS,YAAY,QAAQ,YAAY,UAAU,SAAS,CAAC;AACtG,IAAM,gBAAgB,oBAAI,IAAI,CAAC,QAAQ,UAAU,SAAS,SAAS,UAAU,QAAQ,YAAY,QAAQ,YAAY,UAAU,SAAS,QAAQ,UAAU,QAAQ,UAAU,cAAc,CAAC;AAC3L,IAAM,eAAe,oBAAI,IAAI,CAAC,QAAQ,UAAU,UAAU,SAAS,SAAS,SAAS,SAAS,UAAU,UAAU,cAAc,CAAC;AACjI,IAAM,cAAc,oBAAI,IAAI,CAAC,QAAQ,UAAU,OAAO,CAAC;AACvD,IAAM,aAAa,oBAAI,IAAI,CAAC,QAAQ,WAAW,SAAS,QAAQ,SAAS,YAAY,YAAY,SAAS,MAAM,CAAC;AACjH,IAAM,mBAAmB,oBAAI,IAAI,CAAC,QAAQ,QAAQ,YAAY,YAAY,cAAc,SAAS,SAAS,UAAU,UAAU,QAAQ,WAAW,MAAM,CAAC;AACxJ,IAAM,aAAa,oBAAI,IAAI,CAAC,QAAQ,YAAY,CAAC;AACjD,IAAM,qBAAqB,oBAAI,IAAI,CAAC,YAAY,OAAO,aAAa,QAAQ,UAAU,SAAS,eAAe,UAAU,cAAc,CAAC;AAUvI,IAAM,eAAe;AACrB,IAAM,eAAe,oBAAI,IAAI,CAAC,YAAY,QAAQ,SAAS,SAAS,MAAM,CAAC;AAC3E,IAAM,qBAAqB,oBAAI,IAAI,CAAC,SAAS,OAAO,CAAC;AACrD,IAAM,cAAc,oBAAI,IAAI,CAAC,QAAQ,SAAS,SAAS,iBAAiB,OAAO,MAAM,CAAC;AACtF,IAAM,aAAa,oBAAI,IAAI,CAAC,QAAQ,SAAS,QAAQ,MAAM,CAAC;AAC5D,IAAM,eAAe,oBAAI,IAAI,CAAC,QAAQ,OAAO,CAAC;AAC9C,IAAM,eAAe,oBAAI,IAAI,CAAC,MAAM,CAAC;AACrC,IAAM,cAAc,oBAAI,IAAI,CAAC,QAAQ,SAAS,UAAU,QAAQ,CAAC;AACjE,IAAM,eAAe,oBAAI,IAAI,CAAC,QAAQ,SAAS,SAAS,WAAW,aAAa,MAAM,CAAC;AACvF,IAAM,aAAa,oBAAI,IAAI,CAAC,QAAQ,SAAS,QAAQ,CAAC;AACtD,IAAM,aAAa,oBAAI,IAAI,CAAC,QAAQ,UAAU,YAAY,SAAS,UAAU,SAAS,CAAC;AACvF,IAAM,iBAAiB,oBAAI,IAAI,CAAC,QAAQ,OAAO,CAAC;AAChD,IAAM,oBAAoB,oBAAI,IAAI,CAAC,QAAQ,SAAS,QAAQ,OAAO,CAAC;AACpE,IAAM,iBAAiB,oBAAI,IAAI,CAAC,QAAQ,SAAS,WAAW,QAAQ,YAAY,SAAS,SAAS,MAAM,CAAC;AACzG,IAAM,oBAAoB,oBAAI,IAAI,CAAC,UAAU,QAAQ,CAAC;AAGtD,IAAM,wBAAwB,oBAAI,IAAI,CAAC,SAAS,SAAS,SAAS,SAAS,QAAQ,QAAQ,UAAU,SAAS,QAAQ,QAAQ,OAAO,QAAQ,SAAS,QAAQ,UAAU,QAAQ,CAAC;AAEjL,SAAS,YAAY,KAA8B,OAA8B;AAC/E,SAAO,OAAO,KAAK,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;AACrD;AAQA,SAAS,QAAQ,MAAuB;AACtC,SAAO,MAAM,IAAI,KAAK,KAAK,UAAU,OAAO,OAAO;AACrD;AAOA,SAAS,YAAY,MAAiC;AACpD,SAAO,MAAM,IAAI,KAAK,KAAK,UAAU,OACjC,CAAC,OAAO,2BAA2B,IAAI,IACvC,CAAC,OAAO,yBAAyB,iBAAiB;AACxD;AAGA,SAAS,SAAS,MAAe,MAAuB;AACtD,SAAO,yCAAyC,QAAQ,IAAI,CAAC,GAAG,OAAO,KAAK,IAAI,MAAM,EAAE;AAC1F;AAQA,SAAS,eAAe,GAAY,MAAc,KAAqC,MAAM,eAAqB;AAChH,MAAI,MAAM,QAAQ,CAAC,EAAG,KAAI,MAAM,oDAAoD;AAAA,WAC3E,CAAC,MAAM,CAAC,KAAK,KAAK,EAAG,KAAI,MAAM,GAAG;AAC7C;AAeA,SAAS,gBAAgB,MAAqB;AAC5C,MAAI,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,QAAQ,KAAK,MAAM,EAAG;AACjD,aAAW,SAAS,KAAK,QAAQ;AAC/B,QAAI,CAAC,MAAM,KAAK,EAAG;AACnB,UAAM,SAAU,MAAkC;AAClD,QAAI,CAAC,MAAM,MAAM,EAAG;AACpB,UAAM,KAAK;AACX,QAAI,MAAM,QAAQ,GAAG,MAAM,KAAK,GAAG,OAAO,SAAS,KAAK,GAAG,UAAU,QAAW;AAC9E,SAAG,QAAQ,GAAG,OAAO,CAAC;AAAA,IACxB;AAAA,EACF;AACF;AAEO,SAAS,aAAa,MAAiC;AAC5D,kBAAgB,IAAI;AACpB,SAAO,iBAAiB,IAAI;AAC9B;AAQO,SAAS,qBAAqB,MAAyB;AAC5D,MAAI,CAAC,MAAM,IAAI,EAAG,QAAO,CAAC;AAC1B,UAAQ,iBAAiB,IAAI,EAAE,YAAY,CAAC,GACzC,OAAO,CAAC,MAAM,EAAE,SAAS,sBAAsB,EAAE,SAAS,oBAAoB,EAC9E,IAAI,CAAC,MAAM,EAAE,KAAK,QAAQ,cAAc,KAAK,CAAC;AACnD;AAaO,SAAS,kBAAkB,MAAiB,OAAkC;AACnF,QAAM,SAAS,oBAAI,IAAY;AAC/B,MAAI,aAAa;AACjB,MAAI,SAAS;AACb,MAAI,SAAS;AACb,aAAW,KAAK,OAAO;AAGrB,QAAI,6CAA6C,KAAK,CAAC,EAAG,QAAO,aAAa,IAAI,EAAE;AAEpF,QAAI,MAAM,SAAU,QAAO,aAAa,IAAI,EAAE;AAC9C,UAAM,CAAC,MAAM,GAAG,IAAI,EAAE,MAAM,GAAG;AAC/B,QAAI,SAAS,YAAY,QAAQ,UAAa,QAAQ,KAAK,GAAG,EAAG,QAAO,IAAI,OAAO,GAAG,CAAC;AAAA,aAC9E,SAAS,aAAc,cAAa;AAAA,aACpC,SAAS,SAAU,UAAS;AAAA,aAC5B,SAAS,SAAU,UAAS;AAAA,QAChC,QAAO,aAAa,IAAI,EAAE;AAAA,EACjC;AACA,MAAI,KAAK;AACT,QAAM,MAAM,MAAY;AAAE,SAAK;AAAA,EAAO;AACtC,QAAM,OAAe,MAAM;AAC3B,MAAI,CAAC,MAAM,QAAQ,KAAK,MAAM,EAAG,QAAO;AACxC,aAAW,KAAK,QAAQ;AACtB,UAAM,QAAQ,KAAK,OAAO,CAAC;AAC3B,QAAI,UAAU,OAAW,QAAO;AAChC,kBAAc,OAAO,UAAU,CAAC,KAAK,KAAK,MAAM,IAAI;AAIpD,QAAI,KAAK,UAAU,QAAQ,MAAM,KAAK,KAAK,MAAM,MAAM,MAAM,KAAK,MAAM,OAAO,SAAS,YAAa,MAAK;AAAA,EAC5G;AACA,MAAI,cAAc,KAAK,eAAe,OAAW,oBAAmB,KAAK,YAAY,KAAK,IAAI;AAC9F,MAAI,UAAU,KAAK,WAAW,OAAW,gBAAe,KAAK,QAAQ,UAAU,KAAK,IAAI;AAExF,MAAI,UAAU,KAAK,WAAW,OAAW,gBAAe,KAAK,QAAQ,KAAK,MAAM,IAAI;AACpF,MAAI,OAAO,OAAO,GAAG;AACnB,UAAM,QAAQ,KAAK,OAAO,OAAO,CAAC,GAAG,MAAM,KAAK,MAAM,CAAC,KAAK,MAAM,EAAE,KAAK,IAAI,EAAE,QAAQ,IAAI,CAAC;AAC5F,QAAI,QAAQ,OAAO,SAAU,MAAK;AAAA,EACpC;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,MAAiC;AACzD,QAAM,SAAsB,CAAC;AAC7B,QAAM,WAA0B,CAAC;AACjC,QAAM,MAAM,CAAC,MAAc,YAA0B,KAAK,OAAO,KAAK,EAAE,MAAM,QAAQ,CAAC;AACvF,QAAM,OAAO,CAAC,MAAc,MAAc,YAA0B,KAAK,SAAS,KAAK,EAAE,MAAM,MAAM,QAAQ,CAAC;AAE9G,MAAI,CAAC,MAAM,IAAI,EAAG,QAAO,EAAE,OAAO,OAAO,QAAQ,CAAC,EAAE,MAAM,IAAI,SAAS,yBAAyB,CAAC,GAAG,UAAU,CAAC,EAAE;AAEjH,MAAI,KAAK,kBAAkB,eAAgB,KAAI,iBAAiB,WAAW,cAAc,EAAE;AAC3F,MAAI,CAAC,MAAM,KAAK,EAAE,KAAK,KAAK,GAAG,KAAK,MAAM,GAAI,KAAI,MAAM,4BAA4B;AACpF,MAAI,CAAC,MAAM,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK,MAAM,GAAI,KAAI,SAAS,4BAA4B;AAC7F,MAAI,KAAK,SAAS,UAAa,CAAC,MAAM,KAAK,IAAI,EAAG,KAAI,QAAQ,kBAAkB;AAChF,MAAI,KAAK,oBAAoB,UAAa,CAAC,CAAC,QAAQ,YAAY,WAAW,EAAE,SAAS,KAAK,eAAyB,GAAG;AACrH,QAAI,mBAAmB,qCAAqC;AAAA,EAC9D;AACA,MAAI,KAAK,YAAY,UAAa,CAAC,CAAC,UAAU,UAAU,OAAO,EAAE,SAAS,KAAK,OAAiB,GAAG;AACjG,QAAI,WAAW,iCAAiC;AAAA,EAClD;AACA,MAAI,KAAK,UAAU,UAAa,KAAK,UAAU,QAAQ,KAAK,UAAU,YAAY;AAChF,QAAI,SAAS,2BAA2B;AAAA,EAC1C;AACA,MAAI,KAAK,UAAU,QAAQ,MAAM,QAAQ,KAAK,MAAM,GAAG;AACrD,eAAW,KAAK,KAAK,QAAQ;AAC3B,UAAI,MAAM,CAAC,KAAK,MAAO,EAA8B,MAAM,KAAO,EAA8B,OAAmC,SAAS,aAAa;AACvJ,YAAI,SAAS,wGAAmG;AAChH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,MAAI,KAAK,sBAAsB,QAAW;AACxC,QAAI,CAAC,MAAM,KAAK,iBAAiB,KAAK,KAAK,oBAAoB,OAAO,KAAK,oBAAoB,MAAM;AACnG,UAAI,qBAAqB,uCAAuC;AAAA,IAClE;AAAA,EACF;AACA,MAAI,KAAK,aAAa,WAAc,CAAC,MAAM,KAAK,QAAQ,KAAK,KAAK,WAAW,KAAK,KAAK,WAAW,OAAO,cAAc;AACrH,QAAI,YAAY,uBAAuB,OAAO,WAAW,EAAE;AAAA,EAC7D;AAEA,aAAW,KAAK,YAAY,MAAM,SAAS,GAAG;AAC5C,SAAK,GAAG,oBAAoB,+BAA+B,CAAC,0BAAqB;AAAA,EACnF;AAEA,MAAI,KAAK,eAAe,OAAW,oBAAmB,KAAK,YAAY,KAAK,IAAI;AAChF,MAAI,KAAK,WAAW,OAAW,gBAAe,KAAK,QAAQ,UAAU,KAAK,IAAI;AAC9E,MAAI,KAAK,WAAW,OAAW,gBAAe,KAAK,QAAQ,KAAK,MAAM,IAAI;AAE1E,MAAI,CAAC,MAAM,QAAQ,KAAK,MAAM,KAAK,KAAK,OAAO,WAAW,GAAG;AAC3D,QAAI,UAAU,2BAA2B;AAAA,EAC3C,OAAO;AACL,QAAI,KAAK,OAAO,SAAS,OAAO,UAAW,KAAI,UAAU,WAAW,OAAO,SAAS,SAAS;AAC7F;AACE,UAAI,aAAa;AACjB,iBAAW,KAAK,KAAK,QAA0C;AAC7D,cAAM,KAAK,MAAM,CAAC,IAAK,EAAE,SAAiD;AAC1E,YAAI,CAAC,MAAM,GAAG,SAAS,UAAW;AAClC,cAAM,SAAS,MAAM,QAAQ,GAAG,KAAK,IAAK,GAAG,QAAsB,OAAO,GAAG,SAAS,WAAW,CAAC,EAAE,IAAI,CAAC;AACzG,cAAM,IAAI,OAAO,EAAE,UAAU,YAAY,EAAE,QAAQ,IAAI,EAAE,QAAQ;AACjE,mBAAW,MAAM,QAAQ;AACvB,cAAI,CAAC,MAAM,EAAE,KAAK,OAAO,GAAG,SAAS,SAAU;AAC/C,gBAAM,KAAK,YAAY,GAAG,MAAO,GAAG,YAAyC,MAAM;AACnF,0BAAgB,GAAG,SAAS,QAAQ,IAAI,GAAG,OAAO,WAAW,MAAM,GAAG,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,QAAQ,CAAC,IAAI,MAAM;AAAA,QAC5I;AAAA,MACF;AACA,UAAI,aAAa,uBAAuB;AACtC,YAAI,UAAU,uBAAuB,UAAU,8DAA2D,qBAAqB,EAAE;AAAA,MACnI;AAAA,IACF;AACA,QAAI,QAAQ;AACZ,SAAK,OAAO,QAAQ,CAAC,OAAO,MAAM;AAChC,eAAS,MAAM,KAAK,KAAK,MAAM,MAAM,KAAK,IAAI,MAAM,QAAQ;AAC5D,oBAAc,OAAO,UAAU,CAAC,KAAK,KAAK,MAAM,IAAI;AAAA,IACtD,CAAC;AACD,QAAI,QAAQ,OAAO,SAAU,KAAI,UAAU,kBAAkB,KAAK,gBAAgB,OAAO,QAAQ,EAAE;AAAA,EACrG;AAGA,MAAI,KAAK,aAAa,UAAa,OAAO,WAAW,EAAG,kBAAiB,MAA8B,KAAK,IAAI;AAEhH,SAAO,EAAE,OAAO,OAAO,WAAW,GAAG,QAAQ,SAAS;AACxD;AAGA,SAAS,kBAAkB,IAAa,MAAc,KAAqC,MAAc,MAAe,UAAyB;AAC/I,MAAI,CAAC,MAAM,EAAE,EAAG,QAAO,IAAI,MAAM,+DAA+D;AAChG,aAAW,KAAK,YAAY,IAAI,eAAe,EAAG,MAAK,GAAG,IAAI,IAAI,CAAC,IAAI,oBAAoB,+BAA+B,CAAC,0BAAqB;AAChJ,QAAM,CAAC,KAAK,IAAI,IAAI,YAAY,IAAI;AACpC,QAAM,KAAK,OAAO;AAClB,aAAW,QAAQ,CAAC,KAAK,GAAG,GAAY;AACtC,QAAI,GAAG,IAAI,MAAM,WAAc,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,KAAK,IAAI,GAAG,IAAI,CAAW,IAAI,KAAM,KAAI,GAAG,IAAI,IAAI,IAAI,IAAI,+BAA4B,GAAG,KAAK,IAAI,GAAG;AAAA,EAC5J;AACA,MAAI,GAAG,UAAU,WAAc,CAAC,MAAM,GAAG,KAAK,KAAK,GAAG,QAAQ,KAAK,GAAG,QAAQ,IAAK,KAAI,GAAG,IAAI,UAAU,uBAAuB,EAAE,EAAE;AACnI,MAAI,GAAG,WAAW,WAAc,CAAC,MAAM,GAAG,MAAM,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI,IAAK,KAAI,GAAG,IAAI,WAAW,+BAA4B,EAAE,qBAAqB;AACzJ,MAAI,GAAG,WAAW,WAAc,CAAC,MAAM,GAAG,MAAM,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI,OAAO,0BAA0B;AAC1G,QAAI,GAAG,IAAI,WAAW,0CAAuC,OAAO,uBAAuB,EAAE;AAAA,EAC/F;AACA,MAAI,GAAG,WAAW,QAAW;AAC3B,QAAI,GAAG,WAAW,cAAc,GAAG,WAAW,SAAU,KAAI,GAAG,IAAI,WAAW,+BAA+B;AAAA,aACpG,GAAG,WAAW,YAAY,CAAC,SAAU,KAAI,GAAG,IAAI,WAAW,yGAAoG;AAAA,EAC1K;AACF;AAGA,SAAS,eAAe,QAAiB,KAAqC,MAAc,MAAqB;AAC/G,MAAI,CAAC,MAAM,MAAM,EAAG,QAAO,IAAI,UAAU,kEAAkE;AAC3G,QAAM,QAAQ,OAAO,KAAK,MAAM;AAChC,MAAI,MAAM,SAAS,OAAO,UAAW,KAAI,UAAU,WAAW,OAAO,SAAS,SAAS;AACvF,aAAW,QAAQ,OAAO;AACxB,UAAM,IAAI,UAAU,IAAI;AACxB,QAAI,CAAC,WAAW,KAAK,IAAI,EAAG,KAAI,GAAG,2EAAsE;AACzG,UAAM,IAAI,OAAO,IAAI;AACrB,QAAI,CAAC,MAAM,CAAC,GAAG;AAAE,UAAI,GAAG,0CAA0C;AAAG;AAAA,IAAU;AAC/E,eAAW,KAAK,YAAY,GAAG,WAAW,EAAG,MAAK,GAAG,CAAC,IAAI,CAAC,IAAI,oBAAoB,2BAA2B,CAAC,0BAAqB;AACpI,QAAI,EAAE,YAAY,WAAc,CAAC,MAAM,EAAE,OAAO,KAAK,EAAE,UAAU,KAAK,EAAE,UAAU,GAAI,KAAI,GAAG,CAAC,YAAY,uBAAuB;AACjI,QAAI,EAAE,cAAc,OAAW,mBAAkB,EAAE,WAAW,GAAG,CAAC,cAAc,KAAK,MAAM,MAAM,KAAK;AAAA,EACxG;AACF;AASA,SAAS,iBAAiB,MAAiB,UAA0C,MAAoB;AACvG,MAAI,SAAS;AACb,QAAM,MAAM,CAAC,GAAW,MAAoB;AAAE,aAAS;AAAM,aAAS,GAAG,CAAC;AAAA,EAAG;AAC7E,QAAM,KAAK,KAAK;AAChB,MAAI,CAAC,MAAM,EAAE,EAAG,QAAO,IAAI,YAAY,4CAA4C;AACnF,aAAW,KAAK,YAAY,IAAI,cAAc,EAAG,MAAK,YAAY,CAAC,IAAI,oBAAoB,8BAA8B,CAAC,0BAAqB;AAC/I,MAAI,GAAG,SAAS,UAAa,OAAO,GAAG,SAAS,UAAW,KAAI,iBAAiB,mBAAmB;AACnG,MAAI,GAAG,aAAa,WAAc,CAAC,MAAM,GAAG,QAAQ,KAAK,GAAG,YAAY,KAAK,GAAG,WAAW,OAAO,sBAAsB;AACtH,QAAI,qBAAqB,2CAA2C,OAAO,mBAAmB,EAAE;AAAA,EAClG;AACA,MAAI,GAAG,SAAS,QAAQ,GAAG,aAAa,OAAW,KAAI,qBAAqB,oDAAoD;AAChI,MAAI,CAAC,MAAM,QAAQ,GAAG,IAAI,KAAK,GAAG,KAAK,WAAW,EAAG,QAAO,IAAI,iBAAiB,2BAA2B;AAC5G,MAAI,GAAG,KAAK,SAAS,OAAO,gBAAiB,QAAO,IAAI,iBAAiB,WAAW,OAAO,eAAe,OAAO;AAEjH,QAAM,OAAO,gBAAgB,IAAI;AACjC,QAAM,UAAU,oBAAoB,IAAI;AACxC,QAAM,QAAQ,oBAAI,IAAsB;AACxC,MAAI,SAAS;AACb,KAAG,KAAK,QAAQ,CAAC,KAAK,MAAM;AAC1B,UAAM,IAAI,iBAAiB,CAAC;AAC5B,QAAI,CAAC,MAAM,GAAG,EAAG,QAAO,IAAI,GAAG,iDAAiD;AAChF,eAAW,KAAK,YAAY,KAAK,kBAAkB,EAAG,MAAK,GAAG,CAAC,IAAI,CAAC,IAAI,oBAAoB,yBAAyB,CAAC,0BAAqB;AAC3I,QAAI,KAAK;AACT,QAAI,CAAC,MAAM,IAAI,CAAC,KAAK,IAAI,IAAI,GAAG;AAAE,UAAI,GAAG,CAAC,MAAM,6BAA6B;AAAG,WAAK;AAAA,IAAO;AAC5F,QAAI,IAAI,SAAS,UAAa,IAAI,SAAS,UAAU,IAAI,SAAS,YAAY,IAAI,SAAS,SAAU,KAAI,GAAG,CAAC,SAAS,sCAAsC;AAC5J,QAAI,IAAI,QAAQ,WAAc,CAAC,MAAM,IAAI,GAAG,KAAK,IAAI,MAAM,KAAK,IAAI,MAAM,OAAO,oBAAoB;AACnG,UAAI,GAAG,CAAC,QAAQ,8BAA8B,OAAO,iBAAiB,EAAE;AAAA,IAC1E;AACA,QAAI,EAAE,WAAW,MAAM;AAAE,UAAI,GAAG,CAAC,UAAU,aAAa;AAAG,WAAK;AAAA,IAAO;AACvE,UAAM,KAAK,MAAM,IAAI,IAAI,IAAI,kBAAkB,MAAM,IAAI,IAAI,IAAI;AACjE,QAAI,CAAC,MAAM,IAAI,IAAI,KAAK,IAAI,KAAK,KAAK,MAAM,IAAI;AAAE,UAAI,GAAG,CAAC,SAAS,8BAA8B;AAAG,WAAK;AAAA,IAAO,WACvG,WAAW,KAAK,IAAI,IAAI,KAAK,uBAAuB,KAAK,IAAI,IAAI,GAAG;AAC3E,UAAI,GAAG,CAAC,SAAS,IAAI,IAAI,IAAI,sGAAiG;AAC9H,WAAK;AAAA,IACP,WACS,CAAC,IAAI;AAAE,UAAI,GAAG,CAAC,SAAS,IAAI,IAAI,IAAI,2FAAsF;AAAG,WAAK;AAAA,IAAO,WACzI,OAAO,cAAc,GAAG,WAAW,WAAW,KAAK,OAAO,mBAAmB,OAAO,QAAQ,OAAO,WAAW,OAAO,QAAQ;AACpI,UAAI,GAAG,CAAC,SAAS,IAAI,IAAI,IAAI,qBAAqB;AAClD,WAAK;AAAA,IACP;AACA,QAAI,CAAC,MAAM,CAAC,GAAI;AAChB,UAAM,IAAI,IAAI;AACd,aAAS,KAAK,IAAI,QAAQ,CAAC;AAC3B,UAAM,UAAU,kBAAkB,MAAM,CAAC,EAAE,GAAG,GAAG,MAAM,IAAI,OAAO,IAAI,MAAM,CAAC,CAAC;AAG9E,UAAM,IAAI,kBAAkB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,MAAM,QAAQ,CAAC,EAAiB,IAAI,aAAa,OAAO;AAC9G,QAAI,CAAC,EAAE,OAAO;AACZ,iBAAW,KAAK,EAAE,OAAQ,KAAI,GAAG,CAAC,UAAU,eAAe,IAAI,IAAI,YAAO,EAAE,QAAQ,QAAQ,KAAK,EAAE,OAAO,EAAE;AAC5G;AAAA,IACF;AAGA,QAAI,MAAM,IAAI,KAAK,KAAK,GAAG,SAAS,WAAW,GAAG;AAChD,YAAM,SAAS,aAAa,MAAM,EAAE;AACpC,YAAM,KAAK,MAAM,MAAM,IAAI,OAAO,UAAU,aAAa;AACzD,YAAM,KAAM,IAAI,MAAkC,UAAU;AAC5D,UAAI,OAAO,GAAI,MAAK,GAAG,CAAC,UAAU,yBAAyB,4CAA4C,OAAO,EAAE,CAAC,WAAM,OAAO,EAAE,CAAC,qGAAgG;AAAA,IACnO;AACA,QAAI,oBAAoB,OAAO,MAAM,SAAS;AAC5C,WAAK,GAAG,CAAC,SAAS,2BAA2B,IAAI,IAAI,IAAI,2MAAiM;AAAA,IAC5P;AACA,UAAM,OAAO,MAAM,IAAI,EAAE,KAAK,CAAC;AAC/B,SAAK,KAAK,CAAC;AACX,UAAM,IAAI,IAAI,IAAI;AAClB,UAAM,MAAM,MAAM,IAAI,GAAG,IAAI,IAAI,MAAM;AACvC,QAAI,GAAG,SAAS,QAAQ,MAAM,GAAG,QAAQ,KAAK,IAAI,MAAM,GAAG,UAAU;AACnE,WAAK,GAAG,CAAC,QAAQ,+BAA+B,4BAA4B,IAAI,GAAG,kBAAkB,GAAG,QAAQ,uCAAkC;AAAA,IACpJ;AAAA,EACF,CAAC;AACD,MAAI,GAAG,SAAS,QAAQ,MAAM,GAAG,QAAQ,KAAK,UAAU,GAAG,UAAU;AACnE,QAAI,qBAAqB,4CAA4C,MAAM,iBAAiB;AAAA,EAC9F;AACA,QAAM,SAAS,OAAO;AACtB,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO;AAChC,UAAM,WAAW,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACxD,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAI,SAAS,CAAC,IAAK,SAAS,IAAI,CAAC,IAAK,QAAQ;AAC5C,YAAI,iBAAiB,YAAY,IAAI,QAAQ,SAAS,IAAI,CAAC,CAAC,QAAQ,SAAS,CAAC,CAAC,uBAAuB,MAAM,oBAAoB;AAAA,MAClI;AAAA,IACF;AACA,QAAI,GAAG,SAAS,QAAQ,MAAM,GAAG,QAAQ,KAAK,SAAS,SAAS,GAAG;AACjE,YAAM,UAAU,GAAG,WAAW,SAAS,SAAS,SAAS,CAAC,IAAK,SAAS,CAAC;AACzE,UAAI,UAAU,OAAQ,KAAI,iBAAiB,YAAY,IAAI,QAAQ,SAAS,SAAS,SAAS,CAAC,CAAC,WAAW,SAAS,CAAC,CAAC,kCAAkC,MAAM,yCAAyC;AAAA,IACzM;AAAA,EACF;AAKA,MAAI,OAAQ;AAGZ,QAAM,QAAQ,CAAC,GAAG,eAAe,IAAI,EAAE,KAAK,CAAC;AAC7C,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,KAAK,oBAAoB,MAAM,MAAM,GAAG,GAAG;AACpD,UAAM,IAAI,kBAAkB,MAAM,CAAC;AAEnC,UAAM,QAAQ,KAAK,UAAU,MAAM,IAAI,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,CAAC;AACjE,QAAI,KAAK,IAAI,KAAK,EAAG;AACrB,SAAK,IAAI,KAAK;AACd,QAAI,kBAAkB,GAAG,KAAK,EAAG;AACjC,UAAM,IAAI,aAAa,CAAC,EAAE,OAAO,CAAC;AAClC,QAAI,YAAY,UAAU,KAAK,MAAM,CAAC,CAAC,qDAAgD,IAAI,GAAG,EAAE,QAAQ,QAAQ,KAAK,EAAE,OAAO,KAAK,SAAS,EAAE;AAC9I;AAAA,EACF;AACF;AAEA,SAAS,MAAM,GAAY,MAAc,KAA2C;AAClF,MAAI,CAAC,MAAM,CAAC,KAAK,CAACA,KAAI,KAAK,CAAC,EAAG,KAAI,MAAM,mCAAmC;AAC9E;AAWA,SAAS,eAAe,GAAY,MAAc,KAAqC,MAAoB;AACzG,MAAI,CAAC,MAAM,CAAC,EAAG,QAAO,IAAI,MAAM,mBAAmB;AACnD,aAAW,KAAK,CAAC,SAAS,QAAQ,GAAY;AAC5C,QAAI,EAAE,CAAC,MAAM,WAAc,CAAC,MAAM,EAAE,CAAC,CAAC,KAAM,EAAE,CAAC,IAAe,KAAM,EAAE,CAAC,IAAe,GAAI,KAAI,GAAG,IAAI,IAAI,CAAC,IAAI,uBAAuB;AAAA,EACvI;AACA,MAAI,EAAE,YAAY,UAAa,OAAO,EAAE,YAAY,UAAW,KAAI,GAAG,IAAI,YAAY,mBAAmB;AACzG,aAAW,KAAK,YAAY,GAAG,YAAY,GAAG;AAC5C,SAAK,GAAG,IAAI,IAAI,CAAC,IAAI,oBAAoB,4BAA4B,CAAC,0BAAqB;AAAA,EAC7F;AACF;AAEA,SAAS,mBAAmB,IAAa,KAAqC,MAAoB;AAChG,MAAI,CAAC,MAAM,EAAE,EAAG,QAAO,IAAI,cAAc,mBAAmB;AAC5D,MAAI,GAAG,SAAS,SAAS;AACvB,UAAM,GAAG,OAAO,oBAAoB,GAAG;AACvC,eAAW,KAAK,YAAY,IAAI,cAAc,GAAG;AAC/C,WAAK,cAAc,CAAC,IAAI,oBAAoB,gCAAgC,CAAC,0BAAqB;AAAA,IACpG;AAAA,EACF,WAAW,GAAG,SAAS,YAAY;AACjC,QAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,KAAK,GAAG,MAAM,SAAS,GAAG;AACnD,UAAI,oBAAoB,iCAAiC;AAAA,IAC3D,OAAO;AACL,SAAG,MAAM,QAAQ,CAAC,GAAG,MAAM;AACzB,YAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,EAAG,KAAI,oBAAoB,CAAC,QAAQ,cAAc;AACtG,cAAM,MAAM,CAAC,IAAI,EAAE,QAAQ,QAAW,oBAAoB,CAAC,WAAW,GAAG;AAAA,MAC3E,CAAC;AAAA,IACH;AACA,QAAI,GAAG,UAAU,QAAW;AAC1B,UAAI,CAAC,MAAM,GAAG,KAAK,EAAG,KAAI,oBAAoB,mBAAmB;AAAA,WAC5D;AACH,YAAI,CAAC,MAAM,GAAG,MAAM,MAAM,KAAK,GAAG,MAAM,SAAS,OAAO,gBAAgB;AACtE,cAAI,2BAA2B,cAAc,OAAO,cAAc,KAAK;AAAA,QACzE;AACA,YAAI,GAAG,MAAM,WAAW,WAAc,CAAC,MAAM,GAAG,MAAM,MAAM,KAAK,GAAG,MAAM,UAAU,KAAK,GAAG,MAAM,SAAS,OAAO,iBAAiB;AACjI,cAAI,2BAA2B,sBAAsB,OAAO,cAAc,EAAE;AAAA,QAC9E;AAAA,MACF;AAAA,IACF;AACA,QAAI,GAAG,SAAS,QAAW;AACzB,UAAI,CAAC,MAAM,GAAG,IAAI,EAAG,KAAI,mBAAmB,mBAAmB;AAAA,WAC1D;AACH,cAAM,GAAG,KAAK,OAAO,yBAAyB,GAAG;AACjD,uBAAe,GAAG,KAAK,QAAQ,0BAA0B,GAAG;AAAA,MAC9D;AAAA,IACF;AACA,eAAW,KAAK,YAAY,IAAI,iBAAiB,GAAG;AAClD,WAAK,cAAc,CAAC,IAAI,oBAAoB,gCAAgC,CAAC,0BAAqB;AAAA,IACpG;AAAA,EACF,WAAW,GAAG,SAAS,SAAS;AAC9B,4BAAwB,IAAI,KAAK,IAAI;AAAA,EACvC,OAAO;AACL,QAAI,mBAAmB,kCAAkC;AAAA,EAC3D;AACF;AAYA,SAAS,wBAAwB,IAA6B,KAAqC,MAAoB;AACrH,MAAI,CAAC,MAAM,GAAG,KAAK,KAAK,GAAG,QAAQ,OAAO,iBAAiB,GAAG,QAAQ,OAAO,eAAe;AAC1F,QAAI,oBAAoB,oBAAoB,OAAO,aAAa,KAAK,OAAO,aAAa,mCAAmC;AAAA,EAC9H;AACA,MAAI,GAAG,YAAY,WAAc,CAAC,MAAM,GAAG,OAAO,KAAK,CAAC,OAAO,UAAU,GAAG,OAAO,KAAK,GAAG,UAAU,KAAK,GAAG,UAAU,OAAO,kBAAkB;AAC9I,QAAI,sBAAsB,yBAAyB,OAAO,eAAe,EAAE;AAAA,EAC7E;AACA,MAAI,GAAG,SAAS,WAAc,CAAC,MAAM,GAAG,IAAI,KAAK,GAAG,OAAO,KAAK,GAAG,OAAO,IAAI;AAC5E,QAAI,mBAAmB,uBAAuB;AAAA,EAChD;AACA,MAAI,GAAG,aAAa,WAAc,CAAC,MAAM,GAAG,QAAQ,KAAK,CAAC,OAAO,UAAU,GAAG,QAAQ,KAAK,GAAG,WAAW,KAAK,GAAG,aAAa,KAAK,GAAG,WAAW,OAAO,mBAAmB;AACzK,QAAI,uBAAuB,uCAAuC,OAAO,gBAAgB,EAAE;AAAA,EAC7F;AACA,MAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,KAAK,GAAG,MAAM,SAAS,OAAO,iBAAiB,GAAG,MAAM,SAAS,OAAO,eAAe;AAChH,QAAI,oBAAoB,WAAW,OAAO,aAAa,KAAK,OAAO,aAAa,cAAc;AAAA,EAChG,OAAO;AAIL,aAAS,IAAI,GAAG,IAAI,GAAG,MAAM,QAAQ,IAAK,OAAM,GAAG,MAAM,CAAC,GAAG,oBAAoB,CAAC,KAAK,GAAG;AAAA,EAC5F;AACA,MAAI,GAAG,UAAU,QAAW;AAC1B,QAAI,CAAC,MAAM,GAAG,KAAK,EAAG,KAAI,oBAAoB,mBAAmB;AAAA,SAC5D;AACH,UAAI,CAAC,MAAM,GAAG,MAAM,MAAM,KAAK,GAAG,MAAM,SAAS,OAAO,gBAAgB;AACtE,YAAI,2BAA2B,cAAc,OAAO,cAAc,KAAK;AAAA,MACzE;AACA,UAAI,GAAG,MAAM,WAAW,WAAc,CAAC,MAAM,GAAG,MAAM,MAAM,KAAK,GAAG,MAAM,SAAS,KAAK,GAAG,MAAM,SAAS,OAAO,sBAAsB;AACrI,YAAI,2BAA2B,uBAAuB,OAAO,mBAAmB,EAAE;AAAA,MACpF;AACA,iBAAW,KAAK,YAAY,GAAG,OAAO,iBAAiB,GAAG;AACxD,aAAK,oBAAoB,CAAC,IAAI,oBAAoB,2BAA2B,CAAC,0BAAqB;AAAA,MACrG;AAAA,IACF;AAAA,EACF;AACA,MAAI,GAAG,SAAS,UAAa,CAAC,MAAM,GAAG,IAAI,EAAG,KAAI,mBAAmB,kBAAkB;AACvF,aAAW,KAAK,YAAY,IAAI,cAAc,GAAG;AAC/C,SAAK,cAAc,CAAC,IAAI,oBAAoB,gCAAgC,CAAC,0BAAqB;AAAA,EACpG;AACF;AAEA,SAAS,cAAc,OAAgB,MAAc,KAAqC,MAAc,MAAsB;AAC5H,MAAI,CAAC,MAAM,KAAK,EAAG,QAAO,IAAI,MAAM,mBAAmB;AAEvD,aAAW,KAAK,YAAY,OAAO,WAAW,GAAG;AAC/C,QAAI,MAAM,MAAM;AACd,WAAK,GAAG,IAAI,OAAO,sBAAsB,mFAA8E;AAAA,IACzH,WAAW,MAAM,SAAS;AACxB,WAAK,GAAG,IAAI,UAAU,oBAAoB,gJAA2I;AAAA,IACvL,OAAO;AACL,WAAK,GAAG,IAAI,IAAI,CAAC,IAAI,oBAAoB,2BAA2B,CAAC,0BAAqB;AAAA,IAC5F;AAAA,EACF;AACA,MAAI,CAAC,MAAM,MAAM,KAAK,KAAK,CAAC,OAAO,UAAU,MAAM,KAAK,KAAK,MAAM,QAAQ,GAAG;AAC5E,QAAI,GAAG,IAAI,UAAU,4BAA4B;AAAA,EACnD,WAAW,MAAM,QAAQ,OAAO,aAAa;AAC3C,QAAI,GAAG,IAAI,UAAU,WAAW,OAAO,WAAW,YAAY;AAAA,EAChE;AACA,MAAI,MAAM,SAAS,WAAc,CAAC,QAAQ,MAAM,IAAI,KAAK,MAAM,KAAK,CAAC,KAAK,IAAI;AAC5E,QAAI,GAAG,IAAI,SAAS,SAAS,IAAI,CAAC;AAAA,EACpC;AACA,MAAI,MAAM,SAAS,UAAa,OAAO,MAAM,SAAS,UAAW,KAAI,GAAG,IAAI,SAAS,mBAAmB;AACxG,MAAI,MAAM,SAAS,UAAa,OAAO,MAAM,SAAS,UAAW,KAAI,GAAG,IAAI,SAAS,mBAAmB;AAExG,MAAI,MAAM,UAAU,WAAc,CAAC,QAAQ,MAAM,KAAK,KAAK,MAAM,MAAM,CAAC,IAAI,KAAK,MAAM,MAAM,CAAC,IAAI,IAAI;AACpG,QAAI,GAAG,IAAI,UAAU,uCAAuC;AAAA,EAC9D;AACA,MAAI,MAAM,UAAU,UAAa,CAAC,CAAC,WAAW,UAAU,UAAU,EAAE,SAAS,MAAM,KAAe,GAAG;AACnG,QAAI,GAAG,IAAI,UAAU,oDAAoD;AAAA,EAC3E;AACA,MAAI,MAAM,QAAQ,WAAc,CAAC,MAAM,MAAM,GAAG,KAAK,MAAM,IAAI,KAAK,MAAM,KAAK;AAC7E,QAAI,GAAG,IAAI,QAAQ,4BAA4B;AAAA,EACjD;AACA,MAAI,MAAM,YAAY,WAAc,CAAC,MAAM,MAAM,OAAO,KAAK,MAAM,UAAU,KAAK,MAAM,UAAU,IAAI;AACpG,QAAI,GAAG,IAAI,YAAY,uBAAuB;AAAA,EAChD;AACA,MAAI,MAAM,cAAc,OAAW,mBAAkB,MAAM,WAAW,GAAG,IAAI,cAAc,KAAK,MAAM,MAAM,IAAI;AAChH,MAAI,MAAM,UAAU,QAAW;AAC7B,UAAM,SAAS,MAAM,IAAI,KAAK,MAAM,KAAK,MAAM,IAAI,KAAK,SAAS;AACjE,QAAI,CAAC,MAAM,MAAM,KAAK,EAAG,KAAI,GAAG,IAAI,UAAU,sCAAsC;AAAA,aAC3E,CAAC,UAAU,CAAC,OAAO,UAAU,eAAe,KAAK,QAAQ,MAAM,KAAK,KAAK,CAAC,MAAM,OAAO,MAAM,KAAK,CAAC,EAAG,KAAI,GAAG,IAAI,UAAU,IAAI,MAAM,KAAK,sDAAiD;AAAA,EACtM;AACA,MAAI,MAAM,aAAa,QAAW;AAChC,QAAI,CAAC,MAAM,MAAM,QAAQ,KAAK,CAAC,MAAM,MAAM,SAAS,CAAC,KAAK,CAAC,MAAM,MAAM,SAAS,CAAC,GAAG;AAClF,UAAI,GAAG,IAAI,aAAa,kCAAkC;AAAA,IAC5D,OAAO;AACL,UAAI,MAAM,SAAS,IAAI,KAAK,MAAM,SAAS,IAAI,EAAG,KAAI,GAAG,IAAI,eAAe,cAAc;AAC1F,UAAI,MAAM,SAAS,IAAI,KAAK,MAAM,SAAS,IAAI,EAAG,KAAI,GAAG,IAAI,eAAe,cAAc;AAC1F,YAAM,CAAC,KAAK,IAAI,IAAI,YAAY,IAAI;AACpC,iBAAW,QAAQ,CAAC,MAAM,IAAI,GAAY;AACxC,cAAM,IAAI,MAAM,SAAS,IAAI;AAC7B,YAAI,MAAM,WAAc,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,IAAI,MAAM;AACvD,cAAI,GAAG,IAAI,aAAa,IAAI,IAAI,+BAA4B,GAAG,KAAK,IAAI,GAAG;AAAA,QAC7E;AAAA,MACF;AACA,iBAAW,KAAK,YAAY,MAAM,UAAU,cAAc,EAAG,MAAK,GAAG,IAAI,aAAa,CAAC,IAAI,oBAAoB,8BAA8B,CAAC,0BAAqB;AACnK,YAAM,aAAa,MAAM,MAAM,MAAM,MAAM,MAAM,OAAO,SAAS,UAAU,MAAM,OAAO,SAAS;AACjG,UAAI,MAAM,MAAM,KAAK,KAAK,MAAM,UAAU,KAAK,CAAC,YAAY;AAC1D,YAAI,GAAG,IAAI,aAAa,0GAAqG;AAAA,MAC/H;AAAA,IACF;AAAA,EACF;AACA,MAAI,MAAM,WAAW,QAAW;AAC9B,QAAI,CAAC,MAAM,MAAM,MAAM,EAAG,KAAI,GAAG,IAAI,WAAW,mBAAmB;AAAA,SAC9D;AACH,iBAAW,QAAQ,CAAC,KAAK,GAAG,GAAY;AACtC,cAAM,IAAI,MAAM,OAAO,IAAI;AAC3B,YAAI,MAAM,WAAc,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,IAAI;AAC5D,cAAI,GAAG,IAAI,WAAW,IAAI,IAAI,uCAAuC;AAAA,QACvE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,MAAI,MAAM,UAAU,QAAW;AAC7B,QAAI,CAAC,MAAM,MAAM,KAAK,EAAG,KAAI,GAAG,IAAI,UAAU,mBAAmB;AAAA,SAC5D;AACH,UAAI,CAAC,MAAM,MAAM,MAAM,GAAG,KAAK,MAAM,MAAM,OAAO,KAAK,MAAM,MAAM,MAAM,OAAO,aAAa;AAC3F,YAAI,GAAG,IAAI,cAAc,qBAAqB,OAAO,WAAW,EAAE;AAAA,MACpE;AACA,UAAI,CAAC,MAAM,MAAM,MAAM,MAAM,KAAK,MAAM,MAAM,SAAS,OAAO,gBAAgB;AAC5E,YAAI,GAAG,IAAI,iBAAiB,cAAc,OAAO,cAAc,0BAA0B;AAAA,MAC3F;AACA,UAAI,MAAM,MAAM,SAAS,QAAW;AAClC,YAAI,CAAC,MAAM,MAAM,MAAM,IAAI,EAAG,KAAI,GAAG,IAAI,eAAe,mBAAmB;AAAA,aACtE;AACH,cAAI,CAAC,MAAM,MAAM,MAAM,KAAK,UAAU,KAAK,MAAM,MAAM,KAAK,cAAc,GAAG;AAC3E,gBAAI,GAAG,IAAI,0BAA0B,oCAAoC;AAAA,UAC3E;AACA,cAAI,MAAM,MAAM,KAAK,UAAU,UAAa,CAAC,MAAM,MAAM,MAAM,KAAK,KAAK,GAAG;AAC1E,gBAAI,GAAG,IAAI,qBAAqB,4BAA4B;AAAA,UAC9D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,MAAI,MAAM,SAAS,QAAW;AAC5B,QAAI,QAAQ,MAAM,IAAI,GAAG;AACvB,UAAI,KAAK,IAAI,MAAM,KAAK,CAAC,CAAC,IAAI,OAAO,WAAW,KAAK,IAAI,MAAM,KAAK,CAAC,CAAC,IAAI,OAAO,SAAS;AACxF,YAAI,GAAG,IAAI,SAAS,4CAAyC,OAAO,OAAO,UAAU;AAAA,MACvF;AAAA,IACF,WAAW,CAAC,MAAM,MAAM,IAAI,GAAG;AAC7B,UAAI,GAAG,IAAI,SAAS,qDAAqD;AAAA,IAC3E,WAAW,KAAK,IAAI,MAAM,IAAI,IAAI,OAAO,SAAS;AAChD,UAAI,GAAG,IAAI,SAAS,sBAAmB,OAAO,OAAO,UAAU;AAAA,IACjE;AAAA,EACF;AACA,MAAI,MAAM,WAAW,QAAW;AAC9B,QAAI,QAAQ,MAAM,MAAM,GAAG;AACzB,UAAI,KAAK,IAAI,MAAM,OAAO,CAAC,CAAC,IAAI,OAAO,aAAa,KAAK,IAAI,MAAM,OAAO,CAAC,CAAC,IAAI,OAAO,WAAW;AAChG,YAAI,GAAG,IAAI,WAAW,4CAAyC,OAAO,SAAS,UAAU;AAAA,MAC3F;AAAA,IACF,WAAW,CAAC,MAAM,MAAM,MAAM,GAAG;AAC/B,UAAI,GAAG,IAAI,WAAW,iDAAiD;AAAA,IACzE,WAAW,KAAK,IAAI,MAAM,MAAM,IAAI,OAAO,WAAW;AACpD,UAAI,GAAG,IAAI,WAAW,sBAAmB,OAAO,SAAS,UAAU;AAAA,IACrE;AAAA,EACF;AACA,MAAI,MAAM,SAAS,QAAW;AAC5B,QAAI,CAAC,MAAM,MAAM,IAAI,EAAG,KAAI,GAAG,IAAI,SAAS,mBAAmB;AAAA,SAC1D;AACH,UAAI,CAAC,MAAM,MAAM,KAAK,GAAG,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,KAAK,MAAM,OAAO,YAAY;AACvF,YAAI,GAAG,IAAI,aAAa,qBAAqB,OAAO,UAAU,EAAE;AAAA,MAClE;AACA,UAAI,CAAC,MAAM,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,SAAS,OAAO,gBAAgB;AAC1E,YAAI,GAAG,IAAI,gBAAgB,cAAc,OAAO,cAAc,0BAA0B;AAAA,MAC1F;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,UAAU,QAAW;AAC7B,QAAI,CAAC,MAAM,MAAM,KAAK,EAAG,KAAI,GAAG,IAAI,UAAU,mBAAmB;AAAA,SAC5D;AAIH,YAAM,QAAQ,MAAM,MAAM,SAAS;AACnC,UAAI,CAAC,SAAS,MAAM,MAAM,MAAM,QAAW;AACzC,YAAI,CAAC,MAAM,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,UAAU,MAAM,MAAM,CAAC,KAAK,MAAM,MAAM,IAAI,KAAK,MAAM,MAAM,IAAI,OAAO,WAAW;AACtH,cAAI,GAAG,IAAI,YAAY,yBAAyB,OAAO,SAAS,EAAE;AAAA,QACpE;AAAA,MACF;AACA,UAAI,CAAC,SAAS,MAAM,MAAM,YAAY,UAAa,MAAM,MAAM,YAAY,MAAM;AAC/E;AAAA,UACE,MAAM,MAAM;AAAA,UACZ,GAAG,IAAI;AAAA,UACP;AAAA,UACA,SAAS,MAAM,MAAM,YAAY,SAAY,qFAAgF;AAAA,QAC/H;AAAA,MACF;AACA,UAAI,MAAM,MAAM,UAAU,OAAW,OAAM,MAAM,MAAM,OAAO,GAAG,IAAI,gBAAgB,GAAG;AACxF,UAAI,MAAM,MAAM,UAAU,WAAc,CAAC,MAAM,MAAM,MAAM,KAAK,KAAK,MAAM,MAAM,QAAQ,KAAK,MAAM,MAAM,QAAQ,IAAI;AACpH,YAAI,GAAG,IAAI,gBAAgB,cAAc;AAAA,MAC3C;AACA,UAAI,MAAM,MAAM,UAAU,OAAW,gBAAe,MAAM,MAAM,OAAO,GAAG,IAAI,gBAAgB,GAAG;AACjG,UAAI,MAAM,MAAM,SAAS,UAAa,CAAC,CAAC,WAAW,SAAS,QAAQ,EAAE,SAAS,MAAM,MAAM,IAAc,GAAG;AAC1G,YAAI,GAAG,IAAI,eAAe,wCAAwC;AAAA,MACpE;AACA,UAAI,MAAM,MAAM,YAAY,UAAa,OAAO,MAAM,MAAM,YAAY,WAAW;AACjF,YAAI,GAAG,IAAI,kBAAkB,mBAAmB;AAAA,MAClD;AACA,UAAI,MAAM,MAAM,WAAW,UAAa,OAAO,MAAM,MAAM,WAAW,WAAW;AAC/E,YAAI,GAAG,IAAI,iBAAiB,mBAAmB;AAAA,MACjD;AACA,UAAI,MAAM,MAAM,KAAK,KAAK,MAAM,QAAQ,OAAO,mBAAmB;AAChE,YAAI,GAAG,IAAI,UAAU,0BAA0B,OAAO,iBAAiB,oBAAoB;AAAA,MAC7F;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,WAAW,QAAW;AAC9B,QAAI,MAAM,MAAM,MAAM,MAAM,MAAM,OAAO,SAAS,UAAU,MAAM,OAAO,SAAS,UAAU;AAC1F,YAAM,MAAM,MAAM;AAClB,UAAI,IAAI,SAAS,YAAY,CAAC,MAAM,IAAI,OAAO,KAAK,CAAC,OAAO,UAAU,IAAI,OAAO,KAAK,IAAI,UAAU,KAAK,IAAI,UAAU,OAAO,iBAAiB;AAC7I,YAAI,GAAG,IAAI,mBAAmB,yBAAyB,OAAO,cAAc,EAAE;AAAA,MAChF;AACA,YAAM,QAAQ,CAAC,MAAwB,MAAM,CAAC,KAAK,IAAI;AACvD,UAAI,IAAI,QAAQ,QAAW;AACzB,YAAI,MAAM,IAAI,GAAG,GAAG;AAClB,cAAI,CAAC,MAAM,IAAI,GAAG,EAAG,KAAI,GAAG,IAAI,eAAe,iDAAiD;AAAA,QAClG,WAAW,IAAI,SAAS,WAAW,MAAM,IAAI,GAAG,GAAG;AACjD,cAAI,IAAI,IAAI,MAAM,UAAa,CAAC,MAAM,IAAI,IAAI,CAAC,EAAG,KAAI,GAAG,IAAI,iBAAiB,aAAa;AAC3F,cAAI,IAAI,IAAI,MAAM,UAAa,CAAC,MAAM,IAAI,IAAI,CAAC,EAAG,KAAI,GAAG,IAAI,iBAAiB,aAAa;AAC3F,qBAAW,KAAK,YAAY,IAAI,KAAK,oBAAI,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG;AACzD,iBAAK,GAAG,IAAI,eAAe,CAAC,IAAI,oBAAoB,yBAAyB,CAAC,0BAAqB;AAAA,UACrG;AAAA,QACF,OAAO;AACL,cAAI,GAAG,IAAI,eAAe,IAAI,SAAS,UAAU,uCAAuC,sBAAsB;AAAA,QAChH;AAAA,MACF;AACA,iBAAW,KAAK,YAAY,KAAK,IAAI,IAAI,IAAI,SAAS,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,WAAW,KAAK,CAAC,CAAC,GAAG;AAC7G,aAAK,GAAG,IAAI,WAAW,CAAC,IAAI,oBAAoB,4BAA4B,CAAC,0BAAqB;AAAA,MACpG;AAEA,YAAM,KAAK,MAAM;AACjB,UAAI,MAAM,EAAE,KAAK,MAAM,MAAM,KAAK,GAAG;AACnC,cAAM,WAAW,GAAG,SAAS,UAAU,MAAM,QAAQ,GAAG,OAAO,IAAI,GAAG,QAAQ,SAC1E,GAAG,SAAS,WAAW,MAAM,QAAQ,GAAG,MAAM,IAAI,GAAG,OAAO,SAC1D,GAAG,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IAAI,GAAG,OAAO,SAAS;AACzE,YAAI,aAAa,QAAQ,aAAa,MAAM,OAAO;AACjD,eAAK,GAAG,IAAI,UAAU,wBAAwB,YAAY,MAAM,KAAK,2BAA2B,QAAQ,IAAI,GAAG,SAAS,QAAQ,WAAW,UAAU,aAAQ,IAAI,IAAI,yDAAyD;AAAA,QAChO;AAAA,MACF;AAAA,IACF,WAAW,CAAC,MAAM,MAAM,MAAM,KAAK,MAAM,OAAO,SAAS,QAAQ;AAC/D,UAAI,GAAG,IAAI,WAAW,wDAAwD;AAAA,IAChF,OAAO;AACL,UAAI,MAAM,OAAO,YAAY,WAAc,CAAC,MAAM,MAAM,OAAO,OAAO,KAAK,CAAC,OAAO,UAAU,MAAM,OAAO,OAAO,KAAK,MAAM,OAAO,UAAU,KAAK,MAAM,OAAO,UAAU,OAAO,iBAAiB;AAC/L,YAAI,GAAG,IAAI,mBAAmB,yBAAyB,OAAO,cAAc,EAAE;AAAA,MAChF;AACA,YAAM,MAAM,MAAM,OAAO;AACzB,UAAI,QAAQ,QAAW;AACrB,cAAM,WAAW,CAAC,MAAwB,MAAM,CAAC,KAAK,KAAK,KAAK,KAAK;AACrE,YAAI,MAAM,GAAG,GAAG;AACd,cAAI,CAAC,SAAS,GAAG,EAAG,KAAI,GAAG,IAAI,kBAAkB,cAAc;AAAA,QACjE,WAAW,MAAM,GAAG,GAAG;AACrB,cAAI,IAAI,MAAM,UAAa,CAAC,SAAS,IAAI,CAAC,EAAG,KAAI,GAAG,IAAI,oBAAoB,cAAc;AAC1F,cAAI,IAAI,MAAM,UAAa,CAAC,SAAS,IAAI,CAAC,EAAG,KAAI,GAAG,IAAI,oBAAoB,cAAc;AAAA,QAC5F,OAAO;AACL,cAAI,GAAG,IAAI,kBAAkB,qCAAqC;AAAA,QACpE;AAAA,MACF;AACA,UAAI,MAAM,aAAa,QAAW;AAChC,aAAK,GAAG,IAAI,WAAW,wBAAwB,6EAAwE;AAAA,MACzH;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,SAAS,QAAW;AAC5B,QAAI,CAAC,MAAM,MAAM,IAAI,EAAG,KAAI,GAAG,IAAI,SAAS,mBAAmB;AAAA,SAC1D;AACH,UAAI,MAAM,KAAK,UAAU,WAAc,CAAC,MAAM,MAAM,KAAK,KAAK,KAAK,MAAM,KAAK,QAAQ,IAAI;AACxF,YAAI,GAAG,IAAI,eAAe,mBAAmB;AAAA,MAC/C;AACA,UAAI,MAAM,KAAK,SAAS,WAAc,CAAC,MAAM,MAAM,KAAK,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI;AACrF,YAAI,GAAG,IAAI,cAAc,mBAAmB;AAAA,MAC9C;AACA,UAAI,MAAM,MAAM,KAAK,KAAK,KAAK,MAAM,MAAM,KAAK,IAAI,KAAK,MAAM,KAAK,QAAQ,MAAM,KAAK,OAAO;AAC5F,YAAI,GAAG,IAAI,cAAc,iCAAiC;AAAA,MAC5D;AACA,UAAI,MAAM,KAAK,SAAS,WAAc,CAAC,MAAM,MAAM,KAAK,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI;AACrF,YAAI,GAAG,IAAI,cAAc,mBAAmB;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,UAAU,QAAW;AAC7B,QAAI,CAAC,MAAM,MAAM,KAAK,EAAG,KAAI,GAAG,IAAI,UAAU,mBAAmB;AAAA,SAC5D;AACH,UAAI,CAAC,MAAM,MAAM,MAAM,MAAM,KAAK,MAAM,MAAM,UAAU,KAAK,MAAM,MAAM,SAAS,OAAO,gBAAgB;AACvG,YAAI,GAAG,IAAI,iBAAiB,sBAAsB,OAAO,cAAc,KAAK;AAAA,MAC9E;AACA,UAAI,MAAM,MAAM,SAAS,WAAc,CAAC,MAAM,MAAM,MAAM,IAAI,KAAK,MAAM,MAAM,OAAO,KAAK,MAAM,MAAM,OAAO,IAAI;AAChH,YAAI,GAAG,IAAI,eAAe,cAAc;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,SAAS,QAAW;AAC5B,QAAI,CAAC,MAAM,MAAM,IAAI,EAAG,KAAI,GAAG,IAAI,SAAS,mDAAmD;AAAA,SAC1F;AACH,YAAM,KAAK,MAAM;AACjB,UAAI,CAAC,MAAM,GAAG,KAAK,KAAK,GAAG,QAAQ,OAAO,gBAAgB,GAAG,QAAQ,OAAO,cAAc;AACxF,YAAI,GAAG,IAAI,eAAe,WAAW,OAAO,YAAY,KAAK,OAAO,YAAY,+CAA+C;AAAA,MACjI;AACA,UAAI,CAAC,MAAM,GAAG,IAAI,KAAK,GAAG,OAAO,OAAO,aAAa;AACnD,YAAI,GAAG,IAAI,cAAc,cAAc,OAAO,WAAW,kDAAkD;AAAA,MAC7G,WAAW,MAAM,GAAG,KAAK,KAAK,GAAG,OAAO,GAAG,OAAO;AAChD,YAAI,GAAG,IAAI,cAAc,sEAAsE;AAAA,MACjG;AACA,UAAI,GAAG,WAAW,WAAc,CAAC,MAAM,GAAG,MAAM,KAAK,GAAG,SAAS,KAAK,GAAG,SAAS,IAAI;AACpF,YAAI,GAAG,IAAI,gBAAgB,wEAAwE;AAAA,MACrG;AACA,UAAI,GAAG,SAAS,QAAW;AACzB,YAAI,CAAC,MAAM,QAAQ,GAAG,IAAI,KAAK,GAAG,KAAK,WAAW,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,GAAG;AAC/F,cAAI,GAAG,IAAI,cAAc,qCAAqC;AAAA,QAChE,WAAW,GAAG,KAAK,CAAC,IAAI,KAAK,GAAG,KAAK,CAAC,IAAI,KAAK,GAAG,KAAK,CAAC,IAAI,OAAO,eAAe,GAAG,KAAK,CAAC,IAAI,OAAO,aAAa;AACjH,cAAI,GAAG,IAAI,cAAc,8BAA8B,OAAO,WAAW,EAAE;AAAA,QAC7E;AAAA,MACF;AAGA,UAAI,GAAG,WAAW,KAAK,MAAM,GAAG,KAAK,KAAK,MAAM,GAAG,IAAI,KAAK,MAAM,MAAM,KAAK,KAAK,MAAM,QAAQ,KAAK,GAAG,OAAO,GAAG,QAAQ,MAAM,OAAO;AACrI,aAAK,GAAG,IAAI,cAAc,gBAAgB,qBAAqB,MAAM,KAAK,cAAc,GAAG,QAAQ,MAAM,OAAO,QAAQ,CAAC,CAAC,gCAAgC,GAAG,IAAI,yGAAoG;AAAA,MACvQ;AACA,iBAAW,KAAK,YAAY,IAAI,oBAAI,IAAI,CAAC,SAAS,QAAQ,UAAU,MAAM,CAAC,CAAC,GAAG;AAC7E,aAAK,GAAG,IAAI,SAAS,CAAC,IAAI,oBAAoB,0BAA0B,CAAC,0BAAqB;AAAA,MAChG;AAAA,IACF;AAAA,EACF;AACA,MAAI,MAAM,UAAU,QAAW;AAC7B,QAAI,CAAC,MAAM,MAAM,KAAK,EAAG,KAAI,GAAG,IAAI,UAAU,qCAAqC;AAAA,SAC9E;AACH,YAAM,KAAK,MAAM;AACjB,UAAI,GAAG,UAAU,WAAc,CAAC,MAAM,GAAG,KAAK,KAAK,GAAG,QAAQ,KAAK,GAAG,QAAQ,IAAI;AAChF,YAAI,GAAG,IAAI,gBAAgB,sBAAsB;AAAA,MACnD;AACA,YAAM,OAAO,GAAG,SAAS,SAAY,IAAI,GAAG;AAC5C,UAAI,CAAC,MAAM,IAAI,KAAK,OAAO,OAAO,gBAAgB,OAAO,OAAO,cAAc;AAC5E,YAAI,GAAG,IAAI,eAAe,WAAW,OAAO,YAAY,KAAK,OAAO,YAAY,EAAE;AAAA,MACpF,OAAO;AAGL,cAAM,QAAQ,OAAO,mBAAmB;AACxC,YAAI,MAAM,MAAM,KAAK,KAAK,MAAM,MAAM,MAAM,MAAM,KAAK,MAAM,MAAM,SAAS,OAAO;AACjF,cAAI,GAAG,IAAI,iBAAiB,cAAc,KAAK,oDAAoD,OAAO,gBAAgB,6CAAwC;AAAA,QACpK;AACA,YAAI,MAAM,MAAM,IAAI,KAAK,MAAM,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,SAAS,OAAO;AAC9E,cAAI,GAAG,IAAI,gBAAgB,cAAc,KAAK,oDAAoD,OAAO,gBAAgB,GAAG;AAAA,QAC9H;AACA,cAAM,KAAK,MAAM;AACjB,YAAI,MAAM,EAAE,KAAK,MAAM,GAAG,KAAK,KAAK,MAAM,GAAG,MAAM,MAAM,KAAK,GAAG,MAAM,SAAS,OAAO;AACrF,cAAI,GAAG,IAAI,wBAAwB,cAAc,KAAK,oDAAoD,OAAO,gBAAgB,GAAG;AAAA,QACtI;AAAA,MACF;AACA,iBAAW,KAAK,YAAY,IAAI,oBAAI,IAAI,CAAC,SAAS,MAAM,CAAC,CAAC,GAAG;AAC3D,aAAK,GAAG,IAAI,UAAU,CAAC,IAAI,oBAAoB,2BAA2B,CAAC,0BAAqB;AAAA,MAClG;AAAA,IACF;AAAA,EACF;AACA,iBAAe,MAAM,QAAQ,GAAG,IAAI,WAAW,KAAK,MAAM,IAAI;AAC9D,iBAAe,MAAM,QAAQ,GAAG,IAAI,WAAW,KAAK,MAAM,IAAI;AAChE;AAEA,SAAS,eAAe,QAAiB,MAAc,KAAqC,MAAc,MAAsB;AAC9H,MAAI,CAAC,MAAM,MAAM,EAAG,QAAO,IAAI,MAAM,mBAAmB;AAExD,MAAI;AACJ,MAAI,OAAO,SAAS,SAAS;AAC3B,eAAW;AACX,QAAI,CAAC,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,WAAW,KAAK,CAAC,OAAO,OAAO,MAAM,KAAK,GAAG;AAC9F,UAAI,GAAG,IAAI,WAAW,sCAAsC;AAAA,IAC9D;AACA,kBAAc,QAAQ,MAAM,GAAG;AAAA,EACjC,WAAW,OAAO,SAAS,QAAQ;AACjC,eAAW;AACX,QAAI,CAAC,MAAM,QAAQ,OAAO,OAAO,KAAK,OAAO,QAAQ,WAAW,KAAK,CAAC,OAAO,QAAQ,MAAM,KAAK,GAAG;AACjG,UAAI,GAAG,IAAI,YAAY,sCAAsC;AAAA,IAC/D;AACA,QAAI,OAAO,UAAU,OAAW,OAAM,OAAO,OAAO,GAAG,IAAI,UAAU,GAAG;AACxE,QAAI,OAAO,SAAS,UAAa,CAAC,MAAM,OAAO,IAAI,GAAG;AACpD,UAAI,GAAG,IAAI,SAAS,kBAAkB;AAAA,IACxC;AACA,QAAI,OAAO,UAAU,UAAa,CAAC,CAAC,QAAQ,UAAU,OAAO,EAAE,SAAS,OAAO,KAAe,GAAG;AAC/F,UAAI,GAAG,IAAI,UAAU,+BAA+B;AAAA,IACtD;AACA,QAAI,OAAO,aAAa,UAAa,CAAC,CAAC,OAAO,UAAU,QAAQ,EAAE,SAAS,OAAO,QAAkB,GAAG;AACrG,UAAI,GAAG,IAAI,aAAa,+BAA+B;AAAA,IACzD;AACA,QAAI,OAAO,aAAa,OAAW,gBAAe,OAAO,UAAU,GAAG,IAAI,aAAa,KAAK,2BAA2B;AACvH,qBAAiB,QAAQ,MAAM,GAAG;AAClC,kBAAc,QAAQ,MAAM,GAAG;AAAA,EACjC,WAAW,OAAO,SAAS,UAAU;AACnC,eAAW;AACX,QAAI,CAAC,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,CAAC,KAAK,EAAG,KAAI,GAAG,IAAI,WAAW,SAAS,IAAI,CAAC;AAC1F,UAAM,OAAO,OAAO,GAAG,IAAI,UAAU,GAAG;AACxC,QAAI,OAAO,SAAS,UAAa,OAAO,OAAO,SAAS,UAAW,KAAI,GAAG,IAAI,SAAS,mBAAmB;AAC1G,oBAAgB,QAAQ,MAAM,GAAG;AAAA,EACnC,WAAW,OAAO,SAAS,QAAQ;AACjC,eAAW;AACX,QAAI,CAAC,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,CAAC,KAAK,EAAG,KAAI,GAAG,IAAI,WAAW,SAAS,IAAI,CAAC;AAC1F,UAAM,OAAO,OAAO,GAAG,IAAI,UAAU,GAAG;AACxC,QAAI,OAAO,UAAU,OAAW,gBAAe,OAAO,OAAO,GAAG,IAAI,UAAU,GAAG;AACjF,oBAAgB,QAAQ,MAAM,GAAG;AAAA,EACnC,WAAW,OAAO,SAAS,UAAU;AACnC,eAAW;AACX,QAAI,CAAC,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,CAAC,KAAK,EAAG,KAAI,GAAG,IAAI,WAAW,SAAS,IAAI,CAAC;AAC1F,UAAM,OAAO,OAAO,GAAG,IAAI,UAAU,GAAG;AACxC,QAAI,OAAO,UAAU,OAAW,gBAAe,OAAO,OAAO,GAAG,IAAI,UAAU,GAAG;AACjF,oBAAgB,QAAQ,MAAM,GAAG;AAAA,EACnC,WAAW,OAAO,SAAS,QAAQ;AACjC,eAAW;AACX,QAAI,CAAC,QAAQ,OAAO,KAAK,KAAK,OAAO,MAAM,CAAC,KAAK,EAAG,KAAI,GAAG,IAAI,UAAU,SAAS,IAAI,CAAC;AACvF,QAAI,OAAO,WAAW,WAAc,CAAC,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,CAAC,KAAK,IAAI;AACrF,UAAI,GAAG,IAAI,WAAW,2DAA2D;AAAA,IACnF;AACA,QAAI,OAAO,YAAY,WAAc,CAAC,MAAM,OAAO,OAAO,KAAK,OAAO,UAAU,KAAK,OAAO,UAAU,IAAI;AACxG,UAAI,GAAG,IAAI,YAAY,yDAAyD;AAAA,IAClF;AACA,UAAM,OAAO,OAAO,GAAG,IAAI,UAAU,GAAG;AACxC,oBAAgB,QAAQ,MAAM,GAAG;AAAA,EACnC,WAAW,OAAO,SAAS,OAAO;AAChC,eAAW;AACX,QAAI,CAAC,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,WAAW,KAAK,OAAO,OAAO,SAAS,OAAO,eAAe,CAAC,OAAO,OAAO,MAAM,CAAC,MAAM,MAAM,CAAC,KAAK,KAAK,CAAC,GAAG;AAC/J,UAAI,GAAG,IAAI,WAAW,cAAc,OAAO,WAAW,eAAe;AAAA,IACvE;AACA,mBAAe,OAAO,QAAQ,GAAG,IAAI,WAAW,KAAK,qCAAqC;AAC1F,mBAAe,OAAO,WAAW,GAAG,IAAI,cAAc,GAAG;AACzD,QAAI,OAAO,QAAQ,OAAW,gBAAe,OAAO,KAAK,GAAG,IAAI,QAAQ,GAAG;AAC3E,QAAI,OAAO,cAAc,UAAa,CAAC,CAAC,SAAS,QAAQ,MAAM,MAAM,EAAE,SAAS,OAAO,SAAmB,GAAG;AAC3G,UAAI,GAAG,IAAI,cAAc,0CAA0C;AAAA,IACrE;AACA,UAAM,OAAO,OAAO,GAAG,IAAI,UAAU,GAAG;AACxC,oBAAgB,QAAQ,MAAM,GAAG;AAAA,EACnC,WAAW,OAAO,SAAS,WAAW;AACpC,eAAW;AACX,QAAI,CAAC,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,CAAC,KAAK,EAAG,KAAI,GAAG,IAAI,WAAW,SAAS,MAAM,cAAc,CAAC;AAC1G,QAAI,OAAO,UAAU,UAAa,OAAO,WAAW,QAAW;AAC7D,UAAI,GAAG,IAAI,UAAU,kEAAkE;AAAA,IACzF;AACA,QAAI,OAAO,UAAU,WAAc,CAAC,MAAM,OAAO,KAAK,KAAK,CAAC,OAAO,UAAU,OAAO,KAAK,KAAK,OAAO,QAAQ,OAAO,mBAAmB,OAAO,QAAQ,OAAO,kBAAkB;AAC7K,UAAI,GAAG,IAAI,UAAU,sBAAsB,OAAO,eAAe,KAAK,OAAO,eAAe,EAAE;AAAA,IAChG;AACA,QAAI,OAAO,WAAW,OAAW,qBAAoB,OAAO,QAAQ,GAAG,IAAI,WAAW,GAAG,GAAG;AAC5F,QAAI,OAAO,UAAU,QAAW;AAE9B,iBAAW,KAAK,CAAC,QAAQ,UAAU,SAAS,YAAY,UAAU,QAAQ,UAAU,GAAY;AAC9F,YAAI,OAAO,CAAC,MAAM,OAAW,KAAI,GAAG,IAAI,IAAI,CAAC,IAAI,mBAAmB,CAAC,+BAA+B;AAAA,MACtG;AACA,UAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,KAAK,OAAO,MAAM,WAAW,KAAK,OAAO,MAAM,SAAS,gBAAgB;AACrG,YAAI,GAAG,IAAI,UAAU,cAAc,cAAc,+EAA+E;AAAA,MAClI,OAAO;AACL,eAAO,MAAM,QAAQ,CAAC,MAAe,MAAc;AACjD,gBAAM,KAAK,GAAG,IAAI,UAAU,CAAC;AAC7B,cAAI,CAAC,MAAM,IAAI,EAAG,QAAO,IAAI,IAAI,0EAA0E;AAC3G,4BAAkB,MAAM,IAAI,KAAK,IAAI;AACrC,cAAI,KAAK,UAAU,OAAW,OAAM,KAAK,OAAO,GAAG,EAAE,UAAU,GAAG;AAClE,cAAI,KAAK,YAAY,WAAc,CAAC,MAAM,KAAK,OAAO,KAAK,KAAK,UAAU,KAAK,KAAK,UAAU,GAAI,KAAI,GAAG,EAAE,YAAY,cAAc;AACrI,qBAAW,KAAK,YAAY,MAAM,eAAe,EAAG,MAAK,GAAG,EAAE,IAAI,CAAC,IAAI,oBAAoB,0BAA0B,CAAC,0BAAqB;AAAA,QAC7I,CAAC;AAAA,MACH;AAAA,IACF,WAAW,OAAO,SAAS,QAAW;AACpC,UAAI,OAAO,WAAW,UAAa,OAAO,UAAU,OAAW,KAAI,GAAG,IAAI,SAAS,8CAA8C;AACjI,wBAAkB,QAAQ,MAAM,KAAK,IAAI;AAAA,IAC3C,OAAO;AACL,iBAAW,KAAK,CAAC,YAAY,UAAU,MAAM,EAAY,KAAI,OAAO,CAAC,MAAM,OAAW,KAAI,GAAG,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,mDAAmD;AACjK,UAAI,OAAO,aAAa,OAAW,MAAK,GAAG,IAAI,aAAa,oBAAoB,gDAA2C;AAAA,IAC7H;AACA,QAAI,OAAO,SAAS,UAAa,OAAO,WAAW,QAAW;AAC5D,UAAI,OAAO,SAAS,UAAa,OAAO,UAAU,OAAW,KAAI,GAAG,IAAI,SAAS,gEAAgE;AACjJ,UAAI,OAAO,SAAS,UAAa,CAAC,CAAC,OAAO,SAAS,UAAU,QAAQ,EAAE,SAAS,OAAO,IAAc,EAAG,KAAI,GAAG,IAAI,SAAS,+CAA+C;AAC3K,UAAI,OAAO,WAAW,UAAa,EAAE,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,WAAW,KAAK,OAAO,OAAO,MAAM,CAAC,MAAe,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,GAAI,KAAI,GAAG,IAAI,WAAW,0EAA0E;AAAA,IACzQ;AACA,QAAI,OAAO,SAAS,UAAa,OAAO,OAAO,SAAS,UAAW,KAAI,GAAG,IAAI,SAAS,mBAAmB;AAC1G,UAAM,OAAO,OAAO,GAAG,IAAI,UAAU,GAAG;AACxC,oBAAgB,QAAQ,MAAM,GAAG;AAAA,EACnC,WAAW,OAAO,SAAS,UAAU;AACnC,eAAW;AACX,QAAI,CAAC,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,CAAC,KAAK,EAAG,KAAI,GAAG,IAAI,WAAW,SAAS,MAAM,0BAA0B,CAAC;AACtH,wBAAoB,OAAO,QAAQ,GAAG,IAAI,WAAW,GAAG,GAAG;AAC3D,QAAI,OAAO,UAAU,OAAW,gBAAe,OAAO,OAAO,GAAG,IAAI,UAAU,GAAG;AACjF,QAAI,OAAO,UAAU,UAAa,OAAO,UAAU,YAAY,OAAO,UAAU,SAAU,KAAI,GAAG,IAAI,UAAU,6BAA6B;AAC5I,QAAI,OAAO,UAAU,UAAa,OAAO,OAAO,UAAU,UAAW,KAAI,GAAG,IAAI,UAAU,mBAAmB;AAC7G,QAAI,OAAO,WAAW,UAAa,OAAO,OAAO,WAAW,UAAW,KAAI,GAAG,IAAI,WAAW,mBAAmB;AAChH,UAAM,OAAO,OAAO,GAAG,IAAI,UAAU,GAAG;AACxC,oBAAgB,QAAQ,MAAM,GAAG;AAAA,EACnC,WAAW,OAAO,SAAS,aAAa;AACtC,eAAW;AACX,QAAI,OAAO,OAAO,SAAS,YAAY,OAAO,KAAK,WAAW,GAAG;AAC/D,UAAI,GAAG,IAAI,SAAS,4BAA4B;AAAA,IAClD,WAAW,OAAO,KAAK,SAAS,OAAO,oBAAoB;AACzD,UAAI,GAAG,IAAI,SAAS,mBAAmB,OAAO,kBAAkB,aAAa;AAAA,IAC/E;AACA,QAAI,MAAM,QAAQ,OAAO,QAAQ,GAAG;AAClC,UAAI,GAAG,IAAI,aAAa,oEAAoE;AAAA,IAC9F,WAAW,CAAC,MAAM,OAAO,QAAQ,KAAK,OAAO,YAAY,KAAK,OAAO,WAAW,OAAO,sBAAsB;AAC3G,UAAI,GAAG,IAAI,aAAa,mCAAmC,OAAO,oBAAoB,sBAAsB;AAAA,IAC9G;AACA,QAAI,MAAM,QAAQ,OAAO,QAAQ,GAAG;AAClC,UAAI,GAAG,IAAI,aAAa,oEAAoE;AAAA,IAC9F,WAAW,CAAC,MAAM,OAAO,QAAQ,KAAK,OAAO,WAAW,OAAO,wBAAwB,OAAO,WAAW,OAAO,sBAAsB;AACpI,UAAI,GAAG,IAAI,aAAa,mBAAmB,OAAO,oBAAoB,QAAQ,OAAO,oBAAoB,sBAAsB;AAAA,IACjI;AACA,QAAI,OAAO,eAAe,WAAc,CAAC,MAAM,OAAO,UAAU,KAAK,OAAO,aAAa,OAAO,OAAO,aAAa,IAAI;AACtH,UAAI,GAAG,IAAI,eAAe,wCAAwC;AAAA,IACpE;AACA,QAAI,OAAO,UAAU,UAAa,CAAC,CAAC,QAAQ,UAAU,OAAO,EAAE,SAAS,OAAO,KAAe,GAAG;AAC/F,UAAI,GAAG,IAAI,UAAU,qCAAqC;AAAA,IAC5D;AACA,QAAI,OAAO,UAAU,OAAW,OAAM,OAAO,OAAO,GAAG,IAAI,UAAU,GAAG;AACxE,QAAI,OAAO,WAAW,UAAa,CAAC,mBAAmB,IAAI,OAAO,MAAgB,GAAG;AACnF,UAAI,GAAG,IAAI,WAAW,oHAAoH;AAAA,IAC5I;AACA,QAAI,OAAO,SAAS,QAAW;AAC7B,UAAI,CAAC,MAAM,OAAO,IAAI,KAAK,OAAO,KAAK,KAAK,MAAM,IAAI;AACpD,YAAI,GAAG,IAAI,SAAS,mDAAmD;AAAA,MACzE,WAAW,aAAa,KAAK,OAAO,IAAI,GAAG;AACzC,YAAI,GAAG,IAAI,SAAS,qEAAgE;AAAA,MACtF;AAAA,IACF;AACA,QAAI,OAAO,YAAY,WAAc,CAAC,MAAM,OAAO,OAAO,KAAK,OAAO,UAAU,KAAK,OAAO,UAAU,IAAI;AACxG,UAAI,GAAG,IAAI,YAAY,kCAAkC;AAAA,IAC3D;AACA,qBAAiB,QAAQ,MAAM,GAAG;AAClC,QAAI,OAAO,WAAW,QAAW;AAC/B,YAAM,KAAK,OAAO;AAClB,UAAI,OAAO,OAAO,YAAY,OAAO,QAAQ,MAAM,QAAQ,EAAE,GAAG;AAC9D,YAAI,GAAG,IAAI,WAAW,mBAAmB;AAAA,MAC3C,OAAO;AACL,mBAAW,KAAK,OAAO,KAAK,EAAE,GAAG;AAC/B,cAAI,CAAC,aAAa,IAAI,CAAC,EAAG,KAAI,GAAG,IAAI,WAAW,CAAC,IAAI,sBAAsB;AAAA,QAC7E;AACA,YAAI,GAAG,aAAa,WAAc,CAAC,MAAM,GAAG,QAAQ,KAAK,GAAG,WAAW,KAAK,GAAG,WAAW,IAAI;AAC5F,cAAI,GAAG,IAAI,oBAAoB,kCAAkC;AAAA,QACnE;AACA,YAAI,GAAG,SAAS,UAAa,CAAC,CAAC,cAAc,QAAQ,QAAQ,WAAW,EAAE,SAAS,GAAG,IAAc,GAAG;AACrG,cAAI,GAAG,IAAI,gBAAgB,sDAAsD;AAAA,QACnF;AACA,YAAI,GAAG,SAAS,WAAc,CAAC,MAAM,GAAG,IAAI,KAAK,GAAG,QAAQ,KAAK,GAAG,OAAO,IAAI;AAC7E,cAAI,GAAG,IAAI,gBAAgB,4DAA4D;AAAA,QACzF;AACA,YAAI,GAAG,UAAU,WAAc,CAAC,MAAM,GAAG,KAAK,KAAK,GAAG,QAAQ,KAAK,GAAG,QAAQ,OAAO,iBAAiB;AACpG,cAAI,GAAG,IAAI,iBAAiB,yBAAyB,OAAO,cAAc,kBAAkB;AAAA,QAC9F;AACA,YAAI,GAAG,UAAU,UAAa,OAAO,GAAG,UAAU,WAAW;AAC3D,gBAAM,QAAQ,GAAG;AACjB,cAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG;AACvE,gBAAI,GAAG,IAAI,iBAAiB,gCAAgC;AAAA,UAC9D,OAAO;AACL,uBAAW,KAAK,OAAO,KAAK,KAAK,GAAG;AAClC,kBAAI,CAAC,mBAAmB,IAAI,CAAC,EAAG,KAAI,GAAG,IAAI,iBAAiB,CAAC,IAAI,qBAAqB;AAAA,YACxF;AACA,gBAAI,MAAM,UAAU,WAAc,CAAC,MAAM,MAAM,KAAK,KAAK,MAAM,SAAS,KAAK,MAAM,QAAQ,OAAO,kBAAkB;AAClH,kBAAI,GAAG,IAAI,uBAAuB,qCAAqC,OAAO,eAAe,oBAAoB;AAAA,YACnH;AACA,gBAAI,MAAM,UAAU,OAAW,OAAM,MAAM,OAAO,GAAG,IAAI,uBAAuB,GAAG;AAAA,UACrF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,OAAO;AACL,QAAI,GAAG,IAAI,SAAS,2FAA2F;AAC/G;AAAA,EACF;AAEA,aAAW,KAAK,YAAY,QAAQ,QAAQ,GAAG;AAC7C,QAAI,sBAAsB,IAAI,CAAC,GAAG;AAChC,WAAK,GAAG,IAAI,IAAI,CAAC,IAAI,sBAAsB,IAAI,CAAC,uEAAkE;AAAA,IACpH,OAAO;AACL,WAAK,GAAG,IAAI,IAAI,CAAC,IAAI,oBAAoB,4BAA4B,CAAC,0BAAqB;AAAA,IAC7F;AAAA,EACF;AACF;AAGA,SAAS,gBAAgB,QAAiC,MAAc,KAA2C;AACjH,MAAI,OAAO,WAAW,QAAW;AAC/B,QAAI,CAAC,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,WAAW,GAAG;AAC/D,UAAI,GAAG,IAAI,WAAW,0CAA0C;AAAA,IAClE,OAAO;AACL,aAAO,OAAO,QAAQ,CAAC,GAAY,OAAe,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,KAAK,GAAG,CAAC;AAAA,IAC1F;AAAA,EACF;AACA,MAAI,OAAO,iBAAiB,QAAW;AACrC,QAAI,CAAC,MAAM,QAAQ,OAAO,MAAM,GAAG;AACjC,UAAI,GAAG,IAAI,iBAAiB,2BAA2B;AAAA,IACzD,WAAW,CAAC,MAAM,QAAQ,OAAO,YAAY,KAAK,OAAO,aAAa,WAAW,OAAO,OAAO,QAAQ;AACrG,UAAI,GAAG,IAAI,iBAAiB,4CAA4C;AAAA,IAC1E,WAAW,CAAC,OAAO,aAAa,MAAM,CAAC,MAAe,MAAM,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,OAAO,aAAa,KAAK,CAAC,MAAe,MAAM,CAAC,KAAK,IAAI,CAAC,GAAG;AACzI,UAAI,GAAG,IAAI,iBAAiB,4CAA4C;AAAA,IAC1E;AAAA,EACF;AACF;AAGA,SAAS,iBAAiB,QAAiC,MAAc,KAA2C;AAClH,MAAI,OAAO,SAAS,UAAa,CAAC,WAAW,IAAI,OAAO,IAAc,GAAG;AACvE,QAAI,GAAG,IAAI,SAAS,+BAA+B;AAAA,EACrD;AACF;AAEA,SAAS,cAAc,QAAiC,MAAc,KAA2C;AAC/G,MAAI,OAAO,UAAU,OAAW;AAChC,MAAI,CAAC,MAAM,OAAO,KAAK,EAAG,QAAO,IAAI,GAAG,IAAI,UAAU,mBAAmB;AACzE,MAAI,CAAC,MAAM,OAAO,MAAM,MAAM,KAAK,OAAO,MAAM,SAAS,OAAO,gBAAgB;AAC9E,QAAI,GAAG,IAAI,iBAAiB,cAAc,OAAO,cAAc,0BAA0B;AAAA,EAC3F;AACF;AAEA,SAAS,eAAe,QAAiB,MAAc,KAAqC,MAAc,MAAsB;AAC9H,MAAI,CAAC,MAAM,MAAM,EAAG,QAAO,IAAI,MAAM,mBAAmB;AACxD,QAAM,aAAa,CAAC,MAAM,IAAI,KAAM,KAAiC,UAAU;AAC/E,QAAM,QAAQ,MAAM,IAAI,KAAK,MAAO,KAAiC,iBAAiB,IAAK,KAAiC,oBAA8B,OAAO;AACjK,QAAM,WAAW,aAAa,OAAO,WAAW,QAAQ,OAAO;AAC/D,QAAM,UAAU,CAAC,GAAY,MAAoB;AAC/C,QAAI,CAAC,QAAQ,CAAC,EAAG,KAAI,GAAG,2BAA2B;AAAA,aAC1C,EAAE,CAAC,IAAI,EAAG,KAAI,GAAG,gCAAgC;AAAA,aACjD,EAAE,CAAC,IAAI,SAAU,KAAI,GAAG,qBAAqB,aAAa,SAAS,QAAQ,CAAC,IAAI,wBAAwB,OAAO,WAAW,SAAS,EAAE;AAAA,EAChJ;AAEA,MAAI;AACJ,MAAI,OAAO,SAAS,SAAS;AAC3B,eAAW;AACX,YAAQ,OAAO,OAAO,GAAG,IAAI,QAAQ;AACrC,QAAI,OAAO,UAAU,UAAa,CAAC,MAAM,OAAO,KAAK,EAAG,KAAI,GAAG,IAAI,UAAU,4BAA4B;AACzG,QAAI,OAAO,kBAAkB,UAAa,OAAO,OAAO,kBAAkB,UAAW,KAAI,GAAG,IAAI,kBAAkB,mBAAmB;AACrI,QAAI,OAAO,QAAQ,UAAa,CAAC,MAAM,OAAO,GAAG,EAAG,KAAI,GAAG,IAAI,QAAQ,kBAAkB;AACzF,iBAAa,OAAO,MAAM,GAAG,IAAI,SAAS,KAAK,IAAI;AACnD,QAAI,QAAQ,OAAO,KAAK,KAAK,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY;AAC/D,WAAK,GAAG,IAAI,UAAU,mBAAmB,gBAAgB,OAAO,MAAM,CAAC,CAAC,+EAAqE;AAAA,IAC/I;AAAA,EACF,WAAW,OAAO,SAAS,QAAQ;AACjC,eAAW;AACX,YAAQ,OAAO,OAAO,GAAG,IAAI,QAAQ;AACrC,QAAI,OAAO,SAAS,UAAa,CAAC,MAAM,OAAO,IAAI,EAAG,KAAI,GAAG,IAAI,SAAS,kBAAkB;AAC5F,iBAAa,OAAO,MAAM,GAAG,IAAI,SAAS,KAAK,IAAI;AACnD,QAAI,QAAQ,OAAO,KAAK,KAAK,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY;AAC/D,WAAK,GAAG,IAAI,UAAU,mBAAmB,gBAAgB,OAAO,MAAM,CAAC,CAAC,6EAAmE;AAAA,IAC7I;AAAA,EACF,WAAW,OAAO,SAAS,UAAU;AACnC,eAAW;AACX,YAAQ,OAAO,OAAO,GAAG,IAAI,QAAQ;AACrC,QAAI,QAAQ,OAAO,KAAK,KAAK,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY;AAC/D,WAAK,GAAG,IAAI,UAAU,mBAAmB,gBAAgB,OAAO,MAAM,CAAC,CAAC,+EAAqE;AAAA,IAC/I;AAAA,EACF,WAAW,OAAO,SAAS,UAAU;AACnC,eAAW;AAAA,EACb,WAAW,OAAO,SAAS,SAAS;AAClC,eAAW;AACX,QAAI,CAAC,QAAQ,OAAO,KAAK,EAAG,KAAI,GAAG,IAAI,UAAU,2BAA2B;AAAA,SACvE;AACH,UAAI,KAAK,IAAI,OAAO,MAAM,CAAC,CAAC,IAAI,OAAO,iBAAiB,KAAK,IAAI,OAAO,MAAM,CAAC,CAAC,IAAI,OAAO,cAAe,KAAI,GAAG,IAAI,UAAU,2BAA2B,OAAO,aAAa,UAAU;AACxL,UAAI,KAAK,IAAI,KAAK,IAAI,OAAO,MAAM,CAAC,CAAC,GAAG,KAAK,IAAI,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG;AACtE,aAAK,GAAG,IAAI,UAAU,mBAAmB,+FAAqF;AAAA,MAChI;AAAA,IACF;AACA,QAAI,CAAC,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,CAAC,KAAK,EAAG,KAAI,GAAG,IAAI,WAAW,SAAS,IAAI,CAAC;AAC1F,QAAI,OAAO,WAAW,QAAW;AAC/B,UAAI,CAAC,MAAM,OAAO,MAAM,GAAG;AACzB,YAAI,GAAG,IAAI,WAAW,yCAAyC;AAAA,MACjE,WAAW,WAAW,OAAO,QAAQ;AACnC,YAAI,CAAC,MAAM,OAAO,OAAO,KAAK,KAAK,OAAO,OAAO,MAAM,KAAK,MAAM,IAAI;AACpE,cAAI,GAAG,IAAI,iBAAiB,+BAA+B;AAAA,QAC7D,WAAW,MAAM,IAAI,KAAK,MAAM,QAAS,KAAiC,MAAM,GAAG;AAGjF,gBAAM,SAAU,KAA+B;AAC/C,gBAAM,SAAS,OAAO,KAAK,CAAC,MAAM,MAAM,CAAC,KAAK,EAAE,QAAS,OAAO,OAA6B,KAAK;AAClG,cAAI,CAAC,QAAQ;AACX,gBAAI,GAAG,IAAI,iBAAiB,sBAAsB,OAAO,OAAO,KAAK,GAAG;AAAA,UAC1E,OAAO;AACL,gBAAI,OAAO,UAAU,EAAG,KAAI,GAAG,IAAI,iBAAiB,iCAAiC;AACrF,kBAAM,KAAK,OAAO;AAClB,gBAAI,MAAM,EAAE,KAAK,GAAG,SAAS,WAAW,MAAM,GAAG,MAAM,KAAK,WAAW,GAAG,QAAQ;AAChF,kBAAI,GAAG,IAAI,iBAAiB,2DAA2D;AAAA,YACzF;AAAA,UACF;AAAA,QACF;AAAA,MACF,WAAW,CAAC,MAAM,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,OAAO,OAAO,CAAC,GAAG;AAC7D,YAAI,GAAG,IAAI,WAAW,kCAAkC;AAAA,MAC1D,OAAO;AACL,YAAI,OAAO,OAAO,IAAI,KAAK,OAAO,OAAO,IAAI,EAAG,KAAI,GAAG,IAAI,aAAa,cAAc;AACtF,YAAI,OAAO,OAAO,IAAI,KAAK,OAAO,OAAO,IAAI,EAAG,KAAI,GAAG,IAAI,aAAa,cAAc;AAAA,MACxF;AAAA,IACF;AAAA,EACF,WAAW,OAAO,SAAS,UAAU;AACnC,eAAW;AACX,iBAAa,OAAO,MAAM,GAAG,IAAI,SAAS,KAAK,IAAI;AACnD,YAAQ,OAAO,OAAO,GAAG,IAAI,QAAQ;AACrC,QAAI,OAAO,UAAU,UAAa,CAAC,MAAM,OAAO,KAAK,EAAG,KAAI,GAAG,IAAI,UAAU,4BAA4B;AACzG,UAAM,aAAa,aAAa,OAAO,aAAa,QAAQ,OAAO;AACnE,QAAI,OAAO,YAAY,WAAc,CAAC,MAAM,OAAO,OAAO,KAAK,OAAO,WAAW,KAAK,OAAO,UAAU,aAAa;AAClH,UAAI,GAAG,IAAI,YAAY,sBAAsB,aAAa,WAAW,QAAQ,CAAC,IAAI,oBAAoB,OAAO,aAAa,KAAK,EAAE;AAAA,IACnI;AACA,QAAI,OAAO,cAAc,WAAc,CAAC,MAAM,OAAO,SAAS,KAAK,OAAO,YAAY,KAAK,OAAO,YAAY,IAAI;AAChH,UAAI,GAAG,IAAI,cAAc,cAAc;AAAA,IACzC;AAAA,EACF,WAAW,OAAO,SAAS,QAAQ;AACjC,eAAW;AACX,QAAI,CAAC,QAAQ,OAAO,KAAK,KAAK,OAAO,MAAM,CAAC,IAAI,EAAG,KAAI,GAAG,IAAI,UAAU,kDAAkD;AAAA,aACjH,OAAO,MAAM,CAAC,IAAI,OAAO,aAAc,KAAI,GAAG,IAAI,UAAU,0BAA0B,OAAO,YAAY,kBAAkB;AACpI,QAAI,OAAO,WAAW,QAAW;AAC/B,UAAI,CAAC,MAAM,OAAO,MAAM,KAAK,CAAC,MAAM,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,OAAO,OAAO,CAAC,GAAG;AAC/E,YAAI,GAAG,IAAI,WAAW,kCAAkC;AAAA,MAC1D,OAAO;AACL,YAAI,OAAO,OAAO,IAAI,KAAK,OAAO,OAAO,IAAI,EAAG,KAAI,GAAG,IAAI,aAAa,cAAc;AACtF,YAAI,OAAO,OAAO,IAAI,KAAK,OAAO,OAAO,IAAI,EAAG,KAAI,GAAG,IAAI,aAAa,cAAc;AAAA,MACxF;AAAA,IACF;AAAA,EACF,WAAW,OAAO,SAAS,QAAQ;AACjC,eAAW;AACX,QAAI,CAAC,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,SAAS,OAAO,iBAAiB,OAAO,OAAO,SAAS,OAAO,eAAe;AAC/H,UAAI,GAAG,IAAI,WAAW,uBAAuB,OAAO,aAAa,KAAK,OAAO,aAAa,SAAS;AAAA,IACrG,OAAO;AACL,aAAO,OAAO,QAAQ,CAAC,GAAY,OAAe;AAChD,YAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,EAAE,IAAI,KAAK,EAAE,IAAI,KAAK,EAAE,IAAI,GAAG;AACvF,cAAI,GAAG,IAAI,WAAW,EAAE,KAAK,kCAAkC;AAAA,QACjE;AAAA,MACF,CAAC;AAAA,IACH;AACA,QAAI,CAAC,MAAM,OAAO,QAAQ,KAAK,OAAO,WAAW,OAAO,iBAAiB;AACvE,UAAI,GAAG,IAAI,aAAa,cAAc,OAAO,eAAe,KAAK;AAAA,IACnE;AACA,QAAI,OAAO,UAAU,UAAa,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU;AACxF,UAAI,GAAG,IAAI,UAAU,6BAA6B;AAAA,IACpD;AACA,QAAI,OAAO,WAAW,UAAa,OAAO,OAAO,WAAW,UAAW,KAAI,GAAG,IAAI,WAAW,mBAAmB;AAChH,UAAM,aAAa,aAAa,OAAO,aAAa,QAAQ,OAAO;AACnE,QAAI,OAAO,YAAY,WAAc,CAAC,MAAM,OAAO,OAAO,KAAK,OAAO,WAAW,KAAK,OAAO,UAAU,aAAa;AAClH,UAAI,GAAG,IAAI,YAAY,sBAAsB,aAAa,WAAW,QAAQ,CAAC,IAAI,oBAAoB,OAAO,aAAa,KAAK,EAAE;AAAA,IACnI;AAAA,EACF,OAAO;AACL,QAAI,GAAG,IAAI,SAAS,uEAAuE;AAC3F;AAAA,EACF;AAEA,aAAW,KAAK,YAAY,QAAQ,QAAQ,GAAG;AAC7C,SAAK,GAAG,IAAI,IAAI,CAAC,IAAI,oBAAoB,4BAA4B,CAAC,0BAAqB;AAAA,EAC7F;AACF;AAEA,IAAM,SAAS,CAAC,GAAY,MAAM,MAAe,MAAM,QAAQ,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,EAAE,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,OAAO,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK;AAGhK,IAAM,iBAAiB;AAGvB,SAAS,kBAAkB,OAAgC,MAAc,KAAqC,MAAoB;AAChI,MAAI,OAAO,MAAM,SAAS,YAAY,MAAM,KAAK,WAAW,KAAK,MAAM,KAAK,SAAS,OAAO;AAC1F,QAAI,GAAG,IAAI,SAAS,qEAAqE;AAAA,EAC3F,OAAO;AACL,UAAM,OAAO,YAAY,MAAM,MAAO,MAAM,YAAyC,MAAM;AAC3F,UAAM,SAAS,MAAM,SAAS;AAC9B,QAAI,KAAK,MAAO,KAAI,GAAG,IAAI,SAAS,sBAAsB,KAAK,KAAK,EAAE;AAAA,aAC7D,UAAU,KAAK,OAAO,SAAS,EAAG,KAAI,GAAG,IAAI,SAAS,wFAAwF;AAAA,aAC9I,CAAC,UAAU,KAAK,MAAM,WAAW,EAAG,KAAI,GAAG,IAAI,SAAS,yCAAyC;AAAA,aACjG,KAAK,OAAO,SAAS,gBAAiB,KAAI,GAAG,IAAI,SAAS,eAAe,KAAK,OAAO,MAAM,oBAAoB,eAAe,EAAE;AAAA,aAChI,CAAC,GAAG,KAAK,QAAQ,GAAG,KAAK,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,UAAU,KAAK,IAAI,CAAC,IAAI,MAAM,EAAG,KAAI,GAAG,IAAI,SAAS,uDAAuD;AAAA,EAC/M;AACA,MAAI,MAAM,SAAS,UAAa,OAAO,MAAM,SAAS,UAAW,KAAI,GAAG,IAAI,SAAS,mBAAmB;AACxG,MAAI,MAAM,SAAS,SAAS,MAAM,WAAW,OAAW,KAAI,GAAG,IAAI,SAAS,4CAA4C;AACxH,MAAI,MAAM,aAAa,OAAW,sBAAqB,MAAM,UAAU,GAAG,IAAI,aAAa,GAAG;AAC9F,MAAI,MAAM,WAAW,OAAW,oBAAmB,MAAM,QAAQ,GAAG,IAAI,WAAW,GAAG;AACtF,MAAI,MAAM,aAAa,UAAa,CAAC,CAAC,QAAQ,WAAW,SAAS,EAAE,SAAS,MAAM,QAAkB,EAAG,KAAI,GAAG,IAAI,aAAa,wCAAwC;AACxK,OAAK;AACP;AAGA,SAAS,qBAAqB,GAAY,MAAc,KAA2C;AACjG,MAAI,CAAC,MAAM,CAAC,EAAG,QAAO,IAAI,MAAM,0FAA0F;AAC1H,MAAI,EAAE,SAAS,UAAU;AACvB,QAAI,CAAC,OAAO,EAAE,IAAI,EAAG,KAAI,GAAG,IAAI,SAAS,gDAAgD;AACzF,QAAI,CAAC,OAAO,EAAE,EAAE,EAAG,KAAI,GAAG,IAAI,OAAO,gDAAgD;AAAA,EACvF,WAAW,EAAE,SAAS,UAAU;AAC9B,QAAI,CAAC,OAAO,EAAE,MAAM,EAAG,KAAI,GAAG,IAAI,WAAW,gDAAgD;AAC7F,QAAI,CAAC,MAAM,EAAE,MAAM,KAAK,EAAE,UAAU,KAAK,EAAE,SAAS,EAAG,KAAI,GAAG,IAAI,WAAW,uCAAuC;AACpH,QAAI,EAAE,UAAU,UAAa,CAAC,OAAO,EAAE,KAAK,EAAG,KAAI,GAAG,IAAI,UAAU,gDAAgD;AAAA,EACtH,OAAO;AACL,WAAO,IAAI,GAAG,IAAI,SAAS,6BAA6B;AAAA,EAC1D;AACA,MAAI,EAAE,UAAU,UAAa,EAAE,UAAU,SAAS,EAAE,UAAU,OAAQ,KAAI,GAAG,IAAI,UAAU,sFAAsF;AACjL,MAAI,CAAC,MAAM,QAAQ,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,KAAK,EAAE,MAAM,SAAS,EAAG,QAAO,IAAI,GAAG,IAAI,UAAU,oBAAoB;AACzH,MAAI,OAAO;AACX,IAAE,MAAM,QAAQ,CAAC,IAAa,MAAc;AAC1C,QAAI,CAAC,MAAM,EAAE,EAAG,QAAO,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,iCAAiC;AACnF,QAAI,CAAC,MAAM,GAAG,EAAE,KAAK,GAAG,KAAK,KAAK,GAAG,KAAK,KAAK,GAAG,KAAK,KAAM,KAAI,GAAG,IAAI,UAAU,CAAC,QAAQ,8BAA8B;AAAA,QACpH,QAAO,GAAG;AACf,UAAM,GAAG,OAAO,GAAG,IAAI,UAAU,CAAC,WAAW,GAAG;AAChD,QAAI,GAAG,YAAY,WAAc,CAAC,MAAM,GAAG,OAAO,KAAK,GAAG,UAAU,KAAK,GAAG,UAAU,GAAI,KAAI,GAAG,IAAI,UAAU,CAAC,aAAa,cAAc;AAAA,EAC7I,CAAC;AACH;AAGA,SAAS,mBAAmB,IAAa,MAAc,KAA2C;AAChG,MAAI,CAAC,MAAM,EAAE,EAAG,QAAO,IAAI,MAAM,iDAAiD;AAClF,QAAM,GAAG,OAAO,GAAG,IAAI,UAAU,GAAG;AACpC,MAAI,CAAC,MAAM,GAAG,KAAK,KAAK,GAAG,SAAS,KAAK,GAAG,QAAQ,IAAK,KAAI,GAAG,IAAI,UAAU,gFAAiF;AAC/J,MAAI,GAAG,YAAY,WAAc,CAAC,MAAM,GAAG,OAAO,KAAK,GAAG,UAAU,KAAK,GAAG,UAAU,GAAI,KAAI,GAAG,IAAI,YAAY,cAAc;AAC/H,MAAI,GAAG,SAAS,UAAa,CAAC,CAAC,SAAS,SAAS,OAAO,EAAE,SAAS,GAAG,IAAc,EAAG,KAAI,GAAG,IAAI,SAAS,qCAAqC;AAChJ,MAAI,GAAG,QAAQ,UAAa,CAAC,CAAC,SAAS,QAAQ,QAAQ,EAAE,SAAS,GAAG,GAAa,EAAG,KAAI,GAAG,IAAI,QAAQ,qCAAqC;AAC/I;AAGA,SAAS,oBAAoB,QAAiB,MAAc,KAAa,KAA2C;AAClH,MAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,OAAO,OAAO,SAAS,OAAO,gBAAgB;AAC1F,WAAO,IAAI,MAAM,WAAW,GAAG,KAAK,OAAO,cAAc,2CAA2C;AAAA,EACtG;AACA,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,KAAc,OAAO,CAAC;AAC5B,QAAI,CAAC,MAAM,QAAQ,EAAE,KAAK,GAAG,WAAW,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,KAAK,IAAI,GAAG,CAAC,CAAC,IAAI,KAAK,KAAK,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG;AACzH,UAAI,GAAG,IAAI,IAAI,CAAC,KAAK,sDAAsD;AAAA,IAC7E;AAAA,EACF;AACF;AAEA,SAAS,aAAaC,OAAe,MAAc,KAAqC,MAAoB;AAC1G,MAAIA,UAAS,OAAW;AACxB,MAAI,CAAC,MAAMA,KAAI,EAAG,QAAO,IAAI,MAAM,uDAAuD;AAC1F,MAAIA,MAAK,SAAS,YAAYA,MAAK,SAAS,UAAW,KAAI,GAAG,IAAI,SAAS,8BAA8B;AACzG,MAAI,CAAC,MAAMA,MAAK,GAAG,KAAKA,MAAK,MAAM,OAAO,cAAcA,MAAK,MAAM,OAAO,YAAY;AACpF,QAAI,GAAG,IAAI,QAAQ,WAAW,OAAO,UAAU,KAAK,OAAO,UAAU,KAAK;AAAA,EAC5E;AACA,aAAW,KAAK,YAAYA,OAAM,oBAAI,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC,GAAG;AAC3D,SAAK,GAAG,IAAI,IAAI,CAAC,IAAI,oBAAoB,0BAA0B,CAAC,0BAAqB;AAAA,EAC3F;AACF;AAGO,SAAS,gBAAgB,MAA0B;AACxD,QAAM,IAAI,aAAa,IAAI;AAC3B,MAAI,CAAC,EAAE,OAAO;AACZ,UAAM,IAAI,MAAM;AAAA,EAAwB,EAAE,OAAO,IAAI,CAAC,MAAM,KAAK,EAAE,QAAQ,QAAQ,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EACnH;AACA,SAAO;AACT;AAOO,SAAS,iBAAiB,KAAgC;AAE/D,MAAI,MAAM,GAAG,KAAK,MAAM,QAAQ,IAAI,QAAQ,GAAG;AAC7C,eAAW,OAAO,IAAI,UAAU;AAC9B,UAAI,MAAM,GAAG,KAAK,MAAO,IAAgC,KAAK,GAAG;AAC/D,wBAAiB,IAAgC,KAAK;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACA,MAAI,MAAM,GAAG,KAAK,MAAM,IAAI,GAAG,EAAG,iBAAgB,IAAI,GAAG;AACzD,QAAM,SAAsB,CAAC;AAC7B,QAAM,WAA0B,CAAC;AACjC,QAAM,MAAM,CAAC,MAAc,YAA0B,KAAK,OAAO,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEvF,MAAI,CAAC,MAAM,GAAG,EAAG,QAAO,EAAE,OAAO,OAAO,QAAQ,CAAC,EAAE,MAAM,IAAI,SAAS,6BAA6B,CAAC,GAAG,UAAU,CAAC,EAAE;AAEpH,MAAI,IAAI,WAAW,gBAAiB,KAAI,UAAU,yBAAyB;AAC3E,MAAI,IAAI,kBAAkB,eAAgB,KAAI,iBAAiB,WAAW,cAAc,EAAE;AAC1F,MAAI,CAAC,MAAM,IAAI,EAAE,KAAK,IAAI,GAAG,KAAK,MAAM,GAAI,KAAI,MAAM,4BAA4B;AAClF,MAAI,CAAC,MAAM,IAAI,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,GAAI,KAAI,SAAS,4BAA4B;AAC3F,MAAI,IAAI,SAAS,UAAa,CAAC,MAAM,IAAI,IAAI,EAAG,KAAI,QAAQ,kBAAkB;AAC9E,MAAI,OAAO,IAAI,SAAS,UAAW,KAAI,QAAQ,mBAAmB;AAClE,MAAI,IAAI,SAAS,UAAa,IAAI,SAAS,WAAW,IAAI,SAAS,QAAS,KAAI,QAAQ,2BAA2B;AACnH,MAAI,IAAI,cAAc,UAAa,OAAO,IAAI,cAAc,UAAW,KAAI,aAAa,mBAAmB;AAC3G,MAAI,IAAI,WAAW,OAAW,gBAAe,IAAI,QAAQ,UAAU,KAAK,CAAC,GAAG,MAAM,YAAY,KAAK,SAAS,KAAK,EAAE,MAAM,GAAG,MAAM,QAAQ,CAAC,CAAC;AAE5I,MAAI,CAAC,MAAM,QAAQ,IAAI,QAAQ,KAAK,IAAI,SAAS,WAAW,GAAG;AAC7D,QAAI,YAAY,2BAA2B;AAC3C,WAAO,EAAE,OAAO,OAAO,QAAQ,SAAS;AAAA,EAC1C;AAEA,MAAI,IAAI,SAAS,SAAS,OAAO,aAAa;AAC5C,QAAI,YAAY,WAAW,OAAO,WAAW,WAAW;AAAA,EAC1D;AAEA,QAAM,OAAO,oBAAI,IAAY;AAC7B,MAAI,kBAAkB;AAEtB,WAAS,IAAI,GAAG,IAAI,IAAI,SAAS,QAAQ,KAAK;AAC5C,UAAM,IAAI,IAAI,SAAS,CAAC;AACxB,UAAM,IAAI,YAAY,CAAC;AACvB,QAAI,CAAC,MAAM,CAAC,GAAG;AAAE,UAAI,GAAG,mBAAmB;AAAG;AAAA,IAAU;AAExD,QAAI,CAAC,MAAM,EAAE,GAAG,KAAK,EAAE,IAAI,KAAK,MAAM,IAAI;AACxC,UAAI,GAAG,CAAC,QAAQ,4BAA4B;AAAA,IAC9C,WAAW,KAAK,IAAI,EAAE,GAAa,GAAG;AACpC,UAAI,GAAG,CAAC,QAAQ,kBAAkB,EAAE,GAAG,GAAG;AAAA,IAC5C,OAAO;AACL,WAAK,IAAI,EAAE,GAAa;AAAA,IAC1B;AAEA,QAAI,EAAE,aAAa,QAAW;AAC5B,UAAI,iBAAiB;AACnB,YAAI,GAAG,CAAC,aAAa,gEAAgE;AAAA,MACvF;AACA,UAAI,CAAC,MAAM,EAAE,QAAQ,KAAK,EAAE,WAAW,OAAO,oBAAoB;AAChE,YAAI,GAAG,CAAC,aAAa,cAAc,OAAO,kBAAkB,KAAK;AAAA,MACnE;AAAA,IACF,OAAO;AACL,UAAI,IAAI,IAAI,SAAS,SAAS,GAAG;AAC/B,YAAI,GAAG,CAAC,aAAa,0CAA0C;AAAA,MACjE;AACA,wBAAkB;AAAA,IACpB;AAEA,QAAI,EAAE,YAAY,UAAa,CAAC,CAAC,QAAQ,SAAS,QAAQ,EAAE,SAAS,EAAE,OAAiB,GAAG;AACzF,UAAI,GAAG,CAAC,YAAY,qCAAqC;AAAA,IAC3D;AAEA,QAAI,EAAE,eAAe,QAAW;AAC9B,UAAI,CAAC,MAAM,EAAE,UAAU,GAAG;AACxB,YAAI,GAAG,CAAC,eAAe,mBAAmB;AAAA,MAC5C,WAAW,EAAE,WAAW,SAAS,WAAW,EAAE,WAAW,SAAS,QAAQ;AACxE,YAAI,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,EAAE,WAAW,MAAM,OAAO,oBAAoB,EAAE,WAAW,MAAM,OAAO,kBAAkB;AACxH,cAAI,GAAG,CAAC,mBAAmB,4BAA4B,OAAO,gBAAgB,QAAQ,OAAO,gBAAgB,EAAE;AAAA,QACjH;AAAA,MACF,WAAW,EAAE,WAAW,SAAS,OAAO;AACtC,YAAI,GAAG,CAAC,oBAAoB,kCAAkC;AAAA,MAChE;AACA,UAAI,MAAM,EAAE,UAAU,KAAK,EAAE,WAAW,SAAS,QAAW;AAC1D,YAAI,EAAE,WAAW,SAAS,SAAS;AACjC,cAAI,GAAG,CAAC,oBAAoB,8EAA8E;AAAA,QAC5G,WAAW,EAAE,WAAW,SAAS,UAAU,EAAE,WAAW,SAAS,eAAe,EAAE,WAAW,SAAS,OAAO;AAC3G,cAAI,GAAG,CAAC,oBAAoB,sCAAsC;AAAA,QACpE;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,EAAE,KAAK,GAAG;AAClB,YAAM,cAAc,aAAa,EAAE,KAAK;AACxC,iBAAW,KAAK,YAAY,OAAQ,QAAO,KAAK,EAAE,MAAM,GAAG,CAAC,UAAU,EAAE,IAAI,IAAI,SAAS,EAAE,QAAQ,CAAC;AACpG,UAAI,YAAY,UAAU;AACxB,mBAAW,KAAK,YAAY,SAAU,UAAS,KAAK,EAAE,MAAM,GAAG,CAAC,UAAU,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,SAAS,EAAE,QAAQ,CAAC;AAAA,MACxH;AAAA,IACF,OAAO;AACL,UAAI,GAAG,CAAC,UAAU,kCAAkC;AAAA,IACtD;AAAA,EACF;AAEA,MAAI,IAAI,SAAS,QAAQ,iBAAiB;AACxC,QAAI,QAAQ,qDAAqD;AAAA,EACnE;AAGA,MAAI,IAAI,QAAQ,QAAW;AACzB,QAAI,CAAC,MAAM,IAAI,GAAG,GAAG;AACnB,UAAI,OAAO,4BAA4B;AAAA,IACzC,OAAO;AACL,YAAM,YAAY,aAAa,IAAI,GAAG;AACtC,iBAAW,KAAK,UAAU,OAAQ,QAAO,KAAK,EAAE,MAAM,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,QAAQ,CAAC;AAC3F,iBAAW,KAAK,UAAU,YAAY,CAAC,EAAG,UAAS,KAAK,EAAE,MAAM,OAAO,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,SAAS,EAAE,QAAQ,CAAC;AACnH,UAAI,UAAU,OAAO;AACnB,cAAM,cAAc,CAAC,SACnB,MAAM,IAAI,KAAK,MAAM,QAAQ,KAAK,MAAM,IACpC,KAAK,OAAO,OAAe,CAAC,GAAG,MAAM,KAAK,MAAM,CAAC,KAAK,MAAM,EAAE,KAAK,IAAI,EAAE,QAAQ,IAAI,CAAC,IACtF;AACN,cAAM,WAAW,YAAY,IAAI,GAAG;AACpC,cAAM,UAAU,IAAI,SAAS,OAAe,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,MAAM,CAAC,IAAI,YAAY,EAAE,KAAK,IAAI,CAAC,GAAG,CAAC;AACzG,YAAI,WAAW,UAAU,OAAO,UAAU;AACxC,cAAI,OAAO,gBAAgB,QAAQ,sBAAsB,OAAO,MAAM,WAAW,OAAO,gBAAgB,OAAO,QAAQ,6BAA6B;AAAA,QACtJ;AAEA,YAAI,SAAS,QAAQ,CAAC,GAAG,MAAM;AAC7B,cAAI,MAAM,CAAC,KAAK,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,QAAW;AAClE,qBAAS,KAAK;AAAA,cACZ,MAAM,YAAY,CAAC;AAAA,cACnB,MAAM;AAAA,cACN,SAAS,WAAW,CAAC;AAAA,YACvB,CAAC;AAAA,UACH;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,WAAW,KAAK,MAAM,QAAQ,IAAI,QAAQ,GAAG;AACtD,aAAS,IAAI,GAAG,IAAI,IAAI,SAAS,QAAQ,KAAK;AAC5C,YAAM,IAAI,IAAI,SAAS,CAAC;AACxB,UAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK,EAAE,WAAW,SAAS,QAAS;AACxE,YAAM,OAAO,IAAI,SAAS,IAAI,CAAC;AAC/B,UAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE,KAAK,KAAK,CAAC,MAAM,KAAK,KAAK,EAAG;AACpE,YAAM,OAAO,oBAAoB,EAAE,KAA6B;AAChE,YAAM,OAAO,oBAAqB,KAAiC,KAA6B;AAChG,UAAI,SAAS,MAAM;AACjB,iBAAS,KAAK;AAAA,UACZ,MAAM,YAAY,CAAC;AAAA,UACnB,MAAM;AAAA,UACN,SAAS,YAAY,CAAC,SAAI,IAAI,CAAC;AAAA,QACjC,CAAC;AAAA,MACH,WAAW,EAAE,MAAM,aAAa,UAAc,KAAsE,MAAM,aAAa,UAClI,sBAAsB,EAAE,OAAgC,KAAiC,OAA+B,EAAE,eAAe,EAAE,WAAW,SAAS,eAAe,EAAE,WAAW,SAAS,MAAM,CAAC,GAAG;AAKjN,iBAAS,KAAK;AAAA,UACZ,MAAM,YAAY,CAAC;AAAA,UACnB,MAAM;AAAA,UACN,SAAS,YAAY,CAAC,SAAI,IAAI,CAAC;AAAA,QACjC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,WAAW,KAAK,IAAI,cAAc,MAAM;AACjD,UAAM,KAAK;AACX,UAAM,OAAO,GAAG,SAAS,SAAS;AAClC,UAAM,SAAS,GAAG,SAAS,IAAI,GAAG;AAClC,QAAI,MAAqB;AACzB,QAAI,GAAG,SAAS,KAAM,OAAM;AAAA,aACnB,OAAO,EAAG,OAAM;AAAA,aAChB,QAAQ,SAAS,QAAS,OAAM;AAAA,aAChC,oBAAoB,GAAG,SAAS,IAAI,EAAG,KAAK,MAAM,oBAAoB,GAAG,SAAS,CAAC,EAAG,KAAK,EAAG,OAAM,WAAW,IAAI;AAAA,aACnH,eAAe,IAAI,IAAI,MAAM,EAAG,OAAM,2CAA2C,eAAe,IAAI,IAAI,CAAC;AAClH,QAAI,OAAO,CAAC,aAAa,EAAE,GAAG;AAC5B,eAAS,KAAK,EAAE,MAAM,aAAa,MAAM,uBAAuB,SAAS,4BAA4B,OAAO,uBAAuB,+BAA0B,CAAC;AAAA,IAChK;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,OAAO,WAAW,GAAG,QAAQ,SAAS;AACxD;AAEO,SAAS,oBAAoB,KAA4B;AAC9D,QAAM,IAAI,iBAAiB,GAAG;AAC9B,MAAI,CAAC,EAAE,OAAO;AACZ,UAAM,IAAI,MAAM;AAAA,EAAsB,EAAE,OAAO,IAAI,CAAC,MAAM,KAAK,EAAE,QAAQ,QAAQ,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EACjH;AACA,SAAO;AACT;;;ACr/CO,SAAS,aAAa,MAAiB,GAAW,GAAkD;AACzG,QAAM,QAAQ,KAAK,UAAU,OAAO,IAAI,KAAK,IAAI,GAAG,CAAC;AACrD,QAAM,QAAQ,KAAK,qBAAqB,OAAO;AAC/C,MAAI,aAAa,QAAQ,IAAI,KAAK,IAAI,GAAG,CAAC,IAAI,QAAQ;AACtD,MAAI,aAAa,GAAG;AAClB,UAAM,WAAW,KAAK,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,KAAK,MAAM,EAAE,QAAQ,UAAU,GAAG,CAAC;AACrF,QAAI,WAAW,OAAO,SAAU,eAAc,OAAO,WAAW;AAAA,EAClE;AACA,SAAO,EAAE,OAAO,WAAW;AAC7B;AAGO,IAAM,YAAY;AAElB,IAAM,iBAAiB;AAmFvB,SAAS,eAAe,QAA4B;AACzD,MAAI,OAAO,SAAS,QAAS,QAAO,OAAO,OAAO;AAClD,MAAI,OAAO,SAAS,OAAQ,QAAO,OAAO,QAAQ;AAClD,SAAO;AACT;AAEA,IAAM,UAAU,CAAC,GAAG,KAAK,IAAI;AAC7B,IAAM,aAAsC;AAAA,EAC1C,CAAC,KAAM,IAAK;AAAA,EACZ,CAAC,KAAM,GAAI;AAAA,EACX,CAAC,MAAM,GAAI;AACb;AAGA,SAAS,QAAQ,KAAU,KAAwB;AACjD,QAAM,MAAiB,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,EAAE;AAC1E,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAI,GAAG,KAAK,MAAM,QAAQ,CAAC,IAAK,IAAI,MAAM,KAAK,GAAG,CAAC;AACnD,QAAI,GAAG,KAAM,IAAI,KAAK,KAAM,IAAI,MAAM,WAAW,CAAC,EAAG,CAAC,GAAG,WAAW,CAAC,EAAG,CAAC,CAAC,CAAC;AAC3E,QAAI,IAAI,KAAK,IAAI,MAAM,GAAG,KAAK,KAAK,CAAC,CAAC;AAAA,EACxC;AACA,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAI,GAAG,KAAK,MAAM,QAAQ,CAAC,IAAK,IAAI,MAAM,KAAK,GAAG,CAAC;AACnD,QAAI,GAAG,KAAM,IAAI,KAAK,KAAM,IAAI,MAAM,WAAW,CAAC,EAAG,CAAC,GAAG,WAAW,CAAC,EAAG,CAAC,CAAC,CAAC;AAC3E,QAAI,IAAI,KAAK,IAAI,MAAM,GAAG,KAAK,KAAK,CAAC,CAAC;AAAA,EACxC;AACA,SAAO;AACT;AAEA,IAAM,SAAS;AAWf,SAAS,WACP,MACA,GACA,GAC6B;AAC7B,QAAM,QAAQ,KAAK;AACnB,QAAM,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,UAAU,CAAC,CAAC;AACxD,QAAM,aAAe,IAAI,OAAO,SAAU,IAAK;AAC/C,QAAM,OAAQ,IAAI,KAAK,IAAI,GAAG,CAAC,IAAK;AACpC,QAAM,UAAU,QAAQ,IAAI,UAAU,YAAY,UAAU,QAAQ,SAAS;AAC7E,SAAO;AAAA,IACL;AAAA,IACA,MAAM,KAAK,IAAI,KAAK,MAAM,KAAK;AAAA,IAC/B;AAAA,IACA,UAAU,KAAK,OAAO,CAAC,KAAK;AAAA,IAC5B,QAAQ,KAAK,OAAO,CAAC,KAAK;AAAA,EAC5B;AACF;AAGA,SAAS,cAAc,GAAW,SAA2B;AAC3D,QAAM,QAAQ,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC;AAC/C,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,WAAO,QAAQ,CAAC,IAAK;AACrB,QAAI,IAAI,IAAK,QAAO;AAAA,EACtB;AACA,SAAO,QAAQ,SAAS;AAC1B;AAKO,SAAS,cAAc,OAAkB,KAAU,GAAW,GAAW,QAAQ,GAAG,aAAa,GAAa;AAUnH,QAAM,iBAAiB,eAAe,KAAK,MAAM,WAAW,SACxD,MAAM,QACN,KAAK,IAAI,GAAG,KAAK;AAAA,IACf,KAAK,MAAM,MAAM,QAAQ,UAAU;AAAA,IACnC,MAAM,QAAQ,OAAO,oBAAoB,OAAO;AAAA,EAClD,CAAC;AAGL,QAAM,cAAc,UAAU,IAC1B,CAAC,IAAI,EAAE,IACP,CAAC,KAAK,OAAO,mBAAmB,KAAK,OAAO,iBAAiB;AACjE,QAAM,CAAC,MAAM,IAAI,IAAI,MAAM,QAAQ;AACnC,QAAM,WAAW,eAAe,MAAM,MAAM;AAC5C,QAAM,SAAS,MAAM;AACrB,QAAM,eAAe,eAAe,MAAM,IAAI,OAAO,SAAS;AAC9D,QAAM,eAAe,eAAe,MAAM,IAAI,OAAO,eAAe;AACpE,QAAM,YAAY,cAAc,UAAU;AAC1C,QAAM,QAAgC,OAAO,SAAS,WAAW,OAAO,SAAS,SAAU,OAAO,QAAQ;AAI1G,QAAM,QAAQ,MAAM;AACpB,MAAI,YAA8B;AAClC,MAAI,YAAY;AAChB,MAAI,MAAM,SAAS,UAAU;AAC3B,iBAAa,MAAM,YAAY,UAAU,IAAI,KAAK,SAAS;AAC3D,gBAAY,QAAQ,KAAK,SAAS;AAAA,EACpC;AACA,MAAI,UAAkD;AACtD,MAAI,MAAM,SAAS,QAAQ;AACzB,cAAU,MAAM,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,GAAG,GAAG,EAAE,IAAI,EAAE,EAAE;AAAA,EAChE;AACA,QAAMC,QAAQ,MAAM,SAAS,WAAW,MAAM,SAAS,UAAU,MAAM,SAAS,WAAY,MAAM,OAAO;AACzG,QAAM,aAAa,MAAM,SAAU,MAAM,MAAM,SAAS,KAAK,IAAK,KAAK,KAAK,IAAI;AAGhF,QAAM,SAAS,MAAM;AAErB,QAAM,UAAU,QAAQ,SAAS,UAAU,QAAQ,SAAS;AAC5D,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,SAAS;AACb,MAAI,SAAS;AACb,MAAI,WAAW;AACf,MAAI,QAAQ,SAAS,UAAU,QAAQ,SAAS,SAAS;AACvD,UAAM,OAAO,UAAU,IAAI,OAAO,mBAAmB,OAAO;AAC5D,UAAM,IAAI,OAAO,OAAO;AACxB,YAAQ,OAAO,MAAM,WAAW,IAAI,EAAE,KAAK,QAAQ;AACnD,YAAQ,OAAO,MAAM,WAAW,IAAI,EAAE,KAAK,QAAQ;AACnD,eAAW,OAAO,SAAS,SAAS,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,OAAO,CAAC;AAC9E,UAAM,OAAO,KAAK,IAAI,GAAG,KAAK,KAAK,iBAAiB,QAAQ,CAAC;AAC7D,QAAI,MAAM,UAAU;AAClB,eAAS,MAAM,SAAS,IAAI;AAC5B,eAAS,MAAM,SAAS,IAAI;AAG5B,UAAI,MAAM,SAAS,GAAI,WAAU,MAAM,SAAS,KAAK;AACrD,UAAI,MAAM,SAAS,GAAI,WAAU,MAAM,SAAS,KAAK;AAAA,IACvD,OAAO;AACL,YAAM,CAAC,KAAK,GAAG,IAAI,MAAM,QAAQ,KAAK,CAAC,GAAG,CAAC;AAC3C,YAAM,CAAC,KAAK,GAAG,IAAI,MAAM,QAAQ,KAAK,CAAC,GAAG,CAAC;AAC3C,gBAAW,MAAM,OAAO,IAAK,KAAM,WAAW,KAAK,OAAQ;AAC3D,gBAAW,MAAM,OAAO,IAAK,KAAM,OAAO,KAAK,OAAQ;AAAA,IACzD;AAAA,EACF;AACA,MAAI,WAAW;AACf,MAAI,QAAQ;AACZ,MAAI,QAAQ;AACZ,MAAI,SAAS;AACb,MAAI,SAAS;AACb,MAAI,QAAQ,SAAS,QAAQ;AAC3B,UAAM,CAAC,KAAK,GAAG,IAAI,MAAM,QAAQ,KAAK,CAAC,GAAG,CAAC;AAC3C,UAAM,CAAC,KAAK,GAAG,IAAI,MAAM,QAAQ,KAAK,CAAC,GAAG,CAAC;AAC3C,UAAM,KAAK,KAAK,IAAI,IAAI,MAAM,OAAO,CAAC;AACtC,UAAM,KAAK,KAAK,IAAI,IAAI,MAAM,OAAO,CAAC;AACtC,eAAW,KAAK;AAAA,MACd,OAAO,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,kBAAkB,KAAK,GAAG,CAAC,CAAC;AAAA,MAC/E,OAAO;AAAA,IACT;AACA,UAAM,WAAW,KAAK,IAAI,GAAG,KAAK,KAAK,iBAAiB,QAAQ,CAAC;AACjE,YAAQ,KAAK;AACb,YAAQ,KAAK;AACb,aAAS,MAAM;AACf,aAAS,MAAM;AAAA,EACjB;AAEA,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,gBAAgB,KAAK;AACvC,UAAM,OACJ,OAAO,SAAS,cACZ,OAAO,WAAW,QAClB,OAAO,SAAS,YAAY,OAAO,SAAS,UAAU,OAAO,SAAS,YACpE,IAAI,MAAM,OAAO,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,IAAI,IAAI,QACpD,OAAO,SAAS,YAAY,OAAO,SAAS,WAC1C,IAAI,MAAM,OAAO,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,IAAI,QAChD,OAAO,SAAS,SACd,IAAI,MAAM,OAAO,MAAM,CAAC,GAAG,OAAO,MAAM,CAAC,CAAC,IAAI,QAC9C,OAAO,SAAS,QACd,OAAO,SAAS,QAChB,IAAI,MAAM,MAAM,IAAI,IAAI;AAEtC,UAAM,QAAQ,OAAO,SAAS,SAC1B,QAAQ,OAAO,SAAS,IAAI,MAAM,OAAO,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,IAAI,KACxE,OAAO,SAAS,QACd,OAAO,YAAY,QACnB;AAEN,QAAI,KAAK;AACT,QAAI,KAAK;AACT,QAAI,MAAM;AACV,QAAI,SAA2B;AAC/B,QAAI;AACJ,QAAI,YAAY;AAChB,QAAI,WAAW;AACf,QAAI,WAAW;AACf,UAAM,IAAI,MAAM;AAChB,QAAI,EAAE,SAAS,UAAU;AACvB,eAAS;AAAA,IACX,WAAW,EAAE,SAAS,SAAS;AAC7B,YAAM,IAAI,IAAI,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,IAAI;AAC9C,UAAI,SAAU,EAAE,SAAS,KAAK,KAAK,KAAM;AACzC,UAAI,EAAE,iBAAiB,IAAI,KAAK,IAAI,IAAK,SAAQ,KAAK,KAAK;AAC3D,WAAK,IAAI,KAAK,IAAI,KAAK;AACvB,WAAK,IAAI,KAAK,IAAI,KAAK;AACvB,aAAO,EAAE,OAAO,KAAK;AAAA,IACvB,WAAW,EAAE,SAAS,QAAQ;AAC5B,eAAS;AACT,WAAK,CAAC,IAAI,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,IAAI;AAC1C,aAAO,EAAE,QAAQ,KAAK;AAAA,IACxB,WAAW,EAAE,SAAS,UAAU;AAC9B,eAAS;AACT,YAAM,IAAI,IAAI,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,IAAI;AAC9C,YAAM,IAAI,IAAI,MAAM,GAAG,KAAK,KAAK,CAAC;AAClC,WAAK,IAAI,KAAK,IAAI,CAAC;AACnB,WAAK,IAAI,KAAK,IAAI,CAAC;AAAA,IACrB,WAAW,EAAE,SAAS,SAAS;AAC7B,eAAS;AACT,WAAK,IAAI,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAAA,IACvC,WAAW,EAAE,SAAS,UAAU;AAC9B,eAAS;AACT,YAAM,IAAI,IAAI,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,IAAI;AAC9C,YAAM,UAAU,EAAE,UAAU,SAAa,EAAE,QAAQ,KAAK,KAAM,MAAM,IAAI,MAAM,GAAG,KAAK,KAAK,CAAC;AAC5F,WAAK,IAAI,KAAK,IAAI,OAAO;AACzB,WAAK,IAAI,KAAK,IAAI,OAAO;AAAA,IAC3B,WAAW,EAAE,SAAS,QAAQ;AAC5B,eAAS;AACT,YAAM,KAAK,IAAI,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAC3C,YAAM,QAAQ,IAAI,MAAM,GAAG,KAAK,KAAK,CAAC;AACtC,YAAM,IAAI,IAAI,MAAM,MAAM,CAAC;AAC3B,mBAAa;AAAA,QACX,IAAI,KAAK,IAAI,KAAK,IAAI;AAAA,QACtB,IAAI,KAAK,IAAI,KAAK,IAAI;AAAA,QACtB,IAAI,IAAI,MAAM,WAAW,CAAC;AAAA,QAC1B;AAAA,QACA,KAAK,EAAE,QAAQ,KAAK,OAAO;AAAA,QAC3B,KAAK,EAAE,QAAQ,KAAK,OAAO;AAAA,MAC7B;AAAA,IACF,WAAW,EAAE,SAAS,QAAQ;AAC5B,eAAS;AACT,kBAAY,IAAI,KAAK;AACrB,UAAI,EAAE,SAAS;AACb,mBAAW,IAAI,MAAM,IAAI,CAAC,IAAI,EAAE,UAAU;AAC1C,mBAAW,IAAI,MAAM,IAAI,CAAC,IAAI,EAAE,UAAU;AAAA,MAC5C;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACJ,QAAI,MAAM,YAAY,MAAM,UAAU,GAAG;AACvC,WAAK,MAAM,SAAS,IAAI;AACxB,WAAK,MAAM,SAAS,IAAI;AACxB,UAAI,MAAM,SAAS,GAAI,OAAM,MAAM,SAAS,KAAK;AACjD,UAAI,MAAM,SAAS,GAAI,OAAM,MAAM,SAAS,KAAK;AAAA,IACnD,WAAW,QAAQ,SAAS,UAAU,QAAQ,SAAS,SAAS;AAG9D,UAAI,KAAK;AACT,UAAI,KAAK;AACT,WAAK,SAAU,IAAI,WAAY;AAC/B,WAAK,SAAS,KAAK,MAAM,IAAI,QAAQ,IAAI;AAAA,IAC3C,WAAW,QAAQ,SAAS,QAAQ;AAGlC,YAAM,MAAM,IAAI;AAChB,YAAM,MAAM,KAAK,MAAM,IAAI,QAAQ;AACnC,YAAM,IAAI,OAAO,UAAU;AAC3B,YAAM,KAAK,OAAO,MAAM,WAAW,IAAI,EAAE,KAAK;AAC9C,YAAM,KAAK,OAAO,MAAM,WAAW,IAAI,EAAE,KAAK;AAC9C,WAAK,UAAU,MAAM,OAAO,QAAQ,IAAI,MAAM,MAAM,GAAG,IAAI,KAAK;AAChE,WAAK,UAAU,MAAM,OAAO,QAAQ,IAAI,MAAM,MAAM,GAAG,IAAI,KAAK;AAAA,IAClE,OAAO;AAIL,YAAM,CAAC,KAAK,GAAG,IAAI,MAAM,QAAQ,KAAK,CAAC,GAAG,CAAC;AAC3C,YAAM,CAAC,KAAK,GAAG,IAAI,MAAM,QAAQ,KAAK,CAAC,GAAG,CAAC;AAC3C,WAAK,IAAI,MAAM,MAAM,GAAG,MAAM,CAAC;AAC/B,WAAK,IAAI,MAAM,MAAM,GAAG,MAAM,CAAC;AAAA,IACjC;AAEA,UAAM,cAAc,EAAE,SAAS,WAAW,EAAE,UAAU,WAAW,EAAE,SAAS,EAAE,OAAO,QAAQ;AAE7F,QAAI,KAAK;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA;AAAA;AAAA;AAAA,MAIA,aAAa,WAAW,IAAK,WAAW,IAAI,IAAI,GAAG,WAAW,CAAC,GAAG,IAAI,YAAY,IAAI,IAAI,GAAG,WAAW,CAAC,IAAK;AAAA,MAC9G,OAAO,IAAI,MAAM,GAAG,KAAK,KAAK,CAAC;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,KAAK;AAAA,MAClB,OAAO,MAAM,QAAQ,IAAI,MAAM,MAAM,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,CAAC,IAAI;AAAA,MACjE,UAAU,MAAM,OAAO,OAAO;AAAA,MAC9B,aAAa,MAAM,OAAO,UAAU;AAAA,MACpC,YAAY,MAAM,QAAQ,IAAI,MAAM,GAAG,KAAK,KAAK,CAAC,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,MAKtD,WACE,OAAO,MAAM,SAAS,WACjB,MAAM,OAAO,KAAK,KAAM,MACzB,MAAM,QAAQ,MAAM,IAAI,IACrB,IAAI,MAAM,MAAM,KAAK,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC,IAAI,KAAK,KAAM,MACtD;AAAA,MACR,WAAW,MAAM,OAAO,IAAI,MAAM,GAAG,KAAK,KAAK,CAAC,IAAI;AAAA,MACpD,SAAS,MAAM,MAAM,OAAO;AAAA,MAC5B,YAAY,MAAM,MAAM,UAAU;AAAA,MAClC,WAAW,MAAM,OAAO,IAAI,MAAM,GAAG,KAAK,KAAK,CAAC,IAAI;AAAA,MACpD,QAAQ,EAAE,SAAS,UAAU,IAAI,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,QAAQ;AAAA,MAC3E,SAAS,EAAE,SAAS,WAAW,CAAC,eAAgB,EAAE,QAAuC,KAAK,OAAO,IAAI;AAAA,MACzG,SAAS,EAAE,SAAS,WAAW,CAAC,eAAgB,EAAE,QAAuC,KAAK,OAAO,IAAI;AAAA;AAAA,MAEzG,YAAY,YAAY,IACnB,gBAAgB,aAAa,WAAW,YACrC,cAAc,IAAI,KAAK,GAAG,YAAY,IACtC,WACG,IAAI,IAAI,GAAG,YAAY,CAAC,GAAG,IAAI,aAChC,IAAI,IAAI,GAAG,YAAY,CAAC,IAC9B;AAAA,MACJ,aAAa,QAAQ,MAAM,SAAS;AAAA;AAAA,MAEpC,GAAI,UAAU,SAAY,EAAE,MAAM,IAAI,CAAC;AAAA,MACvC,GAAI,OAAO,SAAS,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC;AAAA,MAC/C,GAAI,UAAU,EAAE,SAAS,KAAc,IAAI,CAAC;AAAA,MAC5C,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,MACrC,GAAI,MAAM,SAAS,QAAQ,EAAE,cAAc,KAAc,IAAI,CAAC;AAAA,MAC9D,GAAI,EAAE,SAAS,WACX;AAAA,QACE,QAAQ;AAAA,UACN,KAAK,QAAQ,KAAK,SAAS;AAAA,UAC3B,QAAQ;AAAA,UACR,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,EAAE,aAAa,CAAC,CAAC;AAAA,UACpD,QAAQ,aAAa,QAAQ,CAAC,IAAK,QAAQ,CAAC,IAAK,QAAQ,CAAC,KAAM;AAAA,QAClE;AAAA,MACF,IACA,CAAC;AAAA,MACL,GAAI,aAAa,EAAE,MAAM,WAAW,IAAI,CAAC;AAAA,MACzC,GAAI,EAAE,SAAS,UAAU,UACrB;AAAA,QACE,MAAM;AAAA,UACJ,KAAK;AAAA,UACL,UAAU,EAAE;AAAA,UACZ,QAAQ,EAAE,WAAW;AAAA,UACrB,QAAQ,EAAE,UAAU;AAAA,UACpB,OAAO;AAAA,UACP,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF,IACA,CAAC;AAAA;AAAA;AAAA,MAGL,GAAIA,QAAO,EAAE,MAAM,EAAE,MAAMA,MAAK,MAAM,KAAKA,MAAK,IAAI,EAAE,IAAI,CAAC;AAAA;AAAA;AAAA,MAG3D,GAAI,OAAO,MAAM,WAAW,WACxB,EAAE,QAAS,MAAM,SAAS,KAAK,KAAM,IAAI,IACzC,MAAM,QAAQ,MAAM,MAAM,IACxB,EAAE,QAAS,IAAI,MAAM,MAAM,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC,IAAI,KAAK,KAAM,IAAI,IACxE,CAAC;AAAA,IACT,CAAC;AAED,QAAI,MAAM,OAAO;AAIf,YAAM,MAAM,IAAI,IAAI,SAAS,CAAC;AAC9B,UAAI,aAAa;AACjB,UAAI,YAAY;AAChB,UAAI,aAAa;AACjB,UAAI,YAAY,MAAM,MAAM,QAAQ;AAAA,IACtC;AACA,QAAI,MAAM,OAAO,MAAM;AAKrB,YAAM,KAAK,KAAK,IAAI,MAAM,MAAM,MAAM,KAAK,aAAa,KAAK;AAC7D,YAAM,OAAQ,MAAM,MAAM,KAAK,SAAS,KAAK,KAAK,KAAM;AACxD,UAAI,IAAI,SAAS,CAAC,EAAG,aAAa,cAAe,KAAK,KAAK,IAAI,GAAG,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,KAAM,KAAK,KAAK;AAAA,IAC9G;AAAA,EACF;AACA,MAAI,MAAM,MAAM;AAGd,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,KAAI,CAAC,EAAG,OAAO,WAAW,MAAM,MAAM,GAAG,IAAI,MAAM;AAAA,EAC1F;AACA,SAAO;AACT;AAGA,SAAS,MAAM,GAAW,GAAmB;AAC3C,QAAM,KAAK,EAAE;AACb,SAAO,KAAK,GAAG,KAAK,GAAG,MAAM,IAAI,MAAO,WAAW,CAAC;AACtD;AAEA,SAAS,WAAW,GAAmB;AACrC,QAAM,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AAClC,SAAO,IAAI,KAAK,IAAI,IAAI;AAC1B;AAGA,IAAM,cAAc;AAOb,SAAS,WAAW,GAAW,GAA0B;AAC9D,QAAM,KAAK,EAAE;AACb,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,UAAW,IAAI,GAAG,SAAS,GAAG,QAAS,GAAG,SAAS,GAAG;AAC5D,SAAO,QAAQ,GAAG,OAAO,QAAQ,GAAG,OAAO;AAC7C;AAGO,SAAS,aAAa,GAAmB;AAC9C,MAAI,IAAI,KAAK,KAAK,EAAG,QAAO;AAC5B,SAAO,IAAI,cAAc,WAAW,IAAI,WAAW,IAAI,IAAI,YAAY,IAAI,gBAAgB,IAAI,YAAY;AAC7G;AAGA,SAAS,UAAU,GAAW,GAAmB;AAC/C,SAAO,EAAE,YAAY,IAAI,EAAE,YAAY;AACzC;AAQA,SAAS,cAAc,GAAW,GAAmB;AACnD,MAAI,CAAC,EAAE,KAAM,QAAO,IAAI;AACxB,MAAI,KAAK;AACT,MAAI,EAAE,KAAM,QAAQ,IAAI,EAAE,KAAK,SAAS,EAAE,KAAK,QAAS,EAAE,KAAK,SAAS,EAAE,KAAK;AAC/E,QAAM,MAAM,EAAE,KAAK;AACnB,QAAM,IAAI,IAAI,KAAK,IAAI,CAAC,KAAK,GAAG;AAChC,UAAQ,EAAE,KAAK,SAAS,WAAW,MAAM,IAAI,KAAK,MAAM,KAAK;AAC/D;AAGO,SAAS,QAAQ,GAAW,GAAmB;AACpD,MAAI,IAAI,EAAE;AACV,MAAI,EAAE,SAAU,KAAI,EAAE,QAAQ,EAAE,WAAW,KAAK,IAAK,UAAU,GAAG,CAAC,IAAI,IAAI,KAAK,KAAM,EAAE,cAAc,EAAE,UAAU;AAClH,MAAI,EAAE,WAAW,QAAQ;AAGvB,UAAM,IAAI,MAAM,GAAG,CAAC;AACpB,SAAK,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC;AAAA,EAC7C;AACA,MAAI,EAAE,MAAM;AACV,UAAM,IAAI,WAAW,GAAG,CAAC;AACzB,QAAI,MAAM,OAAO,IAAI,IAAI,aAAa,CAAC;AAAA,EACzC;AACA,SAAO,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AACjC;AAGO,SAAS,OAAO,GAAW,GAAmB;AACnD,MAAI,IAAI,EAAE;AACV,MAAI,EAAE,QAAS,KAAI,EAAE,QAAQ,IAAI,EAAE,UAAU,KAAK,IAAK,UAAU,GAAG,CAAC,IAAI,IAAI,KAAK,KAAM,EAAE,aAAa,EAAE,SAAS;AAClH,MAAI,EAAE,WAAW,OAAQ,MAAK,KAAK,IAAI,IAAI,MAAM,GAAG,CAAC,GAAG,cAAc;AACtE,MAAI,EAAE,SAAS,EAAE,KAAK,aAAa,KAAK,EAAE,KAAK,WAAW,IAAI;AAC5D,UAAM,IAAI,WAAW,GAAG,CAAC;AACzB,QAAI,MAAM,KAAM,MAAK,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,KAAK,YAAY;AAAA,EAC7E;AACA,SAAO,IAAI,IAAI,IAAI;AACrB;AASO,SAAS,WAAW,GAAW,GAAmB;AACvD,QAAM,OAAO,EAAE,UAAU;AACzB,MAAI,CAAC,EAAE,UAAW,QAAO;AACzB,SAAO,OAAO,EAAE,YAAY,EAAE,aAAa,IAAI;AACjD;AAGO,SAAS,YAAY,MAAoE,GAAmB;AACjH,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,OAAO,KAAK,QAAQ;AAC1B,MAAI,IAAI;AACR,MAAI,KAAK,UAAU,QAAW;AAC5B,QAAI,IAAI,KAAK,MAAO,QAAO;AAC3B,QAAI,OAAO,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI;AAAA,EACxD;AACA,MAAI,KAAK,SAAS,UAAa,KAAK,KAAK,MAAM;AAC7C,SAAK,OAAO,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,QAAQ,IAAI,IAAI;AAAA,EAC5D;AACA,SAAO;AACT;AAEA,SAAS,KAAK,GAAW,KAAa,KAAqB;AACzD,QAAM,QAAQ,MAAM;AACpB,WAAW,IAAI,OAAO,QAAS,SAAS,QAAS;AACnD;AAEA,SAAS,QAAQ,GAAW,KAAa,KAAqB;AAC5D,QAAM,QAAQ,MAAM;AACpB,MAAI,SAAS,EAAG,QAAO;AACvB,QAAM,SAAS,IAAI;AACnB,QAAM,MAAO,IAAI,OAAO,SAAU,UAAU;AAC5C,SAAO,OAAO,IAAI,QAAQ,IAAI,SAAS;AACzC;AAEA,SAASC,YAAW,IAAY,IAAY,IAAY,IAAY,GAAmB;AACrF,QAAM,KAAK,IAAI;AACf,QAAM,KAAK,KAAK;AAChB,SAAO,OAAO,IAAI,MAAM,CAAC,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM,MAAM,CAAC,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM;AAChH;AAEA,SAAS,aAAa,GAAW,GAAqC;AACpE,QAAM,IAAI,EAAE;AACZ,QAAM,IAAI,EAAE,IAAI;AAChB,MAAI,KAAM,IAAI,EAAE,WAAY,EAAE,SAAS;AACvC,MAAI,IAAI,EAAG,MAAK;AAChB,MAAI,CAAC,EAAE,QAAQ;AAEb,UAAM,KAAK,IAAI;AACf,QAAI,KAAK,IAAI,KAAK,IAAI;AAAA,EACxB;AACA,QAAM,OAAO,EAAE,SAAS,IAAI,IAAI;AAChC,QAAM,IAAI,KAAK,IAAI,IAAI,MAAM,OAAO,IAAI;AACxC,QAAM,IAAI,KAAK,MAAM,CAAC;AACtB,QAAM,QAAQ,IAAI;AAClB,QAAM,KAAK,CAAC,MACV,EAAE,SAAS,EAAE,KAAM,IAAI,IAAK,KAAK,CAAC,IAAK,EAAE,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;AAC9E,QAAM,KAAK,GAAG,CAAC;AACf,QAAM,KAAK,GAAG,IAAI,CAAC;AACnB,MAAI,CAAC,EAAE,QAAQ;AACb,WAAO;AAAA,MACL,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,QAAQ,EAAE;AAAA,MACpC,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,QAAQ,EAAE;AAAA,IACtC;AAAA,EACF;AACA,QAAM,KAAK,GAAG,IAAI,CAAC;AACnB,QAAM,KAAK,GAAG,IAAI,CAAC;AACnB,SAAO;AAAA,IACL,GAAGA,YAAW,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,IAAI,EAAE;AAAA,IACjD,GAAGA,YAAW,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,IAAI,EAAE;AAAA,EACnD;AACF;AAGO,SAAS,WAAW,GAAW,GAAW,GAAW,GAAmB;AAC7E,MAAI,EAAE,WAAW,SAAU,QAAO,EAAE,GAAG,EAAE,IAAI,GAAG,EAAE,IAAI,MAAM,MAAM;AAClE,MAAI,EAAE,WAAW,SAAS;AACxB,UAAM,QAAQ,EAAE,QAAS,EAAE,KAAK,KAAK,KAAK,OAAQ,IAAI;AACtD,WAAO;AAAA,MACL,GAAG,EAAE,UAAU,EAAE,SAAS,KAAK,IAAI,KAAK;AAAA,MACxC,GAAG,EAAE,UAAU,EAAE,SAAS,KAAK,IAAI,KAAK;AAAA,MACxC,MAAM;AAAA,IACR;AAAA,EACF;AACA,MAAI,EAAE,WAAW,QAAQ;AACvB,UAAM,KAAK,EAAE;AACb,UAAM,QAAQ,IAAI,MAAM,GAAG,CAAC;AAC5B,UAAM,UAAU,KAAK,IAAI,GAAG,CAAC,IAAI;AACjC,WAAO;AAAA,MACL,GAAG,GAAG,KAAK,GAAG,KAAK,UAAU;AAAA,MAC7B,GAAG,GAAG,KAAK,GAAG,KAAK,UAAU;AAAA,MAC7B,MAAM;AAAA,IACR;AAAA,EACF;AACA,MAAI,EAAE,WAAW,QAAQ;AACvB,UAAM,MAAM,aAAa,GAAG,CAAC;AAC7B,WAAO,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,MAAM,MAAM;AAAA,EAC3C;AACA,QAAM,KAAK,cAAc,GAAG,CAAC;AAC7B,QAAM,IAAI,EAAE;AACZ,MAAI,EAAE,WAAW,UAAU;AACzB,WAAO;AAAA,MACL,GAAG,QAAQ,EAAE,KAAK,EAAE,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,CAAC;AAAA,MAC7C,GAAG,QAAQ,EAAE,KAAK,EAAE,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,CAAC;AAAA,MAC7C,MAAM;AAAA,IACR;AAAA,EACF;AACA,MAAI,EAAE,WAAW,QAAQ;AACvB,UAAMC,KAAI,EAAE,KAAK,EAAE,KAAK;AACxB,WAAO;AAAA,MACL,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,IAAI,MAAM,EAAE,KAAK,IAAI;AAAA,MACzD,GAAG,EAAE,eAAeA,KAAI,KAAKA,IAAG,CAAC,GAAG,IAAI,CAAC;AAAA,MACzC,MAAM;AAAA,IACR;AAAA,EACF;AACA,MAAI,EAAE,WAAW,UAAU;AACzB,UAAM,KAAK,EAAE;AACb,UAAM,IAAI,GAAG;AACb,QAAI,KAAK;AACT,QAAI,KAAK;AACT,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAI,IAAI,GAAG;AACT,eAAO,IAAI,KAAK,GAAG,IAAI,GAAG,CAAC,IAAK,KAAK,IAAI,GAAG,IAAI,GAAG,CAAC,IAAK,IAAI,GAAG,IAAI,IAAI,CAAC,CAAE;AAC3E,eAAO,IAAI,KAAK,GAAG,IAAI,GAAG,CAAC,IAAK,KAAK,IAAI,GAAG,IAAI,GAAG,CAAC,IAAK,IAAI,GAAG,IAAI,IAAI,CAAC,CAAE;AAAA,MAC7E;AACA,UAAI,IAAI,GAAG;AACT,cAAM,IAAI,GAAG,OAAO,GAAG,CAAC,IAAK,KAAK,IAAI,GAAG,OAAO,GAAG,CAAC,IAAK,IAAI,GAAG,OAAO,IAAI,CAAC,CAAE;AAC9E,cAAM,IAAI,GAAG,OAAO,GAAG,CAAC,IAAK,KAAK,IAAI,GAAG,OAAO,GAAG,CAAC,IAAK,IAAI,GAAG,OAAO,IAAI,CAAC,CAAE;AAAA,MAChF;AAAA,IACF;AACA,UAAM,SAAS,IAAI,GAAG;AACtB,UAAMC,KAAI,EAAE,KAAK,EAAE,KAAK,KAAK;AAC7B,UAAMD,KAAI,EAAE,KAAK,EAAE,KAAK,KAAK;AAC7B,WAAO;AAAA,MACL,GAAG,EAAE,eAAeC,KAAI,KAAKA,IAAG,CAAC,QAAQ,IAAI,MAAM;AAAA,MACnD,GAAG,EAAE,eAAeD,KAAI,KAAKA,IAAG,CAAC,QAAQ,IAAI,MAAM;AAAA,MACnD,MAAM,EAAE;AAAA,IACV;AAAA,EACF;AAEA,QAAM,OAAO,EAAE,KAAK,EAAE,KAAK;AAC3B,QAAM,IAAI,EAAE,eAAe,OAAO,KAAK,MAAM,CAAC,GAAG,IAAI,CAAC;AACtD,QAAM,OAAO,EAAE,KAAK,EAAE,KAAK;AAC3B,MAAI,IAAI,EAAE,OAAO,KAAK,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI;AAChE,MAAI,EAAE,IAAK,MAAK,EAAE,MAAM,KAAK,IAAI,IAAI,MAAM,EAAE,KAAK;AAClD,SAAO,EAAE,GAAG,GAAG,MAAM,EAAE,YAAY;AACrC;AAOO,SAAS,UAAU,GAAW,GAAW,GAAW,GAA0B;AACnF,QAAM,OAAO;AACb,QAAM,KAAK,IAAI,OAAO,IAAI,OAAO;AACjC,QAAM,KAAK,KAAK;AAChB,QAAM,IAAI,WAAW,GAAG,IAAI,GAAG,CAAC;AAChC,QAAM,IAAI,WAAW,GAAG,IAAI,GAAG,CAAC;AAChC,QAAM,KAAK,EAAE,IAAI,EAAE;AACnB,QAAM,KAAK,EAAE,IAAI,EAAE;AACnB,MAAI,KAAK,IAAI,EAAE,IAAI,IAAI,KAAK,KAAK,IAAI,EAAE,IAAI,IAAI,EAAG,QAAO;AACzD,MAAI,OAAO,KAAK,OAAO,EAAG,QAAO;AACjC,SAAO,KAAK,MAAM,IAAI,EAAE;AAC1B;AAGO,SAAS,cAAc,GAAW,GAAW,UAA0B;AAC5E,MAAI,CAAC,EAAE,eAAe,YAAY,EAAG,QAAO,EAAE;AAG9C,MAAI,EAAE,QAAS,SAAQ,EAAE,cAAc,KAAK,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,WAAW,KAAK;AACtF,SAAO,KAAK,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,IAAI,KAAK,GAAG,IAAI;AACnG;AASA,SAAS,SACP,IACA,IACA,QACA,GACA,GACQ;AACR,MAAI,KAAK,GAAG,IAAI,GAAG;AACnB,MAAI,KAAK,GAAG,IAAI,GAAG;AACnB,MAAI,QAAQ;AACV,QAAI,KAAK,IAAI,EAAE,IAAI,IAAI,EAAG,MAAK,KAAK,IAAI,KAAK,IAAI,KAAK;AACtD,QAAI,KAAK,IAAI,EAAE,IAAI,IAAI,EAAG,MAAK,KAAK,IAAI,KAAK,IAAI,KAAK;AAAA,EACxD;AACA,SAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACpC;AAOO,SAAS,cAAc,OAA6B,OAAuB;AAChF,SAAO,MAAM,YAAY,SAAY,WAAW,MAAM,UAAU;AAClE;AAUO,SAAS,UACd,OACA,WACA,WACA,QACA,GACA,GACY;AACZ,QAAM,IAAI,UAAU;AACpB,QAAM,OAAO,MAAM,QAAQ;AAC3B,QAAM,IAAI,MAAM,KAAK;AACrB,MAAI,SAAS,SAAS;AACpB,UAAM,MAAkB,CAAC;AACzB,aAAS,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK;AAC9B,UAAI,KAAK,EAAE,GAAG,GAAG,IAAI,GAAG,MAAM,SAAS,UAAU,CAAC,GAAI,UAAU,IAAI,CAAC,GAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;AAAA,IAC1F;AACA,QAAI,MAAM,UAAU,IAAI,EAAG,KAAI,KAAK,EAAE,GAAG,IAAI,GAAG,GAAG,GAAG,MAAM,SAAS,UAAU,IAAI,CAAC,GAAI,UAAU,CAAC,GAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;AACtH,WAAO;AAAA,EACT;AACA,MAAI,SAAS,UAAU;AACrB,UAAM,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,IAAI,QAAQ,CAAC;AACnD,UAAM,QAAQ,oBAAI,IAAY;AAC9B,UAAM,MAAkB,CAAC;AACzB,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,eAAS,OAAO,GAAG,QAAQ,GAAG,QAAQ;AACpC,cAAM,KAAK,IAAI,OAAO,UAAU;AAChC,YAAI,MAAM,EAAG;AACb,cAAM,OAAO,SAAS,UAAU,CAAC,GAAI,UAAU,CAAC,GAAI,QAAQ,GAAG,CAAC;AAChE,YAAI,OAAO,UAAW;AACtB,cAAM,MAAM,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,CAAC;AAC/C,YAAI,CAAC,MAAM,IAAI,GAAG,GAAG;AACnB,gBAAM,IAAI,GAAG;AACb,cAAI,KAAK,EAAE,GAAG,KAAK,IAAI,GAAG,CAAC,GAAG,GAAG,KAAK,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC;AAAA,QACzD;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,SAAO,UAAU,WAAW,GAAG,WAAW,QAAQ,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO;AAAA,IACvE;AAAA,IACA;AAAA,IACA,MAAM,SAAS,UAAU,CAAC,GAAI,UAAU,CAAC,GAAI,QAAQ,GAAG,CAAC;AAAA,EAC3D,EAAE;AACJ;AAIO,SAAS,UACd,WACA,GACA,SACA,QACA,GACA,GACyB;AACzB,QAAM,IAAI,UAAU;AACpB,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,MAA+B,CAAC;AAEtC,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,KAAK,UAAU,CAAC;AACtB,UAAM,YAAgD,CAAC;AACvD,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAI,MAAM,EAAG;AACb,YAAM,KAAK,UAAU,CAAC;AACtB,UAAI,KAAK,GAAG,IAAI,GAAG;AACnB,UAAI,KAAK,GAAG,IAAI,GAAG;AACnB,UAAI,QAAQ;AACV,YAAI,KAAK,IAAI,EAAE,IAAI,IAAI,EAAG,MAAK,KAAK,IAAI,KAAK,IAAI,KAAK;AACtD,YAAI,KAAK,IAAI,EAAE,IAAI,IAAI,EAAG,MAAK,KAAK,IAAI,KAAK,IAAI,KAAK;AAAA,MACxD;AACA,YAAM,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACxC,UAAI,QAAQ,QAAS,WAAU,KAAK,EAAE,MAAM,EAAE,CAAC;AAAA,IACjD;AACA,cAAU,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACrD,aAAS,KAAK,GAAG,KAAK,KAAK,IAAI,GAAG,UAAU,MAAM,GAAG,MAAM;AACzD,YAAM,IAAI,UAAU,EAAE,EAAG;AACzB,YAAM,KAAK,KAAK,IAAI,GAAG,CAAC;AACxB,YAAM,KAAK,KAAK,IAAI,GAAG,CAAC;AACxB,YAAM,MAAM,GAAG,EAAE,IAAI,EAAE;AACvB,UAAI,CAAC,MAAM,IAAI,GAAG,GAAG;AACnB,cAAM,IAAI,GAAG;AACb,YAAI,KAAK,CAAC,IAAI,EAAE,CAAC;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAMA,IAAM,cAAc,IAAI,IAAI,uBAAwB;AACpD,IAAM,YAAY,IAAI,IAAI,YAAY;AAUtC,IAAM,iBAAiB;AAOhB,SAAS,oBAAoB,MAAiC;AACnE,SAAO,QAAQ,eAAe,KAAK,IAAI,IAAI,SAAS;AACtD;AAEA,IAAM,kBAAkB;AASxB,SAAS,YAAY,IAAY,UAA4B,gBAAwB;AACnF,MAAI,YAAY,OAAQ,QAAO;AAC/B,MAAI,OAAO,OAAO,OAAO,IAAM,QAAO;AACtC,MAAI,YAAY,IAAI,EAAE,EAAG,QAAO;AAChC,MAAI,UAAU,IAAI,EAAE,EAAG,QAAO;AAC9B,SAAO;AACT;AAQO,SAAS,YAAY,KAAa,UAA4B,gBAAwB;AAC3F,MAAI,YAAY,OAAQ,QAAO,iBAAiB,GAAG,EAAE,SAAS;AAC9D,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,MAAK,YAAY,IAAI,CAAC,GAAI,OAAO;AACtE,SAAO;AACT;AAYO,SAAS,eAAe,MAAc,YAAoB,UAA4B,gBAAiC;AAC5H,QAAM,aAAa,KAAK,MAAM,IAAI;AAClC,QAAM,QAAyB,CAAC;AAEhC,aAAW,QAAQ,YAAY;AAC7B,QAAI,KAAK,WAAW,GAAG;AACrB,YAAM,KAAK,EAAE,MAAM,IAAI,SAAS,EAAE,CAAC;AACnC;AAAA,IACF;AACA,UAAM,QAAQ,KAAK,MAAM,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAC1D,QAAI,MAAM,WAAW,GAAG;AACtB,YAAM,KAAK,EAAE,MAAM,IAAI,SAAS,EAAE,CAAC;AACnC;AAAA,IACF;AAEA,QAAI,WAAW,MAAM,CAAC;AACtB,QAAI,QAAQ,YAAY,UAAU,OAAO;AACzC,UAAM,SAAS,YAAY,KAAK,OAAO;AAEvC,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,OAAO,MAAM,CAAC;AACpB,YAAM,QAAQ,YAAY,MAAM,OAAO;AACvC,UAAI,QAAQ,SAAS,SAAS,YAAY;AACxC,oBAAY,MAAM;AAClB,iBAAS,SAAS;AAAA,MACpB,OAAO;AACL,cAAM,KAAK,EAAE,MAAM,UAAU,SAAS,MAAM,CAAC;AAC7C,mBAAW;AACX,gBAAQ;AAAA,MACV;AAAA,IACF;AACA,UAAM,KAAK,EAAE,MAAM,UAAU,SAAS,MAAM,CAAC;AAAA,EAC/C;AAEA,SAAO;AACT;AAYO,SAAS,sBACd,GACA,QACA,UACA,QAC4B;AAC5B,MAAI,CAAC,EAAE,OAAQ,QAAO,EAAE,IAAI,GAAG,IAAI,EAAE;AACrC,QAAM,KAAK,EAAE,OAAO,SAAS,MAAM,IAAI,IAAI,EAAE,OAAO,SAAS,OAAO,IAAI,IAAI;AAC5E,QAAM,KAAK,EAAE,OAAO,WAAW,KAAK,IAAI,IAAI,EAAE,OAAO,WAAW,QAAQ,IAAI,IAAI;AAEhF,QAAM,QAAQ,EAAE,UAAU,YAAY,SAAS,YAAY,IAAI,EAAE,UAAU,UAAU,SAAS,WAAW;AACzG,SAAO,EAAE,IAAI,EAAE,QAAQ,KAAK,WAAW,IAAI,EAAE,KAAK,QAAQ;AAC5D;AAWA,SAAS,gBAAgB,IAAqB;AAC5C,SACG,MAAM,OAAU,MAAM;AAAA,EACtB,MAAM,QAAU,MAAM,QACtB,MAAM,QAAU,MAAM,QACtB,MAAM,SAAU,MAAM;AAAA,EACtB,MAAM,UAAW,MAAM;AAAA,EACxB,OAAO;AAEX;AAEA,SAAS,oBAAoB,IAAqB;AAChD,SAAO,MAAM,UAAW,MAAM;AAChC;AAEA,IAAM,MAAM;AAQL,SAAS,iBAAiB,MAAwB;AACvD,QAAM,MAAgB,CAAC;AACvB,MAAI,IAAI;AACR,SAAO,IAAI,KAAK,QAAQ;AACtB,UAAM,KAAK,KAAK,YAAY,CAAC;AAC7B,QAAI,MAAM,KAAK,KAAK,QAAS,IAAI;AAEjC,QAAI,oBAAoB,EAAE,KAAK,MAAM,KAAK,QAAQ;AAChD,YAAM,OAAO,KAAK,YAAY,GAAG;AACjC,UAAI,oBAAoB,IAAI,EAAG,QAAO,OAAO,QAAS,IAAI;AAAA,IAC5D;AAEA,WAAO,MAAM,KAAK,QAAQ;AACxB,YAAM,OAAO,KAAK,YAAY,GAAG;AACjC,UAAI,gBAAgB,IAAI,GAAG;AACzB,eAAO,OAAO,QAAS,IAAI;AAAA,MAC7B,WAAW,SAAS,OAAO,MAAM,IAAI,KAAK,QAAQ;AAChD,cAAM,QAAQ,KAAK,YAAY,MAAM,CAAC;AACtC,eAAO,KAAK,QAAQ,QAAS,IAAI;AAAA,MACnC,OAAO;AACL;AAAA,MACF;AAAA,IACF;AACA,QAAI,KAAK,KAAK,MAAM,GAAG,GAAG,CAAC;AAC3B,QAAI;AAAA,EACN;AACA,SAAO;AACT;AAiCO,SAAS,YAAY,OAAwB,QAAyB,KAA0B;AACrG,QAAM,eAAe,MAAM,IAAI,CAAC,MAAM,iBAAiB,EAAE,IAAI,CAAC;AAC9D,QAAM,iBAAiB,aAAa,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC;AAEpE,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,OAAO,YAAY,CAAC,CAAC;AAC9D,QAAM,QAAQ,OAAO,SAAS;AAC9B,QAAM,QAAQ,QAAQ,KAAK,iBAAiB,IAAI,KAAK,IAAI,GAAI,QAAQ,MAAO,MAAO,cAAc,IAAI;AACrG,QAAM,WAAW,KAAK,IAAI,UAAU,KAAK;AAEzC,QAAM,OAAO,OAAO,QAAQ;AAC5B,MAAI,YAAY;AAChB,MAAI,cAAc;AAMlB,MAAI;AACJ,MAAI,SAAS,aAAa;AAKxB,UAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,OAAO,QAAQ,IAAI,CAAC;AACzD,QAAI,IAAI;AACR,kBAAc,aAAa;AAAA,MAAI,CAAC,aAC9B,SAAS,IAAI,MAAM;AACjB,cAAM,QAAQ,iBAAiB,IAAK,MAAM,kBAAmB,IAAI,KAAK;AACtE,eAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,WAAW,SAAS,CAAC,CAAC;AAAA,MACxD,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,SAAS,QAAQ;AACnB,gBAAY,KAAK,MAAM,WAAW,MAAM,MAAM;AAAA,EAChD,WAAW,SAAS,QAAQ;AAC1B,UAAM,YAAY,MAAM,IAAI,CAAC,MAAO,EAAE,KAAK,WAAW,IAAI,CAAC,IAAI,EAAE,KAAK,MAAM,GAAG,CAAE;AACjF,UAAM,aAAa,UAAU,OAAO,CAAC,GAAG,OAAO,IAAI,GAAG,QAAQ,CAAC;AAC/D,QAAI,YAAY,KAAK,MAAM,WAAW,UAAU;AAChD,eAAW,MAAM,WAAW;AAC1B,UAAI,aAAa,GAAG,QAAQ;AAC1B,qBAAa,GAAG;AAChB;AAEA;AAAA,MACF;AACA,UAAI,YAAY,EAAG,eAAc,GAAG,MAAM,GAAG,SAAS,EAAE,KAAK,GAAG;AAChE;AAAA,IACF;AAAA,EACF,OAAO;AACL,QAAI,YAAY,KAAK,MAAM,WAAW,cAAc;AACpD,eAAW,YAAY,cAAc;AACnC,UAAI,aAAa,SAAS,QAAQ;AAChC,qBAAa,SAAS;AACtB;AACA;AAAA,MACF;AACA,UAAI,YAAY,EAAG,eAAc,SAAS,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE;AACrE;AAAA,IACF;AAAA,EACF;AAIA,MAAI;AACJ,MAAI;AACJ,MAAI,YAAY,SAAS,GAAG;AAC1B,gBAAY;AACZ,kBAAc;AAAA,EAChB,WAAW,YAAY,GAAG;AACxB,gBAAY,YAAY;AACxB,kBAAc,MAAM,YAAY,CAAC,EAAG;AAAA,EACtC,OAAO;AACL,gBAAY;AACZ,kBAAc;AAAA,EAChB;AAEA,SAAO,EAAE,UAAU,WAAW,aAAa,WAAW,aAAa,YAAY;AACjF;;;ACprCA;AAAA,EACE;AAAA,OAOK;;;ACUA,SAAS,YAAY,OAAkB,GAAW,GAAW,MAAkB;AACpF,QAAM,IAAI,MAAM;AAChB,MAAI,EAAG,QAAO,EAAE,GAAG,EAAE,IAAI,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,MAAM,KAAK,KAAK;AACjF,QAAM,KAAK,MAAM,QAAQ,KAAK,CAAC,GAAG,CAAC;AACnC,QAAM,KAAK,MAAM,QAAQ,KAAK,CAAC,GAAG,CAAC;AACnC,SAAO,EAAE,IAAK,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,IAAK,GAAG,IAAK,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,IAAK,EAAE;AACtE;AAGO,SAAS,gBAAgB,IAAoB,OAAyB,GAAW,GAAW,MAAkB;AACnH,SAAO,GAAG,WAAW,YAAY,QAAQ,YAAY,OAAO,GAAG,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;AACjG;AAOO,SAAS,eAAe,IAAoB,GAAO,GAAW,GAAW,MAAc,SAAa,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE,GAAO;AACrI,QAAM,IAAI,GAAG,SAAS;AACtB,QAAM,KAAK,KAAK,GAAG,UAAU;AAC7B,MAAI,KAAK,EAAE,IAAI,OAAO,KAAK;AAC3B,MAAI,KAAK,EAAE,IAAI,OAAO,KAAK;AAC3B,MAAI,GAAG,QAAQ;AACb,UAAM,IAAK,GAAG,SAAS,KAAK,KAAM;AAClC,UAAM,IAAI,KAAK,IAAI,CAAC;AACpB,UAAM,IAAI,KAAK,IAAI,CAAC;AACpB,KAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC;AAAA,EACxC;AACA,SAAO,EAAE,GAAG,IAAI,OAAO,KAAK,GAAG,KAAK,KAAK,MAAM,GAAG,IAAI,OAAO,KAAK,GAAG,KAAK,KAAK,KAAK;AACtF;AAGO,SAAS,cAAc,IAAwC;AACpE,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,IAAI,GAAG,SAAS;AACtB,SAAO,IAAI,KAAK,KAAK,KAAK,IAAI,GAAG,UAAU,CAAC,CAAC;AAC/C;AAGO,SAAS,QAAQ,MAAiB,OAA0C;AACjF,SAAO,MAAM,UAAU,SAAY,SAAY,KAAK,SAAS,MAAM,KAAK;AAC1E;AAEA,IAAM,UAAU,CAAC,MAAuB,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI;AAG3D,SAAS,aAAa,MAAiB,OAA0B;AACtE,QAAM,MAAM,MAAM,YAAY,SAAY,IAAI,QAAQ,MAAM,OAAO;AACnE,QAAM,IAAI,QAAQ,MAAM,KAAK;AAC7B,SAAO,GAAG,YAAY,SAAY,MAAM,MAAM,QAAQ,EAAE,OAAO;AACjE;AAMO,SAAS,UAAU,MAAiB,OAA0B;AACnE,SAAO,cAAc,MAAM,SAAS,IAAI,cAAc,QAAQ,MAAM,KAAK,GAAG,SAAS;AACvF;AAOO,SAAS,SAAS,MAAiB,OAAkB,GAAW,GAAW,MAAsC;AACtH,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,QAAQ,MAAM,KAAK,GAAG;AAClC,MAAI,CAAC,MAAM,CAAC,IAAK,QAAO;AACxB,QAAM,IAAI,KAAK,gBAAgB,IAAI,OAAO,GAAG,GAAG,IAAI,IAAI;AACxD,SAAO,CAAC,MAAM;AACZ,UAAM,IAAI,KAAK,eAAe,IAAI,GAAG,GAAG,GAAG,MAAM,CAAE,IAAI;AACvD,WAAO,MAAM,eAAe,KAAK,GAAG,GAAG,GAAG,IAAI,IAAI;AAAA,EACpD;AACF;AAGO,SAAS,OAAO,KAAoB,KAA6G;AACtJ,QAAM,MAAM,CAAC,CAAC,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,GAAO,EAAM,CAAC,CAAC;AAC1H,SAAO;AAAA,IACL,IAAI,KAAK,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAAA,IACnC,IAAI,KAAK,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAAA,IACnC,IAAI,KAAK,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAAA,IACnC,IAAI,KAAK,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAAA,EACrC;AACF;;;ACpFA,IAAM,SAAS,KAAK,KAAK;AAGlB,IAAM,kBAAkB;AAExB,IAAM,0BAA0B;AAEhC,IAAM,8BAA8B;AAE3C,IAAM,YAAY;AAElB,IAAM,aAAa;AAEZ,IAAM,6BAA6B;AAS1C,IAAM,WAA8B,CAAC,GAAG,MAAM,KAAK,MAAM,CAAG;AAE5D,IAAME,WAAU,CAAC,MAAuB,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AAOzD,SAAS,YAAY,IAAY,IAAY,MAAsB;AACxE,MAAI,IAAI,KAAK,KAAK,KAAK,GAAG,SAAU,IAAI,KAAK,KAAK,KAAK,GAAG,SAAU,IAAI,KAAK,KAAK,OAAO,GAAG,UAAU;AACtG,MAAI,KAAK,KAAK,IAAK,MAAM,IAAK,UAAU;AACxC,MAAI,KAAK,KAAK,IAAK,MAAM,IAAK,UAAU;AACxC,OAAK,MAAM;AACX,UAAQ,MAAM,KAAK;AACrB;AAEA,IAAMC,cAAa,CAAC,MAAsB,IAAI,KAAK,IAAI,IAAI;AAG3D,SAAS,WAAW,GAAW,GAAW,MAAsB;AAC9D,QAAM,KAAK,KAAK,MAAM,CAAC;AACvB,QAAM,KAAK,KAAK,MAAM,CAAC;AACvB,QAAM,KAAKA,YAAW,IAAI,EAAE;AAC5B,QAAM,KAAKA,YAAW,IAAI,EAAE;AAC5B,QAAM,IAAI,YAAY,IAAI,IAAI,IAAI;AAClC,QAAM,IAAI,YAAY,KAAK,GAAG,IAAI,IAAI;AACtC,QAAM,IAAI,YAAY,IAAI,KAAK,GAAG,IAAI;AACtC,QAAM,IAAI,YAAY,KAAK,GAAG,KAAK,GAAG,IAAI;AAC1C,QAAM,MAAM,KAAK,IAAI,KAAK;AAC1B,QAAM,SAAS,KAAK,IAAI,KAAK;AAC7B,SAAO,OAAO,SAAS,OAAO;AAChC;AAGA,SAAS,IAAI,GAAW,GAAW,MAAc,SAAyB;AACxE,MAAI,MAAM;AACV,MAAI,MAAM;AACV,MAAI,OAAO;AACX,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,SAAS,KAAK;AAGhC,WAAO,MAAM,WAAW,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,OAAO,IAAI,GAAG;AAC1E,YAAQ;AACR,WAAO;AACP,SAAK;AAAA,EACP;AACA,SAAO,MAAM;AACf;AAGO,SAAS,aAAa,KAA+C;AAC1E,QAAM,IAAI,KAAK,MAAM,IAAI,WAAW,CAAC;AACrC,SAAO,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AACjC;AAWO,SAAS,gBAAgB,KAAqC,GAAmB;AACtF,SAAO,IAAI,SAAS,IAAI,MAAM,WAAW,IAAI,KAAK,MAAM,IAAI,eAAe,IAAI,kBAAkB;AACnG;AAQO,SAAS,QAAQ,GAAW,GAAW,GAAW,KAAsB,MAAsB;AACnG,QAAM,QAAQ,IAAI;AAClB,QAAM,UAAU,aAAa,GAAG;AAChC,QAAM,KAAK,IAAI,QAAQ,UAAU;AACjC,MAAI,IAAI,IAAI;AACZ,MAAI,IAAI,IAAI;AACZ,QAAM,QAAQ,IAAI;AAClB,MAAI,OAAO;AAKT,UAAM,QAAS,SAAS,IAAK,MAAM;AACnC,UAAM,KAAK,MAAM,UAAU,8BAA8B;AACzD,SAAK,IAAI,KAAK,IAAI,KAAK;AACvB,SAAK,IAAI,KAAK,IAAI,KAAK;AAAA,EACzB;AACA,QAAM,OAAO,IAAI,QAAQ;AACzB,MAAI,OAAO,GAAG;AAIZ,UAAM,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM,OAAO,IAAI;AACtD,UAAM,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,QAAQ,OAAO,IAAI;AACxD,SAAK,OAAO,YAAY;AACxB,SAAK,OAAO,YAAY;AAAA,EAC1B;AACA,QAAM,MAAM,IAAI,GAAG,GAAG,GAAG,OAAO;AAChC,SAAOD,SAAQ,OAAO,MAAM,OAAO,SAAS,OAAO,CAAE;AACvD;AAGO,SAAS,YAAY,KAAuC;AACjE,QAAM,IAAI,IAAI,WAAW,IAAI,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK;AACzF,QAAM,IAAI,kBAAkB,KAAK,CAAC,IAAI,SAAS,EAAE,MAAM,CAAC,GAAG,EAAE,IAAI;AACjE,MAAI,OAAO,MAAM,CAAC,EAAG,QAAO,CAAC,KAAK,KAAK,GAAG;AAC1C,SAAO,CAAE,KAAK,KAAM,KAAM,KAAK,IAAK,KAAK,IAAI,GAAG;AAClD;AAGO,SAAS,WAAW,KAAgD;AACzE,UAAQ,SAAS,IAAI,CAAC,IAAI,SAAS,IAAI,CAAC,IAAI,SAAS,IAAI,CAAC,KAAK;AACjE;AAUO,SAAS,SAAS,OAAe,OAA0B,UAAwD;AACxH,QAAM,IAAI,MAAM;AAChB,QAAM,IAAI,KAAK,MAAM,YAAY,CAAC;AAClC,MAAI;AACJ,MAAI,KAAK,GAAG;AACV,UAAM,QAAQ,KAAK,IAAI,IAAI,GAAG,KAAK,MAAMA,SAAQ,KAAK,IAAI,CAAC,CAAC;AAC5D,QAAK,SAAS,IAAI,MAAO,IAAI;AAAA,EAC/B,OAAO;AACL,QAAIA,SAAQ,KAAK,KAAK,IAAI;AAAA,EAC5B;AACA,QAAM,IAAI,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,CAAC,CAAC;AACvC,QAAM,IAAI,IAAI;AACd,QAAM,IAAI,YAAY,MAAM,CAAC,CAAE;AAC/B,MAAI,MAAM,EAAG,QAAO;AACpB,QAAM,IAAI,YAAY,MAAM,IAAI,CAAC,CAAE;AACnC,SAAO;AAAA,IACL,KAAK,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;AAAA,IACnC,KAAK,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;AAAA,IACnC,KAAK,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;AAAA,EACrC;AACF;AAGO,SAAS,WAAW,GAAW,GAAW,GAAW,KAAsB,MAAwC;AACxH,SAAO,SAAS,QAAQ,GAAG,GAAG,GAAG,KAAK,IAAI,GAAG,IAAI,OAAO,IAAI,QAAQ;AACtE;;;ACvKO,IAAM,aAAa;AAEnB,IAAM,cAAc;AAEpB,IAAM,cAAc;AAEpB,IAAM,eAAe;AAErB,IAAM,oBAAoB;AAEjC,IAAME,WAAU,CAAC,MAAuB,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AAGzD,SAAS,eAAe,GAA8D;AAC3F,SAAO,EAAE,OAAOA,SAAQ,GAAG,SAAS,CAAC,GAAG,QAAQA,SAAQ,GAAG,UAAU,CAAC,EAAE;AAC1E;AAQO,SAAS,gBAAgB,MAAiC;AAC/D,QAAM,KAAK,IAAI,kBAAkB,aAAa,aAAa,CAAC;AAC5D,QAAM,IAAI,SAAS;AACnB,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,aAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,YAAM,KAAK,YAAY,GAAG,GAAG,CAAC,IAAI,YAAY,GAAG,GAAG,IAAI,UAAU,KAAK;AACvE,YAAM,IAAI,KAAK,MAAM,OAAO,IAAI,OAAO,GAAG;AAC1C,SAAG,GAAG,IAAI;AACV,SAAG,GAAG,IAAI;AACV,SAAG,GAAG,IAAI;AACV,SAAG,GAAG,IAAI;AAAA,IACZ;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,cAA0B;AACxC,MAAI,IAAgB,CAAC,CAAC,CAAC,CAAC;AACxB,WAAS,IAAI,GAAG,IAAI,aAAa,KAAK,GAAG;AACvC,UAAM,OAAmB,CAAC;AAC1B,aAAS,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK;AAC9B,YAAM,MAAgB,CAAC;AACvB,eAAS,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK;AAC9B,cAAM,OAAO,EAAE,IAAI,CAAC,EAAG,IAAI,CAAC,IAAK;AACjC,cAAM,YAAY,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI;AAClD,YAAI,KAAK,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,QAAQ,CAAE;AAAA,MACzC;AACA,WAAK,KAAK,GAAG;AAAA,IACf;AACA,QAAI;AAAA,EACN;AACA,SAAO;AACT;AAQO,SAAS,kBAAqC;AACnD,QAAM,IAAI,YAAY;AACtB,QAAM,KAAK,IAAI,kBAAkB,cAAc,cAAc,CAAC;AAC9D,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,aAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,YAAM,IAAI,KAAK,OAAQ,EAAE,CAAC,EAAG,CAAC,IAAK,QAAQ,cAAc,eAAgB,GAAG;AAC5E,SAAG,GAAG,IAAI;AACV,SAAG,GAAG,IAAI;AACV,SAAG,GAAG,IAAI;AACV,SAAG,GAAG,IAAI;AAAA,IACZ;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,YAAY,GAAW,MAAc,SAA4C;AAC/F,MAAI,CAAC,QAAS,QAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAClC,QAAM,SAAS,KAAK,MAAO,IAAI,oBAAqB,GAAI;AACxD,QAAM,IAAI,SAAS;AACnB,SAAO;AAAA,IACL,GAAG,KAAK,MAAM,YAAY,QAAQ,GAAG,CAAC,IAAI,UAAU;AAAA,IACpD,GAAG,KAAK,MAAM,YAAY,QAAQ,GAAG,CAAC,IAAI,UAAU;AAAA,EACtD;AACF;AAUO,SAAS,aAAa,KAAqD;AAChF,QAAM,OAAO,IAAI;AACjB,MAAI,KAAe;AACnB,aAAW,aAAa,CAAC,WAAW,YAAY,GAAY;AAC1D,QAAI,2BAA2B;AAC/B,QAAI,IAAI,6BAA6B,WAAW;AAC9C,WAAK;AACL;AAAA,IACF;AAAA,EACF;AACA,MAAI,2BAA2B;AAC/B,SAAO;AACT;AAsBA,SAAS,WAAW,MAAc,QAA6C;AAC7E,QAAM,SAAoB,OAAO,aAAa,cAAc,SAAS,cAAc,QAAQ,IAAI,IAAI,gBAAgB,MAAM,IAAI;AAC7H,SAAO,QAAQ;AACf,SAAO,SAAS;AAChB,QAAM,MAAM,OAAO,WAAW,IAAI;AAClC,MAAI,CAAC,OAAO,OAAO,IAAI,oBAAoB,WAAY,QAAO;AAC9D,QAAM,MAAM,IAAI,gBAAgB,MAAM,IAAI;AAC1C,MAAI,KAAK,IAAI,MAAM;AACnB,MAAI,aAAa,KAAK,GAAG,CAAC;AAC1B,SAAO;AACT;AAGO,SAAS,iBAAiB,SAAoB,MAAiC;AACpF,QAAM,MAAM,QAAQ,WAAW,MAAM,EAAE,OAAO,MAAM,CAAC;AACrD,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,EAAE,QAAQ,SAAS,KAAK,IAAI,aAAa,GAAG,GAAG,OAAO,MAAM,QAAQ,MAAM,KAAK;AACxF;AAGO,SAAS,kBAAkB,OAAe,QAA2B;AAC1E,MAAI,OAAO,aAAa,YAAa,QAAO,IAAI,gBAAgB,KAAK,IAAI,GAAG,KAAK,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC;AACvG,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,QAAQ,KAAK,IAAI,GAAG,KAAK;AAChC,SAAO,SAAS,KAAK,IAAI,GAAG,MAAM;AAClC,SAAO;AACT;AAEA,SAAS,QAAQ,IAAgB,MAAc,QAAiD;AAC9F,QAAM,OAAO,WAAW,MAAM,MAAM;AACpC,MAAI,CAAC,QAAQ,OAAO,GAAG,IAAI,kBAAkB,WAAY,QAAO;AAChE,SAAO,GAAG,IAAI,cAAc,MAA2B,QAAQ;AACjE;AAcO,SAAS,kBACd,IACA,OACA,GACA,GACA,GACA,QACA,gBACA,OAAe,GAAG,MACZ;AACN,QAAM,IAAI,GAAG;AACb,IAAE,cAAc;AAChB,IAAE,2BAA2B;AAC7B,IAAE,UAAU,OAA4B,GAAG,GAAG,GAAG,CAAC;AAKlD,QAAM,iBAAkB,SAAS,KAAM;AACvC,MAAI,mBAAmB,GAAG,MAAM;AAC9B,OAAG,OAAO;AACV,OAAG,QAAQ;AAAA,EACb;AACA,QAAM,EAAE,OAAO,OAAO,IAAI,eAAe,MAAM;AAC/C,MAAI,QAAQ,GAAG;AACb,OAAG,UAAU,QAAQ,IAAI,YAAY,gBAAgB,GAAG,IAAI,CAAC;AAC7D,QAAI,GAAG,MAAO,QAAO,IAAI,GAAG,OAAO,QAAQ,aAAa,YAAY,GAAG,GAAG,MAAM,kBAAkB,QAAQ,YAAY,IAAI,GAAG,GAAG,CAAC;AAAA,EACnI;AACA,MAAI,SAAS,GAAG;AACd,OAAG,WAAW,QAAQ,IAAI,aAAa,gBAAgB,CAAC;AACxD,QAAI,GAAG,OAAQ,QAAO,IAAI,GAAG,QAAQ,SAAS,cAAc,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC;AAAA,EAClF;AACF;AAEA,SAAS,OAAO,IAAgB,KAAoB,OAAe,KAA+B,GAAW,GAAiB;AAC5H,QAAM,IAAI,GAAG;AACb,IAAE,KAAK;AACP,IAAE,2BAA2B,GAAG;AAChC,IAAE,cAAc;AAChB,IAAE,wBAAwB;AAC1B,IAAE,YAAY;AAGd,IAAE,UAAU,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC;AAC1B,IAAE,SAAS,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC;AAC7B,IAAE,QAAQ;AACZ;;;ACjNO,SAAS,gBAAgB,YAA4B;AAC1D,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,MAAM,MAAM,KAAK,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC;AAC5E;AASO,SAAS,YACd,OACA,GACA,WACA,UACA,OACA,GACA,GACAC,OACA,YACA,WAAW,GACX,WAAW,OACE;AACb,QAAM,OAAO,MAAM,QAAQ;AAC3B,QAAM,IAAI,KAAK,IAAI,KAAK,KAAK,MAAM,SAAS,EAAE,GAAG,OAAO,eAAe;AACvE,QAAM,WAAW,CAAC,MAAsB,aAAa,IAAI,IAAI;AAC7D,QAAM,YAAY,CAAC,MAAuB,WAAW,KAAM,IAAI,IAAI;AACnE,QAAM,QAAQ,CAAC,GAA6B,MAC1CA,UAAS,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI,KAAK,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI;AAEpE,QAAM,OAAO,MAAM,CAAC;AACpB,QAAM,OAAoB,CAAC;AAC3B,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,UAAM,IAAI,IAAI;AACd,UAAM,QAAQ,IAAI,IAAI,MAAM;AAC5B,QAAI,QAAQ,EAAG;AACf,UAAM,MAAM,MAAM,KAAK;AACvB,QAAI,MAAM,MAAM,GAAG,EAAG;AACtB,WAAO;AACP,UAAM,IAAI,SAAS,CAAC;AACpB,QAAI,KAAK,SAAU;AACnB,UAAM,IAAI,UAAU,CAAC;AACrB,QAAI,IAAI,IAAK;AACb,SAAK,KAAK,EAAE,GAAG,OAAO,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,GAAG,OAAO,GAAG,EAAE,CAAC;AAAA,EAC5D;AACA,MAAI,KAAK,WAAW,EAAG,QAAO;AAG9B,QAAM,OAAiB,CAAC;AACxB,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,MAAM,IAAI,OAAO,KAAK,IAAI,CAAC;AACrC,UAAM,IAAI,KAAK,CAAC;AAChB,UAAM,IAAI,KAAK,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AACzC,UAAM,IAAI,IAAI,EAAE,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC,IAAI,IAAI;AAC7C,SAAK,KAAK,CAAC;AACX,aAAS;AAAA,EACX;AACA,MAAI,UAAU,EAAG,QAAO;AACxB,QAAM,QAAQ,QAAQ,aAAa,aAAa,QAAQ;AAExD,QAAM,MAAmB,CAAC;AAC1B,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,KAAK,CAAC;AAChB,UAAM,IAAI,KAAK,MAAM,KAAK,CAAC,IAAK,KAAK;AACrC,QAAI,MAAM,GAAG;AACX,UAAI,KAAK,CAAC;AACV,aAAO;AACP;AAAA,IACF;AACA,UAAM,IAAI,MAAM,IAAI,OAAO,KAAK,IAAI,CAAC;AACrC,UAAM,UAAU,KAAK,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,KAAK,IAAI;AAExD,UAAM,QAAQ,CAAC,OAAe,MAAsB;AAClD,YAAM,IAAI,KAAK,IAAI,GAAG,WAAW,IAAI,EAAE;AACvC,aAAO,WAAW,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,GAAG,CAAC;AAAA,IACtE;AACA,UAAM,KAAK,MAAM,IAAI,IAAI,KAAK,IAAI,CAAC,EAAG;AACtC,UAAM,KAAK,MAAM,IAAI,IAAI,KAAK,IAAI,CAAC,EAAG;AACtC,aAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,YAAM,IAAI,KAAK,IAAI;AACnB,YAAM,KAAK,MAAM,EAAE,IAAI,MAAM;AAC7B,YAAM,IAAI,MAAM,EAAE,IAAI,MAAM;AAC5B,YAAM,MAAM,MAAM,EAAE;AACpB,UAAI,MAAM,MAAM,GAAG,EAAG;AACtB,aAAO;AACP,YAAM,IAAI,UAAU,CAAC;AACrB,UAAI,KAAK,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,GAAG,OAAO,MAAM,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;AAAA,IAC5E;AACA,QAAI,KAAK,EAAE,GAAG,GAAG,OAAO,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AAC7C,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;AJhHA,IAAM,oBAAoB;AAW1B,SAAS,oBAAoB,MAAiB,QAAyC;AACrF,MAAI,MAAM;AACV,aAAW,KAAK,QAAQ;AACtB,QAAI,CAAC,gBAAgB,KAAK,EAAE,IAAI,EAAG;AACnC,UAAM,OAAO,kBAAkB,KAAK,CAAC,CAAC,CAAC;AACvC,QAAI,aAAa,IAAI,EAAE,MAAO,OAAM;AAAA,EACtC;AACA,SAAO;AACT;AAGA,SAAS,UAAU,KAAa,OAAuB;AACrD,QAAM,IAAI,IAAI,WAAW,IAAI,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK;AACzF,QAAM,IAAI,SAAS,EAAE,MAAM,CAAC,GAAG,EAAE;AACjC,SAAO,QAAS,KAAK,KAAM,GAAG,IAAK,KAAK,IAAK,GAAG,IAAI,IAAI,GAAG,IAAI,KAAK;AACtE;AAEA,IAAM,iBAAiB;AAkBvB,IAAM,aAAa;AAanB,SAAS,YAAY,MAAc,QAAwB;AACzD,MAAI,WAAW,EAAG,QAAO;AACzB,SAAO,KAAK,QAAQ,YAAY,CAAC,IAAI,MAAc,IAAI,OAAO,CAAC,IAAI,QAAQ,QAAQ,CAAC,CAAC,IAAI;AAC3F;AAGA,SAAS,qBAAqB,IAAY,MAAsB;AAC9D,QAAM,IAAI,eAAe,KAAK,IAAI;AAClC,MAAI,EAAG,QAAO,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC;AAC/D,SAAO,GAAG,EAAE,MAAM,IAAI;AACxB;AAGO,SAAS,YAAY,MAAgC;AAC1D,QAAM,QAAQ,KAAK,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC;AACzD,QAAM,WAAW,QAAQ,KAAK,SAAS,QAAQ,MAAM,QAAQ,QAAQ,MAAM,WAAW;AACtF,SAAO;AAAA,IACL,IAAI,KAAK;AAAA,IACT,OAAO,KAAK;AAAA;AAAA;AAAA,IAGZ,WAAW;AAAA,IACX,aAAa;AAAA,IACb,YAAY;AAAA,IACZ;AAAA,IACA,iBAAiB,KAAK,mBAAmB;AAAA,IACzC,uBAAuB;AAAA;AAAA;AAAA,IAGvB,MAAM,EAAE,WAAW,KAAK;AAAA,IACxB,aAAa;AAAA,EACf;AACF;AA8FA,IAAMC,WAAU,CAAC,MAAuB,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI;AAalE,IAAM,UAAU,uBAAO,SAAS;AAGhC,SAAS,eAAe,GAAqB,GAAoB;AAC/D,QAAM,IAAI,EAAE,MAAM,IAAI,WAAWA,UAAS,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI;AAChE,SAAO,KAAK,IAAI,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE,IAAI,GAAG,OAAO,EAAE,IAAI;AACjE;AAQA,SAAS,gBAAgB,GAAqB,GAAW,eAAuC;AAC9F,MAAI,IAAI,EAAE,MAAO,QAAO,eAAe,GAAG,CAAC;AAC3C,MAAI,EAAE,SAAS,KAAK,IAAI,EAAE,QAAQ,EAAE,OAAQ,QAAO,UAAU,eAAe,GAAG,EAAE,KAAK,GAAG,cAAc,GAAG,YAAY,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE,IAAI;AAC7J,SAAO;AACT;AAGA,IAAM,UAAU,CAAC,MAA0B,GAAG,EAAE,CAAC,IAAI,KAAK,UAAU,EAAE,KAAK,CAAC;AAG5E,SAAS,YAAY,UAAqB,MAAc,MAAe,IAAa,KAAa,OAAiC;AAChI,QAAM,OAAO,aAAa,UAAU,MAAM,GAAG;AAC7C,SAAO,EAAE,MAAM,KAAK,MAAM,KAAK,YAAY,GAAG,IAAI,CAAC,GAAG,MAAM,IAAI,IAAI,KAAK,KAAK,OAAO,OAAO,OAAO,KAAK,KAAK,OAAO,mBAAmB,QAAQ,OAAO,KAAK,MAAM,EAAE;AACrK;AAOA,SAAS,iBAAiB,UAAqB,WAAkD,GAAW,SAA+B;AACzI,MAAI,UAAU,SAAS,EAAG,QAAO;AACjC,QAAM,SAAuB,CAAC;AAC9B,aAAW,CAAC,MAAM,CAAC,KAAK,WAAW;AACjC,UAAM,IAAI,gBAAgB,GAAG,GAAG,MAAM,aAAa,UAAU,IAAI,CAAC;AAClE,QAAI,MAAM,SAAS;AAAE,eAAS,KAAK,IAAI;AAAG;AAAA,IAAU;AACpD,WAAO,KAAK,EAAE,GAAG,GAAG,MAAM,OAAO,EAAE,CAAC;AAAA,EACtC;AACA,SAAO,OAAO,SAAS,IAAI,kBAAkB,UAAU,MAAM,IAAI;AACnE;AAOA,SAAS,mBAAmB,UAAqB,WAAkD,KAAsB;AAIvH,QAAM,QAAQ,CAAC,GAAG,UAAU,KAAK,CAAC;AAClC,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAMC,WAAU,CAAC,MAAsB,EAAE,MAAM,GAAG,EAAE,MAAM,GAAG,EAAE,WAAW,SAAS,IAAI,IAAI,CAAC,EAAE,KAAK,GAAG;AACtG,QAAM,SAAS,CAAC,GAAG,IAAI,IAAI,MAAM,IAAIA,QAAO,CAAC,CAAC;AAG9C,QAAM,OAAO,MAAM,KAAK,CAAC,MAAM,6CAA6C,KAAK,CAAC,KAAK,MAAM,YAAY,CAAC,2CAA2C,KAAK,CAAC,CAAC;AAC5J,QAAM,OAAO,OAAO,SAAY,CAAC,MAAuB,OAAO,SAASA,SAAQ,CAAC,CAAC;AAClF,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,KAAK,CAAC,KAAK,GAAG,yBAAyB,UAAU,KAAK,OAAO,IAAI,CAAC,GAAG;AAC9E,UAAM,OAAO,oBAAI,IAA8B;AAE/C,eAAW,CAAC,GAAG,CAAC,KAAK,UAAW,KAAI,IAAI,EAAE,MAAO,MAAK,IAAI,GAAG,EAAE,GAAG,GAAG,IAAI,OAAO,kBAAkB,CAAC;AACnG,UAAM,IAAI,iBAAiB,kBAAkB,UAAU,CAAC,GAAG,MAAM,CAAC;AAClE,UAAM,QAAQ,KAAK,UAAU,OAAO,IAAI,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,KAAK,KAAK,CAAC,EAAE,KAAK,GAAG;AACrG,QAAI,KAAK,IAAI,KAAK,EAAG;AACrB,SAAK,IAAI,KAAK;AACd,QAAI,CAAC,kBAAkB,GAAG,KAAK,EAAG,QAAO;AAAA,EAC3C;AACA,SAAO;AACT;AAKA,IAAM,uBAAuB;AAE7B,IAAM,mBAAmB;AAEzB,IAAM,uBAAuB;AAE7B,IAAM,gBAAgB;AAEtB,IAAM,yBAAyB;AAE/B,IAAM,yBAAyB,MAAM;AAErC,IAAM,wBAAwB;AAE9B,IAAM,uBAAuB;AAG7B,SAAS,WAAW,OAA4E;AAC9F,QAAM,KAAK,IAAI,OAAO;AACtB,aAAW,KAAK,OAAO;AACrB,QAAI,EAAE,OAAO,SAAS,EAAG;AACzB,OAAG,OAAO,EAAE,OAAO,CAAC,EAAG,CAAC,GAAG,EAAE,OAAO,CAAC,EAAG,CAAC,CAAC;AAC1C,aAAS,IAAI,GAAG,IAAI,EAAE,OAAO,QAAQ,IAAK,IAAG,OAAO,EAAE,OAAO,CAAC,EAAG,CAAC,GAAG,EAAE,OAAO,CAAC,EAAG,CAAC,CAAC;AACpF,QAAI,EAAE,OAAQ,IAAG,UAAU;AAAA,EAC7B;AACA,SAAO;AACT;AAGA,SAAS,WAAW,GAAiE,OAA0E;AAC7J,IAAE,UAAU;AACZ,aAAW,KAAK,OAAO;AACrB,QAAI,EAAE,OAAO,SAAS,EAAG;AACzB,MAAE,OAAO,EAAE,OAAO,CAAC,EAAG,CAAC,GAAG,EAAE,OAAO,CAAC,EAAG,CAAC,CAAC;AACzC,aAAS,IAAI,GAAG,IAAI,EAAE,OAAO,QAAQ,IAAK,GAAE,OAAO,EAAE,OAAO,CAAC,EAAG,CAAC,GAAG,EAAE,OAAO,CAAC,EAAG,CAAC,CAAC;AACnF,QAAI,EAAE,OAAQ,GAAE,UAAU;AAAA,EAC5B;AACF;AAGA,SAAS,iBAAiB,GAAiE,IAAkC;AAC3H,QAAM,OAAO,GAAG,SAAS,WACrB,EAAE,qBAAqB,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,IACjE,EAAE,sBAAsB,GAAG,SAAS,GAAG,QAAQ,CAAC,IAAI,GAAG,SAAS,GAAG,QAAQ,CAAC,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,GAAG,MAAM;AAC3H,aAAW,MAAM,GAAG,MAAO,MAAK,aAAa,GAAG,IAAI,GAAG,YAAY,SAAY,GAAG,QAAQ,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AACzH,SAAO;AACT;AAGA,SAAS,SAAS,GAAiEC,QAAe,GAA2B;AAC3H,QAAM,OAAO,EAAE,qBAAqB,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACpD,OAAK,aAAa,GAAGA,MAAK;AAC1B,OAAK,aAAa,MAAM,UAAUA,QAAO,IAAI,CAAC;AAC9C,OAAK,aAAa,GAAG,UAAUA,QAAO,CAAC,CAAC;AACxC,SAAO;AACT;AAmBA,IAAM,eAAN,MAA4C;AAAA,EA2F1C,YACmB,MACjB,KACA,OAA4B,CAAC,GAC7B;AAHiB;AAIjB,SAAK,UAAU;AACf,QAAI,KAAK,UAAU;AACjB,WAAK,WAAW;AAChB,WAAK,UAAU,kBAAkB,MAAM,CAAC;AAAA,IAC1C;AACA,SAAK,WAAW;AAChB,SAAK,cAAc,KAAK,gBAAgB;AACxC,UAAM,OAAO,KAAK;AAClB,SAAK,iBAAiB,SAAS,WAAW,SAAS,YAAY,8BAA8B;AAC7F,SAAK,gBAAgB,SAAS,WAAW,SAAS;AAClD,SAAK,OAAO,cAAc,KAAK,QAAQ,IAAI,IAAI;AAC/C,QAAI;AACJ,QAAI,IAAI,SAAS;AACf,eAAS,IAAI;AACb,WAAK,aAAa;AAAA,IACpB,OAAO;AACL,YAAM,KAAK,SAAS,cAAc,QAAQ;AAC1C,SAAG,MAAM,UAAU;AACnB,SAAG,aAAa,eAAe,MAAM;AACrC,UAAI,KAAK,YAAY,EAAE;AACvB,eAAS;AACT,WAAK,aAAa;AAAA,IACpB;AACA,QAAI,KAAK,WAAW,UAAa,CAAC,KAAK,eAAe,CAAC,KAAK,cAAc;AAIxE,YAAM,OAAO,iBAAiB,QAAQ,KAAK,IAAI;AAC/C,UAAI,MAAM;AACR,aAAK,aAAa;AAClB,iBAAS,kBAAkB,IAAI,OAAO,IAAI,MAAM;AAAA,MAClD;AAAA,IACF;AACA,SAAK,SAAS;AAMd,UAAM,MAAM,OAAO,WAAW,MAAM,EAAE,OAAO,KAAK,YAAY,CAAC;AAC/D,QAAI,CAAC,IAAK,OAAM,IAAI,MAAM,6BAA6B;AACvD,SAAK,MAAM;AAEX,SAAK,IAAI,IAAI;AACb,SAAK,IAAI,IAAI;AACb,SAAK,WAAW;AAChB,SAAK,QAAQ;AAEb,SAAK,SAAS,IAAI;AAClB,QAAI,KAAK,QAAQ;AACf,UAAI,CAAC,KAAK,iBAAkB,MAAK,YAAY,GAAG,KAAK,IAAI;AAAA,IAC3D,OAAO;AACL,WAAK,MAAM;AAAA,IACb;AAAA,EACF;AAAA,EA1DmB;AAAA,EA3FF;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EACA;AAAA,EACA,SAAkB,CAAC;AAAA,EACnB,UAAyB;AAAA,EACzB,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA;AAAA,EACR,QAAQ;AAAA;AAAA,EAER,cAAc,OAAO;AAAA;AAAA,EAGrB;AAAA;AAAA,EAEA,aAAqF;AAAA,EACrF,iBAAiB;AAAA;AAAA,EAEjB,iBAAiE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjE,WAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7B,YAA2C,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWnD,aAAa,oBAAI,IAAoB;AAAA;AAAA,EAE5B;AAAA;AAAA,EAET,QAA4B;AAAA,EACnB,eAAe,oBAAI,IAAiD;AAAA;AAAA,EAEpE,eAAe,oBAAI,QAA6B;AAAA,EACzD,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,WAAW;AAAA;AAAA,EAEF,eAAe,oBAAI,QAA+D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUlF,YAAY,oBAAI,IAAyQ;AAAA;AAAA,EAEzR,cAAe,WAA+C,sBAAsB;AAAA;AAAA,EAE7F,iBAAiB;AAAA,EACR,eAAe,oBAAI,IAAgI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAW5J,aAAgC;AAAA;AAAA,EAEvB;AAAA;AAAA,EAgET,YAAoB;AAC1B,QAAI,KAAK,QAAQ,UAAU,KAAM,QAAO;AACxC,WAAO,KAAK,IAAI,KAAK,GAAG,KAAK,CAAC,KAAK,KAAK,QAAQ,qBAAqB,OAAO;AAAA,EAC9E;AAAA,EAEQ,aAAmB;AACzB,UAAM,MAAM,KAAK,IAAI,KAAK,SAAS,KAAK,CAAC;AAOzC,UAAM,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC;AAC/C,UAAM,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC;AAC/C,QAAI,KAAK,OAAO,UAAU,GAAI,MAAK,OAAO,QAAQ;AAClD,QAAI,KAAK,OAAO,WAAW,GAAI,MAAK,OAAO,SAAS;AACpD,SAAK,IAAI,aAAa,KAAK,GAAG,GAAG,KAAK,GAAG,CAAC;AAC1C,QAAI,KAAK,YAAY;AAEnB,UAAI,KAAK,WAAW,OAAO,UAAU,GAAI,MAAK,WAAW,OAAO,QAAQ;AACxE,UAAI,KAAK,WAAW,OAAO,WAAW,GAAI,MAAK,WAAW,OAAO,SAAS;AAC1E,WAAK,WAAW,IAAI,aAAa,KAAK,GAAG,GAAG,KAAK,GAAG,CAAC;AAAA,IACvD;AAEA,SAAK,cAAc,OAAO;AAAA,EAC5B;AAAA;AAAA,EAGQ,UAAgB;AACtB,UAAM,MAAM,UAAU,KAAK,IAAI;AAC/B,UAAM,EAAE,OAAO,WAAW,IAAI,aAAa,KAAK,SAAS,KAAK,GAAG,KAAK,CAAC;AACvE,SAAK,SAAS,KAAK,QAAQ,OAAO,IAAI,CAAC,WAAW,EAAE,OAAO,UAAU,cAAc,OAAO,KAAK,KAAK,GAAG,KAAK,GAAG,OAAO,UAAU,EAAE,EAAE;AACpI,SAAK,iBAAiB,oBAAoB,KAAK,OAAO;AAAA,EACxD;AAAA,EAEQ,QAAc;AACpB,QAAI,KAAK,YAAY,QAAQ,OAAO,0BAA0B,YAAa;AAC3E,SAAK,SAAS;AACd,SAAK,UAAU,sBAAsB,CAAC,QAAQ,KAAK,KAAK,GAAG,CAAC;AAAA,EAC9D;AAAA,EAEQ,OAAa;AACnB,QAAI,KAAK,YAAY,MAAM;AACzB,2BAAqB,KAAK,OAAO;AACjC,WAAK,UAAU;AAAA,IACjB;AAEA,SAAK,QAAQ,KAAK;AAAA,EACpB;AAAA,EAEQ,KAAK,KAAmB;AAC9B,SAAK,UAAU,sBAAsB,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;AACxD,QAAI,KAAK,WAAW,EAAG,MAAK,SAAS;AACrC,SAAK,QAAQ,MAAM,KAAK,SAAS,KAAK;AACtC,SAAK,YAAY,KAAK,OAAO,KAAK,IAAI;AAAA,EACxC;AAAA,EAEQ,eAAe,GAAiB;AACtC,UAAM,EAAE,KAAK,GAAG,EAAE,IAAI;AACtB,UAAM,KAAK,KAAK,QAAQ;AACxB,QAAI,CAAC,MAAM,GAAG,SAAS,SAAS;AAC9B,UAAI,YAAY,IAAI,SAAS;AAC7B,UAAI,SAAS,GAAG,GAAG,GAAG,CAAC;AACvB;AAAA,IACF;AACA,QAAI,GAAG,SAAS,SAAS;AACvB,WAAK,UAAU,IAAI,CAAC;AACpB;AAAA,IACF;AACA,UAAM,IAAI,IAAI,qBAAqB,GAAG,GAAG,GAAG,CAAC;AAC7C,UAAM,QAAQ,GAAG;AACjB,aAAS,IAAI,GAAG,IAAI,GAAG,MAAM,QAAQ,KAAK;AACxC,YAAM,IAAI,GAAG,MAAM,CAAC;AACpB,UAAI,KAAK,EAAE;AACX,UAAI,OAAO;AACT,cAAM,SAAS,MAAM,UAAU;AAC/B,cAAM,QAAS,IAAI,GAAG,MAAM,SAAU,KAAK,KAAK;AAChD,aAAK,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,SAAS,KAAK,IAAK,IAAI,IAAI,KAAK,KAAM,MAAM,SAAS,KAAK,CAAC,CAAC;AAAA,MAChG;AACA,QAAE,aAAa,IAAI,EAAE,KAAK;AAAA,IAC5B;AACA,QAAI,YAAY;AAChB,QAAI,SAAS,GAAG,GAAG,GAAG,CAAC;AACvB,QAAI,GAAG,MAAM;AACX,UAAI,YAAY,GAAG,KAAK;AACxB,YAAM,KAAK,GAAG,KAAK,UAAU,KAAK,QAAQ,UAAU,OAAO,IAAI,KAAK,IAAI,GAAG,CAAC;AAC5E,UAAI,SAAS,GAAG,IAAI,IAAI,GAAG,EAAE;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,UAAU,IAAqB,GAAiB;AACtD,UAAM,EAAE,KAAK,GAAG,EAAE,IAAI;AACtB,UAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AACxC,UAAM,OAAO,KAAK,IAAI,GAAG,KAAK,MAAO,KAAK,iBAAiB,IAAK,KAAK,CAAC;AACtE,UAAM,OAAO,KAAK,IAAI,GAAG,KAAK,MAAO,KAAK,iBAAiB,IAAK,KAAK,CAAC;AACtE,UAAM,KAAK,gBAAgB,IAAI,CAAC;AAIhC,UAAM,MAAM,GAAG,KAAK,UAAU,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AACjE,QAAI,SAAS,KAAK;AAClB,QAAI,CAAC,UAAU,OAAO,QAAQ,KAAK;AACjC,UAAI,CAAC,UAAU,OAAO,SAAS,QAAQ,OAAO,SAAS,MAAM;AAC3D,cAAM,SAA8C,OAAO,aAAa,cACpE,SAAS,cAAc,QAAQ,IAC/B,IAAI,gBAAgB,MAAM,IAAI;AAClC,eAAO,QAAQ;AACf,eAAO,SAAS;AAChB,cAAM,OAAO,OAAO,WAAW,IAAI;AACnC,YAAI,CAAC,KAAM;AACX,iBAAS,EAAE,QAAQ,KAAK,MAAM,MAAM,MAAM,KAAK,GAAG;AAAA,MACpD;AACA,YAAM,MAAM,OAAO,IAAI,gBAAgB,MAAM,IAAI;AACjD,YAAM,OAAO,IAAI;AACjB,YAAM,OAAO,KAAK;AAClB,UAAI,IAAI;AACR,eAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAE7B,cAAM,KAAM,IAAI,OAAO,IAAK,OAAO;AACnC,iBAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,gBAAM,KAAM,IAAI,OAAO,IAAK,OAAO;AACnC,gBAAM,MAAM,WAAW,GAAG,GAAG,IAAI,IAAI,IAAI;AACzC,eAAK,GAAG,IAAI,IAAI,CAAC;AACjB,eAAK,GAAG,IAAI,IAAI,CAAC;AACjB,eAAK,GAAG,IAAI,IAAI,CAAC;AACjB,eAAK,GAAG,IAAI;AAAA,QACd;AAAA,MACF;AACA,aAAO,IAAI,aAAa,KAAK,GAAG,CAAC;AACjC,aAAO,MAAM;AACb,WAAK,QAAQ;AAAA,IACf;AACA,UAAM,SAAS,KAAK,MAAM,GAAG,YAAY,GAAG,MAAM,MAAM,IAAI;AAC5D,UAAM,OAAO,IAAI;AACjB,QAAI,wBAAwB;AAC5B,QAAI,UAAU,OAAO,QAAQ,GAAG,GAAG,GAAG,CAAC;AACvC,QAAI,wBAAwB;AAAA,EAC9B;AAAA;AAAA;AAAA,EAIQ,UAAU,GAAW,GAAW,SAAiE;AACvG,UAAM,IAAI,WAAW,GAAG,GAAG,KAAK,GAAG,KAAK,CAAC;AACzC,QAAI,WAAW,EAAE,aAAa;AAC5B,YAAM,KAAK,WAAW,SAAS,GAAG,KAAK,GAAG,KAAK,CAAC;AAChD,QAAE,KAAK,GAAG;AACV,QAAE,KAAK,GAAG;AAAA,IACZ;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,gBAAgB,OAA6B;AACnD,UAAM,IAAI,MAAM,MAAM;AACtB,QAAI,EAAE,SAAS,WAAW,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,QAAS,QAAO;AACtE,UAAM,MAAM,EAAE,OAAO;AACrB,UAAM,SAAS,KAAK,OAAO,KAAK,CAAC,MAAM,EAAE,MAAM,QAAQ,GAAG;AAC1D,WAAO,QAAQ,SAAS,CAAC,KAAK;AAAA,EAChC;AAAA,EAEQ,UAAU,OAAc,GAAW,GAAW,OAAe,SAA8B;AACjG,UAAM,QAAQ,MAAM,MAAM;AAC1B,QAAI,CAAC,MAAO;AACZ,UAAM,EAAE,KAAK,GAAG,EAAE,IAAI;AACtB,UAAM,YAAY,QAAQ,GAAG,CAAC,IAAI;AAClC,UAAM,WAAW,OAAO,GAAG,CAAC;AAC5B,UAAM,SAAS,MAAM,MAAM;AAC3B,UAAM,SAAS,eAAe,MAAM,KAAK,OAAO,SAAS;AACzD,UAAM,SAAS,OAAO,SAAS,YAAY,CAAC,CAAC,OAAO;AACpD,UAAM,aAAa,OAAO,SAAS,YAAY,CAAC,OAAO;AACvD,UAAM,SAAS,cAAc,KAAK,cAAc,KAAK;AACrD,UAAM,QAAQ,CAAC,OAAyC,KAAK,UAAU,GAAG,IAAI,OAAO;AAIrF,UAAM,OAAO,UAAU,aAAa,IAAI,gBAAgB,MAAM,SAAS,MAAM;AAC7E,UAAM,SAAS,YAAY,OAAO,GAAG,WAAW,UAAU,OAAO,GAAG,GAAG,MAAM,MAAM,SAAS,OAAO,MAAM,GAAG,MAAM,MAAM,UAAU,SAAS;AAC3I,QAAI,OAAO,WAAW,EAAG;AACzB,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,YAAY;AAEd,YAAM,KAAK,KAAK,aAAa,IAAI,KAAK;AACtC,UAAI,OAAO;AACX,UAAI,KAAK,WAAW;AACpB,iBAAW,MAAM,QAAQ;AACvB,WAAG,QAAQ,KAAK,MAAM,GAAG,IAAI,KAAK,GAAG,GAAG,IAAI,KAAK,CAAC,KAAK,KAAK,GAAG;AAC/D,eAAO;AACP,aAAK,GAAG;AAAA,MACV;AAAA,IACF;AAIA,QAAI,QAAQ;AACV,iBAAW,MAAM,OAAQ,MAAK,WAAW,OAAO,GAAG,GAAG,GAAG,GAAG,SAAS,QAAW,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,GAAG,MAAM,CAAC;AACrI;AAAA,IACF;AACA,UAAM,gBAAgB,eAAe,MAAM,IACtC,OAAO,SAAS,EAAE,UAAU,KAAK,OAAO,QACzC,OAAO,SAAS,UAAU,OAAO,SAAS,cAAe,OAAO,SAAS,YAAa;AAC1F,QAAI,QAAQ;AAUV,YAAM,MAAuC,CAAC,IAAI;AAClD,YAAM,QAAkB,CAAC,WAAW,CAAC;AACrC,YAAM,SAAmB,CAAC,SAAS;AACnC,UAAI,QAAQ;AACZ,iBAAW,MAAM,QAAQ;AACvB,cAAM,KAAK,IAAI,IAAI,SAAS,CAAC;AAC7B,cAAM,KAAK,MAAM,MAAM,SAAS,CAAC;AACjC,cAAM,KAAK,OAAO,OAAO,SAAS,CAAC;AACnC,cAAM,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,KAAK,KAAK,MAAM,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AACzF,iBAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,gBAAM,IAAI,IAAI;AACd,cAAI,KAAK,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,CAAC;AAC1C,gBAAM,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC;AAC/B,iBAAO,KAAK,MAAM,GAAG,QAAQ,MAAM,CAAC;AAAA,QACtC;AACA,YAAI,KAAK,EAAE;AACX,cAAM,KAAK,GAAG,CAAC;AACf,eAAO,KAAK,GAAG,KAAK;AACpB,gBAAQ,GAAG;AAAA,MACb;AACA,YAAM,EAAE,MAAM,MAAM,IAAI,YAAY,KAAK,KAAK;AAC9C,UAAI,YAAY;AAChB,YAAM,MAAM,KAAK,IAAI,MAAO,YAAY,IAAI;AAC5C,UAAI,OAAO;AACX,aAAO,OAAO,IAAI,SAAS,GAAG;AAC5B,cAAM,KAAK,OAAO,OAAO,CAAC;AAC1B,YAAI,KAAK,OAAO;AAChB,YAAI,MAAM;AACV,eAAO,KAAK,IAAI,SAAS,KAAK,KAAK,IAAI,OAAO,KAAK,CAAC,IAAK,EAAE,KAAK,KAAK;AAAE,iBAAO,OAAO,KAAK,CAAC;AAAI;AAAA,QAAM;AACrG,YAAI,cAAc,OAAO,KAAK;AAC9B,YAAI,UAAU;AACd,YAAI,OAAO,KAAK,IAAI,EAAG,GAAG,KAAK,IAAI,EAAG,CAAC;AACvC,iBAAS,IAAI,OAAO,GAAG,KAAK,IAAI,IAAK,KAAI,OAAO,KAAK,CAAC,EAAG,GAAG,KAAK,CAAC,EAAG,CAAC;AACtE,iBAAS,IAAI,IAAI,KAAK,MAAM,IAAK,KAAI,OAAO,MAAM,CAAC,EAAG,GAAG,MAAM,CAAC,EAAG,CAAC;AACpE,YAAI,UAAU;AACd,YAAI,KAAK;AACT,eAAO;AAAA,MACT;AACA;AAAA,IACF;AACA,eAAW,MAAM,QAAQ;AACvB,UAAI,cAAc,GAAG;AACrB,UAAI,QAAQ;AACV,cAAM,IAAI,IAAI,qBAAqB,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAClE,UAAE,aAAa,GAAG,aAAa;AAC/B,UAAE,aAAa,MAAM,UAAU,eAAe,IAAI,CAAC;AACnD,UAAE,aAAa,GAAG,UAAU,eAAe,CAAC,CAAC;AAC7C,YAAI,YAAY;AAAA,MAClB,OAAO;AACL,YAAI,YAAY;AAAA,MAClB;AACA,UAAI,UAAU;AACd,UAAI,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,KAAK,CAAC;AACxC,UAAI,KAAK;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,cAAc,OAAuB;AAC3C,QAAI,KAAK,KAAK,aAAa,IAAI,KAAK;AACpC,QAAI,CAAC,IAAI;AACP,WAAK,EAAE,KAAK,KAAK,UAAU,MAAM,GAAG,QAAQ,KAAK;AACjD,WAAK,aAAa,IAAI,OAAO,EAAE;AAAA,IACjC;AACA,QAAI,GAAG,QAAQ,KAAK,UAAU;AAC5B,YAAM,SAAS,MAAM,KAAK,IAAI,KAAK;AACnC,UAAI,GAAG,UAAU,GAAG,OAAO,OAAQ,IAAG,SAAS;AAAA,eACtC,CAAC,GAAG,UAAU,GAAG,OAAO,MAAM,OAAQ,IAAG,SAAS;AAC3D,SAAG,MAAM,KAAK;AACd,SAAG,OAAO;AAAA,IACZ;AACA,WAAO,GAAG;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,SAAS,QAAuB;AACtC,UAAM,MAAM,aAAa,MAAM;AAC/B,QAAI,OAAO,KAAK,UAAU,IAAI,GAAG;AACjC,QAAI,MAAM;AACR,WAAK,UAAU,OAAO,GAAG;AACzB,WAAK,UAAU,IAAI,KAAK,IAAI;AAC5B,aAAO;AAAA,IACT;AACA,QAAI,KAAK,UAAU,QAAQ,eAAe;AACxC,YAAM,CAAC,QAAQ,GAAG,IAAI,KAAK,UAAU,QAAQ,EAAE,KAAK,EAAE;AACtD,iBAAW,OAAO,IAAI,QAAQ,OAAO,EAAG,MAAK,kBAAkB,IAAI;AACnE,WAAK,UAAU,OAAO,MAAM;AAAA,IAC9B;AACA,WAAO,EAAE,SAAS,oBAAI,IAAI,GAAG,SAAS,GAAG,KAAK,MAAM;AACpD,SAAK,UAAU,IAAI,KAAK,IAAI;AAC5B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUiB,aAAa,oBAAI,IAA2D;AAAA,EACrF,cAAc,OAAc,QAAgC;AAClE,UAAM,MAAM,aAAa,MAAM;AAC/B,UAAM,KAAK,KAAK,OAAO,QAAQ,KAAK;AACpC,UAAM,OAAO,KAAK,WAAW,IAAI,EAAE;AACnC,QAAI,QAAQ,KAAK,QAAQ,KAAK,YAAY,KAAK,QAAQ,IAAK,QAAO,KAAK;AACxE,UAAM,SAAS,SAAS,UAAa,KAAK,QAAQ;AAClD,SAAK,WAAW,IAAI,IAAI,EAAE,KAAK,KAAK,KAAK,UAAU,OAAO,CAAC;AAC3D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,aAAa,GAAiE,QAAuBA,QAAe,IAAgB,GAAiB;AAC3J,UAAM,OAAO,KAAK,SAAS,MAAM;AACjC,UAAM,QAAQ,UAAU,MAAM;AAC9B,QAAI,CAAC,KAAK,QAAS,MAAK,UAAU,MAAM,IAAI,OAAO,CAAC,EAAE;AAEtD,QAAI,GAAG,MAAM,GAAG,GAAI,GAAE,UAAU,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,KAAK,GAAG,EAAE;AAC9D,MAAE,MAAM,GAAG,IAAI,GAAG,EAAE;AACpB,UAAM,KAAK,EAAE;AACb,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,OAAO,MAAM,CAAC;AACpB,YAAM,QAAQ,KAAK,QAAQ,CAAC;AAC5B,YAAM,KAAK,KAAK,SAASA;AACzB,UAAI,KAAK,QAAQ,KAAK,KAAK,OAAO,UAAU,GAAG;AAC7C,UAAE,cAAc,KAAK,KAAK;AAC1B,YAAI,KAAK,UAAU,UAAU,QAAQ;AAEnC,gBAAM,EAAE,IAAI,IAAI,IAAI,GAAG,IAAI,KAAK;AAChC,cAAI,MAAM,aAAa,QAAW;AAChC,kBAAM,WAAW,OAAO,WAAW,cAAc,OAAO,WAAW,CAAC,EAAE,QAAQ,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,MAAM,KAAK,IAAI,MAAM,EAAE,CAAqB,GAAG,QAAQ,KAAK,CAAC,CAAC;AAAA,UACrL;AACA,YAAE,KAAK;AACP,YAAE,UAAU,IAAI,GAAG,GAAG,IAAI,IAAI,EAAE;AAChC,YAAE,YAAY,iBAAiB,GAAG,KAAK,QAAQ;AAC/C,cAAI,MAAM,SAAU,GAAE,KAAK,MAAM,UAAU,KAAK,IAAI;AAAA,eAC/C;AAAE,uBAAW,GAAG,CAAC,EAAE,QAAQ,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,MAAM,KAAK,IAAI,MAAM,EAAE,CAAqB,GAAG,QAAQ,KAAK,CAAC,CAAC;AAAG,cAAE,KAAK,KAAK,IAAI;AAAA,UAAG;AAC3J,YAAE,QAAQ;AAAA,QACZ,OAAO;AACL,YAAE,YAAY,KAAK,WAAW,iBAAiB,GAAG,KAAK,QAAQ,IAAI,OAAO,QAAQ,CAAC,OAAO,QAAQ,SAAS,GAAG,IAAI,CAAC,IAAI;AACvH,cAAI,MAAM,SAAS,OAAW,OAAM,OAAO,OAAO,WAAW,cAAc,OAAO,WAAW,CAAC,EAAE,QAAQ,KAAK,KAAK,QAAQ,QAAQ,KAAK,CAAC,CAAC;AACzI,cAAI,MAAM,KAAM,GAAE,KAAK,MAAM,MAAM,KAAK,IAAI;AAAA,eACvC;AAAE,uBAAW,GAAG,CAAC,EAAE,QAAQ,KAAK,KAAK,QAAQ,QAAQ,KAAK,CAAC,CAAC;AAAG,cAAE,KAAK,KAAK,IAAI;AAAA,UAAG;AAAA,QACzF;AAAA,MACF;AACA,YAAM,KAAK,KAAK;AAChB,UAAI,MAAM,KAAK,KAAK,MAAM,QAAQ;AAChC,UAAE,cAAc,KAAK,KAAK,WAAW,GAAG,WAAW;AACnD,UAAE,cAAc,GAAG;AACnB,UAAE,WAAW,GAAG,QAAQ;AACxB,UAAE,UAAU,GAAG,OAAO;AACtB,YAAI,GAAG,SAAS;AAEd,YAAE,YAAa,GAAG,QAAQ,IAAK,GAAG;AAClC,cAAI,MAAM,WAAW,OAAW,OAAM,SAAS,OAAO,WAAW,cAAc,OAAO,WAAW,KAAK,KAAK,KAAK;AAChH,cAAI,MAAM,OAAQ,GAAE,OAAO,MAAM,MAAM;AAAA,eAClC;AAAE,uBAAW,GAAG,KAAK,KAAK,KAAK;AAAG,cAAE,OAAO;AAAA,UAAG;AAAA,QACrD,OAAO;AAGL,gBAAM,SAAS,KAAK,KAAK,MAAM,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,QAAQ,EAAE,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE,CAAqB,EAAE,EAAE;AAC9I,YAAE,KAAK;AACP,YAAE,MAAM,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE;AAC5B,YAAE,YAAY,GAAG,QAAQ;AACzB,qBAAW,GAAG,MAAM;AACpB,YAAE,OAAO;AACT,YAAE,QAAQ;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AACA,MAAE,cAAc;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,SAAS,QAAuB,GAA6B,GAAW,KAAaA,QAAe,IAAyB;AACnI,UAAM,MAAM,KAAK;AACjB,UAAM,OAAO,KAAK,SAAS,MAAM;AACjC,QAAI,KAAK,IAAK,QAAO;AACrB,QAAI,KAAK,OAAQ,QAAO,KAAK,WAAW,QAAQ,MAAM,GAAG,GAAG,KAAKA,QAAO,EAAE;AAC1E,UAAM,IAAI,IAAI,aAAa;AAG3B,QAAI,KAAK,IAAI,EAAE,CAAC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC,IAAI,QAAQ,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,QAAQ,EAAE,EAAE,IAAI,IAAI;AAC5F,WAAK,SAAS;AACd,aAAO,KAAK,WAAW,QAAQ,MAAM,GAAG,GAAG,KAAKA,QAAO,EAAE;AAAA,IAC3D;AACA,UAAM,IAAI,EAAE;AACZ,UAAM,KAAK,IAAI,EAAE,IAAI,EAAE;AACvB,UAAM,KAAK,IAAI,EAAE,IAAI,EAAE;AACvB,UAAM,KAAK,KAAK,MAAM,EAAE;AACxB,UAAM,KAAK,KAAK,MAAM,EAAE;AACxB,UAAM,KAAK,KAAK,OAAO,KAAK,MAAM,CAAC,IAAI;AACvC,UAAM,KAAK,KAAK,OAAO,KAAK,MAAM,CAAC,IAAI;AACvC,UAAM,MAAM,GAAGA,MAAK,KAAK,IAAI,GAAG,QAAQ,CAAC,CAAC,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC,CAAC,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC,CAAC,IAAI,GAAG,EAAE,IAAI,GAAG,EAAE,IAAI,IAAI,QAAQ,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE;AAC9I,QAAI,MAAM,KAAK,QAAQ,IAAI,GAAG;AAC9B,QAAI,CAAC,KAAK;AACR,UAAI,KAAK,QAAQ,QAAQ,sBAAsB;AAC7C,mBAAW,OAAO,KAAK,QAAQ,OAAO,EAAG,MAAK,kBAAkB,IAAI;AACpE,aAAK,QAAQ,MAAM;AAGnB,YAAI,EAAE,KAAK,UAAU,GAAG;AAAE,eAAK,SAAS;AAAM,eAAK,UAAU;AAAG,iBAAO,KAAK,WAAW,QAAQ,MAAM,GAAG,GAAG,KAAKA,QAAO,EAAE;AAAA,QAAG;AAAA,MAC9H;AACA,YAAM,IAAI,KAAK,IAAI,GAAG;AACtB,YAAM,KAAK,KAAK,IAAI,GAAG;AACvB,YAAM,IAAI,IAAI;AACd,UAAI,KAAK,UAAU,KAAK,WAAW,KAAK,UAAU,KAAK;AACvD,YAAM,OAAO,CAAC,MAA8B;AAC1C,cAAM,MAAM,EAAE,CAAC,IAAI,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,GAAG,MAAM,GAAG,KAAK;AACrE,cAAM,IAAI,KAAK,IAAI,KAAK;AACxB,cAAM,IAAI,KAAK,KAAK,KAAK;AACzB,YAAI,IAAI,GAAI,MAAK;AAAG,YAAI,IAAI,GAAI,MAAK;AAAG,YAAI,IAAI,GAAI,MAAK;AAAG,YAAI,IAAI,GAAI,MAAK;AAAA,MAC/E;AACA,UAAI,KAAK;AACT,iBAAW,QAAQ,UAAU,MAAM,GAAG;AACpC,YAAI,KAAK,KAAM,YAAW,KAAK,KAAK,KAAK,OAAQ,MAAK,CAAC;AACvD,YAAI,KAAK,QAAQ;AAAE,eAAK,KAAK,IAAI,IAAI,KAAK,OAAO,KAAK;AAAG,qBAAW,KAAK,KAAK,KAAK,MAAO,YAAW,KAAK,EAAE,OAAQ,MAAK,CAAC;AAAA,QAAG;AAAA,MAC/H;AACA,YAAM,MAAM,IAAI,KAAK,KAAK,KAAK,CAAC;AAChC,YAAM,KAAK,KAAK,MAAM,KAAK,EAAE,IAAI;AACjC,YAAM,KAAK,KAAK,MAAM,KAAK,EAAE,IAAI;AACjC,YAAM,IAAI,KAAK,KAAK,KAAK,EAAE,IAAI,KAAK;AACpC,YAAM,IAAI,KAAK,KAAK,KAAK,EAAE,IAAI,KAAK;AACpC,UAAI,EAAE,IAAI,KAAK,IAAI,MAAM,CAAC,OAAO,SAAS,IAAI,CAAC,EAAG,QAAO;AACzD,UAAI,aAAa,MAAM,KAAM,IAAI,IAAK,OAAO,uBAAuB;AAAE,aAAK,MAAM;AAAM,eAAO;AAAA,MAAO;AACrG,UAAI,KAAK,iBAAiB,IAAI,IAAI,qBAAsB,QAAO;AAC/D,YAAM,OAAO,KAAK,WAAW,CAAC;AAC9B,UAAI,CAAC,KAAM,QAAO;AAClB,WAAK,OAAO,QAAQ;AACpB,WAAK,OAAO,SAAS;AACrB,YAAM,IAAI,KAAK;AACf,QAAE,aAAa,GAAG,GAAG,GAAG,GAAG,KAAK,IAAI,KAAK,EAAE;AAC3C,UAAI,IAAK,GAAE,OAAO,GAAG;AACrB,WAAK,aAAa,GAAG,QAAQA,QAAO,IAAI,CAAC;AACzC,YAAM,EAAE,QAAQ,KAAK,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AACvD,WAAK,kBAAkB,IAAI;AAC3B,WAAK,QAAQ,IAAI,KAAK,GAAG;AAAA,IAC3B;AACA,QAAI,KAAK;AACT,QAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACjC,QAAI,UAAU,IAAI,QAAQ,KAAK,IAAI,IAAI,KAAK,IAAI,EAAE;AAClD,QAAI,QAAQ;AACZ,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,WAAW,QAAuB,MAA0D,GAA6B,GAAW,KAAaA,QAAe,IAAyB;AAC/L,UAAM,MAAM,KAAK;AAEjB,QAAI,CAAC,GAAG,WAAW,GAAG,OAAO,EAAG,QAAO;AACvC,UAAM,IAAI,IAAI,aAAa;AAC3B,UAAM,IAAI,KAAK,KAAK,KAAK,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AACnD,UAAM,IAAI,IAAI;AACd,QAAI,EAAE,KAAK,GAAI,QAAO;AACtB,UAAM,SAAS,MAAM,KAAK,KAAK,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI;AACnD,UAAM,MAAM,KAAKA,MAAK,IAAI,OAAO,QAAQ,CAAC,CAAC;AAC3C,QAAI,MAAM,KAAK,QAAQ,IAAI,GAAG;AAC9B,QAAI,CAAC,KAAK;AACR,UAAI,KAAK,QAAQ,QAAQ,wBAAwB;AAC/C,mBAAW,OAAO,KAAK,QAAQ,OAAO,EAAG,MAAK,kBAAkB,IAAI;AACpE,aAAK,QAAQ,MAAM;AACnB,YAAI,EAAE,KAAK,UAAU,GAAG;AAAE,eAAK,MAAM;AAAM,iBAAO;AAAA,QAAO;AAAA,MAC3D;AACA,UAAI,KAAK,UAAU,KAAK,WAAW,KAAK,UAAU,KAAK,WAAW,KAAK;AACvE,YAAM,OAAO,CAACC,OAA8B;AAAE,YAAIA,GAAE,CAAC,IAAI,GAAI,MAAKA,GAAE,CAAC;AAAG,YAAIA,GAAE,CAAC,IAAI,GAAI,MAAKA,GAAE,CAAC;AAAG,YAAIA,GAAE,CAAC,IAAI,GAAI,MAAKA,GAAE,CAAC;AAAG,YAAIA,GAAE,CAAC,IAAI,GAAI,MAAKA,GAAE,CAAC;AAAA,MAAG;AACtJ,iBAAW,QAAQ,UAAU,MAAM,GAAG;AACpC,YAAI,KAAK,KAAM,YAAWA,MAAK,KAAK,KAAK,OAAQ,MAAK,CAACA,GAAE,CAAC,IAAI,GAAG,IAAIA,GAAE,CAAC,IAAI,GAAG,EAAE,CAAC;AAClF,YAAI,KAAK,QAAQ;AAAE,eAAK,KAAK,IAAI,IAAI,KAAK,OAAO,KAAK;AAAG,qBAAW,KAAK,KAAK,KAAK,MAAO,YAAWA,MAAK,EAAE,OAAQ,MAAK,CAACA,GAAE,CAAC,IAAI,GAAG,IAAIA,GAAE,CAAC,IAAI,GAAG,EAAE,CAAC;AAAA,QAAG;AAAA,MAC1J;AACA,YAAM,MAAM,IAAI,KAAK,KAAK,KAAK,MAAM;AACrC,YAAM,KAAK,KAAK,KAAK,CAAC,KAAK,MAAM,IAAI;AACrC,YAAM,KAAK,KAAK,KAAK,CAAC,KAAK,MAAM,IAAI;AACrC,YAAM,IAAI,KAAK,KAAK,KAAK,KAAK,MAAM,IAAI;AACxC,YAAM,IAAI,KAAK,KAAK,KAAK,KAAK,MAAM,IAAI;AACxC,UAAI,EAAE,IAAI,KAAK,IAAI,MAAM,CAAC,OAAO,SAAS,IAAI,CAAC,EAAG,QAAO;AACzD,UAAI,IAAI,IAAI,wBAAwB;AAAE,aAAK,MAAM;AAAM,eAAO;AAAA,MAAO;AACrE,UAAI,KAAK,iBAAiB,IAAI,IAAI,qBAAsB,QAAO;AAC/D,YAAM,OAAO,KAAK,WAAW,CAAC;AAC9B,UAAI,CAAC,KAAM,QAAO;AAClB,WAAK,OAAO,QAAQ;AACpB,WAAK,OAAO,SAAS;AACrB,WAAK,IAAI,aAAa,GAAG,GAAG,GAAG,GAAG,IAAI,EAAE;AACxC,WAAK,aAAa,KAAK,KAAK,QAAQD,QAAO,EAAE,IAAI,QAAQ,IAAI,QAAQ,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,SAAS,KAAK,GAAG,MAAM;AAElH,YAAM,EAAE,QAAQ,KAAK,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AACvD,WAAK,kBAAkB,IAAI;AAC3B,WAAK,QAAQ,IAAI,KAAK,GAAG;AAAA,IAC3B;AACA,UAAM,IAAI,IAAI;AACd,QAAI,KAAK;AACT,QAAI,UAAU,EAAE,GAAG,EAAE,CAAC;AACtB,QAAI,IAAK,KAAI,OAAO,GAAG;AACvB,QAAI,wBAAwB;AAC5B,QAAI,UAAU,IAAI,QAAQ,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,IAAI,OAAO,QAAQ,GAAG,IAAI,OAAO,SAAS,CAAC;AAC/F,QAAI,QAAQ;AACZ,WAAO;AAAA,EACT;AAAA,EAEQ,WAAW,GAAsI;AACvJ,QAAI;AACF,YAAM,SAAS,OAAO,aAAa,cAAc,SAAS,cAAc,QAAQ,IAAI,IAAI,gBAAgB,GAAG,CAAC;AAC5G,aAAO,QAAQ;AACf,aAAO,SAAS;AAChB,YAAM,IAAI,OAAO,WAAW,IAAI;AAChC,aAAO,IAAI,EAAE,QAAQ,KAAK,EAAE,IAAI;AAAA,IAClC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBQ,YAAY,GAAW,GAA6B,IAAY,IAAY,KAAaA,QAAe,SAA0B;AACxI,UAAM,MAAM,KAAK;AACjB,UAAM,IAAI,OAAO,IAAI,iBAAiB,aAAa,IAAI,aAAa,IAAI;AACxE,QAAI,CAAC,KAAK,EAAE,MAAM,KAAK,EAAE,MAAM,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,EAAG,QAAO;AACjE,UAAM,MAAM,KAAK,IAAI,KAAK,IAAI,GAAG,CAAC;AAClC,UAAM,MAAM,KAAK,IAAI,KAAK,IAAI,GAAG,CAAC;AAClC,UAAM,KAAK,KAAK,MAAM,MAAM,KAAK,MAAM,MAAM,EAAE,CAAC,IAAI;AACpD,UAAM,KAAK,KAAK,MAAM,MAAM,KAAK,MAAM,MAAM,EAAE,CAAC,IAAI;AACpD,UAAM,WAAW,GAAG,OAAO,IAAI,KAAK,MAAM,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,MAAM,GAAI,CAAC,IAAI,EAAE,IAAI,EAAE;AACzH,QAAI,IAAI,KAAK,aAAa,IAAI,CAAC;AAC/B,QAAI,CAAC,KAAK,EAAE,aAAa,UAAU;AAKjC,UAAI,GAAG;AACL,YAAI,EAAE,YAAY,UAAU;AAAE,YAAE,UAAU;AAAU,YAAE,SAAS,KAAK;AAAA,QAAU;AAC9E,YAAI,EAAE,WAAW,KAAK,SAAU,QAAO;AAAA,MACzC;AACA,YAAM,KAAK,KAAK;AAChB,YAAM,QAAQ,KAAK,EAAE,MAAM,MAAM,EAAE,MAAM;AACzC,UAAI,CAAC,SAAS,KAAK,gBAAgB,MAAM,IAAI,EAAE,IAAI,EAAE,IAAI,KAAK,IAAW,QAAO;AAChF,YAAM,QAAQ,KAAK,aAAa,IAAI,OAAO;AAC3C,UAAI,CAAC,MAAO,QAAO;AACnB,YAAM,KAAK,QAAQ,EAAG,QAAQ,KAAK,WAAW,CAAC;AAC/C,YAAM,KAAK,QAAQ,EAAG,OAAO,KAAK,WAAW,CAAC;AAC9C,UAAI,CAAC,MAAM,CAAC,GAAI,QAAO;AACvB,UAAI,CAAC,OAAO;AACV,WAAG,OAAO,QAAQ;AAAI,WAAG,OAAO,SAAS;AACzC,WAAG,OAAO,QAAQ;AAAI,WAAG,OAAO,SAAS;AACzC,aAAK,iBAAiB,MAAM,IAAI,EAAE,IAAI,EAAE,IAAI;AAAA,MAC9C;AACA,YAAM,KAAK,GAAG;AACd,SAAG,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAChC,SAAG,UAAU,GAAG,GAAG,IAAI,EAAE;AACzB,SAAG,UAAU,KAAK,GAAG,KAAK,CAAC;AAC3B,SAAG,MAAM,EAAE,GAAG,EAAE,CAAC;AACjB,UAAI,IAAK,IAAG,OAAO,GAAG;AACtB,SAAG,wBAAwB;AAC3B,SAAG,UAAU,OAAO,CAAC,KAAK,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE;AAC5C,SAAG,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAChC,UAAI,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,OAAO,IAAI,MAAM,IAAI,SAAS,IAAI,QAAQ,GAAG,SAAS,KAAK,iBAAiB,GAAG,SAAS,UAAU,QAAQ,KAAK,SAAS;AACtJ,WAAK,aAAa,IAAI,GAAG,CAAC;AAAA,IAC5B;AAKA,QAAI,EAAE,YAAYA,WAAU,EAAE,YAAY,MAAM,KAAK,WAAW,EAAE,UAAU,IAAI;AAC9E,YAAM,KAAK,EAAE,KAAK;AAClB,SAAG,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAChC,SAAG,2BAA2B;AAC9B,SAAG,UAAU,EAAE,MAAM,QAAQ,GAAG,CAAC;AACjC,SAAG,2BAA2B;AAC9B,SAAG,YAAYA;AACf,SAAG,SAAS,GAAG,GAAG,EAAE,GAAG,EAAE,CAAC;AAC1B,SAAG,2BAA2B;AAC9B,QAAE,UAAUA;AACZ,QAAE,SAAS,KAAK,YAAY,EAAE,WAAW;AACzC,QAAE,UAAU;AAAA,IACd;AACA,UAAM,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE;AACzB,UAAM,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE;AACzB,QAAI,KAAK;AACT,QAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACjC,QAAI,UAAU,EAAE,KAAK,QAAQ,KAAK,MAAM,KAAK,EAAE,IAAI,CAAC,GAAG,KAAK,MAAM,KAAK,EAAE,IAAI,CAAC,CAAC;AAC/E,QAAI,QAAQ;AACZ,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaQ,YAAYA,QAAe,SAA6D;AAC9F,UAAM,MAAM,GAAGA,MAAK,IAAI,OAAO;AAC/B,UAAM,MAAM,KAAK,aAAa,IAAI,GAAG;AACrC,QAAI,KAAK;AAEP,WAAK,aAAa,OAAO,GAAG;AAC5B,WAAK,aAAa,IAAI,KAAK,GAAG;AAC9B,aAAO,IAAI;AAAA,IACb;AACA,UAAM,IAAI;AACV,QAAI,QAAQ,KAAK,aAAa,IAAI,OAAO;AACzC,QAAI,CAAC,OAAO;AACV,YAAM,OAAO,KAAK,WAAW,CAAC;AAC9B,UAAI,CAAC,KAAM,QAAO;AAClB,YAAM,MAAM,KAAK,IAAI,gBAAgB,GAAG,CAAC;AACzC,YAAM,OAAO,IAAI;AACjB,YAAM,OAAiB,CAAC;AACxB,eAAS,IAAI,GAAG,IAAI,GAAG,IAAK,MAAK,KAAK,aAAa,IAAI,OAAO,GAAG,OAAO,CAAC;AACzE,UAAI,IAAI;AACR,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,cAAM,KAAK,KAAK,CAAC;AACjB,iBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,eAAK,GAAG,IAAI;AACZ,eAAK,GAAG,IAAI;AACZ,eAAK,GAAG,IAAI;AACZ,eAAK,GAAG,IAAI,KAAK,MAAM,MAAM,KAAK,KAAK,CAAC,CAAE;AAAA,QAC5C;AAAA,MACF;AACA,WAAK,IAAI,aAAa,KAAK,GAAG,CAAC;AAC/B,UAAI,KAAK,aAAa,QAAQ,EAAG,MAAK,aAAa,OAAO,KAAK,aAAa,KAAK,EAAE,KAAK,EAAE,KAAM;AAChG,cAAQ,KAAK;AACb,WAAK,aAAa,IAAI,SAAS,KAAK;AAAA,IACtC;AACA,QAAI,OAAkI;AACtI,QAAI,KAAK,aAAa,QAAQ,IAAI;AAChC,YAAM,SAAS,KAAK,aAAa,KAAK,EAAE,KAAK,EAAE;AAC/C,aAAO,KAAK,aAAa,IAAI,MAAM;AACnC,WAAK,aAAa,OAAO,MAAM;AAAA,IACjC,OAAO;AACL,aAAO,KAAK,WAAW,CAAC;AACxB,UAAI,CAAC,KAAM,QAAO;AAAA,IACpB;AACA,UAAM,OAAO,KAAK;AAClB,SAAK,2BAA2B;AAChC,SAAK,UAAU,OAAO,GAAG,CAAC;AAC1B,SAAK,2BAA2B;AAChC,SAAK,YAAYA;AACjB,SAAK,SAAS,GAAG,GAAG,GAAG,CAAC;AACxB,SAAK,2BAA2B;AAChC,SAAK,aAAa,IAAI,KAAK,IAAI;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,WAAW,OAAc,GAAW,GAAW,OAAe,SAAwB,OAAmB,MAAoE;AACnL,UAAM,EAAE,IAAI,IAAI;AAChB,UAAM,IAAI,OAAO,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,GAAG,MAAM,MAAM,IAAI,KAAK,UAAU,GAAG,GAAG,OAAO;AACrF,UAAM,SAAS,OAAO,UAAU,MAAM,MAAM;AAC5C,UAAM,KAAK,OAAO,KAAK,OAAO,OAAO,GAAG,CAAC;AACzC,UAAM,MAAM,WAAW,GAAG,CAAC;AAC3B,UAAM,YAAY,KAAK,QAAQ,UAAU,OAAO,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,CAAC;AAC3E,QAAI,cAAc,OAAO,KAAK,QAAQ,QAAQ,GAAG,CAAC,IAAI,SAAS,OAAO,SAAS;AAC/E,QAAI,OAAO,SAAS,QAAQ;AAC1B,YAAM,IAAI,KAAK;AACf,YAAM,gBAAgB,OAAO,SAAS,EAAE,UAAU,KAAK,OAAO;AAC9D,UAAI,cAAc;AAClB,UAAI,YAAY,KAAK,IAAI,MAAM,OAAO,UAAU,cAAc,IAAI,IAAI,SAAU,SAAS;AACzF,UAAI,UAAU;AACd,UAAI,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,KAAK,KAAK,CAAC;AACnC,UAAI,OAAO;AACX;AAAA,IACF;AACA,QAAI,OAAO,SAAS,UAAU;AAC5B,YAAM,gBAAgB,OAAO,SAAS,EAAE,UAAU,KAAK,OAAO;AAC9D,YAAM,WAAW,UAAU,GAAG,GAAG,KAAK,GAAG,KAAK,CAAC,KAAK,KAAK;AACzD,YAAM,QAAQ,EAAE,IAAI,KAAK,IAAI,OAAO,IAAI;AACxC,YAAM,QAAQ,EAAE,IAAI,KAAK,IAAI,OAAO,IAAI;AACxC,YAAM,IAAI,IAAI,qBAAqB,OAAO,OAAO,EAAE,GAAG,EAAE,CAAC;AACzD,QAAE,aAAa,GAAG,UAAU,eAAe,CAAC,CAAC;AAC7C,QAAE,aAAa,GAAG,aAAa;AAC/B,UAAI,cAAc;AAClB,UAAI,YAAY,KAAK,IAAI,MAAM,OAAO,UAAU,cAAc,IAAI,IAAI,SAAU,SAAS;AACzF,UAAI,UAAU;AACd,UAAI,UAAU;AACd,UAAI,OAAO,OAAO,KAAK;AACvB,UAAI,OAAO,EAAE,GAAG,EAAE,CAAC;AACnB,UAAI,OAAO;AACX;AAAA,IACF;AACA,QAAI,OAAO,SAAS,QAAQ;AAC1B,YAAM,gBAAgB,OAAO,SAAS,EAAE,UAAU,KAAK,OAAO;AAC9D,YAAM,KAAK,EAAE,UAAU,SACnB,EAAE,SAAS,EAAE,OAAO,IAAI,KAAK,EAAE,OAAO,KACtC;AACJ,YAAM,UAAU,OAAO,WAAW;AAClC,YAAM,OAAO,UAAU,IAAI,KAAK,YAAY,eAAe,OAAO,IAAI;AAEtE,UAAI,QAAQ,KAAK,YAAY,GAAG,GAAG,IAAI,IAAI,KAAK,eAAe,OAAO,EAAG;AACzE,UAAI,KAAK;AACT,UAAI,UAAU,EAAE,GAAG,EAAE,CAAC;AACtB,UAAI,IAAK,KAAI,OAAO,GAAG;AACvB,UAAI,YAAY;AAChB,UAAI,MAAM;AAIR,cAAM,aAAa,IAAI;AACvB,YAAI,wBAAwB;AAC5B,YAAI,UAAU,MAAM,CAAC,KAAK,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE;AAC5C,YAAI,wBAAwB;AAAA,MAC9B,OAAO;AACL,YAAI,SAAS,CAAC,KAAK,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE;AAAA,MACvC;AACA,UAAI,QAAQ;AACZ;AAAA,IACF;AACA,QAAI,OAAO,SAAS,OAAO;AACzB,YAAM,MAAM,KAAK,YAAY,QAAQ,EAAE,YAAY,CAAC;AACpD,UAAI,OAAO,EAAG;AACd,YAAM,gBAAgB,OAAO,SAAS,EAAE,UAAU,KAAK,OAAO;AAC9D,YAAM,KAAK,EAAE,UAAU,SAAY,EAAE,SAAS,EAAE,OAAO,IAAI,KAAK,EAAE,OAAO,KAAK,KAAK;AACnF,YAAM,MAAM,OAAO,OAAO,aAAa,SAAS,KAAK,EAAE;AACvD,UAAI,KAAK;AACT,UAAI,UAAU,EAAE,GAAG,EAAE,CAAC;AACtB,UAAI,IAAK,KAAI,OAAO,GAAG;AACvB,UAAI,YAAY;AAChB,UAAI,SAAS,IAAI,KAAK,IAAI,OAAO,IAAI,KAAK,IAAI,OAAO,IAAI,QAAQ,GAAG,IAAI,QAAQ,CAAC;AACjF,UAAI,QAAQ;AACZ;AAAA,IACF;AACA,QAAI,OAAO,SAAS,WAAW;AAC7B,YAAM,IAAI,KAAK;AACf,YAAM,gBAAgB,OAAO,SAAS,EAAE,UAAU,KAAK,OAAO;AAC9D,UAAI,cAAc,MAAM,GAAG;AACzB,cAAM,KAAK,UAAU,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC;AAC9C,YAAI,aAAa,MAAM,KAAK,wBAAwB,CAAC,KAAK,eAAe,KAAK,cAAc,OAAO,MAAM,KAAK,KAAK,SAAS,QAAQ,GAAG,GAAG,KAAK,eAAe,EAAE,EAAG;AACnK,YAAI,KAAK;AACT,YAAI,UAAU,EAAE,GAAG,EAAE,CAAC;AACtB,YAAI,IAAK,KAAI,OAAO,GAAG;AACvB,YAAI,IAAI,KAAK,GAAG,KAAK,KAAK,GAAG,KAAK,EAAG,MAAK,aAAa,KAAK,QAAQ,eAAe,IAAI,CAAC;AACxF,YAAI,QAAQ;AACZ;AAAA,MACF;AACA,UAAI,KAAK;AACT,UAAI,UAAU,EAAE,GAAG,EAAE,CAAC;AACtB,UAAI,IAAK,KAAI,OAAO,GAAG;AACvB,UAAI,YAAY,OAAO,OAAO,SAAS,KAAK,eAAe,CAAC,IAAI;AAChE,YAAM,MAAM,cAAc,QAAQ,CAAC;AACnC,UAAI,UAAU;AACd,UAAI,OAAO,IAAI,CAAC,EAAG,GAAG,IAAI,CAAC,EAAG,CAAC;AAC/B,eAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,KAAI,OAAO,IAAI,CAAC,EAAG,GAAG,IAAI,CAAC,EAAG,CAAC;AACpE,UAAI,UAAU;AACd,UAAI,KAAK,gBAAgB,MAAM,CAAC;AAChC,UAAI,QAAQ;AACZ;AAAA,IACF;AACA,QAAI,OAAO,SAAS,UAAU;AAC5B,YAAM,gBAAgB,OAAO,SAAS,EAAE,UAAU,KAAK,OAAO;AAC9D,YAAM,MAAM,cAAc,QAAQ,KAAK,CAAC;AACxC,YAAM,KAAK,cAAc,QAAQ,SAAS;AAC1C,UAAI,KAAK;AACT,UAAI,UAAU,EAAE,GAAG,EAAE,CAAC;AACtB,UAAI,QAAQ;AACZ,UAAI,OAAO,OAAQ,UAAS,UAAU,GAAG,GAAG,KAAK,GAAG,KAAK,CAAC,KAAK;AAC/D,UAAI,MAAO,KAAI,OAAO,KAAK;AAC3B,UAAI,cAAc;AAClB,UAAI,UAAU;AACd,UAAI,WAAW;AACf,UAAI,OAAO,OAAO;AAIhB,cAAM,UAAU,cAAc,KAAK,EAAE;AACrC,YAAI,YAAY;AAChB,YAAI,UAAU;AACd,YAAI,OAAO,QAAQ,CAAC,EAAG,GAAG,QAAQ,CAAC,EAAG,CAAC;AACvC,iBAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,IAAK,KAAI,OAAO,QAAQ,CAAC,EAAG,GAAG,QAAQ,CAAC,EAAG,CAAC;AAChF,YAAI,UAAU;AACd,YAAI,KAAK;AAAA,MACX,OAAO;AACL,YAAI,YAAY;AAChB,YAAI,UAAU;AACd,YAAI,OAAO,IAAI,CAAC,EAAG,GAAG,IAAI,CAAC,EAAG,CAAC;AAC/B,iBAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,KAAI,OAAO,IAAI,CAAC,EAAG,GAAG,IAAI,CAAC,EAAG,CAAC;AACpE,YAAI,OAAO;AAAA,MACb;AACA,UAAI,QAAQ;AACZ;AAAA,IACF;AACA,QAAI,OAAO,SAAS,UAAU;AAC5B,YAAM,IAAI,KAAK;AACf,YAAM,gBAAgB,OAAO,SAAS,EAAE,UAAU,KAAK,OAAO;AAC9D,UAAI,KAAK;AACT,UAAI,KAAK;AACP,YAAI,UAAU,EAAE,GAAG,EAAE,CAAC;AACtB,YAAI,OAAO,GAAG;AACd,YAAI,UAAU,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AAAA,MAC1B;AACA,UAAI,OAAO,MAAM;AACf,cAAM,IAAI,IAAI,qBAAqB,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;AAC3D,UAAE,aAAa,GAAG,aAAa;AAC/B,UAAE,aAAa,MAAM,UAAU,eAAe,IAAI,CAAC;AACnD,UAAE,aAAa,GAAG,UAAU,eAAe,CAAC,CAAC;AAC7C,YAAI,YAAY;AAAA,MAClB,OAAO;AACL,YAAI,YAAY;AAAA,MAClB;AACA,UAAI,UAAU;AACd,UAAI,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,KAAK,KAAK,CAAC;AACnC,UAAI,KAAK;AACT,UAAI,QAAQ;AACZ;AAAA,IACF;AACA,QAAI,OAAO,SAAS,aAAa;AAC/B,YAAME,aAAY,KAAK,IAAI,KAAK,GAAG,KAAK,CAAC;AACzC,YAAM,OAAO,OAAO,WAAWA;AAC/B,YAAM,MAAM,OAAO,cAAc,OAAO;AACxC,YAAM,SAAS,OAAO,WAAWA;AACjC,YAAM,SAAS,SAAS;AACxB,YAAM,QAAQ,eAAe,OAAO,MAAM,QAAQ,oBAAoB,OAAO,IAAI,CAAC;AAClF,YAAM,QAAQ,OAAO,SAAS;AAG9B,YAAM,SAAS,OAAO;AACtB,YAAM,KAAK,SAAS,YAAY,OAAO,QAAQ,CAAC,IAAI;AACpD,YAAM,YAAY,KAAK,GAAG,YAAY,MAAM;AAC5C,UAAI,KAAK;AACT,UAAI,UAAU,EAAE,GAAG,EAAE,CAAC;AACtB,UAAI,IAAK,KAAI,OAAO,GAAG;AACvB,UAAI,OAAO,QAAQ;AAKjB,cAAM,WAAW,MAAM,OAAO,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,OAAO,GAAG,CAAC,IAAI;AACrE,cAAM,EAAE,IAAI,GAAG,IAAI,sBAAsB,QAAQ,QAAQ,UAAU,MAAM,SAAS,EAAE;AACpF,YAAI,OAAO,KAAK,OAAO,EAAG,KAAI,UAAU,IAAI,EAAE;AAAA,MAChD;AAEA,UAAI,OAAO,YAAY,OAAW,KAAI,eAAe,OAAO;AAC5D,UAAI,OAAO,OAAO,OAAO,qBAAqB,MAAM,OAAO,IAAI,IAAI,GAAG,IAAI;AAC1E,UAAI,YAAY,OAAO,SAAS;AAChC,UAAI,eAAe;AACnB,UAAI,YAAY;AAChB,YAAM,OAAO,UAAU,WAAW,SAAS,IAAI,UAAU,UAAU,SAAS;AAC5E,UAAI,IAAI,aAAa;AAUnB,YAAI,YAAY;AAChB,cAAM,YAAY,IAAI;AACtB,iBAAS,KAAK,GAAG,KAAK,MAAM,QAAQ,MAAM;AACxC,gBAAM,SAAS,GAAG,YAAY,EAAE,KAAK,CAAC;AACtC,cAAI,OAAO,SAAS,KAAK,OAAO,CAAC,KAAM,EAAG;AAC1C,gBAAM,WAAW,iBAAiB,MAAM,EAAE,EAAG,IAAI;AACjD,gBAAM,KAAK,IAAI,YAAY,MAAM,EAAE,EAAG,IAAI,EAAE;AAC5C,gBAAM,KAAK,UAAU,YAAY,SAAS,MAAM,IAAI,UAAU,UAAU,SAAS,KAAK;AACtF,cAAI,SAAS;AACb,iBAAO,SAAS,SAAS,WAAW,OAAO,MAAM,KAAK,MAAM,EAAG;AAC/D,cAAI,SAAS;AACb,cAAI,SAAS,GAAG;AACd,qBAAS,SAAS,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE;AAC1C,gBAAI,cAAc;AAClB,gBAAI,SAAS,QAAQ,IAAI,KAAK,EAAE;AAAA,UAClC;AACA,mBAAS,KAAK,QAAQ,KAAK,SAAS,QAAQ,MAAM;AAChD,kBAAM,IAAI,OAAO,EAAE,KAAK;AACxB,gBAAI,KAAK,EAAG;AACZ,gBAAI,cAAc,YAAY;AAC9B,gBAAI,SAAS,SAAS,EAAE,GAAI,KAAK,IAAI,YAAY,MAAM,EAAE,OAAO,KAAK,EAAE;AACvE,sBAAU,SAAS,EAAE;AAAA,UACvB;AAAA,QACF;AACA,YAAI,cAAc;AAAA,MACpB,OAAO;AACL,iBAAS,KAAK,GAAG,KAAK,WAAW,MAAM;AACrC,cAAI,SAAS,MAAM,EAAE,EAAG,MAAM,MAAM,KAAK,EAAE;AAAA,QAC7C;AACA,YAAI,MAAM,GAAG,YAAY,SAAS,GAAG;AACnC,cAAI,SAAS,GAAG,aAAa,MAAM,YAAY,EAAE;AAAA,QACnD;AAAA,MACF;AACA,UAAI,MAAM,OAAQ,OAAO;AACvB,cAAM,MAAM,OAAQ,UAAU,OAAO,CAAC,IAAI,OAAQ;AAClD,cAAM,KAAK,KAAK,IAAI,GAAG,IAAI,SAAS,GAAG;AACvC,cAAM,KAAK,MAAM,KAAK,KAAK,MAAO,IAAI,MAAQ,KAAK,CAAC,IAAI,MAAM;AAC9D,YAAI,IAAI;AAIN,gBAAM,KAAK,IAAI,YAAY,GAAG,WAAW,EAAE;AAC3C,gBAAM,KAAK,UAAU,WAAW,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO;AAC3E,cAAI,YAAY,IAAI,SAAS,OAAO,SAAS;AAC7C,cAAI,SAAS,KAAK,OAAO,MAAM,GAAG,YAAY,IAAI,KAAK,IAAI,GAAG,OAAO,IAAI,GAAG,IAAI;AAAA,QAClF;AAAA,MACF;AACA,UAAI,QAAQ;AACZ;AAAA,IACF;AACA,QAAI,KAAK;AACT,QAAI,UAAU,EAAE,GAAG,EAAE,CAAC;AACtB,QAAI,IAAK,KAAI,OAAO,GAAG;AACvB,QAAI,EAAE,QAAQ,MAAM,MAAM,KAAM,KAAI,MAAM,IAAI,CAAC;AAC/C,QAAI,YAAY;AAChB,QAAI,eAAe;AACnB,QAAI,OAAO,SAAS,SAAS;AAC3B,YAAM,MAAM,cAAc,GAAG,GAAG,OAAO,OAAO,MAAM;AACpD,UAAI,OAAO,GAAG,EAAE;AAChB,UAAI,SAAS,OAAO,OAAO,GAAG,KAAK,OAAO,OAAO,CAAC,GAAI,GAAG,CAAC;AAAA,IAC5D,OAAO;AACL,UAAI,YAAY,OAAO,SAAS;AAChC,UAAI,eAAe,OAAO,YAAY;AAGtC,UAAI,OAAO,OAAO,OACb,WAAW,KAAK,OAAO,IAAI,IAC1B,YAAY,OAAO,MAAM,KAAK,UAAU,CAAC,IACzC,qBAAqB,IAAI,OAAO,IAAI,IACtC,GAAG,EAAE;AACT,UAAI,YAAY,OAAO,SAAS;AAChC,YAAM,MAAM,cAAc,GAAG,GAAG,OAAO,QAAQ,MAAM;AACrD,YAAM,OAAO,OAAO,QAAQ,GAAG,KAAK,OAAO,QAAQ,CAAC;AACpD,YAAM,KAAK,OAAO,WAAW,OAAO,YAAY,KAAK,QAAQ,UAAU,OAAO,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,CAAC,KAAK;AAC9G,UAAI,GAAI,KAAI,SAAS,MAAM,GAAG,GAAG,EAAE;AAAA,UAC9B,KAAI,SAAS,MAAM,GAAG,CAAC;AAAA,IAC9B;AACA,QAAI,QAAQ;AAAA,EACd;AAAA;AAAA,EAGQ,eAAe,GAAiB;AACtC,UAAM,KAAK,KAAK;AAChB,QAAI,CAAC,GAAI;AACT,UAAM,IAAI,GAAG,OAAO,IAAI,KAAK,IAAI,GAAG,UAAU,GAAG;AACjD,SAAK,UAAU,KAAK,IAAI,GAAG,KAAK,SAAS,GAAG,MAAM,GAAG,IAAI,WAAW,CAAC,CAAC;AACtE,QAAI,KAAK,EAAG,MAAK,aAAa;AAG9B,UAAM,MAAM,oBAAoB,KAAK,OAAO;AAC5C,QAAI,QAAQ,KAAK,eAAgB,MAAK,QAAQ;AAAA,QACzC,MAAK,OAAO,QAAQ,CAAC,GAAG,MAAM;AAAE,QAAE,QAAQ,KAAK,QAAQ,OAAO,CAAC,KAAK,EAAE;AAAA,IAAO,CAAC;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,OAA2B;AACpC,UAAM,SAAU,OAAO,UAAU,CAAC;AAClC,QAAI,KAAK,UAAU;AACjB,YAAM,QAAQ,OAAO,SAAS,OAAO,OAAO,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,OAAO,iBAAiB,GAAG,CAAC,IAAI;AACpG,UAAI,CAAC,KAAK,iBAAiB,QAAQ,KAAK,SAAS,IAAI,KAAK,EAAG;AAC7D,UAAI,KAAK,OAAQ,MAAK,YAAY,KAAK,SAAS,GAAG,KAAK,IAAI;AAC5D;AAAA,IACF;AACA,UAAM,SAAS,kBAAkB,KAAK,SAAS,MAAM;AACrD,QAAI,CAAC,aAAa,MAAM,EAAE,MAAO;AACjC,UAAM,MAAM,OAAO,SACf,OAAO,OAAO,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,OAAO,iBAAiB,GAAG,CAAC,IAClE;AACJ,SAAK,aAAa;AAAA,MAChB,MAAM,KAAK,MAAM,KAAK,UAAU,KAAK,OAAO,CAAC;AAAA,MAC7C,IAAI;AAAA,MACJ,QAAQ,KAAK;AAAA,MACb;AAAA,IACF;AACA,QAAI,KAAK,QAAQ;AAEf,WAAK,aAAa;AAClB,WAAK,UAAU;AACf,UAAI,oBAAoB,KAAK,OAAO,MAAM,KAAK,eAAgB,MAAK,QAAQ;AAAA,UACvE,MAAK,OAAO,QAAQ,CAAC,GAAG,MAAM;AAAE,UAAE,QAAQ,KAAK,QAAQ,OAAO,CAAC,KAAK,EAAE;AAAA,MAAO,CAAC;AACnF,WAAK,YAAY,KAAK,OAAO,KAAK,IAAI;AAAA,IACxC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,eAAe,QAAoC;AACjD,QAAI,KAAK,UAAU;AAIjB,YAAM,MAAM,CAAC,GAAG,MAAM;AACtB,UAAI,CAAC,KAAK,iBAAiB,KAAK,CAAC,EAAG,YAAW,KAAK,IAAK,MAAK,iBAAiB,CAAC,CAAC,GAAG,CAAC;AACrF,WAAK,aAAa;AAClB,WAAK,cAAc,OAAO;AAC1B;AAAA,IACF;AACA,UAAM,OAAO,oBAAoB,KAAK,SAAS,MAAM;AACrD,QAAI,SAAS,KAAK,QAAS;AAC3B,SAAK,aAAa;AAClB,SAAK,cAAc,OAAO;AAC1B,SAAK,UAAU;AACf,QAAI,oBAAoB,KAAK,OAAO,MAAM,KAAK,eAAgB,MAAK,QAAQ;AAAA,QACvE,MAAK,OAAO,QAAQ,CAAC,GAAG,MAAM;AAAE,QAAE,QAAQ,KAAK,QAAQ,OAAO,CAAC,KAAK,EAAE;AAAA,IAAO,CAAC;AAAA,EACrF;AAAA,EAEQ,UAAU,OAAc,GAAW,OAAe,SAA8B;AACtF,UAAM,EAAE,MAAM,IAAI,MAAM;AACxB,QAAI,CAAC,MAAO;AACZ,UAAM,EAAE,IAAI,IAAI;AAIhB,UAAM,cAAc,CAAC,SAAS,QAAQ,QAAQ,EAAE,SAAS,MAAM,MAAM,OAAO,IAAI;AAChF,UAAMC,QAAO,MAAM,MAAM,SAAS,SAAS;AAC3C,UAAM,YAAY,MAAM,SAAS,IAAI,CAAC,MAAM,KAAK,UAAU,GAAG,GAAG,OAAO,CAAC;AACzE,UAAM,YAAY,KAAK,QAAQ,UAAU,OAAO,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,CAAC;AAC3E,UAAM,YAAY,cAAc,OAAO,SAAS;AAChD,UAAM,QAAQ,UAAU,OAAO,WAAW,WAAWA,OAAM,KAAK,GAAG,KAAK,CAAC;AACzE,UAAM,eAAe,cAAc,IAAI,IAAI,IAAI,OAAO;AACtD,UAAM,MAAM,MAAM,SAAS,gBAAgB;AAC3C,QAAI,YAAY;AAChB,QAAI,UAAU;AAEd,eAAW,EAAE,GAAG,GAAG,KAAK,KAAK,OAAO;AAClC,YAAM,KAAK,UAAU,CAAC;AACtB,YAAM,KAAK,UAAU,CAAC;AACtB,YAAM,KAAK,MAAM,SAAS,CAAC;AAC3B,UAAI,gBAAgB,MAAM;AAC1B,UAAI,CAAC,eAAe;AAClB,cAAM,SAAS,MAAM,MAAM;AAC3B,YAAI,eAAe,MAAM,GAAG;AAC1B,0BAAgB,OAAO,SAAS,GAAG,UAAU,KAAK,OAAO;AAAA,QAC3D,MAAO,iBAAgB;AAAA,MACzB;AACA,UAAI,IAAI,MAAM,SAAS,QAAQ,IAAI,CAAC;AACpC,UAAI,MAAM,WAAW,OAAO,SAAS,SAAS,EAAG,MAAK,KAAK,IAAI,GAAG,IAAI,OAAO,SAAS;AACtF,UAAI,cAAc,IAAI;AACtB,UAAI,cAAc;AAElB,UAAI,KAAK,GAAG,IAAI,GAAG;AACnB,UAAI,KAAK,GAAG,IAAI,GAAG;AACnB,UAAIA,OAAM;AACR,YAAI,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,EAAG,MAAK,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK;AACrE,YAAI,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,EAAG,MAAK,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK;AAAA,MACvE;AACA,UAAI,UAAU;AACd,UAAI,OAAO,GAAG,GAAG,GAAG,CAAC;AACrB,UAAI,OAAO,GAAG,IAAI,IAAI,GAAG,IAAI,EAAE;AAC/B,UAAI,OAAO;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA,EAIQ,WAAW,GAAW,SAAuB;AACnD,UAAM,EAAE,IAAI,IAAI;AAChB,SAAK;AACL,QAAI,KAAK,SAAU,MAAK,gBAAgB,CAAC;AACzC,QAAI,CAAC,KAAK,aAAa;AACrB,UAAI,cAAc;AAClB,UAAI,2BAA2B;AAC/B,WAAK,eAAe,CAAC;AAAA,IACvB;AACA,QAAI,cAAc;AAClB,UAAM,IAAI,KAAK,OAAO;AACtB,aAAS,KAAK,GAAG,KAAK,GAAG,MAAM;AAE7B,UAAI,CAAC,KAAK,eAAe,KAAK,UAAU,IAAI,CAAC,GAAG;AAC9C,YAAI,IAAI;AACR,eAAO,IAAI,IAAI,KAAK,KAAK,UAAU,IAAI,GAAG,CAAC,EAAG;AAC9C,YAAI,IAAI,MAAM,KAAK,UAAU,IAAI,CAAC,KAAK,oBAAoB,KAAK,WAAW,IAAI,GAAG,CAAC,GAAG;AAAE,eAAK;AAAG;AAAA,QAAU;AAAA,MAC5G;AACA,WAAK,WAAW,IAAI,CAAC;AAAA,IACvB;AACA,QAAI,cAAc;AAClB,QAAI,2BAA2B;AAAA,EACjC;AAAA;AAAA,EAGQ,WAAW,IAAY,GAAiB;AAC9C,UAAM,EAAE,IAAI,IAAI;AAChB,UAAM,QAAQ,KAAK,OAAO,EAAE;AAC5B,UAAM,UAAU,MAAM,MAAM;AAI5B,UAAM,QAAQ,MAAM,MAAM,UAAU,SAAY,SAAY,KAAK,QAAQ,SAAS,MAAM,MAAM,KAAK;AACnG,QAAI,QAAQ,YAAY,SAAY,YAAY,MAAM,MAAM,MAAM,CAAC,IAAI,YAAY,MAAM,MAAM,MAAM,CAAC,IAAIL,SAAQ,OAAO;AACzH,QAAI,OAAO,YAAY,OAAW,UAASA,SAAQ,MAAM,OAAO;AAChE,QAAI,SAAS,EAAG;AAChB,UAAM,UAAU,KAAK,gBAAgB,KAAK;AAC1C,UAAM,KAAK,MAAM,MAAM;AACvB,UAAM,MAAM,OAAO;AACnB,QAAI,MAAM,KAAK;AACb,UAAI,KAAK;AACT,UAAI,IAAK,MAAK,oBAAoB,KAAK,IAAI;AAC3C,UAAI,GAAI,MAAK,oBAAoB,IAAI,MAAM,KAAK;AAAA,IAClD;AACA,QAAI,2BAA2B,MAAM,MAAM,SAAS;AACpD,SAAK,UAAU,OAAO,GAAG,OAAO,OAAO;AACvC,UAAM,WAAW,KAAK,gBAAgB,IAAI,EAAE,KAAK;AACjD,eAAW,KAAK,MAAM,UAAU;AAC9B,WAAK,UAAU,OAAO,GAAG,GAAG,OAAO,OAAO;AAC1C,UAAI,aAAa,MAAM;AACrB,aAAK,WAAW,OAAO,GAAG,GAAG,OAAO,OAAO;AAC3C;AAAA,MACF;AAIA,YAAM,CAAC,MAAM,GAAG,IAAI,SAAS,SAAS,QAClC,CAAC,KAAK,IAAI,GAAG,IAAI,IAAI,SAAS,CAAC,GAAG,KAAK,IAAI,GAAG,IAAI,SAAS,IAAI,CAAC,CAAC,IACjE,CAAC,IAAI,SAAS,GAAG,SAAS,CAAC;AAC/B,UAAI,OAAO,EAAG,MAAK,WAAW,OAAO,GAAG,GAAG,OAAO,SAAS,EAAE,QAAQ,SAAS,UAAU,OAAO,KAAK,CAAC;AACrG,UAAI,MAAM,EAAG,MAAK,WAAW,OAAO,GAAG,GAAG,OAAO,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC1E;AACA,QAAI,MAAM,IAAK,KAAI,QAAQ;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWiB,SAAS,oBAAI,IAA+O;AAAA;AAAA,EAGrQ,UAAU,GAAW,GAAmB;AAC9C,QAAI,IAAI;AACR,aAAS,KAAK,GAAG,MAAM,GAAG,MAAM;AAC9B,YAAM,QAAQ,KAAK,OAAO,EAAE;AAC5B,YAAM,KAAK,MAAM,MAAM;AACvB,UAAI,GAAG,SAAS,aAAa,cAAc,EAAE,EAAG,MAAK,aAAa,EAAE,IAAI,MAAM,SAAS;AAAA,IACzF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGiB,YAAY,oBAAI,IAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7C,UAAU,IAAY,GAAoB;AAChD,UAAM,QAAQ,KAAK,OAAO,EAAE;AAC5B,UAAM,IAAI,MAAM;AAChB,UAAM,KAAK,EAAE;AACb,QAAI,CAAC,cAAc,EAAE,EAAG,QAAO;AAC/B,SAAK,EAAE,SAAS,mBAAmB,cAAe,QAAO;AACzD,QAAI,EAAE,SAAS,EAAE,SAAS,KAAK,gBAAgB,IAAI,EAAE,EAAG,QAAO;AAC/D,QAAI,MAAM,SAAS,SAAS,GAAI,QAAO;AACvC,UAAM,MAAM,KAAK,SAAS,IAAI,CAAC;AAC/B,UAAM,OAAO,KAAK,UAAU,IAAI,EAAE;AAClC,SAAK,UAAU,IAAI,IAAI,GAAG;AAC1B,WAAO,SAAS;AAAA,EAClB;AAAA,EAEQ,SAAS,IAAY,GAAmB;AAC9C,UAAM,QAAQ,KAAK,OAAO,EAAE;AAC5B,UAAM,QAAQ,MAAM,MAAM,UAAU,SAAY,SAAY,KAAK,QAAQ,SAAS,MAAM,MAAM,KAAK;AACnG,UAAM,UAAU,MAAM,MAAM;AAC5B,QAAI,QAAQ,YAAY,SAAY,YAAY,MAAM,MAAM,MAAM,CAAC,IAAI,YAAY,MAAM,MAAM,MAAM,CAAC,IAAIA,SAAQ,OAAO;AACzH,QAAI,OAAO,YAAY,OAAW,UAASA,SAAQ,MAAM,OAAO;AAChE,QAAI,MAAM,GAAG,aAAa,MAAM,MAAM,MAAuB,CAAC,IAAI,MAAM,QAAQ,CAAC,CAAC,IAAI,KAAK,UAAU,MAAM,MAAM,aAAa,IAAI,CAAC,IAAI,KAAK,UAAU,OAAO,aAAa,IAAI,CAAC;AAC/K,UAAM,UAAU,KAAK,gBAAgB,KAAK;AAC1C,eAAW,KAAK,MAAM,UAAU;AAC9B,YAAM,IAAI,KAAK,UAAU,GAAG,GAAG,OAAO;AACtC,aAAO,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,QAAQ,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,UAAU;AAAA,IACnJ;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,SAAS,GAAW,GAAmB;AAC7C,QAAI,MAAM,GAAG,CAAC,IAAI,CAAC;AACnB,aAAS,KAAK,GAAG,MAAM,GAAG,KAAM,QAAO,IAAI,KAAK,UAAU,IAAI,EAAE,CAAC;AACjE,WAAO;AAAA,EACT;AAAA;AAAA,EAGiB,YAAY,oBAAI,QAAwB;AAAA,EACjD,QAAQ,IAA2B;AACzC,QAAI,IAAI,KAAK,UAAU,IAAI,EAAE;AAC7B,QAAI,MAAM,QAAW;AACnB,UAAI;AACJ,UAAI,KAAK;AACT,iBAAW,QAAQ,UAAU,EAAE,GAAG;AAChC,mBAAW,CAAC,GAAG,CAAC,KAAK,KAAK,KAAK,OAAQ,KAAI,KAAK,IAAI,GAAG,KAAK,MAAM,GAAG,CAAC,CAAC;AACvE,mBAAW,KAAK,KAAK,KAAK,MAAO,YAAW,CAAC,GAAG,CAAC,KAAK,EAAE,OAAQ,KAAI,KAAK,IAAI,GAAG,KAAK,MAAM,GAAG,CAAC,CAAC;AAChG,YAAI,KAAK,OAAQ,MAAK,KAAK,IAAI,IAAI,KAAK,OAAO,KAAK;AAAA,MACtD;AACA,WAAK;AACL,WAAK,UAAU,IAAI,IAAI,KAAK,CAAC;AAAA,IAC/B;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,OAAO,GAAW,GAAW,GAAkE;AACrG,UAAM,IAAI,KAAK,IAAI,aAAa;AAChC,QAAI,KAAK,IAAI,EAAE,CAAC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC,IAAI,KAAM,QAAO;AACzD,QAAI,KAAK,UAAU,KAAK,UAAU,KAAK,WAAW,KAAK;AACvD,aAAS,KAAK,GAAG,MAAM,GAAG,MAAM;AAC9B,YAAM,QAAQ,KAAK,OAAO,EAAE;AAC5B,YAAM,QAAQ,MAAM,MAAM,UAAU,SAAY,SAAY,KAAK,QAAQ,SAAS,MAAM,MAAM,KAAK;AACnG,UAAI,MAAM,MAAM,aAAa,OAAO,UAAW,QAAO;AACtD,YAAM,QAAQ,KAAK,QAAQ,MAAM,MAAM,MAAuB;AAC9D,YAAM,UAAU,KAAK,gBAAgB,KAAK;AAC1C,iBAAW,KAAK,MAAM,UAAU;AAC9B,cAAM,IAAI,KAAK,UAAU,GAAG,GAAG,OAAO;AACtC,cAAM,KAAK,MAAM,MAAM;AACvB,cAAM,KAAK,UAAU,IAAI,OAAO,GAAG,CAAC,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC;AACzD,cAAM,MAAM,KAAK,IAAI,GAAG,IAAI,GAAG,EAAE,KAAK,QAAQ,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE;AACrE,aAAK,KAAK,IAAI,IAAI,EAAE,IAAI,GAAG;AAAG,aAAK,KAAK,IAAI,IAAI,EAAE,IAAI,GAAG;AACzD,aAAK,KAAK,IAAI,IAAI,EAAE,IAAI,GAAG;AAAG,aAAK,KAAK,IAAI,IAAI,EAAE,IAAI,GAAG;AAAA,MAC3D;AAAA,IACF;AACA,UAAM,IAAI,KAAK,OAAO,OAAO,IAAI,KAAK,OAAO;AAC7C,UAAM,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC,IAAI,CAAC;AACrD,UAAM,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC,IAAI,CAAC;AACrD,UAAM,KAAK,KAAK,IAAI,GAAG,KAAK,KAAK,EAAE,IAAI,KAAK,EAAE,CAAC,IAAI,CAAC,IAAI;AACxD,UAAM,KAAK,KAAK,IAAI,GAAG,KAAK,KAAK,EAAE,IAAI,KAAK,EAAE,CAAC,IAAI,CAAC,IAAI;AACxD,WAAO,KAAK,KAAK,KAAK,IAAI,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE;AAAA,EACtF;AAAA;AAAA,EAGQ,WAAW,GAAW,GAAW,GAAoB;AAC3D,UAAM,MAAM,KAAK,SAAS,GAAG,CAAC;AAC9B,QAAI,QAAQ,KAAK,OAAO,IAAI,CAAC;AAC7B,QAAI,CAAC,SAAS,MAAM,QAAQ,OAAO,MAAM,QAAQ,KAAK,MAAM,WAAW,KAAK,OAAO,SAAS,MAAM,WAAW,KAAK,OAAO,QAAQ;AAC/H,YAAM,MAAM,KAAK,OAAO,GAAG,GAAG,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,OAAO,OAAO,GAAG,KAAK,OAAO,OAAO;AAC9F,UAAI,CAAC,OAAO;AACV,YAAI,KAAK,OAAO,QAAQ,EAAG,MAAK,OAAO,OAAO,KAAK,OAAO,KAAK,EAAE,KAAK,EAAE,KAAM;AAC9E,cAAM,OAAO,KAAK,WAAW,CAAC;AAC9B,YAAI,CAAC,KAAM,QAAO;AAClB,gBAAQ,EAAE,GAAG,MAAM,KAAK,GAAG,KAAK,IAAI,KAAK,QAAQ,GAAG,QAAQ,EAAE;AAC9D,aAAK,OAAO,IAAI,GAAG,KAAK;AAAA,MAC1B;AACA,YAAM,MAAM;AACZ,YAAM,SAAS,KAAK,OAAO;AAC3B,YAAM,SAAS,KAAK,OAAO;AAC3B,UAAI,IAAI,MAAM,KAAK,IAAI,MAAM,GAAG;AAAE,cAAM,MAAM;AAAK,cAAM,MAAM;AAAG,eAAO;AAAA,MAAM;AAC/E,UAAI,MAAM,OAAO,UAAU,IAAI,EAAG,OAAM,OAAO,QAAQ,IAAI;AAC3D,UAAI,MAAM,OAAO,WAAW,IAAI,EAAG,OAAM,OAAO,SAAS,IAAI;AAC7D,YAAM,KAAK,MAAM;AACjB,SAAG,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAChC,SAAG,cAAc;AACjB,SAAG,2BAA2B;AAC9B,SAAG,UAAU,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAC/B,YAAM,IAAI,KAAK,IAAI,aAAa;AAChC,SAAG,aAAa,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,IAAI,CAAC;AAC5D,YAAM,OAAO;AACb,YAAM,OAAO,KAAK;AAClB,WAAK,MAAM;AACX,UAAI;AACF,iBAAS,KAAK,GAAG,MAAM,GAAG,KAAM,MAAK,WAAW,IAAI,CAAC;AAAA,MACvD,UAAE;AACA,aAAK,MAAM;AAAA,MACb;AACA,YAAM,MAAM;AACZ,YAAM,MAAM;AAAA,IACd;AACA,QAAI,MAAM,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,EAAG,QAAO;AACnD,UAAM,MAAM,KAAK;AACjB,QAAI,KAAK;AACT,QAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACjC,QAAI,cAAc;AAClB,QAAI,2BAA2B;AAC/B,QAAI,UAAU,MAAM,QAAQ,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;AACpD,QAAI,QAAQ;AACZ,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,oBAAoB,IAAoB,OAA+B;AAC7E,UAAM,EAAE,KAAK,GAAG,EAAE,IAAI;AACtB,UAAM,OAAO,KAAK,QAAQ,UAAU,OAAO,IAAI,KAAK,IAAI,GAAG,CAAC;AAC5D,UAAM,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI,gBAAgB,IAAI,OAAO,GAAG,GAAG,IAAI;AAC9D,QAAI,UAAU,MAAM,GAAG,KAAK,KAAK,MAAM,MAAM,GAAG,KAAK,KAAK,IAAI;AAC9D,QAAI,GAAG,OAAQ,KAAI,OAAQ,GAAG,SAAS,KAAK,KAAM,GAAG;AACrD,UAAM,IAAI,GAAG,SAAS;AACtB,QAAI,MAAM,KAAK,GAAG,UAAU,IAAI,CAAC;AACjC,QAAI,UAAU,CAAC,IAAI,CAAC,EAAE;AAAA,EACxB;AAAA;AAAA,EAGQ,WAAmB;AACzB,WAAO,KAAK,gBAAgB,OAAO,oBAAoB,KAAK,cAAc,KAAK;AAAA,EACjF;AAAA;AAAA,EAGQ,gBAAgB,GAAiB;AACvC,UAAM,UAAoB,CAAC;AAC3B,UAAM,OAAO,iBAAiB,kBAAkB,KAAK,UAAW,CAAC,GAAG,KAAK,WAAW,GAAG,OAAO;AAC9F,eAAW,KAAK,QAAS,MAAK,UAAU,OAAO,CAAC;AAChD,SAAK,UAAU;AACf,UAAM,MAAM,oBAAoB,IAAI;AACpC,QAAI,QAAQ,KAAK,eAAgB,MAAK,QAAQ;AAAA,QACzC,MAAK,OAAO,QAAQ,CAAC,GAAG,MAAM;AAAE,QAAE,QAAQ,KAAK,OAAO,CAAC,KAAK,EAAE;AAAA,IAAO,CAAC;AAAA,EAC7E;AAAA;AAAA,EAGQ,iBAAiB,QAA+B,OAAwB;AAC9E,UAAM,MAAM,KAAK,SAAS;AAC1B,UAAM,QAAQ,KAAK;AAKnB,UAAM,SAAS,oBAAI,IAAwB;AAC3C,eAAW,KAAK,QAAQ;AACtB,YAAM,OAAO,kBAAkB,OAAO,EAAE,IAAI;AAC5C,UAAI,CAAC,KAAM;AACX,aAAO,OAAO,IAAI;AAClB,aAAO,IAAI,MAAM,CAAC;AAAA,IACpB;AACA,UAAM,OAAO,IAAI,IAAI,KAAK,SAAS;AACnC,UAAM,QAAiC,CAAC;AACxC,eAAW,CAAC,MAAM,CAAC,KAAK,QAAQ;AAC9B,YAAM,KAAK,QAAQ,CAAC;AACpB,UAAI,KAAK,WAAW,IAAI,IAAI,MAAM,GAAI;AACtC,YAAM,KAAK,CAAC,MAAM,EAAE,CAAC;AACrB,WAAK,IAAI,MAAM,YAAY,KAAK,UAAW,MAAM,QAAQ,IAAI,aAAa,OAAO,IAAI,IAAI,EAAE,OAAO,EAAE,OAAO,KAAK,KAAK,CAAC;AAAA,IACxH;AACA,QAAI,MAAM,WAAW,EAAG,QAAO;AAG/B,QAAI,CAAC,mBAAmB,KAAK,UAAW,MAAM,GAAG,EAAG,QAAO;AAC3D,eAAW,CAAC,GAAG,EAAE,KAAK,MAAO,MAAK,WAAW,IAAI,GAAG,EAAE;AACtD,SAAK,YAAY;AACjB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,oBAA0D;AACxD,WAAO,KAAK,WAAW,IAAI,IAAI,KAAK,SAAS,IAAI;AAAA,EACnD;AAAA;AAAA,EAGA,eAAoC;AAClC,WAAO,IAAI,IAAI,KAAK,UAAU;AAAA,EAChC;AAAA;AAAA,EAGA,gBAA2B;AACzB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,YAAY,GAAW,OAAqB;AAC1C,SAAK,eAAe,CAAC;AACrB,UAAM,IAAI,KAAK,cAAc,IAAK,KAAK,QAAQ,YAAY;AAC3D,QAAI,IAAI,GAAG;AACT,YAAM,KAAK,MAAO;AAClB,YAAM,aAAa,KAAK,gBAAgB,OAAO,qBAC1C,IAAI,KAAK,eACT,IAAI,KAAK,eAAe;AAC7B,UAAI,YAAY;AACd,aAAK,WAAW,GAAG,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;AAAA,MACjE,OAAO;AACL,cAAM,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,GAAG,OAAO,oBAAoB;AAC1F,cAAM,KAAK,KAAK,IAAI,GAAG,IAAI,IAAI,EAAE;AACjC,aAAK,WAAW,IAAI,CAAC;AACrB,iBAAS,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,MAAM,GAAI,MAAK,WAAW,IAAI,IAAI,CAAC;AAC3E,YAAI,IAAI,GAAI,MAAK,WAAW,GAAG,IAAI,CAAC;AAAA,MACtC;AAAA,IACF,OAAO;AACL,WAAK,WAAW,GAAG,CAAC;AAAA,IACtB;AACA,SAAK,cAAc;AAInB,QAAI,KAAK,WAAY,mBAAkB,KAAK,YAAY,KAAK,QAAQ,KAAK,GAAG,KAAK,GAAG,GAAG,KAAK,QAAQ,QAAQ,KAAK,aAAa;AAAA,EACjI;AAAA,EAEA,UAAU,QAAuB;AAC/B,SAAK,SAAS;AACd,QAAI,QAAQ;AACV,WAAK,KAAK;AAAA,IACZ,OAAO;AACL,WAAK,MAAM;AAAA,IACb;AAAA,EACF;AAAA,EAEA,OAAO,OAAe,QAAgB,KAAoB;AACxD,SAAK,IAAI;AACT,SAAK,IAAI;AACT,QAAI,QAAQ,OAAW,MAAK,SAAS,MAAM;AAC3C,SAAK,WAAW;AAChB,SAAK,QAAQ;AACb,QAAI,KAAK,OAAQ,MAAK,YAAY,GAAG,KAAK,IAAI;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,MAAuB;AACjC,SAAK,cAAc,IAAI;AACvB,QAAI,KAAK,UAAU;AAAE,WAAK,gBAAgB,KAAK,SAAS,CAAC;AAAG;AAAA,IAAQ;AACpE,SAAK,UAAU;AACf,UAAM,MAAM,oBAAoB,KAAK,OAAO;AAC5C,QAAI,QAAQ,KAAK,eAAgB,MAAK,QAAQ;AAAA,QACzC,MAAK,OAAO,QAAQ,CAAC,GAAG,MAAM;AAAE,QAAE,QAAQ,KAAK,QAAQ,OAAO,CAAC,KAAK,EAAE;AAAA,IAAO,CAAC;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,cAAc,MAAiB,aAAa,OAAa;AAC/D,UAAM,OAAO,KAAK,WAAW,OAAO;AACpC,QAAI,SAAS,KAAK,YAAY,EAAE,cAAc,QAAQ,KAAK,WAAW;AACpE,WAAK,UAAU,MAAM;AACrB,WAAK,WAAW,MAAM;AAAA,IACxB;AACA,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,qBAAqB,MAAiB,UAAsC;AAC1E,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,YAAY,IAAI;AACrB;AAAA,IACF;AACA,QAAI,CAAC,KAAK,UAAU;AAGlB,WAAK,YAAY,IAAI;AACrB,WAAK,eAAe,QAAQ;AAC5B;AAAA,IACF;AACA,SAAK,cAAc,MAAM,IAAI;AAC7B,eAAW,KAAK,SAAU,MAAK,iBAAiB,CAAC,CAAC,GAAG,CAAC;AACtD,SAAK,gBAAgB,KAAK,SAAS,CAAC;AAAA,EACtC;AAAA;AAAA,EAGA,OAAO,QAAQ,UAAqB,WAA0C,MAA2B,QAA+B,KAAmB;AACzJ,UAAM,KAAK,kBAAkB,UAAU,GAAG;AAG1C,UAAM,SAAS,oBAAI,IAAwB;AAC3C,eAAW,KAAK,QAAQ;AACtB,YAAM,OAAO,kBAAkB,IAAI,EAAE,IAAI;AACzC,UAAI,CAAC,KAAM;AACX,aAAO,OAAO,IAAI;AAClB,aAAO,IAAI,MAAM,CAAC;AAAA,IACpB;AACA,eAAW,CAAC,MAAM,CAAC,KAAK,QAAQ;AAC9B,YAAM,KAAK,QAAQ,CAAC;AACpB,UAAI,KAAK,IAAI,IAAI,MAAM,GAAI;AAC3B,YAAM,QAAQ,IAAI,IAAI,SAAS,EAAE,IAAI,MAAM,YAAY,UAAU,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,CAAC,CAAC;AAChG,UAAI,mBAAmB,UAAU,OAAO,GAAG,GAAG;AAC5C,kBAAU,IAAI,MAAM,MAAM,IAAI,IAAI,CAAE;AACpC,aAAK,IAAI,MAAM,EAAE;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,aAAa,MAAuB;AAClC,SAAK,cAAc,IAAI;AACvB,QAAI,KAAK,UAAU;AAAE,WAAK,gBAAgB,KAAK,SAAS,CAAC;AAAG;AAAA,IAAQ;AACpE,SAAK,UAAU;AACf,SAAK,OAAO,QAAQ,CAAC,GAAG,MAAM;AAAE,QAAE,QAAQ,KAAK,QAAQ,OAAO,CAAC,KAAK,EAAE;AAAA,IAAO,CAAC;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,uBAAuB,WAAiE;AACtF,SAAK,iBAAiB,aAAa,UAAU,OAAO,IAAI,YAAY;AAAA,EACtE;AAAA,EAEA,UAAgB;AACd,SAAK,KAAK;AACV,SAAK,QAAQ;AAGb,UAAM,UAAU,KAAK,YAAY,UAAU,KAAK;AAChD,SAAK,aAAa;AAClB,QAAI,KAAK,cAAc,OAAO,sBAAsB,eAAe,mBAAmB,kBAAmB,SAAQ,OAAO;AAAA,EAC1H;AACF;AAOO,SAAS,aAAa,MAA4B;AACvD,QAAM,QAAQ,gBAAgB,IAAI;AAClC,SAAO;AAAA,IACL,UAAU,YAAY,KAAK;AAAA,IAC3B,OAAO,CAAC,QAAsB,IAAI,aAAa,OAAO,KAAK,EAAE,gBAAiB,IAAyB,eAAe,CAAC;AAAA,IACvH,MAAM;AAAA,EACR;AACF;AAkCA,IAAM,aAAa;AA+BZ,SAAS,mBAAmB,MAAoD;AACrF,SAAO,OAAQ,KAAuC,oBAAoB;AAC5E;AAEA,IAAM,mBAAN,MAAwD;AAAA;AAAA,EAE9C;AAAA,EACS;AAAA,EACA;AAAA,EACA;AAAA,EACT,cAAc;AAAA,EACd,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT,iBAAiB;AAAA,EACR;AAAA,EACT,UAAyB;AAAA,EACzB,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA;AAAA,EAER,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASZ,cAAc;AAAA,EACd,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUhB,kBAAkB;AAAA;AAAA,EAElB,YAAkL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWzK,iBAAiB,oBAAI,IAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7C,oBAAoB,oBAAI,IAAwB;AAAA;AAAA,EAEzD,SAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQhC,WAAkC;AAAA;AAAA,EAEzB;AAAA;AAAA,EAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAgC;AAAA;AAAA,EAEhC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA;AAAA,EAEjB,YAAY,KAAmB,KAA2B;AACxD,SAAK,MAAM;AACX,UAAM,EAAE,eAAe,gBAAgB,GAAG,SAAS,IAAI;AACvD,SAAK,iBAAiB;AACtB,SAAK,cAAc,mBAAmB,WAAW,mBAAmB;AAOpE,QAAI,IAAI,SAAS,WAAW,OAAO,kBAAkB,YAAY,OAAO,SAAS,aAAa,GAAG;AAC/F,WAAK,QAAQ,KAAK,IAAI,GAAG,aAAa;AACtC,WAAK,QAAQ,KAAK;AAClB,WAAK,YAAY,KAAK;AAAA,IACxB;AAEA,QAAI,UAAU,IAAI,WAAW;AAC7B,QAAI,SAAmC;AACvC,QAAI,CAAC,WAAW,OAAO,aAAa,aAAa;AAC/C,eAAS,SAAS,cAAc,QAAQ;AACxC,aAAO,MAAM,UAAU;AACvB,aAAO,aAAa,eAAe,MAAM;AACzC,UAAI,KAAK,YAAY,MAAM;AAC3B,gBAAU;AAAA,IACZ;AACA,SAAK,SAAS;AAId,SAAK,QAAS,IAAI,QAAQ,IAAI,QAAQ,OAAO,KAAM;AACnD,SAAK,gBAAgB,mBAAmB,WAAW,mBAAmB;AAItE,QAAI,oBAAoB,GAAG,KAAK,SAAS;AACvC,YAAM,OAAO,iBAAiB,SAAS,KAAK,IAAI;AAChD,UAAI,MAAM;AACR,aAAK,aAAa;AAClB,kBAAU,kBAAkB,IAAI,OAAO,IAAI,MAAM;AAAA,MACnD;AAAA,IACF;AAIA,SAAK,WAAW,EAAE,GAAG,UAAU,SAAmB,eAAe,KAAK;AACtE,SAAK,YAAY;AACjB,SAAK,WAAW,IAAI,MAAM,IAAI,SAAS,MAAM,EAAE,KAAK,IAAI;AACxD,QAAI,IAAI,KAAK;AACX,WAAK,MAAM,IAAI,aAAa,KAAK,SAAS,IAAI,GAAG,GAAG,KAAK,UAAU,EAAE,gBAAgB,cAAc,KAAK,CAAC;AACzG,WAAK,IAAI,UAAU,IAAI;AAAA,IACzB,OAAO;AACL,WAAK,MAAM;AAAA,IACb;AACA,SAAK,SAAS,IAAI;AAClB,QAAI,KAAK,OAAQ,MAAK,YAAY,KAAK,OAAO,KAAK,IAAI;AAAA,QAClD,MAAK,MAAM;AAAA,EAClB;AAAA,EAEQ,UAAU,OAAe,UAA0B;AACzD,WAAO,KAAK,IAAI,SAAS,KAAK,EAAG,MAAM,QAAQ,KAAK,IAAI,QAAQ;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,SAAS,KAA2B;AAC1C,QAAI,IAAI,QAAQ,KAAM,QAAO;AAC7B,QAAI,KAAK,IAAI,QAAQ,KAAM,QAAO,EAAE,GAAG,KAAK,MAAM,KAAK,IAAI,OAAO,OAAO,YAAY;AACrF,WAAO;AAAA,EACT;AAAA,EAEQ,WAAW,OAA0B;AAC3C,UAAM,MAAM,KAAK,IAAI,SAAS,KAAK;AACnC,QAAI,IAAI,MAAM,QAAQ,KAAM,QAAO,IAAI;AACvC,QAAI,KAAK,IAAI,QAAQ,KAAM,QAAO,EAAE,GAAG,IAAI,OAAO,MAAM,KAAK,IAAI,OAAO,MAAM;AAC9E,WAAO,IAAI;AAAA,EACb;AAAA;AAAA,EAGQ,SAAS,MAAuB;AACtC,WAAO,SAAS,KAAK,KAAK,IAAI;AAAA,EAChC;AAAA;AAAA,EAGQ,eAAe,OAAuB;AAC5C,WAAO,eAAe,KAAK,KAAK,KAAK;AAAA,EACvC;AAAA,EAEQ,SAAS,MAAsB;AACrC,UAAM,KAAK,KAAK,IAAI,SAAS,IAAI,GAAG;AACpC,WAAO,IAAI,SAAS,UAAU,GAAG,MAAM;AAAA,EACzC;AAAA;AAAA,EAGQ,oBAAoB,MAAuB;AACjD,UAAM,KAAK,KAAK,IAAI,SAAS,IAAI,GAAG;AACpC,WAAO,IAAI,SAAS,YAAY,GAAG,SAAS,eAAe,GAAG,SAAS;AAAA,EACzE;AAAA;AAAA,EAGQ,cAAc,MAAmC;AACvD,UAAM,KAAK,KAAK,IAAI,SAAS,IAAI,GAAG;AACpC,WAAO,IAAI,SAAS,WAAW,GAAG,SAAS,QAAQ,QAAQ;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,mBAAmB,OAAkB,OAAkB,QAAmB,GAAW,OAA4B,aAAqD;AAC5K,QAAI,MAA8C;AAClD,aAAS,IAAI,GAAG,IAAI,OAAO,OAAO,QAAQ,KAAK;AAC7C,UAAI,CAAC,kBAAkB,OAAO,OAAO,CAAC,EAAG;AACzC,YAAM,OAAO,MAAM,OAAO,CAAC,EAAG;AAC9B,YAAM,MAAM,OAAO,OAAO,CAAC,EAAG;AAC9B,YAAM,WAAuB,KAAK,SAAS,UAAU,IAAI,SAAS,SAC9D,EAAE,GAAG,KAAK,SAAS,KAAK,QAAQ,IAChC,KAAK,SAAS,eAAe,IAAI,SAAS,cACxC,EAAE,GAAG,KAAK,MAAM,KAAK,KAAK,IAC1B;AACN,UAAI,aAAa,IAAK;AAGtB,OAAC,QAAQ,oBAAI,IAAI,GAAG,IAAI,GAAG,SAAS,QAAQ,EAAE,UAAU,GAAG,KAAK,IAAI,EAAE,UAAU,EAAE,CAAC;AAAA,IACrF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,QAAQ,MAAsB;AACpC,UAAM,KAAK,KAAK,IAAI,SAAS,IAAI,GAAG;AACpC,WAAO,KAAK,eAAe,IAAI,SAAS,SAAS,GAAG,MAAM;AAAA,EAC5D;AAAA;AAAA,EAGQ,aAAqB;AAC3B,UAAM,OAAO,KAAK,IAAI,SAAS,SAAS;AACxC,WAAO,aAAa,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,SAAS,IAAI,EAAG,YAAY;AAAA,EAC9E;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,KAAK,QAAQ;AACf,WAAK,OAAO,MAAM,QAAQ;AAC1B,WAAK,SAAS;AAAA,IAChB;AACA,QAAI,KAAK,UAAU;AACjB,WAAK,SAAS,MAAM,QAAQ;AAC5B,WAAK,WAAW;AAAA,IAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,eAAe,OAAe,MAA8B;AAClE,UAAM,SAA8C,OAAO,aAAa,cACpE,SAAS,cAAc,QAAQ,IAC/B,IAAI,gBAAgB,KAAK,IAAI,GAAG,KAAK,SAAS,KAAK,GAAG,KAAK,IAAI,GAAG,KAAK,SAAS,MAAM,CAAC;AAC3F,UAAM,QAAQ,IAAI,aAAa,KAAK,WAAW,IAAI,GAAG,EAAE,GAAG,KAAK,UAAU,SAAS,OAAO,GAAG,EAAE,aAAa,KAAK,QAAQ,MAAM,gBAAgB,KAAK,gBAAgB,cAAc,KAAK,CAAC;AACxL,UAAM,UAAU,IAAI;AACpB,QAAI,SAAS,MAAO,OAAM,YAAY,KAAK,WAAW,KAAK,CAAC;AAC5D,QAAI,KAAK,eAAe,OAAO,EAAG,OAAM,eAAe,KAAK,eAAe,OAAO,CAAC;AACnF,WAAO,EAAE,OAAO,OAAO,OAAO;AAAA,EAChC;AAAA;AAAA,EAGQ,gBAAgB,IAAoB,GAAW,MAAoB;AACzE,QAAI,KAAK,KAAK;AACZ,YAAM,IAAI,GAAG,OAAO,WAAW,IAAI;AACnC,SAAG,UAAU,GAAG,GAAG,KAAK,SAAS,OAAO,KAAK,SAAS,MAAM;AAAA,IAC9D;AACA,OAAG,MAAM,YAAY,GAAG,IAAI;AAAA,EAC9B;AAAA;AAAA,EAGQ,UAAU,QAA6C,OAAqB;AAClF,UAAM,OAAO,KAAK,SAAS,SAAS,WAAW,IAAI;AACnD,QAAI,CAAC,KAAM;AACX,SAAK,KAAK;AACV,SAAK,cAAc;AACnB,SAAK,2BAA2B;AAChC,SAAK,UAAU,QAAQ,GAAG,GAAG,KAAK,SAAS,OAAO,KAAK,SAAS,MAAM;AACtE,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,eAAe,MAAc,QAAgB,MAA8B;AACjF,QAAI,KAAK,UAAU,KAAK,OAAO,UAAU,MAAM;AAC7C,WAAK,OAAO,MAAM,QAAQ;AAC1B,WAAK,SAAS;AAAA,IAChB;AACA,QAAI,CAAC,KAAK,OAAQ,MAAK,SAAS,KAAK,eAAe,MAAM,KAAK,eAAe,IAAI,CAAC;AACnF,UAAM,SAAS,KAAK,IAAI,SAAS,IAAI,EAAG,YAAY;AACpD,SAAK,gBAAgB,KAAK,QAAQ,SAAS,QAAQ,KAAK,UAAU,KAAK,eAAe,IAAI,GAAG,IAAI,CAAC;AAClG,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,cAAc,OAAe,GAAW,MAA+B;AAC7E,UAAM,QAAQ,KAAK,WAAW,KAAK;AACnC,QAAI,CAAC,MAAM,SAAU,QAAO,KAAK,aAAa,KAAK;AACnD,UAAM,OAAO,KAAK;AAClB,QAAI,QAAQ,SAAS,MAAO,MAAK,OAAO;AACxC,QAAI,KAAK,SAAS,QAAQ,MAAM,OAAO,OAAO,MAAM,MAAM;AAC1D,QAAI,CAAC,IAAI;AACP,WAAK,KAAK,YAAY,OAAO,SAAS,QAAQ,MAAM,UAAU,MAAS;AACvE,UAAI,MAAM;AAAE,YAAI,SAAS,MAAO,MAAK,MAAM;AAAA,YAAS,MAAK,KAAK;AAAA,MAAI;AAAA,IACpE;AACA,WAAO,iBAAiB,kBAAkB,OAAO,CAAC,GAAG,IAAI,CAAC;AAAA,EAC5D;AAAA;AAAA,EAGQ,YAAY,OAAkB,MAA2D;AAC/F,UAAM,MAAM,oBAAI,IAA8B;AAC9C,QAAI,KAAK,eAAe,SAAS,EAAG,QAAO;AAC3C,UAAM,MAAM,kBAAkB,OAAO,CAAC;AACtC,eAAW,KAAK,KAAK,eAAe,OAAO,GAAG;AAC5C,YAAM,OAAO,kBAAkB,KAAK,EAAE,IAAI;AAC1C,UAAI,CAAC,KAAM;AACX,YAAM,QAAQ,IAAI,IAAI,GAAG,EAAE,IAAI,MAAM,YAAY,OAAO,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,CAAC;AACrF,UAAI,mBAAmB,OAAO,OAAO,CAAC,GAAG;AACvC,YAAI,IAAI,MAAM,MAAM,IAAI,IAAI,CAAE;AAC9B,cAAM,IAAI,MAAM,QAAQ,CAAC,CAAC;AAAA,MAC5B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,aAAa,OAA6B;AAChD,WAAO,KAAK,eAAe,SAAS,IAAI,QAAQ,oBAAoB,OAAO,KAAK,eAAe,OAAO,CAAC;AAAA,EACzG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,YAAY,OAAe,WAAuB,kBAA0C;AAClG,QAAI,QAAQ,KAAK,SAAS,KAAK,IAAI,SAAS,OAAQ,SAAQ;AAC5D,QAAI,QAAQ,KAAK,SAAS,KAAK;AAC/B,QAAI,CAAC,OAAO;AAMV,cAAQ,IAAI,aAAa,aAAa,KAAK,WAAW,KAAK,GAAG,KAAK,UAAU,EAAE,aAAa,KAAK,QAAQ,MAAM,kBAAkB,oBAAoB,KAAK,QAAQ,MAAM,gBAAgB,KAAK,gBAAgB,cAAc,KAAK,CAAC;AACjO,WAAK,SAAS,KAAK,IAAI;AAGvB,YAAM,UAAU,IAAI;AACpB,UAAI,UAAW,OAAM,YAAY,KAAK,WAAW,KAAK,CAAC;AACvD,UAAI,KAAK,eAAe,OAAO,EAAG,OAAM,eAAe,KAAK,eAAe,OAAO,CAAC;AAAA,IACrF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa,OAAqB;AACxC,UAAM,QAAQ,KAAK,SAAS,KAAK;AACjC,QAAI,OAAO;AACT,YAAM,QAAQ;AACd,WAAK,SAAS,KAAK,IAAI;AAAA,IACzB;AAAA,EACF;AAAA,EAEQ,QAAc;AACpB,QAAI,KAAK,YAAY,QAAQ,OAAO,0BAA0B,YAAa;AAC3E,SAAK,SAAS;AACd,SAAK,UAAU,sBAAsB,CAAC,QAAQ,KAAK,KAAK,GAAG,CAAC;AAAA,EAC9D;AAAA,EAEQ,OAAa;AACnB,QAAI,KAAK,YAAY,MAAM;AACzB,2BAAqB,KAAK,OAAO;AACjC,WAAK,UAAU;AAAA,IACjB;AACA,SAAK,QAAQ,KAAK;AAAA,EACpB;AAAA,EAEQ,KAAK,KAAmB;AAC9B,SAAK,UAAU,sBAAsB,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;AACxD,QAAI,KAAK,WAAW,EAAG,MAAK,SAAS;AACrC,SAAK,QAAQ,MAAM,KAAK,SAAS,KAAK;AACtC,SAAK,YAAY,KAAK,OAAO,KAAK,IAAI;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,cAAoB;AAC1B,UAAM,KAAK,KAAK;AAChB,QAAI,CAAC,GAAI;AACT,UAAM,MAAM,KAAK,IAAI,KAAK,SAAS,KAAK,CAAC;AACzC,OAAG,OAAO,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,SAAS,QAAQ,GAAG,CAAC;AACnE,OAAG,OAAO,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,SAAS,SAAS,GAAG,CAAC;AACrE,OAAG,IAAI,aAAa,KAAK,GAAG,GAAG,KAAK,GAAG,CAAC;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,cAAmC;AACzC,QAAI,KAAK,IAAI,WAAW,OAAW,QAAO,KAAK,IAAI;AACnD,QAAI,KAAK,cAAc,EAAG,QAAO;AACjC,UAAM,QAAQ,KAAK,WAAW,KAAK,WAAW;AAC9C,QAAI,MAAM,UAAU;AAGlB,YAAM,QAAQ,KAAK,UAAU,UAAU,KAAK,cAAc,KAAK,SAAS,QAAQ,SAC3E,KAAK,SAAS,KAAK,WAAW,KAAK,KAAK,SAAS,KAAK,eAAe,KAAK,WAAW,CAAC;AAC3F,UAAI,KAAM,QAAO,KAAK,cAAc,EAAE;AAAA,IACxC;AACA,WAAO,KAAK,aAAa,KAAK,EAAE;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,kBAA0B;AAChC,QAAI,KAAK,IAAI,WAAW,OAAW,QAAO,KAAK;AAC/C,QAAI,KAAK,cAAc,EAAG,QAAO,KAAK;AACtC,WAAO,kBAAkB,KAAK,KAAK,KAAK,WAAW,KAAK,KAAK;AAAA,EAC/D;AAAA,EAEA,YAAY,GAAW,MAAoB;AACzC,SAAK,YAAY,GAAG,IAAI;AAExB,QAAI,KAAK,YAAY;AACnB,wBAAkB,KAAK,YAAY,KAAK,SAAS,SAAU,KAAK,SAAS,OAAO,KAAK,SAAS,QAAQ,GAAG,KAAK,YAAY,GAAG,KAAK,eAAe,KAAK,gBAAgB,CAAC;AAAA,IACzK;AAAA,EACF;AAAA,EAEQ,YAAY,GAAW,MAAoB;AACjD,SAAK,YAAY;AACjB,UAAM,WAAW,eAAe,KAAK,KAAK,IAAI,KAAK,aAAa,EAAE,eAAe,KAAK,cAAc,CAAC;AACrG,UAAM,EAAE,OAAO,OAAO,IAAI;AAI1B,SAAK,KAAK,YAAY,GAAG,KAAK,IAAI,KAAK,QAAQ,KAAK,IAAI,QAAQ,IAAI;AAMpE,UAAM,UAAU,KAAK,IAAI,SAAS,SAAS;AAC3C,UAAM,UAAU,KAAK,IAAI,QAAQ,UAAU,KAAK,UAAU,MACpD,IAAI,KAAK,eAAe,KAAK,WAAW,KAAK,KAAK;AASxD,UAAM,cAAc,KAAK,IAAI,QAAQ,UAAU,KAAK,UAAU,KAAK,IAAI,KAAK,eAAe,KAAK,WAAW;AAC3G,UAAM,UAAU,QAAQ,IAAI,QAAQ,IAAI;AACxC,UAAM,YAAY,WAAW,IAAI,UAAU,eAAe,aAAa,KAAK,GAAG,IAAI,UAAU;AAC7F,UAAM,cAAc,aAAa,MAC3B,cAAc,UAAU,KAAK,SAAS,OAAO,IAAI,SAClD,SAAS,KAAK,SAAS,SAAS;AACrC,UAAM,WAAW,WAAW,IAAI,UAAU,UAAU,UAAU;AAC9D,UAAM,aAAa,YAAY,KAAK,SAAS,KAAK,QAAQ,QAAQ;AAClE,QAAI,CAAC,cAAc,KAAK,OAAQ,MAAK,cAAc;AAInD,QAAI,KAAK,oBAAoB,UAAU,KAAK,CAAC,YAAa,MAAK,kBAAkB;AAEjF,QAAI,aAAa;AAGf,YAAM,YAAY,KAAK,eAAe,KAAK;AAC3C,UAAI,KAAK,mBAAmB,aAAa,KAAK,WAAW,OAAO,OAAO;AAIrE,cAAM,WAAW,KAAK,SAAS,SAAS;AACxC,aAAK,YAAY,EAAE,MAAM,WAAW,IAAI,OAAO,MAAM,GAAG,KAAK,UAAU,kBAAkB,KAAK,MAAM,SAAS,UAAU,aAAa,KAAK,oBAAI,IAAI,GAAG,IAAI,KAAK;AAAA,MAC/J;AACA,WAAK,iBAAiB;AACtB,WAAK,cAAc;AAGnB,eAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC7C,YAAI,MAAM,UAAW,MAAK,aAAa,CAAC;AAAA,MAC1C;AASA,YAAM,QAAQ,KAAK,YAAY,WAAW,QAAW,KAAK,oBAAoB,SAAS,CAAC;AACxF,YAAM,MAAM,KAAK,SAAS,SAAS;AACnC,YAAM,IAAI,WAAW,SAAS,GAAG;AAgBjC,YAAM,SAAS,KAAK,IAAI,SAAS,SAAS,EAAG,YAAY;AACzD,YAAM,QAAQ,KAAK,cAAc,WAAW,SAAS,QAAQ,KAAK;AAClE,YAAM,QAAQ,KAAK,cAAc,OAAO,QAAQ,IAAI;AACpD,YAAM,SAAS,SAAS,OAAO,OAAO,CAAC;AACvC,YAAM,YAAY,MAAM;AAGxB,YAAM,uBAAuB,KAAK,oBAAoB,SAAS,IAAI,KAAK,mBAAmB,OAAO,OAAO,QAAQ,GAAG,KAAK,cAAc,SAAS,CAAC,IAAI,IAAI;AACzJ,YAAM,YAAY,QAAQ,KAAK,UAAU,WAAW,IAAI,CAAC;AAAA,IAC3D,OAAO;AAEL,UAAI,KAAK,kBAAkB,GAAG;AAE5B,cAAM,UAAU,KAAK,eAAe,KAAK,cAAc;AACvD,aAAK,aAAa,OAAO;AACzB,YAAI,YAAY,KAAK,eAAgB,MAAK,aAAa,KAAK,cAAc;AAC1E,aAAK,iBAAiB;AACtB,aAAK,YAAY;AAAA,MACnB;AAEA,UAAI,UAAU,KAAK,aAAa;AAC9B,iBAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC7C,cAAI,MAAM,MAAO,MAAK,aAAa,CAAC;AAAA,QACtC;AACA,aAAK,cAAc;AAAA,MACrB;AAKA,YAAM,YAAY,KAAK,eAAe,KAAK;AAC3C,YAAM,eAAe,YAAY;AACjC,YAAM,UAAU,eAAe,KAAK,UAAU,WAAW,IAAI,IAAI,KAAK,UAAU,OAAO,IAAI;AAE3F,UAAI,cAAc,KAAK,KAAK;AAI1B,cAAM,IAAI,WAAW,SAAS,KAAK,QAAQ,QAAQ,CAAC;AACpD,YAAI,KAAK,YAAY,KAAK,SAAS,UAAU,OAAO;AAClD,eAAK,SAAS,MAAM,QAAQ;AAC5B,eAAK,WAAW;AAAA,QAClB;AACA,YAAI,CAAC,KAAK,SAAU,MAAK,WAAW,KAAK,eAAe,OAAO,eAAe,YAAY,KAAK;AAC/F,aAAK,gBAAgB,KAAK,UAAU,QAAQ,OAAO;AACnD,cAAM,MAAM,KAAK,eAAe,UAAU,QAAQ,IAAI;AACtD,aAAK,UAAU,KAAK,SAAS,QAAQ,CAAC;AACtC,aAAK,UAAU,IAAI,QAAQ,IAAI,CAAC;AAChC;AAAA,MACF;AAIA,YAAM,QAAQ,eAAe,KAAK,YAAY,OAAO,KAAK,WAAW,SAAS,CAAC,IAAI,KAAK,YAAY,KAAK;AACzG,YAAM,YAAY,QAAQ,OAAO;AACjC,UAAI,YAAY;AAGd,cAAM,MAAM,KAAK,eAAe,UAAU,QAAQ,IAAI;AACtD,aAAK,UAAU,IAAI,QAAQ,IAAI,WAAW,SAAS,KAAK,QAAQ,QAAQ,CAAC,CAAC;AAAA,MAC5E;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UAAU,QAAuB;AAC/B,SAAK,SAAS;AACd,QAAI,OAAQ,MAAK,KAAK;AAAA,QACjB,MAAK,MAAM;AAIhB,eAAW,SAAS,KAAK,UAAU;AACjC,aAAO,UAAU,IAAI;AAAA,IACvB;AACA,SAAK,QAAQ,MAAM,UAAU,IAAI;AACjC,SAAK,UAAU,MAAM,UAAU,IAAI;AACnC,SAAK,KAAK,UAAU,IAAI;AAAA,EAC1B;AAAA,EAEA,OAAO,OAAe,QAAgB,KAAoB;AAOxD,SAAK,SAAS,QAAQ;AACtB,SAAK,SAAS,SAAS;AACvB,QAAI,QAAQ,OAAW,MAAK,SAAS,MAAM;AAC3C,SAAK,YAAY;AACjB,eAAW,SAAS,KAAK,UAAU;AACjC,aAAO,OAAO,OAAO,QAAQ,GAAG;AAAA,IAClC;AACA,SAAK,QAAQ,MAAM,OAAO,OAAO,QAAQ,GAAG;AAC5C,SAAK,UAAU,MAAM,OAAO,OAAO,QAAQ,GAAG;AAC9C,SAAK,KAAK,OAAO,OAAO,QAAQ,GAAG;AAAA,EACrC;AAAA,EAEA,WAAW,OAA2B;AACpC,UAAM,MAAO,OAAO,UAAU,CAAC;AAI/B,UAAM,YAAY,CAAC,MAA2B,KAAK,QAAQ,QAAQ,OAAO,EAAE,SAAS,YAAY,EAAE,KAAK,WAAW,UAAU;AAC7H,UAAM,YAAY,IAAI,OAAO,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM,EAAE,KAAK,MAAM,WAAW,MAAM,EAAE,EAAE;AACpG,QAAI,UAAU,SAAS,GAAG;AACxB,iBAAW,KAAK,UAAW,MAAK,kBAAkB,IAAI,EAAE,MAAM,CAAC;AAC/D,WAAK,IAAK,WAAW,EAAE,GAAG,OAAO,QAAQ,UAAqC,CAAC;AAAA,IACjF;AACA,UAAM,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AAG9C,eAAW,KAAK,QAAQ;AACtB,UAAI,EAAE,SAAS,sBAAsB,OAAO,EAAE,SAAS,SAAU,MAAK,eAAe,IAAI,EAAE,MAAM,CAAC;AAAA,IACpG;AACA,UAAM,WAAW,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,kBAAkB;AACjE,QAAI,kBAAkB;AACtB,QAAI,aAAa,UAAa,OAAO,SAAS,UAAU,UAAU;AAChE,YAAM,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,IAAI,SAAS,SAAS,GAAG,KAAK,MAAM,SAAS,KAAe,CAAC,CAAC;AAIpG,WAAK,kBAAkB,KAAK,IAAI,QAAQ,QAAQ,KAAK,KAAK,IAAI,SAAS,SAAS;AAOhF,WAAK,cAAc,aAAa,KAAK,KAAK,GAAG,IAAI,KAAK;AACtD,WAAK,gBAAgB;AACrB,WAAK,YAAY,KAAK,WAAW,KAAK,IAAI;AAC1C,wBAAkB;AAAA,IACpB;AAEA,UAAM,cAAc,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,kBAAkB;AACtE,QAAI,YAAY,SAAS,GAAG;AAC1B,UAAI,KAAK,kBAAkB,GAAG;AAa5B,cAAM,OAAO,KAAK;AAClB,YAAI,MAAM;AACR,gBAAM,WAAW,KAAK,WAAW,KAAK,IAAI;AAC1C,cAAI,KAAK,OAAO,SAAS,SAAU,cAAa,QAAQ,UAAU,KAAK,KAAK,KAAK,SAAS,aAAa,KAAK,IAAI;AAChH,eAAK,KAAK;AAAA,QACZ;AACA,YAAI,CAAC,gBAAiB,MAAK,YAAY,KAAK,WAAW,KAAK,IAAI;AAAA,MAClE,WAAW,KAAK,eAAe,GAAG;AAIhC,cAAM,QAAQ,KAAK,SAAS,KAAK,WAAW;AAC5C,eAAO,WAAW,EAAE,GAAG,OAAO,QAAQ,YAAuC,CAAC;AAAA,MAChF;AAOA,WAAK,QAAQ,MAAM,WAAW,EAAE,GAAG,OAAO,QAAQ,YAAuC,CAAC;AAC1F,WAAK,UAAU,MAAM,WAAW,EAAE,GAAG,OAAO,QAAQ,YAAuC,CAAC;AAAA,IAC9F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,gBAAgB,MAA6B;AAC3C,QAAI,CAAC,uBAAuB,KAAK,KAAK,IAAI,EAAG,QAAO;AACpD,SAAK,MAAM;AAIX,QAAI,KAAK,OAAO,KAAK,IAAK,MAAK,IAAI,YAAY,oBAAoB,KAAK,SAAS,KAAK,GAAG,GAAG,KAAK,kBAAkB,OAAO,CAAC,CAAC;AAC5H,UAAM,OAAO,CAAC,OAAwC,UAAwB;AAC5E,UAAI,CAAC,MAAO;AACZ,YAAM,QAAQ,KAAK,WAAW,KAAK;AACnC,UAAI,CAAC,MAAM,UAAU;AAAE,cAAM,YAAY,KAAK,aAAa,KAAK,CAAC;AAAG;AAAA,MAAQ;AAK5E,YAAM,qBAAqB,OAAO,KAAK,eAAe,OAAO,CAAC;AAAA,IAChE;AACA,aAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,IAAK,MAAK,KAAK,SAAS,CAAC,GAAG,CAAC;AACvE,QAAI,KAAK,OAAQ,MAAK,KAAK,OAAO,OAAO,KAAK,OAAO,KAAK;AAC1D,QAAI,KAAK,SAAU,MAAK,KAAK,SAAS,OAAO,KAAK,SAAS,KAAK;AAChE,SAAK,YAAY;AAGjB,QAAI,KAAK,OAAQ,MAAK,YAAY,KAAK,WAAW,KAAK,IAAI;AAC3D,WAAO;AAAA,EACT;AAAA,EAEA,UAAgB;AACd,SAAK,KAAK;AACV,SAAK,cAAc;AACnB,aAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC7C,WAAK,aAAa,CAAC;AAAA,IACrB;AACA,SAAK,KAAK,QAAQ;AAClB,QAAI,KAAK,YAAY;AAGnB,WAAK,WAAW,QAAQ;AACxB,WAAK,WAAW,SAAS;AAAA,IAC3B;AACA,QAAI,KAAK,OAAQ,MAAK,OAAO,OAAO;AAAA,EACtC;AACF;AAEA,SAAS,iBAAiB,KAAkC;AAC1D,QAAM,aAAa,IAAI,SAAS,OAAO,CAAC,KAAK,MAAM;AACjD,UAAM,IAAI,EAAE,MAAM,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC;AACxD,WAAO,KAAK,IAAI,KAAK,CAAC;AAAA,EACxB,GAAG,CAAC;AAEJ,QAAM,WAAW,IAAI,MAAM,IAAI,IAAI,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC,IAAI;AAC7E,QAAM,WAAW,WAAW;AAC5B,QAAM,WAAW,WAAW,KAAK,SAAS,WAAW,MAAM,QAAQ,WAAW,MAAM,WAAW;AAC/F,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,OAAO,IAAI;AAAA,IACX,WAAW;AAAA,IACX,aAAa;AAAA,IACb,YAAY;AAAA,IACZ;AAAA,IACA,iBAAiB;AAAA,IACjB,uBAAuB;AAAA,IACvB,MAAM,EAAE,WAAW,KAAK;AAAA,IACxB,aAAa;AAAA,EACf;AACF;AAEO,SAAS,gBAAgB,MAAoC;AAClE,QAAM,QAAQ,oBAAoB,IAAI;AACtC,SAAO;AAAA,IACL,UAAU,iBAAiB,KAAK;AAAA,IAChC,OAAO,CAAC,QAA8B,IAAI,iBAAiB,OAAO,GAAG;AAAA,IACrE,MAAM;AAAA,EACR;AACF;;;AKt9FA,SAAS,aAAAM,kBAAiB;;;ACsB1B,SAAS,kBAAkB,IAA+D;AACxF,QAAM,IAAI,GAAG,MAAM;AACnB,QAAM,IAAI,KAAK,MAAM,GAAG,YAAY,CAAC;AACrC,MAAI,IAAI,EAAG,QAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,YAAY,GAAG,CAAC;AACxD,QAAM,MAAgD,CAAC;AACvD,WAAS,QAAQ,GAAG,QAAQ,GAAG,QAAS,KAAI,KAAK,UAAU,QAAQ,OAAO,GAAG,GAAG,OAAO,CAAC,CAAC;AACzF,SAAO;AACT;AAGO,SAAS,QAAQ,KAAqB;AAC3C,QAAM,IAAI,IAAI,WAAW,IAAI,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK;AACzF,QAAM,IAAI,SAAS,EAAE,MAAM,CAAC,GAAG,EAAE;AACjC,MAAI,OAAO,MAAM,CAAC,EAAG,QAAO;AAC5B,QAAM,KAAM,KAAK,KAAM,OAAO;AAC9B,QAAM,KAAM,KAAK,IAAK,OAAO;AAC7B,QAAM,KAAK,IAAI,OAAO;AACtB,SAAO,SAAS,IAAI,SAAS,IAAI,SAAS;AAC5C;AAEO,SAAS,WAAW,OAAkB,GAAmB;AAC9D,QAAM,IAAI,MAAM;AAChB,MAAI,EAAE,SAAS,aAAa,cAAc,CAAC,GAAG;AAI5C,UAAM,OAAO,EAAE,SAAS,EAAE,UAAU,KAAK,EAAE;AAC3C,QAAI,MAAM,GAAG,OAAO;AACpB,eAAW,QAAQ,UAAU,CAAC,GAAG;AAC/B,YAAM,KAAK,QAAQ,KAAK,SAAS,IAAI;AACrC,UAAI;AACJ,UAAI,CAAC,KAAK,KAAM,KAAI,KAAK,SAAS,QAAQ,KAAK,OAAO,KAAK,IAAI;AAAA,eACtD,KAAK,UAAU;AACtB,YAAI,IAAI;AACR,mBAAW,MAAM,KAAK,SAAS,OAAO;AAAE,gBAAM,IAAI,GAAG,WAAW;AAAG,eAAK,QAAQ,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI;AAAA,QAAI;AAC9G,YAAI,IAAI,KAAK,SAAS,MAAM;AAAA,MAC9B,MAAO,KAAI;AACX,YAAM,IAAI,KAAK,IAAI,MAAM,KAAK,OAAO,YAAY,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,GAAG,IAAI,KAAK;AACzI,aAAO,IAAI;AAAG,cAAQ;AAAA,IACxB;AACA,QAAI,OAAO,EAAG,QAAO,MAAM;AAAA,EAC7B;AACA,MAAI,eAAe,CAAC,GAAG;AACrB,WAAO,QAAQ,EAAE,SAAS,EAAE,UAAU,KAAK,EAAE,KAAK;AAAA,EACpD;AACA,MAAI,EAAE,SAAS,UAAU,EAAE,SAAS,YAAa,QAAO,QAAQ,EAAE,SAAS,SAAS;AACpF,SAAO;AACT;AAGO,SAAS,UAAU,OAAkB,GAA0B;AACpE,QAAM,IAAI,MAAM;AAChB,MAAI,eAAe,CAAC,GAAG;AACrB,WAAO,EAAE,SAAS,EAAE,UAAU,KAAK,EAAE;AAAA,EACvC;AACA,MAAI,EAAE,SAAS,UAAU,EAAE,SAAS,YAAa,QAAO,EAAE,SAAS;AACnE,SAAO;AACT;AAOO,SAAS,eAAe,MAAyB;AACtD,QAAM,KAAK,KAAK;AAChB,MAAI,CAAC,MAAM,GAAG,SAAS,QAAS,QAAO,QAAQ,IAAI,SAAS,SAAS;AACrE,MAAI,GAAG,SAAS,SAAS;AACvB,UAAM,OAAO,kBAAkB,EAAE;AACjC,WAAO,KAAK,OAAO,CAAC,GAAG,MAAM,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,KAAK;AAAA,EAC5D;AACA,SAAO,GAAG,MAAM,OAAO,CAAC,GAAG,OAAO,IAAI,QAAQ,GAAG,KAAK,GAAG,CAAC,IAAI,GAAG,MAAM;AACzE;AAGO,SAAS,OAAO,KAAkD;AACvE,QAAM,IAAI,IAAI,WAAW,IAAI,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK;AACzF,QAAM,IAAI,SAAS,EAAE,MAAM,CAAC,GAAG,EAAE;AACjC,MAAI,OAAO,MAAM,CAAC,EAAG,QAAO,EAAE,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI;AACrD,SAAO,EAAE,IAAK,KAAK,KAAM,OAAO,KAAK,IAAK,KAAK,IAAK,OAAO,KAAK,IAAI,IAAI,OAAO,IAAI;AACrF;AAIO,SAAS,cAAc,MAAsD;AAClF,QAAM,KAAK,KAAK;AAChB,MAAI,CAAC,MAAM,GAAG,SAAS,QAAS,QAAO,OAAO,IAAI,SAAS,SAAS;AACpE,MAAI,GAAG,SAAS,SAAS;AACvB,UAAM,OAAO,kBAAkB,EAAE;AACjC,UAAMC,OAAM,KAAK,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AACzG,WAAO,EAAE,GAAGA,KAAI,IAAI,KAAK,SAAS,KAAK,GAAGA,KAAI,IAAI,KAAK,SAAS,KAAK,GAAGA,KAAI,IAAI,KAAK,SAAS,IAAI;AAAA,EACpG;AACA,QAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,GAAG,KAAK;AAC7C,QAAM,MAAM,QAAQ;AAAA,IAClB,CAAC,GAAG,QAAQ;AACV,YAAM,IAAI,OAAO,GAAG;AACpB,aAAO,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,EAAE;AAAA,IACpD;AAAA,IACA,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE;AAAA,EACrB;AACA,QAAM,IAAI,QAAQ,UAAU;AAC5B,SAAO,EAAE,GAAG,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,EAAE;AACpD;AAsBO,SAAS,iBACd,OACA,QACA,IACQ;AACR,MAAI,MAAM,UAAU,aAAa,MAAM,UAAU,SAAU,QAAO,OAAO;AACzE,QAAM,KAAK,OAAO,IAAI,IAAI,GAAG,IAAI;AACjC,QAAM,KAAK,OAAO,IAAI,IAAI,GAAG,IAAI;AACjC,QAAM,KAAK,OAAO,IAAI,IAAI,GAAG,IAAI;AAGjC,SAAO,KAAK,MAAM,KAAK,KAAK,KAAK,KAAK,KAAK,MAAM,CAAC;AACpD;AAWA,SAAS,aAAa,GAAmB;AACvC,SAAO,KAAK,UAAU,IAAI,QAAQ,KAAK,KAAK,IAAI,SAAS,OAAO,GAAG;AACrE;AAGO,SAAS,kBAAkB,KAAkB;AAClD,SAAO,SAAS,aAAa,IAAI,CAAC,IAAI,SAAS,aAAa,IAAI,CAAC,IAAI,SAAS,aAAa,IAAI,CAAC;AAClG;AAOO,SAAS,gBAAgB,GAAQ,GAAgB;AACtD,QAAM,KAAK,kBAAkB,CAAC;AAC9B,QAAM,KAAK,kBAAkB,CAAC;AAC9B,QAAM,KAAK,KAAK,IAAI,IAAI,EAAE;AAC1B,QAAM,KAAK,KAAK,IAAI,IAAI,EAAE;AAC1B,UAAQ,KAAK,SAAS,KAAK;AAC7B;AAeO,SAAS,gBAAgB,MAAiB,KAAa,GAAW,MAAc,KAAc,GAAY,MAAe,IAAI,GAAQ;AAC1I,QAAM,KAAK,KAAK;AAChB,MAAI,CAAC,MAAM,GAAG,SAAS,QAAS,QAAO,OAAO,IAAI,SAAS,SAAS;AACpE,MAAI,GAAG,SAAS,SAAS;AACvB,QAAI,QAAQ,UAAa,MAAM,OAAW,QAAO,cAAc,IAAI;AACnE,UAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AACxC,UAAM,KAAK,gBAAgB,IAAI,CAAC;AAChC,UAAM,IAAI,WAAW,MAAM,OAAO,MAAM,OAAO,IAAI,IAAI,QAAQ,KAAK,QAAQ,EAAE;AAC9E,WAAO,EAAE,GAAG,EAAE,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC,IAAI,IAAI;AAAA,EACvD;AACA,MAAI,GAAG,MAAM;AACX,UAAM,KAAK,GAAG,KAAK,SAAS;AAC5B,QAAI,OAAO,IAAI,GAAI,QAAO,OAAO,GAAG,KAAK,KAAK;AAAA,EAChD;AACA,QAAM,QAAQ,CAAC,GAAG,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE;AACtD,QAAM,IAAI,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI;AACtD,QAAM,QAAQ,MAAM,CAAC;AACrB,QAAM,OAAO,MAAM,MAAM,SAAS,CAAC;AACnC,MAAI,KAAK,MAAM,GAAI,QAAO,OAAO,MAAM,KAAK;AAC5C,MAAI,KAAK,KAAK,GAAI,QAAO,OAAO,KAAK,KAAK;AAC1C,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,IAAI,MAAM,IAAI,CAAC;AACrB,UAAM,IAAI,MAAM,CAAC;AACjB,QAAI,IAAI,EAAE,GAAI;AACd,UAAM,OAAO,EAAE,KAAK,EAAE;AACtB,UAAM,IAAI,OAAO,KAAK,IAAI,EAAE,MAAM,OAAO;AACzC,UAAM,KAAK,OAAO,EAAE,KAAK;AACzB,UAAM,KAAK,OAAO,EAAE,KAAK;AACzB,WAAO,EAAE,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,EAAE;AAAA,EACjG;AACA,SAAO,OAAO,KAAK,KAAK;AAC1B;AASO,SAAS,gBAAgB,QAAa,QAAa,OAAoB;AAC5E,SAAO;AAAA,IACL,GAAG,OAAO,KAAK,OAAO,IAAI,OAAO,KAAK;AAAA,IACtC,GAAG,OAAO,KAAK,OAAO,IAAI,OAAO,KAAK;AAAA,IACtC,GAAG,OAAO,KAAK,OAAO,IAAI,OAAO,KAAK;AAAA,EACxC;AACF;AAQO,SAAS,cAAc,QAAa,QAAa,OAAe,OAAkC;AACvG,QAAM,MAAM,CAAC,GAAW,MAAsB;AAC5C,UAAM,IAAI,IAAI;AACd,WAAO,UAAU,YAAY,KAAK,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,MAAM,IAAI;AAAA,EACvE;AACA,SAAO,EAAE,GAAG,IAAI,OAAO,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,OAAO,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,OAAO,GAAG,OAAO,CAAC,EAAE;AAC9F;;;AChOA,IAAM,cAAc;AAQpB,IAAM,iBAAiB;AAOhB,IAAM,aAAa;AAG1B,IAAM,kBAAkB;AAOxB,IAAM,aAAa;AA6DnB,IAAM,aAAa;AAEnB,SAAS,YAAY,IAAY,IAAY,GAAkB;AAC7D,SAAO;AAAA,IACL;AAAA,IAAI;AAAA,IAAI,IAAI;AAAA,IAAG,MAAM,KAAK,KAAK,IAAI;AAAA,IACnC,UAAU,CAAC,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,MAAM,IAAI;AAAA,IACpE,SAAS,CAAC,MAAM,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,MAAM;AAClD,YAAM,IAAK,IAAI,IAAK,KAAK,KAAK;AAC9B,YAAM,QAAQ,KAAK,IAAI;AACvB,aAAO,EAAE,GAAG,KAAK,QAAQ,KAAK,IAAI,CAAC,GAAG,GAAG,KAAK,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,IACpE,CAAC;AAAA,EACH;AACF;AAGA,SAAS,UAAU,IAAY,IAAY,KAAoD;AAI7F,QAAM,MAAM,IAAI,OAAO,CAAC,GAAG,MAAM;AAC/B,UAAM,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM;AAClC,WAAO,KAAK,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI;AAAA,EAC5C,CAAC;AAGD,MAAI,IAAI,SAAS,EAAG,QAAO;AAE3B,MAAI,KAAK;AACT,aAAW,KAAK,IAAK,MAAK,KAAK,IAAI,IAAI,KAAK,MAAM,EAAE,IAAI,IAAI,EAAE,IAAI,EAAE,CAAC;AACrE,QAAMC,UAAS,CAAC,GAAW,MAAuB;AAChD,QAAI,MAAM;AACV,aAAS,IAAI,GAAG,IAAI,IAAI,SAAS,GAAG,IAAI,IAAI,QAAQ,IAAI,KAAK;AAC3D,YAAM,IAAI,IAAI,CAAC;AACf,YAAM,IAAI,IAAI,CAAC;AACf,UAAK,EAAE,IAAI,MAAQ,EAAE,IAAI,KAAM,KAAM,EAAE,IAAI,EAAE,MAAM,IAAI,EAAE,MAAO,EAAE,IAAI,EAAE,KAAK,EAAE,EAAG,OAAM,CAAC;AAAA,IAC3F;AACA,WAAO;AAAA,EACT;AACA,QAAM,MAAM,IAAI,IAAI,CAAC,GAAG,MAAM;AAC5B,UAAM,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM;AAClC,WAAO,KAAK,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AAAA,EACxC,CAAC;AACD,QAAM,YAAY,IAAI,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC;AAI/C,QAAM,WAAW,KAAK,IAAI,GAAG,GAAG;AAChC,QAAM,OAAO,KAAK,IAAI,KAAK,YAAY,WAAW,IAAI;AACtD,QAAM,OAAO,YAAY,GAAG;AAC5B,MAAI,EAAE,OAAO,GAAI,QAAO;AACxB,SAAO;AAAA,IACL;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ,UAAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQV,SAAS,CAAC,MAAM;AACd,UAAI,EAAE,YAAY,GAAI,QAAO,CAAC;AAC9B,YAAM,MAAuC,CAAC;AAC9C,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAI,IAAK,IAAI,IAAK;AAClB,YAAI,IAAI;AACR,eAAO,IAAI,IAAI,SAAS,KAAK,IAAI,IAAI,CAAC,GAAI;AAAE,eAAK,IAAI,CAAC;AAAI;AAAA,QAAK;AAC/D,cAAM,IAAI,IAAI,CAAC;AACf,cAAM,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM;AAClC,cAAM,MAAM,IAAI,CAAC;AACjB,cAAM,IAAI,IAAI;AACd,cAAM,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK;AAC/B,cAAM,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK;AAC/B,cAAM,MAAM,EAAE,IAAI,EAAE,KAAK;AACzB,cAAM,MAAM,EAAE,IAAI,EAAE,KAAK;AASzB,iBAAS,IAAI,MAAM,IAAI,GAAG,KAAK,GAAG;AAChC,gBAAM,MAAM,KAAK,KAAK;AACtB,gBAAM,MAAM,KAAK,KAAK;AACtB,cAAIA,QAAO,KAAK,GAAG,GAAG;AAAE,gBAAI,KAAK,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC;AAAG;AAAA,UAAO;AAC7D,gBAAM,MAAM,KAAK,KAAK;AACtB,gBAAM,MAAM,KAAK,KAAK;AACtB,cAAIA,QAAO,KAAK,GAAG,GAAG;AAAE,gBAAI,KAAK,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC;AAAG;AAAA,UAAO;AAC7D,cAAI,IAAI,OAAO,KAAM;AAAA,QACvB;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,SAAS,UAAU,IAAY,IAAY,OAAe,OAAe,KAA2B;AAClG,QAAM,MAAM,KAAK,IAAI,GAAG;AACxB,QAAM,MAAM,KAAK,IAAI,GAAG;AACxB,QAAM,SAAS,CAAC,IAAY,QAAgB,EAAE,GAAG,KAAK,KAAK,MAAM,KAAK,KAAK,GAAG,KAAK,KAAK,MAAM,KAAK,IAAI;AACvG,SAAO,UAAU,IAAI,IAAI;AAAA,IACvB,OAAO,CAAC,OAAO,CAAC,KAAK;AAAA,IAAG,OAAO,OAAO,CAAC,KAAK;AAAA,IAAG,OAAO,OAAO,KAAK;AAAA,IAAG,OAAO,CAAC,OAAO,KAAK;AAAA,EAC3F,CAAC;AACH;AAEA,SAAS,aAAa,IAAY,IAAY,KAAsC,KAA2B;AAC7G,QAAM,MAAM,KAAK,IAAI,GAAG;AACxB,QAAM,MAAM,KAAK,IAAI,GAAG;AACxB,SAAO,UAAU,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,GAAG,KAAK,EAAE,IAAI,MAAM,EAAE,IAAI,KAAK,GAAG,KAAK,EAAE,IAAI,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;AAC7G;AAGA,SAAS,QAAQ,OAAkB,GAAW,GAAW,GAAW,GAAyB;AAC3F,QAAM,IAAI,MAAM;AAChB,MAAI,EAAE,SAAS,YAAY,EAAE,SAAS,UAAU,EAAE,SAAS,UAAW,QAAO;AAC7E,QAAM,IAAI,WAAW,GAAG,GAAG,GAAG,CAAC;AAC/B,QAAM,KAAK,OAAO,GAAG,CAAC;AACtB,MAAI,EAAE,KAAK,GAAI,QAAO;AACtB,MAAI,EAAE,SAAS,SAAU,QAAO,YAAY,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;AAC5D,QAAM,MAAM,WAAW,GAAG,CAAC;AAC3B,MAAI,EAAE,SAAS,QAAQ;AACrB,UAAM,KAAK,EAAE,UAAU,SAAY,EAAE,SAAS,EAAE,OAAO,IAAI,KAAK,EAAE,OAAO,KAAK;AAC9E,WAAO,UAAU,EAAE,GAAG,EAAE,GAAG,KAAK,GAAG,KAAK,GAAG,GAAG;AAAA,EAChD;AACA,SAAO,aAAa,EAAE,GAAG,EAAE,GAAG,cAAc,GAAG,KAAK,CAAC,GAAG,GAAG;AAC7D;AAaO,SAAS,YAAY,OAAiC;AAC3D,QAAM,IAAI,MAAM;AAChB,OAAK,EAAE,SAAS,YAAY,EAAE,SAAS,cAAc,EAAE,MAAM;AAC3D,WAAO;AAAA,EACT;AACA,MAAI,EAAE,SAAS,UAAU,EAAE,SAAS;AAClC,WAAO;AAAA,EACT;AACA,MAAI,MAAM,OAAO;AACf,WAAO,UAAU,MAAM,KAAK;AAAA,EAC9B;AACA,QAAM,CAAC,IAAI,EAAE,IAAI,MAAM,SAAS,CAAC,GAAG,CAAC;AACrC,MAAI,KAAK,KAAK,KAAK,GAAG;AACpB,WAAO,SAAS,OAAO,KAAK,KAAK,GAAG,EAAE,KAAK,EAAE,EAAE;AAAA,EACjD;AACA,MAAI,MAAM,SAAS,MAAM,MAAM,MAAM,GAAG;AACtC,WAAO;AAAA,EACT;AAIA,QAAM,UAAU,YAAY,KAAK,MAAM,QAAQ,EAAE,MAAM,IAAI,EAAE,SAAS;AACtE,QAAM,UAAU,kBAAkB,KAAK,MAAM,QAAQ,EAAE,YAAY,IAAI,EAAE,eAAe;AACxF,MAAI,SAAS;AACX,UAAM,UAAU,YAAY,QAAQ,QAAQ,WAAW,QAAQ;AAC/D,UAAM,YAAY,IAAI,IAAI,QAAQ,OAAO,CAAC,GAAG,MAAM,CAAC,YAAY,QAAS,CAAC,KAAK,KAAK,CAAC,CAAC;AACtF,QAAI,UAAU,OAAO,GAAG;AACtB,aAAO,qBAAqB,UAAU,IAAI;AAAA,IAC5C;AAAA,EACF;AACA,SAAO;AACT;AAWO,SAAS,WACd,QACA,GACA,GACA,GACiB;AACjB,SAAO,OAAO,IAAI,CAAC,EAAE,OAAO,SAAS,GAAG,eAAe;AACrD,UAAM,YAAY,YAAY,KAAK;AACnC,UAAM,OAAiD;AAAA,MACrD;AAAA,MACA,KAAK,MAAM;AAAA,MACX,UAAU,cAAc;AAAA,MACxB;AAAA,IACF;AAIA,QAAI,YAAY,MAAM,MAAM,CAAC,KAAK,EAAG,QAAO,EAAE,GAAG,MAAM,SAAS,MAAM,OAAO,KAAK;AAElF,UAAM,SAA8B,SAAS,IAAI,CAAC,MAAM,QAAQ,OAAO,GAAG,GAAG,GAAG,CAAC,CAAC;AAGlF,UAAM,QAAQ,OAAO,OAAO,CAAC,MAAkB,MAAM,QAAQ,EAAE,OAAO,CAAC;AAGvE,QAAI,MAAM,SAAS,EAAG,QAAO,EAAE,GAAG,MAAM,SAAS,MAAM,OAAO,KAAK;AAEnE,UAAM,SAAS,KAAK,IAAI,GAAG,KAAK,KAAK,MAAM,SAAS,UAAU,CAAC;AAC/D,QAAI,UAAU;AACd,QAAI,SAAS;AACb,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,QAAQ;AAC7C,YAAM,OAAO,MAAM,CAAC;AACpB,YAAM,MAAM,KAAK,QAAQ,eAAe;AACxC,UAAI,IAAI,WAAW,EAAG;AACtB,UAAI,MAAM;AACV,iBAAW,KAAK,KAAK;AACnB,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,cAAI,MAAM,EAAG;AACb,gBAAM,QAAQ,MAAM,CAAC;AACrB,gBAAM,KAAK,EAAE,IAAI,MAAM;AACvB,gBAAM,KAAK,EAAE,IAAI,MAAM;AACvB,cAAI,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK,MAAM,GAAI;AAC7C,cAAI,MAAM,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG;AAAE;AAAO;AAAA,UAAO;AAAA,QAChD;AAAA,MACF;AACA,iBAAW,MAAM,IAAI;AACrB;AAAA,IACF;AAEA,QAAI,WAAW,EAAG,QAAO,EAAE,GAAG,MAAM,SAAS,MAAM,OAAO,KAAK;AAC/D,UAAM,UAAU,QAAQ,UAAU,QAAQ,QAAQ,CAAC,CAAC;AACpD,UAAM,QAAsB,UAAU,cAAc,UAAU,cAAc,OAAO,SAAS;AAC5F,WAAO,EAAE,GAAG,MAAM,SAAS,MAAM;AAAA,EACnC,CAAC;AACH;AAOO,SAAS,kBAAkB,OAAkB,GAAkB,aAA8B;AAClG,MAAI,EAAE,UAAU,YAAY,cAAc,EAAG,QAAO;AACpD,QAAM,CAAC,IAAI,EAAE,IAAI,MAAM,SAAS,CAAC,GAAG,CAAC;AACrC,OAAK,KAAK,MAAM,IAAI,eAAgB,QAAO;AAC3C,SAAO,MAAM,UAAU,aAAa,MAAM,UAAU;AACtD;;;ACvWA,SAAS,aAAAC,kBAAiB;AA6C1B,IAAM,gBAAgB;AAWtB,IAAM,aAAa;AAcnB,IAAM,wBAAwB;AAG9B,IAAM,oBAAoB;AA0B1B,SAAS,WAAW,MAAiB,MAAmC;AACtE,QAAM,EAAE,OAAO,GAAG,QAAQ,EAAE,IAAI,KAAK,YAAY,EAAE,OAAO,MAAM,QAAQ,KAAK;AAI7E,QAAM,OAAO,cAAc,KAAK,QAAQ,KAAK,QAAQ,EAAE;AACvD,QAAM,EAAE,OAAO,WAAW,IAAI,aAAa,MAAM,GAAG,CAAC;AACrD,QAAM,MAAMC,WAAU,IAAI;AAC1B,QAAM,SAAS,KAAK,OAAO,IAAI,CAAC,WAAW,EAAE,OAAO,UAAU,cAAc,OAAO,KAAK,GAAG,GAAG,OAAO,UAAU,EAAE,EAAE;AACnH,QAAM,QAAQ,oBAAI,IAAsB;AACxC,aAAW,EAAE,OAAO,SAAS,KAAK,OAAQ,KAAI,MAAM,IAAK,OAAM,IAAI,MAAM,KAAK,QAAQ;AACtF,MAAI,aAAgD;AACpD,aAAW,EAAE,OAAO,SAAS,KAAK,QAAQ;AAExC,UAAM,MAAM,SAAS,MAAM,OAAO,GAAG,GAAG,KAAK;AAC7C,QAAI,CAAC,IAAK;AACV,mBAAe,oBAAI,IAAI;AACvB,eAAW,KAAK,SAAU,YAAW,IAAI,GAAG,GAAG;AAAA,EACjD;AACA,SAAO,EAAE,GAAG,GAAG,OAAO,MAAM,QAAQ,OAAO,WAAW;AACxD;AAGA,SAAS,MAAM,OAAmB,GAAW,GAAqC;AAChF,QAAM,IAAI,WAAW,GAAG,GAAG,MAAM,GAAG,MAAM,CAAC;AAC3C,MAAI,EAAE,aAAa;AACjB,UAAM,SAAS,MAAM,MAAM,IAAI,EAAE,WAAW,IAAI,CAAC;AACjD,QAAI,QAAQ;AACV,YAAM,KAAK,WAAW,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AACjD,QAAE,KAAK,GAAG;AACV,QAAE,KAAK,GAAG;AAAA,IACZ;AAAA,EACF;AACA,QAAM,MAAM,MAAM,YAAY,IAAI,CAAC;AACnC,SAAO,MAAM,IAAI,CAAC,IAAI;AACxB;AAWA,SAAS,aAAa,MAAiB,GAAW,GAAmB;AACnE,SAAO,KAAK,UAAU,OAAO,IAAI,KAAK,IAAI,GAAG,CAAC,KAAK,KAAK,qBAAqB,OAAO;AACtF;AAGA,SAAS,WAAW,GAAmD,MAAc,WAA2B;AAC9G,QAAM,IAAI,EAAE,OAAO,oBAAoB,KAAK,EAAE,IAAI,IAAI;AACtD,SAAO,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,YAAY;AACxC;AAEA,SAAS,QACP,GACA,GACA,GACA,WACA,WAC0D;AAC1D,QAAM,KAAK,WAAW,GAAG,EAAE,MAAM,SAAS;AAC1C,QAAM,MAAM,EAAE,QAAQ,EAAE,WAAW,KAAK,EAAE,QAAQ,CAAC,KAAK;AAExD,QAAM,MAAM,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,IAAI,IAAI,QAAQ,EAAE,CAAC;AAC7D,QAAM,KAAK,EAAE,WAAW,KAAK,IAAI,KAAK,EAAE,WAAW,SAAS,IAAI;AAChE,QAAM,QAAQ,EAAE,SAAS;AACzB,QAAM,WAAW,EAAE,YAAY;AAC/B,SAAO;AAAA,IACL,IAAI,UAAU,SAAS,EAAE,IAAI,KAAK,IAAI,UAAU,UAAU,EAAE,IAAI,KAAK,IAAI,EAAE;AAAA,IAC3E,IAAI,aAAa,QAAQ,EAAE,IAAI,KAAK,MAAM,aAAa,WAAW,EAAE,IAAI,KAAK,MAAM,EAAE;AAAA,IACrF,OAAO,KAAK;AAAA,IACZ,OAAO,KAAK;AAAA,EACd;AACF;AAEA,SAAS,aACP,GACA,IACA,GACA,GACA,GAC0D;AAC1D,QAAM,YAAY,KAAK,IAAI,GAAG,CAAC;AAC/B,QAAM,OAAO,EAAE,WAAW;AAC1B,QAAM,MAAM,EAAE,cAAc,OAAO;AACnC,QAAM,SAAS,EAAE,WAAW;AAC5B,QAAM,SAAS,SAAS;AACxB,QAAM,QAAQ,eAAe,EAAE,MAAM,QAAQ,oBAAoB,EAAE,IAAI,CAAC;AACxE,QAAM,SAAS,MAAM,SAAS;AAC9B,QAAM,WAAW,MAAM,OAAO,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,OAAO,GAAG,CAAC,IAAI;AACrE,QAAM,QAAQ,EAAE,SAAS;AACzB,QAAM,KAAK,UAAU,WAAW,EAAE,IAAI,SAAS,IAC3C,UAAU,UAAU,EAAE,IAAI,SAAS,WAAW,IAC9C,EAAE,IAAI,WAAW;AAErB,QAAM,EAAE,IAAI,GAAG,IAAI,sBAAsB,GAAG,QAAQ,UAAU,MAAM;AACpE,SAAO;AAAA,IACL,IAAI,KAAK;AAAA,IACT,IAAI,EAAE,IAAI,SAAS,IAAI;AAAA,IACvB,OAAO,WAAW;AAAA,IAClB,OAAO,SAAS;AAAA,EAClB;AACF;AAOA,SAAS,wBACP,GACA,GACA,GACA,GACQ;AACR,MAAI,CAAC,EAAE,OAAQ,QAAO;AACtB,QAAM,YAAY,KAAK,IAAI,GAAG,CAAC;AAC/B,QAAM,SAAU,EAAE,WAAW,aAAc,EAAE,WAAW;AACxD,QAAM,QAAQ,eAAe,EAAE,MAAM,QAAQ,oBAAoB,EAAE,IAAI,CAAC;AACxE,QAAM,KAAK,YAAY,OAAO,EAAE,QAAQ,CAAC;AACzC,MAAI,GAAG,aAAa;AAGlB,QAAI,MAAM;AACV,QAAI,IAAI;AACR,eAAW,QAAQ,GAAG,YAAa,YAAW,KAAK,MAAM;AAAE,aAAO;AAAG;AAAA,IAAK;AAC1E,WAAO,IAAI,IAAI,MAAM,IAAI;AAAA,EAC3B;AACA,SAAO,GAAG;AACZ;AAgBA,SAAS,WAAW,IAAkB,GAAW,GAA8C;AAC7F,MAAI;AACJ,MAAI,GAAG,SAAS,UAAU;AACxB,UAAM,KAAK,GAAG,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,GAAG,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC;AAC3D,UAAM,OAAO,KAAK,KAAK,KAAK,MAAM;AAClC,UAAM,IAAI,GAAG,KAAK,CAAC,KAAK,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,MAAM;AAAA,EACxD,OAAO;AACL,QAAI,KAAK,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC,IAAI,GAAG;AAAA,EAC1D;AACA,QAAM,KAAK,GAAG;AACd,MAAI,KAAK,IAAI,GAAG,CAAC,EAAG,IAAI,KAAK,IAAI,GAAG,GAAG,SAAS,CAAC,EAAG,IAAI,CAAC,CAAC;AAC1D,MAAI,IAAI;AACR,SAAO,IAAI,GAAG,SAAS,KAAK,IAAI,GAAG,IAAI,CAAC,EAAG,GAAI;AAC/C,QAAM,IAAI,GAAG,CAAC,GAAI,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,GAAG,SAAS,CAAC,CAAC;AACvD,QAAM,IAAI,EAAE,KAAK,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM;AACrD,SAAO,EAAE,MAAM,QAAQ,EAAE,KAAK,KAAK,IAAI,KAAK,QAAQ,EAAE,KAAK,IAAI,GAAG,UAAU,EAAE,WAAW,MAAM,IAAI,MAAM,EAAE,WAAW,KAAK,EAAE;AAC/H;AAEA,SAAS,oBACP,KACA,OACA,OACA,IACA,IACA,IACA,IACA,UAAU,OACI;AACd,QAAM,KAAK,KAAK,KAAK;AACrB,QAAM,MAAM,IAAI,aAAa,MAAM,KAAK,KAAK,EAAE;AAC/C,QAAM,OAAO,KAAK;AAClB,QAAM,QAAQ,KAAK,KAAK;AACxB,QAAM,QAAQ,IAAI;AAClB,QAAM,OAA0C,CAAC;AACjD,QAAM,UAAU,CAAC,KAAa,IAAY,OAAqB;AAC7D,UAAM,IAAI,KAAK,IAAI,MAAM,EAAE;AAC3B,UAAM,IAAI,KAAK,IAAI,MAAM,EAAE;AAC3B,QAAI,EAAE,IAAI,GAAI;AACd,UAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC;AAChD,UAAM,OAAO,KAAK,IAAI,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC;AAC/C,aAAS,IAAI,OAAO,KAAK,MAAM,KAAK;AAClC,YAAM,MAAM,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,IAAI,KAAK,IAAI,GAAG,IAAI,KAAK;AAChE,UAAI,MAAM,EAAG,KAAI,MAAM,MAAM,IAAI,GAAG,KAAO,MAAM,QAAS;AAAA,IAC5D;AAAA,EACF;AACA,WAAS,IAAI,IAAI,KAAK,IAAI,KAAK;AAC7B,aAAS,IAAI,GAAG,IAAI,mBAAmB,KAAK;AAC1C,YAAM,KAAK,KAAK,IAAI,OAAO,qBAAqB;AAChD,WAAK,SAAS;AACd,eAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,cAAM,IAAI,IAAI,CAAC;AACf,cAAM,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM;AAClC,cAAM,OAAO,EAAE,KAAK,KAAK,EAAE,IAAI;AAC/B,YAAI,CAAC,QAAQ,EAAE,EAAE,KAAK,KAAK,EAAE,IAAI,GAAI;AACrC,aAAK,KAAK,EAAE,GAAG,EAAE,KAAM,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAO,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC;AAAA,MACpF;AACA,UAAI,KAAK,SAAS,EAAG;AACrB,WAAK,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC;AAC7B,UAAI,OAAO;AACX,UAAI,QAAQ;AACZ,YAAM,SAAS,CAAC,MAAwB,WAAW,IAAI,OAAO,IAAI,MAAM;AACxE,iBAAW,OAAO,MAAM;AACtB,cAAM,SAAS,OAAO,IAAI;AAC1B,gBAAQ,IAAI;AACZ,cAAM,QAAQ,OAAO,IAAI;AACzB,YAAI,CAAC,UAAU,MAAO,SAAQ,IAAI;AAAA,iBACzB,UAAU,CAAC,MAAO,SAAQ,IAAI,IAAI,OAAO,IAAI,CAAC;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAqCA,SAAS,YAAY,GAAmB;AACtC,MAAI,KAAK,EAAG,QAAO;AACnB,MAAI,KAAK,EAAG,QAAO;AACnB,SAAO,KAAK,OAAO,IAAK,OAAO,IAAK,OAAO,QAAQ,KAAK,IAAI,QAAQ;AACtE;AAGA,IAAM,iBAAiB;AAWvB,SAAS,YAAY,IAAY,IAAY,QAAgB,QAAgB,MAAe,IAAY,IAAY,IAAY,IAAoB;AAClJ,QAAM,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,EAAE,CAAC,IAAI;AACjD,QAAM,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,EAAE,CAAC,IAAI;AACjD,QAAM,OAAO,KAAK,MAAM,IAAI,EAAE;AAC9B,QAAM,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,EAAE,GAAG,KAAK,IAAI,KAAK,KAAK,EAAE,CAAC;AAC7D,QAAM,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,EAAE,GAAG,KAAK,IAAI,KAAK,KAAK,EAAE,CAAC;AAC7D,QAAM,MAAM,KAAK,MAAM,IAAI,EAAE;AAC7B,MAAI,QAAQ,UAAU,OAAO,OAAQ,QAAO;AAC5C,MAAI,OAAO,UAAU,QAAQ,OAAQ,QAAO,OAAO,YAAY,KAAK,MAAM,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,EAAE,IAAI,MAAM,IAAI;AAC1H,MAAI,KAAK,UAAU,MAAM,KAAK,UAAU,KAAK,MAAM,KAAK,UAAU,MAAM,KAAK,UAAU,KAAK,IAAI;AAC9F,WAAQ,KAAK,MAAM,OAAO,SAAS,SAAS,iBAAiB,SAAS,SAAS,SAAS,WAAY,KAAK;AAAA,EAC3G;AACA,QAAM,MAAM,KAAK,IAAI,IAAI,KAAK,MAAM;AACpC,QAAM,MAAM,KAAK,IAAI,IAAI,KAAK,MAAM;AACpC,QAAM,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM,IAAI;AAC5C,QAAM,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM,IAAI;AAC5C,MAAI,MAAM,KAAK,MAAM,EAAG,QAAO;AAC/B,QAAM,OAAO,KAAK,IAAI,SAAS,GAAG,IAAI;AACtC,QAAM,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,IAAI,CAAC,CAAC;AACzD,QAAM,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,IAAI,CAAC,CAAC;AACzD,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,YAAM,IAAI,KAAK,MAAM,OAAQ,IAAI,OAAO,KAAM,KAAK,IAAI,OAAQ,IAAI,OAAO,KAAM,KAAK,EAAE;AACvF,UAAI,KAAK,UAAU,KAAK,OAAQ,QAAO,OAAO,YAAY,IAAI,MAAM,IAAI;AAAA,IAC1E;AAAA,EACF;AACA,SAAS,OAAO,KAAK,MAAO,KAAK,MAAO,KAAK;AAC/C;AAcO,SAAS,cAAc,MAAiB,OAA6B,CAAC,GAAkB;AAE7F,SAAO,kBAAkB,MAAM,KAAK,KAAK,GAAI;AAC7C,QAAM,QAAQ,WAAW,MAAM,IAAI;AACnC,QAAM,IAAI,KAAK,KAAK;AACpB,QAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;AACvD,QAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;AACvD,QAAM,EAAE,GAAG,GAAG,MAAM,IAAI;AACxB,QAAM,QAAQ,IAAI;AAClB,QAAM,QAAQ,IAAI;AAKlB,QAAM,KAAK,KAAK;AAChB,QAAM,QAAkB,IAAI,MAAM,IAAI,EAAE,KAAK,CAAC;AAC9C,MAAI;AACJ,MAAI,CAAC,MAAM,GAAG,SAAS,SAAS;AAC9B,UAAM,KAAK,QAAQ,IAAI,SAAS,SAAS,CAAC;AAAA,EAC5C,WAAW,GAAG,SAAS,SAAS;AAC9B,cAAU,IAAI,MAAc,OAAO,IAAI;AACvC,UAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AACxC,UAAM,OAAO,MAAM;AACnB,UAAM,KAAK,gBAAgB,IAAI,CAAC;AAChC,aAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,UAAI,SAAS;AACb,eAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,cAAM,MAAM,WAAW,YAAa,IAAI,OAAO,QAAS,QAAS,IAAI,OAAO,QAAS,OAAO,IAAI,IAAI,IAAI,CAAC;AACzG,gBAAQ,IAAI,OAAO,CAAC,IAAI;AACxB,kBAAU;AAAA,MACZ;AACA,YAAM,CAAC,IAAI,SAAS;AAAA,IACtB;AAAA,EACF,OAAO;AACL,UAAM,QAAQ,CAAC,GAAG,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE;AACtD,aAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,YAAM,KAAK,IAAI,OAAO;AACtB,UAAI;AACJ,UAAI,KAAK,MAAM,CAAC,EAAG,GAAI,OAAM,QAAQ,MAAM,CAAC,EAAG,KAAK;AAAA,eAC3C,KAAK,MAAM,MAAM,SAAS,CAAC,EAAG,GAAI,OAAM,QAAQ,MAAM,MAAM,SAAS,CAAC,EAAG,KAAK;AAAA,WAClF;AACH,YAAI,IAAI;AACR,eAAO,IAAI,MAAM,SAAS,KAAK,MAAM,IAAI,CAAC,EAAG,KAAK,EAAG;AACrD,cAAM,IAAI,MAAM,CAAC;AACjB,cAAM,IAAI,MAAM,IAAI,CAAC;AACrB,cAAM,IAAI,EAAE,OAAO,EAAE,KAAK,KAAK,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE;AACrD,cAAM,QAAQ,EAAE,KAAK,KAAK,QAAQ,EAAE,KAAK,IAAI,QAAQ,EAAE,KAAK,KAAK;AAAA,MACnE;AACA,YAAM,CAAC,IAAI;AAAA,IACb;AACA,QAAI,GAAG,MAAM;AACX,YAAM,SAAS,GAAG,KAAK,UAAU,KAAK,UAAU,OAAO,IAAI,KAAK,IAAI,GAAG,CAAC;AACxE,YAAM,UAAU,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI,UAAU,KAAK,CAAC;AAC5D,eAAS,IAAI,SAAS,IAAI,MAAM,IAAK,OAAM,CAAC,IAAI,QAAQ,GAAG,KAAK,KAAK;AAAA,IACvE;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,MAAc,OAAO,IAAI;AAC3C,WAAS,IAAI,GAAG,IAAI,MAAM,IAAK,UAAS,IAAI,GAAG,IAAI,MAAM,IAAK,OAAM,IAAI,OAAO,CAAC,IAAI,UAAU,QAAQ,IAAI,OAAO,CAAC,IAAK,MAAM,CAAC;AAE9H,QAAM,UAAU,CAAC,KAAa,KAAa,GAAW,UAAoC;AACxF,UAAM,MAAM,MAAM,GAAG;AACrB,QAAI,UAAU,aAAa,UAAU,SAAU,OAAM,GAAG,IAAI,KAAK,IAAI,GAAG,MAAM,MAAM,CAAC;AAAA,aAC5E,UAAU,WAAY,OAAM,GAAG,IAAI,OAAO,IAAI,KAAK,IAAI;AAAA,QAC3D,OAAM,GAAG,IAAI,OAAO,IAAI,KAAK,MAAM;AAAA,EAC1C;AAOA,QAAM,aAAa,CAAC,OAAkB,GAAW,OAAe,OAAe,YAAoB,eAA6B;AAC9H,UAAM,QAAQ,MAAM;AACpB,QAAI,CAAC,MAAO;AACZ,UAAM,YAAY,QAAQ,GAAG,KAAK,IAAI,QAAQ;AAC9C,UAAM,WAAW,OAAO,GAAG,KAAK;AAChC,UAAM,MAAM,WAAW,OAAO,CAAC;AAC/B,UAAM,OAAO,MAAM,OAAO,SAAS,YAAY,CAAC,CAAC,MAAM,OAAO;AAC9D,UAAM,SAAS;AAAA,MAAY;AAAA,MAAO;AAAA,MAAO;AAAA,MAAW;AAAA,MAAU,CAAC,OAAO,MAAM,OAAO,GAAG,EAAE;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG,MAAM,SAAS;AAAA;AAAA;AAAA,MAG9G,eAAe,MAAM,MAAM,KAAK,MAAM,OAAO,SAAS,WAAW,IAAI,gBAAgB,UAAU;AAAA,MAAG;AAAA,MAAO,MAAM,UAAU;AAAA,IAAS;AACpI,eAAW,MAAM,QAAQ;AACvB,YAAM,IAAI,GAAG;AACb,YAAM,MAAM,GAAG;AACf,UAAI,MAAM,OAAO,SAAS,aAAa,MAAM,KAAK,wBAAwB,KAAK,IAAI,OAAO,KAAK,GAAG;AAChG,4BAAoB,OAAO,MAAM,QAAQ,GAAG,IAAI,MAAM,GAAG,KAAK,IAAI,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC;AAClF;AAAA,MACF;AACA,YAAM,MAAM;AACZ,YAAM,KAAK,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI,IAAI,OAAO,KAAK,CAAC;AACxD,YAAM,KAAK,KAAK,IAAI,OAAO,GAAG,KAAK,OAAO,IAAI,IAAI,OAAO,KAAK,CAAC;AAC/D,YAAM,KAAK,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI,IAAI,OAAO,KAAK,CAAC;AACxD,YAAM,KAAK,KAAK,IAAI,OAAO,GAAG,KAAK,OAAO,IAAI,IAAI,OAAO,KAAK,CAAC;AAC/D,eAAS,IAAI,IAAI,KAAK,IAAI,KAAK;AAC7B,iBAAS,IAAI,IAAI,KAAK,IAAI,KAAK;AAC7B,cAAI,MAAM;AACV,cAAI,MAAM;AACR,kBAAM,YAAY,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK;AAChF,gBAAI,OAAO,EAAG;AAAA,UAChB,OAAO;AACL,kBAAM,IAAI,KAAK,OAAO,IAAI,OAAO,QAAQ,IAAI,IAAI,IAAI,OAAO,QAAQ,IAAI,CAAC;AACzE,gBAAI,IAAI,MAAM,KAAK,IAAI,OAAO,KAAK,IAAI,EAAG;AAAA,UAC5C;AACA,kBAAQ,IAAI,OAAO,GAAG,KAAK,KAAK,IAAI,GAAG,IAAI,GAAG,GAAG,MAAM,KAAK;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAOA,QAAM,sBAAsB,CAAC,OAAkB,GAAkB,GAAW,GAA6B,IAAY,GAAW,KAAa,UAAwB;AACnK,UAAM,SAAS,KAAK;AACpB,UAAM,MAAM,WAAW,GAAG,KAAK;AAC/B,UAAM,KAAK,KAAK,IAAI,GAAG;AACvB,UAAM,KAAK,KAAK,IAAI,GAAG;AAGvB,UAAM,KAAK,cAAc,CAAC,IAAI,UAAU,GAAG,QAAQ,GAAG,CAAC,IAAI,EAAE,IAAI,QAAQ,IAAI,QAAQ,IAAI,GAAG,IAAI,GAAG,SAAS,KAAK;AACjH,UAAM,UAAU,CAAC,GAAW,MAAwC;AAClE,YAAM,MAAM,IAAI,GAAG,MAAM,GAAG,IAAI,MAAM,IAAI,GAAG,MAAM,GAAG;AACtD,aAAO,EAAE,GAAG,EAAE,IAAI,KAAK,KAAK,KAAK,IAAI,GAAG,EAAE,IAAI,KAAK,KAAK,KAAK,GAAG;AAAA,IAClE;AACA,UAAM,MAAM,cAAc,CAAC,IACvB,cAAc,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,IACrD,cAAc,GAAG,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,IAAI,GAAG,EAAE;AACxG,QAAI,OAAO;AACX,QAAI,OAAO;AACX,QAAI,OAAO;AACX,QAAI,OAAO;AACX,eAAW,KAAK,KAAK;AACnB,aAAO,KAAK,IAAI,MAAM,EAAE,CAAC;AAAG,aAAO,KAAK,IAAI,MAAM,EAAE,CAAC;AACrD,aAAO,KAAK,IAAI,MAAM,EAAE,CAAC;AAAG,aAAO,KAAK,IAAI,MAAM,EAAE,CAAC;AAAA,IACvD;AAEA,UAAM,gBAAgB,CAAC,SAA+D;AACpF,UAAI,CAAC,KAAK,OAAQ,QAAO,CAAC;AAC1B,YAAM,KAAM,KAAK,OAAO,QAAQ,SAAU;AAC1C,YAAM,MAA8C,CAAC;AACrD,iBAAW,KAAK,KAAK,KAAK,OAAO;AAC/B,cAAM,IAAI,EAAE,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC;AAChD,cAAM,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS;AAC3C,iBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,gBAAM,IAAI,EAAE,CAAC,GAAI,IAAI,GAAG,IAAI,KAAK,EAAE,MAAM;AACzC,gBAAM,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,KAAK,MAAM,IAAI,EAAE,KAAK;AAClE,gBAAM,KAAM,CAAC,KAAK,MAAO,IAAI,KAAM,KAAK,MAAO;AAC/C,cAAI,KAAK,CAAC,EAAE,GAAG,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,GAAG,GAAG,EAAE,GAAG,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,GAAG,GAAG,EAAE,GAAG,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,GAAG,GAAG,EAAE,GAAG,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,GAAG,CAAC,CAAC;AAAA,QACnI;AAAA,MACF;AACA,aAAO;AAAA,IACT;AACA,QAAI,cAAc,CAAC,GAAG;AAEpB,iBAAW,QAAQ,UAAU,CAAC,EAAG,YAAW,QAAQ,cAAc,IAAI,EAAG,YAAW,KAAK,MAAM;AAC7F,eAAO,KAAK,IAAI,MAAM,EAAE,CAAC;AAAG,eAAO,KAAK,IAAI,MAAM,EAAE,CAAC;AAAG,eAAO,KAAK,IAAI,MAAM,EAAE,CAAC;AAAG,eAAO,KAAK,IAAI,MAAM,EAAE,CAAC;AAAA,MAC/G;AAAA,IACF;AACA,UAAM,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,KAAK,CAAC;AAC/C,UAAM,KAAK,KAAK,IAAI,OAAO,GAAG,KAAK,MAAM,OAAO,KAAK,CAAC;AACtD,UAAM,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,KAAK,CAAC;AAC/C,UAAM,KAAK,KAAK,IAAI,OAAO,GAAG,KAAK,MAAM,OAAO,KAAK,CAAC;AACtD,QAAI,KAAK,MAAM,KAAK,GAAI;AACxB,UAAM,KAAK,KAAK,KAAK;AACrB,UAAM,SAAS,CAAC,GAAW,MAAgC;AACzD,YAAM,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE;AAC/B,aAAO,EAAE,KAAK,KAAK,KAAK,MAAM,KAAK,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,KAAK,CAAC,KAAK,KAAK,KAAK,MAAM,KAAK,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,EAAE;AAAA,IACnH;AAGA,UAAM,QAAQ,cAAc,CAAC,IAAI,UAAU,CAAC,IAAI;AAChD,UAAM,WAAW,CAAC,MAAuC,MAAe,SAAiB,OAAe,SAAoC;AAC1I,YAAM,MAAM,oBAAoB,MAAM,OAAO,OAAO,IAAI,IAAI,IAAI,IAAI,IAAI;AACxE,eAAS,IAAI,IAAI,KAAK,IAAI,KAAK;AAC7B,iBAAS,IAAI,IAAI,KAAK,IAAI,KAAK;AAC7B,gBAAM,IAAI,KAAK,IAAI,MAAM,MAAM,IAAI,GAAG;AACtC,cAAI,EAAE,IAAI,GAAI;AACd,gBAAM,KAAK,IAAI,OAAO;AACtB,gBAAM,KAAK,IAAI,OAAO;AACtB,cAAI,KAAK,SAAS,KAAK;AACvB,cAAI,MAAM,UAAU;AAClB,kBAAM,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC;AAC1B,kBAAM,CAAC,IAAI,EAAE,IAAI,cAAc,MAAM,GAAG,CAAC;AACzC,kBAAM,IAAI,WAAW,KAAK,UAAU,IAAI,EAAE;AAC1C,iBAAK,EAAE;AAAM,iBAAK,EAAE;AAAA,UACtB;AACA,gBAAM,MAAM,EAAE,QAAQ,CAAC,QAAQ,IAAI,YAAY,KAAK,MAAM,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,KAAK,IAAI,QAAQ,IAAI,CAAC,IAAI;AACxG,cAAI,MAAM,EAAG,SAAQ,IAAI,OAAO,GAAG,IAAI,IAAI,QAAQ,KAAK,KAAK,IAAI,GAAG,GAAG,GAAG,MAAM,KAAK;AAAA,QACvF;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,OAAO;AACV,eAAS,KAAK,gBAAgB,CAAC,MAAM,WAAW,KAAK,GAAG,IAAI;AAC5D;AAAA,IACF;AACA,eAAW,QAAQ,OAAO;AACxB,YAAM,UAAU,KAAK,QAAQ,QAAQ,KAAK,KAAK,IAAI;AACnD,UAAI,KAAK,QAAQ,KAAK,KAAK,OAAO,UAAU,GAAG;AAC7C,iBAAS,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,KAAK,SAAS,WAAW,SAAS,KAAK,SAAS,IAAI;AAAA,MAChH;AACA,UAAI,KAAK,QAAQ;AACf,cAAM,MAAM,KAAK,OAAO,WAAW,KAAK,KAAK;AAC7C,cAAM,KAAK,QAAQ,KAAK,OAAO,KAAK;AACpC,cAAM,OAAO,IAAI,aAAa,MAAM,KAAK,KAAK,EAAE;AAChD,mBAAW,MAAM,cAAc,IAAI,GAAG;AACpC,cAAI,MAAM,UAAU,MAAM,WAAW,MAAM,UAAU,MAAM;AAC3D,qBAAW,KAAK,IAAI;AAAE,kBAAM,KAAK,IAAI,KAAK,EAAE,CAAC;AAAG,kBAAM,KAAK,IAAI,KAAK,EAAE,CAAC;AAAG,kBAAM,KAAK,IAAI,KAAK,EAAE,CAAC;AAAG,kBAAM,KAAK,IAAI,KAAK,EAAE,CAAC;AAAA,UAAG;AAC9H,gBAAM,KAAK,KAAK,IAAI,IAAI,KAAK,MAAM,MAAM,KAAK,CAAC,GAAG,KAAK,KAAK,IAAI,IAAI,KAAK,MAAM,MAAM,KAAK,CAAC;AAC3F,gBAAM,KAAK,KAAK,IAAI,IAAI,KAAK,MAAM,MAAM,KAAK,CAAC,GAAG,KAAK,KAAK,IAAI,IAAI,KAAK,MAAM,MAAM,KAAK,CAAC;AAC3F,cAAI,KAAK,MAAM,KAAK,GAAI;AACxB,gBAAM,KAAK,oBAAoB,IAAI,OAAO,OAAO,IAAI,IAAI,IAAI,EAAE;AAC/D,gBAAM,KAAK,KAAK,KAAK;AACrB,mBAAS,IAAI,IAAI,KAAK,IAAI,IAAK,UAAS,IAAI,IAAI,KAAK,IAAI,KAAK;AAC5D,kBAAM,KAAK,IAAI,MAAM,MAAM,IAAI;AAC/B,iBAAK,CAAC,IAAI,KAAK,IAAI,GAAG,KAAK,CAAC,IAAK,IAAI,IAAI,MAAM,MAAM,IAAI,GAAG,CAAE;AAAA,UAChE;AAAA,QACF;AACA,iBAAS,IAAI,IAAI,KAAK,IAAI,IAAK,UAAS,IAAI,IAAI,KAAK,IAAI,KAAK;AAC5D,gBAAM,IAAI,MAAM,IAAI,MAAM,MAAM,IAAI,GAAG;AACvC,cAAI,IAAI,EAAG,SAAQ,IAAI,OAAO,GAAG,IAAI,IAAI,KAAK,GAAG,MAAM,KAAK;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAKA,QAAM,YAAY,CAAC,OAAe,eAA6B;AAC/D,eAAW,EAAE,OAAO,SAAS,KAAK,MAAM,QAAQ;AAC9C,YAAM,QAAQ,MAAM,YAAY,UAAa,MAAM,UAAU,SAAY,YAAY,MAAM,MAAM,KAAK,IAAI,YAAY,MAAM,MAAM,KAAK,IAAI,aAAa,MAAM,KAAK;AACnK,UAAI,SAAS,EAAG;AAEhB,iBAAW,KAAK,UAAU;AACxB,mBAAW,OAAO,GAAG,OAAO,OAAO,YAAY,SAAS,MAAM;AAC9D,cAAM,IAAI,KAAK,IAAI,GAAG,QAAQ,GAAG,KAAK,IAAI,KAAK,IAAI;AACnD,YAAI,KAAK,KAAO;AAChB,cAAM,MAAM,WAAW,OAAO,CAAC;AAC/B,cAAM,IAAI,MAAM,OAAO,GAAG,KAAK;AAC/B,cAAM,KAAK,MAAM,aAAa,MAAM,UAAU,SAAY,OAAO,GAAG,KAAK,IAAI,UAAU,MAAM,KAAK,IAAI,OAAO,GAAG,KAAK;AACrH,cAAM,IAAI,MAAM;AAEhB,YAAI,EAAE,SAAS,cAAc,MAAM,wBAAwB,KAAK,IAAI,OAAO,KAAK,KAAM,cAAc,CAAC,OAAO,EAAE,QAAQ,WAAW,SAAS,EAAE,WAAW,UAAc;AACnK,8BAAoB,OAAO,GAAG,GAAG,GAAG,IAAI,GAAG,KAAK,KAAK;AACrD;AAAA,QACF;AACA,YAAI,EAAE,SAAS,UAAU;AAEvB,gBAAM,MAAM,cAAc,GAAG,KAAK,CAAC;AACnC,cAAI,QAAQ,WAAW,GAAG,KAAK;AAC/B,cAAI,EAAE,OAAQ,UAAS,UAAU,GAAG,OAAO,GAAG,CAAC,KAAK;AACpD,gBAAM,KAAK,KAAK,IAAI,KAAK;AACzB,gBAAM,KAAK,KAAK,IAAI,KAAK;AACzB,gBAAM,KAAK,cAAc,GAAG,KAAK;AACjC,gBAAM,UAAU,CAAC,GAA6B,MAAoB;AAChE,kBAAM,IAAI,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,IAAI;AACjC,kBAAM,IAAI,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,IAAI;AACjC,kBAAM,IAAI,KAAK,MAAM,IAAI,KAAK;AAC9B,kBAAM,IAAI,KAAK,MAAM,IAAI,KAAK;AAC9B,gBAAI,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,KAAM;AAC9C,kBAAM,QAAQ,EAAE,QAAQ,YAAY,CAAC,IAAI;AACzC,oBAAQ,IAAI,OAAO,GAAG,KAAK,IAAI,KAAK,IAAI,GAAI,KAAK,QAAS,KAAK,GAAG,MAAM,KAAK;AAAA,UAC/E;AAGA,gBAAM,OAAO,KAAK,IAAI,OAAO,KAAK,IAAI;AACtC,kBAAQ,IAAI,CAAC,GAAI,CAAC;AAClB,mBAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,kBAAM,KAAK,IAAI,IAAI,CAAC;AACpB,kBAAM,KAAK,IAAI,CAAC;AAChB,kBAAM,SAAS,KAAK,MAAM,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,CAAC;AAClD,kBAAM,MAAM,KAAK,IAAI,GAAG,KAAK,KAAK,SAAS,IAAI,CAAC;AAChD,qBAAS,IAAI,GAAG,KAAK,KAAK,KAAK;AAC7B,oBAAM,IAAI,IAAI;AACd,sBAAQ,EAAE,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,EAAE,IAAI,IAAI,IAAI,MAAM,IAAI,SAAS,EAAE;AAAA,YACtG;AAAA,UACF;AACA;AAAA,QACF;AACA,YAAI,EAAE,SAAS,UAAU;AAGvB,gBAAM,WAAW,UAAU,GAAG,OAAO,GAAG,CAAC,KAAK,KAAK,WAAW,GAAG,KAAK;AACtE,gBAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,KAAK,KAAK,KAAK,IAAI,OAAO,KAAK,CAAC,CAAC;AAChE,gBAAM,MAAM,KAAK,IAAI,IAAK,EAAE,UAAU,UAAU,IAAI,IAAI,SAAU,QAAS,KAAK;AAChF,mBAAS,IAAI,GAAG,KAAK,OAAO,KAAK;AAC/B,kBAAM,IAAI,IAAI;AACd,kBAAM,IAAI,EAAE,IAAI,KAAK,IAAI,OAAO,IAAI,MAAM,IAAI;AAC9C,kBAAM,IAAI,EAAE,IAAI,KAAK,IAAI,OAAO,IAAI,MAAM,IAAI;AAC9C,kBAAM,IAAI,KAAK,MAAM,IAAI,KAAK;AAC9B,kBAAM,IAAI,KAAK,MAAM,IAAI,KAAK;AAC9B,gBAAI,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,KAAM;AAC9C,oBAAQ,IAAI,OAAO,GAAG,KAAK,IAAI,IAAI,KAAK,MAAM,KAAK;AAAA,UACrD;AACA;AAAA,QACF;AAEA,YAAI,UAAU,EAAE;AAChB,YAAI,UAAU,EAAE;AAChB,YAAI,QAAQ,KAAK;AACjB,YAAI,QAAQ,EAAE,SAAS,UAAW,EAAE,SAAS,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,OAAO,KAAM,IAAI,KAAK;AAC9F,YAAI,EAAE,SAAS,QAAQ;AACrB,gBAAM,MAAM,QAAQ,GAAG,GAAG,GAAG,aAAa,MAAM,GAAG,CAAC,GAAG,KAAK;AAC5D,oBAAU,IAAI;AACd,oBAAU,IAAI;AACd,kBAAQ,IAAI;AACZ,kBAAQ,IAAI;AAAA,QACd,WAAW,EAAE,SAAS,aAAa;AACjC,gBAAM,MAAM,aAAa,GAAG,GAAG,GAAG,GAAG,CAAC;AACtC,oBAAU,IAAI;AACd,oBAAU,IAAI;AACd,kBAAQ,IAAI;AACZ,kBAAQ,IAAI;AAAA,QACd,WAAW,EAAE,SAAS,OAAO;AAC3B,gBAAM,MAAM,KAAK,YAAY,GAAG,EAAE,YAAY,CAAC;AAC/C,cAAI,OAAO,EAAG;AACd,gBAAM,KAAK,EAAE,UAAU,SAAY,EAAE,SAAS,EAAE,OAAO,IAAI,KAAK,EAAE,OAAO,KAAK,KAAK;AACnF,gBAAM,MAAM,OAAO,EAAE,aAAa,SAAS,KAAK,EAAE;AAGlD,gBAAM,MAAM,WAAW,GAAG,KAAK;AAC/B,gBAAM,KAAK,KAAK,IAAI,GAAG;AACvB,gBAAM,KAAK,KAAK,IAAI,GAAG;AACvB,oBAAU,EAAE,IAAI,IAAI,KAAK,KAAK,IAAI,KAAK;AACvC,oBAAU,EAAE,IAAI,IAAI,KAAK,KAAK,IAAI,KAAK;AACvC,kBAAQ,KAAK,IAAI,IAAI,QAAQ,EAAE,IAAI,KAAK,IAAI,IAAI,QAAQ,EAAE;AAC1D,kBAAQ,KAAK,IAAI,IAAI,QAAQ,EAAE,IAAI,KAAK,IAAI,IAAI,QAAQ,EAAE;AAAA,QAC5D;AACA,cAAM,WAAW,EAAE,SAAS,YAAY,EAAE,SAAS,UAAU,EAAE,SAAS;AACxE,cAAM,QAAQ,EAAE,SAAS,YAAY,EAAE,SAAS,cAAc,CAAC,CAAC,EAAE;AAIlE,cAAM,cAAc,EAAE,SAAS,YAC3B,YAAY,GAAG,KAAK,CAAC,IACrB,EAAE,SAAS,UAAU,EAAE,WACpB,IAAI,EAAE,UAAU,MAAM,IAAI,EAAE,UAAU,KACvC;AAGN,cAAM,KAAK,KAAK,IAAI,GAAG,KAAK,OAAO,UAAU,SAAS,KAAK,CAAC;AAC5D,cAAM,KAAK,KAAK,IAAI,OAAO,GAAG,KAAK,OAAO,UAAU,SAAS,KAAK,CAAC;AACnE,cAAM,KAAK,KAAK,IAAI,GAAG,KAAK,OAAO,UAAU,SAAS,KAAK,CAAC;AAC5D,cAAM,KAAK,KAAK,IAAI,OAAO,GAAG,KAAK,OAAO,UAAU,SAAS,KAAK,CAAC;AAGnE,cAAM,aAAa,EAAE,SAAS,UAAU,EAAE,SAAS,WAAW,EAAE,SAAS,cAAc,OAAO,MACzF,EAAE,SAAS,cAAc,wBAAwB,GAAG,GAAG,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK;AAKvF,cAAM,SAAS,EAAE,SAAS,UAAU,EAAE,SAAS,SAAS,EAAE,SAAS,UAAU,EAAE,SAAS,WAAW,EAAE,SAAS;AAC9G,iBAAS,IAAI,IAAI,KAAK,IAAI,KAAK;AAC7B,gBAAM,KAAK,SAAS,KAAK,IAAI,GAAG,KAAK,KAAK,IAAI,KAAK,OAAO,UAAU,KAAK,IAAI,KAAK,IAAI,IAAI,OAAO,UAAU,KAAK,CAAC,IAAI,QAAQ;AAC7H,cAAI,MAAM,EAAG;AACb,mBAAS,IAAI,IAAI,KAAK,IAAI,KAAK;AAC7B,gBAAI,UAAU;AACZ,oBAAM,QAAQ,EAAE,SAAS,SAAS,KAAK,IAAI,GAAG,SAAS,EAAE,UAAU,UAAU,IAAI,IAAI,SAAU,KAAK,IAAI;AAIxG,oBAAM,MAAM,YAAY,SAAS,SAAS,OAAO,OAAO,MAAM,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK;AAChG,kBAAI,OAAO,EAAG;AACd,sBAAQ,IAAI,OAAO,GAAG,KAAK,IAAI,MAAM,aAAa,MAAM,KAAK;AAAA,YAC/D,WAAW,QAAQ;AACjB,oBAAM,KAAK,KAAK,IAAI,GAAG,KAAK,KAAK,IAAI,KAAK,OAAO,UAAU,KAAK,IAAI,KAAK,IAAI,IAAI,OAAO,UAAU,KAAK,CAAC,IAAI;AAC5G,kBAAI,KAAK,EAAG,SAAQ,IAAI,OAAO,GAAG,KAAK,IAAI,YAAY,cAAc,KAAK,IAAI,MAAM,KAAK;AAAA,YAC3F,OAAO;AACL,sBAAQ,IAAI,OAAO,GAAG,KAAK,IAAI,YAAY,aAAa,MAAM,KAAK;AAAA,YACrE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,UAAI,MAAM,OAAO;AACf,cAAM,YAAY,SAAS,IAAI,CAAC,MAAM,MAAM,OAAO,GAAG,KAAK,CAAC;AAC5D,cAAM,cAAc,CAAC,SAAS,QAAQ,QAAQ,EAAE,SAAS,MAAM,OAAO,IAAI;AAC1E,cAAM,QAAQ,UAAU,MAAM,OAAO,WAAW,cAAc,MAAM,OAAO,KAAK,GAAG,MAAM,SAAS,SAAS,aAAa,GAAG,CAAC;AAC5H,cAAM,KAAK,KAAK,IAAI,IAAI,MAAM,MAAM,SAAS,OAAO,KAAK;AACzD,cAAM,MAAM,MAAM,MAAM,QAAQ,QAAQ,MAAM,MAAM,KAAK,IAAI;AAC7D,cAAM,eAAe,UAAU,IAAI,IAAI,IAAI,OAAO;AAClD,cAAM,MAAM,KAAK,IAAI,IAAK,MAAM,MAAM,SAAS,gBAAgB,QAAS,KAAK,IAAI,KAAK;AACtF,mBAAW,QAAQ,OAAO;AACxB,gBAAM,KAAK,UAAU,KAAK,CAAC;AAC3B,gBAAM,KAAK,UAAU,KAAK,CAAC;AAC3B,gBAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,KAAK,KAAK,OAAO,KAAK,IAAI,OAAO,KAAK,CAAC,CAAC;AACvE,mBAAS,IAAI,GAAG,KAAK,OAAO,KAAK;AAC/B,kBAAM,IAAI,IAAI;AACd,kBAAM,IAAI,KAAK,OAAO,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,KAAK,KAAK;AACvD,kBAAM,IAAI,KAAK,OAAO,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,KAAK,KAAK;AACvD,gBAAI,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,KAAM;AAC9C,oBAAQ,IAAI,OAAO,GAAG,KAAK,KAAK,MAAM,KAAK;AAAA,UAC7C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACA;AAQA,QAAM,QAAQ,KAAK,YAAY;AAC/B,MAAI,QAAQ,GAAG;AACb,UAAM,KAAK,MAAO;AAClB,UAAM,eAAe,KAAK,IAAI,KAAK,KAAK,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,IAAI,KAAK,CAAC,GAAG,OAAO,oBAAoB;AACzG,UAAM,OAAO,KAAK,IAAI,YAAY,YAAY;AAC9C,UAAM,UAAU,eAAe;AAC/B,aAAS,IAAI,MAAM,KAAK,GAAG,KAAK;AAC9B,YAAM,QAAQ,IAAI,IAAI,UAAU;AAChC,UAAI,QAAQ,EAAG;AACf,YAAM,gBACH,KAAK,IAAI,QAAQ,IAAI,KAAK,UAAU,CAAC,KAAK,IAAI,KAAK,IAAI,OAAO,OAAO,MAAO,IAAI;AACnF,gBAAU,OAAO,KAAK,IAAI,GAAG,aAAa,CAAC;AAAA,IAC7C;AAAA,EACF;AACA,YAAU,GAAG,CAAC;AAGd,SAAO,WAAW,MAAM,MAAM,OAAO,OAAO,OAAO;AACrD;AAOA,SAAS,WAAW,MAAc,MAAc,OAAiB,OAAiB,SAAmC;AACnH,MAAI,MAAM;AACV,MAAI,UAAU;AACd,MAAI,SAAS;AACb,MAAI,QAAQ;AACZ,MAAI,QAAQ;AACZ,QAAM,aAAa,IAAI,MAAc,IAAI,EAAE,KAAK,CAAC;AACjD,QAAM,aAAa,IAAI,MAAc,IAAI,EAAE,KAAK,CAAC;AACjD,WAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,aAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,YAAM,IAAI,MAAM,IAAI,OAAO,CAAC;AAC5B,aAAO;AACP,YAAM,MAAM,KAAK,IAAI,KAAK,UAAU,QAAQ,IAAI,OAAO,CAAC,IAAK,MAAM,CAAC,EAAG;AACvE,UAAI,MAAM,KAAM;AAChB,gBAAU;AACV,eAAS,OAAO,IAAI;AACpB,eAAS,OAAO,IAAI;AACpB,iBAAW,CAAC,KAAM;AAClB,iBAAW,CAAC,KAAM;AAAA,IACpB;AAAA,EACF;AACA,WAAS,IAAI,GAAG,IAAI,MAAM,IAAK,YAAW,CAAC,IAAI,WAAW,CAAC,IAAK;AAChE,WAAS,IAAI,GAAG,IAAI,MAAM,IAAK,YAAW,CAAC,IAAI,WAAW,CAAC,IAAK;AAEhE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,GAAI,UAAU,EAAE,iBAAiB,QAAQ,IAAI,CAAC;AAAA,IAC9C,eAAe,OAAO,OAAO;AAAA,IAC7B,UAAU,WAAW,OAAO;AAAA,IAC5B,UAAU,SAAS,OAAO,EAAE,GAAG,QAAQ,SAAS,MAAM,GAAG,QAAQ,SAAS,KAAK,IAAI;AAAA,IACnF;AAAA,IACA;AAAA,EACF;AACF;AAOA,IAAM,SAAqB;AAAA,EACzB,CAAC,MAAM,GAAG,MAAM,CAAC;AAAA,EACjB,CAAC,MAAM,GAAG,MAAM,CAAC;AAAA,EACjB,CAAC,MAAM,GAAG,MAAM,CAAC;AAAA,EACjB,CAAC,MAAM,GAAG,MAAM,CAAC;AACnB;AAEA,IAAM,UAAsB;AAAA,EAC1B,CAAC,GAAM,CAAI;AAAA,EACX,CAAC,GAAM,EAAI;AAAA,EACX,CAAC,GAAM,EAAI;AAAA,EACX,CAAC,IAAM,GAAI;AACb;AAaA,SAAS,WAAW,MAA4C;AAC9D,QAAM,SAAS,CAAC,GAAG,KAAK,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACnD,QAAM,KAAK,OAAO,CAAC;AACnB,QAAM,KAAK,KAAK,IAAI,OAAO,KAAK,MAAM,OAAO,SAAS,IAAI,CAAC,GAAI,KAAK,IAAI;AACxE,SAAO,CAAC,MAAsB,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,GAAG,CAAC,GAAG,GAAG;AAC5F;AAOO,SAAS,iBAAiB,MAA6B;AAC5D,QAAM,SAAS,WAAW,IAAI;AAE9B,QAAM,UAAoB,CAAC;AAC3B,WAAS,KAAK,GAAG,KAAK,KAAK,MAAM,KAAK,OAAO,CAAC,GAAG,MAAM;AACrD,QAAI,OAAO;AACX,aAAS,KAAK,GAAG,KAAK,KAAK,MAAM,KAAK,OAAO,CAAC,GAAG,MAAM;AACrD,UAAI,OAAO;AACX,eAAS,KAAK,GAAG,KAAK,GAAG,MAAM;AAC7B,iBAAS,KAAK,GAAG,KAAK,GAAG,MAAM;AAC7B,gBAAM,IAAI,OAAO,KAAK,OAAO,KAAK,IAAI,MAAM,KAAK,QAAQ,KAAK,IAAI,GAAG,CAAE;AACvE,cAAI,IAAI,OAAO,EAAE,EAAG,EAAE,EAAI,SAAQ,QAAQ,EAAE,EAAG,EAAE;AAAA,QACnD;AAAA,MACF;AACA,cAAQ,OAAO,aAAa,QAAS,IAAI;AAAA,IAC3C;AACA,YAAQ,KAAK,IAAI;AAAA,EACnB;AACA,SAAO,QAAQ,KAAK,IAAI;AAC1B;AAKA,IAAM,eAAe;AASd,SAAS,iBAAiB,MAA6B;AAC5D,QAAM,SAAS,WAAW,IAAI;AAC9B,QAAM,OAAO;AACb,QAAM,QAAkB,CAAC;AACzB,WAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK;AAClC,QAAI,OAAO;AACX,aAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK;AAClC,YAAM,IAAI,OAAO,KAAK,MAAM,IAAI,KAAK,OAAO,CAAC,CAAE;AAC/C,cAAQ,KAAK,KAAK,IAAI,KAAK,SAAS,GAAG,KAAK,MAAM,IAAI,KAAK,MAAM,CAAC,CAAC;AAAA,IACrE;AACA,UAAM,KAAK,IAAI;AAAA,EACjB;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAyBO,SAAS,YAAY,MAAiB,OAAwB,CAAC,GAAqB;AACzF,SAAO,kBAAkB,MAAM,KAAK,KAAK,GAAI;AAC7C,QAAM,QAAQ,WAAW,MAAM,IAAI;AACnC,QAAM,IAAI,KAAK,KAAK;AACpB,QAAM,MAAwB,CAAC;AAC/B,QAAM,OAAO,QAAQ,CAAC,EAAE,OAAO,SAAS,GAAG,eAAe;AACxD,QAAI,MAAM,OAAO,SAAS,aAAa;AACrC,YAAMC,KAAI,MAAM;AAChB,YAAM,YAAY,KAAK,IAAI,MAAM,GAAG,MAAM,CAAC;AAC3C,YAAMC,UAASD,GAAE,WAAW;AAC5B,YAAM,OAAuB,EAAE,YAAY,KAAK,MAAM,KAAK,SAAS,CAACA,GAAE,IAAI,GAAG,OAAO,SAAS,QAAQ,QAAQ,KAAK,MAAMC,OAAM,EAAE;AACjI,UAAID,GAAE,OAAQ,MAAK,WAAW,KAAK,MAAM,wBAAwBA,IAAG,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,GAAG,IAAI;AAClG,UAAI,KAAK,IAAI;AACb;AAAA,IACF;AACA,QAAI,MAAM,OAAO,SAAS,OAAQ;AAClC,UAAM,IAAI,MAAM;AAChB,UAAM,SAAS,WAAW,GAAG,SAAS,CAAC,IAAI,OAAO,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,aAAa,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC;AAC3G,QAAI,KAAK,EAAE,YAAY,KAAK,MAAM,KAAK,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,SAAS,QAAQ,QAAQ,KAAK,MAAM,MAAM,EAAE,CAAC;AAAA,EACtH,CAAC;AACD,SAAO;AACT;AAwBO,SAAS,iBAAiB,MAAiB,OAAwB,CAAC,GAAqB;AAC9F,SAAO,cAAc,aAAa,MAAM,IAAI,CAAC;AAC/C;AAYA,SAAS,cAAc,KAAuC;AAC5D,QAAM,QAAQ,IAAI,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC,KAAK;AACvD,SAAO,IACJ,MAAM,EACN,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,EAClC,IAAI,CAAC,GAAG,OAAO;AAAA,IACd,MAAM,IAAI;AAAA,IACV,YAAY,EAAE;AAAA,IACd,KAAK,EAAE;AAAA,IACP,OAAO,EAAE,SAAS;AAAA,IAClB,aAAa,EAAE;AAAA,IACf,UAAU,EAAE;AAAA,IACZ,SAAS,EAAE;AAAA,EACb,EAAE;AACN;AAGA,SAAS,aAAa,MAAiB,OAAwB,CAAC,GAAmB;AACjF,SAAO,kBAAkB,MAAM,KAAK,KAAK,GAAI;AAC7C,QAAM,QAAQ,WAAW,MAAM,IAAI;AACnC,QAAM,IAAI,KAAK,KAAK;AACpB,QAAM,EAAE,GAAG,GAAG,MAAM,IAAI;AAExB,QAAM,SAAS,eAAe,IAAI;AAQlC,QAAM,QAAQ,KAAK,YAAY;AAC/B,MAAI,gBAAgB;AACpB,MAAI,aAAa;AACjB,MAAI,QAAQ,GAAG;AACb,UAAM,KAAK,MAAO;AAClB,UAAM,SAAS,KAAK,IAAI,KAAK,KAAK,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,IAAI,KAAK,CAAC,GAAG,OAAO,oBAAoB;AACnG,oBAAgB,SAAS;AACzB,iBAAc,SAAS,IAAI,KAAK,IAAI,OAAO,MAAM,MAAO,IAAI,SAAS;AAAA,EACvE;AACA,QAAM,gBAAgB,CAAC,GAAW,WAA2B;AAC3D,UAAM,OAAO,KAAK,IAAI,QAAQ,CAAC;AAC/B,QAAI,QAAQ,EAAG,QAAO;AACtB,UAAM,KAAK,MAAM,OAAO,GAAG,IAAI,IAAI;AACnC,UAAM,KAAK,MAAM,OAAO,GAAG,CAAC;AAC5B,UAAM,KAAK,GAAG,IAAI,GAAG;AACrB,UAAM,KAAK,GAAG,IAAI,GAAG;AACrB,QAAI,KAAK,IAAI,EAAE,IAAI,IAAI,KAAK,KAAK,IAAI,EAAE,IAAI,IAAI,EAAG,QAAO;AACzD,WAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAAA,EACpC;AAEA,QAAM,MAAM,MAAM,OAAO,IAAI,CAAC,EAAE,OAAO,SAAS,GAAG,eAAe;AAChE,UAAM,QAAQ,MAAM,YAAY,UAAa,MAAM,UAAU,SAAY,YAAY,MAAM,MAAM,CAAC,IAAI,YAAY,MAAM,MAAM,CAAC,IAAI,aAAa,MAAM,KAAK;AAC3J,UAAM,UAAU,MAAM,cAAc,UAAa,MAAM,UAAU;AACjE,UAAM,YAAY,UAAU,UAAU,MAAM,KAAK,KAAK,IAAI;AAC1D,QAAI,OAAO;AACX,QAAI,SAAS;AACb,eAAW,KAAK,UAAU;AACxB,YAAM,IAAI,QAAQ,GAAG,CAAC,IAAI;AAC1B,YAAM,KAAK,OAAO,GAAG,CAAC;AACtB,YAAM,IAAI,MAAM;AAChB,UAAI;AACJ,UAAI,EAAE,SAAS,SAAU,WAAU,KAAK,MAAM,KAAK,MAAM,KAAK;AAAA,eACrD,EAAE,SAAS,OAAQ,WAAU,KAAK,KAAK,OAAO,EAAE,UAAU,UAAU,IAAI,IAAI,SAAU,SAAS;AAAA,eAC/F,EAAE,SAAS,SAAU,WAAU,OAAO,EAAE,UAAU,UAAU,IAAI,IAAI,SAAU,SAAS;AAAA,eACvF,EAAE,SAAS,QAAQ;AAC1B,cAAM,KAAK,EAAE,UAAU,SAAY,EAAE,SAAS,EAAE,OAAO,IAAI,KAAK,EAAE,OAAO,KAAK;AAC9E,cAAM,IAAI,EAAE,WAAW,IAAI,EAAE,UAAU,MAAM,IAAI,EAAE,UAAU,KAAK;AAClE,kBAAU,KAAK,KAAK;AAAA,MACtB,WACS,EAAE,SAAS,UAAW,WAAU,YAAY,cAAc,GAAG,KAAK,CAAC,CAAC;AAAA,eACpE,EAAE,SAAS,OAAO;AACzB,cAAM,KAAK,EAAE,UAAU,SAAY,EAAE,SAAS,EAAE,OAAO,IAAI,KAAK,EAAE,OAAO,KAAK,KAAK;AACnF,kBAAU,KAAK,YAAY,GAAG,EAAE,YAAY,CAAC,IAAI;AAAA,MACnD,WACS,EAAE,SAAS,UAAU;AAC5B,cAAM,YAAY,EAAE,QAAQ,OAAO;AACnC,kBAAU,WAAW,cAAc,GAAG,KAAK,CAAC,CAAC,IAAI,cAAc,GAAG,KAAK,IAAI,YAAY;AAAA,MACzF,WACS,EAAE,SAAS,QAAQ;AAC1B,cAAM,MAAM,QAAQ,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,aAAa,MAAM,GAAG,CAAC,GAAG,KAAK;AACzE,kBAAU,IAAI,QAAQ,IAAI,IAAI,QAAQ,IAAI;AAAA,MAC5C,WAAW,EAAE,SAAS,aAAa;AACjC,cAAM,MAAM,aAAa,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC;AACnD,kBAAU,IAAI,QAAQ,IAAI,IAAI,QAAQ,IAAI,OAAO,wBAAwB,GAAG,GAAG,GAAG,CAAC,KAAK,EAAE,WAAW;AAAA,MACvG,MAAO,WAAU,KAAK,KAAK;AAE3B,cAAQ,UAAU,UAAU,YAAY,IAAI,UAAU;AAItD,UAAI,MAAM,OAAO;AACf,cAAM,OAAO,MAAM,MAAM,QAAQ;AACjC,cAAM,OAAO,cAAc,GAAG,MAAM,MAAM,MAAM;AAChD,gBAAQ,OAAO,KAAK,OAAO,KAAK,IAAI,GAAG,IAAI,OAAO,CAAC,IAAI;AAAA,MACzD;AAGA,UAAI,QAAQ,GAAG;AACb,gBAAQ,cAAc,GAAG,aAAa,IAAI,KAAK,aAAa;AAAA,MAC9D;AACA,gBAAU,WAAW,OAAO,CAAC;AAAA,IAC/B;AACA,QAAI,MAAM,SAAS,SAAS,SAAS,GAAG;AACtC,YAAM,YAAY,SAAS,IAAI,CAAC,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC;AACxD,YAAM,cAAc,CAAC,SAAS,QAAQ,QAAQ,EAAE,SAAS,MAAM,OAAO,IAAI;AAC1E,YAAM,QAAQ,UAAU,MAAM,OAAO,WAAW,cAAc,MAAM,OAAO,KAAK,GAAG,MAAM,SAAS,SAAS,aAAa,GAAG,CAAC;AAC5H,YAAM,MAAM,MAAM,MAAM,SAAS,OAAO;AACxC,YAAM,eAAe,UAAU,IAAI,IAAI,IAAI,OAAO;AAClD,YAAM,MAAM,MAAM,MAAM,SAAS,gBAAgB;AACjD,iBAAW,QAAQ,MAAO,SAAQ,KAAK,OAAO,KAAK,KAAK;AAAA,IAC1D;AACA,UAAM,WAAW,SAAS,SAAS,SAAS,SAAS,SAAS;AAC9D,UAAM,WAAW,KAAK,IAAI,WAAW,MAAM,IAAI;AAC/C,UAAM,aAAa,MAAM,UAAU,aAAa,MAAM,UAAU,WAAW,MAAM,MAAM,UAAU,aAAa,MAAM;AACpH,UAAM,cAAc,MAAM,OAAO,SAAS,WAAW,IAAI;AACzD,UAAM,SAAU,QAAQ,IAAI,KAAM,WAAW,aAAa;AAC1D,WAAO,EAAE,YAAY,KAAK,MAAM,KAAK,QAAQ,aAAa,SAAS,QAAQ,UAAU,SAAS,EAAE,MAAM,QAAQ,IAAI,IAAI,UAAU,YAAY,YAAY,EAAE;AAAA,EAC5J,CAAC;AAED,SAAO;AACT;AAYO,SAAS,cAAc,MAAiB,OAAwB,CAAC,GAAoB;AAC1F,SAAO,kBAAkB,MAAM,KAAK,KAAK,GAAI;AAC7C,QAAM,QAAQ,WAAW,MAAM,IAAI;AACnC,SAAO,WAAW,MAAM,QAAQ,KAAK,KAAK,KAAM,MAAM,GAAG,MAAM,CAAC;AAClE;AAsCA,IAAM,eAAe;AAYd,SAAS,YAAY,MAAiB,OAA0C,CAAC,GAAuB;AAC7G,QAAM,IAAI,KAAK,KAAK;AACpB,QAAM,KAAK,KAAK,MAAM;AACtB,QAAM,SAAS,WAAW,kBAAkB,MAAM,CAAC,GAAG,IAAI;AAC1D,QAAM,SAAS,KAAK,WAAW,WAAW,kBAAkB,MAAM,IAAI,EAAE,GAAG,IAAI,IAAI;AACnF,QAAM,EAAE,GAAG,EAAE,IAAI;AACjB,QAAM,OAAO,KAAK,IAAI,GAAG,CAAC;AAC1B,SAAO,OAAO,OAAO,IAAI,CAAC,EAAE,OAAO,SAAS,GAAG,eAAe;AAC5D,UAAM,YAAY,OAAO,OAAO,UAAU,GAAG,YAAY;AACzD,QAAI,MAAM;AACV,QAAI,MAAM;AACV,QAAI,IAAI;AACR,QAAI,KAAK;AACT,QAAI,KAAK;AACT,QAAI,UAAU;AACd,aAAS,QAAQ,CAAC,GAAG,MAAM;AACzB,YAAM,KAAK,MAAM,QAAQ,GAAG,CAAC;AAC7B,YAAM,KAAK,MAAM,QAAQ,UAAU,CAAC,KAAK,GAAG,IAAI,EAAE;AAClD,YAAM,KAAK,GAAG,IAAI,GAAG;AACrB,YAAM,KAAK,GAAG,IAAI,GAAG;AACrB,UAAI,KAAK,IAAI,EAAE,IAAI,IAAI,KAAK,KAAK,IAAI,EAAE,IAAI,IAAI,EAAG;AAClD,YAAM,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACxC,YAAM,QAAS,OAAO,KAAM;AAC5B,aAAO;AACP,YAAM,KAAK,IAAI,KAAK,KAAK;AACzB;AACA,UAAI,OAAO,GAAG;AACZ,cAAM,KAAK;AACX,cAAM,KAAK;AACX;AAAA,MACF;AAAA,IACF,CAAC;AACD,UAAM,YAAY,IAAI,MAAM,IAAI;AAChC,UAAM,cAAc,YAAY;AAChC,UAAM,aAAa,MAAM;AACzB,UAAM,SAAS,cAAc;AAC7B,QAAI,UAAyB;AAC7B,QAAI,gBAA+B;AACnC,QAAI,UAAU,UAAU,GAAG;AACzB,YAAM,KAAK,KAAK;AAChB,YAAM,KAAK,KAAK;AAChB,YAAM,MAAM,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACvC,sBAAgB,IAAI;AACpB,gBAAU,MAAM,QAAS,KAAK,MAAM,IAAI,EAAE,IAAI,MAAO,KAAK,KAAK,OAAO,MAAM;AAAA,IAC9E;AACA,WAAO,EAAE,YAAY,KAAK,MAAM,KAAK,WAAW,UAAU,KAAK,aAAa,YAAY,QAAQ,SAAS,cAAc;AAAA,EACzH,CAAC;AACH;AAmBA,SAAS,SAAS,GAAoF;AACpG,QAAM,MAAM,KAAK,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAClC,QAAM,MAAM,KAAK,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAClC,QAAM,KAAK,MAAM,OAAO;AACxB,QAAM,IAAI,MAAM;AAChB,MAAI,IAAI,KAAM,QAAO,EAAE,GAAG,MAAM,GAAG,GAAG,EAAE;AACxC,QAAM,MAAM,IAAI,MAAM,KAAK,IAAI,MAAM,OAAO,KAAK,MAAM;AACvD,MAAI;AACJ,MAAI,QAAQ,EAAE,EAAG,OAAM,EAAE,IAAI,EAAE,KAAK,KAAK,EAAE,IAAI,EAAE,IAAI,IAAI,MAAM;AAAA,WACtD,QAAQ,EAAE,EAAG,OAAM,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK;AAAA,MAC7C,OAAM,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK;AACjC,SAAO,EAAE,GAAG,MAAM,OAAO,OAAO,GAAG,GAAG,KAAK,EAAE;AAC/C;AAEA,SAAS,MAAM,GAAgD;AAC7D,QAAM,IAAI,CAAC,MAAc,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AACnG,SAAO,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACrC;AAEA,SAAS,eAAe,GAAiH;AACvI,QAAM,MAAM,SAAS,CAAC;AACtB,SAAO,EAAE,KAAK,IAAI,MAAM,OAAO,OAAO,KAAK,MAAM,IAAI,CAAC,GAAG,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAAE,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC,GAAG,KAAK,MAAM,CAAC,EAAE;AACzI;AAYO,SAAS,YAAY,MAAiB,OAAwB,CAAC,GAAgB;AACpF,QAAM,IAAI,KAAK,KAAK;AAEpB,SAAO,kBAAkB,MAAM,CAAC;AAChC,QAAM,QAAQ,WAAW,MAAM,IAAI;AACnC,MAAI,KAAK;AACT,MAAI,KAAK;AACT,MAAI,KAAK;AACT,MAAI,OAAO;AACX,aAAW,EAAE,OAAO,SAAS,KAAK,MAAM,QAAQ;AAE9C,UAAM,QAAQ,YAAY,MAAM,MAAM,CAAC,KAAK,MAAM,YAAY,UAAa,MAAM,UAAU,SAAY,IAAI,aAAa,MAAM,KAAK;AACnI,eAAW,KAAK,UAAU;AACxB,YAAM,MAAM,UAAU,OAAO,CAAC;AAC9B,UAAI,QAAQ,KAAM;AAClB,YAAM,KAAK,OAAO,GAAG,CAAC;AACtB,YAAM,SAAS,QAAQ,GAAG,CAAC,IAAI,SAAS,MAAM,OAAO,SAAS,WAAW,KAAK,MAAM,KAAK,MAAM,KAAK,KAAK,KAAK;AAC9G,UAAI,UAAU,EAAG;AACjB,YAAM,IAAI,OAAO,GAAG;AACpB,YAAM,EAAE,IAAI;AACZ,YAAM,EAAE,IAAI;AACZ,YAAM,EAAE,IAAI;AACZ,cAAQ;AAAA,IACV;AAAA,EACF;AACA,QAAM,KAAK,cAAc,IAAI;AAC7B,QAAM,UAAU,OAAO,IAAI,EAAE,GAAG,KAAK,MAAM,GAAG,KAAK,MAAM,GAAG,KAAK,KAAK,IAAI;AAC1E,SAAO,EAAE,GAAG,eAAe,OAAO,GAAG,YAAY,eAAe,EAAE,EAAE;AACtE;AAGA,SAAS,SAAS,GAAkB,GAAiC;AACnE,MAAI,MAAM,QAAQ,MAAM,KAAM,QAAO;AACrC,MAAI,IAAI,IAAI;AACZ,SAAO,IAAI,IAAK,MAAK;AACrB,SAAO,IAAI,KAAM,MAAK;AACtB,SAAO,KAAK,MAAM,CAAC;AACrB;AAMA,IAAM,eAAe;AAAA,EACnB;AAAA,EAAY;AAAA,EAAc;AAAA,EAC1B;AAAA,EAAY;AAAA,EAAU;AAAA,EACtB;AAAA,EAAe;AAAA,EAAiB;AAClC;AAEA,SAAS,YAAY,MAA+B;AAClD,QAAM,MAAM,IAAI,MAAc,CAAC,EAAE,KAAK,CAAC;AACvC,QAAM,MAAM,IAAI,MAAc,CAAC,EAAE,KAAK,CAAC;AACvC,WAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK;AAClC,aAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK;AAClC,YAAM,MAAM,IAAI,KAAK,OAAO;AAC5B,YAAM,SAAS,KAAK,IAAI,GAAG,KAAK,MAAO,IAAI,KAAK,OAAQ,CAAC,CAAC,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,MAAO,IAAI,KAAK,OAAQ,CAAC,CAAC;AAI7G,UAAI,MAAM,KAAM,KAAK,IAAI,KAAK,MAAM,GAAG,KAAM,KAAK,kBAAkB,KAAK,gBAAgB,GAAG,IAAK,KAAK,WAAW,CAAC,EAAG;AACrH,UAAI,MAAM;AAAA,IACZ;AAAA,EACF;AACA,SAAO,IAAI,IAAI,CAAC,GAAG,MAAO,IAAI,CAAC,IAAK,IAAI,IAAI,CAAC,IAAK,CAAE;AACtD;AA6CO,SAAS,WAAW,GAAc,GAAc,OAA6B,CAAC,GAAc;AACjG,QAAM,IAAI,KAAK,KAAK;AACpB,QAAM,QAAQ,cAAc,GAAG,IAAI;AACnC,QAAM,QAAQ,cAAc,GAAG,IAAI;AACnC,QAAM,QAAQ,YAAY,KAAK;AAC/B,QAAM,QAAQ,YAAY,KAAK;AAC/B,QAAM,OAAO,iBAAiB,GAAG,IAAI;AACrC,QAAM,OAAO,iBAAiB,GAAG,IAAI;AAErC,QAAM,SAAS,CAAC,MAA8B,EAAE,OAAO,SAAS,EAAE,UAAU;AAC5E,QAAM,QAAQ,oBAAI,IAAY,CAAC,GAAG,KAAK,IAAI,MAAM,GAAG,GAAG,KAAK,IAAI,MAAM,CAAC,CAAC;AACxE,QAAM,YAAY,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,QAAQ;AACxC,UAAM,MAAM,KAAK,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,GAAG;AAC9C,UAAM,MAAM,KAAK,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,GAAG;AAC9C,WAAO;AAAA,MACL;AAAA,MACA,OAAO,KAAK,QAAQ;AAAA,MACpB,OAAO,KAAK,QAAQ;AAAA,MACpB,QAAQ,KAAK,SAAS;AAAA,MACtB,QAAQ,KAAK,SAAS;AAAA,IACxB;AAAA,EACF,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,KAAK,IAAI,EAAE,SAAS,EAAE,MAAM,IAAI,KAAK,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC;AAK/E,QAAM,KAAK,KAAK,YAAY,EAAE,OAAO,MAAM,QAAQ,KAAK;AACxD,QAAM,SAAS,IAAI,IAAI,WAAW,GAAG,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC3D,QAAM,SAAS,IAAI,IAAI,WAAW,GAAG,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAE3D,QAAM,OAAO,YAAY,GAAG,IAAI;AAChC,QAAM,OAAO,YAAY,GAAG,IAAI;AAChC,QAAM,OAAO,YAAY,GAAG,IAAI;AAChC,QAAM,OAAO,YAAY,GAAG,IAAI;AAChC,QAAM,WAAW,CAAC,OAA2B,QAAkC;AAC7E,QAAI,MAAM;AACV,QAAI,IAAI;AACR,eAAW,KAAK,OAAO;AACrB,YAAM,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,eAAe,EAAE,UAAU,GAAG,eAAe;AACzE,aAAO,EAAE,cAAc;AACvB,WAAK;AAAA,IACP;AACA,WAAO,IAAI,MAAM,IAAI;AAAA,EACvB;AACA,QAAM,YAAY,CAAC,MAAgC,EAAE,OAAO,SAAS,EAAE,UAAU;AACjF,QAAM,eAAe,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,KAAK,IAAI,SAAS,GAAG,GAAG,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC,EAC/E,IAAI,CAAC,QAAQ;AACZ,UAAM,KAAK,KAAK,KAAK,CAAC,MAAM,UAAU,CAAC,MAAM,GAAG;AAChD,UAAM,KAAK,KAAK,KAAK,CAAC,MAAM,UAAU,CAAC,MAAM,GAAG;AAChD,UAAM,KAAK,IAAI,eAAe;AAC9B,UAAM,KAAK,IAAI,eAAe;AAC9B,WAAO,EAAE,KAAK,GAAG,IAAI,GAAG,IAAI,OAAO,KAAK,IAAI,UAAU,IAAI,WAAW,MAAM,UAAU,IAAI,WAAW,KAAK;AAAA,EAC3G,CAAC,EACA,OAAO,CAAC,MAAM,KAAK,IAAI,EAAE,KAAK,IAAI,QAAQ,EAAE,aAAa,EAAE,QAAQ,EACnE,KAAK,CAAC,GAAG,MAAM,KAAK,IAAI,EAAE,KAAK,IAAI,KAAK,IAAI,EAAE,KAAK,CAAC;AACvD,QAAM,WAAW,SAAS,MAAM,IAAI;AACpC,QAAM,WAAW,SAAS,MAAM,IAAI;AAEpC,SAAO;AAAA,IACL;AAAA,IACA,UAAU,EAAE,GAAG,MAAM,UAAU,GAAG,MAAM,UAAU,OAAO,MAAM,WAAW,MAAM,SAAS;AAAA,IACzF,eAAe,EAAE,GAAG,MAAM,eAAe,GAAG,MAAM,eAAe,OAAO,MAAM,gBAAgB,MAAM,cAAc;AAAA,IAClH,cAAc,MAAM,YAAY,MAAM,WAClC,EAAE,IAAI,MAAM,SAAS,IAAI,MAAM,SAAS,GAAG,IAAI,MAAM,SAAS,IAAI,MAAM,SAAS,EAAE,IACnF;AAAA,IACJ,SAAS,aAAa,IAAI,CAAC,QAAQ,OAAO,EAAE,QAAQ,GAAG,MAAM,CAAC,GAAI,GAAG,MAAM,CAAC,GAAI,OAAO,MAAM,CAAC,IAAK,MAAM,CAAC,EAAG,EAAE;AAAA,IAC/G;AAAA,IACA,QAAQ;AAAA,MACN,GAAG;AAAA,MACH,GAAG;AAAA,MACH,UAAU,SAAS,KAAK,KAAK,KAAK,GAAG;AAAA,MACrC,iBAAiB,EAAE,KAAK,aAAa,KAAK,YAAY,QAAQ,CAAC;AAAA,MAC/D,aAAa,EAAE,KAAK,SAAS,KAAK,QAAQ,QAAQ,CAAC;AAAA,MACnD,YAAY;AAAA,QACV,UAAU,SAAS,KAAK,WAAW,KAAK,KAAK,WAAW,GAAG;AAAA,QAC3D,aAAa,EAAE,KAAK,WAAW,SAAS,KAAK,WAAW,QAAQ,QAAQ,CAAC;AAAA,MAC3E;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,SAAS,EAAE,GAAG,UAAU,GAAG,UAAU,OAAO,WAAW,SAAS;AAAA,MAChE,QAAQ;AAAA,IACV;AAAA,IACA,YAAY;AAAA,MACV,OAAO,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;AAAA,MAC/C,SAAS,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;AAAA,IACnD;AAAA,EACF;AACF;AAsCO,SAAS,cAAc,MAAiB,OAA6B,CAAC,GAAoB;AAI/F,QAAM,QAAQ;AACd,SAAO,kBAAkB,MAAM,KAAK,KAAK,GAAI;AAC7C,QAAM,OAAO,cAAc,MAAM,IAAI;AACrC,SAAO;AAAA,IACL,GAAG,KAAK,KAAK;AAAA,IACb,SAAS,iBAAiB,IAAI;AAAA,IAC9B,SAAS,iBAAiB,IAAI;AAAA,IAC9B,UAAU,KAAK;AAAA,IACf,eAAe,KAAK;AAAA,IACpB,UAAU,KAAK;AAAA,IACf,YAAY,KAAK;AAAA,IACjB,YAAY,KAAK;AAAA,IACjB,WAAW,iBAAiB,MAAM,IAAI;AAAA,IACtC,QAAQ,YAAY,OAAO,IAAI;AAAA,IAC/B,MAAM,cAAc,MAAM,IAAI;AAAA,IAC9B,QAAQ,YAAY,MAAM,IAAI;AAAA,IAC9B,MAAM,YAAY,MAAM,IAAI;AAAA,IAC5B,YAAY,WAAW,MAAM,KAAK,YAAY,EAAE,OAAO,MAAM,QAAQ,KAAK,GAAG,EAAE,GAAG,KAAK,GAAG,MAAM,KAAK,KAAK,CAAC;AAAA,EAC7G;AACF;AAmBA,IAAM,SAAS,CAAC,KAAyB,eAA+B,OAAO,OAAO,UAAU;AAsCzF,SAAS,sBAAsB,KAAmB,GAAW,OAAgC,CAAC,GAA4B;AAC/H,QAAM,EAAE,eAAe,GAAG,SAAS,IAAI;AACvC,QAAM,IAAI,eAAe,KAAK,GAAG,EAAE,cAAc,CAAC;AAClD,QAAM,MAAM,IAAI,SAAS,EAAE,KAAK;AAChC,QAAM,UAA8C,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,KAAK,QAAQ,EAAE,QAAQ,GAAI,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,EAAG;AACxI,QAAM,UAAgC,EAAE,GAAG,UAAU,GAAG,EAAE,QAAQ,MAAM,SAAS,QAAQ,kBAAkB,KAAK,EAAE,KAAK,EAAE;AACzH,MAAI,CAAC,IAAI,IAAK,QAAO,EAAE,GAAG,cAAc,IAAI,OAAO,OAAO,GAAG,SAAS,KAAK,MAAM;AAEjF,QAAM,UAAgC,EAAE,GAAG,UAAU,GAAG,GAAG,MAAM,SAAS,QAAQ,cAAc,GAAG,EAAE;AACrG,QAAM,WAAW,SAAS,YAAY,EAAE,OAAO,MAAM,QAAQ,KAAK;AAGlE,QAAM,MAAiB,EAAE,GAAG,IAAI,OAAO,YAAY,EAAE,MAAM,SAAS,OAAO,UAAU,EAAE;AACvF,SAAO,IAAI;AAEX,QAAM,aAAwB,EAAE,GAAG,KAAK,YAAY,IAAI,IAAI,cAAc,EAAE,MAAM,SAAS,OAAO,UAAU,EAAE;AAE9G,QAAM,UAAU,cAAc,IAAI,KAAK,OAAO;AAC9C,QAAM,UAAU,cAAc,KAAK,OAAO;AAC1C,QAAM,QAAQ,QAAQ,MAAM,IAAI,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,IAAI,QAAQ,MAAM,CAAC,CAAE,CAAC;AAC5E,QAAM,OAAO,WAAW,QAAQ,MAAM,QAAQ,MAAM,OAAO,QAAQ,YAAY,QAAQ,eAAe;AAEtG,QAAM,YAAY,IAAI,IAAI,OAAO;AACjC,QAAM,YAAY,cAAc;AAAA,IAC9B,GAAG,aAAa,IAAI,KAAK,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,KAAK,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;AAAA,IACzF,GAAG,aAAa,YAAY,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,YAAY,EAAE,aAAa,UAAU,EAAE;AAAA,EAClG,CAAC;AACD,QAAM,QAAQ,CAAmC,OAAa,EAAE,GAAG,GAAG,YAAY,EAAE,aAAa,UAAU;AAC3G,QAAM,SAAS,CAA4D,OAAa,EAAE,GAAG,GAAG,KAAK,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE;AAEjI,SAAO;AAAA,IACL,GAAG,EAAE;AAAA,IACL,SAAS,iBAAiB,IAAI;AAAA,IAC9B,SAAS,iBAAiB,IAAI;AAAA,IAC9B,UAAU,KAAK;AAAA,IACf,eAAe,KAAK;AAAA,IACpB,UAAU,KAAK;AAAA,IACf,YAAY,KAAK;AAAA,IACjB,YAAY,KAAK;AAAA,IACjB;AAAA,IACA,QAAQ,CAAC,GAAG,YAAY,IAAI,KAAK,OAAO,EAAE,IAAI,MAAM,GAAG,GAAG,YAAY,KAAK,OAAO,EAAE,IAAI,KAAK,CAAC;AAAA,IAC9F,MAAM,CAAC,GAAG,cAAc,IAAI,KAAK,OAAO,EAAE,IAAI,MAAM,GAAG,GAAG,cAAc,KAAK,OAAO,EAAE,IAAI,KAAK,CAAC;AAAA,IAChG,MAAM,CAAC,GAAG,YAAY,IAAI,KAAK,OAAO,EAAE,IAAI,MAAM,GAAG,GAAG,YAAY,KAAK,OAAO,EAAE,IAAI,KAAK,CAAC;AAAA;AAAA;AAAA,IAG5F,QAAQ,YAAY,YAAY,OAAO;AAAA,IACvC,YAAY;AAAA,MACV,GAAG,WAAW,IAAI,KAAK,UAAU,EAAE,GAAG,GAAG,MAAM,QAAQ,KAAK,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM,OAAO,EAAE,IAAI,GAAG,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAU3G,GAAG,WAAW,YAAY,UAAU,EAAE,GAAG,EAAE,QAAQ,MAAM,QAAQ,MAAM,gBAAgB,QAAQ,QAAQ,GAAG,CAAC;AAAA,IAC7G;AAAA,IACA;AAAA,IACA,KAAK;AAAA,EACP;AACF;;;AHprDA,IAAM,qBAAqB;AAO3B,IAAM,+BAA+B;AAOrC,IAAM,wBAAwB;AAG9B,IAAM,iBAAiB;AAcvB,IAAM,uBAAuB;AAK7B,SAAS,aAAa,OAA8C;AAClE,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,CAAC,GAAG,CAAC,IAAI;AACf,UAAQ,KAAK,QAAQ,KAAK,SAAS,IAAI,KAAK;AAC9C;AAMO,SAAS,WACd,MACA,WAAW,EAAE,OAAO,MAAM,QAAQ,KAAK,GAcvC,OAA+D,CAAC,GACjD;AAMf,QAAM,SAAS,aAAa,IAAI;AAEhC,SAAO,kBAAkB,MAAM,KAAK,KAAK,UAAU;AACnD,QAAM,WAA0B,CAAC;AACjC,QAAM,IAAI,SAAS;AACnB,QAAM,IAAI,SAAS;AACnB,QAAM,EAAE,OAAO,WAAW,IAAI,aAAa,MAAM,GAAG,CAAC;AACrD,QAAM,MAAME,WAAU,KAAK,QAAQ,KAAK,QAAQ,EAAE;AAClD,QAAM,cAAc,KAAK,OAAO,IAAI,CAAC,MAAM,cAAc,GAAG,KAAK,GAAG,GAAG,OAAO,UAAU,CAAC;AAKzF,QAAM,WAAW;AAAA,IACf,KAAK,OAAO,IAAI,CAAC,OAAO,OAAO,EAAE,OAAO,UAAU,YAAY,CAAC,EAAG,EAAE;AAAA,IACpE,KAAK,KAAK;AAAA,IAAY;AAAA,IAAG;AAAA,EAC3B;AAEA,MAAI,gBAAgB;AACpB,MAAI,iBAAiB;AACrB,MAAI,mBAAmB;AAEvB,WAAS,KAAK,GAAG,KAAK,KAAK,OAAO,QAAQ,MAAM;AAC9C,QAAI,SAAS,EAAE,EAAG;AAClB,UAAM,QAAQ,KAAK,OAAO,EAAE;AAC5B,UAAM,WAAW,YAAY,EAAE;AAC/B,qBAAiB,SAAS;AAE1B,UAAM,SAAS,MAAM,OAAO,SAAS,UAAU,MAAM,OAAO,SAAS;AACrE,UAAM,eAAe,UAAU,MAAM,OAAO,SAAS;AACrD,QAAI,aAAc;AAClB,QAAI,MAAM,OAAO,SAAS,SAAU;AAEpC,UAAM,MAAM,SAAS,EAAE;AACvB,QAAI,kBAAkB,OAAO,KAAK,SAAS,MAAM,GAAG;AAMlD,YAAM,IAAI,MAAM;AAChB,YAAM,aAAc,EAAE,SAAS,YAAY,EAAE,SAAS,cAAc,EAAE,QAAU,EAAE,SAAS,UAAU,CAAC,CAAC,EAAE;AACzG,eAAS,KAAK;AAAA,QACZ,MAAM,UAAU,EAAE;AAAA,QAClB,MAAM;AAAA,QACN,SAAS,YACL,iBAAiB,KAAK,OAAO,IAAI,WAAW,KAAK,GAAG,CAAC,mCAAmC,IAAI,SAAS,kQAGrG,iBAAiB,KAAK,OAAO,IAAI,WAAW,KAAK,GAAG,CAAC,8EAC5C,IAAI,SAAS;AAAA,MAE5B,CAAC;AAAA,IACH;AAEA,QAAI,MAAM,SAAS,MAAM,OAAO,SAAS,UAAU;AACjD,eAAS,KAAK;AAAA,QACZ,MAAM,UAAU,EAAE;AAAA,QAClB,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAIA,SAAK,MAAM,OAAO,SAAS,YAAa,MAAM,OAAO,SAAS,YAAY,MAAM,OAAO,WAAY,MAAM,OAAO,SAAS,YAAY,CAAC,MAAM,MAAM;AAChJ,eAAS,KAAK;AAAA,QACZ,MAAM,UAAU,EAAE;AAAA,QAClB,MAAM;AAAA,QACN,SAAS,GAAG,MAAM,OAAO,SAAS,WAAW,0BAA0B,0BAA0B;AAAA,MACnG,CAAC;AAAA,IACH;AAEA,QAAI,MAAM,OAAO,SAAS,YAAY,MAAM,OAAO,cAAc,KAAK,SAAS,UAAU,IAAI;AAC3F,eAAS,KAAK;AAAA,QACZ,MAAM,UAAU,EAAE;AAAA,QAClB,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,QAAI,MAAM,OAAO,SAAS,UAAU;AAClC,YAAM,OAAO,SAAS,OAAO,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC;AACjE,YAAM,WAAW,SAAS,OAAO,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,KAAK,GAAG,CAAC;AAClE,UAAI,OAAO,WAAW,MAAM;AAC1B,iBAAS,KAAK;AAAA,UACZ,MAAM,UAAU,EAAE;AAAA,UAClB,MAAM;AAAA,UACN,SAAS,+BAA+B,KAAK,QAAQ,CAAC,CAAC,WAAQ,SAAS,QAAQ,CAAC,CAAC;AAAA,QACpF,CAAC;AAAA,MACH;AAAA,IACF;AAMA,QAAI,SAAS,SAAS,KAAK,MAAM,OAAO,SAAS,SAAS;AAKxD,YAAM,CAAC,IAAI,EAAE,IAAI,MAAM,WAAW,CAAC,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,IAAK,MAAM,QAAQ,KAAK,CAAC,GAAG,CAAC;AAClG,YAAM,SAAS,CAAC,KAAK,KAAK,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC,MAAM;AAChD,cAAM,MAAM,gBAAgB,MAAM,IAAI,GAAG,GAAG,OAAO,QAAW,QAAW,KAAK,kBAAkB,KAAK,MAAM,KAAK,KAAK,UAAU;AAC/H,eAAO,EAAE,KAAK,MAAM,SAAS,IAAI,IAAI,SAAS,IAAI,IAAI,SAAS,IAAI,EAAE;AAAA,MACvE,CAAC;AAGD,YAAM,OAAO,SAAS,IAAI,CAAC,MAAM;AAC/B,cAAM,MAAM,UAAU,OAAO,CAAC;AAC9B,YAAI,QAAQ,KAAM,QAAO;AACzB,cAAM,MAAM,EAAE,KAAK,OAAO,GAAG,GAAG,MAAM,QAAQ,GAAG,EAAE;AACnD,cAAM,MAAM,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,OAAO,iBAAiB,OAAO,KAAK,EAAE,CAAC,CAAC;AAC5E,YAAI,OAAO,sBAAsB,MAAM,UAAU,aAAa,MAAM,UAAU,SAAU,QAAO;AAI/F,cAAM,QAAQ,YAAY,MAAM,aAAa,IAAI,QAAQ,WAAW,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;AACrF,eAAO,QAAQ,iBAAiB,OAAO,KAAK,KAAK,IAAI;AAAA,MACvD,CAAC;AACD,YAAM,OAAO,KAAK,IAAI,GAAG,IAAI;AAC7B,UAAI,OAAO,oBAAoB;AAC7B,cAAM,WAAW,MAAM,UAAU,aAAa,MAAM,UAAU;AAC9D,iBAAS,KAAK;AAAA,UACZ,MAAM,UAAU,EAAE;AAAA,UAClB,MAAM;AAAA,UACN,SAAS,WACL,6CAA6C,KAAK,QAAQ,CAAC,CAAC,2EAC5D,0BAA0B,KAAK,QAAQ,CAAC,CAAC,6DAA6D,kBAAkB;AAAA,QAC9H,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EAEF;AAGA,MAAI,gBAAgB;AACpB,MAAI,cAAc;AAClB,WAAS,KAAK,GAAG,KAAK,KAAK,OAAO,QAAQ,MAAM;AAC9C,QAAI,SAAS,EAAE,EAAG;AAClB,UAAM,QAAQ,KAAK,OAAO,EAAE;AAC5B,UAAM,WAAW,YAAY,EAAE;AAE/B,UAAM,SAAS,MAAM,YAAY,UAAa,MAAM,UAAU,SAAY,IAAI,aAAa,MAAM,KAAK;AAKtG,UAAM,MAAM,SAAS,MAAM,OAAO,GAAG,GAAG,KAAK;AAC7C,UAAM,YAAY,MAAM,UAAU,MAAM,KAAK,KAAK,IAAI;AACtD,UAAM,WAAW,MAAM,UAAU,aAAa,MAAM,UAAU;AAC9D,eAAW,KAAK,UAAU;AACxB,YAAM,IAAI,EAAE,OAAO;AACnB,UAAI;AACJ,UAAI,MAAM,OAAO,SAAS,UAAU;AAClC,kBAAU,KAAK,KAAK,IAAI;AAAA,MAC1B,WAAW,MAAM,OAAO,SAAS,WAAW;AAG1C,kBAAU,YAAY,cAAc,MAAM,QAAQ,CAAC,CAAC;AAAA,MACtD,WAAW,MAAM,OAAO,SAAS,OAAO;AACtC,kBAAU,EAAE,OAAO,YAAY,MAAM,QAAQ,EAAE,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO;AAAA,MACvF,WAAW,MAAM,OAAO,SAAS,aAAa;AAC5C,cAAM,OAAO,MAAM,OAAO,WAAW;AACrC,cAAM,MAAM,MAAM,OAAO,cAAc,OAAO;AAC9C,cAAM,SAAS,MAAM,OAAO,WAAW;AACvC,cAAM,QAAQ,eAAe,MAAM,OAAO,MAAM,SAAS,MAAM,oBAAoB,MAAM,OAAO,IAAI,CAAC;AACrG,kBAAU,SAAS,MAAM,SAAS,KAAK,QAAQ,MAAM,OAAO,WAAW;AAAA,MACzE,WAAW,MAAM,OAAO,SAAS,QAAQ;AAGvC,cAAM,IAAI,UAAU,MAAM,QAAQ,GAAG,WAAW,GAAG,GAAG,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC;AACvE,mBAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM;AAAA,MAC5C,OAAO;AACL,kBAAU,EAAE,OAAO,EAAE;AAAA,MACvB;AAEA,UAAI,cAAc,EAAG,YAAW;AAChC,UAAI,UAAU,IAAI,EAAG,WAAU,IAAI;AAInC,UAAI,OAAO;AACX,UAAI,MAAM,MAAM;AAGd,cAAM,CAAC,IAAI,EAAE,IAAI,MAAM,KAAK,QAAQ,CAAC,GAAG,CAAC;AACzC,cAAM,MAAM,KAAK,KAAK,KAAK,KAAK,KAAK,MAAM;AAC3C,eAAQ,KAAK,IAAI,MAAM,KAAK,MAAM,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,QAAS,MAAM;AAAA,MAClF;AACA,YAAM,MAAM,WAAW,IAAK,UAAU,EAAE,QAAQ,QAAS,IAAI,KAAM,UAAU,EAAE,QAAQ,OAAO,UAAW,IAAI;AAC7G,uBAAiB;AACjB,UAAI,SAAU,gBAAe;AAAA,IAC/B;AAEA,QAAI,MAAM,OAAO;AACf,YAAM,YAAY,SAAS,IAAI,CAAC,MAAM,WAAW,GAAG,GAAG,GAAG,CAAC,CAAC;AAC5D,YAAM,QAAQ,UAAU,MAAM,OAAO,WAAW,cAAc,MAAM,OAAO,KAAK,GAAG,MAAM,SAAS,OAAO,GAAG,CAAC;AAC7G,YAAM,eAAe,UAAU,IAAI,IAAI,IAAI,OAAO;AAClD,YAAM,QAAQ,MAAM,MAAM,SAAS,gBAAgB;AACnD,YAAM,KAAK,MAAM,MAAM,SAAS;AAChC,iBAAW,QAAQ,MAAO,kBAAiB,WAAW,IAAK,KAAK,OAAO,OAAO,MAAO,IAAI,KAAM,KAAK,OAAO,OAAO,KAAK,UAAW,IAAI;AAAA,IACxI;AAAA,EACF;AAKA,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,gBAAgB,gBAAgB,QAAU,KAAK,OAAO,SAAS;AACrE,MAAI,iBAAiB,YAAY,UAAU;AACzC,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,+BAA+B,gBAAgB,KAAK,QAAQ,CAAC,CAAC;AAAA,IACzE,CAAC;AAAA,EACH;AAEA,MAAI,cAAc,sBAAsB;AACtC,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,mCAAmC,YAAY,QAAQ,CAAC,CAAC;AAAA,IACpE,CAAC;AAAA,EACH;AAEA,MAAI,gBAAgB,OAAO,YAAY,SAAS;AAC9C,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,GAAG,aAAa;AAAA,IAC3B,CAAC;AAAA,EACH;AAEA,MAAI,YAAY,YAAY,gBAAgB,8BAA8B;AACxE,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,mDAAmD,gBAAgB,KAAK,QAAQ,CAAC,CAAC;AAAA,IAC7F,CAAC;AAAA,EACH,WAAW,YAAY,WAAW,eAAe;AAC/C,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS,kDAAkD,gBAAgB,KAAK,QAAQ,CAAC,CAAC;AAAA,IAC5F,CAAC;AAAA,EACH;AAEA,MAAI,KAAK,OAAO,SAAS,KAAK,iBAAiB,KAAK,qBAAqB,GAAG;AAC1E,UAAM,YAAY,iBAAiB,KAAK,OAAO;AAC/C,QAAI,aAAa,KAAK;AACpB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAIA,WAAS,KAAK,GAAG,KAAK,KAAK,OAAO,QAAQ,MAAM;AAC9C,QAAI,SAAS,EAAE,EAAG;AAClB,UAAM,QAAQ,KAAK,OAAO,EAAE;AAC5B,QAAI,CAAC,MAAM,SAAS,MAAM,MAAM,SAAS,QAAS;AAClD,UAAM,WAAW,YAAY,EAAE;AAC/B,UAAM,YAAY,SAAS,IAAI,CAAC,MAAM,WAAW,GAAG,GAAG,GAAG,CAAC,CAAC;AAC5D,UAAM,IAAI,MAAM,MAAM,KAAK;AAC3B,UAAM,QAAQ,UAAU,WAAW,GAAG,cAAc,MAAM,OAAO,KAAK,GAAG,MAAM,SAAS,OAAO,GAAG,CAAC;AACnG,UAAM,cAAc,KAAK,IAAI,SAAS,SAAS,GAAG,SAAS,UAAU,SAAS,SAAS,KAAK,CAAC;AAC7F,QAAI,cAAc,KAAK,MAAM,SAAS,cAAc,KAAK;AACvD,eAAS,KAAK;AAAA,QACZ,MAAM,UAAU,EAAE;AAAA,QAClB,MAAM;AAAA,QACN,SAAS,QAAQ,MAAM,MAAM,IAAI,WAAW;AAAA,MAC9C,CAAC;AAAA,IACH;AAAA,EACF;AAGA,WAAS,KAAK,GAAG,KAAK,KAAK,OAAO,QAAQ,MAAM;AAC9C,QAAI,SAAS,EAAE,EAAG;AAClB,UAAM,QAAQ,KAAK,OAAO,EAAE;AAC5B,QAAI,MAAM,OAAO,SAAS,SAAU;AACpC,UAAM,WAAW,YAAY,EAAE;AAC/B,QAAI,SAAS,SAAS,EAAG;AACzB,UAAM,SAAS,SAAS,IAAI,CAAC,MAAM,KAAK,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;AACvE,UAAM,OAAO,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,OAAO;AACxD,QAAI,SAAS,EAAG;AAChB,UAAM,SAAS,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC;AAChE,QAAI,SAAS,OAAO,MAAM;AACxB,eAAS,KAAK;AAAA,QACZ,MAAM,UAAU,EAAE;AAAA,QAClB,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAKA,QAAM,WAAW,KAAK,OACnB,IAAI,CAAC,GAAG,QAAQ,EAAE,GAAG,IAAI,MAAM,YAAY,EAAE,EAAG,EAAE,EAClD,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC,EAChC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,UAAU,QAAQ,MAAM,EAAE,SAAS,EAAE,OAAO,IAAI,CAAC,EAGrE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,SAAS,WAAW,EAAE,OAAO,UAAU,WAAW,EAAE,OAAO,OAAO;AAClG,QAAM,gBAAgB,SAAS,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,KAAK,QAAQ,CAAC;AACpE,MAAI,iBAAiB,GAAG;AACtB,UAAM,YAAY,SAAS,QAAQ,CAAC,EAAE,KAAK,MAAM,KAAK,IAAI,CAAC,MAAM,WAAW,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;AACxF,UAAM,KAAK,UAAU,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,GAAG,CAAC,IAAI,UAAU,SAAS;AACvE,UAAM,KAAK,UAAU,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,GAAG,CAAC,IAAI,UAAU,SAAS;AAIvE,UAAM,OAAO,KAAK,IAAI,KAAK,GAAG;AAC9B,UAAM,OAAO,KAAK,IAAI,KAAK,GAAG;AAC9B,UAAM,aAAa,CAAC,SAClB,SAAS,OAAO,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,KAAK,aAAa,EAAE,SAAS,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI;AACnG,UAAM,cACH,OAAO,OAAO,QAAQ,OAAO,WAAW,GAAG,KAAK,OAChD,OAAO,OAAO,QAAQ,OAAO,WAAW,GAAG,KAAK;AACnD,SAAK,OAAO,OAAO,OAAO,QAAQ,CAAC,aAAa;AAQ9C,YAAM,OAAO,cAAc,EAAE,GAAG,MAAM,QAAQ,SAAS,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,GAAG,QAAQ,EAAE,GAAG,GAAG,KAAK,KAAK,YAAY,MAAM,KAAK,KAAK,CAAC;AAC3J,YAAM,IAAI,KAAK;AACf,UAAI,MAAM,KAAK,IAAI,EAAE,IAAI,GAAG,IAAI,OAAO,KAAK,IAAI,EAAE,IAAI,GAAG,IAAI,MAAM;AACjE,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,gBAAgB,EAAE,EAAE,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAC;AAAA,QAC5D,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAOA,QAAM,YAAyB,CAAC;AAChC,WAAS,KAAK,GAAG,KAAK,KAAK,OAAO,QAAQ,MAAM;AAC9C,QAAI,SAAS,EAAE,EAAG;AAClB,UAAM,QAAQ,KAAK,OAAO,EAAE;AAC5B,UAAM,IAAI,MAAM;AAChB,QAAI,MAAM,OAAO,SAAS,SAAU;AACpC,QAAI,EAAE,SAAS,UAAU,EAAE,SAAS,YAAa;AACjD,UAAM,QAAQ,MAAM,MAAM,KAAK,MAAM,GAAG,OAAO,UAAU,EAAE;AAC3D,eAAW,KAAK,YAAY,EAAE,GAAI;AAChC,YAAM,IAAI,WAAW,GAAG,GAAG,GAAG,CAAC;AAC/B,YAAM,MAAM,EAAE,SAAS,cAAc,eAAe,GAAG,GAAG,GAAG,CAAC,IAAI,UAAU,GAAG,GAAG,GAAG,MAAM,GAAG,CAAC;AAE/F,YAAM,MAAM,SAAS,MAAM,OAAO,GAAG,GAAG,KAAK;AAC7C,YAAM,MAAM,MAAM,EAAE,GAAG,KAAK,GAAG,OAAO,KAAK,GAAG,EAAE,IAAI;AAOpD,YAAM,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,cAAe,EAAE,WAAW,IAAK;AAChH,YAAM,QAAQ,MAAM,YAAY,UAAa,MAAM,UAAU,SAAY,YAAY,YAAY,aAAa,MAAM,KAAK;AACzH,YAAM,MAAM,EAAE,SAAS,cAAc,EAAE,OAAQ,EAAE,QAAQ,EAAE,WAAW,KAAK,EAAE,QAAQ,CAAC,KAAK;AAC3F,gBAAU,KAAK,EAAE,IAAI,OAAO,OAAO,KAAK,GAAG,KAAK,MAAM,IAAI,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,IAAI,GAAG,CAAC;AAAA,IAChG;AAAA,EACF;AACA,QAAM,aAAa,CAAC,OAAyD;AAAA,IAC3E,GAAG,EAAE,EAAE,KAAK,GAAG,QAAQ,CAAC;AAAA,IACxB,GAAG,EAAE,EAAE,KAAK,GAAG,QAAQ,CAAC;AAAA,IACxB,GAAG,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;AAAA,IACjC,GAAG,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;AAAA,EACnC;AAIA,QAAM,OAAO,IAAI;AACjB,QAAM,OAAO,IAAI;AACjB,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,KAAK,WAAW;AACzB,QAAI,WAAW,IAAI,EAAE,EAAE,EAAG;AAC1B,UAAM,QAAkB,CAAC;AACzB,QAAI,EAAE,KAAK,CAAC,KAAM,OAAM,KAAK,iBAAiB,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI;AACnE,QAAI,EAAE,KAAK,IAAI,KAAM,OAAM,KAAK,kBAAkB,KAAK,MAAM,EAAE,KAAK,CAAC,CAAC,IAAI;AAC1E,QAAI,EAAE,KAAK,CAAC,KAAM,OAAM,KAAK,gBAAgB,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI;AAClE,QAAI,EAAE,KAAK,IAAI,KAAM,OAAM,KAAK,mBAAmB,KAAK,MAAM,EAAE,KAAK,CAAC,CAAC,IAAI;AAC3E,QAAI,MAAM,WAAW,EAAG;AACxB,eAAW,IAAI,EAAE,EAAE;AACnB,aAAS,KAAK;AAAA,MACZ,MAAM,UAAU,EAAE,EAAE;AAAA,MACpB,MAAM;AAAA,MACN,SAAS,GAAG,EAAE,KAAK,sBAAsB,MAAM,KAAK,WAAW,CAAC,OAAO,CAAC,OAAI,CAAC;AAAA,IAC/E,CAAC;AAAA,EACH;AAIA,QAAM,cAAc,oBAAI,IAAY;AACpC,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,aAAS,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AAC7C,YAAM,IAAI,UAAU,CAAC;AACrB,YAAM,IAAI,UAAU,CAAC;AACrB,UAAI,EAAE,OAAO,EAAE,GAAI;AACnB,YAAM,OAAO,GAAG,KAAK,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;AAC5D,UAAI,YAAY,IAAI,IAAI,EAAG;AAC3B,YAAM,KAAK,KAAK,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,KAAK,IAAI,EAAE,IAAI,EAAE,EAAE;AACrD,YAAM,KAAK,KAAK,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,KAAK,IAAI,EAAE,IAAI,EAAE,EAAE;AACrD,UAAI,MAAM,KAAK,MAAM,EAAG;AACxB,YAAM,UAAU,KAAK,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG;AACrF,UAAI,WAAW,EAAG;AAClB,YAAM,QAAS,KAAK,KAAM;AAC1B,UAAI,SAAS,IAAK;AAClB,UAAI,eAAe,GAAG,CAAC,EAAG;AAC1B,kBAAY,IAAI,IAAI;AACpB,YAAM,CAAC,OAAO,MAAM,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;AACpD,eAAS,KAAK;AAAA,QACZ,MAAM,UAAU,MAAM,EAAE;AAAA,QACxB,MAAM;AAAA,QACN,SAAS,GAAG,MAAM,KAAK,QAAQ,OAAO,KAAK,yBAAyB,KAAK,MAAM,QAAQ,GAAG,CAAC;AAAA;AAAA;AAAA,QAG3F,OAAO,CAAC,WAAW,KAAK,GAAG,WAAW,MAAM,CAAC;AAAA,MAC/C,CAAC;AAAA,IACH;AAAA,EACF;AAOA,QAAM,cAAc,oBAAI,IAAY;AACpC,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,UAAM,IAAI,UAAU,CAAC;AACrB,QAAI,YAAY,IAAI,EAAE,EAAE,EAAG;AAC3B,UAAM,QAAQ,KAAK,OAAO,EAAE,EAAE;AAC9B,UAAM,SAAS,MAAM;AACrB,QAAI,QAAQ,SAAS,UAAU,QAAQ,SAAS,QAAS;AACzD,aAAS,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AAC7C,YAAM,IAAI,UAAU,CAAC;AACrB,UAAI,EAAE,OAAO,EAAE,GAAI;AACnB,YAAM,KAAK,KAAK,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,KAAK,IAAI,EAAE,IAAI,EAAE,EAAE;AACrD,YAAM,KAAK,KAAK,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,KAAK,IAAI,EAAE,IAAI,EAAE,EAAE;AACrD,UAAI,MAAM,KAAK,MAAM,EAAG;AACxB,YAAM,UAAU,KAAK,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG;AACrF,UAAI,WAAW,KAAM,KAAK,KAAM,WAAW,IAAK;AAChD,kBAAY,IAAI,EAAE,EAAE;AACpB,YAAM,QAAQ,UAAU,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;AACnD,YAAM,OAAO,UAAU,IAAI,OAAO,mBAAmB,OAAO;AAC5D,YAAM,IAAI,OAAO,OAAO;AACxB,YAAM,KAAK,OAAO,MAAM,WAAW,IAAI,EAAE,KAAK;AAC9C,YAAM,KAAK,OAAO,MAAM,WAAW,IAAI,EAAE,KAAK;AAC9C,YAAM,OAAO,OAAO,SAAS,SAAS,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,OAAO,CAAC;AAChF,YAAM,SAAS,CAAC,MAAuB,UAAU,IAAI,IAAI,IAAI;AAC7D,YAAM,SAAS,CAAC,OAAwB,UAAU,IAAI,KAAK,KAAK,EAAE,IAAI,KAAK,KAAM,KAAK,QAAS,GAAG,IAAI;AACtG,YAAM,OAAO,MAAM,OAAO,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,IAAI,GAAG,CAAC;AAC1D,YAAM,OAAO,MAAM,OAAO,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,IAAI,GAAG,CAAC;AAC1D,YAAM,QAAkB,CAAC;AACzB,YAAM,SAAS,OAAO,KAAK,OAAO,OAAO,EAAE;AAC3C,UAAI,OAAQ,OAAM,KAAK,yBAAyB,KAAK,MAAM,IAAI,CAAC,qBAAqB,KAAK,MAAM,OAAO,EAAE,CAAC,CAAC,uBAAuB,OAAO,MAAM,WAAW,KAAK,IAAI,IAAI,EAAE,qBAAgB,OAAO,MAAM,WAAW,KAAK,IAAI,cAAS,OAAO,OAAO,GAAG,CAAC,EAAE;AACvP,UAAI,CAAC,UAAU,OAAO,OAAO,EAAE,EAAG,OAAM,KAAK,aAAa,KAAK,MAAM,IAAI,CAAC,qBAAqB,KAAK,MAAM,OAAO,EAAE,CAAC,CAAC,oBAAoB,OAAO,MAAM,WAAW,KAAK,IAAI,IAAI,EAAE,qBAAgB,OAAO,MAAM,WAAW,KAAK,IAAI,cAAS,OAAO,OAAO,GAAG,CAAC,EAAE;AAC9P,eAAS,KAAK;AAAA,QACZ,MAAM,UAAU,EAAE,EAAE;AAAA,QACpB,MAAM;AAAA,QACN,SAAS,GAAG,EAAE,KAAK,qBAAqB,CAAC,OAAI,CAAC,OAAO,OAAO,IAAI,8EAA8E,MAAM,KAAK,QAAQ,CAAC;AAAA,QAClK,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC,CAAC;AAAA,MACtC,CAAC;AACD;AAAA,IACF;AAAA,EACF;AAKA,QAAM,cAAc,oBAAI,IAAY;AACpC,aAAW,KAAK,WAAW;AACzB,QAAI,YAAY,IAAI,EAAE,EAAE,EAAG;AAC3B,UAAM,QAAQ,KAAK,OAAO,EAAE,EAAE;AAC9B,UAAM,IAAI,MAAM;AAChB,QAAK,EAAE,SAAS,UAAU,EAAE,SAAS,eAAgB,EAAE,SAAS,OAAQ;AAExE,UAAM,QAAQ,UAAU,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;AACnD,gBAAY,IAAI,EAAE,EAAE;AAEpB,UAAM,MAAM,OAAO,EAAE,SAAS,SAAS;AAIvC,UAAM,YAAY,CAAC,MAAW,UAAuB;AACnD,UAAI,MAAM,UAAU,aAAa,MAAM,UAAU,SAAU,QAAO,cAAc,MAAM,KAAK,OAAO,MAAM,KAAK;AAC7G,UAAI,MAAM,UAAU,YAAY;AAC9B,eAAO;AAAA,UACL,GAAG,KAAK,KAAK,IAAI,QAAQ,IAAI,IAAI;AAAA,UACjC,GAAG,KAAK,KAAK,IAAI,QAAQ,IAAI,IAAI;AAAA,UACjC,GAAG,KAAK,KAAK,IAAI,QAAQ,IAAI,IAAI;AAAA,QACnC;AAAA,MACF;AACA,aAAO,gBAAgB,MAAM,KAAK,KAAK;AAAA,IACzC;AACA,QAAI,QAA6E;AACjF,eAAW,OAAO,OAAO;AACvB,YAAM,MAAM,IAAI,KAAK,IAAI,MAAM;AAC/B,YAAM,MAAM,IAAI,KAAK,IAAI,MAAM;AAC/B,YAAM,YAAY,gBAAgB,MAAM,IAAI,GAAG,OAAO,IAAI,GAAG,KAAK,kBAAkB,KAAK,MAAM,KAAK,KAAK,UAAU;AACnH,YAAM,SAAS,gBAAgB,UAAU,WAAW,IAAI,KAAK,GAAG,SAAS;AACzE,YAAM,MAAM,uBAAuB,MAAM,aAAa,WAAW,KAAK,GAAG,CAAC;AAC1E,YAAM,QAAQ,MAAM,gBAAgB,UAAU,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;AAC9E,UAAI,CAAC,SAAS,KAAK,IAAI,QAAQ,KAAK,IAAI,KAAK,IAAI,MAAM,QAAQ,MAAM,KAAK,GAAG;AAC3E,gBAAQ,EAAE,QAAQ,OAAO,YAAY,KAAK,SAAS,KAAK;AAAA,MAC1D;AAAA,IACF;AACA,QAAI,SAAS,KAAK,IAAI,MAAM,QAAQ,MAAM,KAAK,IAAI,uBAAuB;AACxE,YAAM,QAAQ,MAAM,aAChB,QAAQ,MAAM,MAAM,QAAQ,CAAC,CAAC,YAAY,MAAM,UAAU,sBAC1D;AACJ,eAAS,KAAK;AAAA,QACZ,MAAM,UAAU,EAAE,EAAE;AAAA,QACpB,MAAM;AAAA,QACN,SAAS,GAAG,EAAE,KAAK,qDAAqD,MAAM,OAAO,QAAQ,CAAC,CAAC,8CAA8C,KAAK,iBAAY,qBAAqB;AAAA,MACrL,CAAC;AAAA,IACH;AAIA,UAAM,QAAkB,CAAC;AACzB,UAAM,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC7C,UAAM,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC7C,UAAM,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC7C,UAAM,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC7C,QAAI,KAAK,IAAI,eAAgB,OAAM,KAAK,MAAM;AAC9C,QAAI,KAAK,KAAK,IAAI,gBAAiB,OAAM,KAAK,OAAO;AACrD,QAAI,KAAK,IAAI,eAAgB,OAAM,KAAK,KAAK;AAC7C,QAAI,KAAK,KAAK,IAAI,gBAAiB,OAAM,KAAK,QAAQ;AACtD,QAAI,MAAM,SAAS,GAAG;AACpB,eAAS,KAAK;AAAA,QACZ,MAAM,UAAU,EAAE,EAAE;AAAA,QACpB,MAAM;AAAA,QACN,SAAS,GAAG,EAAE,KAAK,mDAAmD,iBAAiB,GAAG,YAAY,MAAM,KAAK,OAAO,CAAC,QAAQ,MAAM,WAAW,IAAI,KAAK,GAAG,OAAO,CAAC,OAAI,CAAC;AAAA,QAC3K,OAAO,CAAC,WAAW,EAAE,IAAI,IAAI,IAAI,GAAG,CAAC,CAAC;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAeA,SAAS,uBACP,MACA,aACA,QACA,KACA,GACA,GACoC;AACpC,MAAI,OAAwD;AAC5D,WAAS,KAAK,GAAG,KAAK,KAAK,OAAO,QAAQ,MAAM;AAC9C,UAAM,QAAQ,KAAK,OAAO,EAAE;AAC5B,UAAM,QAAQ,MAAM;AACpB,QAAI,UAAU,aAAa,UAAU,SAAU;AAC/C,QAAI,OAAO,IAAI,GAAI;AACnB,UAAM,WAAW,YAAY,EAAE;AAG/B,UAAM,QAAQ,MAAM,cAAc,UAAa,QAAQ,MAAM,KAAK,GAAG,cAAc;AACnF,eAAW,KAAK,UAAU;AACxB,YAAM,MAAM,UAAU,OAAO,CAAC;AAC9B,UAAI,QAAQ,KAAM;AAClB,YAAM,aAAa,EAAE,WAAW,SAAS,iBAAiB,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,KAAK,UAAU,EAAE,KAAK,MAAM,IAAI;AACpH,YAAM,SAAS,KAAK,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,KAAK,IAAI,EAAE,WAAW;AAClE,UAAI,SAAS,IAAI,GAAI;AAErB,UAAI,CAAC,SAAS,CAAC,iBAAiB,GAAG,SAAS,GAAG,KAAK,GAAG,CAAC,EAAG;AAC3D,YAAM,IAAI,MAAM,YAAY,UAAa,MAAM,UAAU,SAAY,KAAK,IAAI,GAAG,EAAE,QAAQ,EAAE,QAAQ,IAAI,KAAK,IAAI,GAAG,EAAE,QAAQ,EAAE,QAAQ,IAAI,aAAa,MAAM,KAAK;AACrK,UAAI,KAAK,EAAG;AACZ,YAAM,QAAQ,cAAc,QAAQ,OAAO,GAAG,GAAG,GAAG,KAAK;AACzD,YAAM,MAAM,kBAAkB,KAAK;AACnC,UAAI,CAAC,QAAQ,MAAM,KAAK,KAAK;AAC3B,eAAO,EAAE,KAAK,OAAO,OAAO,MAAM,MAAM,KAAK,MAAM,GAAG,OAAO,UAAU,EAAE,KAAK,IAAI;AAAA,MACpF;AAAA,IACF;AAAA,EACF;AACA,SAAO,OAAO,EAAE,KAAK,KAAK,KAAK,OAAO,KAAK,MAAM,IAAI;AACvD;AAUA,SAAS,YACP,MACA,aACA,IACA,QACA,IACA,GACA,GACmC;AACnC,MAAI,QAAa,cAAc,IAAI;AACnC,MAAI,UAAU;AACd,WAAS,KAAK,GAAG,KAAK,IAAI,MAAM;AAC9B,QAAI,SAAS,EAAE,EAAG;AAClB,UAAM,QAAQ,KAAK,OAAO,EAAE;AAC5B,UAAM,KAAK,MAAM;AACjB,QAAI,MAAM,OAAO,SAAS,YAAY,MAAM,UAAU,UAAa,MAAM,cAAc,UAAa,QAAQ,MAAM,KAAK,GAAG,cAAc,OAAW;AACnJ,SAAK,GAAG,SAAS,YAAY,GAAG,SAAS,cAAc,GAAG,KAAM;AAChE,QAAI,GAAG,SAAS,YAAY,GAAG,SAAS,UAAU,GAAG,SAAS,UAAW;AACzE,UAAM,IAAI,MAAM,YAAY,UAAa,MAAM,UAAU,SAAY,IAAI,aAAa,MAAM,KAAK;AACjG,eAAW,KAAK,YAAY,EAAE,GAAI;AAChC,UAAI,EAAE,cAAc,KAAK,EAAE,QAAQ,KAAK,EAAG;AAC3C,YAAM,MAAM,UAAU,OAAO,CAAC;AAC9B,UAAI,QAAQ,KAAM;AAClB,YAAM,IAAI,WAAW,GAAG,GAAG,GAAG,CAAC;AAC/B,YAAM,KAAK,GAAG,IAAI,EAAE;AACpB,YAAM,KAAK,GAAG,IAAI,EAAE;AACpB,UAAIC,UAAS;AACb,UAAI,GAAG,SAAS,SAAU,CAAAA,UAAS,KAAK,MAAM,IAAI,EAAE,KAAK,EAAE,OAAO;AAAA,eACzD,GAAG,SAAS,QAAQ;AAC3B,cAAM,QAAQ,EAAE,UAAU,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK;AACzD,cAAM,UAAU,KAAK,IAAI,MAAM,KAAK,KAAK,CAAC,IAAI;AAC9C,YAAI,MAAM,QAAQ,MAAM,KAAK,KAAK,QAAQ,CAAC,QAAS;AACpD,cAAM,MAAM,UAAW,EAAE,SAAS,EAAE,OAAQ,EAAE,QAAQ;AACtD,cAAM,MAAM,UAAU,EAAE,OAAQ,EAAE,SAAS,EAAE,QAAS;AACtD,QAAAA,UAAS,KAAK,IAAI,EAAE,KAAK,MAAM,KAAK,IAAI,EAAE,KAAK;AAAA,MACjD,OAAO;AACL,YAAI,EAAE,OAAQ;AACd,QAAAA,UAAS,eAAe,IAAI,IAAI,cAAc,IAAI,EAAE,OAAO,CAAC,CAAC;AAAA,MAC/D;AACA,UAAI,CAACA,QAAQ;AACb,cAAQ,gBAAgB,OAAO,OAAO,GAAG,GAAG,KAAK,IAAI,GAAG,EAAE,QAAQ,CAAC,CAAC;AACpE,gBAAU;AAAA,IACZ;AAAA,EACF;AACA,SAAO,UAAU,EAAE,KAAK,OAAO,MAAM,SAAS,MAAM,IAAI,SAAS,MAAM,IAAI,SAAS,MAAM,EAAE,IAAI;AAClG;AAEA,SAAS,eAAe,GAAW,GAAW,KAA+C;AAC3F,MAAIA,UAAS;AACb,WAAS,IAAI,GAAG,IAAI,IAAI,SAAS,GAAG,IAAI,IAAI,QAAQ,IAAI,KAAK;AAC3D,UAAM,IAAI,IAAI,CAAC;AACf,UAAM,IAAI,IAAI,CAAC;AACf,QAAK,EAAE,IAAI,MAAQ,EAAE,IAAI,KAAM,KAAM,EAAE,IAAI,EAAE,MAAM,IAAI,EAAE,MAAO,EAAE,IAAI,EAAE,KAAK,EAAE,EAAG,CAAAA,UAAS,CAACA;AAAA,EAC9F;AACA,SAAOA;AACT;AAGA,SAAS,iBAAiB,GAAW,GAAW,KAAgB,GAAW,GAAoB;AAC7F,MAAI,EAAE,WAAW,UAAU;AACzB,UAAM,IAAI,WAAW,GAAG,GAAG,GAAG,CAAC;AAC/B,WAAO,EAAE,IAAI,IAAI,IAAI,MAAM,EAAE,IAAI,IAAI,IAAI,MAAM,EAAE,IAAI,IAAI,IAAI,MAAM,EAAE,IAAI,IAAI,IAAI;AAAA,EACnF;AACA,MAAI,EAAE,WAAW,WAAW,CAAC,EAAE,aAAa;AAC1C,UAAM,OAAO,EAAE,SAAS;AACxB,WAAO,EAAE,UAAU,OAAO,IAAI,MAAM,EAAE,UAAU,OAAO,IAAI,MAAM,EAAE,UAAU,OAAO,IAAI,MAAM,EAAE,UAAU,OAAO,IAAI;AAAA,EACvH;AACA,SAAO;AACT;AAQA,IAAM,uBAAuB;AAE7B,SAAS,eAAe,GAAc,GAAuB;AAC3D,MAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,KAAK,MAAM,GAAI,QAAO;AACnD,QAAM,KAAK,KAAK,IAAI,EAAE,IAAI,EAAE,EAAE;AAC9B,MAAI,MAAM,KAAK,KAAK,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,MAAM,KAAK,IAAI,EAAE,IAAI,EAAE,EAAE,EAAG,QAAO;AAC1E,QAAM,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,EAAE,KAAK,EAAE,MAAM;AAC/C,QAAM,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,EAAE,KAAK,EAAE,MAAM;AAC/C,SAAO,KAAK,MAAM,IAAI,EAAE,KAAK,uBAAuB;AACtD;AAiCA,SAAS,UACP,GACA,GACA,GACA,MACA,GACA,GACK;AACL,QAAM,IAAI,EAAE,OAAO,sCAAsC,KAAK,EAAE,IAAI,IAAI;AACxE,QAAM,YAAY,KAAK,UAAU,OAAO,IAAI,KAAK,IAAI,GAAG,CAAC,KAAK,KAAK,qBAAqB,OAAO;AAC/F,QAAM,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC,IAAI,YAAY,EAAE;AAC5C,QAAM,MAAM,EAAE,QAAQ,EAAE,WAAW,KAAK,EAAE,QAAQ,CAAC,KAAK;AACxD,MAAI,KAAK,YAAY,GAAG,IAAI;AAC5B,MAAI,EAAE,SAAU,MAAK,KAAK,IAAI,IAAI,EAAE,YAAY,KAAK,UAAU,OAAO,IAAI,KAAK,IAAI,GAAG,CAAC,EAAE;AACzF,QAAM,QAAQ,EAAE,SAAS;AACzB,QAAM,WAAW,EAAE,YAAY;AAC/B,QAAM,KAAK,UAAU,SAAS,EAAE,IAAI,UAAU,UAAU,EAAE,IAAI,KAAK,EAAE,IAAI,KAAK;AAC9E,QAAM,KAAK,aAAa,QAAQ,EAAE,IAAI,aAAa,WAAW,EAAE,IAAI,KAAK,EAAE,IAAI,KAAK;AACpF,SAAO,EAAE,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,GAAG;AACpD;AAOA,SAAS,eACP,GACA,GACA,GACA,GACK;AACL,QAAM,OAAO,KAAK,IAAI,GAAG,CAAC;AAC1B,QAAM,OAAO,EAAE,WAAW;AAC1B,QAAM,MAAM,EAAE,cAAc,OAAO;AACnC,QAAM,SAAS,EAAE,WAAW;AAC5B,QAAM,QAAQ,eAAe,EAAE,MAAM,SAAS,MAAM,oBAAoB,EAAE,IAAI,CAAC;AAC/E,QAAM,WAAW,MAAM,OAAO,CAAC,IAAI,MAAM,KAAK,IAAI,IAAI,EAAE,OAAO,GAAG,CAAC,IAAI;AACvE,QAAM,SAAS,MAAM,SAAS;AAC9B,QAAM,QAAQ,EAAE,SAAS;AACzB,QAAM,KAAK,UAAU,WAAW,EAAE,KAAK,SAAS,YAAY,IAAI,UAAU,UAAU,EAAE,IAAI,SAAS,WAAW,EAAE;AAEhH,QAAM,EAAE,IAAI,GAAG,IAAI,sBAAsB,GAAG,QAAQ,UAAU,MAAM;AACpE,SAAO,EAAE,IAAI,KAAK,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,KAAK,KAAK,UAAU,IAAI,EAAE,IAAI,KAAK,QAAQ,IAAI,KAAK;AAC9F;AAWA,SAAS,aAAa,MAAmC;AACvD,MAAI,CAAC,KAAK,UAAU,CAAC,KAAK,OAAO,KAAK,CAAC,MAAM,EAAE,YAAY,MAAS,EAAG,QAAO;AAC9E,QAAM,SAAS,KAAK,WAAW,eAAe,IAAI,IAAI;AACtD,QAAM,aAAa,CAAC,MAAc,MAAe,cAAiC;AAChF,QAAI,SAAS,EAAG,QAAO;AACvB,QAAI,CAAC,OAAQ,QAAO;AACpB,eAAW,CAAC,GAAG,IAAI,KAAK,QAAQ;AAC9B,UAAI,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,EAAG,QAAO;AAC1D,UAAI,UAAU,SAAS,CAAC,EAAG,QAAO;AAAA,IACpC;AACA,WAAO;AAAA,EACT;AACA,QAAM,MAAM,KAAK,OAAO,IAAI,CAAC,GAAG,MAAM;AACpC,UAAM,KAAK,UAAU,CAAC;AACtB,QAAI,WAAW,GAAG,EAAE,YAAY,EAAE,SAAS,CAAC,UAAU,EAAE,CAAC,EAAG,QAAO;AACnE,UAAM,IAAI,EAAE,UAAU,UAAa,KAAK,UAAU,OAAO,UAAU,eAAe,KAAK,KAAK,QAAQ,EAAE,KAAK,IAAI,KAAK,OAAO,EAAE,KAAK,IAAI;AACtI,WAAO,CAAC,CAAC,KAAK,WAAW,UAAU,EAAE,KAAK,YAAY,EAAE,SAAS,CAAC,UAAU,UAAU,EAAE,KAAK,EAAE,CAAC;AAAA,EAClG,CAAC;AACD,SAAO,IAAI,KAAK,OAAO,IAAI,MAAM;AACnC;AAMO,SAAS,eACd,KACA,WAAW,EAAE,OAAO,MAAM,QAAQ,KAAK,GACxB;AACf,QAAM,WAA0B,CAAC;AAEjC,WAAS,IAAI,GAAG,IAAI,IAAI,SAAS,QAAQ,KAAK;AAC5C,UAAM,MAAM,IAAI,SAAS,CAAC;AAK1B,UAAM,QAAQ,CAAC,CAAC,IAAI,MAAM,YAAY,IAAI,aAAa;AACvD,UAAM,UAAU,QAAQ,KAAK,IAAI,YAAY,IAAI,QAAS,IAAI;AAC9D,UAAM,cAAc,WAAW,IAAI,OAAO,UAAU,YAAY,SAAY,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC;AAC/F,UAAM,KAAK,YAAY,SAAY,KAAK,aAAa,UAAU,KAAM,QAAQ,CAAC,CAAC,iBAAiB,IAAI,WAAY,KAAM,QAAQ,CAAC,CAAC;AAChI,eAAW,KAAK,aAAa;AAC3B,eAAS,KAAK,EAAE,MAAM,YAAY,CAAC,WAAW,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,SAAS,EAAE,UAAU,IAAI,OAAO,EAAE,MAAM,CAAC;AAAA,IACjH;AAAA,EACF;AAQA,QAAM,YAAY,IAAI,OAAO,IAAI,SAAS,SAAS,IAAI,SAAS,SAAS;AACzE,QAAM,QAAQ,IAAI,SAAS,MAAM,GAAG,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,YAAY,SAAS,MAAM,EAAE;AAC5F,MAAI,QAAQ,GAAG;AACb,UAAM,QAAQ,IAAI,SAAS,MAAM,GAAG,SAAS,EAAE,UAAU,CAAC,MAAM,EAAE,YAAY,SAAS,MAAM;AAC7F,aAAS,KAAK;AAAA,MACZ,MAAM,YAAY,KAAK;AAAA,MACvB,MAAM;AAAA,MACN,SAAS,kBAAkB,KAAK,mBAAmB,UAAU,IAAI,KAAK,GAAG;AAAA,IAC3E,CAAC;AAAA,EACH;AAEA,WAAS,IAAI,GAAG,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK;AAChD,UAAM,KAAK,IAAI,SAAS,CAAC,EAAG;AAO5B,UAAM,QAAQ,eAAe,kBAAkB,IAAI,SAAS,CAAC,EAAG,OAAO,IAAI,SAAS,CAAC,EAAG,YAAY,CAAC,CAAC;AACtG,UAAM,QAAQ,eAAe,kBAAkB,IAAI,SAAS,IAAI,CAAC,EAAG,OAAO,CAAC,CAAC;AAC7E,UAAM,QAAQ,KAAK,IAAI,QAAQ,KAAK;AACpC,QAAI,QAAQ,OAAO,IAAI,SAAS,QAAQ;AACtC,eAAS,KAAK;AAAA,QACZ,MAAM,YAAY,CAAC;AAAA,QACnB,MAAM;AAAA,QACN,SAAS,8BAA8B,MAAM,QAAQ,CAAC,CAAC,gBAAgB,CAAC,SAAI,IAAI,CAAC,mFAA8E,CAAC;AAAA,MAClK,CAAC;AAAA,IACH;AAEA,QAAI,IAAI,SAAS,SAAS;AACxB,YAAM,OAAO,oBAAoB,IAAI,SAAS,CAAC,EAAG,KAAK;AACvD,YAAM,OAAO,oBAAoB,IAAI,SAAS,IAAI,CAAC,EAAG,KAAK;AAC3D,UAAI,SAAS,MAAM;AACjB,iBAAS,KAAK;AAAA,UACZ,MAAM,YAAY,CAAC;AAAA,UACnB,MAAM;AAAA,UACN,SAAS,YAAY,CAAC,SAAI,IAAI,CAAC;AAAA,QACjC,CAAC;AAAA,MACH,WAAW,CAAC,IAAI,SAAS,CAAC,EAAG,MAAM,YAAY,CAAC,IAAI,SAAS,IAAI,CAAC,EAAG,MAAM,YACtE,sBAAsB,IAAI,SAAS,CAAC,EAAG,OAAO,IAAI,SAAS,IAAI,CAAC,EAAG,OAAO,EAAE,eAAe,GAAG,SAAS,eAAe,GAAG,SAAS,MAAM,CAAC,GAAG;AAC/I,iBAAS,KAAK;AAAA,UACZ,MAAM,YAAY,CAAC;AAAA,UACnB,MAAM;AAAA,UACN,SAAS,YAAY,CAAC,SAAI,IAAI,CAAC;AAAA,QACjC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AIr9BA,SAAS,aAAAC,kBAAiB;AAmCnB,SAAS,cACd,MACA,UAII,CAAC,GACa;AAClB,QAAM,EAAE,OAAO,GAAG,QAAQ,EAAE,IAAI,QAAQ,YAAY,EAAE,OAAO,MAAM,QAAQ,KAAK;AAChF,QAAM,OAAO,QAAQ,QAAQ,KAAK,QAAQ;AAC1C,QAAM,QAAQ,QAAQ,SAAS,CAAC,GAAG,KAAM,IAAK;AAC9C,QAAM,EAAE,OAAO,WAAW,IAAI,aAAa,MAAM,GAAG,CAAC;AAErD,QAAM,MAAMC,WAAU,IAAI;AAC1B,QAAM,cAAc,KAAK,OAAO,IAAI,CAAC,WAAW;AAAA,IAC9C;AAAA,IACA,UAAU,cAAc,OAAO,KAAK,GAAG,GAAG,OAAO,UAAU;AAAA,EAC7D,EAAE;AAEF,QAAM,YAA6B,MAAM,IAAI,CAAC,MAAM;AAClD,UAAM,iBAAkC,YAAY,IAAI,CAAC,EAAE,OAAO,SAAS,MAAM;AAC/E,YAAM,YAAY,SAAS,IAAI,CAAC,MAAM,WAAW,GAAG,GAAG,GAAG,CAAC,CAAC;AAC5D,YAAM,KAAK,UAAU,SAAS,IAAI,UAAU,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,GAAG,CAAC,IAAI,UAAU,SAAS;AAC9F,YAAM,KAAK,UAAU,SAAS,IAAI,UAAU,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,GAAG,CAAC,IAAI,UAAU,SAAS;AAG9F,UAAI,UAAU;AACd,iBAAW,KAAK,UAAU;AACxB,cAAM,IAAI,EAAE,OAAO;AACnB,mBAAW,MAAM,OAAO,SAAS,WAC7B,KAAK,KAAK,IAAI,IACd,MAAM,OAAO,SAAS,YACpB,YAAY,cAAc,MAAM,QAAQ,CAAC,CAAC,IAC1C,EAAE,OAAO,EAAE;AAAA,MACnB;AACA,YAAM,WAAW,WAAW,IAAI;AAChC,YAAM,YAAY,SAAS,SAAS,IAChC,SAAS,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC,IAAI,SAAS,SACrD;AAGJ,UAAI,aAA4B;AAChC,UAAI,gBAA+B;AACnC,UAAI,sBAAqC;AACzC,UAAI,gBAA+B;AACnC,UAAI,MAAM,OAAO;AACf,cAAM,IAAI,SAAS;AACnB,cAAM,QAAQ,UAAU,MAAM,OAAO,WAAW,cAAc,MAAM,OAAO,KAAK,GAAG,MAAM,SAAS,OAAO,GAAG,CAAC,EAC1G,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAU;AACpC,qBAAa,MAAM;AAGnB,wBAAgB,MAAM,MAAM,SAAS,UACjC,KAAK,IAAI,GAAG,IAAI,CAAC,KAAK,MAAM,MAAM,UAAU,IAAI,IAAI,IAAI,KACxD,KAAK,IAAI,KAAK,MAAM,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AAEtD,cAAM,SAAS,MAAM,KAAK,EAAE,QAAQ,SAAS,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC;AAClE,cAAM,OAAO,CAAC,MAAsB;AAClC,iBAAO,OAAO,CAAC,MAAM,GAAG;AAAE,mBAAO,CAAC,IAAI,OAAO,OAAO,CAAC,CAAE;AAAI,gBAAI,OAAO,CAAC;AAAA,UAAI;AAC3E,iBAAO;AAAA,QACT;AACA,mBAAW,CAAC,GAAG,CAAC,KAAK,OAAO;AAC1B,gBAAM,KAAK,KAAK,CAAC;AAAG,gBAAM,KAAK,KAAK,CAAC;AACrC,cAAI,OAAO,GAAI,QAAO,EAAE,IAAI;AAAA,QAC9B;AACA,cAAM,QAAQ,IAAI,IAAI,SAAS,IAAI,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC;AACrD,8BAAsB,MAAM;AAE5B,cAAM,SAAS,IAAI,YAAY,SAAS,MAAM;AAC9C,mBAAW,CAAC,GAAG,CAAC,KAAK,OAAO;AAAE,iBAAO,CAAC;AAAM,iBAAO,CAAC;AAAA,QAAM;AAC1D,wBAAgB,OAAO,OAAO,CAAC,MAAM,MAAM,CAAC,EAAE;AAAA,MAChD;AAEA,aAAO;AAAA,QACL,KAAK,MAAM;AAAA,QACX,OAAO,SAAS;AAAA,QAChB,UAAU,EAAE,GAAG,EAAE,KAAK,GAAG,QAAQ,CAAC,GAAG,GAAG,EAAE,KAAK,GAAG,QAAQ,CAAC,EAAE;AAAA,QAC7D,UAAU,CAAC,SAAS,QAAQ,CAAC;AAAA,QAC7B,WAAW,CAAC,UAAU,QAAQ,CAAC;AAAA,QAC/B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAGD,UAAM,WAAqB,CAAC;AAC5B,eAAW,MAAM,gBAAgB;AAC/B,YAAM,QAAQ,GAAG,OAAO;AACxB,UAAI,GAAG,WAAW,GAAG,YAAY,MAAQ;AACvC,iBAAS,KAAK,GAAG,KAAK,+CAA4C,GAAG,WAAW,GAAG,WAAW,QAAQ,CAAC,CAAC,GAAG;AAAA,MAC7G;AACA,UAAI,GAAG,eAAe,QAAQ,GAAG,kBAAkB,QAAQ,GAAG,gBAAgB,GAAG;AAC/E,cAAM,QAAQ,GAAG,aAAa,GAAG;AACjC,YAAI,QAAQ,KAAK;AACf,mBAAS,KAAK,GAAG,KAAK,4BAAuB,GAAG,UAAU,IAAI,GAAG,aAAa,eAAe;AAAA,QAC/F;AAAA,MACF;AACA,UAAI,GAAG,kBAAkB,QAAQ,GAAG,QAAQ,KAAK,GAAG,gBAAgB,GAAG,QAAQ,KAAK;AAClF,iBAAS,KAAK,GAAG,KAAK,KAAK,GAAG,aAAa,IAAI,GAAG,KAAK,8CAAyC;AAAA,MAClG;AAAA,IACF;AAEA,WAAO,EAAE,GAAG,UAAU,EAAE,GAAG,EAAE,GAAG,QAAQ,gBAAgB,SAAS;AAAA,EACnE,CAAC;AAED,SAAO;AAAA,IACL,MAAM,EAAE,IAAI,KAAK,IAAI,OAAO,KAAK,OAAO,OAAO,KAAK,SAAS,YAAY,GAAI,KAAK,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC,EAAG;AAAA,IACzH;AAAA,EACF;AACF;;;AC3IO,IAAM,gBAA2B;AAAA,EACtC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,KAAK,OAAO,UAAU;AAAA,MAC5B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,IACA,MAAM,EAAE,OAAO,WAAW,QAAQ,QAAQ;AAAA,EAC5C;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,QAAQ,CAAC,aAAM,aAAM,aAAM,aAAM,WAAI,EAAE;AAAA,MAChE,MAAM,CAAC,SAAS,OAAO;AAAA,MACvB,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,SAAS,MAAM,GAAG,eAAe,MAAM,KAAK,QAAS;AAAA,MACtF,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,SAAU,OAAQ,GAAG,OAAO,UAAU;AAAA,MACzE,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,SAAS,OAAO,GAAG,MAAM,QAAS;AAAA,IACpE;AAAA,EACF;AACF;;;AC5BO,IAAM,cAAyB;AAAA,EACpC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,UAAU;AAAA,EACV,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,MAAM,OAAO,UAAU;AAAA,MAC7B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,IACA,OAAO,EAAE,QAAQ,KAAO,QAAQ,IAAI;AAAA,EACtC;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,MAAQ,KAAM,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MACjF,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,QAAQ,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE;AAAA,MACvB,OAAO,CAAC,KAAK,GAAG;AAAA;AAAA,MAEhB,OAAO,EAAE,KAAK,MAAM,QAAQ,KAAM,MAAM,EAAE,YAAY,KAAK,OAAO,GAAG,EAAE;AAAA,IACzE;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,OAAO,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,QACxC,cAAc,CAAC,GAAG,GAAG,CAAC;AAAA,MACxB;AAAA,MACA,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,MAAO,KAAK,GAAG,OAAO,GAAG,SAAS,MAAM,WAAW,IAAI;AAAA,MACzF,QAAQ,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE;AAAA,MACzB,OAAO,CAAC,MAAM,GAAG;AAAA,MACjB,OAAO;AAAA,MACP,MAAM,EAAE,KAAK,MAAM,QAAQ,IAAK;AAAA,IAClC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,OAAO,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,QACxC,cAAc,CAAC,GAAG,KAAK,GAAG;AAAA,MAC5B;AAAA,MACA,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,MAAO,IAAI,GAAG,OAAO,KAAK,SAAS,KAAK,WAAW,KAAK;AAAA,MAC1F,QAAQ,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE;AAAA,MAC1B,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,OAAO;AAAA,MACP,MAAM,EAAE,KAAK,KAAK,QAAQ,KAAM;AAAA,IAClC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,MAAO,IAAK,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MAC/E,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,MAAO,IAAI,GAAG,SAAS,KAAK;AAAA,MAC9D,QAAQ,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE;AAAA,MAC1B,OAAO,CAAC,KAAK,IAAI;AAAA,MACjB,OAAO,EAAE,KAAK,KAAK,QAAQ,KAAK;AAAA,MAChC,OAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACzEO,IAAM,cAAyB;AAAA,EACpC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,KAAK,OAAO,UAAU;AAAA,MAC5B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,IACA,OAAO,EAAE,QAAQ,MAAO,QAAQ,KAAK;AAAA,EACvC;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,QAAU,OAAQ,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MACrF,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO,EAAE,KAAK,MAAM,QAAQ,IAAK;AAAA,IACnC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,SAAU,OAAQ,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MACrF,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,SAAS,MAAM,GAAG,OAAO,IAAI;AAAA,MAC9D,OAAO,CAAC,KAAK,CAAC;AAAA,MACd,OAAO;AAAA,MACP,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,SAAU,MAAO,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MACpF,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,SAAU,OAAO,GAAG,eAAe,MAAM,KAAK,QAAQ;AAAA,MACvF,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO,EAAE,KAAK,KAAK,QAAQ,IAAK;AAAA,MAChC,OAAO;AAAA,MACP,OAAO,EAAE,QAAQ,IAAI;AAAA,IACvB;AAAA,EACF;AACF;;;AC5CO,IAAM,qBAAgC;AAAA,EAC3C,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,KAAK,OAAO,UAAU;AAAA,MAC5B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,QAAQ;AAAA;AAAA,IAEN;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,SAAW,OAAQ,GAAG,OAAO,WAAW,QAAQ,CAAC,WAAW,WAAW,WAAW,SAAS,EAAE;AAAA,MAChI,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO,EAAE,KAAK,KAAK,QAAQ,IAAK;AAAA,MAChC,QAAQ,EAAE,MAAM,SAAS;AAAA,IAC3B;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,SAAU,MAAO,GAAG,OAAO,WAAW,QAAQ,CAAC,WAAW,WAAW,WAAW,SAAS,GAAG,MAAM,KAAK;AAAA,MAC1I,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,SAAU,OAAQ,GAAG,eAAe,MAAM,KAAK,QAAS;AAAA,MACzF,OAAO,EAAE,GAAG,GAAG,SAAS,QAAQ,OAAO,MAAM,OAAO,OAAS;AAAA,IAC/D;AAAA;AAAA,IAEA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,QAAQ,CAAC,UAAK,UAAK,UAAK,QAAG,GAAG,OAAO,EAAE,QAAQ,IAAK,EAAE;AAAA,MAC/E,MAAM,CAAC,SAAS,OAAO;AAAA,MACvB,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,SAAW,OAAQ,GAAG,eAAe,KAAK;AAAA,IAC7E;AAAA,EACF;AACF;;;AC9BO,IAAM,iBAA4B;AAAA,EACvC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,MAAM,OAAO,UAAU;AAAA,MAC7B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,QAAQ;AAAA;AAAA,IAEN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,MAAQ,KAAM,GAAG,OAAO,UAAU;AAAA,MACrE,OAAO,CAAC,MAAM,GAAG;AAAA,MACjB,QAAQ,EAAE,MAAM,QAAQ,SAAS,IAAI,QAAQ,IAAI;AAAA,MACjD,OAAO,EAAE,KAAK,KAAK,QAAQ,MAAM,MAAM,EAAE,YAAY,KAAK,OAAO,GAAG,EAAE;AAAA,MACtE,QAAQ,EAAE,MAAM,SAAS;AAAA,IAC3B;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MAAe,OAAO;AAAA,MAC3B,UAAU,EAAE,GAAG,KAAK,GAAG,MAAM;AAAA,MAC7B,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAQ,KAAM,GAAG,OAAO,UAAU;AAAA,MACxF,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI;AAAA,IAChC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAe,OAAO;AAAA,MAC3B,UAAU,EAAE,GAAG,KAAK,GAAG,MAAM;AAAA,MAC7B,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAQ,KAAM,GAAG,OAAO,UAAU;AAAA,MACxF,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI;AAAA,IAChC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAiB,OAAO;AAAA,MAC7B,UAAU,EAAE,GAAG,OAAO,GAAG,IAAI;AAAA,MAC7B,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,MAAQ,IAAM,GAAG,QAAQ,CAAC,KAAK,GAAG,GAAG,OAAO,UAAU;AAAA,MACtF,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI;AAAA,IAChC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAkB,OAAO;AAAA,MAC9B,UAAU,EAAE,GAAG,OAAO,GAAG,IAAI;AAAA,MAC7B,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,MAAQ,IAAM,GAAG,QAAQ,CAAC,KAAK,GAAG,GAAG,OAAO,UAAU;AAAA,MACtF,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI;AAAA,IAChC;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MAAS,OAAO;AAAA,MACrB,UAAU,EAAE,GAAG,OAAO,GAAG,MAAM;AAAA,MAC/B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,iDAA2C;AAAA,QAAG,OAAO;AAAA,QACrF,MAAM;AAAA,QAAiC,OAAO;AAAA,MAAO;AAAA,MACvD,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI;AAAA,IAChC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAS,OAAO;AAAA,MACrB,UAAU,EAAE,GAAG,KAAK,GAAG,MAAM;AAAA,MAC7B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,cAAc;AAAA,QAAG,OAAO;AAAA,QACxD,MAAM;AAAA,QAAiC,OAAO;AAAA,MAAS;AAAA,MACzD,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI;AAAA,IAChC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAU,OAAO;AAAA,MACtB,UAAU,EAAE,GAAG,OAAO,GAAG,MAAM;AAAA,MAC/B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,mCAA2B;AAAA,QAAG,OAAO;AAAA,QACrE,MAAM;AAAA,QAAkC,OAAO;AAAA,MAAQ;AAAA,MACzD,OAAO,EAAE,KAAK,MAAM,QAAQ,KAAK;AAAA,MACjC,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI;AAAA,IAChC;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MAAS,OAAO;AAAA,MACrB,UAAU,EAAE,GAAG,OAAO,GAAG,MAAM;AAAA,MAC/B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,yCAAmC;AAAA,QAAG,OAAO;AAAA,QAC7E,MAAM;AAAA,QAA6B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACpE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI;AAAA,IAChC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAc,OAAO;AAAA,MAC1B,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,OAAQ,KAAM,GAAG,QAAQ,CAAC,KAAK,GAAG,GAAG,OAAO,UAAU;AAAA,MACtF,OAAO,CAAC,KAAK,IAAI;AAAA,MACjB,QAAQ,EAAE,MAAM,QAAQ,SAAS,GAAG;AAAA,MACpC,QAAQ,EAAE,GAAG,CAAC,OAAO,IAAI,GAAG,GAAG,CAAC,OAAO,KAAK,EAAE;AAAA,MAC9C,OAAO,EAAE,KAAK,MAAM,QAAQ,MAAM,MAAM,EAAE,YAAY,MAAM,OAAO,EAAE,EAAE;AAAA,MACvE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI;AAAA,IAChC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAS,OAAO;AAAA,MACrB,UAAU,EAAE,GAAG,OAAO,GAAG,MAAM;AAAA,MAC/B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,yCAAmC;AAAA,QAAG,OAAO;AAAA,QAC7E,MAAM;AAAA,QAA6B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACpE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI;AAAA,IAChC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAc,OAAO;AAAA,MAC1B,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,OAAQ,KAAM,GAAG,QAAQ,CAAC,KAAK,GAAG,GAAG,OAAO,UAAU;AAAA,MACtF,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,QAAQ,EAAE,MAAM,QAAQ,SAAS,GAAG;AAAA,MACpC,QAAQ,EAAE,GAAG,CAAC,OAAO,IAAI,GAAG,GAAG,CAAC,OAAO,KAAK,EAAE;AAAA,MAC9C,OAAO,EAAE,KAAK,KAAK,QAAQ,MAAM,MAAM,EAAE,YAAY,MAAM,OAAO,EAAE,EAAE;AAAA,MACtE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI;AAAA,IAChC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAS,OAAO;AAAA,MACrB,UAAU,EAAE,GAAG,OAAO,GAAG,MAAM;AAAA,MAC/B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,sDAA2C;AAAA,QAAG,OAAO;AAAA,QACrF,MAAM;AAAA,QAA6B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACpE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAc,OAAO;AAAA,MAC1B,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,OAAQ,KAAM,GAAG,QAAQ,CAAC,KAAK,GAAG,GAAG,OAAO,UAAU;AAAA,MACtF,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,QAAQ,EAAE,MAAM,QAAQ,SAAS,GAAG;AAAA,MACpC,QAAQ,EAAE,GAAG,CAAC,OAAO,IAAI,GAAG,GAAG,CAAC,OAAO,KAAK,EAAE;AAAA,MAC9C,OAAO,EAAE,KAAK,KAAK,QAAQ,MAAM,MAAM,EAAE,YAAY,MAAM,OAAO,EAAE,EAAE;AAAA,MACtE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAa,OAAO;AAAA,MACzB,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,MAAO,IAAK,GAAG,OAAO,UAAU;AAAA,MACnE,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,QAAQ,EAAE,MAAM,QAAQ,SAAS,EAAE;AAAA,MACnC,QAAQ,EAAE,GAAG,CAAC,OAAO,KAAK,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE;AAAA,MAC7C,OAAO,EAAE,KAAK,MAAM,QAAQ,KAAK;AAAA,MACjC,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,KAAM,MAAM,IAAI;AAAA,IACjC;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MAAgB,OAAO;AAAA,MAC5B,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,OAAQ,KAAM,GAAG,QAAQ,CAAC,KAAK,GAAG,GAAG,OAAO,UAAU;AAAA,MACtF,OAAO,CAAC,MAAM,GAAG;AAAA,MACjB,QAAQ,EAAE,MAAM,QAAQ,SAAS,GAAG;AAAA,MACpC,QAAQ,EAAE,GAAG,CAAC,OAAO,KAAK,GAAG,GAAG,CAAC,MAAM,GAAG,EAAE;AAAA,MAC5C,OAAO,EAAE,KAAK,KAAK,QAAQ,MAAM,MAAM,EAAE,YAAY,MAAM,OAAO,EAAE,EAAE;AAAA,MACtE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAW,OAAO;AAAA,MACvB,UAAU,EAAE,GAAG,OAAO,GAAG,MAAM;AAAA,MAC/B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,wDAAkD;AAAA,QAAG,OAAO;AAAA,QAC5F,MAAM;AAAA,QAA6B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACpE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAY,OAAO;AAAA,MACxB,UAAU,EAAE,GAAG,OAAO,GAAG,IAAI;AAAA,MAC7B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,sEAA0D;AAAA,QAAG,OAAO;AAAA,QACpG,MAAM;AAAA,QAA6B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACpE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MAAQ,OAAO;AAAA,MACpB,UAAU,EAAE,GAAG,OAAO,GAAG,IAAI;AAAA,MAC7B,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,OAAO,KAAK,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MAC/E,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAgB,OAAO;AAAA;AAAA;AAAA,MAG5B,QAAQ,EAAE,GAAG,CAAC,OAAO,KAAK,GAAG,GAAG,CAAC,KAAK,GAAG,EAAE;AAAA,MAC3C,QAAQ,EAAE,MAAM,QAAQ,QAAQ,CAAC,OAAO,KAAK,GAAG,OAAO,WAAW,OAAO,MAAO;AAAA,MAChF,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAU,QAAQ,CAAC,OAAQ,KAAM;AAAA,QAAG,OAAO;AAAA,QACzD,QAAQ,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,MAAE;AAAA,MAClE,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,OAAO,KAAK,GAAG,QAAQ,EAAE,GAAG,OAAO,GAAG,IAAI,EAAE;AAAA,MAC9F,OAAO,EAAE,QAAQ,GAAG,MAAM,KAAK;AAAA;AAAA,MAE/B,OAAO,EAAE,GAAG,GAAG,SAAS,KAAK,OAAO,WAAW,OAAO,KAAK,OAAO,OAAQ,MAAM,QAAQ;AAAA,MACxF,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAgB,OAAO;AAAA,MAC5B,UAAU,EAAE,GAAG,OAAO,GAAG,KAAK;AAAA,MAC9B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,mEAAgE;AAAA,QAAG,OAAO;AAAA,QAC1G,MAAM;AAAA,QAA4B,OAAO;AAAA,QAAU,UAAU;AAAA,MAAM;AAAA,MACrE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MAAc,OAAO;AAAA,MAC1B,UAAU,EAAE,GAAG,KAAK,GAAG,KAAK;AAAA,MAC5B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,eAAe;AAAA,QAAG,OAAO;AAAA,QACzD,MAAM;AAAA,QAA4B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACnE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAU,OAAO;AAAA,MACtB,UAAU,EAAE,GAAG,KAAK,GAAG,KAAK;AAAA,MAC5B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,yDAAiD;AAAA,QAAG,OAAO;AAAA,QAC3F,MAAM;AAAA,QAA6B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACpE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAU,OAAO;AAAA,MACtB,UAAU,EAAE,GAAG,KAAK,GAAG,MAAM;AAAA,MAC7B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,2CAAwC;AAAA,QAAG,OAAO;AAAA,QAClF,MAAM;AAAA,QAA6B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACpE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAU,OAAO;AAAA,MACtB,UAAU,EAAE,GAAG,KAAK,GAAG,MAAM;AAAA,MAC7B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,yCAAsC;AAAA,QAAG,OAAO;AAAA,QAChF,MAAM;AAAA,QAA6B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACpE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MAAgB,OAAO;AAAA,MAC5B,UAAU,EAAE,GAAG,OAAO,GAAG,MAAM;AAAA,MAC/B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,gCAA6B;AAAA,QAAG,OAAO;AAAA,QACvE,MAAM;AAAA,QAA4B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACnE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAgB,OAAO;AAAA,MAC5B,UAAU,EAAE,GAAG,OAAO,GAAG,KAAK;AAAA,MAC9B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,YAAY;AAAA,QAAG,OAAO;AAAA,QACtD,MAAM;AAAA,QAAkC,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACzE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAiB,OAAO;AAAA,MAC7B,UAAU,EAAE,GAAG,OAAO,GAAG,MAAM;AAAA,MAC/B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,kDAAkD;AAAA,QAAG,OAAO;AAAA,QAC5F,MAAM;AAAA,QAA6B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACpE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MAAU,OAAO;AAAA,MACtB,UAAU,EAAE,GAAG,OAAO,GAAG,IAAI;AAAA,MAC7B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,kCAAkC;AAAA,QAAG,OAAO;AAAA,QAC5E,MAAM;AAAA,QAA6B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACpE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAU,OAAO;AAAA,MACtB,UAAU,EAAE,GAAG,OAAO,GAAG,MAAM;AAAA,MAC/B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,oCAAoC;AAAA,QAAG,OAAO;AAAA,QAC9E,MAAM;AAAA,QAA6B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACpE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAU,OAAO;AAAA,MACtB,UAAU,EAAE,GAAG,OAAO,GAAG,MAAM;AAAA,MAC/B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,kCAAkC;AAAA,QAAG,OAAO;AAAA,QAC5E,MAAM;AAAA,QAA6B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACpE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MAAS,OAAO;AAAA,MACrB,UAAU,EAAE,GAAG,OAAO,GAAG,KAAK;AAAA,MAC9B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,8CAAoC;AAAA,QAAG,OAAO;AAAA,QAC9E,MAAM;AAAA,QAAkC,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACzE,OAAO,EAAE,KAAK,MAAM,QAAQ,KAAK;AAAA,MACjC,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAa,OAAO;AAAA,MACzB,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,OAAO,CAAC,OAAQ,KAAM;AAAA,QAAG,QAAQ,CAAC,KAAK,GAAG;AAAA,QAChE,OAAO;AAAA,QAAW,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,QAAG,cAAc,CAAC,GAAG,GAAG,CAAC;AAAA,MAAE;AAAA,MACvF,OAAO,CAAC,KAAK,IAAI;AAAA,MACjB,QAAQ,EAAE,MAAM,QAAQ,SAAS,GAAG;AAAA,MACpC,QAAQ,EAAE,GAAG,CAAC,OAAO,KAAK,GAAG,GAAG,CAAC,MAAM,KAAK,EAAE;AAAA,MAC9C,OAAO,EAAE,KAAK,MAAM,QAAQ,MAAM,MAAM,EAAE,YAAY,MAAM,OAAO,EAAE,EAAE;AAAA,MACvE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MAAa,OAAO;AAAA,MACzB,UAAU,EAAE,GAAG,OAAO,GAAG,KAAK;AAAA,MAC9B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,8CAAwC;AAAA,QAAG,OAAO;AAAA,QAClF,MAAM;AAAA,QAA6B,OAAO;AAAA,QAAQ,UAAU;AAAA,MAAM;AAAA,MACpE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MAAU,OAAO;AAAA,MACtB,UAAU,EAAE,GAAG,OAAO,GAAG,KAAK;AAAA,MAC9B,QAAQ;AAAA,QAAE,MAAM;AAAA,QAAQ,SAAS,CAAC,iGAAqF;AAAA,QAAG,OAAO;AAAA,QAC/H,MAAM;AAAA,QAA4B,OAAO;AAAA,MAAO;AAAA,MAClD,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACjC;AAAA,EACF;AACF;;;ACrVO,IAAM,oBAA+B;AAAA,EACvC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,YAAY,EAAE,MAAM,SAAS,OAAO,UAAU;AAAA,EAC9C,QAAQ;AAAA,IACH;AAAA,MACK,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACH,MAAM;AAAA,QACN,QAAQ,CAAC,MAAQ,IAAM;AAAA,QACvB,OAAO;AAAA,MACZ;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,OAAO,CAAC,MAAM,GAAG;AAAA,MACjB,OAAO,EAAE,KAAK,MAAM,QAAQ,IAAK;AAAA,IACtC;AAAA,IACA;AAAA,MACK,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACH,MAAM;AAAA,QACN,QAAQ,CAAC,OAAQ,KAAM;AAAA,QACvB,OAAO;AAAA,MACZ;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,MAAQ,IAAM,EAAE;AAAA,MACjD,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,QAAQ,EAAE,GAAG,CAAC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE;AAAA,MAC3C,OAAO;AAAA,QACF,GAAG;AAAA,QACH,SAAS;AAAA,QACT,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,MACb;AAAA,IACL;AAAA,IACA;AAAA,MACK,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACH,MAAM;AAAA,QACN,QAAQ,CAAC,OAAQ,KAAM;AAAA,QACvB,OAAO;AAAA,QACP,MAAM;AAAA,MACX;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,EAAE;AAAA,MAC5D,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,OAAO;AAAA,MACP,MAAM,EAAE,OAAO,MAAO,MAAM,KAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,GAAG,EAAE;AAAA,IACnE;AAAA,EACL;AACL;;;AC5DO,IAAM,oBAA+B;AAAA,EAC1C,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY,EAAE,MAAM,SAAS,OAAO,UAAU;AAAA,EAC9C,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA,QAC3C,KAAK;AAAA;AAAA;AAAA;AAAA,QAIL,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,OAAO;AAAA,QACP,WAAW;AAAA,MACb;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,QAAQ,EAAE,MAAM,SAAS,SAAS,GAAG,KAAK,KAAK;AAAA,MAC/C,QAAQ,EAAE,GAAG,CAAC,KAAK,GAAG,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE;AAAA,MACzC,OAAO,CAAC,KAAK,IAAI;AAAA,IACnB;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,OAAO;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,MAAM,CAAC,OAAO,KAAK;AAAA,MACnB,QAAQ,EAAE,MAAM,SAAS,SAAS,GAAG,KAAK,KAAK;AAAA,MAC/C,QAAQ,EAAE,GAAG,CAAC,KAAK,GAAG,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE;AAAA,MACzC,OAAO,CAAC,MAAM,IAAI;AAAA,IACpB;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,KAAK,GAAG,KAAK;AAAA,MAC5B,OAAO,CAAC,KAAK,GAAG;AAAA,IAClB;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,KAAK,GAAG;AAAA,QACjB,QAAQ;AAAA,UACN,CAAC,IAAI,CAAC;AAAA,UACN,CAAC,GAAG,CAAC;AAAA,QACP;AAAA,QACA,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,OAAO,KAAK,GAAG,OAAO,GAAG;AAAA,MAC1D,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,OAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC1FO,IAAM,kBAA6B;AAAA,EACxC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,KAAK,OAAO,UAAU;AAAA,MAC5B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,OAAQ,IAAK;AAAA,QACtB,OAAO;AAAA,QACP,QAAQ,CAAC,WAAW,SAAS;AAAA,QAC7B,cAAc,CAAC,GAAG,CAAC;AAAA,MACrB;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,QAAQ,EAAE,MAAM,QAAQ,SAAS,IAAI,QAAQ,EAAE;AAAA,MAC/C,OAAO,CAAC,KAAK,IAAI;AAAA,MACjB,OAAO,EAAE,KAAK,MAAM,QAAQ,KAAM,MAAM,EAAE,YAAY,KAAK,OAAO,GAAG,EAAE;AAAA,MACvE,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE;AAAA,IAC7B;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,MAAM,IAAI;AAAA,QACnB,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,OAAO;AAAA,MACP,MAAM,EAAE,KAAK,KAAK,QAAQ,IAAK;AAAA,MAC/B,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE;AAAA,IAC7B;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,MAAM,IAAI;AAAA,QACnB,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,MAC3B,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,OAAO;AAAA,MACP,MAAM,EAAE,KAAK,MAAM,QAAQ,IAAK;AAAA,MAChC,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE;AAAA,IAC7B;AAAA,EACF;AACF;;;AC/DO,IAAM,gBAA2B;AAAA,EACtC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY,EAAE,MAAM,SAAS,OAAO,UAAU;AAAA,EAC9C,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,OAAQ,KAAM;AAAA,QACvB,OAAO;AAAA,QACP,QAAQ,CAAC,WAAW,SAAS;AAAA,QAC7B,cAAc,CAAC,GAAG,CAAC;AAAA,MACrB;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,MAAO,IAAK;AAAA,QACpB,OAAO;AAAA,QACP,eAAe;AAAA,MACjB;AAAA,MACA,OAAO,CAAC,MAAM,GAAG;AAAA,MACjB,OAAO;AAAA,QACL,GAAG;AAAA,QACH,SAAS;AAAA,QACT,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,MAAM,KAAK;AAAA,QACpB,QAAQ;AAAA,UACN,CAAC,IAAI,GAAG;AAAA,UACR,CAAC,MAAM,IAAI;AAAA,UACX,CAAC,KAAK,IAAI;AAAA,UACV,CAAC,GAAG,GAAG;AAAA,QACT;AAAA,QACA,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,QAAQ,CAAC,WAAW,SAAS;AAAA,MAC/B;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,MAAM,IAAI;AAAA,QAClB,OAAO;AAAA,QACP,eAAe;AAAA,MACjB;AAAA,MACA,OAAO,CAAC,KAAK,GAAG;AAAA,IAClB;AAAA,EACF;AACF;;;AC3DO,IAAM,kBAA6B;AAAA,EACxC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,MAAM,OAAO,UAAU;AAAA,MAC7B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,UACN,CAAC,IAAI,IAAI;AAAA,UACT,CAAC,OAAO,EAAE;AAAA,UACV,CAAC,MAAM,IAAI;AAAA,UACX,CAAC,KAAK,GAAG;AAAA,QACX;AAAA,QACA,QAAQ,CAAC,OAAO,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,QAAQ,CAAC,WAAW,WAAW,WAAW,SAAS;AAAA,QACnD,cAAc,CAAC,GAAG,GAAG,GAAG,CAAC;AAAA,MAC3B;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,OAAO,KAAK,GAAG,OAAO,GAAG;AAAA,MAC1D,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,QAAQ,CAAC,MAAM,GAAG;AAAA,MAClB,MAAM,CAAC,KAAK,EAAE;AAAA,IAChB;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,MAAM,IAAI;AAAA,QACnB,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,MAAO,IAAK;AAAA,QACpB,SAAS;AAAA,QACT,WAAW;AAAA,MACb;AAAA,MACA,OAAO,CAAC,KAAK,IAAI;AAAA,MACjB,OAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACxDO,IAAM,cAAyB;AAAA,EACpC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,KAAK,OAAO,UAAU;AAAA,MAC5B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,MAAO,KAAK;AAAA,QACrB,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ,CAAC,WAAW,SAAS;AAAA,QAC7B,cAAc,CAAC,GAAG,CAAC;AAAA,MACrB;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,OAAO,IAAI;AAAA,QACnB,SAAS;AAAA,QACT,WAAW;AAAA,MACb;AAAA,MACA,OAAO,CAAC,MAAM,GAAG;AAAA,MACjB,OAAO;AAAA,IACT;AAAA,IACA;AAAA;AAAA;AAAA,MAGE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,MAAO,KAAK;AAAA,QACrB,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ,CAAC,WAAW,SAAS;AAAA,QAC7B,cAAc,CAAC,GAAG,CAAC;AAAA,MACrB;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,MAAM,IAAI;AAAA,QAClB,SAAS;AAAA,QACT,WAAW;AAAA,MACb;AAAA,MACA,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO;AAAA,IACT;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,MAAQ,KAAM,GAAG,OAAO,UAAU;AAAA,MACrE,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,OAAO,CAAC,MAAM,GAAG;AAAA,IACnB;AAAA,EACF;AACF;;;ACpCO,IAAM,2BAAyC;AAAA,EACpD,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ,EAAE,OAAO,KAAK,QAAQ,KAAK;AAAA,EACnC,KAAK;AAAA,IACH,eAAe;AAAA,IACf,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,YAAY;AAAA,MACV,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO,CAAC,WAAW,WAAW,SAAS;AAAA,MACvC,OAAO,EAAE,QAAQ,KAAO,QAAQ,KAAK;AAAA,IACvC;AAAA,IACA,QAAQ;AAAA,MACN;AAAA,QACE,KAAK;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,QAAQ,CAAC,OAAQ,IAAK;AAAA,UACtB,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA,QACA,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,MAAO,IAAK,GAAG,OAAO,GAAG;AAAA,QAC1D,OAAO,CAAC,KAAK,IAAI;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAAA,EACA,UAAU;AAAA,IACR;AAAA,MACE,KAAK;AAAA,MACL,UAAU;AAAA,MACV,YAAY,EAAE,MAAM,SAAS,KAAK,MAAM,MAAM,YAAY;AAAA,MAC1D,OAAO;AAAA,QACL,eAAe;AAAA,QACf,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,UACN;AAAA,YACE,KAAK;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,MAAM;AAAA,cACN,UAAU;AAAA,cACV,UAAU;AAAA,cACV,YAAY;AAAA,cACZ,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,MAAM;AAAA,cACN,OAAO;AAAA,cACP,SAAS;AAAA,cACT,QAAQ;AAAA,gBACN,UAAU;AAAA,gBACV,MAAM;AAAA,gBACN,OAAO;AAAA,gBACP,OAAO,EAAE,OAAO,IAAI;AAAA,cACtB;AAAA,YACF;AAAA,YACA,QAAQ,EAAE,MAAM,SAAS;AAAA,YACzB,UAAU,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,YAC3B,OAAO,CAAC,KAAK,GAAG;AAAA,UAClB;AAAA,UACA;AAAA,YACE,KAAK;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,QAAQ,CAAC,OAAQ,KAAM;AAAA,cACvB,OAAO;AAAA,YACT;AAAA,YACA,QAAQ,EAAE,MAAM,SAAS;AAAA,YACzB,OAAO,CAAC,MAAM,IAAI;AAAA,YAClB,OAAO,EAAE,KAAK,MAAM,QAAQ,IAAK;AAAA,UACnC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,UAAU;AAAA,MACV,YAAY,EAAE,MAAM,QAAQ,KAAK,IAAK;AAAA,MACtC,OAAO;AAAA,QACL,eAAe;AAAA,QACf,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,UACN;AAAA,YACE,KAAK;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,MAAM;AAAA,cACN,UAAU;AAAA,cACV,UAAU;AAAA,cACV,YAAY;AAAA,cACZ,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,MAAM;AAAA,cACN,OAAO;AAAA,cACP,SAAS;AAAA,cACT,QAAQ;AAAA,gBACN,UAAU;AAAA,gBACV,MAAM;AAAA,gBACN,OAAO;AAAA,gBACP,OAAO,EAAE,OAAO,IAAI;AAAA,cACtB;AAAA,YACF;AAAA,YACA,QAAQ,EAAE,MAAM,SAAS;AAAA,YACzB,UAAU,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,YAC3B,OAAO,CAAC,KAAK,GAAG;AAAA,UAClB;AAAA,UACA;AAAA,YACE,KAAK;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,QAAQ,CAAC,OAAQ,KAAM;AAAA,cACvB,OAAO;AAAA,YACT;AAAA,YACA,QAAQ,EAAE,MAAM,SAAS;AAAA,YACzB,OAAO,CAAC,MAAM,IAAI;AAAA,YAClB,OAAO,EAAE,KAAK,MAAM,QAAQ,IAAK;AAAA,UACnC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,QACL,eAAe;AAAA,QACf,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,UACN;AAAA,YACE,KAAK;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,QAAQ,CAAC,MAAM,IAAI;AAAA,cACnB,OAAO;AAAA,cACP,QAAQ,CAAC,WAAW,SAAS;AAAA,cAC7B,MAAM;AAAA,YACR;AAAA,YACA,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,OAAO,CAAC,MAAO,IAAK;AAAA,cACpB,SAAS;AAAA,cACT,WAAW;AAAA,YACb;AAAA,YACA,OAAO,CAAC,MAAM,GAAG;AAAA,YACjB,OAAO;AAAA,YACP,MAAM,EAAE,KAAK,KAAK,QAAQ,KAAM;AAAA,UAClC;AAAA,UACA;AAAA,YACE,KAAK;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,QAAQ,CAAC,KAAK,GAAG;AAAA,cACjB,QAAQ;AAAA,gBACN,CAAC,IAAI,GAAG;AAAA,gBACR,CAAC,MAAM,IAAI;AAAA,gBACX,CAAC,KAAK,IAAI;AAAA,gBACV,CAAC,GAAG,GAAG;AAAA,cACT;AAAA,cACA,OAAO;AAAA,cACP,OAAO;AAAA,cACP,OAAO;AAAA,cACP,QAAQ,CAAC,WAAW,SAAS;AAAA,YAC/B;AAAA,YACA,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,OAAO,CAAC,MAAO,IAAK;AAAA,cACpB,OAAO;AAAA,cACP,eAAe;AAAA,YACjB;AAAA,YACA,OAAO,CAAC,KAAK,GAAG;AAAA,YAChB,QAAQ,CAAC,KAAK,EAAE;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACvOO,IAAM,cAAyB;AAAA,EACpC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,MAAM,IAAI;AAAA,QAClB,QAAQ,CAAC,KAAK,GAAG;AAAA,QACjB,OAAO;AAAA,QACP,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,QACxC,SAAS;AAAA,MACX;AAAA,MACA,OAAO,CAAC,MAAM,GAAG;AAAA,MACjB,QAAQ,EAAE,GAAG,CAAC,KAAK,GAAG,GAAG,GAAG,CAAC,KAAK,GAAG,EAAE;AAAA,MACvC,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,MAAO,IAAK,GAAG,SAAS,KAAK;AAAA,MAC/D,MAAM,CAAC,IAAI,CAAC;AAAA,IACd;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,MAAM,IAAI;AAAA,QACnB,QAAQ,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;AAAA,QACvC,OAAO;AAAA,QACP,QAAQ,CAAC,WAAW,WAAW,WAAW,SAAS;AAAA,MACrD;AAAA,MACA,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,MAAO,IAAK,GAAG,SAAS,KAAK;AAAA,MAC/D,MAAM,CAAC,IAAI,CAAC;AAAA,IACd;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,MAAM,IAAI;AAAA,QACnB,QAAQ,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC;AAAA,QACvD,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,MACA,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,MAAO,IAAI,GAAG,OAAO,IAAI,eAAe,KAAK;AAAA,MAC9E,MAAM,CAAC,IAAI,CAAC;AAAA,IACd;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,WAAW,QAAQ,CAAC,MAAO,KAAK,GAAG,OAAO,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MAC1F,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,MAAO,IAAK,EAAE;AAAA,IAClD;AAAA,EACF;AACF;;;AC3EO,IAAM,aAAwB;AAAA,EACnC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,YAAY,EAAE,MAAM,SAAS,OAAO,UAAU;AAAA,EAC9C,QAAQ;AAAA,IACN;AAAA,MACE,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,KAAK,GAAG,KAAK;AAAA,IAC9B;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,MAAQ,KAAM,GAAG,OAAO,UAAU;AAAA,MACrE,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,MAAO,IAAK,GAAG,OAAO,IAAI;AAAA,IAC7D;AAAA,EACF;AACF;;;ACnBO,IAAM,gBAA2B;AAAA,EACtC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,MAAM,OAAO,UAAU;AAAA,MAC7B,EAAE,IAAI,MAAM,OAAO,UAAU;AAAA,MAC7B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,QAAU,OAAQ,GAAG,OAAO,UAAU;AAAA,MACzE,OAAO,CAAC,MAAM,CAAC;AAAA,MACf,QAAQ,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE;AAAA,MACvB,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,QAAU,OAAQ,GAAG,KAAK,QAAU;AAAA,IACvE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,SAAU,OAAQ;AAAA,QAC3B,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO;AAAA,MACP,OAAO,EAAE,KAAK,MAAM,QAAQ,KAAK;AAAA,MACjC,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,SAAU,OAAO,GAAG,MAAM,QAAS;AAAA,IACrE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,SAAU,OAAQ;AAAA,QAC3B,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,OAAO,CAAC,KAAK,CAAC;AAAA,MACd,OAAO;AAAA,MACP,OAAO,EAAE,KAAK,MAAM,QAAQ,KAAK;AAAA,MACjC,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,SAAS,OAAO,GAAG,MAAM,QAAS;AAAA,IACpE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,QAAQ,CAAC,WAAI,EAAE;AAAA,MACxC,MAAM,CAAC,SAAS,OAAO;AAAA,MACvB,OAAO,CAAC,MAAM,CAAC;AAAA,MACf,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,SAAS,OAAO,GAAG,MAAM,QAAS;AAAA,IACpE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,QAAQ,CAAC,WAAI,EAAE;AAAA,MACxC,MAAM,CAAC,QAAQ,OAAO;AAAA,MACtB,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,SAAS,OAAO,GAAG,MAAM,QAAQ;AAAA,IACnE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,SAAU,MAAO,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MACpF,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,OAAO;AAAA,MACP,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE;AAAA,MACvB,OAAO,EAAE,KAAK,KAAK,QAAQ,KAAK;AAAA,MAChC,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,SAAU,OAAQ,GAAG,KAAK,QAAS;AAAA,IACtE;AAAA,EACF;AACF;;;AClEO,IAAM,kBAA6B;AAAA,EACxC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,IACA,OAAO,EAAE,QAAQ,KAAO,QAAQ,IAAI;AAAA,EACtC;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,MAAM,GAAG,GAAG,MAAM,MAAM,OAAO,WAAW,QAAQ,CAAC,WAAW,WAAW,SAAS,EAAE;AAAA,MACvH,OAAO,CAAC,MAAM,GAAG;AAAA,MACjB,OAAO;AAAA,MACP,QAAQ,EAAE,GAAG,CAAC,KAAK,GAAG,GAAG,GAAG,CAAC,KAAK,GAAG,EAAE;AAAA,MACvC,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,MAAO,IAAK,GAAG,SAAS,KAAK;AAAA,MAC/D,OAAO,EAAE,KAAK,MAAM,QAAQ,IAAK;AAAA,IACnC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,MAAQ,KAAM,GAAG,MAAM,MAAM,OAAO,UAAU;AAAA,MACjF,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,MAAO,IAAK,EAAE;AAAA,IAClD;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,aAAa,MAAM,sCAAsC,UAAU,GAAK,UAAU,OAAO,OAAO,WAAW,MAAM,OAAO;AAAA,MACxI,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,IAC/B;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,QAAQ,SAAS,CAAC,cAAc,UAAU,WAAW,WAAW,QAAQ,GAAG,MAAM,aAAa,OAAO,QAAQ,UAAU,UAAU,OAAO,WAAW,MAAM,OAAO;AAAA,MAChL,MAAM,CAAC,MAAM,IAAI;AAAA,MACjB,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,MAC7B,QAAQ,EAAE,MAAM,QAAQ,KAAK,MAAM;AAAA,IACrC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA,QAC3B,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,OAAO;AAAA,QACP,QAAQ,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,MAChE;AAAA,MACA,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,MAC7B,QAAQ,EAAE,MAAM,QAAQ,KAAK,MAAM;AAAA,IACrC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,QAAQ,SAAS,CAAC,OAAO,OAAO,OAAO,OAAO,KAAK,GAAG,MAAM,kBAAkB,OAAO,QAAQ,UAAU,UAAU,OAAO,WAAW,MAAM,OAAO;AAAA,MAChK,MAAM,CAAC,MAAM,IAAI;AAAA,MACjB,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,MAC7B,QAAQ,EAAE,MAAM,QAAQ,KAAK,MAAM;AAAA,IACrC;AAAA,EACF;AACF;;;ACtFO,IAAM,mBAA8B;AAAA,EACzC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,UAAU;AAAA,EACV,YAAY,EAAE,MAAM,SAAS,OAAO,UAAU;AAAA,EAC9C,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,SAAS,CAAC,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AAAA,QACxF,OAAO;AAAA,QACP,MAAM;AAAA,QACN,OAAO,EAAE,QAAQ,IAAI;AAAA,MACvB;AAAA,MACA,MAAM,CAAC,OAAO,IAAI;AAAA,MAClB,QAAQ,EAAE,MAAM,QAAQ,SAAS,IAAI,QAAQ,EAAE,GAAG,EAAE,EAAE;AAAA,MACtD,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,MAAM,IAAI,GAAG,OAAO,GAAG;AAAA,MACxD,OAAO,CAAC,MAAM,GAAG;AAAA,IACnB;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,SAAS,CAAC,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AAAA,QACzE,OAAO;AAAA,QACP,MAAM;AAAA,QACN,OAAO,EAAE,QAAQ,IAAI;AAAA,MACvB;AAAA,MACA,MAAM,CAAC,OAAO,IAAI;AAAA,MAClB,QAAQ,EAAE,MAAM,QAAQ,SAAS,IAAI,QAAQ,EAAE,GAAG,EAAE,EAAE;AAAA,MACtD,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,MAAM,GAAG,GAAG,OAAO,GAAG;AAAA,MACvD,OAAO,CAAC,KAAK,GAAG;AAAA,IAClB;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,SAAS,CAAC,UAAK,UAAK,UAAK,UAAK,UAAK,KAAK,GAAG;AAAA,QAC3C,OAAO;AAAA,QACP,MAAM;AAAA,QACN,OAAO,EAAE,QAAQ,IAAI;AAAA,MACvB;AAAA,MACA,MAAM,CAAC,OAAO,KAAK;AAAA,MACnB,QAAQ,EAAE,MAAM,QAAQ,SAAS,IAAI,QAAQ,EAAE,GAAG,EAAE,EAAE;AAAA,MACtD,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,KAAK,IAAI,GAAG,OAAO,GAAG;AAAA,MACvD,OAAO,CAAC,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF;;;AClDO,IAAM,yBAAoC;AAAA,EAC/C,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,MAAM,OAAO,UAAU;AAAA,MAC7B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,UAAU,EAAE,GAAG,KAAK,GAAG,KAAK;AAAA,MAC5B,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,MAAM,IAAI;AAAA,QACnB,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA;AAAA;AAAA,MAGA,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,OAAO;AAAA,MACP,OAAO,EAAE,KAAK,MAAM,QAAQ,IAAM;AAAA,MAClC,MAAM,EAAE,KAAK,MAAM,QAAQ,IAAM;AAAA,MACjC,QAAQ,EAAE,MAAM,SAAS;AAAA,IAC3B;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,MAAM,KAAK;AAAA,QACpB,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,OAAO;AAAA,MACP,QAAQ,EAAE,GAAG,CAAC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE;AAAA,MAC3C,OAAO,EAAE,KAAK,OAAO,QAAQ,KAAK;AAAA,MAClC,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,MAAO,IAAK,GAAG,MAAM,KAAM;AAAA,IAC7D;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,OAAO,KAAK;AAAA,QACrB,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,OAAO;AAAA,MACP,OAAO,EAAE,KAAK,MAAM,QAAQ,KAAK;AAAA,MACjC,MAAM,EAAE,KAAK,KAAK,QAAQ,KAAK;AAAA;AAAA,MAE/B,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,IAAI,EAAE;AAAA,QACd,QAAQ,CAAC,MAAO,IAAK;AAAA,QACrB,QAAQ,EAAE,GAAG,KAAK,GAAG,KAAK;AAAA,MAC5B;AAAA,IACF;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,OAAO,KAAK;AAAA,QACrB,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,OAAO;AAAA,MACP,OAAO,EAAE,KAAK,MAAM,QAAQ,IAAI;AAAA,MAChC,MAAM,EAAE,KAAK,MAAM,QAAQ,KAAK;AAAA,MAChC,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,IAAI,EAAE;AAAA,QACd,QAAQ,CAAC,OAAQ,KAAM;AAAA,QACvB,QAAQ,EAAE,GAAG,KAAK,GAAG,KAAK;AAAA,MAC5B;AAAA,IACF;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,OAAQ,IAAK;AAAA,QACtB,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ,EAAE,GAAG,CAAC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,GAAG,EAAE;AAAA,MACzC,OAAO,EAAE,KAAK,KAAK,QAAQ,KAAK;AAAA,MAChC,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE;AAAA,MAC/B,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,MAAO,KAAK;AAAA,QACpB,OAAO;AAAA,QACP,KAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACF;;;ACnHO,IAAM,gBAA2B;AAAA,EACtC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,UAAU;AAAA,EACV,YAAY,EAAE,MAAM,SAAS,OAAO,UAAU;AAAA,EAC9C,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,OAAQ,KAAM,GAAG,OAAO,UAAU;AAAA,MACrE,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,MAAM,IAAI,EAAE;AAAA,MAC9C,MAAM;AAAA,MACN,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO,EAAE,GAAG,GAAG,SAAS,GAAG,MAAM,SAAS,QAAQ,MAAM,OAAO,WAAW,OAAO,MAAM,OAAO,MAAO;AAAA,IACvG;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,OAAQ,KAAM,GAAG,OAAO,UAAU;AAAA,MACrE,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,KAAK,GAAG,EAAE;AAAA,MAC5C,MAAM;AAAA,MACN,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO,EAAE,GAAG,GAAG,SAAS,GAAG,MAAM,SAAS,QAAQ,MAAM,OAAO,WAAW,OAAO,MAAM,OAAO,MAAO;AAAA,IACvG;AAAA,EACF;AACF;;;AC5BO,IAAM,cAAyB;AAAA,EACpC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,KAAK,OAAO,UAAU;AAAA,MAC5B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,QAAQ;AAAA;AAAA,IAEN;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,SAAW,OAAQ,GAAG,OAAO,UAAU;AAAA,MAC1E,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO,EAAE,KAAK,KAAK,QAAQ,IAAK;AAAA,MAChC,QAAQ,EAAE,MAAM,SAAS;AAAA,IAC3B;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,SAAS,OAAO,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MACnF,OAAO;AAAA,MACP,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,MAAM,EAAE,KAAK,MAAM,QAAQ,IAAK;AAAA,MAChC,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,IAC7B;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,QAAQ,CAAC,cAAI,EAAE;AAAA,MACxC,MAAM,CAAC,SAAS,OAAO;AAAA,MACvB,MAAM,EAAE,KAAK,MAAM,QAAQ,IAAK;AAAA,MAChC,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,IAC7B;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,QAAQ,CAAC,aAAM,aAAM,WAAI,EAAE;AAAA,MACpD,MAAM,CAAC,SAAS,OAAO;AAAA,MACvB,MAAM;AAAA,MACN,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,SAAS,MAAM,EAAE;AAAA,IACtE;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,QAAQ,CAAC,aAAM,WAAI,EAAE;AAAA,MAC9C,MAAM,CAAC,SAAS,OAAO;AAAA,MACvB,MAAM;AAAA,MACN,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,QAAQ,MAAM,EAAE;AAAA,IACrE;AAAA;AAAA,IAEA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,QAAQ,CAAC,aAAM,WAAI,EAAE;AAAA,MAC9C,MAAM,CAAC,SAAS,OAAO;AAAA,MACvB,MAAM;AAAA,MACN,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,QAAQ,MAAM,EAAE;AAAA,IACpE;AAAA;AAAA,IAEA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,SAAW,OAAQ,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MACtF,OAAO,CAAC,MAAM,GAAG;AAAA,MACjB,OAAO;AAAA,MACP,OAAO,EAAE,KAAK,KAAK,QAAQ,KAAK;AAAA,MAChC,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,SAAS,MAAM,EAAE;AAAA,IACpE;AAAA,EACF;AACF;;;AC5EO,IAAM,aAAwB;AAAA,EACnC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,UAAU;AAAA,EACV,YAAY,EAAE,MAAM,SAAS,OAAO,UAAU;AAAA,EAC9C,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,QAAQ,QAAQ,CAAC,MAAM,IAAI,GAAG,OAAO,WAAW,OAAO,MAAO;AAAA,MAC9E,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,OAAO;AAAA,MACP,QAAQ,EAAE,GAAG,CAAC,KAAK,GAAG,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE;AAAA,MACzC,QAAQ,EAAE,MAAM,SAAS;AAAA;AAAA,MAEzB,MAAM,EAAE,OAAO,MAAO,MAAM,KAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,GAAG,EAAE;AAAA,IACjE;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,OAAQ,IAAK,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MAChF,OAAO,CAAC,KAAK,IAAI;AAAA,MACjB,OAAO;AAAA;AAAA,MAEP,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,MAAM,IAAI,GAAG,MAAM,MAAO,MAAM,EAAE,MAAM,UAAU,KAAK,KAAK,EAAE;AAAA,MAC9F,MAAM,EAAE,OAAO,MAAO,MAAM,KAAM,MAAM,CAAC,KAAK,GAAG,EAAE;AAAA,IACrD;AAAA,EACF;AACF;;;ACpCO,IAAM,kBAA6B;AAAA,EACxC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,KAAK,OAAO,UAAU;AAAA,MAC5B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,IACA,OAAO,EAAE,QAAQ,KAAO,QAAQ,KAAK;AAAA,EACvC;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,MAAQ,KAAM,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MACjF,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,QAAQ,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE;AAAA,MACtB,OAAO,CAAC,MAAM,GAAG;AAAA,MACjB,OAAO,EAAE,KAAK,MAAM,QAAQ,IAAK;AAAA,IACnC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,OAAO,IAAI;AAAA,QACnB,QAAQ,CAAC,KAAK,GAAG;AAAA,QACjB,OAAO;AAAA,QACP,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,QACxC,cAAc,CAAC,GAAG,GAAG,CAAC;AAAA,MACxB;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,UACN,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,UACnB,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,UACnB,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,UACnB,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,UACnB,EAAE,GAAG,MAAM,GAAG,IAAI;AAAA,UAClB,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,QACV,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS;AAAA,MACX;AAAA,MACA,OAAO,CAAC,MAAM,GAAG;AAAA,MACjB,OAAO,EAAE,KAAK,MAAM,QAAQ,KAAK;AAAA,MACjC,MAAM,EAAE,OAAO,KAAM,MAAM,KAAK;AAAA,MAChC,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE;AAAA,IACjC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,OAAO,KAAK,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MAC/E,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,MAAO,KAAK,GAAG,SAAS,KAAK;AAAA,MAC/D,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO;AAAA,MACP,MAAM,EAAE,OAAO,KAAM,MAAM,KAAK;AAAA,IAClC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,QAAQ,QAAQ,CAAC,MAAO,IAAK,GAAG,OAAO,WAAW,OAAO,KAAM;AAAA,MAC/E,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,MAAM,IAAI,GAAG,QAAQ,EAAE,OAAO,SAAS,EAAE;AAAA,MAC5F,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,MAAM,EAAE,OAAO,KAAM,MAAM,IAAK;AAAA,MAChC,OAAO,EAAE,QAAQ,IAAI;AAAA,IACvB;AAAA,EACF;AACF;;;AChFO,IAAM,YAAuB;AAAA,EAClC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY,EAAE,MAAM,SAAS,OAAO,UAAU;AAAA,EAC9C,QAAQ;AAAA,IACN;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,QAAQ,SAAS,CAAC,QAAG,GAAG,OAAO,UAAU;AAAA,MACzD,MAAM,CAAC,SAAS,OAAO;AAAA,MACvB,QAAQ,EAAE,MAAM,SAAS,OAAO,IAAI,OAAO,CAAC,QAAQ,MAAM,EAAE;AAAA,IAC9D;AAAA,EACF;AACF;;;ACTO,IAAM,mBAA8B;AAAA,EACzC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,MAAQ,KAAM,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MACjF,OAAO,CAAC,KAAK,IAAI;AAAA,MACjB,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,MAAO,IAAK,EAAE;AAAA,IAClD;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,aAAa,MAAM,oCAA+B,UAAU,KAAK,UAAU,OAAO,OAAO,UAAU;AAAA,MACnH,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,IAC/B;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,QAAQ,SAAS,CAAC,WAAW,QAAQ,UAAU,SAAS,WAAW,QAAQ,GAAG,MAAM,kBAAkB,OAAO,QAAQ,OAAO,UAAU;AAAA,MACtJ,MAAM,CAAC,OAAO,KAAK;AAAA,MACnB,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,MAAM,GAAG,IAAI;AAAA,MAC5B,QAAQ,EAAE,MAAM,QAAQ,KAAK,MAAM;AAAA,IACrC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA,QAC/B,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,OAAO;AAAA,QACP,QAAQ,CAAC,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,MAC3E;AAAA,MACA,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,MAC3B,QAAQ,EAAE,MAAM,QAAQ,KAAK,MAAM;AAAA,IACrC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,QAAQ,SAAS,CAAC,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK,GAAG,MAAM,aAAa,OAAO,QAAQ,OAAO,UAAU;AAAA,MAChI,MAAM,CAAC,MAAM,IAAI;AAAA,MACjB,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,MAAM,GAAG,IAAI;AAAA,MAC5B,QAAQ,EAAE,MAAM,QAAQ,KAAK,MAAM;AAAA,IACrC;AAAA,EACF;AACF;;;AC/DO,IAAM,cAAyB;AAAA,EACpC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,MAAM,OAAO,UAAU;AAAA,MAC7B,EAAE,IAAI,MAAM,OAAO,UAAU;AAAA,MAC7B,EAAE,IAAI,MAAM,OAAO,UAAU;AAAA,MAC7B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,IACA,OAAO,EAAE,QAAQ,MAAO,QAAQ,KAAK;AAAA,EACvC;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,SAAW,OAAQ;AAAA,QAC5B,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE;AAAA;AAAA,MAEvB,OAAO,EAAE,KAAK,MAAM,QAAQ,KAAM,MAAM,EAAE,YAAY,MAAM,OAAO,GAAG,EAAE;AAAA,MACxE,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,SAAW,OAAQ,GAAG,KAAK,QAAU;AAAA,IACxE;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,QAAQ,CAAC,WAAI,EAAE;AAAA,MACxC,MAAM,CAAC,SAAS,OAAO;AAAA,MACvB,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,MAAM;AAAA,MACN,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,OAAO,KAAK;AAAA,QACpB,OAAO;AAAA,QACP,SAAS;AAAA,QACT,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,QAAQ,CAAC,WAAI,EAAE;AAAA,MACxC,MAAM,CAAC,SAAS,OAAO;AAAA,MACvB,OAAO,CAAC,KAAK,IAAI;AAAA,MACjB,MAAM;AAAA,MACN,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,OAAO,KAAK;AAAA,QACpB,OAAO;AAAA,QACP,SAAS;AAAA,QACT,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,QAAQ,CAAC,WAAI,EAAE;AAAA,MACxC,MAAM,CAAC,SAAS,IAAI;AAAA,MACpB,OAAO,CAAC,MAAM,CAAC;AAAA,MACf,MAAM;AAAA,MACN,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,OAAO,KAAK;AAAA,QACpB,OAAO;AAAA,QACP,SAAS;AAAA,QACT,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,MAAM,KAAK;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,MACA,OAAO,CAAC,KAAK,IAAI;AAAA,MACjB,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,MAAM,IAAI,GAAG,OAAO,IAAI;AAAA,IAC3D;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,MAAQ,IAAK;AAAA,QACtB,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,OAAO,CAAC,MAAM,GAAG;AAAA,MACjB,OAAO;AAAA,MACP,QAAQ,EAAE,GAAG,CAAC,KAAK,GAAG,EAAE;AAAA,MACxB,OAAO,EAAE,KAAK,KAAK,QAAQ,KAAK;AAAA,MAChC,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,MAAO,IAAI,GAAG,SAAS,KAAK;AAAA,IAChE;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,SAAU,OAAQ;AAAA,QAC3B,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE;AAAA;AAAA,MAEtB,OAAO,EAAE,KAAK,MAAM,QAAQ,MAAM,MAAM,EAAE,YAAY,KAAK,OAAO,EAAE,EAAE;AAAA,MACtE,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC,SAAW,OAAQ;AAAA,QAC3B,OAAO;AAAA,QACP,KAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACF;;;ACzIO,IAAM,gBAA2B;AAAA,EACtC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,MAC1B,EAAE,IAAI,KAAK,OAAO,UAAU;AAAA,MAC5B,EAAE,IAAI,GAAG,OAAO,UAAU;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,SAAW,OAAQ,GAAG,OAAO,UAAU;AAAA,MAC1E,QAAQ,EAAE,MAAM,SAAS,OAAO,IAAI,OAAO,CAAC,SAAS,OAAO,GAAG,KAAK,QAAS;AAAA,IAC/E;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,SAAU,OAAQ,GAAG,OAAO,UAAU;AAAA,MACzE,QAAQ,EAAE,MAAM,SAAS,OAAO,IAAI,OAAO,CAAC,SAAS,OAAO,GAAG,KAAK,QAAS;AAAA,IAC/E;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,SAAU,OAAQ,GAAG,OAAO,UAAU;AAAA,MACzE,QAAQ,EAAE,MAAM,SAAS,OAAO,IAAI,OAAO,CAAC,SAAS,MAAM,GAAG,KAAK,QAAS;AAAA,IAC9E;AAAA,EACF;AACF;;;ACvBO,IAAM,qBAAgC;AAAA,EAC3C,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA;AAAA;AAAA,EAGjB,QAAQ,EAAE,OAAO,KAAK,QAAQ,IAAI;AAAA,EAClC,YAAY;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,OAAO,CAAC,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACxE,OAAO,EAAE,QAAQ,KAAO,QAAQ,IAAI;AAAA,EACtC;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,OAAO,KAAK,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MAC/E,QAAQ,EAAE,MAAM,UAAU,OAAO,CAAC,MAAO,IAAK,GAAG,SAAS,MAAM,WAAW,IAAI;AAAA,MAC/E,OAAO,CAAC,MAAM,GAAG;AAAA,MACjB,OAAO;AAAA,MACP,OAAO,EAAE,KAAK,MAAM,QAAQ,IAAK;AAAA,IACnC;AAAA,EACF;AACF;;;ACjCO,IAAM,mBAA8B;AAAA,EACzC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,UAAU;AAAA,EACV,YAAY,EAAE,MAAM,SAAS,OAAO,UAAU;AAAA,EAC9C,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,MAAO,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ,CAAC,WAAW,WAAW,WAAW,SAAS;AAAA,QACnD,cAAc,CAAC,GAAG,GAAG,KAAK,GAAG;AAAA,MAC/B;AAAA,MACA,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,MAAM,IAAI,EAAE;AAAA,MAC5C,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO;AAAA,IACT;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,QAAQ,CAAC,OAAO,IAAI;AAAA,QACpB,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ,CAAC,WAAW,SAAS;AAAA,QAC7B,cAAc,CAAC,GAAG,CAAC;AAAA,MACrB;AAAA,MACA,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,KAAK,IAAI,EAAE;AAAA,MAC3C,OAAO,CAAC,KAAK,CAAC;AAAA,MACd,OAAO;AAAA,IACT;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,UAAU,QAAQ,CAAC,MAAM,IAAI,GAAG,OAAO,WAAW,MAAM,KAAK;AAAA,MAC7E,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,MAC3B,OAAO,CAAC,MAAM,IAAI;AAAA,MAClB,OAAO,EAAE,KAAK,MAAM,QAAQ,IAAK;AAAA,MACjC,OAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC9BO,IAAM,iBAA4B;AAAA,EACvC,eAAe;AAAA,EACf,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,YAAY,EAAE,MAAM,SAAS,OAAO,UAAU;AAAA,EAC9C,QAAQ;AAAA,IACN;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,EAAE,MAAM,QAAQ,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,IAAI,GAAG,OAAO,WAAW,SAAS,IAAI;AAAA,MAC5F,QAAQ,EAAE,MAAM,SAAS,OAAO,CAAC,OAAO,KAAK,GAAG,OAAO,GAAG;AAAA,MAC1D,OAAO,CAAC,KAAK,GAAG;AAAA,MAChB,OAAO;AAAA,IACT;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS;AAAA,QACT,QAAQ;AAAA,UACN,UAAU;AAAA,UACV,MAAM;AAAA,UACN,OAAO;AAAA,UACP,OAAO,EAAE,OAAO,KAAK,OAAO,UAAU;AAAA,QACxC;AAAA,MACF;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,MAC7B,OAAO,CAAC,MAAM,IAAI;AAAA,IACpB;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS;AAAA,QACT,QAAQ,EAAE,UAAU,GAAG,MAAM,aAAa,OAAO,GAAG,MAAM,IAAI;AAAA,MAChE;AAAA,MACA,QAAQ,EAAE,MAAM,SAAS;AAAA,MACzB,UAAU,EAAE,GAAG,MAAM,GAAG,KAAK;AAAA,MAC7B,OAAO,CAAC,KAAK,GAAG;AAAA,IAClB;AAAA,EACF;AACF;;;ACnBO,IAAM,kBAA4C;AAAA,EACvD,EAAE,IAAI,YAAY,OAAO,YAAY,MAAM,cAAc;AAAA,EACzD,EAAE,IAAI,QAAQ,OAAO,QAAQ,MAAM,UAAU;AAAA,EAC7C,EAAE,IAAI,YAAY,OAAO,YAAY,MAAM,cAAc;AAAA,EACzD,EAAE,IAAI,YAAY,OAAO,kBAAkB,MAAM,cAAc;AAAA,EAC/D,EAAE,IAAI,UAAU,OAAO,gBAAgB,MAAM,YAAY;AAAA,EACzD,EAAE,IAAI,iBAAiB,OAAO,kBAAkB,MAAM,eAAe;AAAA,EACrE,EAAE,IAAI,UAAU,OAAO,UAAU,MAAM,YAAY;AAAA,EACnD,EAAE,IAAI,iBAAiB,OAAO,iBAAiB,MAAM,mBAAmB;AAAA,EACxE,EAAE,IAAI,UAAU,OAAO,gBAAgB,MAAM,YAAY;AAAA,EACzD,EAAE,IAAI,UAAU,OAAO,UAAU,MAAM,YAAY;AAAA,EACnD,EAAE,IAAI,eAAe,OAAO,eAAe,MAAM,iBAAiB;AAAA,EAClE,EAAE,IAAI,YAAY,OAAO,YAAY,MAAM,cAAc;AAAA,EACzD,EAAE,IAAI,eAAe,OAAO,eAAe,MAAM,iBAAiB;AAAA,EAClE,EAAE,IAAI,cAAc,OAAO,oBAAoB,MAAM,gBAAgB;AAAA,EACrE,EAAE,IAAI,qBAAqB,OAAO,uBAAuB,MAAM,uBAAuB;AAAA,EACtF,EAAE,IAAI,SAAS,OAAO,SAAS,MAAM,WAAW;AAAA,EAChD,EAAE,IAAI,SAAS,OAAO,SAAS,MAAM,WAAW;AAAA,EAChD,EAAE,IAAI,UAAU,OAAO,UAAU,MAAM,YAAY;AAAA,EACnD,EAAE,IAAI,eAAe,OAAO,eAAe,MAAM,iBAAiB;AAAA,EAClE,EAAE,IAAI,cAAc,OAAO,cAAc,MAAM,gBAAgB;AAAA,EAC/D,EAAE,IAAI,iBAAiB,OAAO,iBAAiB,MAAM,mBAAmB;AAAA,EACxE,EAAE,IAAI,gBAAgB,OAAO,gBAAgB,MAAM,kBAAkB;AAAA,EACrE,EAAE,IAAI,aAAa,OAAO,aAAa,MAAM,eAAe;AAAA,EAC5D,EAAE,IAAI,gBAAgB,OAAO,gBAAgB,MAAM,kBAAkB;AAAA,EACrE,EAAE,IAAI,cAAc,OAAO,cAAc,MAAM,gBAAgB;AAAA,EAC/D,EAAE,IAAI,YAAY,OAAO,YAAY,MAAM,cAAc;AAAA,EACzD,EAAE,IAAI,cAAc,OAAO,cAAc,MAAM,gBAAgB;AAAA,EAC/D,EAAE,IAAI,UAAU,OAAO,UAAU,MAAM,YAAY;AACrD;AAiBO,IAAM,oBAAgD;AAAA,EAC3D,EAAE,IAAI,mBAAmB,OAAO,mBAAmB,UAAU,yBAAyB;AACxF;AAGO,IAAM,gBAA6B,gBAAgB,IAAI,CAAC,MAAM,EAAE,IAAI;AAGpE,IAAM,gBAAqD,OAAO;AAAA,EACvE,gBAAgB,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC;AAC3C;","names":["isObj","HEX","ease","ease","catmullRom","y","x","clamp01","smoothstep","clamp01","wrap","clamp01","groupOf","color","u","unitScale","wrap","createRng","acc","inside","createRng","createRng","s","sizePx","createRng","inside","createRng","createRng"]}
|