axstack 0.36.1 → 0.38.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.
Files changed (137) hide show
  1. package/README.md +5 -4
  2. package/bin/axstack.js +4 -18
  3. package/docs/getting-started.md +6 -6
  4. package/docs/host-operations.md +9 -5
  5. package/docs/installation.md +20 -41
  6. package/docs/workflows.md +12 -9
  7. package/package.json +1 -1
  8. package/profiles/presets/claude-only.json +3 -3
  9. package/profiles/presets/codex-only.json +3 -3
  10. package/profiles/presets/mixed.json +5 -4
  11. package/skills/axstack/references/automations.md +7 -2
  12. package/skills/axstack/references/lifecycle.md +2 -1
  13. package/skills/axstack/references/review-manager-prompt.md +44 -3
  14. package/skills/axstack/references/role-roster.md +13 -6
  15. package/skills/axstack/references/routing.md +2 -1
  16. package/skills/axstack/references/run-record.md +2 -0
  17. package/skills/axstack/references/ui-verification.md +6 -10
  18. package/skills/axstack-anatomy/ANATOMY.md +172 -0
  19. package/skills/axstack-anatomy/CHANGELOG.md +70 -0
  20. package/skills/axstack-anatomy/LICENSE +21 -0
  21. package/skills/axstack-anatomy/PROVENANCE.md +21 -0
  22. package/skills/axstack-anatomy/README.md +316 -0
  23. package/skills/axstack-anatomy/SKILL.md +74 -0
  24. package/skills/axstack-anatomy/SOURCE-PROOF.json +107 -0
  25. package/skills/axstack-anatomy/examples/arcade-cabinet/arcade-cabinet.css +44 -0
  26. package/skills/axstack-anatomy/examples/arcade-cabinet/build.mjs +714 -0
  27. package/skills/axstack-anatomy/examples/arcade-cabinet/live.js +597 -0
  28. package/skills/axstack-anatomy/examples/arcade-cabinet/parts.mjs +89 -0
  29. package/skills/axstack-anatomy/examples/arcade-cabinet/screen.mjs +114 -0
  30. package/skills/axstack-anatomy/examples/desk-computer/build.mjs +435 -0
  31. package/skills/axstack-anatomy/examples/dial-indicator/build.mjs +275 -0
  32. package/skills/axstack-anatomy/examples/raptor-engine/build.mjs +938 -0
  33. package/skills/axstack-anatomy/examples/raptor-engine/live.js +907 -0
  34. package/skills/axstack-anatomy/examples/raptor-engine/raptor.css +359 -0
  35. package/skills/axstack-anatomy/examples/ripple-tank/build.mjs +558 -0
  36. package/skills/axstack-anatomy/examples/ripple-tank/live.js +579 -0
  37. package/skills/axstack-anatomy/examples/ripple-tank/model.mjs +131 -0
  38. package/skills/axstack-anatomy/examples/ripple-tank/ripple.css +103 -0
  39. package/skills/axstack-anatomy/examples/spot-plate/art.tsx +110 -0
  40. package/skills/axstack-anatomy/examples/spot-plate/drops.ts +541 -0
  41. package/skills/axstack-anatomy/examples/spot-plate/fan.ts +84 -0
  42. package/skills/axstack-anatomy/examples/spot-plate/figure.tsx +25 -0
  43. package/skills/axstack-anatomy/examples/spot-plate/geometry.ts +280 -0
  44. package/skills/axstack-anatomy/examples/spot-plate/live.tsx +339 -0
  45. package/skills/axstack-anatomy/examples/spot-plate/rig.ts +230 -0
  46. package/skills/axstack-anatomy/examples/spot-plate/spot-plate.css +92 -0
  47. package/skills/axstack-anatomy/examples/test-rig/art.tsx +196 -0
  48. package/skills/axstack-anatomy/examples/test-rig/figure.tsx +23 -0
  49. package/skills/axstack-anatomy/examples/test-rig/geometry.ts +305 -0
  50. package/skills/axstack-anatomy/examples/test-rig/live.tsx +511 -0
  51. package/skills/axstack-anatomy/examples/test-rig/pose.ts +107 -0
  52. package/skills/axstack-anatomy/examples/test-rig/rig.ts +170 -0
  53. package/skills/axstack-anatomy/examples/test-rig/stretch.css +80 -0
  54. package/skills/axstack-anatomy/examples/test-rig/view.ts +99 -0
  55. package/skills/axstack-anatomy/examples/turning-dial/build.mjs +479 -0
  56. package/skills/axstack-anatomy/examples/turning-dial/dial.css +10 -0
  57. package/skills/axstack-anatomy/examples/turning-dial/live.js +342 -0
  58. package/skills/axstack-anatomy/examples/turning-dial/stress.mjs +269 -0
  59. package/skills/axstack-anatomy/kit/audit.mjs +1913 -0
  60. package/skills/axstack-anatomy/kit/canvas-painter.mjs +722 -0
  61. package/skills/axstack-anatomy/kit/gl-shared.mjs +184 -0
  62. package/skills/axstack-anatomy/kit/gl.mjs +184 -0
  63. package/skills/axstack-anatomy/kit/iso-kit.mjs +674 -0
  64. package/skills/axstack-anatomy/kit/iso-kit.ts +842 -0
  65. package/skills/axstack-anatomy/kit/iso.css +106 -0
  66. package/skills/axstack-anatomy/kit/lathe.mjs +1184 -0
  67. package/skills/axstack-anatomy/kit/react/draw.tsx +205 -0
  68. package/skills/axstack-anatomy/kit/react/live.tsx +140 -0
  69. package/skills/axstack-anatomy/kit/tube.mjs +306 -0
  70. package/skills/axstack-anatomy/kit/turn-audit.mjs +1096 -0
  71. package/skills/axstack-anatomy/kit/turn-build.mjs +1355 -0
  72. package/skills/axstack-anatomy/kit/turn-fixed.mjs +3800 -0
  73. package/skills/axstack-anatomy/kit/turn.mjs +3610 -0
  74. package/skills/axstack-anatomy/references/3d.md +352 -0
  75. package/skills/axstack-anatomy/references/craft.md +325 -0
  76. package/skills/axstack-anatomy/references/kit.md +419 -0
  77. package/skills/axstack-anatomy/references/motion.md +165 -0
  78. package/skills/axstack-anatomy/references/react.md +42 -0
  79. package/skills/axstack-anatomy/references/verify.md +351 -0
  80. package/skills/axstack-anatomy/references/walkthrough.md +75 -0
  81. package/skills/axstack-anatomy/references/webgl.md +473 -0
  82. package/skills/axstack-anatomy/scripts/audit-affine-bounds.test.mjs +54 -0
  83. package/skills/axstack-anatomy/scripts/audit-cache.test.mjs +37 -0
  84. package/skills/axstack-anatomy/scripts/audit-clearance-envelope.test.mjs +39 -0
  85. package/skills/axstack-anatomy/scripts/audit-empty-clipping.test.mjs +38 -0
  86. package/skills/axstack-anatomy/scripts/audit-order-convergence.test.mjs +55 -0
  87. package/skills/axstack-anatomy/scripts/audit-path-origin.test.mjs +26 -0
  88. package/skills/axstack-anatomy/scripts/audit-profile.test.mjs +41 -0
  89. package/skills/axstack-anatomy/scripts/audit-projection.test.mjs +36 -0
  90. package/skills/axstack-anatomy/scripts/audit-slide-clearance.test.mjs +58 -0
  91. package/skills/axstack-anatomy/scripts/audit-svg-attributes.test.mjs +46 -0
  92. package/skills/axstack-anatomy/scripts/audit-taper.test.mjs +29 -0
  93. package/skills/axstack-anatomy/scripts/capture-selector.test.mjs +131 -0
  94. package/skills/axstack-anatomy/scripts/capture.mjs +228 -0
  95. package/skills/axstack-anatomy/scripts/capture.test.mjs +42 -0
  96. package/skills/axstack-anatomy/scripts/chrome-port.mjs +36 -0
  97. package/skills/axstack-anatomy/scripts/chrome-startup.test.mjs +38 -0
  98. package/skills/axstack-anatomy/scripts/drive-actions.test.mjs +46 -0
  99. package/skills/axstack-anatomy/scripts/drive.mjs +302 -0
  100. package/skills/axstack-anatomy/scripts/drive.test.mjs +72 -0
  101. package/skills/axstack-anatomy/scripts/enter-key.test.mjs +38 -0
  102. package/skills/axstack-anatomy/scripts/fidelity-cut.test.mjs +54 -0
  103. package/skills/axstack-anatomy/scripts/fidelity-tube-coverage.test.mjs +40 -0
  104. package/skills/axstack-anatomy/scripts/inline-kit.mjs +26 -0
  105. package/skills/axstack-anatomy/scripts/line-ends.mjs +306 -0
  106. package/skills/axstack-anatomy/scripts/lines-arcs.test.mjs +50 -0
  107. package/skills/axstack-anatomy/scripts/lines-bezier.test.mjs +28 -0
  108. package/skills/axstack-anatomy/scripts/lines-round.test.mjs +56 -0
  109. package/skills/axstack-anatomy/scripts/lines-rounded-rect.test.mjs +32 -0
  110. package/skills/axstack-anatomy/scripts/lines.mjs +31 -0
  111. package/skills/axstack-anatomy/scripts/lines.test.mjs +38 -0
  112. package/skills/axstack-anatomy/scripts/navigation.test.mjs +55 -0
  113. package/skills/axstack-anatomy/scripts/orbit-sampling.test.mjs +50 -0
  114. package/skills/axstack-anatomy/scripts/react-dots-opacity.test.mjs +51 -0
  115. package/skills/axstack-anatomy/scripts/react-readout-first-write.test.mjs +37 -0
  116. package/skills/axstack-anatomy/scripts/react-solid-seamless.test.mjs +47 -0
  117. package/skills/axstack-anatomy/scripts/react-visibility-target.test.mjs +38 -0
  118. package/skills/axstack-anatomy/scripts/turn-bench.mjs +74 -0
  119. package/skills/axstack-anatomy/scripts/turn-check.mjs +641 -0
  120. package/skills/axstack-anatomy/scripts/turn-fidelity.mjs +413 -0
  121. package/skills/axstack-anatomy/scripts/turn-group-reference.test.mjs +40 -0
  122. package/skills/axstack-anatomy/scripts/turn-split-owner.test.mjs +62 -0
  123. package/skills/axstack-anatomy/theme.js +56 -0
  124. package/skills/axstack-explain/SKILL.md +28 -15
  125. package/skills/axstack-explain/references/delivery.md +22 -0
  126. package/skills/{axstack-diagram → axstack-explain}/references/fidelity.md +1 -7
  127. package/skills/axstack-explain/references/inline-pages.md +8 -8
  128. package/skills/axstack-explain/references/visual-qa.md +3 -5
  129. package/skills/axstack-explain/references/whiteboard-defense.md +59 -0
  130. package/skills/axstack-research/SKILL.md +18 -6
  131. package/src/archify-legacy.js +70 -0
  132. package/src/capabilities.js +1 -29
  133. package/src/installer.js +11 -31
  134. package/skills/axstack-diagram/SKILL.md +0 -28
  135. package/skills/axstack-diagram/references/archify.md +0 -76
  136. package/src/archify-pin.js +0 -5
  137. package/src/archify.js +0 -151
@@ -0,0 +1,131 @@
1
+ export const WATER = { depth: 0.006, gravity: 9.81, tension: 0.0728, density: 998, index: 1.333, viscosity: 1.0e-6 };
2
+ export const GLASS = 1.52;
3
+ export const RANGE = { frequency: [8, 28], spacing: [20, 80] };
4
+ export const BEAT = 0.75;
5
+ export const SLOPE = 0.03;
6
+ export const REACH = 24;
7
+
8
+ export function omegaOf(k) {
9
+ const { depth, gravity, tension, density } = WATER;
10
+ return Math.sqrt((gravity * k + (tension / density) * k * k * k) * Math.tanh(k * depth));
11
+ }
12
+
13
+ export function wavenumberOf(frequency) {
14
+ const omega = 2 * Math.PI * frequency;
15
+ let low = 1;
16
+ let high = 20000;
17
+ for (let step = 0; step < 60; step++) {
18
+ const mid = (low + high) / 2;
19
+ if (omegaOf(mid) < omega) low = mid;
20
+ else high = mid;
21
+ }
22
+ return (low + high) / 2;
23
+ }
24
+
25
+ export function waveOf(frequency) {
26
+ const k = wavenumberOf(frequency);
27
+ const lambda = (2 * Math.PI) / k;
28
+ const speed = (2 * Math.PI * frequency) / k;
29
+ const h = 1e-3 * k;
30
+ const group = (omegaOf(k + h) - omegaOf(k - h)) / (2 * h);
31
+ const { viscosity, depth } = WATER;
32
+ const omega = 2 * Math.PI * frequency;
33
+ const damping = 2 * viscosity * k * k + (k * Math.sqrt((viscosity * omega) / 2)) / Math.sinh(2 * k * depth);
34
+ return { frequency, k, lambda, speed, group, damping, decay: damping / group };
35
+ }
36
+
37
+ export function nodalCount(spacing, lambda) {
38
+ return 2 * Math.floor(spacing / lambda + 0.5);
39
+ }
40
+
41
+ export function nodalVertices(spacing, lambda) {
42
+ const out = [];
43
+ for (let m = 0; (m + 0.5) * lambda < spacing; m++) {
44
+ out.push(((m + 0.5) * lambda) / 2, -((m + 0.5) * lambda) / 2);
45
+ }
46
+ return out.sort((a, b) => a - b);
47
+ }
48
+
49
+ export const magnificationOf = (zLamp, zPaper, zWater) => (zLamp - zPaper) / (zLamp - zWater);
50
+
51
+ export function causticOf(zLamp, zPaper, zWater, zFloor = zWater, zBed = zFloor) {
52
+ const n = WATER.index;
53
+ const bend = (zWater - zFloor) * (1 - 1 / n) + ((zFloor - zBed) * (n - 1)) / GLASS + (zBed - zPaper) * (n - 1);
54
+ return bend / magnificationOf(zLamp, zPaper, zWater);
55
+ }
56
+
57
+ export const amplitudeOf = (kMm) => SLOPE / kMm;
58
+
59
+ export const focusOf = (kMm, caustic) => caustic * amplitudeOf(kMm) * kMm * kMm;
60
+
61
+ export function stateOf(frequency, spacingMm, optics) {
62
+ const wave = waveOf(frequency);
63
+ const lambdaMm = wave.lambda * 1000;
64
+ const kMm = wave.k / 1000;
65
+ const amplitude = amplitudeOf(kMm);
66
+ return {
67
+ frequency,
68
+ spacing: spacingMm,
69
+ lambdaMm,
70
+ kMm,
71
+ speed: wave.speed,
72
+ group: wave.group,
73
+ decay: wave.decay / 1000,
74
+ nodal: nodalCount(spacingMm, lambdaMm),
75
+ strobe: frequency - BEAT,
76
+ amplitude,
77
+ focus: focusOf(kMm, optics.caustic),
78
+ projected: lambdaMm * optics.magnification,
79
+ };
80
+ }
81
+
82
+ export const readoutOf = (state) => `f ${state.frequency.toFixed(1)} Hz · λ ${(state.lambdaMm / 10).toFixed(2)} cm · d ${(state.spacing / 10).toFixed(1)} cm · ${state.nodal} nodal lines`;
83
+
84
+ export function wordsOf(state) {
85
+ return `${state.frequency.toFixed(1)} hertz, wavelength ${(state.lambdaMm / 10).toFixed(2)} centimetres, dippers ${(state.spacing / 10).toFixed(1)} centimetres apart, ${state.nodal} nodal lines`;
86
+ }
87
+
88
+ function clippedRunsOf(points, [x0, y0, x1, y1], project) {
89
+ const runs = [];
90
+ let run = [];
91
+ for (const point of points) {
92
+ if (point[0] >= x0 && point[0] <= x1 && point[1] >= y0 && point[1] <= y1) run.push(project(point));
93
+ else if (run.length) {
94
+ if (run.length > 1) runs.push(run);
95
+ run = [];
96
+ }
97
+ }
98
+ if (run.length > 1) runs.push(run);
99
+ return runs.map((points) => points.map(([x, y], index) => `${index ? "L" : "M"}${x.toFixed(1)} ${y.toFixed(1)}`).join("")).join("");
100
+ }
101
+
102
+ export function patternOf(state, { xs, inside, lamp, zWater, zPaper }, project, phase = 0) {
103
+ const lift = (lamp[2] - zPaper) / (lamp[2] - zWater);
104
+ const onPaper = ([x, y]) => project([lamp[0] + (x - lamp[0]) * lift, lamp[1] + (y - lamp[1]) * lift, zPaper]);
105
+ const half = state.spacing / 2;
106
+ const nodal = [];
107
+ for (const vertex of nodalVertices(state.spacing, state.lambdaMm)) {
108
+ const a = Math.abs(vertex);
109
+ const b = Math.sqrt(Math.max(half * half - a * a, 1e-6));
110
+ const points = [];
111
+ for (let index = 0; index <= 240; index++) {
112
+ const t = -4 + (8 * index) / 240;
113
+ points.push([xs + b * Math.sinh(t), Math.sign(vertex) * a * Math.cosh(t)]);
114
+ }
115
+ nodal.push(clippedRunsOf(points, inside, onPaper));
116
+ }
117
+ const crests = [];
118
+ for (const sy of [-half, half]) {
119
+ const reach = Math.max(...[inside[0], inside[2]].flatMap((x) => [inside[1], inside[3]].map((y) => Math.hypot(x - xs, y - sy))));
120
+ for (let r = state.lambdaMm * (1 + (((phase / (2 * Math.PI)) % 1) + 1) % 1); r < reach; r += state.lambdaMm) {
121
+ const points = [];
122
+ const steps = Math.max(24, Math.round(r * 1.2));
123
+ for (let index = 0; index <= steps; index++) {
124
+ const a = (index / steps) * 2 * Math.PI;
125
+ points.push([xs + r * Math.cos(a), sy + r * Math.sin(a)]);
126
+ }
127
+ crests.push(clippedRunsOf(points, inside, onPaper));
128
+ }
129
+ }
130
+ return { nodal: nodal.join(""), crests: crests.join("") };
131
+ }
@@ -0,0 +1,103 @@
1
+ .rt .iso-plate {
2
+ overflow: hidden;
3
+ }
4
+
5
+ .rt {
6
+ --rt-sheet: #1d1d1d;
7
+ --rt-tape: #232323;
8
+ }
9
+
10
+ .iso[data-theme="light"] .rt,
11
+ .rt[data-theme="light"] {
12
+ --rt-sheet: #ffffff;
13
+ --rt-tape: #f1f1ee;
14
+ }
15
+
16
+ .rt-stage {
17
+ position: relative;
18
+ touch-action: pan-y;
19
+ -webkit-tap-highlight-color: transparent;
20
+ user-select: none;
21
+ -webkit-user-select: none;
22
+ cursor: crosshair;
23
+ }
24
+
25
+ .rt-stage[data-gl] .rt-fallback {
26
+ display: none;
27
+ }
28
+
29
+ .rt-said {
30
+ position: absolute;
31
+ width: 1px;
32
+ height: 1px;
33
+ overflow: hidden;
34
+ clip-path: inset(50%);
35
+ white-space: nowrap;
36
+ }
37
+
38
+ .rt-stage:focus-visible {
39
+ outline: 1px solid var(--anatomy-muted);
40
+ outline-offset: 6px;
41
+ }
42
+
43
+ .rt-stage > svg,
44
+ .rt-stage > canvas {
45
+ display: block;
46
+ width: 100%;
47
+ height: auto;
48
+ }
49
+
50
+ .rt-stage > .rt-layer {
51
+ position: absolute;
52
+ inset: 0;
53
+ height: 100% !important;
54
+ pointer-events: none;
55
+ }
56
+
57
+ .iso:not([data-theme="light"]) .rt-paper-gl {
58
+ mix-blend-mode: screen;
59
+ }
60
+
61
+ .rt-sheet > .iso-fill {
62
+ fill: var(--rt-sheet);
63
+ }
64
+
65
+ .rt-tape > .iso-fill {
66
+ fill: var(--rt-tape);
67
+ }
68
+
69
+ .rt-water > .iso-fill {
70
+ fill: var(--anatomy-shade-2);
71
+ opacity: calc(0.7 * (1 - var(--rt-lamp, 0)));
72
+ }
73
+
74
+ .iso[data-theme="light"] .rt-stage[data-gl] .rt-water > .iso-fill,
75
+ .rt[data-theme="light"] .rt-stage[data-gl] .rt-water > .iso-fill {
76
+ opacity: 0;
77
+ }
78
+
79
+ .rt-lever {
80
+ stroke-width: 1.4;
81
+ }
82
+
83
+ @media (max-width: 560px) {
84
+ .rt .iso-plate {
85
+ padding: 48px 6px 70px;
86
+ }
87
+ }
88
+
89
+ @media (max-width: 560px) {
90
+ .rt-stage {
91
+ width: 118%;
92
+ margin: -8% -9% -4%;
93
+ }
94
+
95
+ .rt-stage:focus-visible {
96
+ outline: none;
97
+ }
98
+
99
+ .rt .iso-plate:has(.rt-stage:focus-visible) {
100
+ outline: 1px solid var(--anatomy-muted);
101
+ outline-offset: 4px;
102
+ }
103
+ }
@@ -0,0 +1,110 @@
1
+ import * as React from "react";
2
+ import { Dots, FaceText, Line, Solid } from "../../kit/react/draw";
3
+ import { BASE_ART, BOTTLE_ART, DECK_ART, LABEL, TRAY_ART } from "./geometry";
4
+ import { LiquidLive } from "./live";
5
+
6
+ function Lit({ id, children }: { id: string; children: React.ReactNode }) {
7
+ return (
8
+ <g data-part={id}>{children}</g>
9
+ );
10
+ }
11
+
12
+ const BACK = (
13
+ <g key="back">
14
+ <Lit id="frame">
15
+ <path className="iso-halo" d={BASE_ART.halo} />
16
+ {BASE_ART.feet.map((parts, index) => (
17
+ <g key={index}>
18
+ {parts.map((paths, piece) => (
19
+ <Solid key={piece} paths={paths} tone={piece ? "mid" : "lo"} crease="faint" />
20
+ ))}
21
+ </g>
22
+ ))}
23
+ <Solid paths={BASE_ART.slab} tone="mid" crease="faint" />
24
+ <Line d={BASE_ART.groove} tone="lo" />
25
+ <Line d={BASE_ART.inlay} tone="faint" />
26
+ <Line d={BASE_ART.screwRings} tone="lo" />
27
+ <Dots points={BASE_ART.screws} size={0.5} tone="mid" />
28
+ <Solid className="ml-plate" paths={TRAY_ART.slab} tone="hi" crease="lo" />
29
+ <Line d={TRAY_ART.groove} tone="lo" />
30
+ <Line d={TRAY_ART.inlay} tone="faint" />
31
+ {TRAY_ART.wells.map((well, index) => (
32
+ <g key={index}>
33
+ <path className="ml-floor" d={well.opening} />
34
+ {well.wall ? <path className="ml-wall" d={well.wall} /> : null}
35
+ <Line d={well.foot} tone="faint" />
36
+ <Line d={well.opening} tone="mid" />
37
+ </g>
38
+ ))}
39
+ <Dots points={TRAY_ART.counts} size={0.55} tone="mid" />
40
+ <Line d={TRAY_ART.screwRings} tone="lo" />
41
+ <Dots points={TRAY_ART.screws} size={0.5} tone="mid" />
42
+ </Lit>
43
+ <Lit id="apart">
44
+ <Line d={TRAY_ART.minor} tone="lo" />
45
+ <Line d={TRAY_ART.major} tone="mid" />
46
+ <Line d={TRAY_ART.datum} tone="mid" />
47
+ <Dots points={TRAY_ART.gapMarks} size={0.6} tone="hi" />
48
+ </Lit>
49
+ </g>
50
+ );
51
+
52
+ const DECK = (
53
+ <g key="deck">
54
+ <Lit id="frame">
55
+ <Solid paths={DECK_ART.slab} tone="mid" crease="faint" />
56
+ <Line d={DECK_ART.inlay} tone="faint" />
57
+ <Line d={DECK_ART.screwRings} tone="lo" />
58
+ <Dots points={DECK_ART.screws} size={0.45} tone="mid" />
59
+ <Solid paths={BOTTLE_ART.coaster} tone="mid" crease="faint" />
60
+ <Line d={BOTTLE_ART.coasterRing} tone="faint" />
61
+ <Dots points={BOTTLE_ART.coasterDots} size={0.45} tone="mid" />
62
+ <Solid className="ml-bottle" paths={BOTTLE_ART.body} tone="hi" crease="faint" />
63
+ <Line d={BOTTLE_ART.foot} tone="faint" />
64
+ <Line d={BOTTLE_ART.level} tone="lo" />
65
+ <Line d={BOTTLE_ART.shine} tone="mid" />
66
+ <Solid className="ml-bottle" paths={BOTTLE_ART.shoulder} tone="hi" crease="faint" />
67
+ <Solid paths={BOTTLE_ART.neck} tone="mid" crease="faint" />
68
+ <Solid paths={BOTTLE_ART.collar} tone="mid" crease="faint" />
69
+ <Solid paths={BOTTLE_ART.cap} tone="hi" crease="lo" />
70
+ <Line d={BOTTLE_ART.capKnurl} tone="lo" />
71
+ <Line d={BOTTLE_ART.capRing} tone="faint" />
72
+ <Solid paths={BOTTLE_ART.bulb} tone="mid" crease="faint" />
73
+ <Line d={BOTTLE_ART.bulbShine} tone="lo" />
74
+ <Line d={BOTTLE_ART.bulbRing} tone="faint" />
75
+ <Dots points={[BOTTLE_ART.tip]} size={0.45} tone="mid" />
76
+ </Lit>
77
+ <Lit id="fan">
78
+ <Line d={DECK_ART.guide} tone="faint" dashed />
79
+ {DECK_ART.stops.map((paths, index) => (
80
+ <Solid key={index} paths={paths} tone="mid" crease="faint" />
81
+ ))}
82
+ <Dots points={DECK_ART.stopTops} size={0.45} tone="hi" />
83
+ <Solid paths={DECK_ART.bandBack} tone="mid" crease="faint" />
84
+ <FaceText transform={DECK_ART.label} size={4.2} tone="lo">
85
+ merge
86
+ </FaceText>
87
+ <Solid paths={DECK_ART.washer} tone="lo" crease="faint" />
88
+ </Lit>
89
+ </g>
90
+ );
91
+
92
+ const FRONT = (
93
+ <Lit key="front" id="fan">
94
+ <Solid paths={DECK_ART.bandFront} tone="mid" crease="faint" />
95
+ <Line d={DECK_ART.bandLine} tone="faint" />
96
+ <Line d={DECK_ART.minor} tone="lo" />
97
+ <Line d={DECK_ART.major} tone="mid" />
98
+ <Dots points={DECK_ART.gapDots} size={0.55} tone="hi" />
99
+ <Dots points={[...DECK_ART.ends, DECK_ART.seam]} size={0.45} tone="mid" />
100
+ <Solid paths={DECK_ART.cap} tone="mid" crease="faint" />
101
+ <Solid paths={DECK_ART.nut} tone="hi" crease="lo" />
102
+ <Line d={DECK_ART.nutKnurl} tone="lo" />
103
+ <Line d={DECK_ART.nutRing} tone="faint" />
104
+ <Dots points={[DECK_ART.pin]} size={0.6} tone="hi" />
105
+ </Lit>
106
+ );
107
+
108
+ export function LiquidArt() {
109
+ return <LiquidLive label={LABEL} back={BACK} deck={DECK} front={FRONT} />;
110
+ }