diff --git a/frontend/src/lib/cybersigil.ts b/frontend/src/lib/cybersigil.ts index 200eb14..44c4590 100644 --- a/frontend/src/lib/cybersigil.ts +++ b/frontend/src/lib/cybersigil.ts @@ -207,6 +207,9 @@ export function buildCybersigil(opts: SigilOptions = {}): string { spinePts.push([x, y]); } emit(spline(spinePts, 5), 'cs-sig-main cs-sig-spine'); + // ── Chromatic Aberration: two faint, offset echoes of the spine + emit(spline(spinePts.map(([x, y]) => [x - 1.5, y] as Pt), 5), 'cs-sig-spine-ab cs-sig-spine-ab--1'); + emit(spline(spinePts.map(([x, y]) => [x + 1.5, y] as Pt), 5), 'cs-sig-spine-ab cs-sig-spine-ab--2'); // terminal ornaments on the spine itself (anchors the design) ornament(spinePts[0], -Math.PI / 2, 1.1); @@ -215,6 +218,7 @@ export function buildCybersigil(opts: SigilOptions = {}): string { // ── Branch nodes ride the spine and throw limbs outward. const nodes = opts.count ?? 8 + Math.floor(rng() * 4); // 8–11 const tangleIdx = rng() < 0.7 ? 1 + Math.floor(rng() * (nodes - 2)) : -1; + const nodePoints: Pt[] = []; for (let i = 0; i < nodes; i++) { const isTangle = i === tangleIdx; @@ -225,6 +229,7 @@ export function buildCybersigil(opts: SigilOptions = {}): string { const a = spinePts[si]; const b = spinePts[si + 1]; const node: Pt = [a[0] + (b[0] - a[0]) * sf, a[1] + (b[1] - a[1]) * sf]; + nodePoints.push(node); const bias = -0.3 + tc * 0.8; const limbs = (1 + Math.floor(rng() * 2)) * (isTangle ? 2 : 1); @@ -242,6 +247,15 @@ export function buildCybersigil(opts: SigilOptions = {}): string { } } + // ── Technical Connectors: sparse, straight circuit lines + const numConnectors = 1 + Math.floor(rng() * 3); + for (let i = 0; i < numConnectors; i++) { + const n1 = pick(nodePoints); + const n2 = pick(nodePoints); + if (n1 === n2) continue; + emit(`M${n(n1[0])} ${n(n1[1])} L${n(n2[0])} ${n(n2[1])}`, 'cs-sig-connect'); + } + const half = parts.join(''); const minX = -(maxX + PAD); const vbW = 2 * (maxX + PAD); diff --git a/frontend/src/styles/partials/70-cybersigil.css b/frontend/src/styles/partials/70-cybersigil.css index a45156d..536d612 100644 --- a/frontend/src/styles/partials/70-cybersigil.css +++ b/frontend/src/styles/partials/70-cybersigil.css @@ -205,6 +205,14 @@ html.cybersigil body::after { width: 100%; height: 100%; overflow: visible; + animation: cs-jitter 12s step-end infinite; +} +@keyframes cs-jitter { + 0%, 95% { transform: translate(0,0) scale(1); } + 96% { transform: translate(-2px, 1px) scale(1.01); } + 97% { transform: translate(3px, -2px) rotate(0.5deg); } + 98% { transform: translate(-1px, 2px); } + 99% { transform: translate(0,0); } } .cybersigil .cs-sigil path { fill: none; @@ -216,6 +224,23 @@ html.cybersigil body::after { stroke-dasharray: 1; stroke-dashoffset: 1; } +/* Aberration Echoes */ +.cybersigil .cs-sig-spine-ab { + stroke-width: 0.8; + opacity: 0.4; + mix-blend-mode: screen; +} +.cybersigil .cs-sig-spine-ab--1 { stroke: var(--mauve); } +.cybersigil .cs-sig-spine-ab--2 { stroke: var(--teal); } + +/* Technical Connectors */ +.cybersigil .cs-sig-connect { + stroke: var(--sky); + stroke-width: 0.4; + stroke-dasharray: 4 2; + opacity: 0.6; +} + /* Stroke-weight tiers — heavy growth, hair filaments, prickly barbs, motifs. */ .cybersigil .cs-sigil .cs-sig-main { stroke-width: 2.8; } .cybersigil .cs-sigil .cs-sig-spine {