/* * React Flow, routed through the design tokens. * * Scoped to `.react-flow` rather than added to index.css, so the canvas needs no * tokens of its own and follows the theme in both modes without a `colorMode` * prop. See the root DESIGN-GUIDELINES.md → Shells. */ .react-flow { --xy-background-color: var(--background); --xy-background-pattern-dots-color: color-mix( in srgb, var(--muted-foreground) 30%, transparent ); --xy-edge-stroke: color-mix( in srgb, var(--muted-foreground) 55%, transparent ); --xy-edge-stroke-selected: var(--primary); --xy-edge-stroke-width: 1.5; --xy-handle-background-color: var(--card); --xy-handle-border-color: var(--muted-foreground); --xy-selection-background-color: color-mix( in srgb, var(--primary) 8%, transparent ); --xy-selection-border: 1px solid var(--primary); --xy-attribution-background-color: transparent; } /* A message arriving lights its edge, then decays back to rest. */ @media (prefers-reduced-motion: no-preference) { .react-flow__edge-path.edge-live { animation: edge-pulse var(--duration-pulse) var(--ease-emphasized); } /* * Both ends are plain colours. The implied `to` would be the edge's resting * stroke, which is a `color-mix()` — and interpolating a hex against one of * those goes through oklab and leaves the gamut on the way, which turned * every pulse fluorescent yellow. Landing on `--muted-foreground` instead is * the same hue the edge rests in, so the last step back is invisible. */ @keyframes edge-pulse { from { stroke: var(--primary); stroke-width: 2.5; } to { stroke: var(--muted-foreground); stroke-width: var(--xy-edge-stroke-width); } } } /* A node that just published something says so, once, and settles. */ @media (prefers-reduced-motion: no-preference) { .node-pulse { position: absolute; inset: -3px; border-radius: inherit; border: 2px solid var(--primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 18%, transparent); pointer-events: none; animation: node-pulse var(--duration-pulse) var(--ease-emphasized) forwards; } @keyframes node-pulse { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(1.09); } } } /* Handles are neutral: the one brand-secondary affordance here is Run. */ .react-flow__handle { width: 12px; height: 12px; border-width: 2px; } .react-flow__handle.unbound { border-style: dashed; border-color: color-mix(in srgb, var(--muted-foreground) 40%, transparent); } .react-flow__handle-connecting { border-color: var(--primary); } .react-flow__node:focus-visible, .react-flow__node:focus { outline: none; } /* * Brain graph. Both ends of a connection sit at the neuron's centre, so an * edge runs straight from circle to circle and disappears under them. */ .brain-handle { opacity: 0; left: 50%; top: 50%; transform: translate(-50%, -50%); } .brain-cell { cursor: pointer; transition: border-color var(--duration-base) var(--ease-standard); } .brain-cell:hover { border-color: var(--primary); }