Skip to content

Commit b27e560

Browse files
committed
Intro diagrams refinements
1 parent 102ece0 commit b27e560

3 files changed

Lines changed: 214 additions & 14 deletions

File tree

website/src/components/VisualElements/AgentWorkStabilityDiagram.module.css

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
.pressure rect,
2424
.systemBoundary,
25-
.stabilizer rect,
25+
.stabilizer > rect,
2626
.loopStage rect {
2727
vector-effect: non-scaling-stroke;
2828
}
@@ -105,7 +105,7 @@ marker path[data-tone='warning'] {
105105
stroke-width: 1.5px;
106106
}
107107

108-
.stabilizer rect {
108+
.stabilizer > rect {
109109
fill: var(--surface-raised);
110110
stroke-width: 1px;
111111
}
@@ -118,22 +118,52 @@ marker path[data-tone='warning'] {
118118
letter-spacing: 0.03em;
119119
}
120120

121-
.stabilizer[data-tone='cyan'] rect {
121+
.stabilizer[data-tone='cyan'] > rect {
122122
fill: var(--visual-bg-cyan);
123123
stroke: var(--visual-cyan);
124124
}
125125

126-
.stabilizer[data-tone='indigo'] rect {
126+
.stabilizer[data-tone='indigo'] > rect {
127127
fill: var(--visual-bg-indigo);
128128
stroke: var(--visual-indigo);
129129
}
130130

131-
.stabilizer[data-tone='success'] rect {
131+
.stabilizer[data-tone='success'] > rect {
132132
fill: var(--visual-bg-success);
133133
stroke: var(--visual-success);
134134
}
135135

136-
.loop path {
136+
.stabilizerMotion {
137+
pointer-events: none;
138+
}
139+
140+
.stabilizerOutline,
141+
.stabilizerPing {
142+
fill: none;
143+
vector-effect: non-scaling-stroke;
144+
}
145+
146+
.stabilizerOutline {
147+
stroke-width: 2px;
148+
}
149+
150+
.stabilizerPing {
151+
stroke-width: 1.5px;
152+
}
153+
154+
.stabilizerMotion[data-tone='cyan'] rect {
155+
stroke: var(--visual-cyan);
156+
}
157+
158+
.stabilizerMotion[data-tone='indigo'] rect {
159+
stroke: var(--visual-indigo);
160+
}
161+
162+
.stabilizerMotion[data-tone='success'] rect {
163+
stroke: var(--visual-success);
164+
}
165+
166+
.loop > path {
137167
fill: none;
138168
stroke: var(--border-emphasis);
139169
stroke-width: 1.5px;
@@ -167,6 +197,12 @@ marker path[data-tone='warning'] {
167197
font-weight: 400;
168198
}
169199

200+
@media (prefers-reduced-motion: reduce) {
201+
.stabilizerMotion {
202+
display: none;
203+
}
204+
}
205+
170206
@container (max-width: 36rem) {
171207
.desktop {
172208
display: none;

website/src/components/VisualElements/AgentWorkStabilityDiagram.tsx

Lines changed: 171 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22

3+
import { AnimatedTokenTrain } from './AnimatedTokenFlow';
34
import { EmojiImage } from './ActorNodes';
45
import { EMOJI, type EmojiAsset } from './emojiAssets';
56
import {
@@ -8,6 +9,7 @@ import {
89
ModelCallFrame,
910
} from './ModelCallFrame';
1011
import { TILE_GRID } from './diagramTileLayout';
12+
import { seededTokenTrain } from './TokenTrainSequence';
1113
import styles from './AgentWorkStabilityDiagram.module.css';
1214

1315
type Tone = 'violet' | 'indigo' | 'cyan' | 'warning' | 'success';
@@ -34,6 +36,25 @@ const MOBILE_FRAME = { x: 16, y: 160, width: 308, height: 352 };
3436
const DESKTOP_TAB_WIDTH = 216;
3537
const MOBILE_TAB_WIDTH = 212;
3638
const PRESSURE_ARROW_GRID = TILE_GRID;
39+
const STABILIZER_HEIGHT = 24;
40+
const WORKING_CONTEXT_OFFSET = 80;
41+
const EVIDENCE_OFFSET = { desktop: 240, mobile: 272 } as const;
42+
const LOOP_STAGE_HEIGHT = 32;
43+
const LOOP_STAGE_STEP = 40;
44+
const LOOP_VISUAL_HEIGHT = LOOP_STAGE_STEP * 2 + LOOP_STAGE_HEIGHT;
45+
const CONTROLLED_RUN_DURATION = '9.6s';
46+
const CONTROLLED_RUN_TIMING = {
47+
cycleMs: 9600,
48+
travelMs: 7600,
49+
fadeMs: 900,
50+
repeat: 'loop',
51+
} as const;
52+
const CONTROLLED_RUN_STAGGER = { mode: 'pathSpacing', spacingPx: 32 } as const;
53+
const CONTROLLED_RUN_TOKENS = seededTokenTrain('agent-work-stability-loop', 4);
54+
55+
// Motion spec — A token train repeats Plan → Act → Observe → Verify on the actual loop
56+
// connectors. Stabilizer pings mark their control points; all moving elements disappear
57+
// under reduced motion, where this complete static diagram is canonical.
3758

3859
type WorkFrameGeometry = {
3960
frame: ModelCallFrameBounds;
@@ -294,54 +315,160 @@ function Stabilizers({
294315
width={cardWidth}
295316
label="EXPLICIT BOUNDARIES"
296317
tone="cyan"
318+
motion="boundaries"
297319
icon={EMOJI.compass}
298320
/>
299321
<Stabilizer
300322
x={cardX}
301-
y={y + 80}
323+
y={y + WORKING_CONTEXT_OFFSET}
302324
width={cardWidth}
303325
label="WORKING CONTEXT"
304326
tone="indigo"
327+
motion="context"
305328
icon={EMOJI.books}
306329
/>
307330
<Stabilizer
308331
x={cardX}
309-
y={compact ? y + 272 : y + 240}
332+
y={evidenceStabilizerY(y, compact)}
310333
width={cardWidth}
311334
label="INDEPENDENT EVIDENCE"
312335
tone="success"
336+
motion="evidence"
313337
icon={EMOJI.check}
314338
/>
315339
</>
316340
);
317341
}
318342

343+
type StabilizerMotion = 'boundaries' | 'context' | 'evidence';
344+
345+
type StabilizerMotionTiming = {
346+
outlineTimes: string;
347+
outlineValues: string;
348+
pingTimes: string;
349+
};
350+
351+
const STABILIZER_MOTION: Record<StabilizerMotion, StabilizerMotionTiming> = {
352+
boundaries: {
353+
outlineTimes: '0;0.02;0.12;0.16;1',
354+
outlineValues: '0;1;1;0;0',
355+
pingTimes: '0;0.02;0.06;1',
356+
},
357+
context: {
358+
outlineTimes: '0;0.22;0.27;0.61;0.66;1',
359+
outlineValues: '0;0;1;1;0;0',
360+
pingTimes: '0;0.22;0.26;1',
361+
},
362+
evidence: {
363+
outlineTimes: '0;0.72;0.77;0.85;0.90;1',
364+
outlineValues: '0;0;1;1;0;0',
365+
pingTimes: '0;0.72;0.76;1',
366+
},
367+
};
368+
319369
function Stabilizer({
320370
x,
321371
y,
322372
width,
323373
label,
324374
tone,
375+
motion,
325376
icon,
326377
}: {
327378
x: number;
328379
y: number;
329380
width: number;
330381
label: string;
331382
tone: Tone;
383+
motion: StabilizerMotion;
332384
icon: EmojiAsset;
333385
}) {
334386
return (
335387
<g className={styles.stabilizer} data-tone={tone}>
336-
<rect x={x} y={y} width={width} height={24} rx={0} />
388+
<rect x={x} y={y} width={width} height={STABILIZER_HEIGHT} rx={0} />
337389
<EmojiImage asset={icon} x={x + 8} y={y + 4} size={16} />
338390
<text x={x + 32} y={y + 16} textAnchor="start">
339391
{label}
340392
</text>
393+
<StabilizerSignal x={x} y={y} width={width} tone={tone} motion={motion} />
394+
</g>
395+
);
396+
}
397+
398+
function StabilizerSignal({
399+
x,
400+
y,
401+
width,
402+
tone,
403+
motion,
404+
}: {
405+
x: number;
406+
y: number;
407+
width: number;
408+
tone: Tone;
409+
motion: StabilizerMotion;
410+
}) {
411+
const timing = STABILIZER_MOTION[motion];
412+
return (
413+
<g
414+
className={styles.stabilizerMotion}
415+
data-tone={tone}
416+
transform={`translate(${x + width / 2} ${y + 12})`}
417+
>
418+
<rect
419+
className={styles.stabilizerOutline}
420+
x={-width / 2 - 4}
421+
y={-16}
422+
width={width + 8}
423+
height={32}
424+
opacity="0"
425+
>
426+
<animate
427+
attributeName="opacity"
428+
dur={CONTROLLED_RUN_DURATION}
429+
repeatCount="indefinite"
430+
values={timing.outlineValues}
431+
keyTimes={timing.outlineTimes}
432+
/>
433+
</rect>
434+
<rect
435+
className={styles.stabilizerPing}
436+
x={-width / 2 - 4}
437+
y={-16}
438+
width={width + 8}
439+
height={32}
440+
opacity="0"
441+
>
442+
<animate
443+
attributeName="opacity"
444+
dur={CONTROLLED_RUN_DURATION}
445+
repeatCount="indefinite"
446+
values="0;0.8;0;0"
447+
keyTimes={timing.pingTimes}
448+
/>
449+
<animateTransform
450+
attributeName="transform"
451+
type="scale"
452+
dur={CONTROLLED_RUN_DURATION}
453+
repeatCount="indefinite"
454+
values="1;1;1.12;1.12"
455+
keyTimes={timing.pingTimes}
456+
/>
457+
</rect>
341458
</g>
342459
);
343460
}
344461

462+
function evidenceStabilizerY(y: number, compact: boolean) {
463+
return y + EVIDENCE_OFFSET[compact ? 'mobile' : 'desktop'];
464+
}
465+
466+
function centeredLoopTop(y: number, compact: boolean) {
467+
const contextBottom = y + WORKING_CONTEXT_OFFSET + STABILIZER_HEIGHT;
468+
const evidenceTop = evidenceStabilizerY(y, compact);
469+
return contextBottom + (evidenceTop - contextBottom - LOOP_VISUAL_HEIGHT) / 2;
470+
}
471+
345472
function AgentLoop({
346473
x,
347474
y,
@@ -354,12 +481,21 @@ function AgentLoop({
354481
compact: boolean;
355482
}) {
356483
const center = x + width / 2;
357-
const top = compact ? y + 136 : y + 120;
358-
const side = top + 40;
359-
const bottom = top + 80;
484+
const top = centeredLoopTop(y, compact);
485+
const side = top + LOOP_STAGE_STEP;
486+
const bottom = top + LOOP_STAGE_STEP * 2;
360487
const sideWidth = compact ? 80 : 96;
361488
const left = x + 24;
362489
const right = x + width - sideWidth - 24;
490+
const trainPath = loopTrainPath(
491+
center,
492+
top,
493+
side,
494+
bottom,
495+
left,
496+
right,
497+
sideWidth
498+
);
363499
return (
364500
<g className={styles.loop}>
365501
<LoopPath
@@ -374,6 +510,14 @@ function AgentLoop({
374510
<LoopPath
375511
d={`M ${left} ${side + 16} H ${left + 16} V ${top + 16} H ${center - 48}`}
376512
/>
513+
<AnimatedTokenTrain
514+
pathD={trainPath}
515+
tokens={CONTROLLED_RUN_TOKENS}
516+
timing={CONTROLLED_RUN_TIMING}
517+
stagger={CONTROLLED_RUN_STAGGER}
518+
size={16}
519+
tone="violet"
520+
/>
377521
<LoopStage
378522
x={center - 48}
379523
y={top}
@@ -404,6 +548,26 @@ function AgentLoop({
404548
);
405549
}
406550

551+
function loopTrainPath(
552+
center: number,
553+
top: number,
554+
side: number,
555+
bottom: number,
556+
left: number,
557+
right: number,
558+
sideWidth: number
559+
) {
560+
const planY = top + 16;
561+
const sideY = side + 16;
562+
const observeY = bottom + 16;
563+
return [
564+
`M ${center} ${planY} H ${right - 16} V ${sideY} H ${right + sideWidth}`,
565+
`H ${right + sideWidth - 16} V ${observeY} H ${center - 48}`,
566+
`H ${left + sideWidth + 16} V ${sideY} H ${left}`,
567+
`H ${left + 16} V ${planY} H ${center}`,
568+
].join(' ');
569+
}
570+
407571
function LoopPath({ d }: { d: string }) {
408572
return <path d={d} markerEnd="url(#loop-arrow)" />;
409573
}
@@ -423,7 +587,7 @@ function LoopStage({
423587
}) {
424588
return (
425589
<g className={styles.loopStage}>
426-
<rect x={x} y={y} width={width} height={32} rx={0} />
590+
<rect x={x} y={y} width={width} height={LOOP_STAGE_HEIGHT} rx={0} />
427591
<EmojiImage asset={icon} x={x + 8} y={y + 8} size={16} />
428592
<text x={x + 30} y={y + 21} textAnchor="start">
429593
{label}

website/src/components/VisualElements/OperatorTransformationDiagram.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ function WorkingScene({
376376
width={width - 32}
377377
height={GATE_HEIGHT}
378378
rx={0}
379-
fill="var(--surface-raised)"
379+
fill="var(--visual-bg-cyan)"
380380
stroke="var(--visual-system)"
381381
strokeWidth={1}
382382
/>

0 commit comments

Comments
 (0)