/ src / components / ui / ArchitectureSketch.tsx
ArchitectureSketch.tsx
  1  // Copyright (c) 2026 VPL Solutions. All rights reserved.
  2  // Licensed under the MIT License. See LICENSE for details.
  3  
  4  /**
  5   * Hand-drawn architecture diagram overlay for the sign-in screen.
  6   * Renders a chalk-on-dark SVG showing Meridian's data flow:
  7   *   Documents -> RAG Engine -> Knowledge Base
  8   *                    |
  9   *              MCP Server  <-- AI Agents
 10   *                    |
 11   *            Governance Gate
 12   *
 13   * Uses wobbly SVG paths to simulate hand-drawing. Rendered at low
 14   * opacity as an atmospheric background element.
 15   */
 16  
 17  // Slight jitter for hand-drawn feel
 18  function jitter(v: number, amount = 1.5): number {
 19    // Deterministic wobble based on value (no Math.random — SSR-safe)
 20    return v + Math.sin(v * 7.3) * amount;
 21  }
 22  
 23  // Hand-drawn rectangle as a wobbly path
 24  function sketchRect(x: number, y: number, w: number, h: number): string {
 25    const j = 1.2;
 26    return [
 27      `M${jitter(x, j)},${jitter(y, j)}`,
 28      `L${jitter(x + w, j)},${jitter(y, j)}`,
 29      `L${jitter(x + w, j)},${jitter(y + h, j)}`,
 30      `L${jitter(x, j)},${jitter(y + h, j)}`,
 31      'Z',
 32    ].join(' ');
 33  }
 34  
 35  // Hand-drawn arrow from point A to point B
 36  function sketchArrow(
 37    x1: number, y1: number, x2: number, y2: number,
 38  ): { line: string; head: string } {
 39    const j = 1;
 40    const angle = Math.atan2(y2 - y1, x2 - x1);
 41    const headLen = 8;
 42    const line = `M${jitter(x1, j)},${jitter(y1, j)} L${jitter(x2, j)},${jitter(y2, j)}`;
 43    const head = [
 44      `M${x2},${y2}`,
 45      `L${x2 - headLen * Math.cos(angle - 0.4)},${y2 - headLen * Math.sin(angle - 0.4)}`,
 46      `M${x2},${y2}`,
 47      `L${x2 - headLen * Math.cos(angle + 0.4)},${y2 - headLen * Math.sin(angle + 0.4)}`,
 48    ].join(' ');
 49    return { line, head };
 50  }
 51  
 52  // Box definitions: label, x, y, w, h
 53  const BOXES = [
 54    { label: 'Documents', x: 40, y: 55, w: 90, h: 30 },
 55    { label: 'RAG Engine', x: 185, y: 55, w: 95, h: 30 },
 56    { label: 'Knowledge Base', x: 335, y: 55, w: 115, h: 30 },
 57    { label: 'MCP Server', x: 185, y: 130, w: 95, h: 30 },
 58    { label: 'AI Agents', x: 345, y: 130, w: 85, h: 30 },
 59    { label: 'Governance', x: 185, y: 200, w: 95, h: 30 },
 60  ] as const;
 61  
 62  // Arrows: from box center-right to box center-left (or center-bottom to center-top)
 63  const ARROWS = [
 64    // Documents -> RAG Engine
 65    { x1: 130, y1: 70, x2: 185, y2: 70 },
 66    // RAG Engine -> Knowledge Base
 67    { x1: 280, y1: 70, x2: 335, y2: 70 },
 68    // RAG Engine -> MCP Server (down)
 69    { x1: 232, y1: 85, x2: 232, y2: 130 },
 70    // AI Agents -> MCP Server (left arrow)
 71    { x1: 345, y1: 145, x2: 280, y2: 145 },
 72    // MCP Server -> Governance (down)
 73    { x1: 232, y1: 160, x2: 232, y2: 200 },
 74  ] as const;
 75  
 76  // Chalk stroke style
 77  const CHALK = {
 78    stroke: 'rgba(255, 255, 255, 0.55)',
 79    strokeWidth: 1.2,
 80    fill: 'none',
 81    strokeLinecap: 'round' as const,
 82    strokeLinejoin: 'round' as const,
 83  };
 84  
 85  const CHALK_TEXT = {
 86    fill: 'rgba(255, 255, 255, 0.5)',
 87    fontSize: 9,
 88    fontFamily: "'Segoe UI', system-ui, -apple-system, sans-serif",
 89    fontWeight: 400,
 90    textAnchor: 'middle' as const,
 91    dominantBaseline: 'central' as const,
 92  };
 93  
 94  export function ArchitectureSketch() {
 95    return (
 96      <svg
 97        className="absolute pointer-events-none"
 98        style={{ bottom: '5%', right: '3%', width: '480px', height: '260px', opacity: 0.14 }}
 99        viewBox="0 0 480 260"
100        xmlns="http://www.w3.org/2000/svg"
101      >
102        {/* Underline accent — subtle chalk line across top */}
103        <path
104          d={`M${jitter(20)},${jitter(30)} L${jitter(460)},${jitter(30)}`}
105          {...CHALK}
106          strokeWidth={0.4}
107          strokeDasharray="3 6"
108        />
109  
110        {/* Title */}
111        <text x={240} y={18} {...CHALK_TEXT} fontSize={11} fontWeight={500} letterSpacing={2}>
112          MERIDIAN ARCHITECTURE
113        </text>
114  
115        {/* Boxes */}
116        {BOXES.map(({ label, x, y, w, h }) => (
117          <g key={label}>
118            <path d={sketchRect(x, y, w, h)} {...CHALK} />
119            <text x={x + w / 2} y={y + h / 2} {...CHALK_TEXT}>
120              {label}
121            </text>
122          </g>
123        ))}
124  
125        {/* Arrows */}
126        {ARROWS.map(({ x1, y1, x2, y2 }, i) => {
127          const { line, head } = sketchArrow(x1, y1, x2, y2);
128          return (
129            <g key={`arrow-${i}`}>
130              <path d={line} {...CHALK} />
131              <path d={head} {...CHALK} />
132            </g>
133          );
134        })}
135  
136        {/* Annotation labels — small chalk notes */}
137        <text x={155} y={48} {...CHALK_TEXT} fontSize={7} fontStyle="italic" opacity={0.7}>
138          ingest
139        </text>
140        <text x={310} y={48} {...CHALK_TEXT} fontSize={7} fontStyle="italic" opacity={0.7}>
141          embed + index
142        </text>
143        <text x={250} y={112} {...CHALK_TEXT} fontSize={7} fontStyle="italic" opacity={0.7}>
144          tools/call
145        </text>
146        <text x={315} y={138} {...CHALK_TEXT} fontSize={7} fontStyle="italic" opacity={0.7}>
147          Claude / SK
148        </text>
149        <text x={250} y={188} {...CHALK_TEXT} fontSize={7} fontStyle="italic" opacity={0.7}>
150          confidence gate
151        </text>
152  
153        {/* Bottom annotation */}
154        <text x={240} y={248} {...CHALK_TEXT} fontSize={7} letterSpacing={1.5} opacity={0.5}>
155          governed RAG platform
156        </text>
157      </svg>
158    );
159  }