@classytic/stage 0.1.0 → 0.2.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/README.md +2 -2
- package/dist/assets/kit/glyphs.d.mts +5 -5
- package/dist/assets/kit/glyphs.mjs +4 -4
- package/dist/builder/SceneBuilder.mjs +4 -4
- package/dist/builder/editor.d.mts +2 -1
- package/dist/builder/editor.mjs +14 -4
- package/dist/builder/tools.d.mts +1 -1
- package/dist/builder/tools.mjs +1 -1
- package/dist/chem/index.d.mts +5 -5
- package/dist/chem/index.mjs +4 -4
- package/dist/circuit/index.d.mts +92 -0
- package/dist/circuit/index.mjs +333 -0
- package/dist/core/clock.d.mts +1 -1
- package/dist/core/clock.mjs +3 -3
- package/dist/core/control.d.mts +1 -1
- package/dist/core/control.mjs +2 -2
- package/dist/core/coords.d.mts +4 -4
- package/dist/core/coords.mjs +1 -1
- package/dist/core/learner.d.mts +1 -1
- package/dist/core/learner.mjs +1 -1
- package/dist/core/motion.d.mts +6 -6
- package/dist/core/motion.mjs +6 -6
- package/dist/core/richText.d.mts +2 -2
- package/dist/core/vec.d.mts +1 -1
- package/dist/field/index.d.mts +11 -3
- package/dist/field/index.mjs +20 -3
- package/dist/index.d.mts +3 -1
- package/dist/index.mjs +3 -1
- package/dist/interaction/MovableDot.d.mts +17 -1
- package/dist/interaction/MovableDot.mjs +141 -43
- package/dist/interaction/index.d.mts +2 -1
- package/dist/interaction/index.mjs +2 -1
- package/dist/interaction/useDraggable.d.mts +1 -1
- package/dist/interaction/useDraggable.mjs +31 -1
- package/dist/interaction/usePressSpring.d.mts +24 -0
- package/dist/interaction/usePressSpring.mjs +67 -0
- package/dist/logic/ast.d.mts +1 -1
- package/dist/logic/index.mjs +8 -3
- package/dist/logic/minimize.d.mts +2 -2
- package/dist/logic/minimize.mjs +56 -18
- package/dist/logic/table.mjs +1 -1
- package/dist/math/ast.d.mts +1 -1
- package/dist/math/ast.mjs +1 -1
- package/dist/math/calculus.mjs +68 -9
- package/dist/math/compile.d.mts +8 -0
- package/dist/math/compile.mjs +40 -0
- package/dist/math/defs.mjs +1 -1
- package/dist/math/index.d.mts +4 -3
- package/dist/math/index.mjs +4 -3
- package/dist/math/parse.mjs +2 -2
- package/dist/math/tokenize.mjs +1 -1
- package/dist/primitives/CanvasLayer.mjs +3 -3
- package/dist/primitives/Grid.d.mts +12 -1
- package/dist/primitives/Grid.mjs +15 -9
- package/dist/primitives/Label.d.mts +1 -1
- package/dist/primitives/Label.mjs +1 -1
- package/dist/primitives/Tex.mjs +2 -2
- package/dist/scene/Scene.mjs +1 -1
- package/dist/scene/assets.d.mts +2 -2
- package/dist/scene/assets.mjs +2 -2
- package/dist/scene/commands.d.mts +10 -1
- package/dist/scene/commands.mjs +42 -2
- package/dist/scene/evaluators.mjs +2 -2
- package/dist/scene/index.d.mts +2 -2
- package/dist/scene/index.mjs +2 -2
- package/dist/scene/migrate.mjs +1 -1
- package/dist/scene/sims.mjs +1 -1
- package/dist/scene/types.d.mts +4 -4
- package/dist/sim/particles.d.mts +2 -2
- package/dist/sim/rate.d.mts +4 -4
- package/dist/sim/rate.mjs +1 -1
- package/dist/sim/registry.d.mts +1 -1
- package/dist/sim/sampler.d.mts +5 -5
- package/dist/sim/thermal.d.mts +3 -3
- package/dist/sim/thermal.mjs +2 -2
- package/dist/sim/types.d.mts +2 -2
- package/dist/sim/wave.d.mts +2 -2
- package/dist/sim/wave.mjs +2 -2
- package/dist/steps/index.d.mts +1 -1
- package/dist/steps/index.mjs +3 -3
- package/dist/thermo/index.d.mts +1 -1
- package/dist/thermo/index.mjs +1 -1
- package/dist/view/Stage.mjs +2 -2
- package/dist/view/useInView.mjs +1 -1
- package/package.json +8 -4
- package/styles.css +23 -0
package/dist/sim/particles.d.mts
CHANGED
|
@@ -28,14 +28,14 @@ interface ParticlesState {
|
|
|
28
28
|
py: number[];
|
|
29
29
|
vx: number[];
|
|
30
30
|
vy: number[];
|
|
31
|
-
/** 0 or 1
|
|
31
|
+
/** 0 or 1, two populations (for diffusion / colour). */
|
|
32
32
|
group: number[];
|
|
33
33
|
tSec: number;
|
|
34
34
|
/** Mean kinetic energy ∝ temperature. */
|
|
35
35
|
temp: number;
|
|
36
36
|
/** Smoothed pressure (wall-collision momentum per unit time per unit perimeter). */
|
|
37
37
|
pressure: number;
|
|
38
|
-
/** Mixing index 0 (separated) → 1 (uniform)
|
|
38
|
+
/** Mixing index 0 (separated) → 1 (uniform), fraction-based, for diffusion. */
|
|
39
39
|
mixed: number;
|
|
40
40
|
}
|
|
41
41
|
declare const ParticlesCore: SimCore<ParticlesState, ParticlesParams>;
|
package/dist/sim/rate.d.mts
CHANGED
|
@@ -8,7 +8,7 @@ interface RateParams {
|
|
|
8
8
|
value0?: number;
|
|
9
9
|
/** Asymptote the value relaxes toward. Default 0 (pure decay). */
|
|
10
10
|
target?: number;
|
|
11
|
-
/** Time constant τ (seconds)
|
|
11
|
+
/** Time constant τ (seconds), the e-folding time. Default 1. */
|
|
12
12
|
tau?: number;
|
|
13
13
|
/** Stop after this many seconds (essentially relaxed) so it doesn't run forever. Default ∞. */
|
|
14
14
|
maxTime?: number;
|
|
@@ -21,15 +21,15 @@ interface RateState {
|
|
|
21
21
|
tau: number;
|
|
22
22
|
/** Seconds elapsed on this core's timeline. */
|
|
23
23
|
tSec: number;
|
|
24
|
-
/** Rolling history of `value`, oldest-first
|
|
24
|
+
/** Rolling history of `value`, oldest-first, for the curve. */
|
|
25
25
|
samples: number[];
|
|
26
26
|
cap: number;
|
|
27
27
|
maxTime: number;
|
|
28
|
-
/** True once tSec ≥ maxTime
|
|
28
|
+
/** True once tSec ≥ maxTime, the runtime stops the loop. */
|
|
29
29
|
done: boolean;
|
|
30
30
|
}
|
|
31
31
|
declare const RateCore: SimCore<RateState, RateParams>;
|
|
32
|
-
/** τ from a half-life (and back)
|
|
32
|
+
/** τ from a half-life (and back), t½ = τ·ln2. */
|
|
33
33
|
declare const halfLifeToTau: (halfLife: number) => number;
|
|
34
34
|
declare const tauToHalfLife: (tau: number) => number;
|
|
35
35
|
//#endregion
|
package/dist/sim/rate.mjs
CHANGED
package/dist/sim/registry.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SimCore } from "./types.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/sim/registry.d.ts
|
|
4
|
-
/** A core with its specifics erased
|
|
4
|
+
/** A core with its specifics erased, the runtime reads state fields by name. */
|
|
5
5
|
type AnySim = SimCore<Record<string, unknown>, Record<string, unknown>>;
|
|
6
6
|
declare function registerSim<S extends Record<string, unknown>, P>(name: string, core: SimCore<S, P>): void;
|
|
7
7
|
declare function getSim(name: string): AnySim | undefined;
|
package/dist/sim/sampler.d.mts
CHANGED
|
@@ -8,7 +8,7 @@ interface SamplerParams {
|
|
|
8
8
|
perStep?: number;
|
|
9
9
|
/** PRNG seed. Default 1. */
|
|
10
10
|
seed?: number;
|
|
11
|
-
/** Stop drawing once `n` reaches this
|
|
11
|
+
/** Stop drawing once `n` reaches this, a converged sim shouldn't run forever. Default ∞. */
|
|
12
12
|
maxDraws?: number;
|
|
13
13
|
/** History ring-buffer capacity for the headline estimate p[0]. Default 240. */
|
|
14
14
|
trace?: number;
|
|
@@ -20,7 +20,7 @@ interface SamplerState {
|
|
|
20
20
|
* Current PRNG state (advances every draw). Deliberately NOT named `seed`: the
|
|
21
21
|
* Scene runtime merges the SimDecl `params` (which carries the initial `seed`)
|
|
22
22
|
* onto the state each frame, so an evolving field sharing a param name would be
|
|
23
|
-
* clobbered back to its initial value
|
|
23
|
+
* clobbered back to its initial value, freezing the RNG. Keep evolving state
|
|
24
24
|
* fields disjoint from param names.
|
|
25
25
|
*/
|
|
26
26
|
rng: number;
|
|
@@ -30,16 +30,16 @@ interface SamplerState {
|
|
|
30
30
|
counts: number[];
|
|
31
31
|
/** Running frequency estimate per outcome (counts / n). */
|
|
32
32
|
p: number[];
|
|
33
|
-
/** True (normalized) probabilities
|
|
33
|
+
/** True (normalized) probabilities, for convergence comparison. */
|
|
34
34
|
p0: number[];
|
|
35
35
|
/** Index of the most recent draw (-1 before the first). */
|
|
36
36
|
last: number;
|
|
37
|
-
/** Rolling history of p[0], oldest-first
|
|
37
|
+
/** Rolling history of p[0], oldest-first, for an LLN convergence plot. */
|
|
38
38
|
samples: number[];
|
|
39
39
|
cap: number;
|
|
40
40
|
/** Draw cap; step() becomes a no-op once n reaches it. */
|
|
41
41
|
maxDraws: number;
|
|
42
|
-
/** True once n ≥ maxDraws
|
|
42
|
+
/** True once n ≥ maxDraws, the runtime stops the loop. */
|
|
43
43
|
done: boolean;
|
|
44
44
|
}
|
|
45
45
|
declare const SamplerCore: SimCore<SamplerState, SamplerParams>;
|
package/dist/sim/thermal.d.mts
CHANGED
|
@@ -21,10 +21,10 @@ interface Substance {
|
|
|
21
21
|
/** Liquid colour token (for the skin). */
|
|
22
22
|
color: string;
|
|
23
23
|
}
|
|
24
|
-
/** Real water
|
|
24
|
+
/** Real water, the canonical example (note: latent vaporisation ≫ everything,
|
|
25
25
|
* so the boiling plateau dwarfs the rest, which is exactly the lesson). */
|
|
26
26
|
declare const WATER: Substance;
|
|
27
|
-
/** Ethanol
|
|
27
|
+
/** Ethanol, lower boiling point, smaller latent heats; a contrasting curve. */
|
|
28
28
|
declare const ETHANOL: Substance;
|
|
29
29
|
type Phase = 'solid' | 'melting' | 'liquid' | 'boiling' | 'gas';
|
|
30
30
|
/** One run of the energy ladder. `kind:'heat'` is a sloped temperature rise
|
|
@@ -58,7 +58,7 @@ interface ThermalState {
|
|
|
58
58
|
powerW: number;
|
|
59
59
|
tStart: number;
|
|
60
60
|
tMax: number;
|
|
61
|
-
/** The full energy ladder
|
|
61
|
+
/** The full energy ladder, the heating curve, as data. */
|
|
62
62
|
segs: ThermalSeg[];
|
|
63
63
|
/** Total heat to walk the whole ladder, J. */
|
|
64
64
|
totalJ: number;
|
package/dist/sim/thermal.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/sim/thermal.ts
|
|
2
2
|
const clamp01 = (v) => Math.max(0, Math.min(1, v));
|
|
3
|
-
/** Real water
|
|
3
|
+
/** Real water, the canonical example (note: latent vaporisation ≫ everything,
|
|
4
4
|
* so the boiling plateau dwarfs the rest, which is exactly the lesson). */
|
|
5
5
|
const WATER = {
|
|
6
6
|
name: "Water",
|
|
@@ -16,7 +16,7 @@ const WATER = {
|
|
|
16
16
|
tBoil: 100,
|
|
17
17
|
color: "var(--stage-accent, #3b82f6)"
|
|
18
18
|
};
|
|
19
|
-
/** Ethanol
|
|
19
|
+
/** Ethanol, lower boiling point, smaller latent heats; a contrasting curve. */
|
|
20
20
|
const ETHANOL = {
|
|
21
21
|
name: "Ethanol",
|
|
22
22
|
solidName: "solid",
|
package/dist/sim/types.d.mts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
//#region src/sim/types.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* Sim cores
|
|
3
|
+
* Sim cores, the "physics engine" half of a lab: pure, time-stepped simulators
|
|
4
4
|
* with NO React and NO pixels. A core is `reset(params) → state`, then
|
|
5
5
|
* `step(state, dt) → state` once per frame. Because a core is a pure function of
|
|
6
6
|
* (params, elapsed time), a lab built on one is deterministic: it replays
|
|
7
7
|
* identically under a Remotion fixed-frame clock (→ video) and is unit-testable
|
|
8
8
|
* with no DOM. Rendering (glyphs) READS the returned state; drawing never lives
|
|
9
|
-
* in here. Live controls write their target fields onto `state` between steps
|
|
9
|
+
* in here. Live controls write their target fields onto `state` between steps ,
|
|
10
10
|
* so a core's mutable inputs (e.g. `volts`, `mode`) live IN its state, which is
|
|
11
11
|
* also why those fields are readable by name from a binding.
|
|
12
12
|
*/
|
package/dist/sim/wave.d.mts
CHANGED
|
@@ -22,9 +22,9 @@ interface WaveState {
|
|
|
22
22
|
tSec: number;
|
|
23
23
|
/** Instantaneous signed voltage; sign = current direction. */
|
|
24
24
|
v: number;
|
|
25
|
-
/** ∫v·dt
|
|
25
|
+
/** ∫v·dt, accumulated charge displacement; what flow position (electrons / water) reads. */
|
|
26
26
|
charge: number;
|
|
27
|
-
/** Rolling history of `v`, oldest-first, length ≤ `cap
|
|
27
|
+
/** Rolling history of `v`, oldest-first, length ≤ `cap`, for the live trace. */
|
|
28
28
|
samples: number[];
|
|
29
29
|
/** Fixed capacity of `samples`. */
|
|
30
30
|
cap: number;
|
package/dist/sim/wave.mjs
CHANGED
|
@@ -2,9 +2,9 @@ import { oscillate } from "../core/motion.mjs";
|
|
|
2
2
|
|
|
3
3
|
//#region src/sim/wave.ts
|
|
4
4
|
/**
|
|
5
|
-
* `wave
|
|
5
|
+
* `wave`, the AC/DC signal source. One core drives a whole scene: a DC source
|
|
6
6
|
* holds a steady voltage; an AC source oscillates. Either way it exposes the
|
|
7
|
-
* instantaneous voltage `v` (signed
|
|
7
|
+
* instantaneous voltage `v` (signed, sign IS current direction) plus a rolling
|
|
8
8
|
* `samples` buffer for a live scrolling trace. The SAME `v` can skin many ways at
|
|
9
9
|
* once (a lamp's brightness, electrons in a wire, water sloshing in a pipe), which
|
|
10
10
|
* is the point: sim ≠ render, so one signal feeds every visual metaphor in sync.
|
package/dist/steps/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
2
|
|
|
3
3
|
//#region src/steps/index.d.ts
|
|
4
|
-
/** One step in the sequence
|
|
4
|
+
/** One step in the sequence, identity + gating only. Its TITLE, PROSE, and the
|
|
5
5
|
* interactive itself live in the authored Section block, not here. */
|
|
6
6
|
interface StepSpec {
|
|
7
7
|
id: string;
|
package/dist/steps/index.mjs
CHANGED
|
@@ -5,14 +5,14 @@ import { createContext, createElement, useContext, useMemo, useRef, useSyncExter
|
|
|
5
5
|
|
|
6
6
|
//#region src/steps/index.ts
|
|
7
7
|
/**
|
|
8
|
-
* Step progress + gating
|
|
8
|
+
* Step progress + gating, the runtime that turns an ordered sequence of lesson
|
|
9
9
|
* STEPS into "unlock the next when this one is solved" + aggregated completion.
|
|
10
10
|
*
|
|
11
|
-
* ONE SOURCE OF TRUTH for the step sequence is the authored content itself
|
|
11
|
+
* ONE SOURCE OF TRUTH for the step sequence is the authored content itself, the
|
|
12
12
|
* @classytic/cms-ui `Section`/`Step` blocks a creator orders in the editor
|
|
13
13
|
* (serialized in the MDX). This engine deliberately does NOT model an authored
|
|
14
14
|
* "LessonDoc": that would be a SECOND, competing definition of the same steps
|
|
15
|
-
* (and creators never hand-write one
|
|
15
|
+
* (and creators never hand-write one, they build Section blocks). The host's
|
|
16
16
|
* Section player derives a `StepSpec[]` from the section order, wraps each
|
|
17
17
|
* section's interactive in `<StepScope id>`, and reads `useStepProgress` to gate
|
|
18
18
|
* reveal. Each lab's `useLearner().report` flows into step completion AND
|
package/dist/thermo/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/thermo/index.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* `thermo
|
|
3
|
+
* `thermo`, ideal-gas thermodynamic processes, as a PURE kernel (like `field`:
|
|
4
4
|
* no React, no pixels, no time-stepping). A lab drives it with a slider/progress
|
|
5
5
|
* fraction; the kernel returns the full P–V path of a quasi-static process plus the
|
|
6
6
|
* first-law bookkeeping along it (work, heat, internal energy, entropy).
|
package/dist/thermo/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/thermo/index.ts
|
|
2
2
|
/**
|
|
3
|
-
* `thermo
|
|
3
|
+
* `thermo`, ideal-gas thermodynamic processes, as a PURE kernel (like `field`:
|
|
4
4
|
* no React, no pixels, no time-stepping). A lab drives it with a slider/progress
|
|
5
5
|
* fraction; the kernel returns the full P–V path of a quasi-static process plus the
|
|
6
6
|
* first-law bookkeeping along it (work, heat, internal energy, entropy).
|
package/dist/view/Stage.mjs
CHANGED
|
@@ -8,10 +8,10 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
8
8
|
|
|
9
9
|
//#region src/view/Stage.tsx
|
|
10
10
|
/**
|
|
11
|
-
* <Stage
|
|
11
|
+
* <Stage>, the SVG root. SSR-safe: builds a CoordinateSystem from explicit
|
|
12
12
|
* width/height/aspectRatio (or a default) so children render on first paint;
|
|
13
13
|
* after mount a ResizeObserver swaps in the measured width. There is ONE content
|
|
14
|
-
* group with no transform
|
|
14
|
+
* group with no transform, every primitive self-positions via coords.toPx().
|
|
15
15
|
* A pixel-space overlay group hosts selection halos/handles (builder phase).
|
|
16
16
|
*/
|
|
17
17
|
const DEFAULT_VIEW = {
|
package/dist/view/useInView.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { useEffect, useRef, useState } from "react";
|
|
|
4
4
|
|
|
5
5
|
//#region src/view/useInView.ts
|
|
6
6
|
/**
|
|
7
|
-
* useInView
|
|
7
|
+
* useInView, pause work when a lab scrolls off-screen. Sim labs drive an
|
|
8
8
|
* unbounded requestAnimationFrame loop; without this, every sim on a page runs
|
|
9
9
|
* forever even when nobody can see it (and a gallery of labs pins the CPU). Gate
|
|
10
10
|
* `useFrameLoop({ running: inView })` on this. SSR-safe; if IntersectionObserver
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@classytic/stage",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Domain-neutral visual primitive engine for the web. Declarative SVG diagram/math primitives, draggable handles, a math↔pixel coordinate system, a motion core + energy effect defs, theming, pure sim cores, and a small kit of neutral glyph primitives. Reactive, web-native, agent-drivable. The render foundation under @classytic/labs (subject-matter glyphs live there); canvas + 3D subpaths later.",
|
|
5
5
|
"author": "Classytic",
|
|
6
6
|
"license": "MIT",
|
|
@@ -60,6 +60,10 @@
|
|
|
60
60
|
"types": "./dist/field/index.d.mts",
|
|
61
61
|
"default": "./dist/field/index.mjs"
|
|
62
62
|
},
|
|
63
|
+
"./circuit": {
|
|
64
|
+
"types": "./dist/circuit/index.d.mts",
|
|
65
|
+
"default": "./dist/circuit/index.mjs"
|
|
66
|
+
},
|
|
63
67
|
"./thermo": {
|
|
64
68
|
"types": "./dist/thermo/index.d.mts",
|
|
65
69
|
"default": "./dist/thermo/index.mjs"
|
|
@@ -68,9 +72,9 @@
|
|
|
68
72
|
"types": "./dist/chem/index.d.mts",
|
|
69
73
|
"default": "./dist/chem/index.mjs"
|
|
70
74
|
},
|
|
71
|
-
"./
|
|
72
|
-
"types": "./dist/
|
|
73
|
-
"default": "./dist/
|
|
75
|
+
"./steps": {
|
|
76
|
+
"types": "./dist/steps/index.d.mts",
|
|
77
|
+
"default": "./dist/steps/index.mjs"
|
|
74
78
|
},
|
|
75
79
|
"./styles.css": "./styles.css",
|
|
76
80
|
"./package.json": "./package.json"
|
package/styles.css
CHANGED
|
@@ -49,6 +49,19 @@
|
|
|
49
49
|
--stage-wire: var(--stage-metal);
|
|
50
50
|
--stage-live: var(--stage-good);
|
|
51
51
|
--stage-charge: var(--stage-accent);
|
|
52
|
+
|
|
53
|
+
/* Categorical series palette: 8 distinct, theme-aware hues for group / series
|
|
54
|
+
colours (K-map loops, distributions, selection groups, arrangement letters).
|
|
55
|
+
Labs import these via kit/palette instead of hardcoding hex arrays that
|
|
56
|
+
ignore dark mode. cat-1/2/3 align with accent / accent-2 / good. */
|
|
57
|
+
--stage-cat-1: oklch(0.59 0.20 261);
|
|
58
|
+
--stage-cat-2: oklch(0.63 0.17 45);
|
|
59
|
+
--stage-cat-3: oklch(0.58 0.16 150);
|
|
60
|
+
--stage-cat-4: oklch(0.55 0.20 300);
|
|
61
|
+
--stage-cat-5: oklch(0.62 0.12 200);
|
|
62
|
+
--stage-cat-6: oklch(0.60 0.21 18);
|
|
63
|
+
--stage-cat-7: oklch(0.70 0.15 92);
|
|
64
|
+
--stage-cat-8: oklch(0.60 0.20 332);
|
|
52
65
|
}
|
|
53
66
|
|
|
54
67
|
.dark {
|
|
@@ -67,4 +80,14 @@
|
|
|
67
80
|
--stage-pan: oklch(0.83 0.02 255);
|
|
68
81
|
--stage-weight-2: var(--brand-2, oklch(0.74 0.15 50));
|
|
69
82
|
--stage-liquid: oklch(0.7 0.13 220 / 0.6);
|
|
83
|
+
|
|
84
|
+
/* Brighter categorical hues for the dark card surface. */
|
|
85
|
+
--stage-cat-1: oklch(0.72 0.17 261);
|
|
86
|
+
--stage-cat-2: oklch(0.78 0.15 52);
|
|
87
|
+
--stage-cat-3: oklch(0.72 0.17 150);
|
|
88
|
+
--stage-cat-4: oklch(0.71 0.18 300);
|
|
89
|
+
--stage-cat-5: oklch(0.76 0.12 200);
|
|
90
|
+
--stage-cat-6: oklch(0.73 0.18 22);
|
|
91
|
+
--stage-cat-7: oklch(0.83 0.16 92);
|
|
92
|
+
--stage-cat-8: oklch(0.75 0.18 332);
|
|
70
93
|
}
|