Skip to content

Commit 935a9b0

Browse files
committed
feat: cinematic 3D scene, light/dark theme system, and design system hardening
## What Changed ### 3D Scene (Three.js) - Added SceneManager.js — full Three.js scene with rotating wireframe cube, inner icosahedron, 100×100 GridHelper, and 500-particle volumetric dust system - Added Scene.svelte — Svelte lifecycle wrapper that mounts/destroys the canvas; canvas is position:fixed, z-index:-1, pointer-events:none so it renders behind all page content without intercepting interaction - Added ProductMonoliths.svelte — three interactive wireframe panels on the home page that sit behind the product cards; respond to hover with tilt, glow edges, and color transitions via raycasting - Animation loop (tick/rAF), mouse parallax on cube rotation, and scroll-linked grid drift are all wired up in SceneManager constructor ### Light / Dark Theme System - Defined dual-theme CSS variable sets in app.css: :root / [data-theme='light'] — pure white bg, black text [data-theme='dark'] — pure black bg, white text Both themes are fully monochrome; no accent colors at any layer - Theme toggle implemented in +layout.svelte; state persists to localStorage with prefers-color-scheme as fallback when no stored preference exists - data-theme attribute set on <html> element; all CSS variables resolve automatically - SceneManager.js watches data-theme via MutationObserver and calls updateThemeColors() to sync fog color/density, wireframe color, grid colors, and particle opacity to the active theme in real time - ProductMonoliths.svelte has its own MutationObserver for the same reason - Theme toggle button added to Nav.svelte; displays [LIGHT] / [DARK] label ### Design System Hardening - Removed overly aggressive wildcard transparency rule: main, section, div:not(.webgl-canvas) { background-color: transparent } This rule was interfering with component styles. Body transparent is sufficient since the canvas sits at z-index:-1 behind everything - Replaced all hardcoded rgba(255,255,255,...) values in +page.svelte with theme-aware CSS variables (--surface, --border-glow) so hover states and text-shadows work correctly in both light and dark mode - Nav background set to transparent with backdrop-filter:blur for glass effect over 3D canvas; footer background set to transparent for same reason - Removed debug console.log from SceneManager.updateThemeColors() ### Documentation - README.md: complete rewrite from Vite boilerplate to full project README covering what the Sovren Stack is, tech stack, project structure tree with every file annotated, architecture sections for theme system and 3D scene, shared component reference, deployment, SEO, and IDE setup - CLAUDE.md: added Theme System section (data flow diagram, adding theme-aware styles guide), added 3D Scene System section (architecture tree, key files, CSS layering requirements, theme color mapping table, modification guidelines), updated color tokens to reflect dual-theme variable structure, updated rules to prohibit hardcoded color values, updated Remaining Work with completed items ## Problems Solved - 3D scene disappeared after theme toggle integration — root cause was the animation loop (tick()) being dropped during refactor; restored in constructor - 3D canvas was occluded by page content — fixed by making body/nav/footer backgrounds transparent and keeping canvas at z-index:-1 - Light mode 3D elements had no contrast — fixed by mapping wireframe/grid/fog colors per theme (black wireframes on white in light, white on black in dark) - Fog density was a type error — fixed by instanceof check before accessing FogExp2.density vs Fog (which has no density property) - Product card hover used hardcoded white rgba values — broke in light mode; replaced with --surface and --border-glow tokens - README was the default Vite scaffold boilerplate — replaced with accurate project documentation that explains the codebase to any new contributor
1 parent 286fe80 commit 935a9b0

File tree

8 files changed

+538
-107
lines changed

8 files changed

+538
-107
lines changed

CLAUDE.md

Lines changed: 138 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ Marketing site for Sovren Software at `sovren.software`.
66

77
## Stack
88

9-
- **Framework**: SvelteKit + `@sveltejs/adapter-static` (prerendered static site)
9+
- **Framework**: SvelteKit 2.x + `@sveltejs/adapter-static` (prerendered static site)
10+
- **3D Scene**: Three.js 0.183 (wireframe cube, grid, particles, product monoliths)
11+
- **Animation**: GSAP 3.x
1012
- **Font**: Geist Mono Variable (self-hosted, `static/fonts/GeistMono-Variable.woff2`)
13+
- **Build**: Vite 7.x
1114
- **Deploy**: GitHub Actions → `sovren-software.github.io`, CNAME `sovren.software`
1215
- **CDN**: Cloudflare proxy in front of GitHub Pages (enables crawler access, hides Fastly)
1316
- **Search**: Bing Webmaster Tools verified, sitemap submitted
@@ -18,29 +21,36 @@ Centralized in `src/app.css` with 60+ design tokens. All styles reference tokens
1821

1922
### Colors
2023

21-
**Dark mode (default):**
24+
The site uses a `data-theme` attribute on `<html>` to switch between light and dark mode. CSS custom properties swap automatically.
25+
26+
**Light mode (default — `:root` / `[data-theme='light']`):**
2227
```
23-
--bg: #000000
24-
--surface: #080808
25-
--surface-2: #111111
26-
--border: rgba(255,255,255,0.1)
27-
--text-primary: #ffffff
28-
--text-secondary: rgba(255,255,255,0.55)
29-
--text-muted: rgba(255,255,255,0.25)
30-
--text-ghost: rgba(255,255,255,0.12)
28+
--bg: #ffffff
29+
--surface: rgba(230,230,230,0.4)
30+
--surface-2: rgba(210,210,210,0.5)
31+
--border: rgba(0,0,0,0.15)
32+
--border-glow: rgba(0,0,0,0.8)
33+
--text-primary: #000000
34+
--text-secondary: rgba(0,0,0,0.65)
35+
--text-muted: rgba(0,0,0,0.35)
36+
--text-ghost: rgba(0,0,0,0.15)
3137
```
3238

33-
**Light sections (overview/CTA blocks):**
39+
**Dark mode (`[data-theme='dark']`):**
3440
```
35-
--light-bg: #ffffff
36-
--light-border: #e5e5e5
37-
--light-text-primary: #000000
38-
--light-text-body: #333333
39-
--light-text-secondary: #555555
40-
--light-text-muted: #999999
41-
--light-text-dim: #888888
41+
--bg: #000000
42+
--surface: rgba(25,25,25,0.4)
43+
--surface-2: rgba(40,40,40,0.5)
44+
--border: rgba(255,255,255,0.15)
45+
--border-glow: rgba(255,255,255,0.8)
46+
--text-primary: #ffffff
47+
--text-secondary: rgba(255,255,255,0.65)
48+
--text-muted: rgba(255,255,255,0.35)
49+
--text-ghost: rgba(255,255,255,0.15)
4250
```
4351

52+
**Important:** Both themes are pure monochrome. No accent colors, no brand colors. Emphasis is achieved through weight and spacing, never color.
53+
4454
### Typography
4555

4656
| Token | Size | Usage |
@@ -117,8 +127,113 @@ Reusable Svelte components in `src/lib/`:
117127

118128
- Never add a second typeface
119129
- Never use color for emphasis — use weight and letter-spacing only
120-
- White contrast sections use light tokens, never hardcoded values
121-
- All transitions: `var(--transition-fast)` (0.15s)
130+
- All color values must use theme-aware CSS variables — never hardcode `rgba(255,...)` or `rgba(0,...)`
131+
- All transitions: `var(--transition-fast)` (0.15s) or `var(--transition-slow)` (0.4s)
132+
133+
## Theme System
134+
135+
Light/dark mode toggle with persistence and system preference fallback.
136+
137+
### How It Works
138+
139+
1. **`+layout.svelte`** owns the theme state and provides `toggleTheme()` to `Nav.svelte`
140+
2. On mount: checks `localStorage('theme')` → falls back to `prefers-color-scheme` → defaults to light
141+
3. Sets `document.documentElement.setAttribute('data-theme', theme)`
142+
4. CSS variables in `app.css` swap via `:root` / `[data-theme='light']` and `[data-theme='dark']` selectors
143+
5. 3D scene reacts via `MutationObserver` on `data-theme` attribute changes
144+
145+
### Theme Flow
146+
147+
```
148+
User clicks toggle → +layout.svelte toggleTheme()
149+
→ sets data-theme on <html>
150+
→ saves to localStorage
151+
→ CSS variables swap instantly
152+
→ MutationObserver in SceneManager.js fires
153+
→ updateThemeColors() adjusts fog, wireframes, grid, particles
154+
→ MutationObserver in ProductMonoliths.svelte fires
155+
→ monolith wireframe colors update
156+
```
157+
158+
### Adding Theme-Aware Styles
159+
160+
Always use CSS variables. Never hardcode colors:
161+
```css
162+
/* ✓ Correct */
163+
color: var(--text-primary);
164+
background: var(--surface);
165+
border-color: var(--border);
166+
167+
/* ✗ Wrong */
168+
color: #ffffff;
169+
background: rgba(255, 255, 255, 0.1);
170+
```
171+
172+
## 3D Scene System
173+
174+
A cinematic Three.js background renders behind all page content on every route.
175+
176+
### Architecture
177+
178+
```
179+
+layout.svelte
180+
└── <Scene /> # Svelte lifecycle wrapper
181+
└── SceneManager.js # Core Three.js logic
182+
├── Camera (z=15)
183+
├── Renderer (alpha: true, transparent canvas)
184+
├── FogExp2 (theme-aware color + density)
185+
├── Wireframe cube (rotating, mouse-reactive)
186+
├── Inner icosahedron (counter-rotating)
187+
├── GridHelper (100×100, scroll-linked drift)
188+
└── Particle system (500 dust particles)
189+
190+
+page.svelte (home only)
191+
└── <ProductMonoliths /> # Three wireframe panels behind product cards
192+
├── Augmentum monolith
193+
├── Visage monolith
194+
└── MrHaven monolith
195+
```
196+
197+
### Key Files
198+
199+
| File | Responsibility |
200+
|------|---------------|
201+
| `src/lib/three/Scene.svelte` | Canvas element creation, SceneManager lifecycle (mount/destroy) |
202+
| `src/lib/three/SceneManager.js` | Camera, renderer, scene objects, animation loop, resize/scroll/mouse handlers, theme color updates, cleanup |
203+
| `src/lib/three/ProductMonoliths.svelte` | Three interactive wireframe panels on home page, hover effects (tilt, glow, color), theme-aware materials |
204+
205+
### CSS Layering
206+
207+
The 3D canvas must remain visible behind all content. This requires:
208+
209+
```
210+
Canvas: position: fixed; z-index: -1; pointer-events: none;
211+
Body: background: transparent;
212+
Nav: background: transparent; backdrop-filter: blur(10px);
213+
Footer: background: transparent;
214+
```
215+
216+
All page sections must have transparent backgrounds. Do **not** add `background-color` to `main`, `section`, or generic `div` elements — this will occlude the 3D canvas.
217+
218+
### Theme Color Mapping (3D)
219+
220+
| Element | Light Mode | Dark Mode |
221+
|---------|-----------|-----------|
222+
| Fog color | `0xffffff` | `0x000000` |
223+
| Fog density | `0.015` | `0.02` |
224+
| Wireframe color | `0x000000` | `0xffffff` |
225+
| Grid primary | `0x888888` | `0x444444` |
226+
| Grid secondary | `0xcccccc` | `0x222222` |
227+
| Particle color | `0x000000` (opacity 0.2) | `0xffffff` (opacity 0.4) |
228+
| Monolith wireframe | `0x333333` | `0xffffff` |
229+
230+
### Modifying the 3D Scene
231+
232+
- All scene setup is in `SceneManager.js` constructor
233+
- Animation loop is `tick()` — called via `requestAnimationFrame`
234+
- Theme updates go in `updateThemeColors()` — called by the `MutationObserver`
235+
- Always clean up resources in `destroy()` (geometries, materials, observers, event listeners)
236+
- The renderer uses `alpha: true` — the CSS `background: var(--bg)` on the canvas provides the background color
122237

123238
## Routing
124239

@@ -223,6 +338,9 @@ DNS: 4 A records (185.199.108-111.153) + www CNAME → `sovren-software.github.i
223338
- [ ] MrHaven SDK section on the MrHaven page (when SDK docs exist)
224339
- [ ] Visual convergence diagram on Ecosystem page
225340
- [ ] X profile update (currently MrHaven-branded)
341+
- [x] 3D cinematic scene — wireframe cube, grid, particles, product monoliths (2026-02-25)
342+
- [x] Light/dark theme toggle with persistence and 3D sync (2026-02-25)
343+
- [x] Theme-aware CSS variables — all hardcoded colors removed (2026-02-25)
226344
- [x] Waitlist capture on Augmentum OS page — mailto:hello@sovren.software (2026-02-24)
227345
- [x] Visage version updated to v0.2.0 (2026-02-24)
228346
- [x] AI agent angle surfaced on MrHaven page (2026-02-24)

README.md

Lines changed: 146 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,165 @@
1-
# Svelte + Vite
1+
# Sovren Software — sovren.software
22

3-
This template should help get you started developing with Svelte in Vite.
3+
Marketing site for **Sovren Software**, the company behind the Sovren Stack: a sovereign computing platform spanning OS, identity, and programmable finance.
44

5-
## Recommended IDE Setup
5+
Live at **[sovren.software](https://sovren.software)**
66

7-
[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
7+
---
88

9-
## Need an official Svelte framework?
9+
## What Is the Sovren Stack?
1010

11-
Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.
11+
The Sovren Stack is three products that together give individuals full-stack digital sovereignty:
1212

13-
## Technical considerations
13+
| Product | Layer | Status |
14+
|---------|-------|--------|
15+
| **Augmentum OS** | Computing — declarative NixOS system | Ships Summer 2026 |
16+
| **Visage** | Identity — local face auth via PAM + ONNX | Live · v0.2.0 · MIT |
17+
| **MrHaven** | Finance — non-custodial USDC time vault on Base L2 | Live on mainnet |
1418

15-
**Why use this over SvelteKit?**
19+
This website is the public face of all three products and the ecosystem manifesto.
1620

17-
- It brings its own routing solution which might not be preferable for some users.
18-
- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
21+
---
1922

20-
This template contains as little as possible to get started with Vite + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.
23+
## Tech Stack
2124

22-
Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.
25+
| Layer | Technology |
26+
|-------|-----------|
27+
| Framework | SvelteKit 2.x + `@sveltejs/adapter-static` |
28+
| 3D Scene | Three.js (wireframe cube, grid, particles, product monoliths) |
29+
| Animation | GSAP 3.x |
30+
| Font | Geist Mono Variable (self-hosted) |
31+
| Build | Vite 7.x |
32+
| Deploy | GitHub Actions → GitHub Pages → Cloudflare proxy |
33+
| Domain | `sovren.software` (CNAME in `static/CNAME`) |
2334

24-
**Why include `.vscode/extensions.json`?**
35+
---
2536

26-
Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
37+
## Quick Start
2738

28-
**Why enable `checkJs` in the JS template?**
39+
```bash
40+
npm install
41+
npm run dev # http://localhost:5173
42+
npm run build # static output → dist/
43+
npm run preview # preview production build
44+
```
45+
46+
**Requirements:** Node.js 18+
47+
48+
---
49+
50+
## Project Structure
51+
52+
```
53+
src/
54+
├── app.css # Global design tokens + theme definitions
55+
├── app.html # HTML shell with JSON-LD structured data
56+
├── lib/
57+
│ ├── Nav.svelte # Navigation with theme toggle
58+
│ ├── ProductHero.svelte # Reusable hero section
59+
│ ├── Overview.svelte # Reusable overview + spec table
60+
│ ├── PillarList.svelte # Reusable numbered feature list
61+
│ ├── CtaSection.svelte # Reusable call-to-action section
62+
│ └── three/
63+
│ ├── Scene.svelte # Svelte wrapper for Three.js canvas lifecycle
64+
│ ├── SceneManager.js # Core 3D scene: camera, renderer, animation loop, theme colors
65+
│ └── ProductMonoliths.svelte # Interactive 3D product panels on home page
66+
├── routes/
67+
│ ├── +layout.svelte # Global layout: Scene, Nav, footer, theme logic
68+
│ ├── +layout.js # Prerender flag (static site generation)
69+
│ ├── +page.svelte # Home page: hero, product grid, thesis
70+
│ ├── +error.svelte # 404 error page
71+
│ ├── augmentum/+page.svelte # Augmentum OS product page
72+
│ ├── visage/+page.svelte # Visage product page
73+
│ ├── mrhaven/+page.svelte # MrHaven product page
74+
│ └── ecosystem/+page.svelte # Ecosystem manifesto page
75+
static/
76+
├── CNAME # GitHub Pages custom domain
77+
├── fonts/GeistMono-Variable.woff2 # Self-hosted font
78+
├── robots.txt # Crawler access rules
79+
├── sitemap.xml # All routes for search engines
80+
├── llms.txt # AI crawler context file
81+
└── BingSiteAuth.xml # Bing Webmaster verification
82+
```
83+
84+
---
85+
86+
## Architecture
87+
88+
### Theme System (Light / Dark)
89+
90+
The site supports light and dark modes with a cinematic toggle in the navigation.
91+
92+
- **Default:** Light mode (`:root` / `[data-theme='light']`)
93+
- **Toggle:** Button in `Nav.svelte` calls `toggleTheme()` in `+layout.svelte`
94+
- **Persistence:** `localStorage.getItem('theme')` with system preference fallback via `prefers-color-scheme`
95+
- **Mechanism:** `data-theme` attribute on `<html>` drives CSS variable swaps
96+
- **3D sync:** `SceneManager.js` observes `data-theme` via `MutationObserver` and updates fog, wireframe, grid, and particle colors in real time
97+
98+
All colors use CSS custom properties — no hardcoded color values in components.
99+
100+
### 3D Scene (Three.js)
101+
102+
A full-viewport 3D background renders behind all page content:
29103

30-
It is likely that most cases of changing variable types in runtime are likely to be accidental, rather than deliberate. This provides advanced typechecking out of the box. Should you like to take advantage of the dynamically-typed nature of JavaScript, it is trivial to change the configuration.
104+
- **Canvas:** `position: fixed`, `z-index: -1`, `pointer-events: none` — sits behind all UI
105+
- **Elements:** Rotating wireframe cube, inner icosahedron, infinite grid, volumetric dust particles
106+
- **Interaction:** Mouse parallax on cube rotation, scroll-linked grid drift
107+
- **Theme-aware:** Materials, fog color/density, and particle opacity adapt to light/dark mode
108+
- **Lifecycle:** `Scene.svelte` mounts/unmounts the canvas; `SceneManager.js` handles the animation loop and cleanup
31109

32-
**Why is HMR not preserving my local component state?**
110+
The home page also renders `ProductMonoliths.svelte` — three interactive wireframe panels positioned behind the product cards that respond to hover with tilt, glow, and color transitions.
33111

34-
HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/sveltejs/svelte-hmr/tree/master/packages/svelte-hmr#preservation-of-local-state).
112+
### Shared Components
35113

36-
If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
114+
Product pages (Augmentum, Visage, MrHaven) share four components with zero local CSS:
37115

38-
```js
39-
// store.js
40-
// An extremely simple external store
41-
import { writable } from 'svelte/store'
42-
export default writable(0)
116+
| Component | Props | Purpose |
117+
|-----------|-------|---------|
118+
| `ProductHero.svelte` | title, category, status, tagline, size | Hero section |
119+
| `Overview.svelte` | lead, specs[], stackNote, slot | Overview with spec table |
120+
| `PillarList.svelte` | label, pillars[] | Numbered feature list |
121+
| `CtaSection.svelte` | title, body, actions[] | Call-to-action with buttons |
122+
123+
### Design System
124+
125+
Centralized in `src/app.css` with 60+ design tokens covering:
126+
127+
- **Colors** — Theme-aware via `--bg`, `--surface`, `--border`, `--text-primary/secondary/muted/ghost`
128+
- **Typography** — Fluid `clamp()` scale from `--fs-hero` down to `--fs-label-xs`
129+
- **Spacing**`--space-xs` through `--space-7xl`
130+
- **Layout**`--max-w`, `--max-w-prose`, `--nav-h`, `--z-nav`
131+
- **Transitions**`--transition-fast`, `--transition-slow`
132+
133+
Rules: one typeface only, no color for emphasis (use weight/spacing), all values via tokens.
134+
135+
---
136+
137+
## Deployment
138+
139+
```bash
140+
npm run build # verify build passes
141+
git push # GitHub Actions auto-deploys from main
43142
```
143+
144+
- Output: `dist/` directory (static adapter)
145+
- DNS: 4 GitHub Pages A records + `www` CNAME → `sovren-software.github.io`, proxied via Cloudflare
146+
- `static/CNAME` contains `sovren.software` — do not delete
147+
148+
---
149+
150+
## SEO & AI Discoverability
151+
152+
- `app.html` — JSON-LD structured data (Organization + WebSite schemas)
153+
- Each page — `<svelte:head>` with unique title, description, and Open Graph meta
154+
- `static/llms.txt` — full product descriptions for AI crawlers (ChatGPT, Perplexity, Claude)
155+
- `static/sitemap.xml` — all 5 routes
156+
- Cloudflare proxy prevents GitHub/Fastly from blocking AI crawler IPs
157+
- Bing Webmaster Tools verified
158+
159+
---
160+
161+
## IDE Setup
162+
163+
[VS Code](https://code.visualstudio.com/) + [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode)
164+
165+
For AI-assisted development, see `CLAUDE.md` for the full design system reference, copy guidelines, and product context.

0 commit comments

Comments
 (0)