Style and layout rules for the SVG diagrams used throughout the Strvct docs.
The docs use ~30 inline SVG diagrams to visualize architecture, flows, and relationships. Without a shared style they drift apart, become harder to scan, and require per-page mental re-orientation. The rules below let any diagram be authored, edited, or scripted against the same set of expectations.
Every diagram opens with the same <style> block:
<style>
text { font-family: 'Inter', system-ui, -apple-system, sans-serif; font-size: 12px; fill: #111; }
.b { font-weight: 600; }
.dim { fill: #666; }
.box { fill: none; stroke: #111; stroke-width: 1; }
.fill { fill: #f0ede5; stroke: #111; stroke-width: 1; }
.flow { stroke: #111; stroke-width: 1; fill: none; }
.flow-dashed { stroke: #111; stroke-width: 1; fill: none; stroke-dasharray: 4 3; }
</style>.b — bold text (titles, labels).dim — secondary text (descriptions, captions); color #666.box — outline rectangle, no fill; used for outer containers.fill — cream-filled rectangle (#f0ede5); used for inner content blocks.flow — solid line for direct references / calls / direct data flow.flow-dashed — dashed line (4 3) for indirect notifications, observers, no-direct-reference relationshipsA single arrowhead marker is defined per diagram in <defs>, with a unique id (e.g., ato, aio, anc):
<defs>
<marker id="xxx" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
<path d="M0,0 L10,5 L0,10 z" fill="#111"/>
</marker>
</defs>Lines reference it via marker-end="url(#xxx)".
Content is left-top justified with consistent padding:
fill.x + 15 (15px left padding)fill.y + 20fill.h = (last_text_y - fill.y) + 14.Vertically adjacent fill rects in the same column should sit 15px apart when they're sibling rows in a list. Larger gaps (~30px) are appropriate when an arrow + label lives between them.
For centered stacks (rects whose horizontal centers align around viewBox.width / 2), give all rects the same width — use the maximum needed by any row's content, centered.
Containers wrap one or more .fill rects plus optional title/subtitle text and caption text below the fills.
container.x + 15, container.y + 22container.x + 15, container.y + 42 (when present)container.x + 15, container.y + 60+ (with 15px horizontal padding from container edges)container.x + 15, starting at last_fill_bottom + 24, with 18px line spacingFor 2- and 3-column comparisons, each column's containers should be the same width and aligned at the top (y=20). Container heights should match (use the tallest column's height). Captions inside columns are still left-justified to their column.
.flow) — direct reference or call (e.g., a UI view calling getter/setter on its model node).flow-dashed) — indirect notification or observation (e.g., the model posts a notification, observers pick it up without holding a reference)For the Model ↔ UI ↔ Storage triple, mutation notifications from Model outward are dashed (Model holds no references); UI/Storage calls into Model are solid (they hold direct references).
When labeling a line in a tight gap:
arrow_y - 22 and arrow_y - 7arrow_y + 13 and arrow_y + 28text-anchor="middle" at the gap midpoint xThe summary line below a diagram is left-justified at the same x as the leftmost container (when there is one) or container.x + 15. Do not center such lines.
The conventions exist to keep diagrams scannable, not to be rigid. Acceptable deviations:
When in doubt, prefer consistency with adjacent diagrams in the same page or section.