2026-02-19T12-37-24_auto_memory/memories.db-shm, memory/memories.db-wal, me
This commit is contained in:
parent
043b32060b
commit
a4de8f409a
@ -1413,3 +1413,15 @@
|
||||
{"timestamp":"2026-02-19T12:32:12.315Z","level":"info","category":"watcher","message":"File added","data":{"path":"/home/nicholai/.agents/memory/memories.db-wal"}}
|
||||
{"timestamp":"2026-02-19T12:32:12.317Z","level":"info","category":"watcher","message":"File changed","data":{"path":"/home/nicholai/.agents/memory/memories.db-wal"}}
|
||||
{"timestamp":"2026-02-19T12:32:12.327Z","level":"info","category":"watcher","message":"File changed","data":{"path":"/home/nicholai/.agents/memory/memories.db"}}
|
||||
{"timestamp":"2026-02-19T12:32:17.330Z","level":"warn","category":"git","message":"Git add failed"}
|
||||
{"timestamp":"2026-02-19T12:32:17.509Z","level":"info","category":"git","message":"Auto-committed","data":{"message":"2026-02-19T12-32-17_auto_memory/memories.db-shm, memory/memories.db-wal, me","filesChanged":4}}
|
||||
{"timestamp":"2026-02-19T12:33:17.933Z","level":"info","category":"git","message":"Git push","data":{"commits":4}}
|
||||
{"timestamp":"2026-02-19T12:37:12.019Z","level":"warn","category":"git","message":"Periodic sync failed: No git credentials found. Run `gh auth login` or set GITHUB_TOKEN secret."}
|
||||
{"timestamp":"2026-02-19T12:37:19.528Z","level":"info","category":"watcher","message":"File added","data":{"path":"/home/nicholai/.agents/memory/memories.db-shm"}}
|
||||
{"timestamp":"2026-02-19T12:37:19.528Z","level":"info","category":"watcher","message":"File added","data":{"path":"/home/nicholai/.agents/memory/memories.db-wal"}}
|
||||
{"timestamp":"2026-02-19T12:37:19.530Z","level":"info","category":"watcher","message":"File changed","data":{"path":"/home/nicholai/.agents/memory/memories.db-wal"}}
|
||||
{"timestamp":"2026-02-19T12:37:19.546Z","level":"info","category":"watcher","message":"File changed","data":{"path":"/home/nicholai/.agents/memory/memories.db"}}
|
||||
{"timestamp":"2026-02-19T12:37:19.528Z","level":"info","category":"watcher","message":"File added","data":{"path":"/home/nicholai/.agents/memory/memories.db-shm"}}
|
||||
{"timestamp":"2026-02-19T12:37:19.528Z","level":"info","category":"watcher","message":"File added","data":{"path":"/home/nicholai/.agents/memory/memories.db-wal"}}
|
||||
{"timestamp":"2026-02-19T12:37:19.530Z","level":"info","category":"watcher","message":"File changed","data":{"path":"/home/nicholai/.agents/memory/memories.db-wal"}}
|
||||
{"timestamp":"2026-02-19T12:37:19.546Z","level":"info","category":"watcher","message":"File changed","data":{"path":"/home/nicholai/.agents/memory/memories.db"}}
|
||||
|
||||
Binary file not shown.
@ -12,6 +12,8 @@ description: >
|
||||
|
||||
# Signet Design System
|
||||
|
||||
See `assets/design-brief.png` for a full-page reference screenshot.
|
||||
|
||||
## Aesthetic Direction
|
||||
|
||||
Technical. Industrial. Near-monochrome. The visual language draws from
|
||||
@ -29,6 +31,34 @@ Core principles:
|
||||
- **Registration marks** — crosshair (+) elements as visual punctuation
|
||||
- **Generative texture** — Bayer-dithered halftone art as bold compositional elements
|
||||
- **Dual theme** — dark (near-black) and light (warm beige cream)
|
||||
- **Background opacity 0.8** — all overlay elements (connectors, nodes,
|
||||
schematic circles) sit at 80% opacity to recede behind content
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
These violate the design system. Never do:
|
||||
- **Border-radius** — no rounded corners, no pills, no circles on
|
||||
containers. Only exception: schematic decorator circles.
|
||||
- **Filled buttons at rest** — buttons are always outlined, fill only
|
||||
on hover (invert).
|
||||
- **Generic fonts** — no Inter, Roboto, Arial, system-ui. Only Chakra
|
||||
Petch and IBM Plex Mono.
|
||||
- **Serif fonts** — never. Too editorial, too warm.
|
||||
- **Saturated color** — no bright blues, greens, purples. The palette
|
||||
is desaturated gray with muted danger/success accents only.
|
||||
- **Purple gradients** — the quintessential AI slop aesthetic. Banned.
|
||||
- **Soft/friendly UI** — no rounded icons, no emoji glyphs, no pastel
|
||||
tones, no bouncy animations.
|
||||
- **Opacity on muted text** — use `--color-text-muted` directly,
|
||||
never layer `opacity: 0.5` on top of already-muted colors.
|
||||
- **Pure white backgrounds** — light theme uses warm beige `#e4dfd8`,
|
||||
never `#ffffff`.
|
||||
- **Single-font hierarchy** — always pair display + mono. Using one
|
||||
font for everything flattens the hierarchy.
|
||||
- **Attention-grabbing animation** — no bounce, no scale-up entrances,
|
||||
no flash effects. Ambient only.
|
||||
- **S-curves or multi-inflection connector lines** — connectors use
|
||||
single-curve quadratic beziers. Never cubic with two control points.
|
||||
|
||||
## Typography
|
||||
|
||||
@ -56,10 +86,6 @@ CSS variables:
|
||||
--font-mono: 'IBM Plex Mono', monospace;
|
||||
```
|
||||
|
||||
Anti-patterns: using a single font for everything (lacks hierarchy),
|
||||
serif fonts, generic sans (Inter, Roboto, Arial), any font that
|
||||
feels too polished for the raw industrial aesthetic.
|
||||
|
||||
## Design Tokens
|
||||
|
||||
See `assets/globals.css` for the full token set. All tokens use CSS
|
||||
@ -89,8 +115,7 @@ Light background is warm beige, never pure white. Borders flip from
|
||||
white-alpha to black-alpha. Dither dots flip color via `--color-dither`.
|
||||
|
||||
Readability: light mode `--color-text-muted` must be dark enough for
|
||||
legible text on the beige surface (~3.5:1 contrast min). Avoid
|
||||
layering opacity on top of muted-colored text — use the token directly.
|
||||
legible text on the beige surface (~3.5:1 contrast min).
|
||||
|
||||
## Icon System
|
||||
|
||||
@ -151,17 +176,92 @@ Stroked containers with monospace text. `.badge-accent` variant
|
||||
uses bright text + bright border. Can include inline icons.
|
||||
|
||||
### Inputs
|
||||
Monospace, surface background, strong border. Focus brightens border.
|
||||
Select uses custom SVG chevron background-image.
|
||||
Monospace, surface background, strong border. Focus brightens border
|
||||
and adds 1px `box-shadow` ring. Select uses custom SVG chevron
|
||||
background-image. `border-radius: 0` always.
|
||||
|
||||
### Section Panels
|
||||
Content sections wrap in `.section-panel` — `--color-surface` bg,
|
||||
`--color-border` stroke, 6px corner L-bracket registration marks
|
||||
via `::before`/`::after`. Elevates content above the background
|
||||
layers.
|
||||
|
||||
### Decorative Elements
|
||||
- Crosshair marks (`.crosshair`) — 10px, muted
|
||||
- Crosshair marks (`.crosshair`) — 10px, muted color
|
||||
- 4-pointed star (`.star-4`) — clip-path polygon
|
||||
- Schematic circles — stroked circles with centered crosshairs
|
||||
- Connector lines — 1px lines with dot endpoints
|
||||
- Corner star markers (`****`)
|
||||
- Schematic circles — stroked circles with centered crosshairs,
|
||||
`opacity: 0.8`, `node-pulse` animation
|
||||
- Corner star markers (`****`) — mono text, positioned absolute
|
||||
- Vertical sidebar text (`writing-mode: vertical-rl`)
|
||||
- Numbered index grids (00–23 in 8-column grid)
|
||||
- Inverted labels (`.label-inv`) — bright bg, dark text, no radius
|
||||
|
||||
## Embedding Graph Overlay
|
||||
|
||||
A background layer of interconnected crosshair nodes arranged as
|
||||
an embedding/vector-space visualization. Inspired by Detroit
|
||||
Underground record sleeve schematics.
|
||||
|
||||
### Node Layout
|
||||
16 crosshair nodes (`#ch-0` through `#ch-15`) in 4 clusters plus
|
||||
outliers, positioned with `position: absolute` percentages:
|
||||
|
||||
- **Cluster A** (upper-left, near `#sc-1`): ch-0 through ch-3
|
||||
- **Cluster B** (upper-right, sparse): ch-4, ch-5
|
||||
- **Cluster C** (mid-left, near `#sc-2`): ch-6 through ch-8
|
||||
- **Cluster D** (lower region): ch-9 through ch-12
|
||||
- **Outliers**: ch-13, ch-14, ch-15 (bridge nodes between clusters)
|
||||
|
||||
3 hub nodes as larger schematic circles (`#sc-1`, `#sc-2`, `#sc-3`)
|
||||
with crosshair pseudo-elements and `node-pulse` animation.
|
||||
3 star markers (`#sm-1`, `#sm-2`, `#sm-3`) as `****` text.
|
||||
|
||||
### Edge Topology
|
||||
Edges defined as `[fromId, toId, style, label?]` array:
|
||||
- **Intra-cluster** — short connections within each cluster
|
||||
- **Inter-cluster bridges** — longer connections between clusters,
|
||||
labeled with embedding metrics (`cos=0.74`, `d=0.12`)
|
||||
- **Hub connections** — edges from crosshair nodes to schematic
|
||||
circles and star markers
|
||||
|
||||
### Connector Rendering
|
||||
JS-drawn SVG overlay. On load (and resize), reads
|
||||
`getBoundingClientRect` centers of all nodes, then draws
|
||||
**quadratic bezier curves** (`Q` command) between them:
|
||||
|
||||
```js
|
||||
const dx = b.x - a.x, dy = b.y - a.y;
|
||||
const mx = (a.x + b.x) / 2 + dy * 0.12;
|
||||
const my = (a.y + b.y) / 2 - dx * 0.12;
|
||||
path.setAttribute('d', `M ${a.x},${a.y} Q ${mx},${my} ${b.x},${b.y}`);
|
||||
```
|
||||
|
||||
Single control point offset 12% perpendicular from the midpoint.
|
||||
This produces exactly one gentle arc per line — never S-curves.
|
||||
|
||||
Connector styles:
|
||||
- `conn-dashed` — `stroke-dasharray: 6 4`, animated `dash-flow` 12s
|
||||
- `conn-dashed-rev` — same dash, reverse direction 15s
|
||||
- `conn-dot` — 2px filled circles at each endpoint
|
||||
- `conn-label` — 7px mono text near midpoint (`d=0.12`, `cos=0.74`)
|
||||
- All connectors render at `opacity: 0.8` base
|
||||
|
||||
### Node Hover Interaction
|
||||
Crosshair nodes have `pointer-events: auto` (rest of the field is
|
||||
`pointer-events: none`). On hover:
|
||||
|
||||
1. **Crosshair expansion** — `::before`/`::after` pseudo-elements
|
||||
scale 1.8x on their respective axes, color brightens to
|
||||
`--color-text`
|
||||
2. **SLOT label** — `SLOT_XX` micro-tooltip appears above node.
|
||||
6px mono text, bordered container with `--color-bg` background
|
||||
3. **Ring pulse** — circular ring (`.ch-ring`) scales from 0.6 to
|
||||
1.0 and fades in at 50% opacity around the node
|
||||
4. **Connected edge highlight** — JS builds adjacency map from
|
||||
edge list. On hover, all SVG elements belonging to connected
|
||||
edges get `.conn-highlight` class: stroke brightens to
|
||||
`--color-text`, width increases to 1.5px, dots/labels brighten
|
||||
5. **On mouseleave** — all `.conn-highlight` classes removed
|
||||
|
||||
## Generative Art
|
||||
|
||||
@ -180,29 +280,29 @@ Use `--color-dither` so canvases adapt to theme.
|
||||
|
||||
## Depth & Layering
|
||||
|
||||
The design uses multiple overlapping layers to create spatial depth,
|
||||
inspired by flight terminal / CRT interface aesthetics:
|
||||
Multiple overlapping layers create spatial depth, inspired by
|
||||
flight terminal / CRT interface aesthetics:
|
||||
|
||||
1. **SVG noise grain** — `body::before`, fixed, z-index 9999 (0.04/0.06 opacity)
|
||||
2. **Bleed typography** — massive text (12–20rem) bleeding off viewport edges,
|
||||
2.5% opacity, `--font-display`, provides subliminal brand reinforcement
|
||||
3. **Floating panels** — 4–6 translucent rectangles (`--color-surface` and
|
||||
`--color-surface-raised`) at 15–50% opacity, positioned at various
|
||||
depths around the viewport. Creates the layered glass-panel effect.
|
||||
4. **Metadata fragments** — scattered timestamps, coordinates, version codes,
|
||||
reference numbers in 7px mono text at 35% opacity. Both functional
|
||||
texture and information-density signifier.
|
||||
5. **Schematic overlay** — circles with crosshairs, connector lines, star markers
|
||||
6. **Crosshair field** — repeating + marks at very low opacity
|
||||
1. **SVG noise grain** — `body::before`, fixed, z-index 9999
|
||||
(0.04/0.06 opacity)
|
||||
2. **Bleed typography** — massive text (12–20rem) bleeding off
|
||||
viewport edges, 2.5% opacity, `--font-display`
|
||||
3. **Floating panels** — 4–6 translucent rectangles at 15–50%
|
||||
opacity, drifting ±3–4px over 40–65s cycles
|
||||
4. **Metadata fragments** — scattered timestamps, coordinates,
|
||||
version codes in 7px mono text at 35% opacity
|
||||
5. **Embedding graph** — crosshair nodes + quadratic bezier
|
||||
connectors at 80% opacity (see section above)
|
||||
6. **Schematic overlay** — circles with crosshairs, star markers
|
||||
7. **Right edge dither** — 240px canvas strip, organic noise
|
||||
8. **Section panels** — content wrapped in `--color-surface` panels with
|
||||
corner registration marks (6px L-brackets). Elevates content above
|
||||
the background layers.
|
||||
8. **Section panels** — content wrapped in `--color-surface`
|
||||
panels with corner registration marks
|
||||
|
||||
## Animation & Interaction
|
||||
|
||||
All animations are subtle and ambient — never attention-grabbing. The
|
||||
goal is to create the feeling of a live, breathing system dashboard.
|
||||
All animations are subtle and ambient — never attention-grabbing.
|
||||
The goal is to create the feeling of a live, breathing system
|
||||
dashboard.
|
||||
|
||||
### Ambient (CSS keyframes)
|
||||
- **Floating panel drift** — `fp-drift` 40–65s ease-in-out infinite
|
||||
@ -210,33 +310,33 @@ goal is to create the feeling of a live, breathing system dashboard.
|
||||
- **Metadata flicker** — `mf-flicker` 7–15s. Brief opacity dip to
|
||||
simulate data refresh. Stagger child delays.
|
||||
- **SVG connector dash flow** — `dash-flow` / `dash-flow-rev` on
|
||||
`stroke-dasharray: 6 4` paths, 12–15s linear infinite. Dashed
|
||||
bezier curves and straight lines with endpoint dots.
|
||||
`stroke-dasharray: 6 4` paths, 12–15s linear infinite.
|
||||
- **Schematic node pulse** — `node-pulse` 5–8s, scale 1→1.04 and
|
||||
opacity 1→0.7 on circles with crosshairs.
|
||||
opacity 1→0.7 on hub circles with crosshairs.
|
||||
- **Scan line sweep** — 1px horizontal gradient line sweeps top to
|
||||
bottom every 15–25s at 0.06 opacity. Triggered via JS setTimeout.
|
||||
|
||||
### Interactive (JS + CSS transitions)
|
||||
- **Scroll reveal** — `.reveal` class, `IntersectionObserver` with
|
||||
`threshold: 0.08`. Fade+translateY(12px→0), 0.6s ease-out. Above-fold
|
||||
elements stagger with 80ms delay increments.
|
||||
- **Cursor coordinates** — fixed `div` follows mouse, shows `x: # y: #`
|
||||
in 7px mono, fades to 0 after 2s idle.
|
||||
- **Icon hover coordinates** — CV-debug-style `x:### y:###` label at
|
||||
top-right of icon cells, green color (`--color-success`), fades in
|
||||
on hover. Icon SVGs scale 1.12x.
|
||||
`threshold: 0.08`. Fade+translateY(12px→0), 0.6s ease-out.
|
||||
Above-fold elements stagger with 80ms delay increments.
|
||||
- **Cursor coordinates** — fixed `div` follows mouse, shows
|
||||
`x: # y: #` in 7px mono, fades to 0 after 2s idle.
|
||||
- **Node hover** — crosshair expansion + ring pulse + SLOT label +
|
||||
connected edge highlighting (see Embedding Graph section).
|
||||
- **Icon hover coordinates** — CV-debug-style `x:### y:###` label
|
||||
at top-right of icon cells, green color (`--color-success`),
|
||||
fades in on hover. Icon SVGs scale 1.12x.
|
||||
- **Swatch hover** — scale 1.08x with 1px outline ring.
|
||||
- **Input focus glow** — 1px `box-shadow` ring on focus.
|
||||
|
||||
### SVG Connector Overlay
|
||||
JS-drawn SVG layer. On load (and resize), reads `getBoundingClientRect`
|
||||
centers of schematic circles (`#sc-*`), crosshairs (`#ch-*`), and
|
||||
star markers (`#sm-*`), then draws cubic bezier curves between them
|
||||
with endpoint dots and slot/pass labels. This ensures connectors
|
||||
always attach to real background elements. Edges defined as
|
||||
`[fromId, toId, style, label?]` array. Uses `conn-dashed` /
|
||||
`conn-dashed-rev` classes for animated `stroke-dashoffset`.
|
||||
### Animation Anti-Patterns
|
||||
- No bounce or spring animations
|
||||
- No scale-up entrance effects
|
||||
- No flash/blink effects
|
||||
- No parallax scrolling
|
||||
- Durations always > 5s for ambient, 0.2–0.6s for interactive
|
||||
- Never `animation-iteration-count: 1` for ambient effects
|
||||
|
||||
## Layout Principles
|
||||
|
||||
@ -258,9 +358,11 @@ On toggle: update attribute, re-render all canvas dither art after
|
||||
|
||||
## Resources
|
||||
|
||||
- `assets/design-brief.png` — Full-page reference screenshot of
|
||||
the design brief with all components and background layers.
|
||||
- `assets/globals.css` — Complete token stylesheet with dual themes,
|
||||
typography, components, icon classes, and utilities.
|
||||
- `assets/index.html` — Full reference implementation with all
|
||||
components, icon set, generative art, theme toggle.
|
||||
components, icon set, generative art, embedding graph, theme toggle.
|
||||
- `references/generative-patterns.md` — Perlin noise + fbm + Bayer
|
||||
dither + glitch smear implementation with code.
|
||||
|
||||
BIN
skills/signet-design/assets/design-brief.png
Normal file
BIN
skills/signet-design/assets/design-brief.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
@ -255,6 +255,7 @@
|
||||
border: 1px solid var(--color-border-strong);
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
opacity: 0.8;
|
||||
animation: node-pulse 6s ease-in-out infinite;
|
||||
}
|
||||
.schematic-circle:nth-child(2) { animation-delay: -2s; animation-duration: 8s; }
|
||||
@ -299,6 +300,8 @@
|
||||
stroke: var(--color-border-strong);
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
opacity: 0.8;
|
||||
transition: opacity 0.3s ease, stroke 0.3s ease, stroke-width 0.3s ease;
|
||||
}
|
||||
.connector-svg .conn-dashed {
|
||||
stroke-dasharray: 6 4;
|
||||
@ -317,6 +320,8 @@
|
||||
.connector-svg .conn-dot {
|
||||
fill: var(--color-text-muted);
|
||||
r: 2;
|
||||
opacity: 0.8;
|
||||
transition: opacity 0.3s ease, fill 0.3s ease;
|
||||
}
|
||||
.connector-svg .conn-dot--bright {
|
||||
fill: var(--color-text);
|
||||
@ -334,6 +339,21 @@
|
||||
text-transform: uppercase;
|
||||
fill: var(--color-text-muted);
|
||||
opacity: 0.4;
|
||||
transition: opacity 0.3s ease, fill 0.3s ease;
|
||||
}
|
||||
/* Highlight state for edges connected to hovered node */
|
||||
.connector-svg path.conn-highlight {
|
||||
stroke: var(--color-text);
|
||||
stroke-width: 1.5;
|
||||
opacity: 1;
|
||||
}
|
||||
.connector-svg .conn-dot.conn-highlight {
|
||||
fill: var(--color-text-bright);
|
||||
opacity: 1;
|
||||
}
|
||||
.connector-svg .conn-label.conn-highlight {
|
||||
fill: var(--color-text);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* Vertical sidebar */
|
||||
@ -639,12 +659,17 @@
|
||||
position: absolute;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
pointer-events: auto;
|
||||
cursor: crosshair;
|
||||
opacity: 0.8;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
.crosshair-field .ch::before,
|
||||
.crosshair-field .ch::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background: var(--color-border);
|
||||
transition: background 0.25s ease, transform 0.25s ease;
|
||||
}
|
||||
.crosshair-field .ch::before {
|
||||
width: 1px;
|
||||
@ -656,6 +681,55 @@
|
||||
height: 1px;
|
||||
top: 50%;
|
||||
}
|
||||
/* Node hover — expand crosshair, brighten */
|
||||
.crosshair-field .ch:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.crosshair-field .ch:hover::before {
|
||||
background: var(--color-text);
|
||||
transform: scaleY(1.8);
|
||||
}
|
||||
.crosshair-field .ch:hover::after {
|
||||
background: var(--color-text);
|
||||
transform: scaleX(1.8);
|
||||
}
|
||||
/* Node label — hidden until hover */
|
||||
.crosshair-field .ch-label {
|
||||
position: absolute;
|
||||
top: -16px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 6px;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-text);
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
transition: opacity 0.25s ease;
|
||||
pointer-events: none;
|
||||
background: var(--color-bg);
|
||||
padding: 1px 4px;
|
||||
border: 1px solid var(--color-border-strong);
|
||||
}
|
||||
.crosshair-field .ch:hover .ch-label {
|
||||
opacity: 1;
|
||||
}
|
||||
/* Ring pulse on hover */
|
||||
.crosshair-field .ch-ring {
|
||||
position: absolute;
|
||||
inset: -6px;
|
||||
border: 1px solid var(--color-text-muted);
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
transform: scale(0.6);
|
||||
transition: opacity 0.3s ease, transform 0.3s ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
.crosshair-field .ch:hover .ch-ring {
|
||||
opacity: 0.5;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
/* === Schematic overlay === */
|
||||
.schematic-overlay {
|
||||
@ -790,26 +864,26 @@
|
||||
<!-- Graph nodes — positioned as embedding clusters -->
|
||||
<div class="crosshair-field">
|
||||
<!-- Cluster A: upper-left (near sc-1) -->
|
||||
<div class="ch" id="ch-0" style="top: 6%; left: 12%;"></div>
|
||||
<div class="ch" id="ch-1" style="top: 15%; left: 16%;"></div>
|
||||
<div class="ch" id="ch-2" style="top: 10%; left: 22%;"></div>
|
||||
<div class="ch" id="ch-3" style="top: 20%; left: 10%;"></div>
|
||||
<div class="ch" id="ch-0" style="top: 6%; left: 12%;"><span class="ch-ring"></span><span class="ch-label">SLOT_00</span></div>
|
||||
<div class="ch" id="ch-1" style="top: 15%; left: 16%;"><span class="ch-ring"></span><span class="ch-label">SLOT_01</span></div>
|
||||
<div class="ch" id="ch-2" style="top: 10%; left: 22%;"><span class="ch-ring"></span><span class="ch-label">SLOT_02</span></div>
|
||||
<div class="ch" id="ch-3" style="top: 20%; left: 10%;"><span class="ch-ring"></span><span class="ch-label">SLOT_03</span></div>
|
||||
<!-- Cluster B: upper-right (sparse) -->
|
||||
<div class="ch" id="ch-4" style="top: 8%; right: 10%;"></div>
|
||||
<div class="ch" id="ch-5" style="top: 16%; right: 6%;"></div>
|
||||
<div class="ch" id="ch-4" style="top: 8%; right: 10%;"><span class="ch-ring"></span><span class="ch-label">SLOT_04</span></div>
|
||||
<div class="ch" id="ch-5" style="top: 16%; right: 6%;"><span class="ch-ring"></span><span class="ch-label">SLOT_05</span></div>
|
||||
<!-- Cluster C: mid-left (near sc-2) -->
|
||||
<div class="ch" id="ch-6" style="top: 45%; left: 12%;"></div>
|
||||
<div class="ch" id="ch-7" style="top: 55%; left: 14%;"></div>
|
||||
<div class="ch" id="ch-8" style="top: 48%; left: 20%;"></div>
|
||||
<div class="ch" id="ch-6" style="top: 45%; left: 12%;"><span class="ch-ring"></span><span class="ch-label">SLOT_06</span></div>
|
||||
<div class="ch" id="ch-7" style="top: 55%; left: 14%;"><span class="ch-ring"></span><span class="ch-label">SLOT_07</span></div>
|
||||
<div class="ch" id="ch-8" style="top: 48%; left: 20%;"><span class="ch-ring"></span><span class="ch-label">SLOT_08</span></div>
|
||||
<!-- Cluster D: lower region -->
|
||||
<div class="ch" id="ch-9" style="top: 72%; left: 6%;"></div>
|
||||
<div class="ch" id="ch-10" style="top: 78%; left: 12%;"></div>
|
||||
<div class="ch" id="ch-11" style="bottom: 14%; right: 14%;"></div>
|
||||
<div class="ch" id="ch-12" style="bottom: 22%; right: 10%;"></div>
|
||||
<div class="ch" id="ch-9" style="top: 72%; left: 6%;"><span class="ch-ring"></span><span class="ch-label">SLOT_09</span></div>
|
||||
<div class="ch" id="ch-10" style="top: 78%; left: 12%;"><span class="ch-ring"></span><span class="ch-label">SLOT_10</span></div>
|
||||
<div class="ch" id="ch-11" style="bottom: 14%; right: 14%;"><span class="ch-ring"></span><span class="ch-label">SLOT_11</span></div>
|
||||
<div class="ch" id="ch-12" style="bottom: 22%; right: 10%;"><span class="ch-ring"></span><span class="ch-label">SLOT_12</span></div>
|
||||
<!-- Outliers -->
|
||||
<div class="ch" id="ch-13" style="top: 35%; left: 4%;"></div>
|
||||
<div class="ch" id="ch-14" style="top: 65%; right: 5%;"></div>
|
||||
<div class="ch" id="ch-15" style="bottom: 8%; left: 8%;"></div>
|
||||
<div class="ch" id="ch-13" style="top: 35%; left: 4%;"><span class="ch-ring"></span><span class="ch-label">SLOT_13</span></div>
|
||||
<div class="ch" id="ch-14" style="top: 65%; right: 5%;"><span class="ch-ring"></span><span class="ch-label">SLOT_14</span></div>
|
||||
<div class="ch" id="ch-15" style="bottom: 8%; left: 8%;"><span class="ch-ring"></span><span class="ch-label">SLOT_15</span></div>
|
||||
</div>
|
||||
|
||||
<canvas id="dither-edge"></canvas>
|
||||
@ -1544,16 +1618,14 @@
|
||||
const a = elCenter(fromEl);
|
||||
const b = elCenter(toEl);
|
||||
|
||||
// Curved path with control points offset perpendicular
|
||||
// Single-curve quadratic bezier — one control point offset perpendicular
|
||||
const dx = b.x - a.x;
|
||||
const dy = b.y - a.y;
|
||||
const cx1 = a.x + dx * 0.3 + dy * 0.15;
|
||||
const cy1 = a.y + dy * 0.3 - dx * 0.15;
|
||||
const cx2 = a.x + dx * 0.7 - dy * 0.15;
|
||||
const cy2 = a.y + dy * 0.7 + dx * 0.15;
|
||||
const mx = (a.x + b.x) / 2 + dy * 0.12;
|
||||
const my = (a.y + b.y) / 2 - dx * 0.12;
|
||||
|
||||
const path = document.createElementNS(svgNS, 'path');
|
||||
path.setAttribute('d', `M ${a.x},${a.y} C ${cx1},${cy1} ${cx2},${cy2} ${b.x},${b.y}`);
|
||||
path.setAttribute('d', `M ${a.x},${a.y} Q ${mx},${my} ${b.x},${b.y}`);
|
||||
path.classList.add(style === 'dashed-rev' ? 'conn-dashed-rev' : 'conn-dashed');
|
||||
connSvg.appendChild(path);
|
||||
|
||||
@ -1583,6 +1655,49 @@
|
||||
|
||||
drawConnectors();
|
||||
|
||||
// === Node hover → highlight connected edges ===
|
||||
// Build adjacency: nodeId → [edge indices]
|
||||
const nodeEdges = {};
|
||||
edges.forEach(([fromId, toId], i) => {
|
||||
if (!nodeEdges[fromId]) nodeEdges[fromId] = [];
|
||||
if (!nodeEdges[toId]) nodeEdges[toId] = [];
|
||||
nodeEdges[fromId].push(i);
|
||||
nodeEdges[toId].push(i);
|
||||
});
|
||||
|
||||
// Each edge produces: 1 path + 2 dots + optional label = 3 or 4 SVG children
|
||||
// We track which SVG children belong to which edge index
|
||||
function getEdgeElements(edgeIdx) {
|
||||
let childIdx = 0;
|
||||
for (let i = 0; i < edges.length; i++) {
|
||||
const pathEl = connSvg.children[childIdx++]; // path
|
||||
const dot1 = connSvg.children[childIdx++]; // dot
|
||||
const dot2 = connSvg.children[childIdx++]; // dot
|
||||
let labelEl = null;
|
||||
if (edges[i][3]) {
|
||||
labelEl = connSvg.children[childIdx++]; // label
|
||||
}
|
||||
if (i === edgeIdx) return [pathEl, dot1, dot2, labelEl].filter(Boolean);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
document.querySelectorAll('.crosshair-field .ch').forEach(ch => {
|
||||
ch.addEventListener('mouseenter', () => {
|
||||
const id = ch.id;
|
||||
const indices = nodeEdges[id] || [];
|
||||
for (const idx of indices) {
|
||||
const els = getEdgeElements(idx);
|
||||
els.forEach(el => el.classList.add('conn-highlight'));
|
||||
}
|
||||
});
|
||||
ch.addEventListener('mouseleave', () => {
|
||||
connSvg.querySelectorAll('.conn-highlight').forEach(el => {
|
||||
el.classList.remove('conn-highlight');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
let resizeTimer;
|
||||
window.addEventListener('resize', () => {
|
||||
clearTimeout(resizeTimer);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user