Reorganize docs, add mockup assets and research materials

- Restructure docs/ into brand/, build-phases/, product/, technical/ subdirectories
- Add consolidated Phase 1 & 2 build plan
- Add complete user journey, architecture diagrams, and build framework docs
- Add science foundation document
- Add initial mockup assets (11 SVGs, design system CSS, implementation instructions)
- Add logo mockup finalists and semi-finalists
- Add academic research PDFs for scientific foundation
- Add screen directory structure for 64 planned mockup screens

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matt 2026-02-21 22:58:58 +01:00
parent 0835cadfd9
commit 040793f806
82 changed files with 14232 additions and 461 deletions

11
.claude/launch.json Normal file
View File

@ -0,0 +1,11 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "mockups",
"runtimeExecutable": "node",
"runtimeArgs": ["./serve-mockups.js"],
"port": 8090
}
]
}

View File

@ -0,0 +1,12 @@
{
"permissions": {
"allow": [
"Bash(dir:*)",
"Bash(git init:*)",
"Bash(git remote add:*)",
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git push:*)"
]
}
}

View File

@ -0,0 +1,31 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<linearGradient id="b1" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#A78BFA"/><stop offset="100%" stop-color="#6D28D9"/></linearGradient>
<linearGradient id="b2" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#60A5FA"/><stop offset="100%" stop-color="#1E40AF"/></linearGradient>
<linearGradient id="b3" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#34D399"/><stop offset="100%" stop-color="#065F46"/></linearGradient>
<linearGradient id="b4" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#FCD34D"/><stop offset="100%" stop-color="#92400E"/></linearGradient>
<linearGradient id="b5" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#F472B6"/><stop offset="100%" stop-color="#9D174D"/></linearGradient>
<linearGradient id="b6" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#818CF8"/><stop offset="100%" stop-color="#3730A3"/></linearGradient>
<linearGradient id="prismatic" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#C4B5FD"/>
<stop offset="25%" stop-color="#93C5FD"/>
<stop offset="50%" stop-color="#6EE7B7"/>
<stop offset="75%" stop-color="#FDE68A"/>
<stop offset="100%" stop-color="#FBCFE8"/>
</linearGradient>
<filter id="glow">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<g transform="translate(200,200)">
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b1)" opacity="0.9"/>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b2)" opacity="0.87" transform="rotate(60)"/>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b3)" opacity="0.87" transform="rotate(120)"/>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b4)" opacity="0.87" transform="rotate(180)"/>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b5)" opacity="0.87" transform="rotate(240)"/>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b6)" opacity="0.82" transform="rotate(300)"/>
<circle r="30" fill="url(#prismatic)" filter="url(#glow)"/>
<circle cx="-6" cy="-8" r="8" fill="white" opacity="0.3"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,175 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<defs>
<!-- Background Gradient -->
<radialGradient id="bgGlow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#0A0E1A" />
<stop offset="100%" stop-color="#050508" />
</radialGradient>
<!-- Center Backlight Glow -->
<radialGradient id="centerLight" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#ffffff" stop-opacity="0.2" />
<stop offset="100%" stop-color="#ffffff" stop-opacity="0" />
</radialGradient>
<!-- Blade Gradients: Amethyst (0°) -->
<linearGradient id="g0_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A78BFA" />
<stop offset="100%" stop-color="#8B5CF6" />
</linearGradient>
<linearGradient id="g0_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#8B5CF6" />
<stop offset="100%" stop-color="#5B21B6" />
</linearGradient>
<!-- Blade Gradients: Sapphire (60°) -->
<linearGradient id="g1_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#93C5FD" />
<stop offset="100%" stop-color="#3B82F6" />
</linearGradient>
<linearGradient id="g1_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3B82F6" />
<stop offset="100%" stop-color="#1D4ED8" />
</linearGradient>
<!-- Blade Gradients: Emerald (120°) -->
<linearGradient id="g2_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6EE7B7" />
<stop offset="100%" stop-color="#10B981" />
</linearGradient>
<linearGradient id="g2_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#10B981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- Blade Gradients: Amber (180°) -->
<linearGradient id="g3_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#FCD34D" />
<stop offset="100%" stop-color="#F59E0B" />
</linearGradient>
<linearGradient id="g3_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F59E0B" />
<stop offset="100%" stop-color="#B45309" />
</linearGradient>
<!-- Blade Gradients: Rose (240°) -->
<linearGradient id="g4_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F9A8D4" />
<stop offset="100%" stop-color="#EC4899" />
</linearGradient>
<linearGradient id="g4_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#EC4899" />
<stop offset="100%" stop-color="#BE185D" />
</linearGradient>
<!-- Blade Gradients: Indigo (300°) -->
<linearGradient id="g5_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A5B4FC" />
<stop offset="100%" stop-color="#6366F1" />
</linearGradient>
<linearGradient id="g5_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6366F1" />
<stop offset="100%" stop-color="#4338CA" />
</linearGradient>
<!-- Prismatic Core Gradient -->
<linearGradient id="prismatic" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#8B5CF6" />
<stop offset="25%" stop-color="#3B82F6" />
<stop offset="50%" stop-color="#10B981" />
<stop offset="75%" stop-color="#F59E0B" />
<stop offset="100%" stop-color="#EC4899" />
</linearGradient>
<!-- Standard Glow Filter -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<!-- Strong Core Glow -->
<filter id="coreGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="12" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<!-- Deep Dark Space Background -->
<rect width="100%" height="100%" fill="url(#bgGlow)" />
<!-- Center Backlight -->
<circle cx="200" cy="200" r="120" fill="url(#centerLight)" />
<!-- The Iris (Rotated by -15 deg to emphasize "The Turn" & "New Angle") -->
<g transform="translate(200, 200) rotate(-15)">
<!--
THE KALEIDOSCOPE SHARDS
Overlapping translucent facets using screen blend mode for emergent colors
-->
<!-- Amethyst Blade (0°) -->
<g transform="rotate(0)" style="mix-blend-mode: screen;">
<!-- Main Outer Face -->
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g0_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round" />
<!-- Inner Crystalline Bevel -->
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g0_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round" />
</g>
<!-- Sapphire Blade (60°) -->
<g transform="rotate(60)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g1_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round" />
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g1_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round" />
</g>
<!-- Emerald Blade (120°) -->
<g transform="rotate(120)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g2_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round" />
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g2_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round" />
</g>
<!-- Amber Blade (180°) -->
<g transform="rotate(180)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g3_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round" />
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g3_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round" />
</g>
<!-- Rose Blade (240°) -->
<g transform="rotate(240)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g4_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round" />
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g4_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round" />
</g>
<!-- Indigo Blade (300°) -->
<g transform="rotate(300)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g5_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round" />
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g5_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round" />
</g>
<!--
THE KALEIDOSCOPE CORE (The Point of Transformation)
Solid hexagonal prism reflecting the mirrors inside the optical instrument
-->
<g filter="url(#coreGlow)">
<!-- Prismatic Hexagon Aperture -->
<polygon points="38,0 19,32.909 -19,32.909 -38,0 -19,-32.909 19,-32.909" fill="url(#prismatic)" />
<!-- Internal Kaleidoscope Mirror Lines -->
<line x1="-38" y1="0" x2="38" y2="0" stroke="#ffffff" stroke-width="1.5" opacity="0.6" />
<line x1="-19" y1="-32.909" x2="19" y2="32.909" stroke="#ffffff" stroke-width="1.5" opacity="0.6" />
<line x1="19" y1="-32.909" x2="-19" y2="32.909" stroke="#ffffff" stroke-width="1.5" opacity="0.6" />
<!-- Center Refraction Point -->
<circle r="4" fill="#ffffff" filter="url(#glow)" />
</g>
<!-- Outer Core Reflection Edge -->
<polygon points="38,0 19,32.909 -19,32.909 -38,0 -19,-32.909 19,-32.909" fill="none" stroke="#ffffff" stroke-width="1" opacity="0.8" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -0,0 +1,333 @@
# Kalei Build Plan — Phases 1 & 2
### From Platform Foundation to Core Experience
**Total Duration:** 58 weeks
**Approach:** Backend-first in Phase 1, then mobile + backend in parallel in Phase 2
---
## Overview
This document consolidates the two core build phases that take Kalei from a configured dev environment to a fully functional app with Mirror, Turn, and Lens experiences end-to-end. Phase 1 lays the platform foundation (auth, schema, AI gateway, safety). Phase 2 builds the user-facing experience on top of that foundation.
```
Phase 1: Platform Foundation (Weeks 1-3)
→ Auth, schema, entitlements, AI gateway, safety, observability
Phase 2: Core Experience Build (Weeks 4-8)
→ Mirror v1, Turn v1, Lens v1, Gallery, end-to-end flows
```
---
# PHASE 1 — Platform Foundation
**Duration:** 23 weeks
**Primary owner:** Backend-first with mobile stub integration
## 1.1 Objective
Build a production-grade platform foundation: robust auth and session model, entitlement checks for free vs. paid plans, core domain schema for Mirror/Turn/Lens, AI gateway scaffold with usage metering, and observability + error handling baseline.
## 1.2 Entry Criteria
Phase 0 exit checklist must be complete.
---
## 1.3 Core Scope
### 1.3.1 API Module Setup
Implement service modules: auth, profiles, entitlements, mirror (session/message skeleton), turn (request skeleton), lens (goal/action skeleton), ai_gateway, usage_cost, safety (precheck skeleton).
Each module needs: route handlers, input/output schema validation, service layer, repository/data access layer, and unit tests.
### 1.3.2 Identity and Access
Implement: email/password registration and login, JWT access token (short TTL), refresh token rotation and revocation, logout all sessions, role model (at least `user`, `admin`).
Security details: hash passwords with Argon2id or bcrypt, store refresh tokens hashed, include device metadata per session.
### 1.3.3 Entitlement Model
Implement plan model now, even before paywall UI is complete.
Suggested plan keys: `free`, `prism`, `prism_plus`.
Implement gates for: turns per day, mirror sessions per week, spectrum access.
Integration approach: no RevenueCat dependency. Ingest App Store Server Notifications and Google Play RTDN notifications directly. Maintain local entitlement snapshots as source of truth for authorization.
### 1.3.4 Data Model (Phase 1 Schema)
Create migrations for: users, profiles, subscriptions, entitlement_snapshots, turns, mirror_sessions, mirror_messages, mirror_fragments, lens_goals, lens_actions, ai_usage_events, safety_events.
Design requirements: every row has `created_at`, `updated_at` where relevant. Index by `user_id` and key query timestamps. Soft delete where legal retention requires it.
### 1.3.5 AI Gateway Scaffold
Implement a strict abstraction now: provider adapter interface, request envelope (feature, model, temperature, timeout), response normalization, token usage extraction, retry + timeout + circuit breaker policy.
Do not expose provider SDK directly in feature modules.
### 1.3.6 Safety Precheck Skeleton
Implement now even if rule set is basic: deterministic keyword precheck, safety event logging, return safety status to caller. Mirror and Turn endpoints must call this precheck before generation.
### 1.3.7 Usage Metering and Cost Guardrails
Implement: per-user usage counters in Redis, endpoint-level rate limit middleware, AI usage event write on every provider call, per-feature daily budget checks.
### 1.3.8 Observability Baseline
Implement: structured logging with request IDs, error tracking to GlitchTip, latency and error metrics per endpoint, AI cost metrics by feature.
---
## 1.4 Build Sequence
**Week 1:**
1. Finalize schema and migration files
2. Implement auth and profile endpoints
3. Add integration tests for auth flows
**Week 2:**
1. Implement entitlements and plan gating middleware
2. Implement AI gateway interface and one real provider adapter
3. Implement Redis rate limits and usage counters
**Week 3:**
1. Implement Mirror and Turn endpoint skeletons with safety precheck
2. Implement Lens goal and action skeleton endpoints
3. Add complete observability hooks and dashboards
---
## 1.5 API Contract — End of Phase 1
**Auth:**
- `POST /auth/register`
- `POST /auth/login`
- `POST /auth/refresh`
- `POST /auth/logout`
- `GET /me`
**Entitlements:**
- `GET /billing/entitlements`
- Webhook endpoints for App Store and Google Play billing event ingestion
**Feature Skeletons:**
- `POST /mirror/sessions`
- `POST /mirror/messages`
- `POST /turns`
- `POST /lens/goals`
## 1.6 Testing Requirements
Minimum automated coverage: auth happy path and invalid credential path, token refresh rotation path, entitlement denial for free limits, safety precheck path for crisis keyword match, AI gateway timeout and fallback behavior. Recommended: basic load test for auth + turn skeleton endpoints.
## 1.7 Phase 1 Deliverables
**Code:** Migration files for core schema, API modules with tests, Redis-backed rate limit and usage tracking, AI gateway abstraction with one provider, safety precheck middleware.
**Operational:** GlitchTip configured, endpoint metrics visible, API runbook for local and staging.
## 1.8 Phase 1 Exit Criteria
You can exit Phase 1 when: core auth model is stable and tested, plan gating is enforced server-side, Mirror/Turn/Lens endpoint skeletons are live, AI calls only happen through AI gateway, logs/metrics/error tracking are active.
## 1.9 Phase 1 Risks
- **Auth complexity balloons early.** Mitigation: keep v1 auth strict but minimal; defer advanced IAM.
- **Schema churn from feature uncertainty.** Mitigation: maintain a schema decision log and avoid premature optimization.
- **Provider coupling in feature code.** Mitigation: enforce gateway adapter pattern in code review.
---
---
# PHASE 2 — Core Experience Build
**Duration:** 35 weeks
**Primary owner:** Mobile + backend in parallel
## 2.1 Objective
Ship Kalei's core user experience end-to-end: Mirror with fragment highlighting and inline reframe, Turn generation with 3 perspectives and micro-action, Lens goals/daily actions/daily focus, Gallery/history views for user continuity.
## 2.2 Entry Criteria
Phase 1 exit checklist complete.
---
## 2.3 Product Scope
### 2.3.1 Mirror (Awareness)
**Required behavior:** User starts mirror session → submits messages → backend runs safety precheck first → backend runs fragment detection on safe content → app highlights detected fragments above confidence threshold → user taps fragment for inline reframe → user closes session and receives reflection summary.
**Backend work:** Finalize `mirror_sessions`, `mirror_messages`, `mirror_fragments`. Add close-session reflection endpoint. Add mirror session list/detail endpoints.
**Mobile work:** Mirror compose UI, highlight rendering for detected fragment ranges, tap-to-reframe interaction card, session close and reflection display.
### 2.3.2 Turn (Kaleidoscope)
**Required behavior:** User submits a fragment or thought → backend runs safety precheck → backend generates 3 reframed perspectives → backend returns micro-action (if-then) → user can save turn to gallery.
**Backend work:** Finalize `turns` table and categories. Add save/unsave state. Add history list endpoint.
**Mobile work:** Turn input and loading animation, display 3 patterns + micro-action, save to gallery and view history.
### 2.3.3 Lens (Direction)
**Required behavior:** User creates one or more goals → app generates or stores daily action suggestions → user can mark actions complete → optional daily affirmation/focus shown.
**Backend work:** Finalize `lens_goals`, `lens_actions`. Daily action generation endpoint. Daily affirmation endpoint through AI gateway.
**Mobile work:** Goal creation UI, daily action checklist UI, completion updates and streak indicator.
### 2.3.4 The Rehearsal (Lens Sub-Feature)
**Required behavior:** User selects "Rehearse" within a Lens goal → backend generates a personalized visualization script (process-oriented, first-person, multi-sensory, with obstacle rehearsal) → app displays as a guided text flow with SVG progress ring → session completes with a follow-up micro-action.
**Backend work:** Rehearsal generation endpoint through AI gateway. Prompt template enforcing: first-person perspective, present tense, multi-sensory detail, process focus, obstacle inclusion, ~10 min reading pace. Cache generated scripts per goal; refresh when actions change. Add `rehearsal_sessions` table.
**Mobile work:** Rehearsal screen (single flowing view with SVG progress ring timer). Step transitions (Grounding → Process → Obstacle → Close). Completion state with generated SVG pattern. Rehearsal history in Gallery.
### 2.3.5 The Ritual (Context-Anchored Daily Flow)
**Required behavior:** User selects a Ritual template (Morning/Evening/Quick) and anchors to a daily context → app delivers a timed, sequenced flow chaining Mirror/Turn/Lens steps → Ritual completion tracked with context consistency metrics.
**Backend work:** `ritual_configs` table (template, anchored time, notification preferences). `ritual_completions` table (timestamp, duration, steps completed). Context consistency calculation logic (same-window tracking per Wood et al.). Ritual notification scheduling.
**Mobile work:** Ritual selection/setup during onboarding or settings. Single flowing Ritual screen with SVG progress segments per step. Step transitions without navigation. Completion state with Ritual pattern. Context consistency display in streaks.
### 2.3.6 The Evidence Wall (Mastery Tracking)
**Required behavior:** System automatically collects proof points from all features (completed actions, saved keepsakes, self-corrections, streak milestones, goal completions, reframe echoes) → Evidence Wall in "You" tab displays as SVG mosaic → AI surfaces evidence contextually when self-efficacy dip detected.
**Backend work:** `evidence_points` table (user_id, type, source_feature, source_id, description, created_at). Background job to detect and log proof points from existing feature activity. Efficacy-dip detection logic (pattern analysis on recent Mirror/Turn language). Evidence surfacing endpoint for contextual AI integration.
**Mobile work:** Evidence Wall view in "You" tab (SVG mosaic grid, color-coded by source). Timeline toggle view. Evidence count badges. Contextual evidence card component for use within Mirror/Turn sessions.
---
## 2.4 Deep Technical Workstreams
### 2.4.1 Prompt and Output Contracts
Create strict prompt templates and JSON output contracts per feature: Mirror fragment detection, Mirror inline reframe, Turn multi-pattern output, Lens daily focus output, Rehearsal visualization script, Evidence Wall contextual surfacing. Require server-side validation of AI output shape before returning to clients.
### 2.4.2 Safety Integration
At this phase safety must be complete for user-facing flows: all Mirror and Turn requests pass safety gate, crisis response path returns resource payload (not reframe payload), safety events are queryable for audit.
### 2.4.3 Entitlement Enforcement
Enforce in API middleware: free turn daily limits, free mirror weekly limits, spectrum endpoint lock for non-entitled users. Add clear response codes and client UI handling for plan limits.
### 2.4.4 Performance Targets
Set targets now and test against them: Mirror fragment detection p95 under 3.5s, Turn generation p95 under 3.5s, client screen transitions under 300ms for cached navigation.
---
## 2.5 Build Plan
**Week 1 (Week 4 overall):**
- Finish Mirror backend and basic mobile UI
- Complete fragment highlight rendering
**Week 2 (Week 5 overall):**
- Finish inline reframe flow and session reflections
- Add Mirror history and session detail view
**Week 3 (Week 6 overall):**
- Finish Turn backend and mobile flow
- Add save/history integration
**Week 4 (Week 7 overall):**
- Finish Lens goals and daily actions
- Add daily focus/affirmation flow
- Build Rehearsal backend + mobile UI (Lens sub-feature)
**Week 5 (Week 8 overall):**
- Build Ritual backend (config, completions, consistency tracking)
- Build Ritual mobile UI (single-flow screen, SVG progress, setup flow)
- Build Evidence Wall backend (proof point collection job, evidence_points table)
**Week 6 (Week 9 overall):**
- Build Evidence Wall mobile UI (mosaic view, timeline, contextual card)
- Wire Evidence Wall contextual surfacing into Mirror/Turn sessions
- Integrate Ritual into onboarding flow
**Week 7 (Week 10 overall — hardening):**
- Optimize latency across all features
- Improve retry and offline handling
- Run end-to-end QA pass across all flows including Ritual → Mirror → Turn → Lens → Evidence
---
## 2.6 Test Plan
**Unit tests:** Prompt builder functions, AI output validators, entitlement middleware, safety decision functions.
**Integration tests:** Full Mirror message lifecycle, full Turn generation lifecycle, Lens action completion lifecycle.
**Manual QA matrix:** Normal usage, plan-limit blocked usage, low-connectivity behavior, crisis-language safety behavior.
## 2.7 Phase 2 Deliverables
**Functional:** Mirror v1 complete, Turn v1 complete, Lens v1 complete (with Rehearsal), Ritual v1 complete, Evidence Wall v1 complete, Gallery/history v1 complete.
**Engineering:** Stable endpoint contracts, documented prompt versions, meaningful test coverage for critical flows, feature-level latency and error metrics.
## 2.8 Phase 2 Exit Criteria
You can exit Phase 2 when: users can complete Mirror → Turn → Lens flow end-to-end, Ritual sequences features into a single daily flow, Rehearsal generates process-oriented visualization scripts, Evidence Wall collects and surfaces proof points, plan limits and safety behavior are consistent and test-backed, no critical P0 bugs in core user paths, telemetry confirms baseline latency and reliability targets.
## 2.9 Phase 2 Risks
- **Output variability from model causes UI breakage.** Mitigation: strict response schema validation and fallback copy.
- **Too much feature scope in one pass.** Mitigation: ship v1 flows first, defer advanced UX polish.
- **Latency drift from complex prompts.** Mitigation: simplify prompts and use cached static context.
---
---
# Cross-Phase Reference
## Combined Timeline
| Week | Phase | Focus |
|------|-------|-------|
| 1 | Phase 1 | Schema, auth, profile endpoints |
| 2 | Phase 1 | Entitlements, AI gateway, rate limits |
| 3 | Phase 1 | Feature skeletons, safety, observability |
| 4 | Phase 2 | Mirror backend + mobile UI |
| 5 | Phase 2 | Mirror inline reframes + history |
| 6 | Phase 2 | Turn backend + mobile flow |
| 7 | Phase 2 | Lens goals + daily actions + Rehearsal |
| 8 | Phase 2 | Ritual (backend + mobile + onboarding) + Evidence Wall backend |
| 9 | Phase 2 | Evidence Wall mobile + contextual surfacing integration |
| 10 | Phase 2 | Hardening, latency, end-to-end QA |
## Dependencies
- Phase 2 Mirror depends on Phase 1 AI gateway + safety precheck
- Phase 2 entitlement enforcement depends on Phase 1 plan gating middleware
- Phase 2 Lens daily actions depend on Phase 1 AI gateway being stable
- All Phase 2 features depend on Phase 1 observability for debugging
## Combined API Surface (End of Phase 2)
**Auth:** register, login, refresh, logout, me
**Billing:** entitlements, App Store + Google Play webhooks
**Mirror:** create session, send message (with fragment detection), close session (with reflection), list sessions, session detail
**Turn:** create turn (with 3 patterns + micro-action), save/unsave, list history
**Lens:** create goal, generate daily actions, complete action, daily affirmation
**Rehearsal:** generate visualization script (per goal), list rehearsal history
**Ritual:** create/update ritual config, start ritual session, complete ritual, list completions, context consistency stats
**Evidence Wall:** list proof points (filterable by type/source), get contextual evidence (for AI surfacing)
**Gallery:** list saved turns + mirror reflections + rehearsal/ritual patterns (unified history)

View File

@ -1,235 +0,0 @@
# Phase 1 - Platform Foundation
Duration: 2-3 weeks
Primary owner: Backend-first with mobile stub integration
## 1. Objective
Build a production-grade platform foundation:
- robust auth and session model
- entitlement checks for free vs paid plans
- core domain schema for Mirror, Turn, and Lens
- AI gateway scaffold with usage metering
- observability and error handling baseline
## 2. Entry Criteria
Phase 0 exit checklist must be complete.
## 3. Core Scope
## 3.1 API Module Setup
Implement service modules:
- auth
- profiles
- entitlements
- mirror (session/message skeleton)
- turn (request skeleton)
- lens (goal/action skeleton)
- ai_gateway
- usage_cost
- safety (precheck skeleton)
Each module needs:
- route handlers
- input/output schema validation
- service layer
- repository/data access layer
- unit tests
## 3.2 Identity and Access
Implement:
- email/password registration and login
- JWT access token (short TTL)
- refresh token rotation and revocation
- logout all sessions
- role model (at least `user`, `admin`)
Security details:
- hash passwords with Argon2id or bcrypt
- store refresh tokens hashed
- include device metadata per session
## 3.3 Entitlement Model
Implement plan model now, even before paywall UI is complete.
Suggested plan keys:
- `free`
- `prism`
- `prism_plus`
Implement gates for:
- turns per day
- mirror sessions per week
- spectrum access
Integration approach:
- no RevenueCat dependency
- ingest App Store Server Notifications directly
- ingest Google Play RTDN notifications directly
- maintain local entitlement snapshots as source of truth for authorization
## 3.4 Data Model (Phase 1 schema)
Create migrations for:
- users
- profiles
- subscriptions
- entitlement_snapshots
- turns
- mirror_sessions
- mirror_messages
- mirror_fragments
- lens_goals
- lens_actions
- ai_usage_events
- safety_events
Design requirements:
- every row has `created_at`, `updated_at` where relevant
- index by `user_id` and key query timestamp
- soft delete where legal retention requires it
## 3.5 AI Gateway Scaffold
Implement a strict abstraction now:
- provider adapter interface
- request envelope (feature, model, temperature, timeout)
- response normalization
- token usage extraction
- retry + timeout + circuit breaker policy
Do not expose provider SDK directly in feature modules.
## 3.6 Safety Precheck Skeleton
Implement now even if rule set is basic:
- deterministic keyword precheck
- safety event logging
- return safety status to caller
Mirror and Turn endpoints must call this precheck before generation.
## 3.7 Usage Metering and Cost Guardrails
Implement:
- per-user usage counters in Redis
- endpoint-level rate limit middleware
- AI usage event write on every provider call
- per-feature daily budget checks
## 3.8 Observability Baseline
Implement:
- structured logging with request IDs
- error tracking to GlitchTip
- latency and error metrics per endpoint
- AI cost metrics by feature
## 4. Detailed Build Sequence
Week 1:
1. Finalize schema and migration files.
2. Implement auth and profile endpoints.
3. Add integration tests for auth flows.
Week 2:
1. Implement entitlements and plan gating middleware.
2. Implement AI gateway interface and one real provider adapter.
3. Implement Redis rate limits and usage counters.
Week 3:
1. Implement Mirror and Turn endpoint skeletons with safety precheck.
2. Implement Lens goal and action skeleton endpoints.
3. Add complete observability hooks and dashboards.
## 5. API Contract Minimum For End Of Phase
Auth:
- `POST /auth/register`
- `POST /auth/login`
- `POST /auth/refresh`
- `POST /auth/logout`
- `GET /me`
Entitlements:
- `GET /billing/entitlements`
- webhook endpoints for App Store and Google Play billing event ingestion
Feature skeleton:
- `POST /mirror/sessions`
- `POST /mirror/messages`
- `POST /turns`
- `POST /lens/goals`
## 6. Testing Requirements
Minimum automated coverage:
- auth happy path and invalid credential path
- token refresh rotation path
- entitlement denial for free limits
- safety precheck path for crisis keyword match
- AI gateway timeout and fallback behavior
Recommended:
- basic load test for auth + turn skeleton endpoints
## 7. Phase Deliverables
Code deliverables:
- migration files for core schema
- API modules with tests
- Redis-backed rate limit and usage tracking
- AI gateway abstraction with one provider
- safety precheck middleware
Operational deliverables:
- GlitchTip configured
- endpoint metrics visible
- API runbook for local and staging
## 8. Exit Criteria
You can exit Phase 1 when:
- core auth model is stable and tested
- plan gating is enforced server-side
- Mirror/Turn/Lens endpoint skeletons are live
- AI calls only happen through AI gateway
- logs, metrics, and error tracking are active
## 9. Risks To Watch
- Risk: auth complexity balloons early.
- Mitigation: keep v1 auth strict but minimal; defer advanced IAM.
- Risk: schema churn from feature uncertainty.
- Mitigation: maintain a schema decision log and avoid premature optimization.
- Risk: provider coupling in feature code.
- Mitigation: enforce gateway adapter pattern in code review.

View File

@ -1,210 +0,0 @@
# Phase 2 - Core Experience Build
Duration: 3-5 weeks
Primary owner: Mobile + backend in parallel
## 1. Objective
Ship Kalei's core user experience end-to-end:
- Mirror with fragment highlighting and inline reframe
- Turn generation with 3 perspectives and micro-action
- Lens goals, daily actions, and daily focus/affirmation flow
- Gallery/history views for user continuity
## 2. Entry Criteria
Phase 1 exit checklist complete.
## 3. Product Scope In This Phase
## 3.1 Mirror (Awareness)
Required behavior:
- user starts mirror session
- user submits messages
- backend runs safety precheck first
- backend runs fragment detection on safe content
- app highlights detected fragments above confidence threshold
- user taps fragment for inline reframe
- user closes session and receives reflection summary
Backend work:
- finalize `mirror_sessions`, `mirror_messages`, `mirror_fragments`
- add close-session reflection endpoint
- add mirror session list/detail endpoints
Mobile work:
- mirror compose UI
- highlight rendering for detected fragment ranges
- tap-to-reframe interaction card
- session close and reflection display
## 3.2 Turn (Kaleidoscope)
Required behavior:
- user submits a fragment or thought
- backend runs safety precheck
- backend generates 3 reframed perspectives
- backend returns micro-action (if-then)
- user can save turn to gallery
Backend work:
- finalize `turns` table and categories
- add save/unsave state
- add history list endpoint
Mobile work:
- turn input and loading animation
- display 3 patterns + micro-action
- save to gallery and view history
## 3.3 Lens (Direction)
Required behavior:
- user creates one or more goals
- app generates or stores daily action suggestions
- user can mark actions complete
- optional daily affirmation/focus shown
Backend work:
- finalize `lens_goals`, `lens_actions`
- daily action generation endpoint
- daily affirmation endpoint through AI gateway
Mobile work:
- goal creation UI
- daily action checklist UI
- completion updates and streak indicator
## 4. Deep Technical Workstreams
## 4.1 Prompt and Output Contracts
Create strict prompt templates and JSON output contracts per feature:
- Mirror fragment detection
- Mirror inline reframe
- Turn multi-pattern output
- Lens daily focus output
Require server-side validation of AI output shape before returning to clients.
## 4.2 Safety Integration
At this phase safety must be complete for user-facing flows:
- all Mirror and Turn requests pass safety gate
- crisis response path returns resource payload, not reframe payload
- safety events are queryable for audit
## 4.3 Entitlement Enforcement
Enforce in API middleware:
- free turn daily limits
- free mirror weekly limits
- spectrum endpoint lock for non-entitled users
Add clear response codes and client UI handling for plan limits.
## 4.4 Performance Targets
Set targets now and test against them:
- Mirror fragment detection p95 under 3.5s
- Turn generation p95 under 3.5s
- client screen transitions under 300ms for cached navigation
## 5. Detailed Build Plan
Week 1:
- finish Mirror backend and basic mobile UI
- complete fragment highlight rendering
Week 2:
- finish inline reframe flow and session reflections
- add Mirror history and session detail view
Week 3:
- finish Turn backend and mobile flow
- add save/history integration
Week 4:
- finish Lens goals and daily actions
- add daily focus/affirmation flow
Week 5 (optional hardening week):
- optimize latency
- improve retry and offline handling
- run end-to-end QA pass
## 6. Test Plan
Unit tests:
- prompt builder functions
- AI output validators
- entitlement middleware
- safety decision functions
Integration tests:
- full Mirror message lifecycle
- full Turn generation lifecycle
- Lens action completion lifecycle
Manual QA matrix:
- normal usage
- plan-limit blocked usage
- low-connectivity behavior
- crisis-language safety behavior
## 7. Deliverables
Functional deliverables:
- Mirror v1 complete
- Turn v1 complete
- Lens v1 complete
- Gallery/history v1 complete
Engineering deliverables:
- stable endpoint contracts
- documented prompt versions
- meaningful test coverage for critical flows
- feature-level latency and error metrics
## 8. Exit Criteria
You can exit Phase 2 when:
- users can complete Mirror -> Turn -> Lens flow end-to-end
- plan limits and safety behavior are consistent and test-backed
- no critical P0 bugs in core user paths
- telemetry confirms baseline latency and reliability targets
## 9. Risks To Watch
- Risk: output variability from model causes UI breakage.
- Mitigation: strict response schema validation and fallback copy.
- Risk: too much feature scope in one pass.
- Mitigation: ship v1 flows first, defer advanced UX polish.
- Risk: latency drift from complex prompts.
- Mitigation: simplify prompts and use cached static context.

View File

@ -0,0 +1,292 @@
# Kalei — The Science Behind Every Turn
### How Peer-Reviewed Research Powers Every Feature in the App
**Version:** 1.0 · February 2026
**Purpose:** Map every Kalei feature to its scientific foundation, ensuring real cognitive science is woven into the user journey — not as decoration, but as structural integrity.
---
## Why This Document Exists
Kalei's core differentiator is that it treats "manifestation" as what it actually is: a structured psychological process operating through known cognitive and behavioral mechanisms. Every feature in the app should be traceable back to published, peer-reviewed research. This document is the bridge between our research library and the product — a reference for anyone building, writing, or designing any part of Kalei.
The rule is simple: **if we can't cite it, we don't claim it.**
---
## The Research Library — 7 Pillars
Our research base spans 16 peer-reviewed papers across 7 scientific domains. Each domain maps directly to one or more of Kalei's 6 Steps and core features.
| # | Research Pillar | Papers | Primary Kalei Feature(s) |
|---|---|---|---|
| 1 | Goal Setting & Implementation | 4 | Step 1: Decide (Clarity) · Step 5: Act in Alignment · The Lens |
| 2 | Visualization & Mental Imagery | 3 | Step 2: See It · Guided Visualizations |
| 3 | Self-Efficacy | 1 | Step 3: Believe It's Possible (But Not Guaranteed) · The Turn |
| 4 | Attention & Neuroscience | 3 | Step 4: Notice Differently · The Mirror · The Reframer |
| 5 | Habit Formation | 2 | Step 6: Repeat and Compound · Streaks & Rituals |
| 6 | Placebo & Expectation Effects | 2 | Overall framework · Onboarding · Belief calibration |
| 7 | Social Networks | 1 | Future community features · The Spectrum |
---
## Pillar 1: Goal Setting & Implementation
### The Science
**Locke & Latham (2002)** — *Building a Practically Useful Theory of Goal Setting and Task Motivation: A 35-Year Odyssey*
The foundational paper on goal-setting theory, drawn from over 35 years of research. Core finding: specific, challenging goals consistently lead to higher performance than vague "do your best" goals. The mechanism works through four channels — goals direct attention, energize effort, increase persistence, and promote the discovery of task-relevant strategies.
**Locke & Latham (2006)** — *New Directions in Goal-Setting Theory*
Extends the original theory with moderators and mediators. Goals work best when paired with high self-efficacy, feedback loops, and commitment. Critically, goal complexity matters — overly complex goals without adequate learning time can backfire. This informs how Kalei scaffolds goals progressively rather than demanding perfection upfront.
**Gollwitzer (1999)** — *Implementation Intentions: Strong Effects of Simple Plans*
The landmark paper on "if-then" planning. When people form implementation intentions ("If situation X arises, I will do Y"), follow-through rates increase dramatically — in some studies doubling or tripling goal attainment. The mechanism: implementation intentions create strong mental links between situational cues and planned responses, effectively delegating action initiation to environmental triggers rather than relying on willpower.
**Gollwitzer & Sheeran** — *Implementation Intentions*
A comprehensive overview confirming that implementation intentions are most effective when self-regulatory problems threaten goal striving and when backed by strong, activated goal intentions. The if-then format works because it puts people in a position to both *see* and *seize* opportunities to act.
### Where It Lives in Kalei
**Step 1: Decide (Clarity)** — The Lens feature guides users through defining exactly what they want, using AI to help them move from vague wishes ("I want to be happier") to specific, challenging goals ("I want to complete a 5K run by June, training 3x per week"). The AI draws on Locke & Latham's specificity principle: the more precise the goal, the more it directs attention and effort.
**Step 5: Act in Alignment** — Every micro-action the AI generates follows Gollwitzer's if-then format. Instead of "exercise more," Kalei produces: "If it's 7am on Monday/Wednesday/Friday, then I put on my running shoes and walk out the front door." This isn't a style choice — it's the most empirically validated action-planning format in psychology.
**The Lens (Manifestation Engine)** — The entire goal-creation flow is structured around Locke & Latham's principles: clarity of outcome, challenge calibration (not too easy, not impossibly hard), commitment rituals, and built-in feedback loops through progress tracking.
**Design implications:**
- Goal inputs should guide toward specificity (prompts, not blank fields)
- Challenge level should be calibrated — the AI should push back on goals that are too vague or too easy
- Implementation intentions should always use the literal "If... then..." structure
- Progress feedback should be frequent and visible
---
## Pillar 2: Visualization & Mental Imagery
### The Science
**Schuster et al. (2011)** — *Best Practice for Motor Imagery: A Systematic Literature Review*
A massive cross-disciplinary review across education, medicine, music, psychology, and sports. Key finding: motor imagery (mentally rehearsing actions) is most effective when combined with physical practice, when sessions are structured with clear protocols, and when the imagery is vivid and first-person. Pure fantasy without behavioral specificity doesn't work — the visualization must be *process-oriented*, not just outcome-oriented.
**Liu et al. (2025)** — *Effects of Imagery Practice on Athletes' Performance: A Multilevel Meta-Analysis*
A meta-analysis of 86 studies with 3,593 athletes confirming that imagery practice enhances performance across agility, strength, and sport-specific skills. The optimal dosage: approximately 10 minutes, 3 times per week, over about 100 days. Combining imagery with 1-2 additional psychological skills (like self-talk or goal setting) produces stronger effects than imagery alone.
**Seok & Choi (2023)** — *The Impact of Mental Practice on Motor Function in Patients With Stroke*
A systematic review and meta-analysis demonstrating that mental practice facilitates motor recovery in stroke patients — evidence that visualization activates overlapping neural circuits with actual physical execution, even when the body cannot currently perform the action.
### Where It Lives in Kalei
**Step 2: See It (Mental Rehearsal)** — Kalei generates personalized visualization scripts that guide users through mentally rehearsing the *process* of achieving their goal, not just imagining the end state. This distinction is critical: the research shows process visualization (imagining yourself studying, training, preparing) outperforms outcome visualization (imagining yourself on the podium).
**Guided Visualization Sessions** — Following Schuster et al.'s best-practice findings, Kalei's visualization prompts are first-person, sensory-rich, and process-focused. The AI asks users to engage multiple senses: what do you see, hear, feel? The recommended frequency (Liu et al.'s finding of ~10 minutes, 3x/week) informs the suggested cadence of visualization reminders.
**Design implications:**
- Visualization scripts must be process-oriented, not just outcome fantasy
- First-person perspective, multi-sensory detail
- Sessions should be ~10 minutes, suggested 3x per week
- Combine visualization with goal-setting and self-talk elements for maximum effect
- Never present visualization as sufficient alone — always pair with action steps
---
## Pillar 3: Self-Efficacy
### The Science
**Bandura (1977)** — *Self-Efficacy: Toward a Unifying Theory of Behavioral Change*
One of the most cited papers in all of psychology. Bandura's core claim: the belief in one's *capability* to execute specific behaviors is the strongest predictor of whether someone will attempt, sustain, and succeed at a goal. Self-efficacy is not general confidence — it's domain-specific belief that "I can do this particular thing."
Four sources build self-efficacy, in order of potency:
1. **Mastery experiences** — successfully doing the thing (strongest source)
2. **Vicarious experience** — watching someone similar succeed
3. **Verbal persuasion** — being told you can do it (weakest but still real)
4. **Physiological states** — interpreting your emotional/physical state as capability vs. inadequacy
Critically, Bandura distinguishes *efficacy expectations* (I can do it) from *outcome expectations* (doing it will produce results). Both matter, but self-efficacy is the bottleneck — people don't attempt what they don't believe they can execute.
### Where It Lives in Kalei
**Step 3: Believe It's Possible — But Not Guaranteed** — This is the philosophical soul of Kalei. The app explicitly rejects certainty-based belief ("the universe will provide") in favor of Bandura's capability-based belief ("I have or can develop the skills to make this happen"). This single distinction separates Kalei from every magical-thinking manifestation app on the market.
**The Turn (Reframing Engine)** — When users submit a negative thought, the AI reframe is designed to build self-efficacy, not just provide comfort. A good reframe should help users:
- Recognize past mastery experiences ("You've handled difficult things before — remember when...")
- Reinterpret physiological states ("That anxiety isn't proof you can't do this — it's your body preparing to perform")
- Shift from outcome fixation to capability focus ("You can't control whether you get the job, but you can control how well you prepare")
**Onboarding & Belief Calibration** — The coaching style selection (brutal honesty, gentle guidance, logical analysis, etc.) maps to Bandura's verbal persuasion channel. Different people respond to different persuasion styles. A skeptic needs logical arguments for capability; someone more emotionally oriented needs warmth and encouragement. The coaching style personalizes the persuasion channel.
**Design implications:**
- Reframes should target capability belief, never promise outcomes
- Track and surface mastery experiences ("You've completed 12 micro-actions this week")
- Coaching tone selection = personalizing the verbal persuasion channel
- Never say "you will succeed" — say "you have what it takes to give this your best shot"
- Celebrate effort and execution, not just outcomes
---
## Pillar 4: Attention & Neuroscience
### The Science
**Yantis (2008)** — *The Neural Basis of Selective Attention: Cortical Sources and Targets of Attentional Modulation*
Selective attention is an intrinsic component of how the brain processes reality. Modulatory signals from frontal and parietal cortex amplify neural responses to relevant information and suppress irrelevant inputs. What you attend to literally changes what your brain represents — attention isn't just noticing, it's constructing your experienced reality.
**Stevens & Bavelier (2012)** — *The Role of Selective Attention on Academic Foundations*
Attention is trainable. This paper demonstrates that selective attention underlies learning, memory, and skill acquisition. Crucially, attention training transfers — improving attentional control in one domain can enhance performance broadly. The brain's attentional system is plastic and responsive to practice.
**Koch & Tsuchiya** — *Attention and Consciousness: Two Distinct Brain Processes*
A critical theoretical paper distinguishing attention from consciousness. You can attend to things without being conscious of them, and you can be conscious of things without attending to them. This matters for Kalei because it means that training attention (a controllable process) can shift what enters conscious awareness (what feels like "reality") — without requiring mystical explanations.
### Where It Lives in Kalei
**Step 4: Notice Differently** — After setting a goal and building belief, Kalei trains users to notice differently. This isn't "the universe sending signs" — it's Yantis's selective attention at work. When you define a goal, your brain's attentional filters begin prioritizing goal-relevant information. Opportunities that were always there become visible because your attentional system is now tuned to detect them.
**The Mirror (Freeform Notebook)** — The Mirror feature directly applies attentional science. As users write freely, Kalei's AI detects cognitive distortion patterns (catastrophizing, black-and-white thinking, etc.) and gently highlights them. This is attention training in action: the AI acts as an external attentional spotlight, pointing at patterns the user's own attentional system has habituated to and therefore stopped noticing.
**The Reframer's Pattern Analysis** — Over time, the app analyzes which cognitive distortions appear most frequently in a user's Turns and Mirror sessions. This longitudinal attention data helps users see their own attentional biases — "You tend to catastrophize most on Sunday evenings" — turning unconscious attentional habits into conscious, addressable patterns.
**Design implications:**
- Frame "noticing" in neurological terms, never mystical ones
- The Mirror's highlighting is literally externalized attentional modulation
- Pattern analytics should reveal attentional biases over time
- Use language like "your brain is filtering for this now" not "the universe is showing you signs"
---
## Pillar 5: Habit Formation
### The Science
**Wood & Neal (2007)** — *A New Look at Habits and the Habit-Goal Interface*
Habits form through the gradual learning of associations between responses and context features (physical settings, time of day, preceding actions). Once formed, perception of the context triggers the habitual response *without a mediating goal* — the behavior becomes automatic. Goals can direct habit formation (by motivating repetition) but once habits are established, they run on context cues, not intentions.
**Wood, Mazar & Neal (2021)** — *Habits and Goals in Human Behavior: Separate but Interacting Systems*
Extends the 2007 model: habits and goals are separate cognitive systems that interact. ~43% of daily behavior is habitual. Habit change requires disrupting the context-response link — either by changing contexts, or by introducing friction into the habitual response. For building new habits, the key is consistent repetition in stable contexts until the behavior becomes automatic.
### Where It Lives in Kalei
**Step 6: Repeat and Compound** — The final step in Kalei's manifestation system is explicitly about habit formation. The app helps users build daily rituals — consistent, context-anchored micro-actions that compound over time. The AI generates context-specific triggers ("Every morning after your first coffee, open Kalei and do one Turn") because Wood's research shows that context stability is the single biggest predictor of habit formation.
**Streaks & Ritual Tracking** — Kalei's streak system isn't gamification for its own sake — it's measuring the repetition that Wood et al. show is necessary for habit crystallization. The app tracks not just frequency but context consistency ("You've done your morning Turn at roughly the same time for 18 days — this is becoming automatic").
**The Mirror as Habitual Practice** — Regular Mirror sessions train the habit of self-reflection. Over time, the act of writing and examining thoughts becomes an automatic response to stress or uncertainty, rather than requiring conscious effort each time.
**Design implications:**
- Always pair actions with specific context cues (time, location, preceding action)
- Streak tracking should emphasize context consistency, not just count
- Frame habit formation as ~66 days of consistent repetition (Lally et al.'s median)
- Celebrate automaticity milestones ("This is becoming second nature")
- When habits break, help users rebuild the context-response link rather than relying on willpower
---
## Pillar 6: Placebo & Expectation Effects
### The Science
**Pardo-Cabello et al. (2022)** — *Placebo: A Brief Updated Review*
A comprehensive review of placebo/nocebo effects across medicine. The placebo effect has been observed across multiple medical conditions and administration routes. Key finding: expectations directly influence physiological and behavioral outcomes. The doctor-patient relationship (or in Kalei's case, the app-user relationship) is the most important factor in whether expectation effects materialize. The psycho-neurobiological mechanisms are real and measurable.
**Stetler (2014)** — *Adherence, Expectations, and the Placebo Response*
Investigates why adherence to even inert treatments produces health benefits. The model: initial expectations shape behavior and physiological responses, and consistent adherence reinforces those expectations in a positive feedback loop. This is not "it's all in your head" — it's "what's in your head measurably changes what happens in your body and behavior."
### Where It Lives in Kalei
**The Overall Framework** — Kalei's entire approach leverages expectation effects honestly. We don't hide the mechanism — we explain it. Telling users "structured positive expectation, when combined with action, measurably improves outcomes" is both scientifically accurate and itself a form of positive expectation setting. The transparency is the feature.
**Onboarding & Science Education** — When users first encounter Kalei, the app explains *why* it works, citing real research. This serves two purposes: (1) it builds credibility with our skeptic-friendly audience, and (2) it primes legitimate expectation effects. Understanding that these mechanisms are real makes them more effective, not less — unlike placebos in medicine, where disclosure sometimes weakens the effect, in behavioral change, understanding the mechanism often strengthens engagement.
**Belief Calibration** — Stetler's finding about adherence reinforcing expectations informs Kalei's emphasis on daily practice. The more consistently users engage, the stronger their expectation of benefit becomes, which in turn increases the actual benefit. This is not circular logic — it's a documented feedback loop.
**Design implications:**
- Always explain the science behind features — transparency strengthens engagement
- The app-user relationship quality matters (tone, personalization, responsiveness)
- Consistent engagement creates a positive expectation-behavior feedback loop
- Frame this honestly: "Expectation shapes behavior. We're using that deliberately and transparently."
- Never hide the mechanism or pretend Kalei works through unknown forces
---
## Pillar 7: Social Networks & Community
### The Science
**Granovetter (1973)** — *The Strength of Weak Ties*
One of the most influential papers in sociology. Granovetter demonstrates that transformative opportunities — new jobs, novel information, unexpected connections — come disproportionately from *weak ties* (acquaintances, distant contacts) rather than strong ties (close friends, family). Strong ties tend to share overlapping information; weak ties bridge different social worlds and provide access to non-redundant resources.
### Where It Lives in Kalei
**Future Community Features (The Spectrum)** — When Kalei eventually adds social features, Granovetter's weak-ties theory informs the design. Anonymous sharing of reframes, goals, and breakthroughs creates a network of weak ties — users inspiring other users they'll never meet. The value isn't in building close friendships within the app (strong ties) but in being unexpectedly inspired by someone else's Turn on a problem you share (weak ties).
**Design implications:**
- Community features should optimize for weak-tie connections (diverse, anonymous, cross-context)
- Don't try to build a social network — build a constellation of shared perspectives
- Anonymous or pseudonymous sharing preserves the weak-tie benefit (no obligation, no social pressure)
- Surface unexpected resonance: "42 other people Turned a similar thought this week"
---
## The Chain: How the 7 Pillars Create the Manifestation Mechanism
The research pillars aren't independent — they form a causal chain:
```
Clear Goal (Locke & Latham)
→ biases attention toward goal-relevant information (Yantis, Stevens & Bavelier)
→ mental rehearsal primes execution (Schuster, Liu, Seok)
→ capability belief sustains effort through setbacks (Bandura)
→ if-then plans automate action initiation (Gollwitzer)
→ repetition builds automatic habits (Wood & Neal)
→ consistent practice reinforces positive expectations (Stetler, Pardo-Cabello)
→ broader action increases exposure to opportunity (Granovetter)
→ probability of desired outcome increases
```
This is what "manifestation" actually is: a chain of well-documented psychological mechanisms that compound to tilt probability in your favor. Not magic. Not metaphysics. Not "the universe." Just your brain doing what brains do when properly directed.
---
## Quick Reference: Feature → Science Map
| Kalei Feature | Primary Research | Key Principle |
|---|---|---|
| **The Lens** (goal creation) | Locke & Latham 2002, 2006 | Specific, challenging goals with feedback |
| **The Turn** (reframing) | Bandura 1977; Yantis 2008 | Capability belief + attentional retraining |
| **The Mirror** (freeform notebook) | Stevens & Bavelier 2012; Koch & Tsuchiya | Externalized attentional spotlight |
| **The Rehearsal** (guided visualization) | Schuster 2011; Liu 2025; Seok 2023 | Process-oriented mental rehearsal (~10min, 3x/week) |
| **The Ritual** (daily flow) | Wood & Neal 2007; Wood et al. 2021 | Context-anchored habit formation; context stability |
| **The Evidence Wall** (mastery tracking) | Bandura 1977 | Mastery experiences (strongest efficacy source) |
| **If-Then Micro-Actions** | Gollwitzer 1999; Gollwitzer & Sheeran | Implementation intentions |
| **Coaching Styles** | Bandura 1977 | Personalized verbal persuasion |
| **Pattern Analytics** | Yantis 2008; Stevens & Bavelier 2012 | Revealing attentional biases |
| **Science Explanations** | Pardo-Cabello 2022; Stetler 2014 | Transparent expectation effects |
| **Community (future)** | Granovetter 1973 | Weak-tie opportunity exposure |
---
## Guardrails: What the Science Does NOT Support
Just as important as what we cite is what we explicitly reject:
1. **"The universe responds to your thoughts"** — No research supports metaphysical causation. We never imply it.
2. **"Visualize and it will happen"** — Outcome-only visualization without action can actually *decrease* performance (by providing premature satisfaction). We always pair visualization with process focus and action steps.
3. **"Believe hard enough and you'll succeed"** — Bandura's self-efficacy is about capability belief, not outcome certainty. We always say "possible, not guaranteed."
4. **"Positive thinking cures everything"** — Toxic positivity. Kalei acknowledges real constraints, structural barriers, and randomness. The science improves odds — it doesn't eliminate uncertainty.
5. **"You attracted your problems"** — Victim-blaming disguised as empowerment. Never. The attentional science explains perception, not causation.
---
## How to Use This Document
**For developers:** When building a feature, check this doc to understand the scientific principle behind it. The AI prompts, UX copy, and interaction patterns should all reflect the cited research.
**For AI prompt engineering:** Every reframe, visualization script, and goal scaffold should be traceable to a specific pillar. If a prompt produces output that contradicts the research (e.g., promising guaranteed outcomes), it needs revision.
**For content and copy:** When writing user-facing text — onboarding, tooltips, push notifications, feature descriptions — ground it in the relevant pillar. Users should feel the science without needing to read papers.
**For marketing:** "Science-backed" is not a buzzword for Kalei. It's a specific claim backed by 16 peer-reviewed papers across 7 research domains. This document is the receipt.
---
*Same pieces. New angle. Real science.*

View File

@ -0,0 +1,112 @@
Final Conclusion: What “Manifesting” Really Is (Scientifically)
When stripped of spiritual language, “manifesting” is a structured psychological process that increases the probability of desired outcomes through well-documented cognitive and behavioral mechanisms.
It does not mean:
Reality bends to thought.
The universe delivers outcomes on demand.
Belief overrides randomness.
It does mean:
1⃣ Clear Goals Change Performance
Research on goal-setting shows that specific, challenging goals direct attention, increase effort, and improve persistence.
Clarity is not motivational fluff — it changes how the brain allocates cognitive resources.
2⃣ Mental Rehearsal Primes Execution
Visualization activates overlapping neural circuits used in real performance.
When used as behavioral rehearsal (not fantasy), it improves readiness, confidence, and execution quality.
3⃣ Self-Efficacy Changes Behavior
Belief in capability (self-efficacy) predicts:
Greater effort
Longer persistence
Better stress tolerance
Faster recovery from setbacks
Belief influences behavior — behavior influences outcomes.
4⃣ Attention Is Biased by Goals
The brain filters information according to relevance.
When you define a goal, you increase the likelihood of noticing:
Opportunities
Relevant information
Signals
Threats
You dont create opportunities out of nothing — you detect them more effectively.
5⃣ Planning Automates Action
Implementation intentions (“If X happens, I do Y”) dramatically increase follow-through.
This reduces reliance on willpower and increases consistency.
6⃣ Repetition Builds Habits
Repeated, goal-aligned behaviors become automatic over time.
Once habits form, less conscious effort is required — increasing long-term probability of success.
7⃣ Exposure Increases Opportunity
Network research shows that broader exposure (especially weak ties) increases access to opportunities.
Repeated aligned action increases surface area for luck.
The Core Mechanism
Clear intention
→ biases attention
→ increases belief-driven persistence
→ improves quality and frequency of action
→ expands exposure to opportunity
→ increases probability of desired outcomes
Thats it.
The Real Conclusion
“Manifesting” is not mystical causation.
It is:
Goal-directed cognition
Expectancy effects
Behavioral alignment
Habit formation
Increased opportunity exposure
Compounded probability
It works because it operates through known psychological and social mechanisms, not because it overrides reality.
The Honest Boundary
This process:
Improves odds
Does not guarantee outcomes
Cannot eliminate randomness
Cannot override structural constraints
But over time, it systematically tilts probability in your favor.

View File

@ -279,6 +279,19 @@ AI-generated weekly summary covering:
- Level-ups tied to *consistency* (not volume — doing it daily matters more than doing 10 in one day) - Level-ups tied to *consistency* (not volume — doing it daily matters more than doing 10 in one day)
- No leaderboards, no competitive mechanics. This is personal transformation, not a game. - No leaderboards, no competitive mechanics. This is personal transformation, not a game.
### Connector Features (Science-Driven Engagement)
These three features weave the core pillars into a cohesive daily practice. Each directly implements a research pillar that was underserved by the core feature set.
**The Rehearsal (Guided Visualization — Lens sub-feature):**
Step 2 (See It) implemented as a concrete feature. AI-generated, personalized mental rehearsal scripts tied to the user's active Lens goals. Following Schuster et al.'s best-practice protocol and Liu et al.'s optimal dosage (~10 min, 3x/week), each Rehearsal walks users through the *process* of achieving their goal in first-person, present-tense, multi-sensory detail — including obstacle rehearsal to prevent the toxic positivity trap. Always paired with a follow-up micro-action. All visuals are SVG-generated (progress rings, completion patterns).
**The Ritual (Context-Anchored Daily Flow):**
Step 6 (Repeat and Compound) implemented as active habit scaffolding, not just passive streak tracking. A timed, sequenced daily flow (Morning/Evening/Quick templates) that chains 2-3 Kalei activities into one context-anchored routine. Directly implements Wood & Neal's (2007) core finding that context stability predicts habit formation. The user builds *one habit* ("my morning Ritual") instead of three separate ones. The Ritual tracks context consistency (same time, same sequence) per Wood et al. (2021), not just frequency. Addresses the week 3-4 retention cliff by making daily usage automatic before novelty fades. UI is a single flowing screen with SVG progress segments — no navigation, no friction.
**The Evidence Wall (Mastery Tracking — You tab):**
Upgrades Kalei's self-efficacy building from Bandura's weakest source (verbal persuasion via reframes) to his *strongest* source (mastery experiences). Automatically collects proof of capability from all features: completed micro-actions, saved keepsakes, self-correction moments, streak milestones, goal completions, reframe echoes in later writing. The AI surfaces this evidence contextually when it detects self-efficacy dips — "Here's what I've seen: you've completed 23 micro-actions this month." Visual design is a growing SVG mosaic of color-coded geometric proof-point tiles. Evidence, not cheerleading.
--- ---
## 6. User Experience Flows ## 6. User Experience Flows

View File

@ -16,9 +16,11 @@ This isn't toxic positivity. A kaleidoscope doesn't pretend the glass isn't brok
--- ---
## The Four Pillars ## The Core System
Kalei is built on four optical instruments. Each one does something different with light. Together, they form a complete system for seeing your life from new angles. Kalei is built on four optical instruments plus three science-driven engagement features. The optical instruments are the primary experience. The engagement features weave them into a cohesive daily practice.
### The Four Pillars
| Pillar | Feature | Optical Element | User Need | Phase | | Pillar | Feature | Optical Element | User Need | Phase |
|--------|---------|----------------|-----------|-------| |--------|---------|----------------|-----------|-------|
@ -27,7 +29,15 @@ Kalei is built on four optical instruments. Each one does something different wi
| **Direction** | The Lens | Lens | "I need to move forward" | Phase 1 | | **Direction** | The Lens | Lens | "I need to move forward" | Phase 1 |
| **Intelligence** | The Spectrum | Prism | "I need to understand myself" | Phase 2 | | **Intelligence** | The Spectrum | Prism | "I need to understand myself" | Phase 2 |
These four pillars form a natural progression: ### The Three Connectors
| Feature | Science Pillar | User Need | Phase |
|---------|---------------|-----------|-------|
| **The Rehearsal** | Visualization & Mental Imagery (Schuster, Liu, Seok) | "I need to prepare" | Phase 1 (Lens sub-feature) |
| **The Ritual** | Habit Formation (Wood & Neal) | "I need consistency" | Phase 1 |
| **The Evidence Wall** | Self-Efficacy: Mastery Experiences (Bandura) | "I need proof I can do this" | Phase 1 (You tab) |
### How They Flow Together
``` ```
THE MIRROR THE KALEIDOSCOPE THE LENS THE SPECTRUM THE MIRROR THE KALEIDOSCOPE THE LENS THE SPECTRUM
@ -41,9 +51,22 @@ writing reframing manifestation self-knowled
Fragments Fragments → Patterns Patterns → Focus All data → Insight Fragments Fragments → Patterns Patterns → Focus All data → Insight
detected revealed applied understood detected revealed applied understood
↕ ↕
THE RITUAL THE REHEARSAL
(Daily Flow) (Mental Preparation)
Sequences all Visualizes the
features into process of getting
one habit there
THE EVIDENCE WALL
(Proof of Capability)
Collects mastery evidence
from all features
``` ```
Not every session follows this sequence. Some days you just need a quick Turn. Some days you just need to write in the Mirror. Some days you go straight to the Lens. But when a user flows through all four, that's the **Kalei experience** at its deepest — and the Spectrum ties it all together with longitudinal intelligence. Not every session follows this sequence. Some days you just need a quick Turn. Some days you just need to write in the Mirror. Some days you go straight to the Lens. But the **Ritual** makes the daily practice automatic, the **Rehearsal** makes the goals vivid, and the **Evidence Wall** makes the progress undeniable.
--- ---
@ -108,6 +131,12 @@ Every app builds an unconscious vocabulary through the words it uses in buttons,
> *The mirror doesn't tell you what to see. It shows you what's already there.* > *The mirror doesn't tell you what to see. It shows you what's already there.*
### Scientific Basis
The Mirror is grounded in selective attention research. Yantis (2008) demonstrated that selective attention is an intrinsic component of perception — what you attend to literally shapes what your brain represents. Stevens & Bavelier (2012) showed that attentional control is trainable and transfers across domains. Koch & Tsuchiya's work distinguishing attention from consciousness means that training attention (a controllable process) can shift what enters conscious awareness without requiring mystical explanations.
The Mirror applies this by acting as an external attentional spotlight — pointing at cognitive patterns the user's own attentional system has habituated to and stopped noticing. The AI doesn't create insight; it redirects attention toward what was always there.
### Concept ### Concept
The Kaleidoscope (Turn) is structured: one fragment in, patterns out. It works when you **know** what's bothering you. The Kaleidoscope (Turn) is structured: one fragment in, patterns out. It works when you **know** what's bothering you.
@ -242,6 +271,10 @@ The Reflection is saved to the Gallery as a distinct type: a Mirror Reflection.
> *The Kaleidoscope helps you see beauty in what's already there.* > *The Kaleidoscope helps you see beauty in what's already there.*
### Scientific Basis
The Turn draws on two research pillars. First, Bandura's self-efficacy theory (1977): every reframe is designed to build capability belief, not provide comfort. The AI shifts users from outcome fixation ("Will this work out?") to capability focus ("What can I do about this?") — directly implementing Bandura's finding that efficacy expectations are the strongest predictor of behavioral change. Second, the attentional retraining from Yantis (2008) and Stevens & Bavelier (2012): each Turn is an exercise in redirecting attention from threat-focused perception to opportunity-aware perception. Repeated Turns train the brain's attentional filters to automatically surface alternative interpretations.
### Concept ### Concept
The flagship feature. User inputs a negative thought (a fragment), and Kalei reveals multiple reframed perspectives (patterns). This is the core mechanic — structured, immediate, and satisfying. The flagship feature. User inputs a negative thought (a fragment), and Kalei reveals multiple reframed perspectives (patterns). This is the core mechanic — structured, immediate, and satisfying.
@ -291,6 +324,14 @@ arranged in a way the user hadn't seen before."
> *The Lens helps you focus on what's ahead.* > *The Lens helps you focus on what's ahead.*
### Scientific Basis
The Lens is built on three pillars of the research. Locke & Latham's goal-setting theory (2002, 2006) provides the structure: specific, challenging goals with feedback loops consistently outperform vague aspirations. The AI-guided goal creation process implements their specificity principle directly — moving users from "I want to be healthier" to measurable, time-bound commitments.
Gollwitzer's implementation intentions (1999) power every micro-action the Lens generates. The "if-then" format ("If it's 7am Monday, then I put on my running shoes") dramatically increases follow-through by delegating action initiation to environmental cues rather than willpower.
The visualization and mental imagery research (Schuster et al. 2011, Liu et al. 2025) informs the Lens's "The View" feature — guided mental rehearsal sessions that are process-oriented (imagining the steps), not just outcome fantasy (imagining the result). Liu et al.'s meta-analysis found optimal dosage at ~10 minutes, 3x per week — informing the suggested visualization cadence.
### Concept ### Concept
If the Kaleidoscope shows you new patterns in what already exists, the Lens focuses your vision on what you're building toward. Goal-setting and manifestation, powered by AI. If the Kaleidoscope shows you new patterns in what already exists, the Lens focuses your vision on what you're building toward. Goal-setting and manifestation, powered by AI.
@ -324,6 +365,14 @@ The Lens connects insights from other features to forward momentum:
> *White light looks simple. The Spectrum shows you everything it's made of.* > *White light looks simple. The Spectrum shows you everything it's made of.*
### Scientific Basis
The Spectrum synthesizes insights from across the research library. The expectation effects literature (Stetler 2014, Pardo-Cabello et al. 2022) provides the theoretical foundation: when users see concrete evidence that reframing works (Turn Impact data), this creates a positive feedback loop where expectations of benefit increase actual benefit. Stetler showed that consistent adherence reinforces positive expectations — the Spectrum's evidence engine accelerates this cycle.
The habit formation research (Wood & Neal 2007, Wood et al. 2021) informs Rhythm Detection and streak mechanics. Wood et al. found that ~43% of daily behavior is habitual, and that context stability predicts habit formation. The Spectrum tracks not just frequency but context consistency, reinforcing the context-response links that make Kalei usage automatic.
The attention research (Yantis 2008, Stevens & Bavelier 2012) powers Fragment Pattern tracking. By surfacing which cognitive distortions appear most frequently, the Spectrum makes unconscious attentional biases visible — the same principle as the Mirror, but operating at a longitudinal scale.
### Concept ### Concept
Every wellness app asks you to rate your mood on a scale. Tap a smiley face. Drag a slider. It's self-reported, inaccurate, and most people stop doing it after two weeks because it feels like homework. Every wellness app asks you to rate your mood on a scale. Tap a smiley face. Drag a slider. It's self-reported, inaccurate, and most people stop doing it after two weeks because it feels like homework.
@ -441,6 +490,291 @@ The Spectrum doesn't bombard users with data. Insights surface at natural moment
- After a Turn: "This is the 3rd time you've Turned a work-related fragment this week. The Spectrum can show you more about this pattern." - After a Turn: "This is the 3rd time you've Turned a work-related fragment this week. The Spectrum can show you more about this pattern."
- Lens: "Your Lens focus on [career growth] aligns with the fragments you've been processing. You're working on the right things." - Lens: "Your Lens focus on [career growth] aligns with the fragments you've been processing. You're working on the right things."
---
## The Rehearsal — Guided Visualization (Lens Sub-Feature)
> *The Lens shows you where you're going. The Rehearsal helps you see yourself getting there.*
### Scientific Basis
The Rehearsal is the most direct implementation of the visualization and mental imagery research — a gap in the current feature set that the science explicitly calls for.
**Schuster et al. (2011)** reviewed motor imagery across five disciplines and found that structured mental rehearsal is most effective when: (1) combined with physical practice (not used in isolation), (2) sessions follow a clear protocol, and (3) imagery is vivid, first-person, and process-oriented. Pure outcome fantasy ("imagine yourself on the podium") can actually *decrease* performance by providing premature satisfaction. Process visualization ("imagine yourself preparing, executing, recovering from mistakes") is what drives results.
**Liu et al. (2025)** meta-analyzed 86 studies with 3,593 athletes and identified an optimal dosage: approximately **10 minutes, 3 times per week, over ~100 days**. Combining imagery with 1-2 additional psychological skills (self-talk, goal setting) produced stronger effects than imagery alone.
**Seok & Choi (2023)** demonstrated that mental practice activates overlapping neural circuits with actual physical execution — even when the body cannot currently perform the action. This confirms that visualization isn't metaphorical; it's neurological preparation.
### Concept
The Rehearsal is a guided visualization feature nested within the Lens. After a user sets a goal, the Rehearsal generates AI-powered, personalized mental rehearsal scripts that walk them through the *process* of achieving it — not just imagining the end state.
This is not meditation. This is not affirmation. This is **cognitive preparation** — the same technique elite athletes use, backed by the same research, adapted for personal goals.
### How It Works
**Entry point:** Within the Lens tab, beneath the active goal. A "Rehearse" button appears alongside "Today's Focus" and "The View."
**Session structure (following Schuster et al.'s best-practice protocol):**
1. **Grounding** (~1 min) — Brief settling. Eyes closed or soft focus. "Take a breath. We're going to walk through something together."
2. **Process visualization** (~5-7 min) — The AI generates a first-person, present-tense script specific to the user's goal and upcoming actions. Multi-sensory: what you see, hear, feel, think. Example for a job interview goal:
> "It's Tuesday morning. You're walking into the building. Notice the weight of your bag, the sound of your shoes on the floor. You're prepared — you reviewed your notes last night. You sit down across from the interviewer. They ask the question you've been anticipating. You feel a quick pulse of nerves — that's normal, that's your body getting ready. You take a breath, and you begin..."
3. **Obstacle rehearsal** (~2 min) — The script includes a moment where something goes imperfectly, and the user mentally rehearses recovering. This prevents the toxic positivity trap and builds realistic self-efficacy.
> "Midway through your answer, you lose your train of thought. You pause. That's fine — you've practiced pausing before. You take a beat, reconnect with your main point, and continue. The interviewer nods."
4. **Close** (~1 min) — Return to present. Anchor the feeling. "You've just walked through it. Your brain now has a draft of this experience. When the real moment comes, it won't be the first time."
**Session length:** ~10 minutes (per Liu et al.'s optimal dosage finding).
**Suggested cadence:** 3x per week, tied to active Lens goals. The app suggests: "You have a Rehearsal ready for [goal]. Best done in the morning."
### Vocabulary
- **Feature name:** "The Rehearsal" or "Rehearse"
- **CTA:** "Rehearse" (verb, like "Turn")
- **Session label:** "A Rehearsal"
- **Completion:** "Rehearsal complete. Your brain has a draft."
- **In the Gallery:** Rehearsal sessions get their own visual style — more fluid, less geometric, like light passing through a lens
### Visual Design (SVG-Native)
The Rehearsal UI is text-driven — the AI-generated script is the experience, not complex graphics. Visual elements are minimal and SVG-generated:
- **Background:** A slow, subtle radial gradient animation (CSS-only on an SVG circle) — simulating light focusing through a lens. Deep jewel tones fading inward.
- **Progress indicator:** A simple SVG ring that fills as the session progresses (similar to a meditation timer). Prismatic gradient stroke.
- **Step transitions:** Gentle SVG fade between Grounding → Process → Obstacle → Close, with a small geometric icon per step (a circle, a path, a crack, a diamond).
- **Completion pattern:** A unique SVG pattern generated from the session — simpler and more fluid than Turn patterns. Think concentric lens rings with soft color shifts, procedurally generated from the goal text seed.
- **No custom illustrations, no photography, no complex animations.** The Rehearsal is an intimate, text-focused experience. The visual design supports focus, not spectacle.
### Key Design Rules
1. **Always process-oriented, never pure outcome fantasy.** The script walks through steps, not podiums.
2. **Always include obstacle rehearsal.** A visualization without setbacks is toxic positivity in disguise.
3. **Always pair with action.** A Rehearsal without a corresponding micro-action in the Lens is incomplete. After each session: "Now make it real. Here's your next step."
4. **First-person, present tense, multi-sensory.** Per Schuster et al.'s findings.
5. **Personalized to the user's goal and context.** Not generic scripts. The AI uses the goal details, timeline, and any Mirror/Turn data about related anxieties to make the Rehearsal feel personal.
### Monetization
| | Free (Kalei) | Prism |
|---|---|---|
| Rehearsal access | 1 per week | Unlimited |
| Script personalization | Basic | Deep (uses Mirror/Turn context) |
| Obstacle rehearsal | ✗ | ✓ |
| Audio playback | ✗ | ✓ (AI-generated narration) |
### Technical Notes
The Rehearsal script is generated via the AI gateway using the user's active Lens goal, upcoming actions, and optionally relevant Mirror fragments/Turn history. The prompt must enforce: first-person perspective, present tense, multi-sensory detail, process focus, obstacle inclusion, and ~10 minute reading pace. Output is cached per goal and refreshed when actions change.
---
## The Ritual — Context-Anchored Daily Flow
> *A kaleidoscope isn't turned randomly. The best patterns come from consistent, deliberate turns.*
### Scientific Basis
The Ritual directly implements Wood & Neal's (2007) core finding: habits form through the gradual learning of associations between responses and **context features** (physical settings, time of day, preceding actions). Once formed, perception of the context triggers the habitual response without a mediating goal — the behavior becomes automatic.
Wood, Mazar & Neal (2021) extended this: ~43% of daily behavior is habitual, not deliberate. Sustained change requires building automatic routines, not just relying on willpower. The single biggest predictor of habit formation is **context stability** — doing the same thing, at the same time, in the same place, in the same sequence.
Current Kalei features track streaks (measuring repetition) but don't actively **scaffold** the context-response link. The Ritual bridges that gap.
### Concept
The Ritual is a timed, sequenced daily flow that chains 2-3 Kalei activities into a single context-anchored routine. Instead of the user deciding each day whether to open Kalei, what to do, and in what order — the Ritual removes all decision points and delivers a pre-structured 5-10 minute experience tied to a specific daily moment.
The user isn't building three separate habits (Mirror, Turn, Lens). They're building **one habit** — "My morning Ritual" — that contains all three.
### Ritual Templates
**The Morning Ritual (~7 minutes)**
Best for: users building a proactive practice
1. **Check-in** (1 min) — Quick Mirror prompt: "One sentence. How are you showing up today?"
2. **Focus** (2 min) — Lens daily action review: "Here's what's on your plate. Which one matters most?"
3. **Rehearse** (3 min) — Abbreviated Rehearsal for today's key action (shorter than a full Rehearsal session)
4. **Set the angle** (1 min) — One-line intention for the day, saved as a fragment seed
**The Evening Ritual (~5 minutes)**
Best for: users who need to process and decompress
1. **Release** (2 min) — Quick Mirror dump: "What are you still carrying from today?"
2. **Turn** (2 min) — AI surfaces the heaviest fragment from the dump and offers a quick Turn
3. **Acknowledge** (1 min) — Lens action review: "What did you complete today?" + Evidence Wall entry
**The Quick Ritual (~3 minutes)**
Best for: busy days, maintaining the streak
1. **One Turn** — AI surfaces a prompt based on recent patterns or a random fragment seed
2. **One action** — Lens shows the single most important action for today
3. **Done** — "That's your Ritual. Same pieces. New angle. See you tomorrow."
### How It Works
**Setup:** During onboarding (or first week), the user selects a Ritual template and anchors it to a context:
- **When:** "Every morning after my first coffee" / "Every evening before bed" / custom
- **What:** Morning / Evening / Quick
- **Notification:** "Your Ritual is ready" sent at the anchored time
**The experience:** The Ritual opens as a single, flowing screen — not tabbed navigation between Mirror/Turn/Lens. Each step transitions seamlessly into the next with a gentle visual progression (the kaleidoscope pattern building as they complete each step). No menus, no choices, no friction. Just follow the light.
**Completion:** "Ritual complete" + updated streak + optional one-line insight. The Ritual pattern (a simpler, more structured pattern than Mirror or Turn patterns) saves to the Gallery.
### Context Stability Tracking
Per Wood et al.'s findings, the app tracks not just *whether* the Ritual was completed, but *when* and *how consistently*:
> "You've completed your Morning Ritual within the same 30-minute window for 12 days. This is becoming automatic."
> "Your Ritual timing drifted this week — 7am Monday, 9am Wednesday, skipped Friday. Consistency is the engine. Can we lock in a time?"
This is the most direct implementation of the habit formation science anywhere in the app.
### Vocabulary
- **Feature name:** "The Ritual"
- **CTA:** "Start your Ritual"
- **Completion:** "Ritual complete"
- **Streak label:** "X-day Ritual streak"
- **Context anchor:** "Your Ritual time"
- **Notification:** "Your Ritual is ready" (not "Time for your Ritual" — no pressure)
### Monetization
| | Free (Kalei) | Prism |
|---|---|---|
| Ritual access | Quick Ritual only | All 3 templates |
| Customization | Fixed template | Customize steps and order |
| Context tracking | Basic streak | Full consistency analytics |
| Ritual patterns in Gallery | ✗ | ✓ |
### Visual Design (SVG-Native)
The Ritual is a flowing, minimal experience. No complex UI — just a sequence of steps with clean transitions.
- **Ritual screen:** A single scrolling view. Each step is a card with a subtle SVG border (thin geometric frame, prismatic gradient stroke). Steps stack vertically, each revealing as the previous completes.
- **Progress visualization:** A simple SVG horizontal bar or arc that fills step-by-step. Each completed step adds a faceted segment in a different jewel tone. Think a prismatic progress bar — 3-5 colored geometric segments filling left to right.
- **Completion state:** All segments filled → the bar pulses once with a soft glow (CSS animation on SVG), then collapses into a small Ritual pattern icon (a simple symmetric SVG — like a mandala made from 3-5 triangles) that saves to the Gallery.
- **Timer overlay:** A minimal SVG circle timer for timed steps (Mirror check-in, Rehearsal). Thin stroke, ambient color.
- **No illustrations, no photography, no Lottie animations.** The Ritual's premium feel comes from spacing, typography, and color — not complexity. Think Apple Health's simplicity meets Kalei's jewel-tone palette.
### Retention Impact
The Ritual addresses the week 3-4 retention cliff head-on. By that point:
- The novelty of individual features (Mirror, Turn, Lens) has faded
- But the *Ritual habit* is forming — context cues are starting to trigger automatic behavior
- The user opens Kalei not because they decided to, but because it's 7am and they just poured coffee
- By the time the Spectrum launches (Phase 2), the Ritual has already made daily usage automatic
This is the difference between an app that relies on motivation (which declines) and one that builds habits (which compound).
---
## The Evidence Wall — Mastery Tracking
> *A kaleidoscope collects fragments. The Evidence Wall collects proof.*
### Scientific Basis
Bandura (1977) identified four sources of self-efficacy, ranked by potency:
1. **Mastery experiences** — successfully doing the thing (strongest source by far)
2. **Vicarious experience** — watching someone similar succeed
3. **Verbal persuasion** — being told you can do it (what reframes primarily provide)
4. **Physiological states** — interpreting your body's signals as capability vs. inadequacy
The Turn and Mirror currently operate primarily through **verbal persuasion** (reframes that tell you "you can handle this") — Bandura's *weakest* efficacy source. The Evidence Wall adds the *strongest* source: concrete evidence of past mastery.
When a user hits a setback and their self-efficacy dips, the most powerful intervention isn't a new reframe. It's their own track record: "Look at what you've already done."
### Concept
The Evidence Wall is a dedicated section (accessible from the "You" tab or within the Lens) that automatically collects and curates evidence of the user's growing capability:
- **Completed micro-actions** from the Lens
- **Turning points** — Turns that produced a saved keepsake
- **Self-corrections** — moments in Mirror sessions where the user caught their own fragment before Kalei highlighted it (detected by self-editing patterns)
- **Streak milestones** — consistency evidence
- **Goal completions** — finished Lens goals
- **Reframe echoes** — instances where language from a saved Turn pattern appeared organically in later Mirror writing (the user internalized the reframe)
- **Spectrum growth markers** — fragment density drops, new distortion types addressed
### How It Shows Up
**Passive collection:** The Evidence Wall populates automatically from usage data. The user doesn't need to manually log anything — the evidence accumulates naturally as they use Kalei.
**Active surfacing — The "Remember" Moment:** When the AI detects a self-efficacy dip (repeated catastrophizing, increased helplessness language in Mirror sessions, abandoned Lens actions), it can surface Evidence Wall entries contextually:
> **In a Mirror session:**
> "I notice you're being hard on yourself about your ability to follow through. Here's what I've seen: you've completed 23 micro-actions this month, hit your running goal 3 weeks in a row, and last Tuesday you caught a catastrophizing pattern before I even highlighted it. That's your track record."
> **After a Turn:**
> "This pattern — doubting your capability — has come up before. Last time, you Turned it and saved this keepsake: [displays saved reframe]. Since then, you've completed 4 of the 5 actions you set for yourself."
**The Wall itself:** A visual timeline or mosaic in the "You" tab. Each evidence type gets its own visual marker (faceted shapes in different colors). The Wall grows denser and more colorful over time — a literal accumulation of proof.
### Vocabulary
- **Feature name:** "The Evidence Wall" or "Your Evidence"
- **Section in You tab:** "Your Evidence"
- **Individual entries:** "Proof points"
- **AI surfacing:** "Here's what I've seen" (not "remember when you..." — the AI presents evidence, not nostalgia)
- **Milestone:** "New proof point added to your Wall"
### Key Design Rules
1. **Evidence, not cheerleading.** The Wall presents facts ("You completed 23 actions"), not encouragement ("You're doing amazing!"). Bandura's research shows that mastery evidence works because it's *credible* — the user can't argue with their own track record.
2. **Automatic, not manual.** If the user has to log their own wins, it becomes a gratitude journal (which is a different thing). The power is that the evidence accumulates without effort.
3. **Contextual surfacing, not nagging.** The AI only surfaces evidence when it detects a dip in self-efficacy language. Unsolicited "look how great you're doing!" messages feel performative and erode trust.
4. **Concrete and specific.** "23 actions completed" not "you've been consistent." Numbers, dates, specific Turns and reframes. The more specific, the more credible, the stronger the efficacy effect.
### Integration with Other Features
| Feature | Evidence Collected |
|---|---|
| **Mirror** | Self-correction moments, reduced fragment density over time |
| **Turn** | Saved keepsakes, reframe echoes in later writing |
| **Lens** | Completed actions, hit goals, streak milestones |
| **Rehearsal** | Completed rehearsals (preparation as evidence) |
| **Ritual** | Consistency streaks, context stability data |
| **Spectrum** | Growth trajectory markers, distortion reduction data |
### Monetization
| | Free (Kalei) | Prism |
|---|---|---|
| Evidence collection | Last 30 days | Full history |
| AI surfacing in sessions | ✗ | ✓ |
| Visual Evidence Wall | Basic count | Full timeline visualization |
| Export/share proof points | ✗ | ✓ |
### Visual Design (SVG-Native)
The Evidence Wall's visual identity is a growing mosaic — each proof point is a small geometric SVG tile that accumulates into a larger pattern.
- **Individual proof points:** Small SVG shapes — hexagons, diamonds, triangles — color-coded by source (amber for Mirror self-corrections, emerald for Lens completions, sapphire for Turn keepsakes, amethyst for Spectrum milestones). Simple flat fills with thin borders. No icons, no illustrations — just colored geometric shapes.
- **The Wall view:** A grid/mosaic layout of these shapes in the "You" tab. As proof points accumulate, the mosaic grows denser and more colorful. Early on it's sparse (a few shapes scattered on dark background). After months, it's a rich tapestry. This creates the same "collection" satisfaction as the Gallery but for evidence instead of patterns.
- **Timeline mode:** Toggle from mosaic to a simple SVG timeline — a horizontal line with proof point markers along it. Colored dots on a dark line. Tap any dot to see the detail.
- **AI surfacing card:** When the Evidence Wall surfaces contextually in a Mirror or Turn session, it appears as a simple card with a thin prismatic border, a count, and 2-3 specific proof points. No fancy animations — just clean typography and jewel-tone accents on dark background.
- **No complex data visualizations.** The Evidence Wall is a collection, not a dashboard. Its visual simplicity is intentional — the evidence itself is the feature, not the presentation.
### Why This Matters
Without the Evidence Wall, Kalei's self-efficacy building relies entirely on verbal persuasion (reframes). With it, the app deploys Bandura's *strongest* efficacy mechanism. The difference:
- **Without Evidence Wall:** "You can handle this" (the AI says so)
- **With Evidence Wall:** "You've handled 23 things like this in the last month" (the data says so)
The second is dramatically more powerful. It shifts self-efficacy from something the app *tells* the user to something the user *knows* because they can see the proof.
--- ---
--- ---
@ -450,28 +784,41 @@ The Spectrum doesn't bombard users with data. Insights surface at natural moment
## Visual Design Language ## Visual Design Language
### SVG-First Design Philosophy
Kalei's visual identity is built to be implemented without external designers or complex asset pipelines. Every visual element should be achievable with **SVGs (hand-crafted or procedurally generated), CSS gradients, and minimal animation**. The premium feel comes from restraint — jewel tones on dark backgrounds, geometric precision, generous spacing, and quality typography. Not from illustrations, photography, or complex motion graphics.
**This means:**
- All patterns (Turn, Mirror, Rehearsal, Ritual, Evidence Wall) are procedurally generated SVGs using the input text as a seed
- All icons are geometric SVG shapes — faceted, angular, simple
- All backgrounds use CSS/SVG gradients — no raster images
- All animations are CSS transitions on SVG elements — no Lottie, no After Effects
- The "premium" feel comes from: dark backgrounds, jewel-tone color palette, precise geometric shapes, quality typography, and intentional negative space
### The Kaleidoscope Aesthetic ### The Kaleidoscope Aesthetic
The visual identity evokes the feeling of looking through a kaleidoscope without being literal or childish. The visual identity evokes the feeling of looking through a kaleidoscope without being literal or childish.
**Color Palette:** **Color Palette:**
- **Primary:** Deep jewel tones — amethyst purple, sapphire blue, emerald green - **Primary:** Deep jewel tones — amethyst purple (#7B2D8E), sapphire blue (#1E3A5F), emerald green (#2D5F3E)
- **Secondary:** Warm golds and soft amber (the light passing through glass) - **Secondary:** Warm golds and soft amber (#D4A574, #C8956C) (the light passing through glass)
- **Background:** Near-black or deep navy (the dark tube of a kaleidoscope — fragments shine against darkness) - **Background:** Near-black (#0A0A0F) or deep navy (#0D1117) (the dark tube of a kaleidoscope — fragments shine against darkness)
- **Accent:** Prismatic gradients for highlights and CTAs (light refracting) - **Accent:** Prismatic gradients for highlights and CTAs (linear-gradient sweeps through the jewel tones)
- **Fragment highlight:** Warm amber glow (#D4A574 at 40% opacity)
**Why dark backgrounds:** A kaleidoscope works by reflecting light against darkness. The dark UI makes colorful elements pop — and positions Kalei as premium, not bubbly. **Why dark backgrounds:** A kaleidoscope works by reflecting light against darkness. The dark UI makes colorful elements pop — and positions Kalei as premium, not bubbly.
**Avoid:** Pastel wellness aesthetic. No sage green, no cream, no watercolor blobs. Kalei is jewel-toned, rich, and confident. **Avoid:** Pastel wellness aesthetic. No sage green, no cream, no watercolor blobs. Kalei is jewel-toned, rich, and confident.
**Typography:** **Typography:**
- Clean, modern sans-serif for body text (clarity, legibility) - Clean, modern sans-serif for body text (clarity, legibility) — Inter or similar
- One geometric or slightly decorative font for headlines (faceted, angular — like cut glass) - One geometric or slightly decorative font for headlines (faceted, angular — like cut glass) — consider Lexend, Space Grotesk, or similar geometric sans-serif
**Iconography:** **Iconography:**
- Geometric and faceted — hexagons, triangles, crystalline shapes - Geometric and faceted — hexagons, triangles, crystalline shapes — all SVG
- Avoid circles and soft curves (that's every other wellness app) - Avoid circles and soft curves (that's every other wellness app)
- Subtle symmetry in icon design (mirrors the symmetry of kaleidoscope patterns) - Subtle symmetry in icon design (mirrors the symmetry of kaleidoscope patterns)
- All icons deliverable as single-path SVGs with stroke or fill in brand colors
--- ---
@ -561,6 +908,10 @@ An opt-in public gallery where users share their best patterns anonymously. Brow
## Onboarding Flow ## Onboarding Flow
### Scientific Note on Onboarding
The onboarding serves a dual purpose grounded in the placebo/expectation research (Pardo-Cabello et al. 2022, Stetler 2014). First, it creates a mastery experience (Bandura 1977) within 60 seconds — the user successfully reframes a real thought, building immediate self-efficacy. Second, it primes legitimate expectation effects: the experience of "this actually works" on the very first use sets up the positive expectation-behavior loop that Stetler identified as the mechanism behind adherence benefits.
The onboarding teaches the metaphor through experience, not explanation. The onboarding teaches the metaphor through experience, not explanation.
**Screen 1 — The Fragment** **Screen 1 — The Fragment**
@ -597,6 +948,10 @@ The user types a real negative thought. Kalei processes it and returns 23 ref
## Notifications & Engagement Copy ## Notifications & Engagement Copy
### Scientific Note on Engagement Design
All engagement mechanics are grounded in Wood & Neal's habit formation research (2007, 2021). Notifications are timed to reinforce context-response links (same time, same trigger → same behavior). Streak tracking measures the repetition necessary for habit crystallization. The goal is automaticity — the point where opening Kalei becomes a reflexive response to context cues, not a willpower-dependent decision. Stetler (2014) further supports this: consistent adherence creates a positive expectation-behavior feedback loop that compounds over time.
### Daily Prompt (Push Notification) ### Daily Prompt (Push Notification)
Rotate through styles: Rotate through styles:
@ -718,6 +1073,15 @@ Open to a dramatic reveal of their personal Spectrum — the river visualization
| | | Export sessions | | | | Export sessions |
| **Lens** | Basic goal setting | Full Lens with AI-powered affirmations | | **Lens** | Basic goal setting | Full Lens with AI-powered affirmations |
| | | Vision board / The View | | | | Vision board / The View |
| **Rehearsal** | 1 per week | Unlimited |
| | Basic script | Deep personalization (uses Mirror/Turn context) |
| | | Obstacle rehearsal + audio playback |
| **Ritual** | Quick Ritual only | All 3 templates (Morning/Evening/Quick) |
| | | Customize steps and order |
| | Basic streak | Full consistency analytics |
| **Evidence Wall** | Last 30 days | Full history |
| | | AI surfacing in sessions |
| | | Full timeline visualization |
| **Gallery** | Last 30 days | Full history | | **Gallery** | Last 30 days | Full history |
| | | Export and share patterns | | | | Export and share patterns |
| **Spectrum** | Simplified weekly summary (1 insight, no visuals) | Full dashboard with all 5 components | | **Spectrum** | Simplified weekly summary (1 insight, no visuals) | Full dashboard with all 5 components |
@ -991,7 +1355,7 @@ If AI detects crisis language (self-harm, suicidal ideation), surface crisis res
## Feature Map — Full Ecosystem ## Feature Map — Full Ecosystem
``` ```
PHASE 1 PHASE 2 PHASE 1 — CORE FEATURES PHASE 2
───────────────────────────────── ────────────────────── ───────────────────────────────── ──────────────────────
THE MIRROR (Awareness) ──→ feeds data to ──→ THE SPECTRUM THE MIRROR (Awareness) ──→ feeds data to ──→ THE SPECTRUM
@ -1008,13 +1372,31 @@ THE LENS (Direction) ──→ informed by ──→
Goal setting Goal setting
Daily affirmations Daily affirmations
Vision tracking Vision tracking
+ THE REHEARSAL (sub-feature)
Guided visualization sessions
Process-oriented mental rehearsal
PHASE 1 — CONNECTORS
─────────────────────────────────
THE RITUAL ──→ sequences ──→ Mirror + Turn + Lens
Morning / Evening / Quick into one daily habit
Context-anchored timing
Consistency tracking
THE EVIDENCE WALL ←── collects from ←── All features
Mastery evidence accumulation
Contextual AI surfacing
Proof-point mosaic
◇ ◇ ◇ ◇
Kalei Free Kalei Prism Kalei Free Kalei Prism
3 Turns/day Unlimited everything 3 Turns/day Unlimited everything
2 Mirror/week + Full Spectrum 2 Mirror/week + Full Spectrum
Basic Lens + Weekly/monthly insights Basic Lens + All Ritual templates
+ Growth trajectory Quick Ritual only + Unlimited Rehearsals
1 Rehearsal/week + Full Evidence Wall
Evidence Wall (30 days) + Growth trajectory
+ Fragment analytics + Fragment analytics
``` ```

View File

@ -0,0 +1,545 @@
# Kalei — Complete User Journey Map
> Version 2.0 — February 2026
> Updated to include Ritual, Rehearsal, Evidence Wall, and full cross-feature integration
---
## Overview
This document maps every user-facing flow in Kalei from first launch to long-term mastery. It serves as the single source of truth for what the user experiences, when, and why — covering all 7 features across the 5-tab architecture.
**Navigation Architecture:** Turn ◇ | Mirror ✦ | Lens ◎ | Gallery ▦ | You ●
**Core Features (4 Pillars):**
- The Turn (Kaleidoscope) — Perspective shifting via cognitive reframing
- The Mirror — Awareness through freeform journaling with AI fragment detection
- The Lens — Direction through goal setting, visualization, and action planning
- Gallery — Pattern collection and history
**Connector Features (3 Bridges):**
- The Ritual — Context-anchored daily habit sequences chaining Mirror → Turn → Lens
- The Rehearsal — Guided multi-sensory visualization (Lens sub-feature)
- The Evidence Wall — Mastery tracking mosaic (You tab sub-feature)
**Intelligence Layer (Phase 2):**
- The Spectrum — AI-powered self-knowledge dashboard
---
## Journey Stage 1: First Launch & Onboarding
### Screen 1: Splash
- Breathing logo animation (soft-elegance iris, slow rotation, core pulse)
- Background: Void (#050508) with subtle breathing aura
- Duration: 2 seconds, auto-advance
### Screen 2: Welcome — "Same pieces. New angle."
- Hero kaleidoscope pattern (6-blade prismatic, screen blend mode)
- Tagline in Space Grotesk display font
- Single CTA: "See how it works" (Amethyst shimmer button)
### Screen 3: The Metaphor — Fragment Introduction
- Visual: A single thought fragment (◇) appears, glowing Amber
- Copy: "Your thoughts are like pieces of glass in a kaleidoscope."
- Interaction: User taps the fragment → it pulses with detected-state animation
- Copy continues: "Sometimes you see sharp edges. Sometimes beautiful patterns."
### Screen 4: The Turn Demo — Live Reframe
- Pre-populated negative thought: "I always mess everything up"
- Auto-animated Turn sequence (1.5s): collapse → multiply → crystallize → settle
- Three reframed perspectives appear as jewel-toned cards (Amethyst, Sapphire, Emerald)
- Copy: "Same pieces. New angle. That's a Turn."
### Screen 5: Choose Your Style
- 4 coaching style cards with fragment icons:
- Stoic Sage (Sapphire ◇) — "Clear-eyed perspective"
- Compassionate Friend (Rose ◇) — "Gentle understanding"
- Pragmatic Coach (Emerald ◇) — "Practical next steps"
- Growth Catalyst (Amber ◇) — "Opportunity in everything"
- User selects default (can change later)
### Screen 6: Notification Permission
- Copy: "When would you like a gentle nudge to check in?"
- Time picker with morning/evening presets
- Skip option available
### Screen 7: Account Creation
- Email + password OR Apple/Google SSO
- Minimal fields — name optional at this stage
- Privacy assurance: "Your thoughts stay yours. Always encrypted."
### Screen 8: First Real Turn
- Empty Turn input with prompt: "What's weighing on you right now?"
- User types their first real negative thought
- Full Turn animation plays
- 3 reframed perspectives appear
- User can save favorites (→ Gallery) or dismiss
- Success burst animation on save
### Screen 9: Welcome Complete
- Copy: "Welcome to Kalei. Your kaleidoscope is ready."
- Mini kaleidoscope pattern generated from their first Turn (deterministic, seeded from input)
- CTA: "Start exploring" → Tab bar appears, Turn tab active
---
## Journey Stage 2: Daily Core Loop
### 2A: The Turn (Tab 1 — Amethyst ◇)
**Entry:** User opens app → Turn tab is default home
**Empty State:**
- Breathing logo at center, subtle floating shards in background
- Rotating prompts: "What thought keeps circling?", "What would you like to see differently?", "What feels heavy right now?"
- Single large text input area
**Active Flow:**
1. User types or speaks a negative thought
2. Tap "Turn it" button (Amethyst shimmer)
3. Turn animation plays (1.5s kaleidoscope rotation)
4. 3 reframed perspectives appear as cards:
- Each card has a coaching style label, the reframe text, and a fragment icon
- Cards use jewel tone gradients matching their style
5. Below perspectives: "If-Then Micro-Action" card
- Format: "If [situation], then I will [specific action]"
- Emerald accent, action-oriented
6. User actions:
- Save any perspective → goes to Gallery as a Keepsake
- Save micro-action → goes to Lens as a suggested action
- Share → generates Pattern Card (kaleidoscope pattern + reframe text)
- Dismiss → confirmation, thought is discarded
**Turn History:**
- Scrollable list below input showing today's Turns
- Each entry: timestamp, first line of thought, fragment count badge, pattern thumbnail
**Rate Limiting (Free tier):**
- 3 Turns per day
- After limit: "You've used your 3 Turns today. Upgrade to Kalei Prism for unlimited Turns."
- Gentle, never punishing
### 2B: The Mirror (Tab 2 — Amber ✦)
**Entry:** Mirror tab → New session or continue existing
**Empty State:**
- Soft amber glow background
- Copy: "What's on your mind? Write freely — no judgment, no rules."
- Suggested prompts rotate: "How are you feeling right now?", "What happened today?", "What's been on repeat in your head?"
**Active Session Flow:**
1. User writes freely in chat-like interface (user messages appear as dark bubbles)
2. After each message, AI processes silently (AI thinking animation: 3 oscillating fragments)
3. AI responds with warm, reflective prompts (light bubbles with subtle amber border)
4. Simultaneously, AI detects cognitive distortions in user's text
5. Detected fragments appear as inline highlights:
- Amber glow underline beneath the distorted phrase
- Small ◇ icon at start of highlight
- Highlight appears post-message (never while typing)
6. User taps a highlight → Half-sheet modal:
- Distortion type name + icon (from icons-distortions.svg)
- Brief explanation: "Catastrophizing: Assuming the worst possible outcome"
- 1-2 quick reframes
- "Take to Turn" button → opens Turn with this thought pre-filled
- Dismiss to continue writing
**Session Close:**
- User taps "End Session" or navigates away
- AI generates Reflection:
- Themes detected
- Fragment count and types
- One-line insight
- Unique kaleidoscope pattern (seeded from session content)
- Reflection saved to Gallery
**Nudge System:**
- If user ignores 5+ highlighted fragments, ONE gentle offer:
- "I noticed a few patterns in what you wrote. Want to look at them together?"
- Max once per session
- Dismissible
**Rate Limiting (Free):** 2 sessions per week, 3 distortion types detected (Catastrophizing, Black-and-White, Should Statements). Prism: unlimited sessions, all 10 types.
### 2C: The Lens (Tab 3 — Emerald ◎)
**Entry:** Lens tab → Goal dashboard
**Dashboard View:**
- Active goals displayed as cards with progress rings
- Each goal card shows: title, progress percentage, next action, streak indicator
- "Add Goal" floating action button (Emerald gradient)
**Goal Creation Flow (6 Steps):**
**Step 1: Decide — Set a SMART Goal**
- AI-guided conversation to refine a vague desire into a specific goal
- Template: "I want to [specific outcome] by [date] measured by [metric]"
- AI suggests refinements if goal is vague
**Step 2: See It — The View (Vision Board)**
- AI generates a visualization description based on goal
- User can add personal images or AI-generated imagery
- "The View" appears as a full-screen card they can revisit
**Step 3: Believe — Capability Building**
- Evidence Wall integration: surfaces past achievements relevant to this goal
- AI generates affirmations based on goal + user's history
- Daily affirmation card appears at Lens tab top
**Step 4: Notice — Attention Training**
- AI prompts awareness exercises: "Today, notice one moment where you [goal-related behavior]"
- Prompts delivered via notification at user-chosen time
- User logs noticed moments → feeds Evidence Wall
**Step 5: Act — If-Then Micro-Actions**
- AI generates situation-specific implementation intentions
- Format: "If [context], then [specific action]"
- User can mark actions complete → feeds Evidence Wall
- Action completion streak tracking
**Step 6: Compound — Habit Tracking**
- Visual habit tracker (fragment-shaped step indicators)
- Streak counter with flame icon
- Weekly review of consistency
**The Rehearsal (Lens Sub-Feature):**
- Accessed from goal detail screen → "Rehearse" button
- Timer ring appears (default: 10 minutes)
- AI generates personalized visualization script:
- First-person perspective
- Multi-sensory (see, hear, feel, smell)
- Process-oriented (not just outcome)
- Includes obstacle rehearsal ("When X happens, I will Y")
- Script plays as text cards with breathing animation pacing
- Progress ring counts down
- Completion → Success burst → logged to Evidence Wall
- Free: 1 Rehearsal per week. Prism: unlimited.
### 2D: Gallery (Tab 4 — Sapphire ▦)
**Entry:** Gallery tab → Collection view
**Views:**
- **All Patterns** (default): Reverse-chronological grid of kaleidoscope pattern thumbnails
- **Keepsakes**: Saved reframes, reflections, and insights
- **By Feature**: Filter by Turn / Mirror / Lens source
- **By Distortion**: Filter by cognitive distortion type
**Pattern Card Detail:**
- Full kaleidoscope pattern (hero variant, animated)
- Source content (the reframe or reflection that generated it)
- Date, feature source, distortion types tagged
- Share button → exports as Pattern Card image
- Delete with confirmation
**Search:**
- Text search across all saved content
- Filter chips: date range, feature, distortion type, favorites
### 2E: You (Tab 5 — Soft Light ●)
**Entry:** You tab → Profile dashboard
**Sections:**
- **Profile**: Name, avatar, member since
- **Stats Overview**: Total Turns, Mirror sessions, Goals active, Streak count
- **Evidence Wall** (prominent card → opens full view)
- **Settings**: Coaching style, notification times, theme (dark only for now), data export
- **Subscription**: Current plan, upgrade CTA (if free)
- **Support**: FAQ, contact, crisis resources
**The Evidence Wall (You Sub-Feature):**
- Accessed from You tab → "Your Evidence Wall" card
- Opens full-screen mosaic view
**Evidence Wall States:**
*Empty State (0-2 items):*
- Ghost tile outlines (dashed borders) showing where tiles will appear
- Central fragment icon with breathing animation
- Copy: "Start collecting evidence. Each Turn adds a tile to your wall."
*Early State (3-7 items):*
- Small cluster of tiles, connections forming
- Tiles are mixed shapes (diamond, hex, rectangle, pentagon, triangle)
- Each tile represents one proof point:
- Completed action (Emerald border)
- Saved keepsake (Sapphire border)
- Self-correction in Mirror (Amber border)
- Streak milestone (Amethyst border)
- Goal completion (Emerald border, larger tile)
- Reframe echo (Indigo border) — when user's later writing echoes a saved reframe
*Mid State (8-20 items):*
- Mosaic takes shape, dashed connection lines between related tiles
- Tiles glow softly when tapped → detail half-sheet
*Full State (20+ items):*
- Dense mosaic with visible connection web
- Zoom/pan enabled
- Most impactful tiles glow brighter
**Contextual Surfacing:**
- During low self-efficacy moments (detected in Mirror or Turn), the Evidence Wall surfaces 1-2 relevant tiles
- Example: User writes "I can never stick to anything" → Evidence Wall suggests: "You completed 12 actions in the last month and maintained a 7-day streak"
- Presented as a gentle card, not a correction
---
## Journey Stage 3: The Ritual (Connector Feature)
The Ritual chains Mirror → Turn → Lens into a single context-anchored daily flow.
**Access:** Dedicated "Start Ritual" button at top of Turn tab, or via notification
**Template Selection:**
*Morning Ritual (15-20 min):*
1. Mirror check-in: "How are you waking up today?" (3 min writing)
2. Turn: AI identifies strongest fragment from Mirror → offers reframe (2 min)
3. Lens: Today's priority action from active goal (1 min review)
4. Affirmation: Daily affirmation card
5. Set intention: One sentence for the day
*Evening Ritual (10-15 min):*
1. Mirror reflection: "What stood out about today?" (3 min writing)
2. Turn: Process any unresolved thought from the day (2 min)
3. Lens review: Mark completed actions, log noticed moments
4. Gratitude: One thing from today (saved to Gallery)
*Quick Ritual (5 min):*
1. One-line check-in
2. Fastest Turn (single perspective)
3. One action reminder
**Ritual Flow UI:**
- Step indicators using fragment-shaped progress bar (from progress-indicators.svg)
- Each step has a timer (visible but not pressuring)
- Smooth transitions between steps (fragment scatter/converge animation)
- Completion → Success burst → streak updated
**Ritual Tracking:**
- Streak calendar (7-day week view, Amber jewel tone)
- Context consistency tracking (Wood et al.): same time, same place → stronger habit
- Ritual completion logged to Evidence Wall
**Rate Limiting (Free):** Quick Ritual only. Prism: all 3 templates.
---
## Journey Stage 4: Spectrum (Phase 2 — Intelligence Layer)
**Unlock:** After 2 weeks of active use (minimum 5 Turns, 2 Mirror sessions)
**Teaser Period:**
- Notification: "Something is forming... Your Spectrum is almost ready."
- Small locked card on You tab with shimmer animation
**Launch Reveal:**
- Full-screen animation: fragments converge into prismatic kaleidoscope
- User's first Spectrum dashboard appears
**Dashboard Components:**
**The River (Emotional Flow):**
- Flowing prismatic gradient band showing emotional valence over time
- Data points as fragment icons at key moments
- X-axis: days/weeks, Y-axis: emotional valence
- Hover/tap any point → detail card with source Turn/Mirror session
**Your Glass (Distortion Distribution):**
- Radar/spider chart showing which of the 10 distortion types appear most
- Amber jewel tone data shape on hex grid
- Vertices as fragment icons
- Evolves weekly as patterns shift
**Turn Impact (Before/After):**
- Bar chart pairs showing emotional metrics before and after Turns
- Metrics: Distress level, Clarity, Hope
- Ruby bars (before) vs Emerald bars (after)
- Rolling 30-day average
**Rhythm Detection (Your Cycles):**
- Time-of-day engagement pattern
- Bubble sizes represent intensity
- Peak labels with fragment accents
- Helps user identify best times for practice
**Growth Trajectory (The Long View):**
- Line chart with fragment data points
- Y-axis: Resilience Score (composite of fragment density, self-correction rate, reframe adoption, distortion diversity, Turn-to-insight ratio)
- Milestone markers (10th Turn, 30-day streak, etc.)
- Monthly trend with prismatic gradient fill under curve
**Cadence:**
- Weekly summary: Sunday evening notification with 1 key insight
- Monthly deep dive: First of month with month-over-month comparison
- In-context nudges: Insights surface within Mirror/Turn/Lens at natural moments
**Rate Limiting (Free):** Simplified weekly summary (1 insight, no visuals, basic fragment counts). Prism: full dashboard, all 5 components, weekly/monthly deep dives, growth trajectory, export.
---
## Journey Stage 5: Engagement Deepening & Retention
### Streak System
- Daily streak counter (consecutive days with at least 1 Turn or Ritual)
- Visual: flame icon with Amber gradient, pulse animation
- Milestones: 3, 7, 14, 30, 60, 90, 180, 365 days
- Each milestone → special pattern generated, saved to Gallery
- Streak freeze: 1 free per week (Prism: 3 per week)
### Push Notifications
- Daily check-in at user's chosen time
- Streak maintenance reminders (if about to break)
- Milestone celebrations
- Weekly Spectrum insights (Prism)
- Ritual reminders at consistent time/place
- Never more than 2 per day
### Empty States
- Every screen has a warm, encouraging empty state
- Uses breathing logo animation or floating shard clusters
- Copy examples:
- Turn: "What would you like to see differently today?"
- Mirror: "Ready to write? There's no wrong way to start."
- Lens: "What are you working toward? Let's build a path."
- Gallery: "Your first pattern is waiting to be created."
- Evidence Wall: "Every small step is evidence. Start collecting."
### Upgrade Moments (Free → Prism)
- After hitting 3 Turn limit: "You're on a roll. Unlock unlimited Turns."
- After 2nd Mirror session: "Want to explore all 10 distortion types?"
- After first Rehearsal: "That felt good, right? Get unlimited Rehearsals."
- After Evidence Wall shows 10+ tiles: "Your evidence is growing. See the full picture with Spectrum."
- Never blocks current action — always shows after completion
---
## Journey Stage 6: System States
### Loading States
- Initial load: Breathing logo animation
- Feature transitions: Fragment scatter/converge
- AI processing: 3-fragment oscillation (AI thinking bubble)
- Data loading: Skeleton shimmer (text lines + card shapes)
- Long operations: Iris spinner with progress text
### Error States
- Network error: "Lost connection. Your data is safe — we'll sync when you're back."
- AI error: "Our thinking engine needs a moment. Try again in a few seconds."
- Rate limit: Feature-specific messaging (see each feature above)
- Generic: Ruby-accent toast with retry option
### Success States
- Turn saved: Emerald toast "Turn saved" with fragment icon
- Goal completed: Success burst animation (expanding rings + particle fragments)
- Streak milestone: Special celebration with pattern generation
- Ritual complete: Prismatic ring completion animation
### Offline Mode
- Turn input cached locally, syncs when online
- Mirror sessions continue with local fragment detection (basic)
- Gallery browsable offline
- Clear indicator: "Offline — your work will sync automatically"
---
## Monetization Tiers
### Kalei (Free)
| Feature | Limit |
|---------|-------|
| Turn | 3 per day |
| Mirror | 2 sessions per week, 3 distortion types |
| Lens | 1 active goal, basic actions |
| Rehearsal | 1 per week |
| Ritual | Quick template only |
| Evidence Wall | 30-day window |
| Gallery | Full access |
| Spectrum | Simplified weekly summary (text only) |
### Kalei Prism ($7.99/month)
| Feature | Access |
|---------|--------|
| Turn | Unlimited |
| Mirror | Unlimited sessions, all 10 distortion types, unlimited inline reframes |
| Lens | Unlimited goals, AI-refined actions |
| Rehearsal | Unlimited |
| Ritual | All 3 templates |
| Evidence Wall | Full history, no time window |
| Gallery | Full access + export |
| Spectrum | Full dashboard, all 5 components, weekly/monthly insights, growth trajectory |
---
## Appendix: Screen Inventory
| # | Screen | Tab | Feature |
|---|--------|-----|---------|
| 1 | Splash | — | System |
| 2 | Welcome | — | Onboarding |
| 3 | Fragment Intro | — | Onboarding |
| 4 | Turn Demo | — | Onboarding |
| 5 | Style Selection | — | Onboarding |
| 6 | Notification Permission | — | Onboarding |
| 7 | Account Creation | — | Onboarding |
| 8 | First Turn | — | Onboarding |
| 9 | Welcome Complete | — | Onboarding |
| 10 | Turn Home (empty) | Turn | Turn |
| 11 | Turn Input Active | Turn | Turn |
| 12 | Turn Animation | Turn | Turn |
| 13 | Turn Results | Turn | Turn |
| 14 | Turn History | Turn | Turn |
| 15 | Mirror Home (empty) | Mirror | Mirror |
| 16 | Mirror Session Active | Mirror | Mirror |
| 17 | Mirror Fragment Highlight | Mirror | Mirror |
| 18 | Mirror Fragment Detail (half-sheet) | Mirror | Mirror |
| 19 | Mirror Session Reflection | Mirror | Mirror |
| 20 | Lens Dashboard | Lens | Lens |
| 21 | Lens Goal Creation Step 1 | Lens | Lens |
| 22 | Lens Goal Creation Step 2 | Lens | Lens |
| 23 | Lens Goal Creation Step 3 | Lens | Lens |
| 24 | Lens Goal Creation Step 4 | Lens | Lens |
| 25 | Lens Goal Creation Step 5 | Lens | Lens |
| 26 | Lens Goal Creation Step 6 | Lens | Lens |
| 27 | Lens Goal Detail | Lens | Lens |
| 28 | Lens Daily Affirmation | Lens | Lens |
| 29 | Rehearsal Session | Lens | Rehearsal |
| 30 | Rehearsal Complete | Lens | Rehearsal |
| 31 | Gallery All Patterns | Gallery | Gallery |
| 32 | Gallery Keepsakes | Gallery | Gallery |
| 33 | Gallery Pattern Detail | Gallery | Gallery |
| 34 | Gallery Search/Filter | Gallery | Gallery |
| 35 | You Profile | You | You |
| 36 | You Stats | You | You |
| 37 | You Settings | You | Settings |
| 38 | You Subscription | You | Billing |
| 39 | Evidence Wall (empty) | You | Evidence Wall |
| 40 | Evidence Wall (early) | You | Evidence Wall |
| 41 | Evidence Wall (mid) | You | Evidence Wall |
| 42 | Evidence Wall (full) | You | Evidence Wall |
| 43 | Evidence Wall Tile Detail | You | Evidence Wall |
| 44 | Ritual Template Selection | Turn | Ritual |
| 45 | Ritual Morning Flow | Turn | Ritual |
| 46 | Ritual Evening Flow | Turn | Ritual |
| 47 | Ritual Quick Flow | Turn | Ritual |
| 48 | Ritual Complete | Turn | Ritual |
| 49 | Ritual Streak View | Turn | Ritual |
| 50 | Spectrum Dashboard | You | Spectrum |
| 51 | Spectrum The River | You | Spectrum |
| 52 | Spectrum Your Glass | You | Spectrum |
| 53 | Spectrum Turn Impact | You | Spectrum |
| 54 | Spectrum Rhythm | You | Spectrum |
| 55 | Spectrum Growth | You | Spectrum |
| 56 | Spectrum Weekly Summary | You | Spectrum |
| 57 | Spectrum Monthly Deep Dive | You | Spectrum |
| 58 | Upgrade Modal | — | Billing |
| 59 | Rate Limit Notice | — | System |
| 60 | Crisis Response | — | Safety |
| 61 | Pattern Card Share | — | Social |
| 62 | Notification Settings | You | Settings |
| 63 | Data Export | You | Settings |
| 64 | Account Deletion Confirm | You | Settings |

View File

@ -1,5 +1,19 @@
# The Mirror — Kalei's Notebook Feature # The Mirror — Kalei's Notebook Feature
## Scientific Foundation
The Mirror is Kalei's most direct application of attention and neuroscience research.
**Selective Attention as the Core Mechanism:** Yantis (2008) showed that selective attention operates through modulatory signals that amplify relevant information and suppress irrelevant inputs. The Mirror externalizes this process — Kalei's AI acts as an attentional amplifier, highlighting cognitive patterns the user's own system has habituated to and stopped noticing. The highlighted fragments aren't new information; they're existing patterns made visible through redirected attention.
**Attention Is Trainable:** Stevens & Bavelier (2012) demonstrated that attentional control improves with practice and transfers across domains. Regular Mirror use trains the user to notice their own cognitive distortions — first with AI assistance, eventually independently. The Spectrum's "self-correction rate" metric (Phase 2) directly measures this training effect.
**Attention vs. Consciousness:** Koch & Tsuchiya's distinction between attention and consciousness is operationally important. The Mirror works at the attention level: it doesn't require the user to be consciously aware of their patterns (consciousness) — it simply redirects attention toward them. The conscious recognition follows naturally.
**Habit Formation Through Consistent Practice:** Wood & Neal (2007) showed that habits form through context-response associations. Regular Mirror sessions — anchored to consistent contexts (time of day, emotional state) — train the habit of reflective self-examination until it becomes automatic.
---
## The Concept ## The Concept
The Kaleidoscope (Turn) is structured: one fragment in, patterns out. It works when you **know** what's bothering you. The Kaleidoscope (Turn) is structured: one fragment in, patterns out. It works when you **know** what's bothering you.
@ -86,7 +100,7 @@ As the user writes (or after each message is sent), Kalei's AI analyzes the text
- A small **◇ icon** (fragment symbol) appears at the end of the highlighted phrase, indicating this fragment can be Turned - A small **◇ icon** (fragment symbol) appears at the end of the highlighted phrase, indicating this fragment can be Turned
- Highlights appear **after the user finishes a message** (not while typing — that would be intrusive and anxiety-inducing) - Highlights appear **after the user finishes a message** (not while typing — that would be intrusive and anxiety-inducing)
**Critical UX principle:** The highlighting must feel like **noticing**, not **judging**. The AI is a mirror, not a critic. The user should feel seen, not corrected. **Critical UX principle:** The highlighting must feel like **noticing**, not **judging**. The AI is a mirror, not a critic. The user should feel seen, not corrected. This distinction is scientifically grounded — Bandura (1977) showed that perceived criticism undermines self-efficacy, while neutral observation preserves it. The Mirror builds capability awareness, not self-judgment.
### Tapping a Fragment — Inline Reframing ### Tapping a Fragment — Inline Reframing
@ -202,6 +216,8 @@ Track separately from Turn streaks:
- "You've written in the Mirror 5 days in a row" - "You've written in the Mirror 5 days in a row"
- Mirror sessions tend to be longer and more personal → higher engagement signal - Mirror sessions tend to be longer and more personal → higher engagement signal
**Science note:** Wood et al. (2021) found that context stability is the single biggest predictor of habit formation. Mirror streaks should track not just frequency but context consistency — "You've written in the Mirror at roughly the same time for 14 days" is a stronger habit signal than "14 sessions total across random times."
### Fragment Tracking Over Time ### Fragment Tracking Over Time
The Gallery can show **fragment patterns over time**: The Gallery can show **fragment patterns over time**:
@ -211,6 +227,8 @@ The Gallery can show **fragment patterns over time**:
This turns the Mirror from a journal into a **self-awareness engine**. Users can literally see their thinking patterns change over time. This turns the Mirror from a journal into a **self-awareness engine**. Users can literally see their thinking patterns change over time.
**Science note:** This longitudinal tracking implements Stevens & Bavelier's (2012) finding that attention training transfers and compounds. The fragment density decline over time is a measurable proxy for improved attentional self-awareness — the user is literally catching patterns earlier and more often because their attentional system has been retrained.
### Mirror Prompts ### Mirror Prompts
For days when the user opens the Mirror but doesn't know what to write: For days when the user opens the Mirror but doesn't know what to write:

View File

@ -1,5 +1,19 @@
# The Spectrum — Kalei Phase 2 # The Spectrum — Kalei Phase 2
## Scientific Foundation
The Spectrum is where multiple research pillars converge into a single intelligence layer.
**Expectation Effects (Stetler 2014, Pardo-Cabello et al. 2022):** The Turn Impact component ("Before & After") is a deliberate evidence engine. Stetler demonstrated that consistent adherence to a process reinforces positive expectations, which in turn improve outcomes — a documented feedback loop. By showing users concrete proof that reframing measurably shifts their subsequent emotional state, the Spectrum accelerates this cycle. The transparency doesn't weaken the effect; it strengthens it.
**Habit Formation (Wood & Neal 2007, Wood et al. 2021):** Rhythm Detection and streak mechanics implement Wood's finding that ~43% of daily behavior is habitual and that context stability predicts habit formation. The Spectrum tracks context patterns (time-of-day rhythms, weekly cycles) to help users understand and leverage their own behavioral patterns.
**Selective Attention (Yantis 2008, Stevens & Bavelier 2012):** Fragment Pattern tracking ("Your Glass") operates the Mirror's attentional principle at a longitudinal scale. Instead of highlighting individual distortions in real-time, it reveals macro-patterns: which cognitive biases dominate, how they shift over time, and which respond most to reframing. This is attentional self-knowledge — seeing your own perceptual filters from the outside.
**Self-Efficacy (Bandura 1977):** The Growth Trajectory ("The Long View") directly implements Bandura's most potent self-efficacy source: mastery experiences. By tracking fragment density decline, self-correction rate, and reframe adoption, the Spectrum provides concrete evidence of growing capability — "You are getting better at this" backed by data, not platitudes.
---
## Emotional Intelligence, Not Mood Tracking ## Emotional Intelligence, Not Mood Tracking
Every wellness app asks you to rate your mood on a scale. Tap a smiley face. Drag a slider. It's self-reported, inaccurate, and most people stop doing it after two weeks because it feels like homework. Every wellness app asks you to rate your mood on a scale. Tap a smiley face. Drag a slider. It's self-reported, inaccurate, and most people stop doing it after two weeks because it feels like homework.
@ -91,6 +105,8 @@ The AI compares the emotional tone of Mirror sessions **before and after** a Tur
This is the **evidence engine** for Kalei's core thesis: that changing the angle actually changes how you feel. Users can see the proof in their own data. This is the **evidence engine** for Kalei's core thesis: that changing the angle actually changes how you feel. Users can see the proof in their own data.
**Science note:** This directly implements Stetler's (2014) adherence-expectation model. When users see measurable shifts in their own emotional data after Turns, it reinforces the expectation that reframing works — which increases future engagement and actual benefit. Pardo-Cabello et al. (2022) confirmed that the quality of the therapeutic relationship (or in Kalei's case, the app-user relationship) is the strongest predictor of whether expectation effects materialize. The Spectrum builds that trust through evidence.
### 4. Rhythm Detection — "Your Cycles" ### 4. Rhythm Detection — "Your Cycles"
Identifies recurring emotional patterns tied to time. Identifies recurring emotional patterns tied to time.
@ -110,6 +126,8 @@ Identifies recurring emotional patterns tied to time.
The user starts to see their emotional life as a **landscape with terrain** rather than random weather. Some hills are always there. Some valleys are seasonal. That awareness alone is a superpower. The user starts to see their emotional life as a **landscape with terrain** rather than random weather. Some hills are always there. Some valleys are seasonal. That awareness alone is a superpower.
**Science note:** Rhythm Detection operationalizes Wood et al.'s (2021) finding that habits are triggered by context cues. By revealing temporal patterns ("Mondays are heavy on should-statements"), the Spectrum helps users anticipate and prepare for predictable emotional terrain — turning reactive coping into proactive awareness.
### 5. Growth Trajectory — "The Long View" ### 5. Growth Trajectory — "The Long View"
The headline metric: **how is this person's relationship with their own thinking changing over time?** The headline metric: **how is this person's relationship with their own thinking changing over time?**
@ -125,6 +143,8 @@ The headline metric: **how is this person's relationship with their own thinking
This becomes the **centerpiece of the Spectrum dashboard** — your personal growth, visualized as a living kaleidoscope pattern. This becomes the **centerpiece of the Spectrum dashboard** — your personal growth, visualized as a living kaleidoscope pattern.
**Science note:** Every tracked indicator maps to Bandura's (1977) self-efficacy sources. Fragment density decline and self-correction rate are mastery experiences (the strongest efficacy source). Reframe adoption shows vicarious learning internalized. The evolving pattern visualization provides a visceral, non-numerical representation of growing capability — "I am getting better at this" made visible.
**Milestone moments:** **Milestone moments:**
> "Your fragment density has dropped 30% since you started. You're catching your own patterns now." > "Your fragment density has dropped 30% since you started. You're catching your own patterns now."
@ -347,6 +367,8 @@ The Spectrum solves the biggest problem in wellness apps: **the drop-off after t
The Spectrum turns Kalei from a tool you use when you feel bad into a **dashboard you check because you're curious about yourself.** That's the difference between reactive usage (declining) and proactive usage (compounding). The Spectrum turns Kalei from a tool you use when you feel bad into a **dashboard you check because you're curious about yourself.** That's the difference between reactive usage (declining) and proactive usage (compounding).
**Science note:** This retention mechanic is grounded in both habit formation and expectation effects. Wood et al. (2021) showed that shifting behavior from goal-directed (conscious, effortful) to habitual (automatic, context-triggered) is what sustains long-term change. Stetler (2014) showed that consistent engagement reinforces positive expectations. The Spectrum provides the evidence that keeps both loops spinning.
--- ---
## Phase 2 Launch Sequence ## Phase 2 Launch Sequence

View File

@ -0,0 +1,643 @@
# Kalei — Architecture & User Journey Diagrams
All diagrams below are valid Mermaid syntax. Paste into any Mermaid renderer (mermaid.live, GitHub markdown, VS Code preview) to visualize.
---
## 1. Complete User Journey
Shows the full lifecycle from app discovery through onboarding, daily habit loops, conversion, and long-term retention.
```mermaid
flowchart LR
subgraph Acquisition["Acquisition"]
A1["App Store Discovery"] --> A2["Download App"]
A2 --> A3["Open for First Time"]
end
subgraph Onboarding["Onboarding Flow"]
A3 --> O1["Welcome Screen"]
O1 --> O2["3 Swipeable Intro Cards"]
O2 --> O3["Choose Reframe Style\n(Brutal / Gentle / Logical / Philosophical / Humor)"]
O3 --> O4["Set Daily Check-in Time"]
O4 --> O5["Create Account\n(Email / Google / Apple)"]
O5 --> O6["First Reframe — WOW Moment"]
O6 --> O7["Land on Home Screen"]
end
subgraph DailyLoop["Daily Habit Loop"]
O7 --> D1["Push Notification\n'What's weighing on you?'"]
D1 --> D2{"User Intent"}
D2 -->|"Quick reframe"| T1["The Turn\n(Kaleidoscope)"]
D2 -->|"Need to process"| M1["The Mirror\n(Freeform Writing)"]
D2 -->|"Goal focus"| L1["The Lens\n(Manifestation)"]
D2 -->|"Review history"| G1["The Gallery"]
T1 --> D3["Save Reframe / Keepsake"]
M1 --> D3
L1 --> D3
D3 --> D4["Streak Updated"]
D4 --> D5["Return Tomorrow"]
D5 --> D1
end
subgraph Deepening["Engagement Deepening"]
G1 --> E1["See Thought Patterns Over Time"]
E1 --> E2["Weekly Summary\n(Sunday Push)"]
E2 --> E3["Discover Recurring Fragments"]
E3 --> E4["Motivation to Continue"]
E4 --> D1
end
subgraph Conversion["Free → Premium"]
D4 --> C1{"Hit Free Tier Limit?"}
C1 -->|"Yes"| C2["Soft Paywall\n'Unlock unlimited Turns'"]
C2 --> C3{"Convert?"}
C3 -->|"Yes"| C4["Subscribe to Prism\n($4.99/mo)"]
C3 -->|"Not yet"| D5
C4 --> C5["Full Access Unlocked"]
C5 --> D1
end
subgraph Retention["Long-Term Retention"]
C5 --> R1["Spectrum Dashboard\n(Phase 2 / Prism+)"]
R1 --> R2["Monthly AI Insights"]
R2 --> R3["Growth Trajectory"]
R3 --> R4["Deep Self-Knowledge"]
R4 --> D1
end
```
---
## 2. Backend System Architecture
The full backend from client through edge, API services, AI layer, data stores, and external integrations.
```mermaid
flowchart TB
subgraph Client["Client Layer"]
APP["React Native + Expo App"]
TURN_UI["Turn Screen"]
MIRROR_UI["Mirror Screen"]
LENS_UI["Lens Screen"]
GALLERY_UI["Gallery Screen"]
SPECTRUM_UI["Spectrum Dashboard"]
PROFILE_UI["Profile & Settings"]
end
subgraph Edge["Edge Layer"]
CF["Cloudflare\nDNS / CDN / DDoS"]
NGINX["Nginx\nReverse Proxy / SSL / Rate Limit"]
end
subgraph API["API Layer — Modular Monolith (Fastify)"]
GW["API Gateway & Auth\n(JWT + Refresh Rotation)"]
TURN_SVC["Turn Service"]
MIRROR_SVC["Mirror Service"]
LENS_SVC["Lens Service"]
SPECTRUM_SVC["Spectrum Service"]
SAFETY_SVC["Safety Service\n(Crisis Detection)"]
ENT_SVC["Entitlement Service\n(Plan Gating)"]
COST_SVC["Usage Meter &\nCost Guard"]
JOBS["Job Scheduler\n& Workers"]
NOTIF["Notification Service"]
end
subgraph AI["AI Layer"]
AI_GW["AI Gateway\n(Provider Routing)"]
CLAUDE["Claude Haiku 4.5\n(Primary — Quality Lane)"]
CLAUDE_BATCH["Claude Batch API\n(50% Off — Spectrum)"]
FALLBACK["Groq / OpenRouter\n(Cost Fallback Lane)"]
end
subgraph Data["Data Layer"]
PG["PostgreSQL 16\n(Source of Truth)"]
REDIS["Redis\n(Cache / Rate Limits / Counters)"]
OBJ["Object Storage\n(Spectrum Exports)"]
end
subgraph External["External Services"]
APPLE["Apple App Store\nBilling API"]
GOOGLE["Google Play\nBilling API"]
APNS["APNs"]
FCM["FCM"]
POSTHOG["PostHog\n(Self-Hosted Analytics)"]
GLITCHTIP["GlitchTip\n(Error Tracking)"]
end
APP --> CF --> NGINX --> GW
GW --> TURN_SVC
GW --> MIRROR_SVC
GW --> LENS_SVC
GW --> SPECTRUM_SVC
GW --> ENT_SVC
TURN_SVC --> SAFETY_SVC
MIRROR_SVC --> SAFETY_SVC
LENS_SVC --> SAFETY_SVC
TURN_SVC --> AI_GW
MIRROR_SVC --> AI_GW
LENS_SVC --> AI_GW
SPECTRUM_SVC --> AI_GW
AI_GW --> CLAUDE
AI_GW --> CLAUDE_BATCH
AI_GW --> FALLBACK
TURN_SVC --> COST_SVC
MIRROR_SVC --> COST_SVC
LENS_SVC --> COST_SVC
COST_SVC --> REDIS
TURN_SVC --> PG
MIRROR_SVC --> PG
LENS_SVC --> PG
SPECTRUM_SVC --> PG
ENT_SVC --> PG
JOBS --> PG
ENT_SVC --> APPLE
ENT_SVC --> GOOGLE
NOTIF --> APNS
NOTIF --> FCM
GW --> POSTHOG
GW --> GLITCHTIP
```
---
## 3. The Mirror (Awareness) — Sequence Diagram
Complete sequence from session start through writing, fragment detection, inline reframing, and session reflection.
```mermaid
sequenceDiagram
participant U as User
participant App as Mobile App
participant API as Kalei API
participant Safety as Safety Service
participant Ent as Entitlement Service
participant AI as AI Gateway
participant Model as Claude Haiku 4.5
participant DB as PostgreSQL
participant R as Redis
Note over U,R: Session Start
U->>App: Opens Mirror tab
App->>API: POST /mirror/sessions
API->>Ent: Check plan (free: 2/week, prism: unlimited)
Ent->>R: Read session counter
R-->>Ent: Counter value
Ent-->>API: Allowed / Denied
API->>DB: Create mirror_session row
API-->>App: Session ID + empty state prompt
Note over U,R: Writing & Fragment Detection Loop
U->>App: Writes message freely
App->>API: POST /mirror/messages
API->>Safety: Crisis precheck on text
alt Crisis Detected
Safety->>DB: Log safety_event
API-->>App: Crisis resources (hotlines, warm message)
else Safe Content
API->>AI: Fragment detection prompt + user text
AI->>Model: Inference request (cached system prompt)
Model-->>AI: JSON with fragments + confidence scores
AI-->>API: Validated structured result
API->>DB: Save message + fragments (confidence > 0.75)
API->>R: Increment usage counters
API-->>App: Message with highlighted fragments (amber glow + ◇ icons)
end
Note over U,R: User Taps a Fragment
U->>App: Taps highlighted fragment ◇
App->>API: POST /mirror/fragments/{id}/reframe
API->>AI: Reframe prompt + fragment + surrounding context
AI->>Model: Inference request
Model-->>AI: Reframe + distortion explanation
AI-->>API: Validated reframe response
API->>DB: Update fragment (was_tapped, was_reframed, reframe_text)
API-->>App: Mini-card slides up with reframe
App-->>U: Shows pattern name + alternative angle + Full Turn option
Note over U,R: Session Close & Reflection
U->>App: Presses Done / closes Mirror
App->>API: POST /mirror/sessions/{id}/close
API->>AI: Generate Reflection from all messages + fragments
AI->>Model: Batch summary request
Model-->>AI: Mosaic themes + fragment count + insight
AI-->>API: Reflection payload
API->>DB: Update session with reflection + pattern_seed
API-->>App: Reflection card (Mosaic + fragments found + patterns + one-line insight)
App-->>U: Reflection saved to Gallery
```
---
## 4. The Turn (Kaleidoscope) — Sequence Diagram
The structured reframing flow with entitlement gating, safety checks, and multi-perspective AI generation.
```mermaid
sequenceDiagram
participant U as User
participant App as Mobile App
participant API as Kalei API
participant Ent as Entitlement Service
participant Safety as Safety Service
participant AI as AI Gateway
participant Model as Claude Haiku 4.5
participant DB as PostgreSQL
participant Cost as Cost Guard
participant R as Redis
Note over U,R: User Submits a Fragment for Turning
U->>App: Types negative thought + selects style
App->>API: POST /turns {text, style, context}
Note over API,R: Validation & Gating
API->>Ent: Validate tier + daily Turn cap
Ent->>R: Check daily counter (free: 3/day)
R-->>Ent: Current count
Ent-->>API: Allowed / Limit reached
alt Limit Reached
API-->>App: Soft paywall prompt
App-->>U: "Unlock unlimited Turns with Prism"
else Allowed
Note over API,R: Safety Gate
API->>Safety: Crisis precheck on text
alt Crisis Detected
Safety->>DB: Log safety_event
API-->>App: Crisis resources response
App-->>U: Hotline numbers + warm message
else Safe Content
Note over API,R: AI Reframe Generation
API->>AI: Build prompt (cached system + user style + fragment + history context)
AI->>Model: Streaming inference request
Model-->>AI: 3 reframe perspectives + micro-action (if-then)
AI-->>API: Validated structured response + token count
Note over API,R: Record & Respond
API->>Cost: Record token usage + budget check
Cost->>R: Update per-user + global counters
API->>DB: Save turn + reframes + metadata
API-->>App: Stream final Turn result
Note over U,App: User Sees the Turn Card
App-->>U: Original fragment quoted
App-->>U: 3 perspective reframes in chosen style
App-->>U: Micro-action (Gollwitzer if-then)
App-->>U: "Why This Works" expandable science drawer
Note over U,App: Post-Turn Actions
U->>App: Save as Keepsake / Try Different Style / Share
App->>API: POST /turns/{id}/save
API->>DB: Mark as saved keepsake
API-->>App: Streak counter updated
end
end
```
---
## 5. The Lens (Manifestation Engine) — 6-Step Flow
The complete goal creation and daily action system mapped to the 6 research-backed steps.
```mermaid
flowchart TB
subgraph Step1["Step 1: DECIDE — Clarity"]
S1A["User taps 'Create a Manifestation'"] --> S1B["AI Conversation (3-5 exchanges)\n'What do you want to achieve?'"]
S1B --> S1C["SMART Goal Refinement"]
S1C --> S1D["Output: Clarity Statement Card"]
end
subgraph Step2["Step 2: SEE IT — Mental Rehearsal"]
S1D --> S2A["AI generates personalized\nvisualization script"]
S2A --> S2B["First-person, sensory-rich,\nprocess-focused imagery"]
S2B --> S2C["User reads/listens\nMarks as complete"]
S2C --> S2D["Output: Vision Summary\n(revisitable daily)"]
end
subgraph Step3["Step 3: BELIEVE — Self-Efficacy"]
S2D --> S3A["AI asks:\n'What makes you doubt\nthis is possible?'"]
S3A --> S3B["User lists doubts"]
S3B --> S3C["AI addresses each with:\npast successes + transferable skills\n+ role models + small wins"]
S3C --> S3D["Output: Belief Statement Card\n'You CAN — here's the evidence'"]
end
subgraph Step4["Step 4: NOTICE — Attention Training"]
S3D --> S4A["AI sets up daily\nattention prompts"]
S4A --> S4B["Daily push:\n'Notice one thing aligned\nwith your goal today'"]
S4B --> S4C["User logs observations\nBuilds Evidence Journal"]
S4C --> S4D["AI surfaces patterns:\n'23 alignment instances\nthis month'"]
end
subgraph Step5["Step 5: ACT — Implementation Intentions"]
S4D --> S5A["AI generates weekly\nmicro-actions"]
S5A --> S5B["Gollwitzer if-then format:\n'If [time/situation],\nthen I will [15-min action]'"]
S5B --> S5C["User checks off\ncompleted actions"]
S5C --> S5D["AI adapts difficulty:\n2-min actions → scales up\nas habit solidifies"]
end
subgraph Step6["Step 6: REPEAT — Compound"]
S5D --> S6A["Habit Tracking Dashboard"]
S6A --> S6B["Visual growth charts\nMilestone celebrations"]
S6B --> S6C["Weekly AI Summary:\nreframes + patterns +\nprogress + adjustments"]
S6C --> S6D["Celebrates PROCESS\nnot just outcomes"]
S6D --> S4B
end
```
---
## 6. AI Processing Pipeline & Cost Routing
How every AI request flows through the gateway with prompt caching, safety guards, and cost-aware provider routing.
```mermaid
flowchart LR
subgraph Input["Request Sources"]
MIRROR["Mirror\n(Fragment Detection)"]
TURN["Turn\n(3 Reframes)"]
LENS["Lens\n(Affirmations)"]
SPECTRUM["Spectrum\n(Weekly Insights)"]
end
subgraph Pipeline["AI Gateway Pipeline"]
PROMPT["Prompt Builder\n(System + User Context + Research Grounding)"]
CACHE["Prompt Cache Check\n(90% savings on cached system prompts)"]
SAFETY_CHECK["Anti-Toxicity Guard\n(No toxic positivity / magical thinking)"]
ROUTER{"Cost Router\nBudget Check"}
end
subgraph QualityLane["Quality Lane"]
CLAUDE_RT["Claude Haiku 4.5\n(Real-time Inference)"]
end
subgraph BatchLane["Batch Lane (50% Off)"]
CLAUDE_BATCH["Claude Haiku 4.5\nBatch API"]
end
subgraph CostLane["Cost Fallback Lane"]
GROQ["Groq — Qwen3-32B\n($0.29/MTok)"]
end
subgraph Output["Response Handling"]
VALIDATE["Structured Output\nValidation (JSON)"]
TOKEN_LOG["Token Usage Logger"]
BUDGET["Budget Tracker\n(Per-user daily + Global monthly)"]
RESPONSE["Stream Response\nto Client"]
end
subgraph Alerts["Cost Controls"]
ALERT50["50% Budget Alert"]
ALERT80["80% Budget Alert\nDegrade Lens to templates"]
ALERT95["95% Budget Alert\nPause Spectrum generation"]
HARDCAP["100% Hard Cap\nGraceful service message"]
end
MIRROR --> PROMPT
TURN --> PROMPT
LENS --> PROMPT
SPECTRUM --> PROMPT
PROMPT --> CACHE
CACHE --> SAFETY_CHECK
SAFETY_CHECK --> ROUTER
ROUTER -->|"Mirror / Turn\n(quality critical)"| CLAUDE_RT
ROUTER -->|"Spectrum / Weekly\n(non-realtime)"| CLAUDE_BATCH
ROUTER -->|"Lens / basic content\n(budget pressure)"| GROQ
CLAUDE_RT --> VALIDATE
CLAUDE_BATCH --> VALIDATE
GROQ --> VALIDATE
VALIDATE --> TOKEN_LOG
TOKEN_LOG --> BUDGET
BUDGET --> RESPONSE
BUDGET --> ALERT50
BUDGET --> ALERT80
BUDGET --> ALERT95
BUDGET --> HARDCAP
```
---
## 7. Safety & Crisis Detection Flow
The multi-stage safety pipeline that ensures crisis content is never reframed.
```mermaid
flowchart TB
subgraph Input["User Input Arrives"]
MSG["User text from\nMirror / Turn / Lens"]
end
subgraph Stage1["Stage 1: Deterministic Keyword Scan"]
KW["Keyword & Pattern Matcher\n(Regex-based, zero latency)"]
KW_YES{"Crisis keywords\ndetected?"}
end
subgraph Stage2["Stage 2: AI Confirmation"]
AI_CHECK["Low-latency AI model\nconfirms severity"]
AI_YES{"Confirmed\ncrisis?"}
end
subgraph CrisisResponse["Crisis Response — NEVER Reframed"]
CR1["Hardcoded crisis template\n(Not AI-generated)"]
CR2["Display local hotline numbers\n(988 Lifeline, Crisis Text Line)"]
CR3["Warm handoff message:\n'You matter. Help is available\nright now.'"]
CR4["Log safety_event to DB\nfor monitoring"]
end
subgraph NormalFlow["Normal Processing"]
PROCEED["Continue to AI Gateway\nfor reframing / detection"]
end
subgraph Monitoring["Safety Monitoring"]
FP["Track false positives\nfor filter tuning"]
FN["Track false negatives\nvia user reports"]
REVIEW["Weekly safety review loop"]
end
MSG --> KW
KW --> KW_YES
KW_YES -->|"Yes — high confidence\n(explicit phrases)"| CR1
KW_YES -->|"Maybe — ambiguous"| AI_CHECK
KW_YES -->|"No"| PROCEED
AI_CHECK --> AI_YES
AI_YES -->|"Yes"| CR1
AI_YES -->|"No — false alarm"| PROCEED
CR1 --> CR2
CR2 --> CR3
CR3 --> CR4
PROCEED --> FP
CR4 --> FN
FP --> REVIEW
FN --> REVIEW
```
---
## 8. Subscription & Billing State Machine
All user states from anonymous through free, Prism, and Prism+ with renewal, grace period, and downgrade flows.
```mermaid
stateDiagram-v2
[*] --> Anonymous: App Downloaded
Anonymous --> FreeUser: Account Created
state FreeUser {
[*] --> ActiveFree
ActiveFree --> LimitHit: Daily/weekly cap reached
LimitHit --> ActiveFree: Next day/week resets
LimitHit --> PaywallShown: Soft upgrade prompt
}
state PrismSubscriber {
[*] --> ActivePrism
ActivePrism --> PrismRenewal: Monthly renewal
PrismRenewal --> ActivePrism: Payment success
PrismRenewal --> GracePeriod: Payment failed
GracePeriod --> ActivePrism: Retry success
GracePeriod --> Expired: Grace period ends
}
state PrismPlusSubscriber {
[*] --> ActivePrismPlus
ActivePrismPlus --> PlusMRenewal: Monthly renewal
PlusMRenewal --> ActivePrismPlus: Payment success
PlusMRenewal --> PlusGrace: Payment failed
PlusGrace --> ActivePrismPlus: Retry success
PlusGrace --> PlusExpired: Grace period ends
}
FreeUser --> PrismSubscriber: Subscribe $4.99/mo
FreeUser --> PrismPlusSubscriber: Subscribe $9.99/mo
PrismSubscriber --> PrismPlusSubscriber: Upgrade
PrismPlusSubscriber --> PrismSubscriber: Downgrade
PrismSubscriber --> FreeUser: Cancel / Expired
PrismPlusSubscriber --> FreeUser: Cancel / PlusExpired
state EntitlementCheck {
[*] --> CheckPlan
CheckPlan --> FreeTier: No active subscription
CheckPlan --> PrismTier: Active Prism
CheckPlan --> PrismPlusTier: Active Prism+
FreeTier --> ApplyLimits: 3 Turns/day, 2 Mirror/week
PrismTier --> FullAccess: Unlimited Turns + Mirror
PrismPlusTier --> FullPlusAccess: Full + Spectrum + Insights
}
```
---
## 9. Data Entity Relationship Model
All database domains showing how Users connect to every feature, commerce, and ops table.
```mermaid
flowchart LR
subgraph Identity["Identity Domain"]
USERS["USERS\nid, email, password_hash"]
PROFILES["PROFILES\nuser_id, display_name\nreframe_style, checkin_time"]
AUTH["AUTH_SESSIONS\nid, user_id, device_info"]
REFRESH["REFRESH_TOKENS\nid, user_id, token_hash"]
end
subgraph Mirror["Mirror Domain"]
M_SESS["MIRROR_SESSIONS\nid, user_id, started_at\nreflection_summary"]
M_MSG["MIRROR_MESSAGES\nid, session_id\ncontent (encrypted)"]
M_FRAG["MIRROR_FRAGMENTS\nid, message_id\ndistortion_type, confidence\nwas_tapped, reframe_text"]
end
subgraph Turn["Turn Domain"]
TURNS["TURNS\nid, user_id, input_text\nreframe_style, reframes\nmicro_action, is_saved"]
end
subgraph Lens["Lens Domain"]
GOALS["LENS_GOALS\nid, user_id, goal_text\nclarity_statement\nbelief_statement"]
ACTIONS["LENS_ACTIONS\nid, goal_id, action_text\nif_then_format, completed"]
end
subgraph Spectrum["Spectrum (Phase 2)"]
S_WEEK["SPECTRUM_WEEKLY\nuser_id, week_start\naggregates, insight"]
S_MONTH["SPECTRUM_MONTHLY\nuser_id, month\ngrowth_trajectory"]
end
subgraph Commerce["Commerce"]
SUBS["SUBSCRIPTIONS\nid, user_id, plan\nstore, status, expires_at"]
end
subgraph Ops["Safety and Ops"]
SAFE["SAFETY_EVENTS\nid, user_id, trigger_text\ndetection_stage"]
AI_USE["AI_USAGE_EVENTS\nid, user_id, feature\nmodel, tokens, cost"]
end
USERS --> PROFILES
USERS --> AUTH
USERS --> REFRESH
USERS --> M_SESS
M_SESS --> M_MSG
M_MSG --> M_FRAG
USERS --> TURNS
USERS --> GOALS
GOALS --> ACTIONS
USERS --> S_WEEK
USERS --> S_MONTH
USERS --> SUBS
USERS --> SAFE
USERS --> AI_USE
```
---
## 10. Deployment Topology & Scaling Path
How the infrastructure evolves from a single EUR 8.45/mo VPS to a multi-node architecture as DAU grows.
```mermaid
flowchart TB
subgraph Phase1["Phase 1: Single VPS — 50 DAU — ~EUR 26/mo"]
P1_CF["Cloudflare (Free)"] --> P1_NGINX["Nginx"]
P1_NGINX --> P1_API["Node.js API + Workers"]
P1_API --> P1_PG["PostgreSQL 16"]
P1_API --> P1_REDIS["Redis"]
P1_API --> P1_AI["Claude Haiku 4.5"]
end
subgraph Phase2["Phase 2: Split DB — 200 DAU — ~EUR 95/mo"]
P2_CF["Cloudflare"] --> P2_NGINX["Nginx"]
P2_NGINX --> P2_API["Node.js API + Workers"]
P2_API --> P2_PG["PostgreSQL (Separate VPS)"]
P2_API --> P2_REDIS["Redis"]
P2_API --> P2_AI["Claude + Groq fallback"]
end
subgraph Phase3["Phase 3: Scale API — 1000 DAU — ~EUR 425/mo"]
P3_CF["Cloudflare"] --> P3_LB["Load Balancer"]
P3_LB --> P3_API1["API Replica 1"]
P3_LB --> P3_API2["API Replica 2"]
P3_API1 --> P3_PG["PostgreSQL (Dedicated)"]
P3_API2 --> P3_PG
P3_API1 --> P3_REDIS["Redis Cluster"]
P3_API2 --> P3_REDIS
P3_WORKER["Spectrum Workers"] --> P3_PG
P3_API1 --> P3_AI["AI Gateway Multi-provider"]
P3_API2 --> P3_AI
end
Phase1 -->|"p95 latency > 120ms\nor storage > 70%"| Phase2
Phase2 -->|"CPU > 70% sustained\nor p95 > SLO"| Phase3
```

View File

@ -0,0 +1,959 @@
# Kalei — Claude Code Build Framework
Version: 2.0
Date: 2026-02-20
Status: Implementation-ready technical framework
Author: Matt + Claude
This document is the operational build bible for constructing Kalei from zero to production using Claude Code as the primary development tool. It translates all existing architecture, design, and phase documents into a practical, session-by-session execution framework.
This is not a summary of what exists. This is the missing piece: how you actually sit down and build it.
---
## 1. How This Framework Works
Every section in this document maps to a concrete Claude Code session. Each session has a clear input (what you tell Claude Code), a clear output (what gets committed), and a definition of done (how you know it worked). You work through them in order. If a session fails validation, you fix it before moving on.
The framework is organized into build tracks that run roughly in sequence but with deliberate parallelism where safe. Each track contains numbered sessions. Each session is designed to be completable in a single focused Claude Code interaction (30-90 minutes of wall time).
### 1.1 Session Anatomy
Every session follows this structure:
1. Context: what Claude Code needs to know before starting.
2. Prompt: what you paste or describe to Claude Code.
3. Deliverables: what files get created or modified.
4. Validation: how you confirm it works.
5. Commit: what the git message should look like.
### 1.2 Working Principles
These rules apply to every session:
- Never skip validation. A session is not done until validation passes.
- Commit after every successful session. Small, clean commits.
- If Claude Code generates something that does not match the architecture docs, the architecture docs win.
- Every AI call goes through the AI gateway. No direct provider SDK imports in feature code. Ever.
- Every user-facing AI path goes through the safety gate first. No exceptions.
- TypeScript strict mode everywhere. No `any` unless explicitly justified.
- Tests are not optional. Every endpoint gets at least one happy-path and one failure-path test.
---
## 2. Toolchain Decisions (Locked)
These are final. Do not revisit during build.
### Backend
| Layer | Tool | Version Target | Why |
|---|---|---|---|
| Language | TypeScript | 5.x strict | Type safety across full stack, shared types |
| Runtime | Node.js | 22 LTS | Current LTS, native fetch, native test runner fallback |
| API framework | Fastify | 5.x | Fastest Node framework, plugin encapsulation model maps perfectly to our modular monolith. Note: v5 prohibits decorating request/reply with reference types — use onRequest hooks or getter decorators instead. |
| ORM / query | Drizzle ORM | Latest stable | Type-safe schemas as code, zero-overhead SQL, migration generation via drizzle-kit. Use prepared statements for hot-path queries (auth lookups, usage checks). |
| Database | PostgreSQL | 16 | JSONB, RLS, pgcrypto, mature ecosystem |
| Cache / counters | Redis | 7.x | Rate limiting, usage counters, session cache, idempotency store |
| AI SDK | @anthropic-ai/sdk | Latest | Native streaming, structured output via `messages.parse()` + `jsonSchemaOutputFormat()`, prompt caching support |
| Password hashing | @node-rs/argon2 | Latest | Argon2id via native Rust binding, fastest safe option |
| JWT | jose | Latest | Standards-compliant, no native deps, supports all JWT operations |
### Mobile
| Layer | Tool | Version Target | Why |
|---|---|---|---|
| Framework | React Native + Expo | SDK 54+ (New Architecture enabled by default) | Fabric renderer + TurboModules = 60fps UI, precompiled iOS builds (10x faster), EAS builds + OTA updates |
| Navigation | Expo Router | v4+ | File-system routing, typed routes, deep linking, shared element transitions |
| Server state | TanStack Query (React Query) | v5 | Industry standard for data fetching in production React Native apps. Provides caching (staleTime/gcTime), background refetching, optimistic mutations, offline persistence via `networkMode: 'offlineFirst'`, and paused mutation resume. Replaces raw HTTP clients as the data layer. |
| Client state | Zustand | Latest | Minimal boilerplate, persist middleware with MMKV adapter for offline-first state |
| Local storage | react-native-mmkv | v4 | 30x faster than AsyncStorage, built-in AES encryption, synchronous reads. Used for auth tokens, user preferences, offline cache. Premium apps universally use MMKV over AsyncStorage. |
| Animations | react-native-reanimated | v4+ | UI-thread animations via shared values + useAnimatedStyle. Spring physics, layout animations, entering/exiting transitions, shared element transitions. Required for premium-feeling interactions. |
| Gestures | react-native-gesture-handler | Latest | Native gesture system — pan, pinch, rotation, tap. Composes with Reanimated for gesture-driven animations (swipe-to-dismiss, pull-to-refresh, card interactions). |
| Haptics | expo-haptics | Latest | Tactile feedback on key interactions: Turn save (success notification), action completion (light impact), fragment tap (selection), onboarding progression (soft impact). Standard in premium wellness apps. |
| Images | expo-image | Latest | Faster than React Native Image, aggressive caching, blurhash placeholders, animated image support. |
| Lists | @shopify/flash-list | Latest | 60fps scrolling for long lists, view recycling, superior to FlatList. Used for Gallery timeline, Turn history, and any scrollable content with 50+ items. |
### Shared / Tooling
| Layer | Tool | Version Target | Why |
|---|---|---|---|
| Validation | Zod | 3.x | Shared schemas between API and mobile, runtime + compile-time safety |
| Linting | Biome | Latest | Single tool for lint + format, faster than ESLint + Prettier combined |
| Unit testing | Vitest | Latest | Vite-powered, native TypeScript, compatible with Fastify test patterns |
| E2E testing | Maestro | Latest | Industry standard for mobile E2E testing. YAML-based flow definitions, visual regression, CI-friendly. Tests critical paths: onboarding, Turn flow, Mirror session, purchase. |
| CI | Gitea Actions (self-hosted, free) or GitHub Actions (2,000 free mins/month private, unlimited public) | N/A | Lint + test + type-check on every PR. Gitea is fully self-hosted on the VPS at zero cost. |
| Monorepo | pnpm workspaces | Native | Strict dependency resolution, disk-efficient, prevents phantom deps |
### 2.1 Package Manager
Use `pnpm` as the package manager. It is faster, more disk-efficient, and has strict dependency resolution that prevents phantom dependencies. Install globally:
```bash
npm install -g pnpm
```
### 2.2 What We Are NOT Using (And Why)
| Rejected | Reason |
|---|---|
| Express | Slower, no schema validation, no encapsulation model |
| Prisma | Heavy runtime, slower queries, migration lock-in |
| Supabase Cloud | 3x cost of self-hosting, unnecessary service overhead |
| RevenueCat | Third-party dependency in billing critical path |
| Redux / MobX | Overkill for this app's state complexity. Zustand + TanStack Query covers both client and server state |
| AsyncStorage | 30x slower than MMKV, no encryption, async-only reads. Not used in premium apps |
| Axios / ky / ofetch | TanStack Query is the data layer now. Raw HTTP clients are only used inside query/mutation functions, not directly in components. Use native fetch inside TanStack Query's queryFn. |
| React Navigation (standalone) | Expo Router wraps React Navigation with file-based routing — no reason to use React Navigation directly |
| Animated (built-in) | React Native's built-in Animated API runs on the JS thread. Reanimated runs on the UI thread — mandatory for 60fps premium animations. |
| Jest | Slower, heavier config, Vitest is drop-in compatible |
| ESLint + Prettier | Two tools where Biome does both faster |
| tRPC | Over-engineering for a mobile + API monorepo with Zod already shared |
| Detox | Slower, more complex setup than Maestro for E2E testing. Maestro's YAML flows are faster to write and maintain |
### 2.3 Zero-Cost Development Guarantee
Every tool and dependency in this stack can be used at zero cost during development. This section maps each component to its free path.
**All npm packages are free and open source.** Every library in the Backend, Mobile, and Shared toolchain tables is MIT, Apache 2.0, or BSD licensed. This includes Fastify, Drizzle ORM, TanStack Query, Zustand, MMKV, Reanimated, FlashList, Zod, Biome, Vitest, Pino, jose, @node-rs/argon2, and ioredis. Zero license costs, ever.
**Local infrastructure is free.** PostgreSQL and Redis run locally via Docker Compose (Docker Engine is free and open source). No cloud database or managed Redis required during development.
**Mobile builds are free locally.** Use `npx expo run:ios` and `npx expo run:android` for development builds — these compile using your local Xcode and Android Studio (both free). For production builds, use `eas build --local --platform ios` and `eas build --local --platform android` to build .ipa and .aab files on your machine at zero cost. EAS Cloud Build's free tier (30 builds/month) is available but optional. OTA updates via EAS Update are free for up to 1,000 active users.
**AI API costs are zero during development.** The mock AI provider (`mock.provider.ts`) returns deterministic, schema-valid responses for all unit and integration tests. You never hit real AI APIs during normal development. For manual testing against real AI, use the initial free credits that come with new Anthropic accounts ($5-10), plus Venice.ai's free tier for the fallback provider. Google Cloud Vertex AI offers $300 in free credits for new accounts (Claude models are available there). During development, you will spend $0 on AI.
**Testing is free.** Vitest (MIT) for unit/integration tests. Maestro CLI (Apache 2.0) runs locally against simulators/emulators at no cost — do not use Maestro Cloud. k6 (Apache 2.0) for load testing runs locally.
**Error tracking is free.** GlitchTip is self-hosted via Docker Compose on your dev machine (or later on the VPS). It is Sentry-compatible and 100% open source. No SaaS subscription needed.
**Analytics is free.** PostHog can be self-hosted via Docker for up to ~100k events/month, or use their cloud free tier (1M events/month, no credit card required). For development, self-hosted PostHog in Docker Compose alongside Postgres and Redis costs nothing.
**Push notifications are free.** Expo Push Notification API is free with a 600 notifications/second/project rate limit. No paid tier required.
**CI/CD is free.** Gitea Actions is self-hosted and free. GitHub Actions offers 2,000 minutes/month free for private repos, unlimited for public repos.
**SSL/HTTPS is free.** Caddy auto-provisions Let's Encrypt certificates. Let's Encrypt is a free certificate authority.
**Costs that only apply at launch (not during development):**
| Item | Cost | When |
|---|---|---|
| Netcup VPS 1000 G12 | €8.45/month | Production deployment |
| Apple Developer Program | $99/year | App Store submission |
| Google Play Developer | $25 one-time | Play Store submission |
| Anthropic API (production traffic) | ~$15-30/month at launch scale | Live users hitting AI endpoints |
| Domain name | ~$10-15/year | Production domain |
Total development cost: **$0.** Total launch cost: approximately **€30/month** + one-time store fees.
---
## 3. Repository Architecture
This is the exact folder structure. Claude Code should scaffold this in the first session.
```
kalei/
package.json # Workspace root
pnpm-workspace.yaml # Workspace config
tsconfig.base.json # Shared TS config
biome.json # Lint + format config
.env.example # Root env template
.gitignore
apps/
mobile/ # Expo React Native app
app/ # Expo Router file-based routes
(tabs)/ # Tab navigator group
_layout.tsx # Tab layout with 5 tabs
index.tsx # Home / daily focus
mirror.tsx # Mirror entry
turn.tsx # Kaleidoscope entry
lens.tsx # Lens goals
gallery.tsx # Gallery / history
(auth)/ # Auth flow group
_layout.tsx
login.tsx
register.tsx
onboarding.tsx
(spectrum)/ # Spectrum (Phase 4)
_layout.tsx
dashboard.tsx
weekly.tsx
monthly.tsx
_layout.tsx # Root layout (auth gate)
src/
api/ # API layer
client.ts # Base fetch wrapper with auth header injection
query-client.ts # TanStack Query client config (staleTime, gcTime, offline persistence)
queries/ # TanStack Query hooks organized by feature
use-auth.ts # useLogin, useRegister, useRefresh mutations
use-mirror.ts # useMirrorSession, useSendMessage, useReframe queries/mutations
use-turn.ts # useCreateTurn, useTurns, useSaveTurn
use-lens.ts # useGoals, useCreateGoal, useCompleteAction, useDailyAffirmation
use-spectrum.ts # useWeeklyInsight, useMonthlyInsight
use-billing.ts # useEntitlements
keys.ts # Query key factory for organized cache invalidation
stores/ # Zustand stores (client state only — NOT server state)
auth.store.ts # Token state, persisted to MMKV
ui.store.ts # UI preferences, theme mode, onboarding state
offline-queue.store.ts # Queued mutations for offline-first
lib/ # Core utilities
storage.ts # MMKV instance setup with encryption
haptics.ts # Centralized haptic feedback helpers (tapHaptic, successHaptic, etc.)
analytics.ts # PostHog event tracking (self-hosted or cloud free tier — 1M events/month free)
components/ # Reusable UI components
ui/ # Primitives (Button, Card, Input, TextArea, etc.)
animations/ # Reanimated animation components (FadeIn, SlideUp, PulseGlow, KaleidoscopeSpinner)
mirror/ # Mirror-specific components
turn/ # Turn-specific components
lens/ # Lens-specific components
spectrum/ # Spectrum-specific components
hooks/ # Custom React hooks
use-keyboard-aware.ts # Keyboard avoidance for writing screens
use-network-state.ts # Online/offline detection
use-app-state.ts # Foreground/background lifecycle
utils/ # Helpers, formatters, constants
theme/ # Colors, typography, spacing tokens, dark mode support
types/ # Mobile-specific types
assets/ # Images, fonts, Lottie animations
e2e/ # Maestro E2E test flows
onboarding.yaml
turn-flow.yaml
mirror-session.yaml
purchase-flow.yaml
app.config.ts # Expo config (newArchEnabled: true is default in SDK 54)
package.json
tsconfig.json
.env.example
services/
api/ # Fastify API server
src/
server.ts # Fastify app factory
config.ts # Environment config with Zod validation
modules/ # Feature modules (Fastify plugins)
auth/
auth.routes.ts
auth.service.ts
auth.schemas.ts
auth.test.ts
mirror/
mirror.routes.ts
mirror.service.ts
mirror.schemas.ts
mirror.test.ts
turn/
turn.routes.ts
turn.service.ts
turn.schemas.ts
turn.test.ts
lens/
lens.routes.ts
lens.service.ts
lens.schemas.ts
lens.test.ts
spectrum/
spectrum.routes.ts
spectrum.service.ts
spectrum.schemas.ts
spectrum.test.ts
billing/
billing.routes.ts
billing.service.ts
billing.schemas.ts
billing.test.ts
plugins/ # Cross-cutting Fastify plugins
auth.plugin.ts # JWT verification decorator
entitlement.plugin.ts # Plan gating middleware
rate-limit.plugin.ts # Redis-backed rate limiting
request-id.plugin.ts # Request ID injection
error-handler.plugin.ts
gateway/ # AI Gateway abstraction
ai-gateway.ts # Main gateway interface
providers/
anthropic.provider.ts
openai-compatible.provider.ts # Venice/Groq/OpenRouter
prompts/
mirror-detect.prompt.ts
mirror-reframe.prompt.ts
turn-reframe.prompt.ts
lens-affirmation.prompt.ts
spectrum-weekly.prompt.ts
spectrum-monthly.prompt.ts
output-schemas/ # Zod schemas for AI output validation
mirror-fragments.schema.ts
turn-perspectives.schema.ts
lens-output.schema.ts
safety/ # Safety service
safety.service.ts # Multi-stage crisis filter
crisis-keywords.ts # Deterministic keyword sets
crisis-resources.ts # Regional crisis hotline data
safety.test.ts
db/ # Database layer
client.ts # Drizzle client setup
schema/ # Drizzle schema definitions
users.ts
auth.ts
mirror.ts
turn.ts
lens.ts
spectrum.ts
billing.ts
safety.ts
usage.ts
index.ts # Re-exports all schemas
migrations/ # Generated by drizzle-kit
seed.ts # Dev seed data
redis/
client.ts # Redis connection
usage-counter.ts # Per-user usage tracking
rate-limiter.ts # Sliding window rate limiter
idempotency.ts # Idempotency key store
workers/ # Background job processors
spectrum-weekly.worker.ts
spectrum-monthly.worker.ts
push-notification.worker.ts
billing-reconciliation.worker.ts
utils/
logger.ts # Pino structured logger
crypto.ts # Column-level encryption helpers
errors.ts # Custom error classes
drizzle.config.ts # Drizzle Kit configuration
package.json
tsconfig.json
vitest.config.ts
.env.example
packages/
shared/ # Shared types and schemas
src/
schemas/ # Zod schemas shared between API and mobile
auth.schema.ts
mirror.schema.ts
turn.schema.ts
lens.schema.ts
spectrum.schema.ts
billing.schema.ts
types/ # TypeScript type exports
index.ts
constants/ # Shared constants
plans.ts # Plan definitions and limits
cognitive-distortions.ts # Fragment type taxonomy
crisis-patterns.ts # Shared crisis detection patterns
package.json
tsconfig.json
infra/
docker/
docker-compose.yml # Postgres + Redis for local dev
docker-compose.prod.yml # Production compose (VPS deployment)
scripts/
setup-local.sh # One-command local environment setup
deploy.sh # Production deployment script
backup-db.sh # PostgreSQL backup script
restore-db.sh # PostgreSQL restore script
nginx/
kalei.conf # Nginx reverse proxy config
caddy/
Caddyfile # Alternative: Caddy auto-HTTPS config
docs/ # Existing documentation (unchanged)
```
### 3.1 Why This Structure
**Backend: Fastify plugin encapsulation.** Each module in `services/api/src/modules/` is a self-contained Fastify plugin that registers its own routes, schemas, and services. Fastify v5 enforces this cleanly — you cannot decorate request/reply with reference types directly (use onRequest hooks or getter decorators instead). Each module can be tested in isolation, and extraction to a separate service later is a matter of moving the plugin to its own process.
**Mobile: Separation of server state and client state.** This is the pattern every premium React Native app follows in 2026. TanStack Query owns all server state (API data, caching, background refetching, optimistic updates). Zustand owns only client state (auth tokens, UI preferences, offline queue). Components never call fetch directly — they use query hooks from `src/api/queries/`. This separation makes offline-first behavior trivial: TanStack Query's `networkMode: 'offlineFirst'` plus MMKV-backed Zustand persistence means the app works without network.
**Shared schemas.** The `packages/shared` workspace ensures that Zod schemas defined once are used identically for API request validation, TanStack Query response typing, and mobile form validation. When the API says a turn response has exactly 3 perspectives, the mobile app knows this at compile time.
**AI gateway isolation.** The `gateway/` directory is intentionally separate from `modules/`. Feature code calls the gateway; the gateway calls providers. Feature code never imports provider SDKs. This is the single most important architectural boundary in the entire codebase.
### 3.2 Premium UX Architecture Principles
These patterns separate a forgettable app from a premium one:
**60fps everywhere.** All animations run on the UI thread via Reanimated shared values. Never animate with React state or the built-in Animated API. Screen transitions use Reanimated's layout animations (FadeIn, SlideInRight). The Turn kaleidoscope animation uses withRepeat + withSpring for organic-feeling motion.
**Haptic vocabulary.** Define a consistent haptic language: `Haptics.selectionAsync()` for tapping fragments, `Haptics.impactAsync(Light)` for completing actions, `Haptics.notificationAsync(Success)` for saving turns, `Haptics.impactAsync(Soft)` for onboarding progression. Centralize in `src/lib/haptics.ts` so the haptic vocabulary stays consistent.
**Offline-first by default.** Every screen must work without network. MMKV persists Zustand state synchronously. TanStack Query caches API responses with configurable stale times. Mutations queue locally and resume when connectivity returns (via `resumePausedMutations()`). The Mirror writing experience must never be interrupted by network issues.
**Optimistic UI.** When the user saves a Turn, the UI updates immediately via TanStack Query's optimistic mutation pattern — the save icon fills instantly, and the server sync happens in the background. If it fails, it rolls back. The user never waits.
**Image optimization.** Use `expo-image` with blurhash placeholders for any loaded images. Profile avatars, onboarding illustrations, and Spectrum chart images all load with a color-blur placeholder that resolves to the full image.
**Accessibility from day one.** All interactive elements have accessibility labels. The Mirror writing area supports dynamic type sizes. Color contrast meets WCAG AA. VoiceOver/TalkBack navigation works for all core flows.
---
## 4. Build Track A — Foundation (Phase 0)
Duration: 3-5 days
Goal: Everything runs. Nothing is broken. You can develop features.
### Session A1: Repository Scaffold
Context: Starting from empty repo.
Prompt to Claude Code:
> Initialize a pnpm monorepo with three workspaces: apps/mobile, services/api, and packages/shared. Set up tsconfig.base.json with strict mode. Add biome.json with reasonable defaults. Add .gitignore covering node_modules, .env, dist, .expo, and drizzle migration artifacts. Create package.json files for each workspace. The API workspace should use Fastify 5, Drizzle ORM with postgres-js driver, zod, pino, ioredis, jose, and @node-rs/argon2. The mobile workspace should use Expo SDK 54 with expo-router, and these critical dependencies: @tanstack/react-query for server state, zustand for client state, react-native-mmkv v4 for encrypted local storage (use createMMKV API), react-native-reanimated v4 for UI-thread animations, react-native-gesture-handler for native gestures, expo-haptics for tactile feedback, expo-image for optimized image loading, and zod for shared validation. The shared workspace should export Zod schemas and TypeScript types. Add a pnpm-workspace.yaml. Make the whole thing build and type-check cleanly.
Deliverables:
- All package.json files with correct dependencies
- tsconfig files with project references
- biome.json
- pnpm-workspace.yaml
- Clean `pnpm install` and `pnpm -r run type-check`
Validation:
```bash
pnpm install
pnpm -r run type-check # Zero errors
pnpm biome check . # Zero errors
```
### Session A2: Docker Infrastructure
Context: Repo scaffold exists.
Prompt to Claude Code:
> Create infra/docker/docker-compose.yml with PostgreSQL 16 and Redis 7. Postgres should use kalei/kalei credentials with a kalei database. Add health checks for both services. Create a root-level Makefile with targets: up (start docker), down (stop docker), reset-db (drop and recreate), and logs. Also create .env.example files for both API and mobile workspaces with all expected environment variables documented with comments.
Deliverables:
- docker-compose.yml with health checks
- Makefile
- .env.example files
Validation:
```bash
make up
docker compose -f infra/docker/docker-compose.yml ps # Both healthy
make down
```
### Session A3: API Server Skeleton
Context: Docker running, dependencies installed.
Prompt to Claude Code:
> Create the Fastify server factory in services/api/src/server.ts. It should: load config from environment using Zod validation (src/config.ts), register CORS, helmet, and sensible plugins, add a request ID plugin that generates UUIDs and injects them into pino logs, add a global error handler that logs errors and returns structured JSON errors, register a GET /health endpoint that checks Postgres and Redis connectivity and returns status/uptime/version. Add the database client (src/db/client.ts) using Drizzle ORM with postgres-js as the driver. Add the Redis client (src/redis/client.ts) using ioredis with reconnection strategy. Wire it all up in an index.ts that starts the server. Use Fastify's plugin encapsulation model — each capability should be a registered plugin.
Deliverables:
- server.ts (app factory)
- config.ts (Zod-validated env)
- db/client.ts (Drizzle + postgres-js)
- redis/client.ts (ioredis)
- plugins/request-id.plugin.ts
- plugins/error-handler.plugin.ts
- Health endpoint returning JSON
Validation:
```bash
make up
cd services/api && pnpm dev
curl http://localhost:8080/health # Returns JSON with status: ok
```
### Session A4: Mobile App Skeleton
Context: API server running.
Prompt to Claude Code:
> Create the Expo app in apps/mobile using Expo Router with file-based routing and the New Architecture (enabled by default in SDK 54). Set up the root layout (_layout.tsx) with: a TanStack Query provider (QueryClientProvider with defaults: staleTime 5 minutes, gcTime 10 minutes, networkMode offlineFirst), a GestureHandlerRootView wrapper, and an auth gate that checks for a stored token in MMKV. Set up MMKV storage in src/lib/storage.ts using createMMKV with encryption enabled. Set up the TanStack Query client in src/api/query-client.ts. Create a Zustand auth store in src/stores/auth.store.ts that persists tokens to MMKV (using zustand/middleware persist with a custom MMKV storage adapter). Create the (auth) group with login and register screens (just UI shells with Reanimated FadeIn entering animations). Create the (tabs) group with 5 tabs: Home, Mirror, Turn, Lens, Gallery. Each tab should show its name and a placeholder with a subtle FadeIn.duration(300) entering animation. Set up the theme directory with Kalei's color tokens (primary deep teal #1A3A3A, accent amber #D4A574, background warm off-white #FAF8F5, text near-black #1A1A1A) and typography scale. Create a TanStack Query hook in src/api/queries/use-health.ts that fetches /health. Create src/lib/haptics.ts with centralized haptic helpers (tapHaptic, successHaptic, errorHaptic, selectionHaptic) wrapping expo-haptics. Display the health status on the Home tab using the useHealth query hook.
Deliverables:
- Expo Router file structure with all route groups
- Root layout with TanStack Query provider, GestureHandlerRootView, auth gate
- MMKV storage setup with encryption
- TanStack Query client with offline-first defaults
- Zustand auth store persisted to MMKV
- Haptics helper library
- 5 tab screens with Reanimated entering animations
- Theme tokens and typography scale
- useHealth query hook calling /health
- Query key factory in src/api/queries/keys.ts
Validation:
```bash
cd apps/mobile && npx expo start
# Open on device (not Expo Go — need dev build for MMKV/Reanimated native modules)
# See tabs with fade-in animations, see health status from API
# Kill app and reopen — auth state persists from MMKV
```
### Session A5: Database Schema v1
Context: API server and Drizzle client working.
Prompt to Claude Code:
> Create the full Phase 1 database schema using Drizzle ORM for PostgreSQL. Define all tables in separate files under services/api/src/db/schema/. Tables needed: users (id uuid, email, password_hash, display_name, role, created_at, updated_at), profiles (user_id FK, onboarding_complete, timezone, preferred_reframe_style, created_at, updated_at), auth_sessions (id uuid, user_id FK, device_info jsonb, ip_address, created_at, expires_at), refresh_tokens (id uuid, user_id FK, token_hash, session_id FK, created_at, expires_at, revoked_at), subscriptions (id uuid, user_id FK, plan enum free/prism/prism_plus, store enum apple/google, store_subscription_id, status enum, current_period_start, current_period_end, created_at, updated_at), entitlement_snapshots (id uuid, user_id FK, plan, features jsonb, valid_from, valid_until), turns (id uuid, user_id FK, input_text encrypted, perspectives jsonb, micro_action text, reframe_style, saved boolean, created_at), mirror_sessions (id uuid, user_id FK, status enum, started_at, ended_at, reflection_text), mirror_messages (id uuid, session_id FK, user_id FK, content encrypted, sequence_number, created_at), mirror_fragments (id uuid, message_id FK, user_id FK, fragment_type, start_offset, end_offset, confidence, reframe_text, created_at), lens_goals (id uuid, user_id FK, title, description, status, created_at, updated_at), lens_actions (id uuid, goal_id FK, user_id FK, title, completed boolean, completed_at, due_date, created_at), ai_usage_events (id uuid, user_id FK, feature, model, provider, input_tokens, output_tokens, cost_usd, latency_ms, created_at), safety_events (id uuid, user_id FK, trigger_type, trigger_content_hash, action_taken, created_at). Use proper indexes on user_id and created_at for all tables. Use Drizzle relations for type-safe joins. Create an index.ts that re-exports everything. Then configure drizzle.config.ts and generate the initial migration with drizzle-kit generate.
Deliverables:
- Schema files for all tables
- Drizzle relations defined
- drizzle.config.ts
- Generated SQL migration
- Clean migration apply
Validation:
```bash
cd services/api
pnpm drizzle-kit generate # Generates migration SQL
pnpm drizzle-kit migrate # Applies to local Postgres
pnpm drizzle-kit studio # Opens Drizzle Studio, verify all tables exist
```
### Session A6: Shared Schemas and Quality Gates
Context: Schema exists, both apps scaffold complete.
Prompt to Claude Code:
> Create the shared Zod schemas in packages/shared/src/schemas/ for all API request/response contracts. Auth schemas: RegisterInput, LoginInput, TokenResponse, ProfileResponse. Mirror schemas: CreateSessionInput, SendMessageInput, FragmentResponse, ReframeResponse, ReflectionResponse. Turn schemas: CreateTurnInput (input_text, reframe_style enum), TurnResponse (3 perspectives array + micro_action). Lens schemas: CreateGoalInput, GoalResponse, CreateActionInput, DailyAffirmationResponse. Also create packages/shared/src/constants/plans.ts with plan definitions including feature limits (free: 3 turns/day, 2 mirror/week; prism: unlimited; prism_plus: unlimited + spectrum). Add packages/shared/src/constants/cognitive-distortions.ts with the 10 cognitive distortion types used for fragment detection. Then set up Vitest config for the API workspace with a test that imports the shared schemas. Set up Biome and add scripts to root package.json: lint, format, test, type-check, e2e (runs `maestro test apps/mobile/e2e/`). Add a CI-ready check script that runs lint + format + type-check + test (unit/integration). E2E tests via Maestro run separately in the release pipeline since they require a running device/emulator.
Deliverables:
- All shared Zod schemas
- Plan constants with limits
- Cognitive distortion taxonomy
- Vitest configuration
- Root-level quality scripts
- At least one passing test
Validation:
```bash
pnpm run check # Runs lint + format + type-check + test — all pass
```
---
## 5. Build Track B — Platform Core (Phase 1)
Duration: 2-3 weeks
Goal: Auth, entitlements, AI gateway, safety, and rate limiting are production-grade.
### Session B1: Auth — Registration and Login
Prompt to Claude Code:
> Implement the auth module in services/api/src/modules/auth/. Create auth.routes.ts as a Fastify plugin that registers POST /auth/register and POST /auth/login. Registration should: validate input with shared Zod schema, check email uniqueness, hash password with Argon2id, create user + profile, generate JWT access token (15 min TTL) and refresh token (7 day TTL), store refresh token hash in DB, return both tokens. Login should: validate credentials, verify password, create new session with device info from user-agent, generate token pair, return tokens. Use jose for JWT signing with RS256 or HS256 based on config. Create auth.service.ts for business logic and use Drizzle for data access. Add auth.schemas.ts importing from shared schemas. Write tests for: successful registration, duplicate email rejection, successful login, wrong password rejection.
### Session B2: Auth — Token Refresh and Sessions
Prompt to Claude Code:
> Add POST /auth/refresh and POST /auth/logout to the auth module. Refresh should: accept refresh token, verify it exists and is not expired or revoked, rotate it (revoke old, issue new pair), return new tokens. This implements refresh token rotation — if a revoked token is reused, revoke ALL tokens for that user (compromise detection). Logout should: revoke the current refresh token and mark the session as ended. Add GET /me that returns the current user profile. Add PATCH /me/profile for updating display_name, timezone, and preferred_reframe_style. Create the auth.plugin.ts in plugins/ that adds a Fastify decorator `authenticate` — a preHandler hook that verifies the JWT access token, extracts user ID, and decorates the request with `request.user`. Test: full token lifecycle (register, use access token, refresh, use new token, logout, verify old refresh fails).
### Session B3: Entitlement and Plan Gating
Prompt to Claude Code:
> Implement the entitlement system. Create plugins/entitlement.plugin.ts as a Fastify plugin that adds a `requirePlan` decorator. This decorator takes a minimum plan level and returns a preHandler that: loads the user's current entitlement snapshot, checks if their plan meets the minimum, returns 403 with a clear upgrade message if not. Also implement feature-specific gates: a `checkTurnLimit` preHandler that reads today's turn count from Redis and enforces the daily cap for free users (3/day), and a `checkMirrorLimit` preHandler that reads this week's mirror session count and enforces the weekly cap for free users (2/week). Create billing.routes.ts with webhook endpoints for Apple and Google (POST /billing/webhooks/apple and /billing/webhooks/google) — these should parse notification payloads, update subscriptions table, and write new entitlement snapshots. For now, implement the webhook signature verification as a placeholder. Add GET /billing/entitlements that returns the user's current plan and feature limits with usage counts. Test: free user hitting turn limit, prism user bypassing limit, entitlement check after plan change.
### Session B4: AI Gateway — Core Abstraction
Prompt to Claude Code:
> Build the AI gateway in services/api/src/gateway/. Create ai-gateway.ts with a TypeScript interface: AIGateway with methods `generate(request: AIRequest): Promise<AIResponse>` and `stream(request: AIRequest): AsyncGenerator<AIChunk>`. The AIRequest type should include: feature (mirror_detect | mirror_reframe | turn_reframe | lens_affirmation | spectrum_weekly | spectrum_monthly), messages array, model override (optional), temperature, max_tokens, output_schema (Zod schema for structured output validation). Create providers/anthropic.provider.ts that implements this interface using @anthropic-ai/sdk. It should: use prompt caching by marking system message content blocks with `cache_control: { type: "ephemeral" }` (this tells Anthropic to cache the system prompt — subsequent calls within a 5-minute window pay only 10% of base input rate, saving 40-50% on input costs), support streaming via the SDK's stream method, extract token usage from response metadata, validate output against the provided Zod schema and retry once on validation failure. Create providers/openai-compatible.provider.ts as the Venice/Groq/OpenRouter adapter using the OpenAI-compatible API format. The gateway factory should read config to determine which provider to use per feature, with fallback chains. Log every call to ai_usage_events with feature, model, provider, token counts, cost estimate, and latency. Test: mock provider returns valid structured output, mock provider returns invalid output and retry succeeds, token usage logging works.
### Session B5: AI Gateway — Prompt Templates
Prompt to Claude Code:
> Create all prompt templates in services/api/src/gateway/prompts/. Each template exports a function that takes context and returns the messages array for the AI gateway. Mirror fragment detection (mirror-detect.prompt.ts): system prompt instructs the model to analyze freeform writing and identify cognitive distortions from our taxonomy (all-or-nothing, catastrophizing, emotional reasoning, fortune telling, labeling, magnification, mental filtering, mind reading, overgeneralization, should statements). Output must be a JSON array of fragments with: type, start_offset, end_offset, confidence (0-1), and a brief explanation. Mirror inline reframe (mirror-reframe.prompt.ts): takes the original text and a specific fragment, generates a gentle compassionate reframe (2-3 sentences). Turn reframe (turn-reframe.prompt.ts): system prompt generates exactly 3 perspective reframes (compassionate, rational, growth-oriented) plus one micro-action as an if-then implementation intention. Output is strictly structured JSON. Lens affirmation (lens-affirmation.prompt.ts): takes user's active goals and generates a personalized daily affirmation. Create corresponding output validation schemas in output-schemas/ using Zod. Each prompt template should include a version string (e.g., "mirror-detect-v1") for tracking prompt revisions. Test: each template produces valid messages arrays, output schemas validate correct and reject incorrect shapes.
### Session B6: Safety Service
Prompt to Claude Code:
> Build the safety service in services/api/src/safety/. Create crisis-keywords.ts with deterministic keyword and phrase sets for crisis detection: explicit self-harm language, suicidal ideation phrases, immediate danger phrases, and severe distress indicators. These must be comprehensive but avoid false positives on common expressions. Create safety.service.ts with a multi-stage crisis filter: Stage 1 is deterministic keyword/regex matching (instant, no AI call). If Stage 1 flags, immediately return crisis response — no further processing. Stage 2 (optional, for ambiguous cases): send flagged text to AI gateway for confirmation with a safety-specific prompt that returns a confidence score. If confirmed, return crisis response. Create crisis-resources.ts with structured data for crisis hotlines by region (start with US: 988 Suicide and Crisis Lifeline, Crisis Text Line). The crisis response payload should include: is_crisis boolean, resources array with name/phone/text/url per resource, a compassionate message, and explicit instruction that the content was NOT reframed. Wire the safety service as a preHandler on all AI-facing routes (mirror messages, turn creation, lens if accepting user input). Log every safety event to safety_events table. Test: known crisis phrases trigger immediate response, safe text passes through, ambiguous text reaches Stage 2, crisis response never contains reframed content.
### Session B7: Rate Limiting and Usage Metering
Prompt to Claude Code:
> Build Redis-backed rate limiting and usage tracking. Create redis/rate-limiter.ts implementing a sliding window rate limiter. It should support: per-IP rate limiting (general API protection, 100 req/min), per-user rate limiting (feature-specific, configurable), and burst allowance. Create redis/usage-counter.ts for tracking: daily turn count per user, weekly mirror session count per user, monthly token usage per user. Create redis/idempotency.ts that stores idempotency keys with TTL — if a request includes an X-Idempotency-Key header and we've seen it before, return the cached response. Create plugins/rate-limit.plugin.ts that registers the general rate limiter on all routes and exposes decorators for feature-specific limits. Create a usage cost tracking function that estimates USD cost from token counts based on current model pricing (configurable). Add middleware that records every AI-backed request to ai_usage_events. Test: rate limit kicks in at threshold, idempotency key returns cached response, usage counters increment correctly.
### Session B8: Push Notification Infrastructure
Prompt to Claude Code:
> Set up push notification infrastructure. Install expo-notifications in the mobile app and configure it to request permissions and register for push tokens on login. Create a notification service in the API (services/api/src/modules/notifications/) that: stores device push tokens per user session, sends push notifications via Expo Push API (which handles both APNs and FCM routing), supports notification types: daily_affirmation_reminder, mirror_nudge, weekly_spectrum_ready, turn_streak_reminder. Create a notification preferences table in the schema so users can toggle notification types on/off. Create a worker (workers/push-notification.worker.ts) that runs scheduled notifications: daily affirmation reminder at user's preferred time (default 8am local), weekly spectrum summary notification on Monday morning. For development, log notifications to console instead of sending. Test: push token registration, notification send via Expo Push API, user preference toggle, scheduled notification timing.
### Session B9: Observability Baseline
Prompt to Claude Code:
> Set up structured logging and error tracking. Configure Pino logger in utils/logger.ts with: JSON output in production, pretty output in development, request ID correlation, user ID hash (never log raw user ID), redaction of sensitive fields (authorization headers, passwords, tokens). Create a Fastify hook that logs request start (method, url, request_id) and response end (status, duration_ms, request_id). Add GlitchTip integration for error tracking — GlitchTip is free and open source, self-hosted via Docker Compose alongside our existing Postgres and Redis (add it to docker-compose.yml). Install @sentry/node (GlitchTip is Sentry-compatible, same SDK) and create an initialization plugin that points to the local GlitchTip instance. For development, GlitchTip runs on your machine; in production, it runs on the VPS. Zero SaaS cost. Create a /metrics endpoint that returns: request count by endpoint, error count by endpoint, AI token usage by feature (daily/monthly), AI cost by feature, active sessions count, rate limit denial count. For now this can be a simple JSON endpoint — we'll add Prometheus format later if needed. Test: verify request logs contain request_id, verify error tracking captures unhandled errors, verify metrics endpoint returns non-zero data after some requests.
---
## 6. Build Track C — Core Experience (Phase 2)
Duration: 3-5 weeks
Goal: Users can complete the Mirror to Turn to Lens flow end-to-end.
### Session C1: Mirror — Session Lifecycle API
Prompt to Claude Code:
> Implement the Mirror module backend. POST /mirror/sessions creates a new session (status: active). POST /mirror/messages accepts message content, runs it through the safety gate, then through the AI gateway for fragment detection. The response includes the original message with an array of detected fragments (type, offsets, confidence). Each fragment above the confidence threshold (0.7) is stored in mirror_fragments. POST /mirror/fragments/:id/reframe triggers an inline reframe for a specific fragment — calls AI gateway with the original context and fragment, returns the reframed perspective. POST /mirror/sessions/:id/close ends the session and triggers a reflection generation — the AI summarizes the session's themes, patterns noticed, and a gentle closing thought. GET /mirror/sessions lists sessions with pagination. DELETE /mirror/sessions/:id soft-deletes a session. All endpoints enforce authentication, safety precheck, and entitlement limits. The message content should be encrypted at rest using the column-level encryption helper. Test: full session lifecycle, fragment detection returns valid offsets, reframe returns compassionate text, reflection summarizes themes, safety gate blocks crisis content.
### Session C2: Mirror — Mobile UI
Prompt to Claude Code:
> Build the Mirror screen in the mobile app as a premium writing experience. The compose UI should feel like a peaceful writing space — warm off-white background (#FAF8F5), gentle typography (system serif or Inter at 18px), generous padding, no distracting UI elements. Use keyboard-aware scrolling so the text input stays visible above the keyboard. As the user types and pauses (debounce 2 seconds after last keystroke), use a TanStack Query mutation (useSendMessage from src/api/queries/use-mirror.ts) to send content to the API for fragment detection. When fragments come back, render subtle highlights on the detected text — use a warm amber (#D4A574) underline with a Reanimated FadeIn.duration(400) animation, not aggressive red highlighting. Add Haptics.selectionAsync() when the user taps a highlighted fragment. Show a bottom sheet card (animated with Reanimated SlideInDown.springify()) with the fragment type name (e.g., "Catastrophizing"), a brief explanation, and a "See another perspective" button that triggers the reframe mutation. The reframe slides in as an animated card with FadeInUp. When the user closes the session, show the Reflection as a full-screen gentle summary with Reanimated FadeIn. All API calls should go through TanStack Query hooks — useMirrorSession, useSendMessage, useReframe, useCloseSession. Configure the useSendMessage mutation with optimistic updates so fragment highlights appear immediately from cached data while the server processes. Handle offline gracefully using TanStack Query's offline mutation persistence — queue messages locally in the mutation cache and resume when connectivity returns via resumePausedMutations.
### Session C3: Turn — Reframe Engine API
Prompt to Claude Code:
> Implement the Turn module backend. POST /turns accepts input_text and optional reframe_style (compassionate, rational, growth, or all). Runs safety precheck. Calls AI gateway with the turn-reframe prompt. Returns exactly 3 perspectives, each with: style label, reframed text (2-3 sentences), and a brief explanation of the cognitive shift. Also returns one micro_action as an if-then implementation intention (e.g., "If I notice myself catastrophizing about work, then I will take 3 breaths and name one thing I can control"). POST /turns/:id/save toggles the saved state. GET /turns returns paginated history. GET /turns/:id returns a single turn with full details. Support streaming for the reframe generation — the API should use Server-Sent Events so the mobile app can show perspectives appearing in real-time. Enforce daily turn limits for free users. Test: valid turn creates 3 perspectives, streaming delivers chunks, save toggle works, daily limit enforced, crisis content blocked.
### Session C4: Turn — Mobile UI
Prompt to Claude Code:
> Build the Turn (Kaleidoscope) screen as the premium signature experience. The input should be a focused single-purpose screen: a large text input with placeholder "What thought is weighing on you?" and a "Turn" button that pulses gently using Reanimated withRepeat(withTiming()) when the input has text. Add Haptics.impactAsync(Medium) when the Turn button is pressed. When processing, show a kaleidoscope animation built with Reanimated — rotate a geometric SVG pattern using useSharedValue + withRepeat(withSpring()) for organic, non-mechanical motion. This is the core product moment and must feel magical. As perspectives stream in via SSE, render them as cards that appear one at a time using Reanimated's layout animation FadeInDown.springify().delay(index * 200) — each card shows the perspective style icon, the reframed text, and the cognitive shift explanation. The micro-action appears last with a distinct card style and FadeInUp animation. The save button (bookmark icon) should use Reanimated withSpring for a satisfying scale bounce on tap, with Haptics.notificationAsync(Success) feedback. Use TanStack Query for all data: useCreateTurn mutation (with streaming SSE handling), useTurns query for history, useSaveTurn mutation with optimistic update (the save icon fills immediately, server syncs in background — rollback on failure). The Gallery tab should show saved turns in a timeline view using FlashList for performant scrolling. Implement pull-to-refresh with Reanimated-powered custom refresh indicator. All loading states must use skeleton placeholders with a Reanimated shimmer effect, never a spinner.
### Session C5: Lens — Goals and Actions API
Prompt to Claude Code:
> Implement the Lens module backend. POST /lens/goals creates a goal with title and optional description. GET /lens/goals returns active goals. PATCH /lens/goals/:id updates goal status. POST /lens/goals/:id/actions creates an action item. POST /lens/actions/:id/complete marks it done with timestamp. GET /lens/affirmation/today generates or returns cached daily affirmation — it calls the AI gateway with the user's active goals as context and generates a personalized affirmation. Cache the affirmation in Redis with a TTL that expires at midnight in the user's timezone. If the AI budget is constrained, fall back to a template-based affirmation system using pre-written affirmations matched to goal themes. Test: goal CRUD, action completion, affirmation generation, affirmation caching, template fallback.
### Session C6: Lens — Mobile UI
Prompt to Claude Code:
> Build the Lens screen as a calm, empowering daily direction hub. Top section shows the daily affirmation in a prominent card with gentle serif typography and a Reanimated FadeIn.delay(200).duration(600) entering animation — this card should feel like the first thing you notice. Use TanStack Query's useDailyAffirmation hook (from src/api/queries/use-lens.ts) with staleTime set to Infinity (the affirmation is cached for the full day). Below the affirmation, show active goals as expandable cards using Reanimated Layout animations (LayoutAnimation.springify()) for smooth expand/collapse. Each goal card shows its title and an animated circular progress indicator — use Reanimated useAnimatedProps to animate the SVG circle stroke-dashoffset as actions are completed. Tapping a goal expands it with a spring animation to show action items as a checklist. Completing an action triggers: Haptics.impactAsync(ImpactFeedbackStyle.Light), a Reanimated withSpring scale bounce on the checkbox (1 → 1.3 → 1), and an optimistic update via TanStack Query's useCompleteAction mutation (checkbox fills immediately, server syncs in background, rollback on failure). When all actions in a goal are complete, trigger Haptics.notificationAsync(NotificationFeedbackType.Success) and play a subtle confetti-like Reanimated animation. Add a floating action button with a Reanimated withSpring scale entrance animation. The create goal flow opens as a bottom sheet (animated with Reanimated SlideInDown.springify()) with title and optional description fields. All data flows through TanStack Query hooks: useGoals, useCreateGoal, useCompleteAction, useDailyAffirmation. Goals and actions persist offline via TanStack Query's cache + MMKV persistence — creating a goal while offline queues the mutation. Keep the UI minimal and focused — this is the "direction" pillar, it should feel empowering and clear, not like a corporate task manager.
### Session C7: Gallery and History Views
Prompt to Claude Code:
> Build the Gallery tab as a premium history experience using FlashList for buttery-smooth scrolling. Use @shopify/flash-list instead of FlatList — it recycles views for 60fps scrolling even with hundreds of items. The gallery shows a unified timeline with three content types: saved turns (with perspective previews), mirror session summaries (with fragment count and date), and lens achievements (completed actions and goals). Each type should have a distinct but cohesive card design using Reanimated entering animations — cards use FadeInUp.delay(index * 80) for staggered appearance as they scroll into view. Add filtering by content type and date range with an animated filter bar (Reanimated layout animations for smooth filter chip transitions). Add search across saved turn content and mirror reflections — the search bar slides in with Reanimated SlideInDown and uses debounced TanStack Query with the search term as a query key. For free users, gallery shows last 30 days; for prism users, full history. Implement infinite scroll with cursor-based pagination using TanStack Query's useInfiniteQuery — configure getNextPageParam for cursor-based pagination and flatMap pages for FlashList data. Add pull-to-refresh with a custom Reanimated-powered refresh indicator (not the default system spinner). Add a detail view that opens when tapping any gallery item with a shared element transition (Reanimated's SharedTransition) — the card expands into the full detail view. Turns show full perspectives, mirror sessions show the reflection, lens items show the goal with all actions. Add Haptics.selectionAsync() when tapping gallery items. All data through TanStack Query hooks: useGalleryItems (infinite query), useGallerySearch, useTurnDetail, useMirrorDetail. Stale time 2 minutes for gallery list, 5 minutes for detail views. Gallery works offline with cached data from TanStack Query's persisted cache.
### Session C8: Onboarding Flow
Prompt to Claude Code:
> Build the onboarding experience in the (auth) group as a premium first impression. After registration, guide the user through 3-4 screens using a horizontal pager with Reanimated-powered page transitions — each page slides in with a spring physics animation using withSpring({ damping: 20, stiffness: 90 }) for a soft, organic feel (not the stiff default transitions). Screen 1 explains the kaleidoscope metaphor — "Your thoughts are like light. Sometimes they get stuck in one pattern. Kalei helps you turn them and see new colors." Animate the kaleidoscope illustration with a gentle Reanimated rotation (withRepeat + withTiming over 8 seconds) so it feels alive. Screen 2 asks the user to set their preferred reframe style (compassionate, rational, growth) with brief descriptions of each — use Reanimated scale animations on the selection cards (withSpring scale 1 → 1.05 on selection) and Haptics.selectionAsync() on tap. Screen 3 invites the user to try their first Turn — embed a mini version of the Turn input with a pulsing "Turn" button (Reanimated withRepeat opacity animation). Screen 4 shows the result and introduces the daily rhythm (morning affirmation, journaling, reframing) — use staggered FadeInUp animations for each rhythm item. Add a progress indicator using Reanimated interpolation — animated dots that fill as the user progresses, with Haptics.impactAsync(ImpactFeedbackStyle.Soft) on each page transition. Store onboarding completion in the profile via a TanStack Query mutation (useCompleteOnboarding). Skip onboarding for returning users by checking the auth store's onboarding_complete flag (persisted in MMKV). The entire onboarding should feel like a guided meditation — slow, intentional, beautiful.
---
## 7. Build Track D — Launch Hardening (Phase 3)
Duration: 2-4 weeks
Goal: Production-safe, store-ready, monitored.
### Session D1: Safety Hardening
> Expand crisis keyword sets with comprehensive coverage. Add regional crisis resources for all launch regions. Add a safety dashboard endpoint that returns: total safety events by type, false positive rate (manually tagged), response time percentiles. Add an admin-only endpoint to review and tag safety events for quality improvement. Verify that no code path can return reframed content when crisis is detected — write an integration test that traces every AI-facing route with crisis input and asserts the response is always the crisis resource payload.
### Session D2: Billing Integration — Apple
> Implement full App Store Server Notifications v2 handling. Verify notification signatures using Apple's public key. Parse all notification types: SUBSCRIBED, DID_RENEW, EXPIRED, DID_FAIL_TO_RENEW, REFUND, REVOKE, GRACE_PERIOD_EXPIRED. Update subscription status and entitlement snapshots accordingly. Implement a reconciliation job that periodically verifies subscription status directly with Apple's API to catch any missed webhooks. Test with Apple's sandbox environment.
### Session D3: Billing Integration — Google
> Implement Google Play Real-Time Developer Notifications. Verify Pub/Sub message authenticity. Handle all notification types: SUBSCRIPTION_RECOVERED, SUBSCRIPTION_RENEWED, SUBSCRIPTION_CANCELED, SUBSCRIPTION_PURCHASED, SUBSCRIPTION_ON_HOLD, SUBSCRIPTION_IN_GRACE_PERIOD, SUBSCRIPTION_EXPIRED, SUBSCRIPTION_REVOKED. Update subscription and entitlement records. Add reconciliation job for Google Play API verification.
### Session D4: Security Audit Pass
> Review and harden: verify all endpoints require authentication (except /health, /auth/register, /auth/login, /auth/refresh, billing webhooks). Verify password hashing uses Argon2id with secure parameters. Verify JWT tokens use appropriate algorithms and key sizes. Verify refresh token rotation and compromise detection work. Add secure HTTP headers (HSTS, CSP, X-Frame-Options). Verify no PII in logs. Verify column-level encryption on mirror message content and turn input text. Run a dependency audit (pnpm audit). Add rate limiting on auth endpoints (5 attempts per minute per IP for login). Add PostgreSQL Row-Level Security (RLS) policies as defense-in-depth: enable RLS on all user-data tables, create policies that restrict SELECT/UPDATE/DELETE to rows where user_id matches the authenticated user's ID from the JWT claim. This ensures that even if application-level ownership checks are bypassed, the database itself prevents cross-user data access. Create a migration that enables RLS and adds the policies. Test: verify a query with the wrong user_id returns zero rows when RLS is active.
### Session D5: Performance and Load Testing
> Create a load test script using k6 or autocannon that simulates: 50 concurrent users performing the Turn flow (the most AI-intensive path), 20 concurrent Mirror sessions with message submission, 100 concurrent health checks. Measure: p50/p95/p99 latency for each endpoint, error rate under load, AI gateway response time distribution, database query time distribution. Identify and fix any bottlenecks. Target: p95 under 3.5s for AI-backed endpoints, p95 under 200ms for non-AI endpoints. Additionally, run the full Maestro E2E suite (apps/mobile/e2e/) on both iOS simulator and Android emulator to verify all critical flows pass under realistic conditions. Measure: screen transition times (target under 300ms), animation frame drops (target zero dropped frames in Reanimated animations), TanStack Query cache hit rates, and offline-to-online mutation resume success rate.
### Session D6: Deployment Pipeline
> Create the production deployment setup. Docker Compose for the VPS (Fastify API, Postgres 16, Redis 7, Caddy reverse proxy with auto-HTTPS via Let's Encrypt — all free). Create deploy.sh that: builds the API, runs migrations, restarts the service with zero-downtime (using Fastify's graceful shutdown). Create backup-db.sh for automated PostgreSQL backups. Set up the mobile build pipeline using local builds as the primary path: configure eas.json with development, preview, and production profiles, then build locally using `eas build --local --platform ios --profile production` and `eas build --local --platform android --profile production`. This avoids EAS Cloud Build costs entirely — builds run on your machine using Xcode and Android Studio (both free). For development builds during day-to-day work, use `npx expo run:ios` and `npx expo run:android` which compile directly against local toolchains. EAS Cloud Build (30 free builds/month) is available as a convenience but not required. Create the app store metadata: screenshots, description, privacy policy URL, support URL.
### Session D7: Beta Testing Pipeline
> Configure TestFlight for iOS internal testing and Google Play internal testing track. Set up EAS Update for over-the-air updates during beta. Create a beta feedback mechanism — either in-app feedback button or a simple form. Add Maestro E2E tests to the release gate: configure the CI pipeline so that all Maestro flows (onboarding, turn-flow, mirror-session, purchase-flow) must pass on both iOS and Android before a TestFlight or Play Store upload proceeds. Run through the complete user journey manually: register, onboard, complete a Mirror session, do a Turn, set a Lens goal, complete an action, view Gallery. Verify that offline-first behavior works: enable airplane mode, create a turn, re-enable network, verify the turn syncs. Verify haptic feedback fires on all premium touch points (fragment tap, turn save, action complete, onboarding page transition). Document any issues. Fix launch-blocking bugs.
---
## 8. Build Track E — Spectrum Intelligence (Phase 4)
Duration: 3-6 weeks
Goal: Weekly and monthly AI-powered insights from accumulated usage data.
### Session E1: Spectrum Schema and Data Pipeline
> Create Drizzle schema for spectrum tables: spectrum_session_analysis (session_id, emotional_vectors jsonb, fragment_distribution jsonb, created_at), spectrum_turn_analysis (turn_id, pre_emotional_state jsonb, post_emotional_state jsonb, impact_score float, created_at), spectrum_weekly (user_id, week_start, emotional_landscape jsonb, top_fragments jsonb, turn_impact_summary jsonb, rhythm_patterns jsonb, narrative text, created_at), spectrum_monthly (user_id, month_start, growth_trajectory jsonb, theme_evolution jsonb, narrative text, created_at). Add event hooks in Mirror and Turn services that write to spectrum analysis tables after each session/turn completes. Add exclusion flags so users can opt out specific sessions from analysis.
### Session E2: Aggregation Workers
> Build background workers for Spectrum aggregation. The weekly worker runs every Sunday night: loads all non-excluded sessions and turns from the past week, computes emotional vectors using the AI gateway (batch mode for cost savings), aggregates fragment distributions, calculates turn impact scores, generates a narrative summary of the week's patterns. The monthly worker runs on the 1st of each month: aggregates weekly data into monthly trends, identifies growth trajectory, generates a deeper narrative. Both workers must be idempotent (safe to re-run), use retry with backoff, and log failures to a dead-letter table. Use BullMQ or a simple PostgreSQL-based job queue for scheduling.
### Session E3: Spectrum API and Mobile Dashboard
> Create Spectrum API endpoints: GET /spectrum/weekly returns the latest weekly insight (or 404 if not enough data), GET /spectrum/monthly returns the latest monthly summary, POST /spectrum/reset clears all spectrum data for the user, POST /spectrum/exclusions manages session exclusions. Build the Spectrum mobile dashboard as the (spectrum) route group. The dashboard should show: an emotional landscape visualization (could be a simple radar chart or heatmap of the 6 emotional dimensions), fragment pattern distribution (which cognitive distortions appear most), turn impact summary (how much emotional shift the reframes produce), and the AI-generated narrative insight. Gate all Spectrum features behind the prism_plus entitlement.
---
## 9. AI Cost Control Strategy
This section defines the exact implementation of cost guardrails.
### 9.1 Budget Hierarchy
```
Global monthly cap ($50 Phase 1, scales with revenue)
└─ Per-feature daily budget
├─ Turn: 40% of daily budget (core product)
├─ Mirror: 35% of daily budget (core product)
├─ Lens: 10% of daily budget (can fall back to templates)
└─ Spectrum: 15% of daily budget (batch, can defer)
└─ Per-user daily token cap
├─ Free: 100k tokens/day
└─ Prism: 500k tokens/day
```
### 9.2 Degradation Order
When budget pressure hits (80% of daily budget consumed):
1. Lens affirmations switch to template-based (no AI cost).
2. Spectrum narrative generation deferred to next day.
3. Mirror fragment detection reduces max fragments per message from 10 to 5.
4. Turn reframes reduce from 3 perspectives to 2.
5. If 95% consumed: all non-critical AI paused, only safety detection continues.
### 9.3 Provider Routing
The AI gateway routes by feature and cost pressure:
| Feature | Default Provider | Fallback (cost pressure) |
|---|---|---|
| Turn reframe | Claude Haiku 4.5 | Qwen3 235B via Venice |
| Mirror detect | Claude Haiku 4.5 | Qwen3 235B via Venice |
| Mirror reframe | Claude Haiku 4.5 | Qwen3 235B via Venice |
| Lens affirmation | Claude Haiku 4.5 | Template system (no AI) |
| Crisis detection | Keyword + Claude Haiku 4.5 | Keywords only (never skip) |
| Spectrum weekly | Claude Haiku 4.5 Batch API | Deferred |
| Spectrum monthly | Claude Haiku 4.5 Batch API | Deferred |
### 9.4 Prompt Caching Strategy
System prompts for each feature are designed to be identical across users and requests. With Anthropic's prompt caching:
- System prompt tokens (600-800 per feature) are cached after first call.
- Subsequent calls within 5-minute window pay only 10% of base input rate.
- At 90 turns/month per free user, caching saves approximately 40-50% on input costs.
- Implementation: mark system message content blocks with `cache_control: { type: "ephemeral" }` in the Anthropic provider.
---
## 10. Testing Strategy
### 10.1 Test Pyramid
| Layer | Tool | What | Coverage Target |
|---|---|---|---|
| Unit | Vitest | Pure functions, schemas, validators, prompt builders | High (80%+) |
| Integration | Vitest + Supertest | API routes with real DB (test container) | All endpoints |
| Safety | Vitest | Crisis detection accuracy | 100% of known patterns |
| AI Output | Vitest | Schema validation of AI responses | All prompt templates |
| E2E (Mobile) | Maestro | Critical mobile user flows | All happy paths + key error paths |
| Load | k6 | Concurrency and latency under load | Phase 3 only |
### 10.2 Test Database Strategy
Use a separate PostgreSQL database for tests. Before each test suite: run migrations on the test DB. After each test suite: truncate all tables. Never run tests against the development database.
### 10.3 AI Mock Strategy
For unit and integration tests, mock the AI gateway at the provider level. Create a `mock.provider.ts` that returns deterministic, schema-valid responses. This means tests never hit real AI APIs, are fast, free, and deterministic. This is the primary reason AI costs are zero during development — you develop and test against the mock, not real providers. Add a small set of "golden file" tests that run against the real AI provider (gated behind an environment variable `REAL_AI_TESTS=true`) to catch prompt regression. These golden file tests should only be run occasionally during prompt engineering, using free API credits (Anthropic initial credits, Venice free tier, or Google Cloud Vertex AI $300 new-account credits).
### 10.4 Maestro E2E Testing Strategy
Maestro is the industry standard for mobile E2E testing in 2026. It uses YAML-based flow definitions that are faster to write and more readable than code-based alternatives.
**Flow files live in `apps/mobile/e2e/`:**
```yaml
# e2e/onboarding.yaml — Verify new user onboarding flow
appId: com.kalei.app
---
- launchApp
- assertVisible: "Your thoughts are like light"
- swipeLeft
- assertVisible: "How would you like your reframes?"
- tapOn: "Compassionate"
- swipeLeft
- assertVisible: "Try your first Turn"
- tapOn: "What thought is weighing on you?"
- inputText: "I feel overwhelmed with everything"
- tapOn: "Turn"
- assertVisible: "perspective"
- swipeLeft
- assertVisible: "Your daily rhythm"
```
```yaml
# e2e/turn-flow.yaml — Verify complete Turn lifecycle
appId: com.kalei.app
---
- launchApp
- tapOn: "Turn"
- tapOn: "What thought is weighing on you?"
- inputText: "Nothing ever works out for me"
- tapOn: "Turn"
- assertVisible: "Compassionate"
- assertVisible: "Rational"
- assertVisible: "Growth"
- assertVisible: "If I notice"
- tapOn:
id: "save-turn-button"
- assertVisible: "Saved"
```
```yaml
# e2e/mirror-session.yaml — Verify Mirror writing and fragment detection
appId: com.kalei.app
---
- launchApp
- tapOn: "Mirror"
- tapOn: "Begin writing"
- inputText: "Everything is terrible and nothing will get better"
- wait: 3000
- assertVisible: "Catastrophizing"
- tapOn: "Catastrophizing"
- assertVisible: "See another perspective"
- tapOn: "See another perspective"
- assertVisible: "perspective"
```
```yaml
# e2e/purchase-flow.yaml — Verify paywall and upgrade path
appId: com.kalei.app
---
- launchApp
- tapOn: "Turn"
# Exhaust free tier (3 turns)
- repeat:
times: 4
commands:
- tapOn: "What thought is weighing on you?"
- inputText: "Test thought"
- tapOn: "Turn"
- wait: 2000
- assertVisible: "Upgrade to Prism"
```
**Running Maestro tests:**
```bash
# Run a single flow
maestro test apps/mobile/e2e/onboarding.yaml
# Run all flows
maestro test apps/mobile/e2e/
# Run with screenshot capture on failure
maestro test --format junit --output e2e-results/ apps/mobile/e2e/
# Run in CI (headless)
maestro test --no-ansi apps/mobile/e2e/
```
**Maestro in CI (Session D7):** Add Maestro to the CI pipeline by running the Maestro CLI locally on a CI runner with an emulator (Maestro CLI is free and open source — do not use Maestro Cloud which is a paid service). For self-hosted CI via Gitea Actions, install Maestro and an Android emulator on the runner. Gate releases on E2E pass — no TestFlight or Play Store upload if Maestro flows fail. Target: all 4 core flows pass on both iOS and Android before every release.
---
## 11. Deployment and Operations
### 11.1 Phase 1 Deployment (Single VPS)
```
Netcup VPS 1000 G12 (€8.45/month)
├── Caddy (reverse proxy, auto-HTTPS)
├── Node.js API (Fastify, PM2 process manager)
├── PostgreSQL 16 (direct install)
├── Redis 7 (direct install)
└── Background workers (same process or separate PM2 app)
```
### 11.2 Deployment Checklist
Before every production deploy:
1. All tests pass locally.
2. Migration is tested on a staging copy of the database.
3. Rollback migration exists and is tested.
4. Health endpoint returns ok after deploy.
5. Error rate does not spike in first 15 minutes.
6. AI cost telemetry is within expected range.
### 11.3 Backup Strategy
- PostgreSQL: daily pg_dump to encrypted offsite storage.
- Redis: RDB snapshots daily (Redis data is ephemeral and rebuildable, but snapshots prevent cold-start recalculation of usage counters).
- Verified restore drill: run monthly.
---
## 12. Session Execution Checklist
Use this checklist for every Claude Code session:
```
[ ] Read the session description and understand the deliverables
[ ] Verify prerequisites from previous sessions are met
[ ] Execute the session with Claude Code
[ ] Run the validation steps — all must pass
[ ] Run the full quality check: pnpm run check
[ ] Review generated code for architecture compliance:
[ ] AI calls go through gateway only
[ ] Safety precheck on all AI-facing routes
[ ] Entitlement checks where required
[ ] Structured logging with request IDs
[ ] Zod validation on all inputs
[ ] TypeScript strict mode — no any
[ ] Commit with descriptive message
[ ] Update this checklist with any issues or deviations
```
---
## 13. Timeline Summary
| Track | Sessions | Duration | Outcome |
|---|---|---|---|
| A: Foundation | A1-A6 | 3-5 days | Repo, infra, schema, skeletons |
| B: Platform Core | B1-B9 | 2-3 weeks | Auth, billing, AI gateway, safety, push, observability |
| C: Core Experience | C1-C8 | 3-5 weeks | Mirror, Turn, Lens, Gallery, Onboarding |
| D: Launch Hardening | D1-D7 | 2-4 weeks | Safety, billing, security, performance, deployment |
| E: Spectrum | E1-E3 | 3-6 weeks | Analytics pipeline, insights, dashboard |
Total to MVP launch (end of Track D): 8-14 weeks.
Total including Spectrum (end of Track E): 14-22 weeks.
---
## 14. Critical Path Dependencies
```
A1 (repo) → A2 (docker) → A3 (API) → A5 (schema)
A4 (mobile) ←─── A3 (API)
A6 (shared schemas) → B1 (auth) → B2 (tokens) → B3 (entitlements)
B4 (AI gateway) → B5 (prompts) → B6 (safety) ──────→ C1 (mirror API)
B7 (rate limits) → B8 (push) → B9 (observability) ──→ C3 (turn API)
C1 → C2 (mirror UI) ─────────────────────────────→ C7 (gallery)
C3 → C4 (turn UI) ─────────────────────────────→ C7 (gallery)
C5 → C6 (lens UI) ─────────────────────────────→ C7 (gallery)
C8 (onboarding) → D1-D7 (hardening) → E1-E3 (spectrum)
```
---
## 15. What This Framework Deliberately Excludes
These are not in scope for the build framework and should be handled separately:
- Pixel-level UI specs (refer to kalei-complete-design.md and kalei-brand-guidelines.md)
- Marketing copy and App Store optimization (refer to app-blueprint.md section on ASO)
- Legal review of privacy policy and terms of service
- Detailed threat modeling (should be commissioned separately before Phase 3)
- Community building and growth hacking strategy
- Investor materials or pitch decks
---
*This framework is the operational bridge between Kalei's architecture documents and actual code. Follow it session by session. Deviate only when reality demands it, and document every deviation.*

View File

@ -0,0 +1,603 @@
# Kalei — User Journey Technical Map
> Version 1.0 — February 2026
> Maps every user-facing flow to backend API endpoints, database operations, frontend components, and AI calls
---
## Architecture Summary
**Backend:** Fastify 5.x (Node.js 22 LTS), Drizzle ORM, PostgreSQL 16, Redis 7
**Frontend:** React Native + Expo SDK 54+, Expo Router, TanStack Query v5, Zustand, MMKV v4
**AI:** Claude Haiku 4.5 (primary), Groq/Qwen fallback, provider-agnostic AI Gateway
**Auth:** JWT with refresh token rotation, Apple/Google SSO
**Billing:** Direct App Store / Google Play webhook integration
---
## 1. Authentication & Onboarding
### 1.1 Account Registration
**User Action:** Enters email + password or taps Apple/Google SSO
| Layer | Detail |
|-------|--------|
| **API** | `POST /auth/register` — body: `{ email, password, provider? }` |
| **Validation** | Zod: email format, password 8+ chars, provider enum |
| **DB Write** | `INSERT INTO users (id, email, password_hash, created_at)` |
| **DB Write** | `INSERT INTO profiles (user_id, display_name, coaching_style, onboarding_complete)` |
| **DB Write** | `INSERT INTO subscriptions (user_id, plan, status, started_at)` — defaults to `free` |
| **Redis** | Set `rate:auth:{ip}` with TTL for brute-force protection |
| **Response** | `{ access_token, refresh_token, user: { id, email, profile } }` |
| **Frontend** | `AuthStore.setTokens()` → MMKV encrypted storage → navigate to onboarding |
### 1.2 Token Refresh
| Layer | Detail |
|-------|--------|
| **API** | `POST /auth/refresh` — body: `{ refresh_token }` |
| **DB Read** | `SELECT FROM refresh_tokens WHERE token = $1 AND revoked = false` |
| **DB Write** | Revoke old token, issue new pair (rotation) |
| **Redis** | Invalidate old session cache |
### 1.3 Onboarding Completion
**User Action:** Completes screens 2-9 (style selection, first Turn)
| Layer | Detail |
|-------|--------|
| **API** | `PATCH /me/profile` — body: `{ coaching_style, notification_time, onboarding_complete: true }` |
| **DB Write** | `UPDATE profiles SET coaching_style = $1, notification_time = $2, onboarding_complete = true` |
| **Push** | Schedule first notification via push service at chosen time |
| **Frontend** | `OnboardingStore.complete()` → navigate to main tab navigator |
---
## 2. The Turn (Reframing)
### 2.1 Submit a Turn
**User Action:** Types thought → taps "Turn it"
| Layer | Detail |
|-------|--------|
| **Frontend** | Validate non-empty input, show Turn animation (1.5s kaleidoscope rotation) |
| **API** | `POST /turns` — body: `{ input_text, coaching_style? }` |
| **Rate Check** | Redis: `INCR rate:turns:{user_id}:{date}` → reject if > 3 (free) or > 100 (prism) |
| **Entitlement** | `SELECT plan FROM subscriptions WHERE user_id = $1` → gate check |
| **Safety** | Deterministic keyword scan → if flagged: `INSERT INTO safety_events`, return crisis response |
| **AI Call** | AI Gateway → Claude Haiku 4.5: system prompt (coaching style + reframe instructions) + user input |
| **AI Response** | JSON: `{ perspectives: [{ style, text, emotion_before, emotion_after }], micro_action: { if_clause, then_clause }, fragments_detected: [{ type, phrase, confidence }] }` |
| **DB Write** | `INSERT INTO turns (id, user_id, input_text, perspectives, micro_action, fragments, emotion_vector, created_at)` |
| **DB Write** | `INSERT INTO ai_usage_events (user_id, feature, model, input_tokens, output_tokens, latency_ms, cost_usd)` |
| **Redis** | Increment daily counter, update streak cache |
| **Response** | `{ turn_id, perspectives, micro_action, fragments, pattern_seed }` |
| **Frontend** | Dismiss animation → render 3 perspective cards + micro-action card |
### 2.2 Save a Turn / Keepsake
**User Action:** Taps save on a perspective card
| Layer | Detail |
|-------|--------|
| **API** | `POST /turns/{id}/save` — body: `{ perspective_index, save_type: "keepsake" }` |
| **DB Write** | `UPDATE turns SET saved = true, saved_perspective_index = $1` |
| **DB Write** | `INSERT INTO evidence_wall_tiles (user_id, tile_type, source_feature, source_id, color_accent, created_at)` — type: `saved_keepsake` |
| **Response** | `{ saved: true, gallery_id, evidence_tile_id }` |
| **Frontend** | Success toast "Turn saved" → update Gallery cache via TanStack Query invalidation |
### 2.3 Get Turn History
| Layer | Detail |
|-------|--------|
| **API** | `GET /turns?limit=20&offset=0&date=2026-02-21` |
| **DB Read** | `SELECT id, input_text, perspectives, fragments, created_at FROM turns WHERE user_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3` |
| **Cache** | Redis: cache recent 20 turns per user, 5 min TTL |
---
## 3. The Mirror (Journaling + Fragment Detection)
### 3.1 Start Mirror Session
**User Action:** Opens Mirror tab → starts new session
| Layer | Detail |
|-------|--------|
| **API** | `POST /mirror/sessions` — body: `{ prompt_id? }` |
| **Rate Check** | Redis: `INCR rate:mirror:{user_id}:{week}` → reject if > 2 (free) |
| **DB Write** | `INSERT INTO mirror_sessions (id, user_id, status, started_at)` — status: `active` |
| **Response** | `{ session_id, opening_prompt }` |
| **Frontend** | Navigate to session view, show opening prompt in AI bubble |
### 3.2 Send Message in Mirror
**User Action:** Types and sends a message
| Layer | Detail |
|-------|--------|
| **Frontend** | Append user message to local state, show AI thinking animation |
| **API** | `POST /mirror/sessions/{id}/messages` — body: `{ content, message_type: "user" }` |
| **DB Write** | `INSERT INTO mirror_messages (id, session_id, role, content, created_at)` |
| **AI Call #1** | Fragment Detection: system prompt (10 distortion types + detection rules) + session context + new message |
| **AI Response #1** | `{ fragments: [{ type, phrase, start_index, end_index, confidence }] }` |
| **Entitlement Gate** | Free: filter to 3 types (catastrophizing, black_and_white, should_statements). Prism: all 10 |
| **DB Write** | `INSERT INTO mirror_fragments (id, session_id, message_id, distortion_type, phrase, start_idx, end_idx, confidence)` |
| **AI Call #2** | Reflective Response: system prompt (warm, non-directive, Mirror voice) + session history + detected fragments |
| **AI Response #2** | `{ response_text, suggested_prompts: [] }` |
| **DB Write** | `INSERT INTO mirror_messages (id, session_id, role: "assistant", content)` |
| **Response** | `{ message_id, ai_response, fragments: [{ type, phrase, indices }] }` |
| **Frontend** | Render AI response bubble, apply amber highlight underlines to user's message at fragment positions |
### 3.3 Tap Fragment Highlight → Inline Reframe
**User Action:** Taps highlighted text in their message
| Layer | Detail |
|-------|--------|
| **Frontend** | Open half-sheet modal with distortion info (local data from fragment detection response) |
| **API** | `POST /mirror/fragments/{id}/reframe` — body: `{ fragment_id }` |
| **Rate Check** | Free: 1 inline reframe per session |
| **AI Call** | Quick reframe: system prompt + fragment context + distortion type |
| **AI Response** | `{ reframes: [{ text, style }], can_turn: true }` |
| **Response** | `{ reframes, turn_prefill }``turn_prefill` is the fragment phrase ready for Turn |
| **Frontend** | Render reframes in half-sheet. "Take to Turn" button navigates to Turn tab with `input_text` pre-filled |
### 3.4 Close Mirror Session → Generate Reflection
**User Action:** Taps "End Session" or navigates away
| Layer | Detail |
|-------|--------|
| **API** | `POST /mirror/sessions/{id}/close` |
| **DB Read** | Fetch all messages + fragments for session |
| **AI Call** | Reflection generation: full session transcript + all fragments → themes, insight, pattern seed |
| **AI Response** | `{ themes: [], fragment_summary: { total, by_type }, insight: "string", pattern_seed: "hash" }` |
| **DB Write** | `UPDATE mirror_sessions SET status = "closed", reflection = $1, pattern_seed = $2, closed_at = NOW()` |
| **DB Write** | `INSERT INTO evidence_wall_tiles (user_id, tile_type: "mirror_reflection", source_id, ...)` |
| **Response** | `{ reflection, pattern_seed, fragment_summary }` |
| **Frontend** | Show reflection card with generated kaleidoscope pattern thumbnail → auto-saved to Gallery |
---
## 4. The Lens (Goals + Actions)
### 4.1 Create Goal
| Layer | Detail |
|-------|--------|
| **API** | `POST /lens/goals` — body: `{ title, description, target_date?, category? }` |
| **AI Call** | Goal refinement: make SMART, suggest metrics, generate initial visualization description |
| **DB Write** | `INSERT INTO lens_goals (id, user_id, title, description, target_date, visualization_text, status, created_at)` |
| **Response** | `{ goal_id, refined_title, visualization, suggested_actions }` |
### 4.2 Get Daily Actions + Affirmation
| Layer | Detail |
|-------|--------|
| **API** | `GET /lens/today` |
| **DB Read** | Active goals + incomplete actions + today's affirmation |
| **AI Call** (if no affirmation cached) | Generate daily affirmation based on active goals + recent progress |
| **Redis** | Cache today's affirmation, 24h TTL |
| **Response** | `{ goals: [...], today_actions: [...], affirmation: { text, goal_id } }` |
### 4.3 Complete Action
| Layer | Detail |
|-------|--------|
| **API** | `POST /lens/actions/{id}/complete` |
| **DB Write** | `UPDATE lens_actions SET completed = true, completed_at = NOW()` |
| **DB Write** | `INSERT INTO evidence_wall_tiles (tile_type: "completed_action", source_id, color_accent: "emerald")` |
| **Redis** | Update streak counter |
| **Response** | `{ completed: true, goal_progress_pct, streak_count, evidence_tile_id }` |
### 4.4 Start Rehearsal Session
**User Action:** On goal detail → taps "Rehearse"
| Layer | Detail |
|-------|--------|
| **API** | `POST /lens/goals/{id}/rehearsal` |
| **Rate Check** | Free: 1/week, Prism: unlimited |
| **DB Read** | Fetch goal details + user's recent Mirror/Turn data for personalization |
| **AI Call** | Visualization script generation: first-person, multi-sensory, process-oriented, obstacle rehearsal |
| **AI Response** | `{ script_segments: [{ text, duration_seconds, breathing_cue? }], total_duration }` |
| **DB Write** | `INSERT INTO rehearsal_sessions (id, user_id, goal_id, script, duration, created_at)` |
| **Response** | `{ session_id, script_segments, total_duration }` |
| **Frontend** | Enter Rehearsal mode: timer ring, text card sequence with breathing animation pacing |
### 4.5 Complete Rehearsal
| Layer | Detail |
|-------|--------|
| **API** | `POST /lens/rehearsals/{id}/complete` |
| **DB Write** | `UPDATE rehearsal_sessions SET completed = true, completed_at = NOW()` |
| **DB Write** | `INSERT INTO evidence_wall_tiles (tile_type: "rehearsal_complete", source_id, color_accent: "amethyst")` |
| **Response** | `{ completed: true, evidence_tile_id }` |
| **Frontend** | Success burst animation → navigate back to goal detail |
---
## 5. The Ritual (Daily Habit Sequences)
### 5.1 Start Ritual
**User Action:** Taps "Start Ritual" on Turn tab or from notification
| Layer | Detail |
|-------|--------|
| **API** | `POST /rituals/start` — body: `{ template: "morning" | "evening" | "quick" }` |
| **Rate Check** | Free: only `quick` template allowed |
| **DB Write** | `INSERT INTO ritual_sessions (id, user_id, template, status, started_at)` |
| **DB Read** | Fetch user's active goals, recent fragments, streak data for personalization |
| **AI Call** | Personalize ritual prompts based on user context |
| **Response** | `{ session_id, steps: [{ type, prompt, duration_seconds }] }` |
| **Frontend** | Enter Ritual mode: fragment-shaped step progress bar, step-by-step flow |
### 5.2 Ritual Step Completion
Each step may trigger its own API call:
| Step | API Calls |
|------|-----------|
| Mirror check-in | `POST /mirror/sessions` + `POST /mirror/sessions/{id}/messages` (lightweight, 1-2 exchanges) |
| Turn | `POST /turns` (with ritual context flag) |
| Lens review | `POST /lens/actions/{id}/complete` (for each completed action) |
| Affirmation | `GET /lens/today` (cached) |
| Gratitude | `POST /rituals/{id}/gratitude` — body: `{ text }` |
### 5.3 Complete Ritual
| Layer | Detail |
|-------|--------|
| **API** | `POST /rituals/{id}/complete` |
| **DB Write** | `UPDATE ritual_sessions SET status = "completed", completed_at = NOW()` |
| **DB Write** | `INSERT INTO evidence_wall_tiles (tile_type: "ritual_complete", color_accent: "amber")` |
| **Redis** | Update ritual streak: `INCR streak:ritual:{user_id}`, check context consistency (same time ± 30 min) |
| **DB Write** | `UPDATE profiles SET ritual_streak = $1, ritual_consistency_score = $2` |
| **Response** | `{ completed: true, streak_count, consistency_score, evidence_tile_id }` |
| **Frontend** | Prismatic ring completion animation → streak view |
---
## 6. Gallery
### 6.1 Get All Patterns
| Layer | Detail |
|-------|--------|
| **API** | `GET /gallery?view=all&limit=20&offset=0` |
| **DB Read** | `SELECT id, source_feature, pattern_seed, preview_text, created_at FROM gallery_items WHERE user_id = $1 ORDER BY created_at DESC` |
| **Cache** | Redis: cache first page, 2 min TTL |
### 6.2 Get Pattern Detail
| Layer | Detail |
|-------|--------|
| **API** | `GET /gallery/{id}` |
| **DB Read** | Full gallery item with source content, fragments, pattern seed |
| **Frontend** | Render hero kaleidoscope pattern (deterministic from seed), source content, metadata |
### 6.3 Search / Filter
| Layer | Detail |
|-------|--------|
| **API** | `GET /gallery/search?q=text&feature=turn&distortion=catastrophizing&from=2026-01-01` |
| **DB Read** | Full-text search on gallery content + filter joins |
### 6.4 Generate Pattern Card (Share)
| Layer | Detail |
|-------|--------|
| **API** | `POST /gallery/{id}/share` |
| **Backend** | Generate Pattern Card image: kaleidoscope pattern + reframe text overlay + Kalei watermark |
| **Response** | `{ share_url, image_url }` |
| **Frontend** | Native share sheet with generated image |
---
## 7. Evidence Wall
### 7.1 Get Evidence Wall
| Layer | Detail |
|-------|--------|
| **API** | `GET /evidence-wall?limit=50` |
| **DB Read** | `SELECT * FROM evidence_wall_tiles WHERE user_id = $1 ORDER BY created_at DESC` |
| **Entitlement** | Free: 30-day window (`WHERE created_at > NOW() - INTERVAL '30 days'`). Prism: all history |
| **Response** | `{ tiles: [...], connections: [...], stage: "empty" | "early" | "mid" | "full" }` |
| **Frontend** | Render mosaic view based on stage, assign tile shapes (diamond, hex, rect, pentagon, triangle) based on tile_type |
### 7.2 Get Tile Detail
| Layer | Detail |
|-------|--------|
| **API** | `GET /evidence-wall/tiles/{id}` |
| **DB Read** | Tile + source data (join to turns/mirror_sessions/lens_actions/ritual_sessions/rehearsal_sessions) |
| **Response** | `{ tile, source_content, source_feature, created_at }` |
| **Frontend** | Half-sheet with tile detail, source content, link to source feature |
### 7.3 Contextual Evidence Surfacing
**Trigger:** AI detects low self-efficacy language in Mirror or Turn
| Layer | Detail |
|-------|--------|
| **AI Detection** | During Mirror fragment detection or Turn processing, flag self-efficacy score < threshold |
| **DB Read** | `SELECT * FROM evidence_wall_tiles WHERE user_id = $1 ORDER BY relevance_score DESC LIMIT 2` |
| **Response** | Included in Mirror/Turn response: `{ evidence_nudge: { tiles: [...], message: "..." } }` |
| **Frontend** | Render gentle card below main content with 1-2 evidence tiles |
---
## 8. Spectrum (Phase 2)
### 8.1 Weekly Aggregation (Background Job)
| Layer | Detail |
|-------|--------|
| **Trigger** | Cron: Sunday 6pm UTC |
| **DB Read** | All turns + mirror_sessions + lens_actions for user's week |
| **AI Call** | Batch API (50% cost): analyze emotional vectors, fragment patterns, Turn impact |
| **DB Write** | `INSERT INTO spectrum_weekly (user_id, week_start, river_data, glass_data, impact_data, rhythm_data, growth_score, insight_text)` |
| **Push** | Notification: "Your weekly Spectrum insight is ready" |
### 8.2 Get Spectrum Dashboard
| Layer | Detail |
|-------|--------|
| **API** | `GET /spectrum/dashboard` |
| **Entitlement** | Free: simplified `{ weekly_insight_text, basic_fragment_count }`. Prism: full dashboard |
| **DB Read** | Latest weekly + monthly aggregates |
| **Response** | `{ river, glass, impact, rhythm, growth, weekly_insight, monthly_insight? }` |
| **Frontend** | Render 5 visualization components from spectrum-visualizations.svg data |
### 8.3 Monthly Deep Dive (Background Job)
| Layer | Detail |
|-------|--------|
| **Trigger** | Cron: 1st of month |
| **DB Read** | All weekly aggregates for the month |
| **AI Call** | Batch API: month-over-month narrative generation |
| **DB Write** | `INSERT INTO spectrum_monthly (user_id, month_start, narrative, growth_trajectory, milestone_events)` |
---
## 9. Billing & Entitlements
### 9.1 Entitlement Check (Middleware)
Every rate-limited endpoint runs this check:
```
1. Redis: GET entitlement:{user_id} → if cached, return
2. DB: SELECT plan, status FROM subscriptions WHERE user_id = $1 AND status = 'active'
3. Redis: SET entitlement:{user_id} = plan, EX 300 (5 min cache)
4. Return plan → middleware applies feature gates
```
### 9.2 App Store Webhook
| Layer | Detail |
|-------|--------|
| **API** | `POST /billing/webhooks/apple` |
| **Validation** | Verify Apple JWT signature |
| **DB Write** | `INSERT/UPDATE subscriptions SET plan = $1, status = $2, apple_transaction_id = $3` |
| **Redis** | Invalidate `entitlement:{user_id}` cache |
| **DB Write** | `INSERT INTO entitlement_snapshots (user_id, plan, event_type, timestamp)` |
### 9.3 Google Play Webhook
Same pattern as Apple, with Google-specific JWT validation and `google_purchase_token`.
---
## 10. Safety System
### 10.1 Crisis Detection Pipeline
Every AI-processed input runs through:
```
Stage 1: Deterministic keyword scan (regex, ~1ms)
→ If match: flag, skip AI, return crisis template
Stage 2: AI confirmation (during normal processing)
→ AI output includes safety_flag: boolean
→ If flagged: return hardcoded crisis response (never AI-generated)
Stage 3: Logging
→ INSERT INTO safety_events (user_id, input_hash, detection_stage, action_taken)
→ Alert: send to safety dashboard
```
### 10.2 Crisis Response
| Layer | Detail |
|-------|--------|
| **Response** | Hardcoded template: empathetic acknowledgment + 988 Suicide & Crisis Lifeline + Crisis Text Line |
| **UI** | Full-screen modal with prominent crisis resource links, "I'm OK" dismiss button |
| **Logging** | All crisis events logged, never the content itself |
---
## Database Schema Summary
### Core Tables
| Table | Key Columns | Indexes |
|-------|------------|---------|
| `users` | id (uuid), email, password_hash, created_at | email (unique) |
| `profiles` | user_id (FK), display_name, coaching_style, notification_time, onboarding_complete, ritual_streak, ritual_consistency_score | user_id (unique) |
| `subscriptions` | user_id (FK), plan (enum), status, started_at, expires_at, apple_transaction_id?, google_purchase_token? | user_id, status |
| `refresh_tokens` | id, user_id (FK), token_hash, revoked, expires_at | token_hash, user_id |
### Feature Tables
| Table | Key Columns | Indexes |
|-------|------------|---------|
| `turns` | id, user_id, input_text (encrypted), perspectives (jsonb), micro_action (jsonb), fragments (jsonb), emotion_vector (jsonb), saved, pattern_seed, created_at | user_id + created_at |
| `mirror_sessions` | id, user_id, status, reflection (jsonb), pattern_seed, started_at, closed_at | user_id + status |
| `mirror_messages` | id, session_id (FK), role, content (encrypted), created_at | session_id + created_at |
| `mirror_fragments` | id, session_id (FK), message_id (FK), distortion_type (enum), phrase, start_idx, end_idx, confidence | session_id, distortion_type |
| `lens_goals` | id, user_id, title, description, target_date, visualization_text, status, created_at | user_id + status |
| `lens_actions` | id, goal_id (FK), text, if_clause, then_clause, completed, completed_at | goal_id + completed |
| `rehearsal_sessions` | id, user_id, goal_id (FK), script (jsonb), duration, completed, started_at, completed_at | user_id + goal_id |
| `ritual_sessions` | id, user_id, template (enum), status, steps_completed (jsonb), started_at, completed_at | user_id + created_at |
| `gallery_items` | id, user_id, source_feature (enum), source_id, content_preview, pattern_seed, distortion_types (text[]), created_at | user_id + source_feature, full-text on content_preview |
| `evidence_wall_tiles` | id, user_id, tile_type (enum), source_feature, source_id, color_accent, metadata (jsonb), created_at | user_id + created_at, user_id + tile_type |
### Analytics Tables
| Table | Key Columns | Indexes |
|-------|------------|---------|
| `spectrum_weekly` | id, user_id, week_start, river_data (jsonb), glass_data (jsonb), impact_data (jsonb), rhythm_data (jsonb), growth_score, insight_text | user_id + week_start |
| `spectrum_monthly` | id, user_id, month_start, narrative (text), growth_trajectory (jsonb), milestone_events (jsonb) | user_id + month_start |
| `ai_usage_events` | id, user_id, feature, model, input_tokens, output_tokens, latency_ms, cost_usd, created_at | user_id + feature, created_at |
| `safety_events` | id, user_id, input_hash, detection_stage, action_taken, created_at | user_id, created_at |
### Enum Types
```sql
CREATE TYPE plan_type AS ENUM ('free', 'prism');
CREATE TYPE subscription_status AS ENUM ('active', 'expired', 'canceled', 'trial', 'grace_period');
CREATE TYPE distortion_type AS ENUM ('catastrophizing', 'black_and_white', 'mind_reading', 'fortune_telling', 'personalization', 'discounting_positives', 'emotional_reasoning', 'should_statements', 'labeling', 'overgeneralization');
CREATE TYPE tile_type AS ENUM ('saved_keepsake', 'mirror_reflection', 'completed_action', 'self_correction', 'streak_milestone', 'goal_completion', 'reframe_echo', 'rehearsal_complete', 'ritual_complete');
CREATE TYPE ritual_template AS ENUM ('morning', 'evening', 'quick');
CREATE TYPE source_feature AS ENUM ('turn', 'mirror', 'lens', 'rehearsal', 'ritual');
```
---
## Redis Key Patterns
| Key | Type | TTL | Purpose |
|-----|------|-----|---------|
| `rate:turns:{user_id}:{date}` | counter | 24h | Daily Turn rate limit |
| `rate:mirror:{user_id}:{week}` | counter | 7d | Weekly Mirror rate limit |
| `rate:rehearsal:{user_id}:{week}` | counter | 7d | Weekly Rehearsal rate limit |
| `entitlement:{user_id}` | string | 5 min | Cached subscription plan |
| `streak:daily:{user_id}` | hash | — | Current daily streak count + last active date |
| `streak:ritual:{user_id}` | hash | — | Ritual streak + consistency data |
| `affirmation:{user_id}:{date}` | string | 24h | Today's cached affirmation |
| `turns:recent:{user_id}` | list | 5 min | Cached recent turns |
| `session:{session_id}` | hash | 2h | Active Mirror session context |
---
## AI Gateway Call Patterns
### Cost Tiers
| Feature | Model | Est. Cost/Call | Caching |
|---------|-------|----------------|---------|
| Turn (reframe) | Claude Haiku 4.5 | ~$0.003 | System prompt cached (40% saving) |
| Mirror (fragment detection) | Claude Haiku 4.5 | ~$0.002 | System prompt cached |
| Mirror (reflective response) | Claude Haiku 4.5 | ~$0.003 | System prompt cached |
| Mirror (session reflection) | Claude Haiku 4.5 | ~$0.005 | — |
| Lens (goal refinement) | Claude Haiku 4.5 | ~$0.004 | — |
| Rehearsal (script gen) | Claude Haiku 4.5 | ~$0.008 | — |
| Ritual (personalization) | Claude Haiku 4.5 | ~$0.003 | System prompt cached |
| Spectrum (weekly) | Claude Batch API | ~$0.010 | Batch (50% off) |
| Spectrum (monthly) | Claude Batch API | ~$0.015 | Batch (50% off) |
| Safety (confirmation) | Included in feature call | $0 | Part of existing call |
### Prompt Template Versioning
All prompts stored as versioned templates: `prompts/{feature}/{version}.json`
| Prompt | Current Version |
|--------|----------------|
| turn_reframe | v1.0 |
| mirror_fragment_detect | v1.0 |
| mirror_reflect | v1.0 |
| mirror_session_close | v1.0 |
| lens_goal_refine | v1.0 |
| rehearsal_script | v1.0 |
| ritual_personalize | v1.0 |
| spectrum_weekly | v1.0 |
| spectrum_monthly | v1.0 |
| safety_check | v1.0 |
---
## Frontend Component Architecture
### Navigation
```
AppNavigator (Expo Router)
├── (auth)
│ ├── login.tsx
│ ├── register.tsx
│ └── onboarding/
│ ├── welcome.tsx
│ ├── metaphor.tsx
│ ├── turn-demo.tsx
│ ├── style-select.tsx
│ ├── notifications.tsx
│ └── first-turn.tsx
├── (tabs)
│ ├── turn/
│ │ ├── index.tsx — Turn home + input
│ │ ├── results.tsx — Turn results display
│ │ ├── ritual-select.tsx — Ritual template picker
│ │ └── ritual-flow.tsx — Active ritual flow
│ ├── mirror/
│ │ ├── index.tsx — Session list + new session
│ │ └── session.tsx — Active Mirror session
│ ├── lens/
│ │ ├── index.tsx — Goal dashboard
│ │ ├── create-goal.tsx — 6-step goal creation
│ │ ├── goal-detail.tsx — Goal detail + actions
│ │ └── rehearsal.tsx — Rehearsal session
│ ├── gallery/
│ │ ├── index.tsx — Pattern grid + filters
│ │ └── detail.tsx — Pattern detail + share
│ └── you/
│ ├── index.tsx — Profile + stats
│ ├── evidence-wall.tsx — Evidence Wall mosaic
│ ├── spectrum.tsx — Spectrum dashboard
│ ├── settings.tsx — App settings
│ └── subscription.tsx — Plan management
└── (modals)
├── fragment-detail.tsx — Half-sheet for fragment info
├── upgrade.tsx — Prism upgrade prompt
├── crisis.tsx — Crisis response (safety)
├── share-card.tsx — Pattern card share sheet
└── rate-limit.tsx — Rate limit notice
```
### Shared Components
| Component | Usage | SVG Asset |
|-----------|-------|-----------|
| `FragmentIcon` | Everywhere — the core ◇ | `fragment-icons.svg` |
| `TabBar` | Main navigation | `icons-tab-bar.svg` |
| `DistortionBadge` | Mirror highlights, Gallery filters | `icons-distortions.svg` |
| `ActionIcon` | Buttons, list items, settings | `icons-actions.svg` |
| `KaleidoscopePattern` | Gallery, Turn result, share card | `patterns-kaleidoscope.svg` |
| `ProgressRing` | Lens goals, Rehearsal timer | `progress-indicators.svg` |
| `StepDots` | Lens 6-step, Ritual flow | `progress-indicators.svg` |
| `StreakCalendar` | Ritual tracking, You stats | `progress-indicators.svg` |
| `EvidenceMosaic` | Evidence Wall | `evidence-wall.svg` |
| `LoadingSpinner` | All loading states | `loading-animations.svg` |
| `SkeletonShimmer` | Data loading | `loading-animations.svg` |
| `TurnAnimation` | Turn processing | `loading-animations.svg` |
| `AIThinkingBubble` | Mirror AI processing | `loading-animations.svg` |
| `SuccessBurst` | Completion celebrations | `loading-animations.svg` |
| `BreathingLogo` | Splash, idle states | `loading-animations.svg` |
| `StatusBar` | Device chrome | `device-chrome.svg` |
| `NavHeader` | All screens | `device-chrome.svg` |
| `TabBarFrame` | Tab bar container | `device-chrome.svg` |
| `Toast` | Success/error feedback | `device-chrome.svg` |
| `InputAccessory` | Mirror, Turn text input | `device-chrome.svg` |
| `ShardCluster` | Empty states, backgrounds | `decorative-shards.svg` |
| `PrismaticDivider` | Section separators | `decorative-shards.svg` |
| `CornerAccent` | Card decorations | `decorative-shards.svg` |
| `SpectrumRiver` | Spectrum dashboard | `spectrum-visualizations.svg` |
| `SpectrumGlass` | Spectrum dashboard | `spectrum-visualizations.svg` |
| `SpectrumImpact` | Spectrum dashboard | `spectrum-visualizations.svg` |
| `SpectrumRhythm` | Spectrum dashboard | `spectrum-visualizations.svg` |
| `SpectrumGrowth` | Spectrum dashboard | `spectrum-visualizations.svg` |

View File

@ -0,0 +1,42 @@
# Kalei SVG Asset Library — Index
All assets derive their visual language from the **soft-elegance-final.svg** logo: crystalline geometry, jewel tone gradients, glow filters, breathing animations, and prismatic color cycling.
## Files
| File | Description | Elements |
|------|-------------|----------|
| `design-system.css` | Shared CSS with all design tokens, components, animations | Colors, typography, buttons, cards, inputs, utilities |
| `icons-tab-bar.svg` | 5 navigation tab icons | Turn ◇, Mirror ✦, Lens ◎, Gallery ▦, You ● — active + inactive states |
| `icons-distortions.svg` | 10 cognitive distortion type icons | Catastrophizing, Black-and-White, Mind Reading, Fortune Telling, Personalization, Discounting Positives, Emotional Reasoning, Should Statements, Labeling, Overgeneralization |
| `icons-actions.svg` | 30 action/UI icons | Navigation, actions, status, feature-specific, media controls |
| `fragment-icons.svg` | Fragment ◇ variants + highlight effects | 5 sizes (xs-xl), 8 color states, highlight underline, highlight bubble |
| `decorative-shards.svg` | Background decorative elements | Breathing aura, floating shards, prismatic divider, corner accent, hero shard, shard cluster, orbiting motes, edge shimmer |
| `patterns-kaleidoscope.svg` | 7 kaleidoscope pattern variants | Turn pattern, Mirror pattern, Ritual pattern, Simple, Complex, Thumbnail, Hero |
| `progress-indicators.svg` | 8 progress visualization types | Large/small rings, linear bar, step dots, streak calendar, ritual bar, timer, evidence counter |
| `evidence-wall.svg` | Evidence Wall mosaic system | 5 tile shapes, 3 mosaic stages (early/mid/full), connection lines, empty state |
| `loading-animations.svg` | 10 loading/animation states | Spinners, skeleton shimmers, Turn animation, breathing logo, AI thinking, success burst |
| `device-chrome.svg` | 8 device frame elements | Status bar, tab bar frame, nav header, iOS keyboard, device frame, modal scrim, toast, input accessory |
| `spectrum-visualizations.svg` | 5 Spectrum analytics visualizations | The River, Your Glass, Turn Impact, Rhythm Detection, Growth Trajectory |
## Color Reference
| Token | Hex | Usage |
|-------|-----|-------|
| Void | `#050508` | Deepest background |
| Kalei Navy | `#0A0E1A` | Primary surfaces |
| Deep Glass | `#121628` | Elevated surfaces, inputs |
| Twilight | `#1C2240` | Borders, dividers |
| Amethyst | `#8B5CF6` | Primary accent, Turn |
| Sapphire | `#3B82F6` | Info, Gallery |
| Emerald | `#10B981` | Success, Lens |
| Amber | `#F59E0B` | Fragments, Mirror |
| Rose | `#EC4899` | Social, sharing |
| Ruby | `#EF4444` | Error, destructive |
| Indigo | `#6366F1` | Extended palette |
## Total Asset Count
- **11 SVG files** containing **100+ individual elements**
- **1 CSS design system** with complete component library
- All assets use consistent prismatic color palette and crystalline design language

View File

@ -0,0 +1,299 @@
<svg viewBox="0 0 700 880" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grAmethyst" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#C4B5FD"><animate attributeName="stop-color" values="#C4B5FD;#DDD6FE;#C4B5FD" dur="4s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#7C3AED"/>
</linearGradient>
<linearGradient id="grSapphire" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#93C5FD"/><stop offset="100%" stop-color="#2563EB"/>
</linearGradient>
<linearGradient id="grEmerald" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#6EE7B7"/><stop offset="100%" stop-color="#059669"/>
</linearGradient>
<linearGradient id="grAmber" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FDE68A"/><stop offset="100%" stop-color="#D97706"/>
</linearGradient>
<linearGradient id="grRose" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBCFE8"/><stop offset="100%" stop-color="#DB2777"/>
</linearGradient>
<linearGradient id="grIndigo" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#A5B4FC"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<linearGradient id="prismaticH" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="50%" stop-color="#10B981"><animate attributeName="stop-color" values="#10B981;#F59E0B;#EC4899;#8B5CF6;#3B82F6;#10B981" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"><animate attributeName="stop-color" values="#EC4899;#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899" dur="8s" repeatCount="indefinite"/></stop>
</linearGradient>
<radialGradient id="auraGrad" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#8B5CF6" stop-opacity="0.15"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="10s" repeatCount="indefinite"/></stop>
<stop offset="60%" stop-color="#8B5CF6" stop-opacity="0.04"/>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<filter id="glowSm" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="1.5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowMd" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowLg" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="8" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowXl" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur stdDeviation="14" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="shimmer" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="2" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<style>
text { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; }
.lbl { font-size: 9px; fill: #94A3B8; text-anchor: middle; font-weight: 500; }
.section-lbl { font-size: 11px; fill: #64748B; font-weight: 600; letter-spacing: 0.08em; }
</style>
</defs>
<rect width="700" height="880" fill="#050508"/>
<text x="350" y="28" font-size="13" font-weight="700" fill="#94A3B8" text-anchor="middle" letter-spacing="0.12em">DECORATIVE SHARD ELEMENTS</text>
<text x="350" y="44" font-size="9" fill="#475569" text-anchor="middle">Background auras, floating shards, prismatic dividers, corner accents, edge shimmers</text>
<!-- 1. BREATHING AURA -->
<text x="24" y="74" class="section-lbl">BREATHING AURA</text>
<line x1="24" y1="80" x2="670" y2="80" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(175, 160)">
<circle r="70" fill="url(#auraGrad)">
<animate attributeName="r" values="60;75;60" dur="6s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.6;1;0.6" dur="6s" repeatCount="indefinite"/>
</circle>
<circle r="40" fill="#8B5CF6" opacity="0.05" filter="url(#glowXl)">
<animate attributeName="r" values="35;45;35" dur="4s" repeatCount="indefinite"/>
</circle>
<text x="0" y="100" class="lbl">Behind cards, hero sections</text>
</g>
<!-- 2. FLOATING SHARDS -->
<g transform="translate(475, 100)">
<text x="0" y="-14" class="section-lbl" text-anchor="middle">FLOATING SHARDS</text>
<!-- Shard 1 - large, slow drift -->
<g filter="url(#glowMd)">
<path d="M 0,-18 L 10,-4 L 2,16 L -8,6 Z" fill="url(#grAmethyst)" opacity="0.25">
<animate attributeName="opacity" values="0.15;0.35;0.15" dur="7s" repeatCount="indefinite"/>
</path>
<path d="M 0,-18 L 10,-4 L -8,6 Z" fill="#fff" opacity="0.06"/>
<animateTransform attributeName="transform" type="translate" values="0,0;5,-8;0,0" dur="12s" repeatCount="indefinite"/>
</g>
<!-- Shard 2 - medium, angled -->
<g transform="translate(50, 30)" filter="url(#glowSm)">
<path d="M 0,-10 L 7,2 L -2,12 L -6,0 Z" fill="url(#grSapphire)" opacity="0.2">
<animate attributeName="opacity" values="0.1;0.3;0.1" dur="5s" repeatCount="indefinite"/>
</path>
<animateTransform attributeName="transform" type="translate" values="50,30;55,22;50,30" dur="9s" repeatCount="indefinite"/>
</g>
<!-- Shard 3 - small, faster -->
<g transform="translate(-40, 50)" filter="url(#glowSm)">
<path d="M 0,-6 L 5,0 L 0,8 L -4,2 Z" fill="url(#grEmerald)" opacity="0.2">
<animate attributeName="opacity" values="0.1;0.25;0.1" dur="4s" repeatCount="indefinite"/>
</path>
<animateTransform attributeName="transform" type="translate" values="-40,50;-35,42;-40,50" dur="7s" repeatCount="indefinite"/>
</g>
<!-- Shard 4 - tiny mote -->
<g transform="translate(30, -20)" filter="url(#shimmer)">
<path d="M 0,-4 L 3,0 L 0,4 L -3,0 Z" fill="url(#grRose)" opacity="0.3">
<animate attributeName="opacity" values="0.15;0.4;0.15" dur="3s" repeatCount="indefinite"/>
</path>
<animateTransform attributeName="transform" type="translate" values="30,-20;33,-25;30,-20" dur="5s" repeatCount="indefinite"/>
</g>
<!-- Shard 5 - amber fleck -->
<g transform="translate(-60, -10)" filter="url(#shimmer)">
<path d="M 0,-5 L 4,0 L 0,5 L -4,0 Z" fill="url(#grAmber)" opacity="0.2">
<animate attributeName="opacity" values="0.1;0.3;0.1" dur="6s" repeatCount="indefinite"/>
</path>
<animateTransform attributeName="transform" type="translate" values="-60,-10;-58,-16;-60,-10" dur="8s" repeatCount="indefinite"/>
</g>
<text x="0" y="100" class="lbl">Scattered across backgrounds, parallax layers</text>
</g>
<!-- 3. PRISMATIC DIVIDER -->
<text x="24" y="274" class="section-lbl">PRISMATIC DIVIDER</text>
<line x1="24" y1="280" x2="670" y2="280" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(350, 320)" filter="url(#glowMd)">
<!-- Main prismatic line -->
<line x1="-280" y1="0" x2="280" y2="0" stroke="url(#prismaticH)" stroke-width="1.5" opacity="0.6"/>
<!-- Glow underneath -->
<line x1="-280" y1="0" x2="280" y2="0" stroke="url(#prismaticH)" stroke-width="4" opacity="0.15"/>
<!-- Center diamond accent -->
<path d="M 0,-6 L 6,0 L 0,6 L -6,0 Z" fill="url(#grAmethyst)" opacity="0.7" filter="url(#shimmer)">
<animate attributeName="opacity" values="0.5;0.8;0.5" dur="3s" repeatCount="indefinite"/>
</path>
<path d="M 0,-6 L 6,0 L 0,0 Z" fill="#fff" opacity="0.15"/>
<!-- Shimmer sweep -->
<rect x="-280" y="-1" width="40" height="2" fill="#fff" opacity="0" rx="1">
<animate attributeName="opacity" values="0;0.3;0" dur="3s" repeatCount="indefinite"/>
<animate attributeName="x" values="-280;280" dur="3s" repeatCount="indefinite"/>
</rect>
<!-- End shards -->
<g transform="translate(-280, 0)" filter="url(#glowSm)">
<path d="M 0,-3 L 3,0 L 0,3 L -3,0 Z" fill="#8B5CF6" opacity="0.4"/>
</g>
<g transform="translate(280, 0)" filter="url(#glowSm)">
<path d="M 0,-3 L 3,0 L 0,3 L -3,0 Z" fill="#EC4899" opacity="0.4"/>
</g>
<text x="0" y="30" class="lbl">Section divider with cycling prismatic gradient</text>
</g>
<!-- 4. CORNER ACCENTS -->
<text x="24" y="384" class="section-lbl">CORNER ACCENTS</text>
<line x1="24" y1="390" x2="670" y2="390" stroke="#1C2240" stroke-width="0.5"/>
<!-- Demo card with corner accents -->
<g transform="translate(100, 420)">
<rect width="200" height="120" rx="12" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.8"/>
<!-- Top-left corner -->
<g filter="url(#glowSm)">
<path d="M 0,20 L 0,0 L 20,0" fill="none" stroke="#8B5CF6" stroke-width="1" opacity="0.5"/>
<path d="M 0,-2 L 4,2 L 0,6 L -4,2 Z" fill="url(#grAmethyst)" opacity="0.6" transform="translate(0,0)"/>
</g>
<!-- Top-right corner -->
<g filter="url(#glowSm)" transform="translate(200, 0)">
<path d="M 0,20 L 0,0 L -20,0" fill="none" stroke="#3B82F6" stroke-width="1" opacity="0.5"/>
<path d="M 0,-2 L 4,2 L 0,6 L -4,2 Z" fill="url(#grSapphire)" opacity="0.6"/>
</g>
<!-- Bottom-left corner -->
<g filter="url(#glowSm)" transform="translate(0, 120)">
<path d="M 0,-20 L 0,0 L 20,0" fill="none" stroke="#10B981" stroke-width="1" opacity="0.5"/>
<path d="M 0,-2 L 4,2 L 0,6 L -4,2 Z" fill="url(#grEmerald)" opacity="0.6"/>
</g>
<!-- Bottom-right corner -->
<g filter="url(#glowSm)" transform="translate(200, 120)">
<path d="M 0,-20 L 0,0 L -20,0" fill="none" stroke="#F59E0B" stroke-width="1" opacity="0.5"/>
<path d="M 0,-2 L 4,2 L 0,6 L -4,2 Z" fill="url(#grAmber)" opacity="0.6"/>
</g>
<text x="100" y="65" font-size="10" fill="#475569" text-anchor="middle">Card Content</text>
<text x="100" y="152" class="lbl">Corner accent marks on cards</text>
</g>
<!-- 5. HERO SHARD BURST -->
<g transform="translate(475, 490)">
<text x="0" y="-70" class="section-lbl" text-anchor="middle">HERO SHARD BURST</text>
<!-- Central glow -->
<circle r="30" fill="#8B5CF6" opacity="0.08" filter="url(#glowXl)">
<animate attributeName="r" values="25;35;25" dur="5s" repeatCount="indefinite"/>
</circle>
<!-- Radiating shards -->
<g filter="url(#glowMd)">
<path d="M 0,-40 L 4,-20 L 0,-15 L -4,-20 Z" fill="url(#grAmethyst)" opacity="0.5">
<animate attributeName="opacity" values="0.3;0.6;0.3" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 35,-20 L 20,-16 L 15,-20 L 20,-24 Z" fill="url(#grSapphire)" opacity="0.4" transform="rotate(30)">
<animate attributeName="opacity" values="0.2;0.5;0.2" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 22,4 L 18,0 L 22,-4 Z" fill="url(#grEmerald)" opacity="0.4">
<animate attributeName="opacity" values="0.25;0.5;0.25" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 20,35 L 16,18 L 20,14 L 24,18 Z" fill="url(#grAmber)" opacity="0.35" transform="rotate(-20)">
<animate attributeName="opacity" values="0.2;0.45;0.2" dur="3.8s" repeatCount="indefinite"/>
</path>
<path d="M -35,20 L -18,16 L -14,20 L -18,24 Z" fill="url(#grRose)" opacity="0.35">
<animate attributeName="opacity" values="0.2;0.5;0.2" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M -20,-35 L -16,-18 L -20,-14 L -24,-18 Z" fill="url(#grIndigo)" opacity="0.4">
<animate attributeName="opacity" values="0.25;0.55;0.25" dur="3.5s" repeatCount="indefinite"/>
</path>
</g>
<!-- Orbiting mote -->
<g filter="url(#shimmer)">
<circle r="2" fill="#A78BFA" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-50 A50,50 0 1 1 -0.1,-50"/>
<animate attributeName="opacity" values="0;0.8;0;0;0" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#3B82F6" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-45 A45,45 0 1 0 -0.1,-45"/>
<animate attributeName="opacity" values="0;0;0.7;0;0" dur="6s" repeatCount="indefinite"/>
</circle>
</g>
<text x="0" y="80" class="lbl">Hero/splash background accent</text>
</g>
<!-- 6. SHARD CLUSTER -->
<text x="24" y="604" class="section-lbl">SHARD CLUSTER</text>
<line x1="24" y1="610" x2="670" y2="610" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(175, 690)">
<g filter="url(#glowMd)">
<!-- Primary large shard -->
<path d="M 0,-20 L 12,0 L 0,20 L -12,0 Z" fill="url(#grAmethyst)" opacity="0.5">
<animate attributeName="opacity" values="0.4;0.6;0.4" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-20 L 12,0 L 0,0 Z" fill="#fff" opacity="0.1"/>
</g>
<g filter="url(#glowSm)">
<!-- Secondary shard, offset -->
<path d="M 18,-12 L 26,-2 L 20,10 L 14,0 Z" fill="url(#grSapphire)" opacity="0.35">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4s" begin="0.5s" repeatCount="indefinite"/>
</path>
<!-- Tertiary small shard -->
<path d="M -16,8 L -10,14 L -14,22 L -20,16 Z" fill="url(#grEmerald)" opacity="0.3">
<animate attributeName="opacity" values="0.2;0.4;0.2" dur="3.5s" begin="1s" repeatCount="indefinite"/>
</path>
<!-- Tiny accent shards -->
<path d="M 8,-18 L 12,-14 L 10,-10 L 6,-14 Z" fill="url(#grAmber)" opacity="0.25"/>
<path d="M -20,-8 L -16,-12 L -12,-8 L -16,-4 Z" fill="url(#grRose)" opacity="0.2"/>
</g>
<text x="0" y="50" class="lbl">Decorative cluster for empty states, backgrounds</text>
</g>
<!-- 7. EDGE SHIMMER -->
<g transform="translate(475, 660)">
<text x="0" y="-34" class="section-lbl" text-anchor="middle">EDGE SHIMMER</text>
<!-- Demo card edge -->
<rect x="-80" y="-20" width="160" height="80" rx="10" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.8"/>
<!-- Left edge shimmer -->
<line x1="-80" y1="-18" x2="-80" y2="58" stroke="url(#prismaticH)" stroke-width="1.5" opacity="0.3"/>
<!-- Shimmer travel -->
<rect x="-81" y="-20" width="2" height="16" rx="1" fill="#fff" opacity="0">
<animate attributeName="opacity" values="0;0.4;0" dur="2.5s" repeatCount="indefinite"/>
<animate attributeName="y" values="-20;60" dur="2.5s" repeatCount="indefinite"/>
</rect>
<!-- Top edge subtle shimmer -->
<line x1="-78" y1="-20" x2="78" y2="-20" stroke="#8B5CF6" stroke-width="0.5" opacity="0.15"/>
<rect x="-78" y="-21" width="24" height="2" rx="1" fill="#C4B5FD" opacity="0">
<animate attributeName="opacity" values="0;0.25;0" dur="3s" repeatCount="indefinite"/>
<animate attributeName="x" values="-78;78" dur="3s" repeatCount="indefinite"/>
</rect>
<text x="0" y="20" font-size="10" fill="#475569" text-anchor="middle">Card Content</text>
<text x="0" y="90" class="lbl">Edge shimmer on focused/hovered cards</text>
</g>
<!-- 8. ORBITING MOTES (standalone) -->
<text x="24" y="784" class="section-lbl">ORBITING MOTES</text>
<line x1="24" y1="790" x2="670" y2="790" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(350, 840)" filter="url(#shimmer)">
<!-- Mote orbit paths (faint) -->
<circle r="30" fill="none" stroke="#1C2240" stroke-width="0.3" stroke-dasharray="2 4"/>
<circle r="22" fill="none" stroke="#1C2240" stroke-width="0.3" stroke-dasharray="2 4"/>
<!-- Orbiting motes -->
<circle r="2.5" fill="#A78BFA" opacity="0">
<animateMotion dur="5s" repeatCount="indefinite" path="M0,-30 A30,30 0 1 1 -0.1,-30"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="5s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#3B82F6" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-30 A30,30 0 1 0 -0.1,-30"/>
<animate attributeName="opacity" values="0;0;0.8;0;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#10B981" opacity="0">
<animateMotion dur="4s" repeatCount="indefinite" path="M0,-22 A22,22 0 1 1 -0.1,-22"/>
<animate attributeName="opacity" values="0;0.7;0;0.5;0" dur="4s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#F59E0B" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-22 A22,22 0 1 0 -0.1,-22"/>
<animate attributeName="opacity" values="0;0;0;0.9;0" dur="6s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#EC4899" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-30 A30,30 0 1 1 -0.1,-30" begin="2s"/>
<animate attributeName="opacity" values="0;0.8;0;0;0.5;0" dur="9s" repeatCount="indefinite"/>
</circle>
<text x="0" y="52" class="lbl">Floating motes around logos, loaders, hero elements</text>
</g>
<text x="350" y="874" font-size="8" fill="#334155" text-anchor="middle">Decorative elements use breathing animations, prismatic color cycling, glow filters from the soft-elegance visual language</text>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,755 @@
/* ============================================
KALEI DESIGN SYSTEM
Extracted from soft-elegance-final.svg
============================================ */
/* --- CSS Custom Properties (Design Tokens) --- */
:root {
/* Backgrounds */
--void: #050508;
--kalei-navy: #0A0E1A;
--deep-glass: #121628;
--twilight: #1C2240;
/* Jewel Tones */
--amethyst: #8B5CF6;
--amethyst-light: #A78BFA;
--amethyst-dark: #6D28D9;
--sapphire: #3B82F6;
--sapphire-light: #60A5FA;
--sapphire-dark: #1D4ED8;
--emerald: #10B981;
--emerald-light: #34D399;
--emerald-dark: #047857;
--ruby: #EF4444;
--amber: #F59E0B;
--amber-light: #FCD34D;
--amber-dark: #B45309;
--rose: #EC4899;
--rose-light: #F9A8D4;
--indigo: #6366F1;
--indigo-light: #818CF8;
/* Text */
--pure-light: #FFFFFF;
--soft-light: #E2E8F0;
--dim-light: #94A3B8;
--faint-light: #475569;
/* Prismatic Gradient */
--prismatic: linear-gradient(135deg, #8B5CF6, #3B82F6, #10B981, #F59E0B, #EC4899);
--prismatic-subtle: linear-gradient(135deg, rgba(139,92,246,0.15), rgba(59,130,246,0.15), rgba(16,185,129,0.15), rgba(245,158,11,0.15), rgba(236,72,153,0.15));
/* Typography */
--font-primary: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
--font-display: 'Space Grotesk', 'Inter', sans-serif;
/* Spacing */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
/* Radii */
--radius-sm: 8px;
--radius-md: 10px;
--radius-lg: 12px;
--radius-xl: 16px;
--radius-2xl: 20px;
--radius-full: 9999px;
/* Shadows (glow-based, not drop-shadow) */
--glow-amethyst: 0 0 20px rgba(139, 92, 246, 0.3);
--glow-sapphire: 0 0 20px rgba(59, 130, 246, 0.3);
--glow-emerald: 0 0 20px rgba(16, 185, 129, 0.3);
--glow-amber: 0 0 20px rgba(245, 158, 11, 0.3);
--glow-rose: 0 0 20px rgba(236, 72, 153, 0.3);
--glow-white: 0 0 16px rgba(255, 255, 255, 0.15);
/* Device frame */
--device-width: 390px;
--device-height: 844px;
--status-bar-height: 54px;
--tab-bar-height: 83px;
--nav-header-height: 56px;
}
/* --- Reset & Base --- */
* { margin: 0; padding: 0; box-sizing: border-box; }
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Space+Grotesk:wght@400;500;600;700&display=swap');
body {
background: #000;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: var(--font-primary);
color: var(--pure-light);
-webkit-font-smoothing: antialiased;
}
/* --- Device Frame --- */
.device-frame {
width: var(--device-width);
height: var(--device-height);
background: var(--void);
border-radius: 44px;
overflow: hidden;
position: relative;
box-shadow: 0 0 0 2px rgba(255,255,255,0.06), 0 20px 60px rgba(0,0,0,0.5);
display: flex;
flex-direction: column;
}
/* --- Status Bar --- */
.status-bar {
height: var(--status-bar-height);
padding: 14px 28px 0;
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
background: transparent;
position: relative;
z-index: 10;
}
.status-bar .time {
font-size: 15px;
font-weight: 600;
color: var(--pure-light);
}
.status-bar .icons {
display: flex;
gap: 6px;
align-items: center;
}
.status-bar .icons svg { width: 16px; height: 16px; }
/* --- Navigation Header --- */
.nav-header {
height: var(--nav-header-height);
padding: 0 var(--space-4);
display: flex;
align-items: center;
justify-content: space-between;
flex-shrink: 0;
position: relative;
z-index: 10;
}
.nav-header .nav-title {
font-size: 20px;
font-weight: 600;
color: var(--pure-light);
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.nav-header .nav-back {
display: flex;
align-items: center;
gap: 4px;
color: var(--amethyst-light);
font-size: 16px;
cursor: pointer;
text-decoration: none;
}
.nav-header .nav-back svg {
width: 20px;
height: 20px;
}
.nav-header .nav-action {
color: var(--dim-light);
cursor: pointer;
}
/* --- Screen Content Area --- */
.screen-content {
flex: 1;
overflow-y: auto;
padding: 0 var(--space-4);
position: relative;
}
.screen-content::-webkit-scrollbar { display: none; }
.screen-content.no-pad { padding: 0; }
.screen-content.centered {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
/* --- Tab Bar --- */
.tab-bar {
height: var(--tab-bar-height);
background: var(--kalei-navy);
border-top: 1px solid var(--twilight);
display: flex;
align-items: flex-start;
justify-content: space-around;
padding-top: 8px;
flex-shrink: 0;
position: relative;
z-index: 10;
}
.tab-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
cursor: pointer;
text-decoration: none;
min-width: 60px;
}
.tab-item svg {
width: 24px;
height: 24px;
}
.tab-item .tab-label {
font-size: 10px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.tab-item.inactive svg { fill: var(--dim-light); stroke: var(--dim-light); }
.tab-item.inactive .tab-label { color: var(--faint-light); }
.tab-item.active .tab-label { color: var(--pure-light); }
/* Active tab colors by type */
.tab-item.active[data-tab="turn"] svg { fill: var(--amethyst); stroke: var(--amethyst); }
.tab-item.active[data-tab="turn"] .tab-label { color: var(--amethyst-light); }
.tab-item.active[data-tab="mirror"] svg { fill: var(--amber); stroke: var(--amber); }
.tab-item.active[data-tab="mirror"] .tab-label { color: var(--amber-light); }
.tab-item.active[data-tab="lens"] svg { fill: var(--emerald); stroke: var(--emerald); }
.tab-item.active[data-tab="lens"] .tab-label { color: var(--emerald-light); }
.tab-item.active[data-tab="gallery"] svg { fill: var(--sapphire); stroke: var(--sapphire); }
.tab-item.active[data-tab="gallery"] .tab-label { color: var(--sapphire-light); }
.tab-item.active[data-tab="you"] svg { fill: var(--soft-light); stroke: var(--soft-light); }
.tab-item.active[data-tab="you"] .tab-label { color: var(--soft-light); }
/* --- Typography --- */
.display-xl { font-family: var(--font-display); font-size: 40px; font-weight: 700; line-height: 1.1; }
.display-lg { font-family: var(--font-display); font-size: 32px; font-weight: 700; line-height: 1.15; }
.display-md { font-size: 24px; font-weight: 600; line-height: 1.2; }
.heading { font-size: 20px; font-weight: 600; line-height: 1.3; }
.subheading { font-size: 16px; font-weight: 600; line-height: 1.4; }
.body-lg { font-size: 17px; font-weight: 400; line-height: 1.5; }
.body { font-size: 15px; font-weight: 400; line-height: 1.5; }
.body-sm { font-size: 13px; font-weight: 400; line-height: 1.5; }
.label { font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.06em; }
.text-pure { color: var(--pure-light); }
.text-soft { color: var(--soft-light); }
.text-dim { color: var(--dim-light); }
.text-faint { color: var(--faint-light); }
.text-amethyst { color: var(--amethyst-light); }
.text-sapphire { color: var(--sapphire-light); }
.text-emerald { color: var(--emerald-light); }
.text-amber { color: var(--amber-light); }
.text-rose { color: var(--rose-light); }
.text-prismatic {
background: var(--prismatic);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
/* --- Buttons --- */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--space-2);
font-family: var(--font-primary);
font-weight: 600;
border: none;
cursor: pointer;
transition: all 0.2s ease;
text-decoration: none;
}
.btn-primary {
height: 52px;
padding: 0 var(--space-6);
background: var(--amethyst);
color: var(--pure-light);
font-size: 16px;
border-radius: var(--radius-lg);
width: 100%;
box-shadow: var(--glow-amethyst);
}
.btn-primary:hover { background: var(--amethyst-light); }
.btn-primary.btn-emerald { background: var(--emerald); box-shadow: var(--glow-emerald); }
.btn-primary.btn-amber { background: var(--amber); box-shadow: var(--glow-amber); color: var(--void); }
.btn-primary.btn-rose { background: var(--rose); box-shadow: var(--glow-rose); }
.btn-secondary {
height: 44px;
padding: 0 var(--space-5);
background: var(--deep-glass);
color: var(--soft-light);
font-size: 15px;
border-radius: var(--radius-md);
border: 1px solid var(--twilight);
width: 100%;
}
.btn-secondary:hover { background: var(--twilight); }
.btn-ghost {
height: 40px;
padding: 0 var(--space-4);
background: transparent;
color: var(--amethyst-light);
font-size: 15px;
border-radius: var(--radius-md);
}
.btn-ghost:hover { background: rgba(139, 92, 246, 0.1); }
.btn-sm { height: 36px; font-size: 13px; padding: 0 var(--space-3); border-radius: var(--radius-sm); }
.btn-icon { width: 44px; height: 44px; padding: 0; border-radius: var(--radius-md); }
.btn-disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
/* --- Inputs --- */
.input-field {
width: 100%;
height: 48px;
background: var(--deep-glass);
border: 1px solid var(--twilight);
border-radius: var(--radius-md);
padding: 0 14px;
font-family: var(--font-primary);
font-size: 16px;
color: var(--pure-light);
outline: none;
transition: border-color 0.2s;
}
.input-field::placeholder { color: var(--faint-light); }
.input-field:focus { border-color: var(--amethyst); }
.textarea-field {
width: 100%;
min-height: 120px;
background: var(--deep-glass);
border: 1px solid var(--twilight);
border-radius: var(--radius-lg);
padding: 14px;
font-family: var(--font-primary);
font-size: 17px;
line-height: 1.5;
color: var(--pure-light);
outline: none;
resize: none;
transition: border-color 0.2s;
}
.textarea-field::placeholder { color: var(--faint-light); }
.textarea-field:focus { border-color: var(--amethyst); }
.input-label {
font-size: 13px;
font-weight: 500;
color: var(--dim-light);
margin-bottom: var(--space-2);
display: block;
}
/* --- Cards --- */
.card {
background: var(--kalei-navy);
border: 1px solid rgba(28, 34, 64, 0.6);
border-radius: var(--radius-xl);
padding: var(--space-4);
position: relative;
overflow: hidden;
}
.card-elevated {
background: var(--deep-glass);
border-color: var(--twilight);
}
.card-pattern {
padding: 0;
overflow: hidden;
}
.card-pattern .pattern-visual {
height: 160px;
display: flex;
align-items: center;
justify-content: center;
background: var(--void);
border-radius: var(--radius-xl) var(--radius-xl) 0 0;
position: relative;
overflow: hidden;
}
.card-pattern .pattern-content {
padding: var(--space-3) var(--space-4);
}
.card-action {
display: flex;
align-items: center;
gap: var(--space-3);
padding: var(--space-3) var(--space-4);
cursor: pointer;
transition: background 0.15s;
}
.card-action:hover { background: var(--deep-glass); }
.card-action .card-action-icon {
width: 40px;
height: 40px;
border-radius: var(--radius-md);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.card-action .card-action-text { flex: 1; }
.card-action .card-action-chevron { color: var(--faint-light); }
/* --- Chips / Tags --- */
.chip {
display: inline-flex;
align-items: center;
gap: var(--space-1);
height: 28px;
padding: 0 var(--space-3);
border-radius: var(--radius-full);
font-size: 12px;
font-weight: 500;
}
.chip-amethyst { background: rgba(139,92,246,0.15); color: var(--amethyst-light); }
.chip-sapphire { background: rgba(59,130,246,0.15); color: var(--sapphire-light); }
.chip-emerald { background: rgba(16,185,129,0.15); color: var(--emerald-light); }
.chip-amber { background: rgba(245,158,11,0.15); color: var(--amber-light); }
.chip-rose { background: rgba(236,72,153,0.15); color: var(--rose-light); }
/* --- Fragment Highlight --- */
.fragment-highlight {
position: relative;
display: inline;
}
.fragment-highlight::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
right: 0;
height: 3px;
background: var(--amber);
border-radius: 2px;
opacity: 0.6;
box-shadow: 0 0 8px rgba(245, 158, 11, 0.4);
animation: fragmentGlow 2s ease-in-out infinite;
}
.fragment-icon {
display: inline-flex;
align-items: center;
margin-left: 4px;
color: var(--amber);
animation: fragmentPulse 2s ease-in-out infinite;
}
/* --- Chat Bubbles (Mirror) --- */
.chat-bubble {
max-width: 80%;
padding: var(--space-3) var(--space-4);
border-radius: var(--radius-xl);
margin-bottom: var(--space-3);
font-size: 16px;
line-height: 1.5;
}
.chat-bubble.user {
background: rgba(139, 92, 246, 0.15);
border: 1px solid rgba(139, 92, 246, 0.2);
margin-left: auto;
border-bottom-right-radius: var(--space-1);
}
.chat-bubble.ai {
background: var(--kalei-navy);
border: 1px solid var(--twilight);
margin-right: auto;
border-bottom-left-radius: var(--space-1);
color: var(--soft-light);
}
/* --- Progress Ring --- */
.progress-ring {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
}
.progress-ring svg { transform: rotate(-90deg); }
.progress-ring .progress-text {
position: absolute;
font-size: 20px;
font-weight: 700;
color: var(--pure-light);
}
.progress-ring .progress-label {
position: absolute;
top: 58%;
font-size: 11px;
color: var(--dim-light);
text-transform: uppercase;
letter-spacing: 0.05em;
}
/* --- Modals --- */
.modal-overlay {
position: absolute;
inset: 0;
background: rgba(5, 5, 8, 0.7);
backdrop-filter: blur(8px);
display: flex;
align-items: flex-end;
justify-content: center;
z-index: 50;
}
.modal-overlay.centered { align-items: center; }
.modal-sheet {
width: 100%;
max-height: 70%;
background: var(--kalei-navy);
border-radius: var(--radius-2xl) var(--radius-2xl) 0 0;
padding: var(--space-6) var(--space-4) var(--space-8);
position: relative;
}
.modal-sheet .modal-handle {
width: 36px;
height: 4px;
background: var(--twilight);
border-radius: var(--radius-full);
margin: 0 auto var(--space-5);
}
.modal-card {
width: 340px;
background: var(--kalei-navy);
border: 1px solid var(--twilight);
border-radius: var(--radius-2xl);
padding: var(--space-6);
}
/* --- Dividers --- */
.divider {
height: 1px;
background: var(--twilight);
margin: var(--space-4) 0;
}
/* --- Section Headers --- */
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--space-3);
}
.section-header .section-title {
font-size: 13px;
font-weight: 600;
color: var(--dim-light);
text-transform: uppercase;
letter-spacing: 0.06em;
}
.section-header .section-action {
font-size: 13px;
color: var(--amethyst-light);
cursor: pointer;
}
/* --- Stat Block --- */
.stat-row {
display: flex;
gap: var(--space-3);
}
.stat-block {
flex: 1;
background: var(--deep-glass);
border-radius: var(--radius-lg);
padding: var(--space-3);
text-align: center;
}
.stat-value {
font-size: 24px;
font-weight: 700;
color: var(--pure-light);
}
.stat-label {
font-size: 11px;
color: var(--dim-light);
margin-top: 2px;
}
/* --- Toggle / Radio --- */
.radio-option {
display: flex;
align-items: center;
gap: var(--space-3);
padding: var(--space-3) var(--space-4);
background: var(--deep-glass);
border: 1px solid var(--twilight);
border-radius: var(--radius-lg);
cursor: pointer;
margin-bottom: var(--space-2);
transition: all 0.2s;
}
.radio-option.selected {
border-color: var(--amethyst);
background: rgba(139, 92, 246, 0.08);
}
.radio-dot {
width: 20px;
height: 20px;
border-radius: 50%;
border: 2px solid var(--twilight);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.radio-option.selected .radio-dot {
border-color: var(--amethyst);
}
.radio-option.selected .radio-dot::after {
content: '';
width: 10px;
height: 10px;
border-radius: 50%;
background: var(--amethyst);
}
/* --- Step Progress --- */
.step-progress {
display: flex;
align-items: center;
justify-content: center;
gap: var(--space-2);
padding: var(--space-3) 0;
}
.step-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--twilight);
}
.step-dot.active { background: var(--amethyst); box-shadow: 0 0 8px rgba(139, 92, 246, 0.4); }
.step-dot.completed { background: var(--emerald); }
.step-label {
font-size: 12px;
color: var(--dim-light);
margin-left: var(--space-2);
}
/* --- Reframe Blocks --- */
.reframe-block {
padding: var(--space-4);
border-radius: var(--radius-lg);
margin-bottom: var(--space-3);
border-left: 3px solid;
}
.reframe-block.amethyst { border-color: var(--amethyst); background: rgba(139,92,246,0.06); }
.reframe-block.sapphire { border-color: var(--sapphire); background: rgba(59,130,246,0.06); }
.reframe-block.emerald { border-color: var(--emerald); background: rgba(16,185,129,0.06); }
.reframe-block .reframe-label {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
margin-bottom: var(--space-2);
}
.reframe-block.amethyst .reframe-label { color: var(--amethyst-light); }
.reframe-block.sapphire .reframe-label { color: var(--sapphire-light); }
.reframe-block.emerald .reframe-label { color: var(--emerald-light); }
.reframe-block .reframe-text {
font-size: 15px;
line-height: 1.5;
color: var(--soft-light);
}
/* --- Animations (from soft-elegance SVG language) --- */
@keyframes breathing {
0%, 100% { opacity: 0.6; transform: scale(1); }
50% { opacity: 1; transform: scale(1.03); }
}
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
@keyframes pulse {
0%, 100% { opacity: 0.7; }
50% { opacity: 1; }
}
@keyframes fragmentGlow {
0%, 100% { opacity: 0.4; }
50% { opacity: 0.8; }
}
@keyframes fragmentPulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes slideUp {
from { transform: translateY(100%); }
to { transform: translateY(0); }
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes prismaticShift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
/* Loading shimmer effect */
.loading-shimmer {
background: linear-gradient(90deg, var(--deep-glass) 25%, rgba(28,34,64,0.6) 50%, var(--deep-glass) 75%);
background-size: 200% 100%;
animation: shimmer 1.5s ease-in-out infinite;
border-radius: var(--radius-md);
}
/* Breathing aura (decorative background) */
.aura {
position: absolute;
border-radius: 50%;
filter: blur(60px);
opacity: 0.15;
animation: breathing 6s ease-in-out infinite;
pointer-events: none;
}
/* --- Utilities --- */
.mt-1 { margin-top: var(--space-1); }
.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mt-6 { margin-top: var(--space-6); }
.mt-8 { margin-top: var(--space-8); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }
.mb-6 { margin-bottom: var(--space-6); }
.gap-2 { gap: var(--space-2); }
.gap-3 { gap: var(--space-3); }
.gap-4 { gap: var(--space-4); }
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-center { justify-content: center; }
.justify-between { justify-content: space-between; }
.text-center { text-align: center; }
.w-full { width: 100%; }
.relative { position: relative; }
.overflow-hidden { overflow: hidden; }

View File

@ -0,0 +1,199 @@
<svg viewBox="0 0 700 700" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grAmethyst" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#C4B5FD"/><stop offset="100%" stop-color="#7C3AED"/>
</linearGradient>
<linearGradient id="grSapphire" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#93C5FD"/><stop offset="100%" stop-color="#2563EB"/>
</linearGradient>
<linearGradient id="grEmerald" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#6EE7B7"/><stop offset="100%" stop-color="#059669"/>
</linearGradient>
<linearGradient id="grAmber" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FDE68A"/><stop offset="100%" stop-color="#D97706"/>
</linearGradient>
<linearGradient id="prismaticH" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#8B5CF6"/><stop offset="25%" stop-color="#3B82F6"/><stop offset="50%" stop-color="#10B981"/><stop offset="75%" stop-color="#F59E0B"/><stop offset="100%" stop-color="#EC4899"/>
</linearGradient>
<filter id="glowSm" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="1.5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowMd" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<style>
text { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; }
.lbl { font-size: 9px; fill: #94A3B8; text-anchor: middle; font-weight: 500; }
.section-lbl { font-size: 11px; fill: #64748B; font-weight: 600; letter-spacing: 0.08em; }
.chrome-text { font-size: 10px; fill: #E2E8F0; font-weight: 600; }
</style>
</defs>
<rect width="700" height="700" fill="#050508"/>
<text x="350" y="28" font-size="13" font-weight="700" fill="#94A3B8" text-anchor="middle" letter-spacing="0.12em">DEVICE CHROME ELEMENTS</text>
<text x="350" y="44" font-size="9" fill="#475569" text-anchor="middle">Status bar, tab bar, nav header, keyboard, device frame, modal scrim, toast, input accessory</text>
<!-- 1. STATUS BAR (iPhone 14 style) -->
<text x="24" y="74" class="section-lbl">STATUS BAR</text>
<line x1="24" y1="80" x2="670" y2="80" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(350, 110)">
<rect x="-195" y="-15" width="390" height="30" fill="#050508"/>
<!-- Time -->
<text x="-170" y="3" font-size="12" fill="#E2E8F0" font-weight="600">9:41</text>
<!-- Dynamic island -->
<rect x="-40" y="-8" width="80" height="16" rx="8" fill="#000"/>
<!-- Right side indicators -->
<!-- Signal -->
<g transform="translate(130, -4)">
<rect x="0" y="4" width="3" height="4" rx="0.5" fill="#E2E8F0" opacity="0.4"/>
<rect x="4" y="2" width="3" height="6" rx="0.5" fill="#E2E8F0" opacity="0.6"/>
<rect x="8" y="0" width="3" height="8" rx="0.5" fill="#E2E8F0" opacity="0.8"/>
<rect x="12" y="-2" width="3" height="10" rx="0.5" fill="#E2E8F0"/>
</g>
<!-- WiFi -->
<g transform="translate(152, 0)">
<path d="M 0,-4 C 3,-4 5,-2 6,0" fill="none" stroke="#E2E8F0" stroke-width="1.2" stroke-linecap="round"/>
<path d="M -2,-1 C 2,-1 4,0 5,2" fill="none" stroke="#E2E8F0" stroke-width="1" stroke-linecap="round" opacity="0.8"/>
<circle cx="2" cy="3" r="1" fill="#E2E8F0"/>
</g>
<!-- Battery -->
<g transform="translate(166, -4)">
<rect x="0" y="0" width="22" height="9" rx="2" fill="none" stroke="#E2E8F0" stroke-width="1" opacity="0.5"/>
<rect x="22" y="2" width="2" height="5" rx="1" fill="#E2E8F0" opacity="0.3"/>
<rect x="1.5" y="1.5" width="16" height="6" rx="1" fill="#10B981" opacity="0.9"/>
</g>
<text x="0" y="30" class="lbl">iOS Status Bar — 390px wide, #050508 background</text>
</g>
<!-- 2. NAV HEADER -->
<text x="24" y="164" class="section-lbl">NAVIGATION HEADER</text>
<line x1="24" y1="170" x2="670" y2="170" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(350, 208)">
<rect x="-195" y="-22" width="390" height="44" fill="#0A0E1A"/>
<line x1="-195" y1="22" x2="195" y2="22" stroke="#1C2240" stroke-width="0.5"/>
<!-- Back chevron -->
<path d="M -175,-2 L -170,-7 M -175,-2 L -170,3" fill="none" stroke="#8B5CF6" stroke-width="1.5" stroke-linecap="round"/>
<!-- Title -->
<text x="0" y="4" font-size="14" fill="#E2E8F0" font-weight="700" text-anchor="middle" font-family="'Space Grotesk', sans-serif">Mirror</text>
<!-- Right action (settings gear outline) -->
<circle cx="172" cy="0" r="7" fill="none" stroke="#94A3B8" stroke-width="1"/>
<circle cx="172" cy="0" r="2" fill="none" stroke="#94A3B8" stroke-width="0.8"/>
<text x="0" y="44" class="lbl">Nav Header — back chevron, centered title, right action</text>
</g>
<!-- 3. TAB BAR FRAME -->
<text x="24" y="280" class="section-lbl">TAB BAR FRAME</text>
<line x1="24" y1="286" x2="670" y2="286" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(350, 330)">
<rect x="-195" y="-28" width="390" height="56" fill="#0A0E1A"/>
<!-- Top border with subtle prismatic -->
<line x1="-195" y1="-28" x2="195" y2="-28" stroke="url(#prismaticH)" stroke-width="0.5" opacity="0.3"/>
<!-- 5 tab slots -->
<g font-size="8" fill="#475569" text-anchor="middle" font-weight="500">
<!-- Turn (active) -->
<g transform="translate(-156, 0)">
<g filter="url(#glowSm)">
<path d="M 0,-10 L 8,0 L 0,10 L -8,0 Z" fill="url(#grAmethyst)" opacity="0.8"/>
<path d="M 0,-10 L 8,0 L 0,0 Z" fill="#fff" opacity="0.15"/>
</g>
<text x="0" y="20" fill="#A78BFA" font-weight="600">Turn</text>
</g>
<!-- Mirror (inactive) -->
<g transform="translate(-78, 0)">
<path d="M 0,-6 L 4,-3 L 6,3 L 0,7 L -6,3 L -4,-3 Z" fill="none" stroke="#475569" stroke-width="0.8"/>
<text x="0" y="20">Mirror</text>
</g>
<!-- Lens (inactive) -->
<g transform="translate(0, 0)">
<circle r="7" fill="none" stroke="#475569" stroke-width="0.8"/>
<circle r="3" fill="none" stroke="#475569" stroke-width="0.5"/>
<text x="0" y="20">Lens</text>
</g>
<!-- Gallery (inactive) -->
<g transform="translate(78, 0)">
<rect x="-6" y="-6" width="5" height="5" rx="1" fill="none" stroke="#475569" stroke-width="0.7"/>
<rect x="1" y="-6" width="5" height="5" rx="1" fill="none" stroke="#475569" stroke-width="0.7"/>
<rect x="-6" y="1" width="5" height="5" rx="1" fill="none" stroke="#475569" stroke-width="0.7"/>
<rect x="1" y="1" width="5" height="5" rx="1" fill="none" stroke="#475569" stroke-width="0.7"/>
<text x="0" y="20">Gallery</text>
</g>
<!-- You (inactive) -->
<g transform="translate(156, 0)">
<circle r="6" fill="none" stroke="#475569" stroke-width="0.8"/>
<circle r="2.5" fill="none" stroke="#475569" stroke-width="0.6" cy="-1"/>
<text x="0" y="20">You</text>
</g>
</g>
<!-- Home indicator -->
<rect x="-50" y="30" width="100" height="4" rx="2" fill="#475569" opacity="0.3"/>
<text x="0" y="52" class="lbl">Tab Bar — 5 tabs, prismatic top border, home indicator</text>
</g>
<!-- 4. MODAL SCRIM -->
<text x="24" y="410" class="section-lbl">MODAL SCRIM AND TOAST</text>
<line x1="24" y1="416" x2="670" y2="416" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(200, 500)">
<!-- Scrim background -->
<rect x="-100" y="-50" width="200" height="100" rx="4" fill="#050508" opacity="0.7"/>
<rect x="-100" y="-50" width="200" height="100" rx="4" fill="none" stroke="#1C2240" stroke-width="0.5"/>
<!-- Modal card on top -->
<rect x="-70" y="-30" width="140" height="60" rx="12" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.8"/>
<!-- Grab handle -->
<rect x="-16" y="-26" width="32" height="3" rx="1.5" fill="#475569" opacity="0.4"/>
<text x="0" y="0" font-size="10" fill="#E2E8F0" text-anchor="middle" font-weight="600">Modal Content</text>
<text x="0" y="14" font-size="8" fill="#64748B" text-anchor="middle">60% backdrop blur scrim</text>
<text x="0" y="68" class="lbl">Modal Scrim — #050508 at 70% + backdrop blur</text>
</g>
<!-- Toast -->
<g transform="translate(530, 480)">
<g filter="url(#glowSm)">
<rect x="-90" y="-16" width="180" height="32" rx="16" fill="#121628" stroke="#10B981" stroke-width="0.6"/>
<!-- Emerald fragment -->
<g transform="translate(-68, 0)">
<path d="M 0,-5 L 5,0 L 0,5 L -5,0 Z" fill="url(#grEmerald)" opacity="0.8"/>
<path d="M 0,-5 L 5,0 L 0,0 Z" fill="#fff" opacity="0.15"/>
</g>
<text x="4" y="4" font-size="10" fill="#E2E8F0" text-anchor="middle" font-weight="500">Turn saved</text>
</g>
<text x="0" y="34" class="lbl">Success Toast — pill shape, emerald accent</text>
</g>
<!-- Error Toast -->
<g transform="translate(530, 540)">
<g filter="url(#glowSm)">
<rect x="-90" y="-16" width="180" height="32" rx="16" fill="#121628" stroke="#EF4444" stroke-width="0.6"/>
<g transform="translate(-68, 0)">
<path d="M 0,-5 L 5,0 L 0,5 L -5,0 Z" fill="#EF4444" opacity="0.8"/>
</g>
<text x="4" y="4" font-size="10" fill="#E2E8F0" text-anchor="middle" font-weight="500">Connection lost</text>
</g>
<text x="0" y="34" class="lbl">Error Toast — pill shape, ruby accent</text>
</g>
<!-- 5. INPUT ACCESSORY / KEYBOARD TOP -->
<text x="24" y="600" class="section-lbl">INPUT ACCESSORY</text>
<line x1="24" y1="606" x2="670" y2="606" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(350, 648)">
<rect x="-195" y="-20" width="390" height="40" fill="#0A0E1A"/>
<line x1="-195" y1="-20" x2="195" y2="-20" stroke="#1C2240" stroke-width="0.5"/>
<!-- Text input area -->
<rect x="-180" y="-12" width="310" height="24" rx="12" fill="#121628" stroke="#1C2240" stroke-width="0.5"/>
<text x="-168" y="3" font-size="10" fill="#475569">Type your thought...</text>
<!-- Send button -->
<g transform="translate(165, 0)" filter="url(#glowSm)">
<circle r="12" fill="url(#grAmethyst)" opacity="0.8"/>
<path d="M -3,-3 L 4,0 L -3,3" fill="none" stroke="#fff" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<text x="0" y="36" class="lbl">Input Accessory Bar — text field + send button, above keyboard</text>
</g>
<text x="350" y="692" font-size="8" fill="#334155" text-anchor="middle">Device chrome at 390x844px (iPhone 14) — all elements use Kalei dark theme with jewel tone accents</text>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,250 @@
<svg viewBox="0 0 700 680" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grAmethyst" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#C4B5FD"/><stop offset="100%" stop-color="#7C3AED"/>
</linearGradient>
<linearGradient id="grSapphire" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#93C5FD"/><stop offset="100%" stop-color="#2563EB"/>
</linearGradient>
<linearGradient id="grEmerald" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#6EE7B7"/><stop offset="100%" stop-color="#059669"/>
</linearGradient>
<linearGradient id="grAmber" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FDE68A"/><stop offset="100%" stop-color="#D97706"/>
</linearGradient>
<linearGradient id="grRose" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBCFE8"/><stop offset="100%" stop-color="#DB2777"/>
</linearGradient>
<linearGradient id="grIndigo" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#A5B4FC"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<filter id="glowSm" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="1.5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowMd" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowLg" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<style>
text { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; }
.lbl { font-size: 9px; fill: #94A3B8; text-anchor: middle; font-weight: 500; }
.section-lbl { font-size: 11px; fill: #64748B; font-weight: 600; letter-spacing: 0.08em; }
</style>
</defs>
<rect width="700" height="680" fill="#050508"/>
<text x="350" y="28" font-size="13" font-weight="700" fill="#94A3B8" text-anchor="middle" letter-spacing="0.12em">EVIDENCE WALL MOSAIC</text>
<text x="350" y="44" font-size="9" fill="#475569" text-anchor="middle">5 tile shapes, 3 mosaic stages (early/mid/full), connection lines, empty state</text>
<!-- TILE SHAPES -->
<text x="24" y="74" class="section-lbl">TILE SHAPES</text>
<line x1="24" y1="80" x2="670" y2="80" stroke="#1C2240" stroke-width="0.5"/>
<!-- Tile 1: Diamond -->
<g transform="translate(80, 130)">
<g filter="url(#glowMd)">
<path d="M 0,-24 L 24,0 L 0,24 L -24,0 Z" fill="#121628" stroke="#8B5CF6" stroke-width="0.8"/>
<path d="M 0,-24 L 24,0 L 0,0 Z" fill="#8B5CF6" opacity="0.06"/>
<!-- Inner fragment -->
<path d="M 0,-8 L 8,0 L 0,8 L -8,0 Z" fill="url(#grAmethyst)" opacity="0.5" filter="url(#glowSm)"/>
<path d="M 0,-8 L 8,0 L 0,0 Z" fill="#fff" opacity="0.1"/>
</g>
<text x="0" y="44" class="lbl">Diamond</text>
</g>
<!-- Tile 2: Tall Hex -->
<g transform="translate(200, 130)">
<g filter="url(#glowMd)">
<path d="M 0,-28 L 20,-14 L 20,14 L 0,28 L -20,14 L -20,-14 Z" fill="#121628" stroke="#3B82F6" stroke-width="0.8"/>
<path d="M 0,-28 L 20,-14 L 0,0 L -20,-14 Z" fill="#3B82F6" opacity="0.05"/>
<path d="M 0,-10 L 10,0 L 0,10 L -10,0 Z" fill="url(#grSapphire)" opacity="0.4" filter="url(#glowSm)"/>
</g>
<text x="0" y="48" class="lbl">Tall Hex</text>
</g>
<!-- Tile 3: Wide Rectangle -->
<g transform="translate(340, 130)">
<g filter="url(#glowMd)">
<rect x="-30" y="-18" width="60" height="36" rx="4" fill="#121628" stroke="#10B981" stroke-width="0.8"/>
<rect x="-30" y="-18" width="60" height="18" rx="4" fill="#10B981" opacity="0.04"/>
<path d="M -8,-6 L 0,-12 L 8,-6 L 0,6 Z" fill="url(#grEmerald)" opacity="0.45" filter="url(#glowSm)"/>
</g>
<text x="0" y="38" class="lbl">Wide Rect</text>
</g>
<!-- Tile 4: Pentagon -->
<g transform="translate(470, 130)">
<g filter="url(#glowMd)">
<path d="M 0,-24 L 23,-7 L 14,20 L -14,20 L -23,-7 Z" fill="#121628" stroke="#F59E0B" stroke-width="0.8"/>
<path d="M 0,-24 L 23,-7 L 0,0 L -23,-7 Z" fill="#F59E0B" opacity="0.05"/>
<path d="M 0,-8 L 8,0 L 0,8 L -8,0 Z" fill="url(#grAmber)" opacity="0.45" filter="url(#glowSm)"/>
</g>
<text x="0" y="42" class="lbl">Pentagon</text>
</g>
<!-- Tile 5: Triangle -->
<g transform="translate(600, 130)">
<g filter="url(#glowMd)">
<path d="M 0,-26 L 24,18 L -24,18 Z" fill="#121628" stroke="#EC4899" stroke-width="0.8"/>
<path d="M 0,-26 L 24,18 L 0,0 Z" fill="#EC4899" opacity="0.05"/>
<path d="M 0,-6 L 6,4 L -6,4 Z" fill="url(#grRose)" opacity="0.45" filter="url(#glowSm)"/>
</g>
<text x="0" y="42" class="lbl">Triangle</text>
</g>
<!-- MOSAIC STAGES -->
<text x="24" y="210" class="section-lbl">MOSAIC STAGES</text>
<line x1="24" y1="216" x2="670" y2="216" stroke="#1C2240" stroke-width="0.5"/>
<!-- Early Stage (3 tiles) -->
<g transform="translate(120, 320)">
<g filter="url(#glowSm)">
<!-- Tile A -->
<path d="M 0,-20 L 18,0 L 0,20 L -18,0 Z" fill="#121628" stroke="#8B5CF6" stroke-width="0.6"/>
<path d="M 0,-6 L 6,0 L 0,6 L -6,0 Z" fill="url(#grAmethyst)" opacity="0.4"/>
<!-- Tile B -->
<g transform="translate(30, 25)">
<rect x="-16" y="-10" width="32" height="20" rx="3" fill="#121628" stroke="#10B981" stroke-width="0.6"/>
<path d="M 0,-4 L 4,0 L 0,4 L -4,0 Z" fill="url(#grEmerald)" opacity="0.35"/>
</g>
<!-- Tile C -->
<g transform="translate(-25, 30)">
<path d="M 0,-14 L 14,8 L -14,8 Z" fill="#121628" stroke="#F59E0B" stroke-width="0.6"/>
<path d="M 0,-4 L 4,2 L -4,2 Z" fill="url(#grAmber)" opacity="0.35"/>
</g>
<!-- Connection lines -->
<line x1="10" y1="10" x2="22" y2="18" stroke="#1C2240" stroke-width="0.5" stroke-dasharray="2 3"/>
<line x1="-10" y1="10" x2="-18" y2="22" stroke="#1C2240" stroke-width="0.5" stroke-dasharray="2 3"/>
</g>
<text x="0" y="66" class="lbl">Early (3 tiles)</text>
</g>
<!-- Mid Stage (8 tiles) -->
<g transform="translate(350, 310)">
<g filter="url(#glowSm)">
<!-- Row 1 -->
<path d="M 0,-30 L 14,-16 L 0,-2 L -14,-16 Z" fill="#121628" stroke="#8B5CF6" stroke-width="0.5"/>
<path d="M 0,-20 L 4,-16 L 0,-12 L -4,-16 Z" fill="url(#grAmethyst)" opacity="0.4"/>
<g transform="translate(28, -22)">
<rect x="-12" y="-8" width="24" height="16" rx="2" fill="#121628" stroke="#3B82F6" stroke-width="0.5"/>
<path d="M 0,-3 L 3,0 L 0,3 L -3,0 Z" fill="url(#grSapphire)" opacity="0.35"/>
</g>
<g transform="translate(-28, -20)">
<path d="M 0,-12 L 10,6 L -10,6 Z" fill="#121628" stroke="#EC4899" stroke-width="0.5"/>
<path d="M 0,-4 L 3,2 L -3,2 Z" fill="url(#grRose)" opacity="0.35"/>
</g>
<!-- Row 2 -->
<g transform="translate(20, 8)">
<path d="M 0,-14 L 12,0 L 0,14 L -12,0 Z" fill="#121628" stroke="#10B981" stroke-width="0.5"/>
<path d="M 0,-4 L 4,0 L 0,4 L -4,0 Z" fill="url(#grEmerald)" opacity="0.35"/>
</g>
<g transform="translate(-20, 10)">
<path d="M 0,-12 L 10,-4 L 10,8 L -10,8 L -10,-4 Z" fill="#121628" stroke="#F59E0B" stroke-width="0.5"/>
<path d="M 0,-3 L 3,0 L 0,3 L -3,0 Z" fill="url(#grAmber)" opacity="0.35"/>
</g>
<!-- Row 3 -->
<g transform="translate(0, 30)">
<rect x="-14" y="-8" width="28" height="16" rx="2" fill="#121628" stroke="#6366F1" stroke-width="0.5"/>
<path d="M 0,-3 L 3,0 L 0,3 L -3,0 Z" fill="url(#grIndigo)" opacity="0.35"/>
</g>
<g transform="translate(30, 28)">
<path d="M 0,-10 L 8,4 L -8,4 Z" fill="#121628" stroke="#8B5CF6" stroke-width="0.5"/>
</g>
<g transform="translate(-32, 28)">
<path d="M 0,-10 L 10,0 L 0,10 L -10,0 Z" fill="#121628" stroke="#3B82F6" stroke-width="0.5"/>
</g>
<!-- Connection lines between tiles -->
<line x1="8" y1="-8" x2="18" y2="-16" stroke="#1C2240" stroke-width="0.4" stroke-dasharray="2 2"/>
<line x1="-8" y1="-10" x2="-20" y2="-14" stroke="#1C2240" stroke-width="0.4" stroke-dasharray="2 2"/>
<line x1="10" y1="6" x2="14" y2="4" stroke="#1C2240" stroke-width="0.4" stroke-dasharray="2 2"/>
<line x1="-10" y1="8" x2="-14" y2="8" stroke="#1C2240" stroke-width="0.4" stroke-dasharray="2 2"/>
</g>
<text x="0" y="66" class="lbl">Mid (8 tiles, connections forming)</text>
</g>
<!-- Full Stage (dense mosaic) -->
<g transform="translate(580, 305)">
<g filter="url(#glowMd)">
<!-- Dense mosaic of tiles -->
<path d="M 0,-38 L 12,-26 L 0,-14 L -12,-26 Z" fill="#121628" stroke="#8B5CF6" stroke-width="0.5"/>
<path d="M 0,-30 L 4,-26 L 0,-22 L -4,-26 Z" fill="url(#grAmethyst)" opacity="0.5"/>
<g transform="translate(20, -30)">
<rect x="-8" y="-6" width="16" height="12" rx="2" fill="#121628" stroke="#3B82F6" stroke-width="0.4"/>
<path d="M 0,-2 L 2,0 L 0,2 L -2,0 Z" fill="url(#grSapphire)" opacity="0.4"/>
</g>
<g transform="translate(-20, -28)">
<path d="M 0,-8 L 8,4 L -8,4 Z" fill="#121628" stroke="#EC4899" stroke-width="0.4"/>
<path d="M 0,-3 L 2,1 L -2,1 Z" fill="url(#grRose)" opacity="0.35"/>
</g>
<g transform="translate(16, -12)">
<path d="M 0,-10 L 8,0 L 0,10 L -8,0 Z" fill="#121628" stroke="#10B981" stroke-width="0.4"/>
<path d="M 0,-3 L 3,0 L 0,3 L -3,0 Z" fill="url(#grEmerald)" opacity="0.4"/>
</g>
<g transform="translate(-18, -10)">
<path d="M 0,-8 L 7,-3 L 7,5 L -7,5 L -7,-3 Z" fill="#121628" stroke="#F59E0B" stroke-width="0.4"/>
<path d="M 0,-2 L 2,0 L 0,2 L -2,0 Z" fill="url(#grAmber)" opacity="0.4"/>
</g>
<g transform="translate(0, 6)">
<rect x="-10" y="-6" width="20" height="12" rx="2" fill="#121628" stroke="#6366F1" stroke-width="0.4"/>
<path d="M 0,-2 L 2,0 L 0,2 L -2,0 Z" fill="url(#grIndigo)" opacity="0.4"/>
</g>
<g transform="translate(-22, 8)">
<path d="M 0,-8 L 6,0 L 0,8 L -6,0 Z" fill="#121628" stroke="#8B5CF6" stroke-width="0.4"/>
</g>
<g transform="translate(22, 8)">
<path d="M 0,-6 L 6,4 L -6,4 Z" fill="#121628" stroke="#3B82F6" stroke-width="0.4"/>
</g>
<g transform="translate(10, 22)">
<path d="M 0,-8 L 8,0 L 0,8 L -8,0 Z" fill="#121628" stroke="#10B981" stroke-width="0.4"/>
<path d="M 0,-3 L 3,0 L 0,3 L -3,0 Z" fill="url(#grEmerald)" opacity="0.35"/>
</g>
<g transform="translate(-12, 22)">
<rect x="-8" y="-6" width="16" height="12" rx="2" fill="#121628" stroke="#EC4899" stroke-width="0.4"/>
</g>
<g transform="translate(0, 36)">
<path d="M 0,-8 L 10,4 L -10,4 Z" fill="#121628" stroke="#F59E0B" stroke-width="0.4"/>
</g>
<!-- Glowing connection web -->
<g stroke="#1C2240" stroke-width="0.3" opacity="0.5">
<line x1="0" y1="-20" x2="14" y2="-14"/>
<line x1="0" y1="-20" x2="-14" y2="-14"/>
<line x1="12" y1="-6" x2="6" y2="4"/>
<line x1="-12" y1="-4" x2="-6" y2="6"/>
<line x1="6" y1="10" x2="8" y2="18"/>
<line x1="-6" y1="10" x2="-8" y2="18"/>
</g>
</g>
<text x="0" y="66" class="lbl">Full (dense mosaic with connections)</text>
</g>
<!-- EMPTY STATE -->
<text x="24" y="420" class="section-lbl">EMPTY STATE</text>
<line x1="24" y1="426" x2="670" y2="426" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(350, 540)">
<!-- Ghost tiles -->
<g opacity="0.15">
<path d="M 0,-30 L 16,-16 L 0,-2 L -16,-16 Z" fill="none" stroke="#475569" stroke-width="0.8" stroke-dasharray="3 3"/>
<path d="M 24,-20 L 36,-8 L 24,4 L 12,-8 Z" fill="none" stroke="#475569" stroke-width="0.8" stroke-dasharray="3 3"/>
<path d="M -24,-18 L -12,-6 L -24,6 L -36,-6 Z" fill="none" stroke="#475569" stroke-width="0.8" stroke-dasharray="3 3"/>
<rect x="-14" y="6" width="28" height="18" rx="3" fill="none" stroke="#475569" stroke-width="0.8" stroke-dasharray="3 3"/>
</g>
<!-- Central message area -->
<g filter="url(#glowSm)">
<path d="M 0,-8 L 8,0 L 0,8 L -8,0 Z" fill="url(#grAmethyst)" opacity="0.2">
<animate attributeName="opacity" values="0.1;0.3;0.1" dur="4s" repeatCount="indefinite"/>
</path>
</g>
<text x="0" y="52" font-size="10" fill="#64748B" text-anchor="middle" font-weight="500">Start collecting evidence</text>
<text x="0" y="66" font-size="8" fill="#475569" text-anchor="middle">Each Turn adds a tile to your wall</text>
<text x="0" y="100" class="lbl">Empty state — dashed ghost tiles with CTA</text>
</g>
<text x="350" y="672" font-size="8" fill="#334155" text-anchor="middle">Evidence Wall tiles use mixed shapes, jewel tones per feature, dashed connection lines, and glow on new additions</text>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,322 @@
<svg viewBox="0 0 700 520" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- Prismatic gradients for each jewel tone -->
<linearGradient id="grAmethyst" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#C4B5FD"><animate attributeName="stop-color" values="#C4B5FD;#DDD6FE;#C4B5FD" dur="4s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#7C3AED"/>
</linearGradient>
<linearGradient id="grSapphire" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="4.5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#2563EB"/>
</linearGradient>
<linearGradient id="grEmerald" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#059669"/>
</linearGradient>
<linearGradient id="grAmber" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FDE68A"><animate attributeName="stop-color" values="#FDE68A;#FEF3C7;#FDE68A" dur="4.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#D97706"/>
</linearGradient>
<linearGradient id="grRose" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBCFE8"><animate attributeName="stop-color" values="#FBCFE8;#FCE7F3;#FBCFE8" dur="4.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#DB2777"/>
</linearGradient>
<linearGradient id="grRuby" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FCA5A5"/><stop offset="100%" stop-color="#DC2626"/>
</linearGradient>
<linearGradient id="grIndigo" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#A5B4FC"><animate attributeName="stop-color" values="#A5B4FC;#C7D2FE;#A5B4FC" dur="5.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<linearGradient id="grSoftLight" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#F1F5F9"/><stop offset="100%" stop-color="#94A3B8"/>
</linearGradient>
<linearGradient id="grPrismatic" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#3B82F6"><animate attributeName="stop-color" values="#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6;#3B82F6" dur="8s" repeatCount="indefinite"/></stop>
</linearGradient>
<filter id="glowSm" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="1.5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowMd" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowLg" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="6" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowXl" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur stdDeviation="10" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="shimmer" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="2" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<style>
text { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; }
.lbl { font-size: 9px; fill: #94A3B8; text-anchor: middle; font-weight: 500; }
.section-lbl { font-size: 11px; fill: #64748B; font-weight: 600; letter-spacing: 0.08em; }
</style>
</defs>
<rect width="700" height="520" fill="#050508"/>
<text x="350" y="28" font-size="13" font-weight="700" fill="#94A3B8" text-anchor="middle" letter-spacing="0.12em">FRAGMENT ICONS AND HIGHLIGHT EFFECTS</text>
<text x="350" y="44" font-size="9" fill="#475569" text-anchor="middle">The core diamond fragment in 5 sizes, 8 color states, highlight underline, highlight bubble</text>
<!-- SECTION 1: Five Sizes -->
<text x="24" y="74" class="section-lbl">FIVE SIZES</text>
<line x1="24" y1="80" x2="670" y2="80" stroke="#1C2240" stroke-width="0.5"/>
<!-- XS: 12x12 -->
<g transform="translate(80, 120)">
<g filter="url(#glowSm)">
<path d="M 0,-6 L 6,0 L 0,6 L -6,0 Z" fill="url(#grAmethyst)" opacity="0.9"/>
<path d="M 0,-6 L 6,0 L 0,0 Z" fill="#fff" opacity="0.15"/>
<path d="M 0,-6 L -6,0 L 0,0 Z" fill="#fff" opacity="0.08"/>
<line x1="0" y1="-6" x2="0" y2="6" stroke="#fff" stroke-width="0.3" opacity="0.2"/>
</g>
<text x="0" y="24" class="lbl">XS (12px)</text>
</g>
<!-- SM: 16x16 -->
<g transform="translate(180, 120)">
<g filter="url(#glowSm)">
<path d="M 0,-8 L 8,0 L 0,8 L -8,0 Z" fill="url(#grAmethyst)" opacity="0.9"/>
<path d="M 0,-8 L 8,0 L 0,0 Z" fill="#fff" opacity="0.15"/>
<path d="M 0,-8 L -8,0 L 0,0 Z" fill="#fff" opacity="0.08"/>
<line x1="0" y1="-8" x2="0" y2="8" stroke="#fff" stroke-width="0.4" opacity="0.2"/>
<line x1="-8" y1="0" x2="8" y2="0" stroke="#fff" stroke-width="0.3" opacity="0.1"/>
</g>
<text x="0" y="24" class="lbl">SM (16px)</text>
</g>
<!-- MD: 24x24 -->
<g transform="translate(300, 120)">
<g filter="url(#glowMd)">
<path d="M 0,-12 L 12,0 L 0,12 L -12,0 Z" fill="url(#grAmethyst)" opacity="0.9">
<animate attributeName="fill-opacity" values="0.85;1;0.85" dur="3s" repeatCount="indefinite"/>
</path>
<path d="M 0,-12 L 12,0 L 0,0 Z" fill="#fff" opacity="0.18"/>
<path d="M 0,-12 L -12,0 L 0,0 Z" fill="#fff" opacity="0.1"/>
<line x1="0" y1="-12" x2="0" y2="12" stroke="#fff" stroke-width="0.5" opacity="0.2"/>
<line x1="-12" y1="0" x2="12" y2="0" stroke="#fff" stroke-width="0.3" opacity="0.12"/>
<circle cx="-3" cy="-3" r="1.5" fill="#fff" opacity="0.3"/>
</g>
<text x="0" y="28" class="lbl">MD (24px)</text>
</g>
<!-- LG: 36x36 -->
<g transform="translate(440, 120)">
<g filter="url(#glowLg)">
<path d="M 0,-18 L 18,0 L 0,18 L -18,0 Z" fill="url(#grAmethyst)" opacity="0.85">
<animate attributeName="fill-opacity" values="0.80;0.95;0.80" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 0,-18 L 18,0 L 0,0 Z" fill="#fff" opacity="0.15"/>
<path d="M 0,-18 L -18,0 L 0,0 Z" fill="#fff" opacity="0.08"/>
<line x1="0" y1="-18" x2="0" y2="18" stroke="#fff" stroke-width="0.5" opacity="0.2"/>
<line x1="-18" y1="0" x2="18" y2="0" stroke="#fff" stroke-width="0.4" opacity="0.12"/>
<line x1="-9" y1="-9" x2="9" y2="9" stroke="#fff" stroke-width="0.3" opacity="0.08"/>
<circle cx="-5" cy="-5" r="2" fill="#fff" opacity="0.25"/>
<circle cx="3" cy="-2" r="1" fill="#fff" opacity="0.4"/>
</g>
<text x="0" y="36" class="lbl">LG (36px)</text>
</g>
<!-- XL: 48x48 -->
<g transform="translate(600, 120)">
<g filter="url(#glowXl)">
<path d="M 0,-24 L 24,0 L 0,24 L -24,0 Z" fill="url(#grAmethyst)" opacity="0.85">
<animate attributeName="fill-opacity" values="0.75;0.95;0.75" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 L 24,0 L 0,0 Z" fill="#fff" opacity="0.15"/>
<path d="M 0,-24 L -24,0 L 0,0 Z" fill="#fff" opacity="0.08"/>
<path d="M 0,24 L 24,0 L 0,0 Z" fill="#000" opacity="0.08"/>
<line x1="0" y1="-24" x2="0" y2="24" stroke="#fff" stroke-width="0.6" opacity="0.2"/>
<line x1="-24" y1="0" x2="24" y2="0" stroke="#fff" stroke-width="0.5" opacity="0.15"/>
<line x1="-12" y1="-12" x2="12" y2="12" stroke="#fff" stroke-width="0.3" opacity="0.08"/>
<line x1="12" y1="-12" x2="-12" y2="12" stroke="#fff" stroke-width="0.3" opacity="0.08"/>
<circle cx="-7" cy="-7" r="3" fill="#fff" opacity="0.2"/>
<circle cx="4" cy="-3" r="1.5" fill="#fff" opacity="0.4"/>
<line x1="0" y1="-24" x2="24" y2="0" stroke="#C4B5FD" stroke-width="0.8" opacity="0">
<animate attributeName="opacity" values="0;0.4;0" dur="3s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="-24" x2="-24" y2="0" stroke="#E9D5FF" stroke-width="0.8" opacity="0">
<animate attributeName="opacity" values="0;0.3;0" dur="3s" begin="1.5s" repeatCount="indefinite"/>
</line>
</g>
<text x="0" y="44" class="lbl">XL (48px)</text>
</g>
<!-- SECTION 2: Eight Color States -->
<text x="24" y="204" class="section-lbl">EIGHT COLOR STATES</text>
<line x1="24" y1="210" x2="670" y2="210" stroke="#1C2240" stroke-width="0.5"/>
<!-- Amethyst -->
<g transform="translate(56, 252)">
<g filter="url(#glowMd)">
<path d="M 0,-12 L 12,0 L 0,12 L -12,0 Z" fill="url(#grAmethyst)" opacity="0.9"/>
<path d="M 0,-12 L 12,0 L 0,0 Z" fill="#fff" opacity="0.18"/>
<line x1="0" y1="-12" x2="0" y2="12" stroke="#fff" stroke-width="0.5" opacity="0.2"/>
<circle cx="-3" cy="-3" r="1.5" fill="#fff" opacity="0.3"/>
</g>
<text x="0" y="28" class="lbl">Amethyst</text>
</g>
<!-- Sapphire -->
<g transform="translate(138, 252)">
<g filter="url(#glowMd)">
<path d="M 0,-12 L 12,0 L 0,12 L -12,0 Z" fill="url(#grSapphire)" opacity="0.9"/>
<path d="M 0,-12 L 12,0 L 0,0 Z" fill="#fff" opacity="0.18"/>
<line x1="0" y1="-12" x2="0" y2="12" stroke="#fff" stroke-width="0.5" opacity="0.2"/>
<circle cx="-3" cy="-3" r="1.5" fill="#fff" opacity="0.3"/>
</g>
<text x="0" y="28" class="lbl">Sapphire</text>
</g>
<!-- Emerald -->
<g transform="translate(220, 252)">
<g filter="url(#glowMd)">
<path d="M 0,-12 L 12,0 L 0,12 L -12,0 Z" fill="url(#grEmerald)" opacity="0.9"/>
<path d="M 0,-12 L 12,0 L 0,0 Z" fill="#fff" opacity="0.18"/>
<line x1="0" y1="-12" x2="0" y2="12" stroke="#fff" stroke-width="0.5" opacity="0.2"/>
<circle cx="-3" cy="-3" r="1.5" fill="#fff" opacity="0.3"/>
</g>
<text x="0" y="28" class="lbl">Emerald</text>
</g>
<!-- Amber -->
<g transform="translate(302, 252)">
<g filter="url(#glowMd)">
<path d="M 0,-12 L 12,0 L 0,12 L -12,0 Z" fill="url(#grAmber)" opacity="0.9"/>
<path d="M 0,-12 L 12,0 L 0,0 Z" fill="#fff" opacity="0.18"/>
<line x1="0" y1="-12" x2="0" y2="12" stroke="#fff" stroke-width="0.5" opacity="0.2"/>
<circle cx="-3" cy="-3" r="1.5" fill="#fff" opacity="0.3"/>
</g>
<text x="0" y="28" class="lbl">Amber</text>
</g>
<!-- Rose -->
<g transform="translate(384, 252)">
<g filter="url(#glowMd)">
<path d="M 0,-12 L 12,0 L 0,12 L -12,0 Z" fill="url(#grRose)" opacity="0.9"/>
<path d="M 0,-12 L 12,0 L 0,0 Z" fill="#fff" opacity="0.18"/>
<line x1="0" y1="-12" x2="0" y2="12" stroke="#fff" stroke-width="0.5" opacity="0.2"/>
<circle cx="-3" cy="-3" r="1.5" fill="#fff" opacity="0.3"/>
</g>
<text x="0" y="28" class="lbl">Rose</text>
</g>
<!-- Ruby -->
<g transform="translate(466, 252)">
<g filter="url(#glowMd)">
<path d="M 0,-12 L 12,0 L 0,12 L -12,0 Z" fill="url(#grRuby)" opacity="0.9"/>
<path d="M 0,-12 L 12,0 L 0,0 Z" fill="#fff" opacity="0.18"/>
<line x1="0" y1="-12" x2="0" y2="12" stroke="#fff" stroke-width="0.5" opacity="0.2"/>
<circle cx="-3" cy="-3" r="1.5" fill="#fff" opacity="0.3"/>
</g>
<text x="0" y="28" class="lbl">Ruby</text>
</g>
<!-- Indigo -->
<g transform="translate(548, 252)">
<g filter="url(#glowMd)">
<path d="M 0,-12 L 12,0 L 0,12 L -12,0 Z" fill="url(#grIndigo)" opacity="0.9"/>
<path d="M 0,-12 L 12,0 L 0,0 Z" fill="#fff" opacity="0.18"/>
<line x1="0" y1="-12" x2="0" y2="12" stroke="#fff" stroke-width="0.5" opacity="0.2"/>
<circle cx="-3" cy="-3" r="1.5" fill="#fff" opacity="0.3"/>
</g>
<text x="0" y="28" class="lbl">Indigo</text>
</g>
<!-- Soft Light -->
<g transform="translate(630, 252)">
<g filter="url(#glowMd)">
<path d="M 0,-12 L 12,0 L 0,12 L -12,0 Z" fill="url(#grSoftLight)" opacity="0.9"/>
<path d="M 0,-12 L 12,0 L 0,0 Z" fill="#fff" opacity="0.18"/>
<line x1="0" y1="-12" x2="0" y2="12" stroke="#fff" stroke-width="0.5" opacity="0.2"/>
<circle cx="-3" cy="-3" r="1.5" fill="#fff" opacity="0.3"/>
</g>
<text x="0" y="28" class="lbl">Soft Light</text>
</g>
<!-- SECTION 3: Special States and Highlights -->
<text x="24" y="330" class="section-lbl">SPECIAL STATES AND HIGHLIGHTS</text>
<line x1="24" y1="336" x2="670" y2="336" stroke="#1C2240" stroke-width="0.5"/>
<!-- Active/Detected glow -->
<g transform="translate(80, 390)">
<g filter="url(#glowLg)">
<path d="M 0,-14 L 14,0 L 0,14 L -14,0 Z" fill="url(#grAmethyst)" opacity="0.95">
<animate attributeName="fill-opacity" values="0.85;1;0.85" dur="2s" repeatCount="indefinite"/>
</path>
<path d="M 0,-14 L 14,0 L 0,0 Z" fill="#fff" opacity="0.2"/>
<line x1="0" y1="-14" x2="0" y2="14" stroke="#fff" stroke-width="0.5" opacity="0.25"/>
<circle cx="-4" cy="-4" r="2" fill="#fff" opacity="0.35"/>
<path d="M 0,-18 L 18,0 L 0,18 L -18,0 Z" fill="none" stroke="#A78BFA" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.5;0" dur="2s" repeatCount="indefinite"/>
<animate attributeName="stroke-width" values="1;0.3;1" dur="2s" repeatCount="indefinite"/>
</path>
<path d="M 0,-22 L 22,0 L 0,22 L -22,0 Z" fill="none" stroke="#A78BFA" stroke-width="0.5" opacity="0">
<animate attributeName="opacity" values="0;0.3;0" dur="2s" begin="0.3s" repeatCount="indefinite"/>
</path>
</g>
<text x="0" y="44" class="lbl">Active / Detected</text>
</g>
<!-- Prismatic cycling -->
<g transform="translate(220, 390)">
<g filter="url(#glowLg)">
<path d="M 0,-14 L 14,0 L 0,14 L -14,0 Z" fill="url(#grPrismatic)" opacity="0.9">
<animate attributeName="fill-opacity" values="0.8;1;0.8" dur="3s" repeatCount="indefinite"/>
</path>
<path d="M 0,-14 L 14,0 L 0,0 Z" fill="#fff" opacity="0.15"/>
<line x1="0" y1="-14" x2="0" y2="14" stroke="#fff" stroke-width="0.5" opacity="0.2"/>
<circle cx="-4" cy="-4" r="2" fill="#fff" opacity="0.3"/>
</g>
<text x="0" y="44" class="lbl">Prismatic Cycle</text>
</g>
<!-- Dimmed / Inactive -->
<g transform="translate(360, 390)">
<path d="M 0,-14 L 14,0 L 0,14 L -14,0 Z" fill="none" stroke="#475569" stroke-width="0.8" opacity="0.5"/>
<line x1="0" y1="-14" x2="0" y2="14" stroke="#475569" stroke-width="0.3" opacity="0.3"/>
<text x="0" y="44" class="lbl">Dimmed / Inactive</text>
</g>
<!-- Highlight Underline -->
<g transform="translate(500, 380)">
<text x="0" y="0" font-size="11" fill="#E2E8F0" text-anchor="middle" font-weight="500">highlighted text</text>
<g filter="url(#shimmer)">
<rect x="-48" y="4" width="96" height="3" rx="1.5" fill="url(#grAmethyst)" opacity="0.6">
<animate attributeName="opacity" values="0.4;0.7;0.4" dur="3s" repeatCount="indefinite"/>
</rect>
<rect x="-48" y="4" width="20" height="3" rx="1.5" fill="#fff" opacity="0">
<animate attributeName="opacity" values="0;0.3;0" dur="2s" repeatCount="indefinite"/>
<animate attributeName="x" values="-48;48" dur="2s" repeatCount="indefinite"/>
</rect>
</g>
<g transform="translate(-52, 5)">
<path d="M 0,-3 L 3,0 L 0,3 L -3,0 Z" fill="url(#grAmethyst)" opacity="0.8" filter="url(#glowSm)"/>
</g>
<text x="0" y="30" class="lbl">Highlight Underline</text>
</g>
<!-- Highlight Bubble -->
<g transform="translate(350, 470)">
<g filter="url(#glowMd)">
<rect x="-80" y="-18" width="160" height="36" rx="18" fill="#121628" stroke="#8B5CF6" stroke-width="0.8" opacity="0.9"/>
<rect x="-78" y="-16" width="156" height="32" rx="16" fill="#8B5CF6" opacity="0.06"/>
<g transform="translate(-56, 0)">
<path d="M 0,-6 L 6,0 L 0,6 L -6,0 Z" fill="url(#grAmethyst)" opacity="0.9" filter="url(#glowSm)"/>
<path d="M 0,-6 L 6,0 L 0,0 Z" fill="#fff" opacity="0.15"/>
</g>
<text x="4" y="4" font-size="10" fill="#C4B5FD" text-anchor="middle" font-weight="500">Catastrophizing</text>
<rect x="-82" y="-20" width="164" height="40" rx="20" fill="none" stroke="#8B5CF6" stroke-width="0.5" opacity="0">
<animate attributeName="opacity" values="0;0.3;0" dur="3s" repeatCount="indefinite"/>
</rect>
</g>
<text x="0" y="38" class="lbl">Highlight Bubble (distortion detected in text)</text>
</g>
<text x="350" y="510" font-size="8" fill="#334155" text-anchor="middle">Fragment — Core visual element of Kalei — Crystalline faceted diamond with gradient fills, specular highlights, glow filters</text>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,380 @@
<svg viewBox="0 0 560 560" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="gl" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="1.5" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<linearGradient id="gAme" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#C4B5FD"/><stop offset="100%" stop-color="#7C3AED"/>
</linearGradient>
<linearGradient id="gSoft" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#F1F5F9"/><stop offset="100%" stop-color="#94A3B8"/>
</linearGradient>
<linearGradient id="gEm" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#6EE7B7"/><stop offset="100%" stop-color="#047857"/>
</linearGradient>
<linearGradient id="gSap" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#93C5FD"/><stop offset="100%" stop-color="#1D4ED8"/>
</linearGradient>
<linearGradient id="gAmb" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FDE68A"/><stop offset="100%" stop-color="#D97706"/>
</linearGradient>
<linearGradient id="gRose" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBCFE8"/><stop offset="100%" stop-color="#BE185D"/>
</linearGradient>
<style>
text { font-family: 'Inter', -apple-system, sans-serif; }
.lbl { font-size: 8px; fill: #64748B; text-anchor: middle; font-weight: 500; }
</style>
</defs>
<rect width="560" height="560" fill="#050508"/>
<text x="280" y="22" font-size="12" font-weight="600" fill="#94A3B8" text-anchor="middle" letter-spacing="0.1em">ACTION &amp; UI ICONS</text>
<!-- === ROW 1: NAVIGATION (Soft Light #E2E8F0 strokes) === -->
<text x="20" y="50" font-size="9" fill="#475569" font-weight="600" letter-spacing="0.08em">NAVIGATION</text>
<!-- Back chevron -->
<g transform="translate(30, 60)">
<path d="M 14,4 L 6,12 L 14,20" fill="none" stroke="#E2E8F0" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<text x="12" y="34" class="lbl">Back</text>
</g>
<!-- Close X -->
<g transform="translate(90, 60)">
<path d="M 6,6 L 18,18 M 18,6 L 6,18" fill="none" stroke="#E2E8F0" stroke-width="1.5" stroke-linecap="round"/>
<text x="12" y="34" class="lbl">Close</text>
</g>
<!-- More (3 diamonds) -->
<g transform="translate(150, 60)">
<path d="M 12,4 L 14,6 L 12,8 L 10,6 Z" fill="#E2E8F0" opacity="0.8"/>
<path d="M 12,10 L 14,12 L 12,14 L 10,12 Z" fill="#E2E8F0" opacity="0.8"/>
<path d="M 12,16 L 14,18 L 12,20 L 10,18 Z" fill="#E2E8F0" opacity="0.8"/>
<text x="12" y="34" class="lbl">More</text>
</g>
<!-- Chevron right -->
<g transform="translate(210, 60)">
<path d="M 10,4 L 18,12 L 10,20" fill="none" stroke="#94A3B8" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
<text x="12" y="34" class="lbl">Next</text>
</g>
<!-- Up (scroll to top / expand) -->
<g transform="translate(270, 60)">
<path d="M 4,16 L 12,6 L 20,16" fill="none" stroke="#E2E8F0" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<text x="12" y="34" class="lbl">Up</text>
</g>
<!-- Down -->
<g transform="translate(330, 60)">
<path d="M 4,8 L 12,18 L 20,8" fill="none" stroke="#E2E8F0" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<text x="12" y="34" class="lbl">Down</text>
</g>
<!-- === ROW 2: PRIMARY ACTIONS (Amethyst) === -->
<text x="20" y="120" font-size="9" fill="#475569" font-weight="600" letter-spacing="0.08em">PRIMARY ACTIONS</text>
<!-- Save / Bookmark (gem shape) -->
<g transform="translate(30, 130)" filter="url(#gl)">
<path d="M 12,3 L 20,8 L 20,21 L 12,17 L 4,21 L 4,8 Z" fill="url(#gAme)" opacity="0.85"/>
<path d="M 12,3 L 20,8 L 4,8 Z" fill="#fff" opacity="0.12"/>
<text x="12" y="34" class="lbl">Save</text>
</g>
<!-- Share (angular arrow up-right) -->
<g transform="translate(90, 130)" filter="url(#gl)">
<path d="M 12,4 L 18,4 L 18,10" fill="none" stroke="#A78BFA" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 18,4 L 6,16" fill="none" stroke="#A78BFA" stroke-width="1.5" stroke-linecap="round"/>
<path d="M 6,8 L 6,20 L 18,20" fill="none" stroke="#8B5CF6" stroke-width="1" opacity="0.5"/>
<text x="12" y="34" class="lbl">Share</text>
</g>
<!-- Copy -->
<g transform="translate(150, 130)">
<rect x="8" y="6" width="12" height="14" rx="2" fill="none" stroke="#A78BFA" stroke-width="1.2"/>
<rect x="4" y="4" width="12" height="14" rx="2" fill="none" stroke="#8B5CF6" stroke-width="1"/>
<text x="12" y="34" class="lbl">Copy</text>
</g>
<!-- Delete -->
<g transform="translate(210, 130)">
<path d="M 6,8 L 18,8" stroke="#EF4444" stroke-width="1.2" stroke-linecap="round"/>
<path d="M 8,8 L 8,20 L 16,20 L 16,8" fill="none" stroke="#EF4444" stroke-width="1"/>
<path d="M 10,6 L 10,8 M 14,6 L 14,8" stroke="#EF4444" stroke-width="1" stroke-linecap="round"/>
<line x1="10" y1="11" x2="10" y2="17" stroke="#EF4444" stroke-width="0.8" opacity="0.5"/>
<line x1="14" y1="11" x2="14" y2="17" stroke="#EF4444" stroke-width="0.8" opacity="0.5"/>
<text x="12" y="34" class="lbl">Delete</text>
</g>
<!-- Edit -->
<g transform="translate(270, 130)">
<path d="M 4,20 L 4,16 L 16,4 L 20,8 L 8,20 Z" fill="none" stroke="#A78BFA" stroke-width="1.2" stroke-linejoin="round"/>
<line x1="14" y1="6" x2="18" y2="10" stroke="#A78BFA" stroke-width="0.8" opacity="0.5"/>
<text x="12" y="34" class="lbl">Edit</text>
</g>
<!-- Refresh (angular cycle) -->
<g transform="translate(330, 130)">
<path d="M 18,10 A 7,7 0 1 0 16,18" fill="none" stroke="#A78BFA" stroke-width="1.3" stroke-linecap="round"/>
<path d="M 18,6 L 18,11 L 13,11" fill="none" stroke="#A78BFA" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
<text x="12" y="34" class="lbl">Refresh</text>
</g>
<!-- Send (angular arrow) -->
<g transform="translate(390, 130)" filter="url(#gl)">
<path d="M 4,20 L 4,12 L 20,4 L 12,20 L 10,14 Z" fill="url(#gAme)" opacity="0.8"/>
<path d="M 4,12 L 20,4 L 10,14 Z" fill="#fff" opacity="0.1"/>
<text x="12" y="34" class="lbl">Send</text>
</g>
<!-- === ROW 3: STATUS (contextual colors) === -->
<text x="20" y="190" font-size="9" fill="#475569" font-weight="600" letter-spacing="0.08em">STATUS &amp; FEEDBACK</text>
<!-- Checkmark (Emerald, animated subtle pulse) -->
<g transform="translate(30, 200)" filter="url(#gl)">
<circle cx="12" cy="12" r="10" fill="none" stroke="#10B981" stroke-width="1.2" opacity="0.5"/>
<path d="M 7,12 L 11,16 L 18,8" fill="none" stroke="url(#gEm)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<animate attributeName="opacity" values="0.7;1;0.7" dur="3s" repeatCount="indefinite"/>
</path>
<text x="12" y="34" class="lbl">Success</text>
</g>
<!-- Warning (Amber triangle) -->
<g transform="translate(90, 200)" filter="url(#gl)">
<path d="M 12,3 L 22,21 L 2,21 Z" fill="none" stroke="#F59E0B" stroke-width="1.2" stroke-linejoin="round"/>
<path d="M 12,3 L 22,21 L 2,21 Z" fill="#F59E0B" opacity="0.08"/>
<line x1="12" y1="10" x2="12" y2="15" stroke="#FCD34D" stroke-width="1.5" stroke-linecap="round"/>
<circle cx="12" cy="18" r="1" fill="#FCD34D"/>
<text x="12" y="34" class="lbl">Warning</text>
</g>
<!-- Info (hexagonal i) -->
<g transform="translate(150, 200)">
<path d="M 12,2 L 20,7 L 20,17 L 12,22 L 4,17 L 4,7 Z" fill="none" stroke="#3B82F6" stroke-width="1" opacity="0.6"/>
<circle cx="12" cy="8" r="1" fill="#60A5FA"/>
<line x1="12" y1="11" x2="12" y2="17" stroke="#60A5FA" stroke-width="1.5" stroke-linecap="round"/>
<text x="12" y="34" class="lbl">Info</text>
</g>
<!-- Lock -->
<g transform="translate(210, 200)">
<rect x="6" y="12" width="12" height="10" rx="2" fill="none" stroke="#94A3B8" stroke-width="1.2"/>
<path d="M 9,12 L 9,8 A 3,3 0 0 1 15,8 L 15,12" fill="none" stroke="#94A3B8" stroke-width="1.2"/>
<circle cx="12" cy="17" r="1.2" fill="#94A3B8"/>
<text x="12" y="34" class="lbl">Lock</text>
</g>
<!-- Unlock -->
<g transform="translate(270, 200)">
<rect x="6" y="12" width="12" height="10" rx="2" fill="none" stroke="#10B981" stroke-width="1.2"/>
<path d="M 9,12 L 9,8 A 3,3 0 0 1 15,8 L 15,6" fill="none" stroke="#10B981" stroke-width="1.2"/>
<circle cx="12" cy="17" r="1.2" fill="#10B981"/>
<text x="12" y="34" class="lbl">Unlock</text>
</g>
<!-- Error (Ruby X in circle) -->
<g transform="translate(330, 200)">
<circle cx="12" cy="12" r="10" fill="none" stroke="#EF4444" stroke-width="1" opacity="0.5"/>
<path d="M 8,8 L 16,16 M 16,8 L 8,16" stroke="#EF4444" stroke-width="1.5" stroke-linecap="round"/>
<text x="12" y="34" class="lbl">Error</text>
</g>
<!-- === ROW 4: FEATURE-SPECIFIC (mixed jewel tones) === -->
<text x="20" y="260" font-size="9" fill="#475569" font-weight="600" letter-spacing="0.08em">FEATURE ICONS</text>
<!-- Turn/Rotate (animated slowly) -->
<g transform="translate(30, 270)" filter="url(#gl)">
<path d="M 12,4 L 18,12 L 12,20 L 6,12 Z" fill="url(#gAme)" opacity="0.7"/>
<path d="M 12,4 L 18,12 L 6,12 Z" fill="#fff" opacity="0.1"/>
<!-- Rotation arc -->
<path d="M 20,6 A 9,9 0 0 1 20,18" fill="none" stroke="#C4B5FD" stroke-width="0.8" opacity="0.5">
<animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="12s" repeatCount="indefinite"/>
</path>
<text x="12" y="34" class="lbl">Rotate</text>
</g>
<!-- Streak flame (Amber, animated flicker) -->
<g transform="translate(90, 270)" filter="url(#gl)">
<path d="M 12,3 Q 16,8 15,14 Q 18,10 17,6 Q 20,12 16,20 L 8,20 Q 4,12 7,6 Q 6,10 9,14 Q 8,8 12,3 Z" fill="url(#gAmb)" opacity="0.85">
<animate attributeName="opacity" values="0.75;0.95;0.75" dur="1.5s" repeatCount="indefinite"/>
</path>
<path d="M 12,3 Q 14,7 13,10 L 11,10 Q 10,7 12,3 Z" fill="#fff" opacity="0.15"/>
<text x="12" y="34" class="lbl">Streak</text>
</g>
<!-- Bell (notification) -->
<g transform="translate(150, 270)">
<path d="M 12,3 L 12,5 M 8,20 Q 12,23 16,20" fill="none" stroke="#E2E8F0" stroke-width="1" stroke-linecap="round"/>
<path d="M 6,18 L 6,12 Q 6,6 12,5 Q 18,6 18,12 L 18,18 Z" fill="none" stroke="#E2E8F0" stroke-width="1.2"/>
<!-- Notification dot -->
<circle cx="17" cy="6" r="2.5" fill="#EF4444" opacity="0.9">
<animate attributeName="opacity" values="0.7;1;0.7" dur="2s" repeatCount="indefinite"/>
</circle>
<text x="12" y="34" class="lbl">Notify</text>
</g>
<!-- Heart (angular, Rose) -->
<g transform="translate(210, 270)" filter="url(#gl)">
<path d="M 12,19 L 4,11 L 4,7 L 8,3 L 12,7 L 16,3 L 20,7 L 20,11 Z" fill="url(#gRose)" opacity="0.8"/>
<path d="M 12,7 L 8,3 L 4,7 L 4,11 Z" fill="#fff" opacity="0.1"/>
<text x="12" y="34" class="lbl">Heart</text>
</g>
<!-- Star (6-pointed crystalline) -->
<g transform="translate(270, 270)" filter="url(#gl)">
<path d="M 12,2 L 14,9 L 21,9 L 16,14 L 18,21 L 12,17 L 6,21 L 8,14 L 3,9 L 10,9 Z" fill="url(#gAmb)" opacity="0.75"/>
<path d="M 12,2 L 14,9 L 10,9 Z" fill="#fff" opacity="0.12"/>
<text x="12" y="34" class="lbl">Star</text>
</g>
<!-- Settings (hexagonal gear) -->
<g transform="translate(330, 270)">
<path d="M 10,2 L 14,2 L 16,5 L 20,5 L 22,9 L 20,12 L 22,15 L 20,19 L 16,19 L 14,22 L 10,22 L 8,19 L 4,19 L 2,15 L 4,12 L 2,9 L 4,5 L 8,5 Z" fill="none" stroke="#94A3B8" stroke-width="1"/>
<circle cx="12" cy="12" r="4" fill="none" stroke="#94A3B8" stroke-width="1"/>
<text x="12" y="34" class="lbl">Settings</text>
</g>
<!-- Calendar -->
<g transform="translate(390, 270)">
<rect x="4" y="6" width="16" height="16" rx="2" fill="none" stroke="#94A3B8" stroke-width="1"/>
<line x1="4" y1="10" x2="20" y2="10" stroke="#94A3B8" stroke-width="0.8"/>
<line x1="8" y1="4" x2="8" y2="8" stroke="#94A3B8" stroke-width="1" stroke-linecap="round"/>
<line x1="16" y1="4" x2="16" y2="8" stroke="#94A3B8" stroke-width="1" stroke-linecap="round"/>
<!-- Date dots -->
<circle cx="8" cy="14" r="1" fill="#94A3B8" opacity="0.5"/>
<circle cx="12" cy="14" r="1" fill="#8B5CF6" opacity="0.8"/>
<circle cx="16" cy="14" r="1" fill="#94A3B8" opacity="0.5"/>
<circle cx="8" cy="18" r="1" fill="#94A3B8" opacity="0.5"/>
<circle cx="12" cy="18" r="1" fill="#94A3B8" opacity="0.5"/>
<text x="12" y="34" class="lbl">Calendar</text>
</g>
<!-- === ROW 5: MEDIA & UI CONTROLS === -->
<text x="20" y="330" font-size="9" fill="#475569" font-weight="600" letter-spacing="0.08em">MEDIA &amp; CONTROLS</text>
<!-- Play -->
<g transform="translate(30, 340)">
<path d="M 7,4 L 20,12 L 7,20 Z" fill="url(#gAme)" opacity="0.8"/>
<path d="M 7,4 L 20,12 L 7,12 Z" fill="#fff" opacity="0.08"/>
<text x="12" y="34" class="lbl">Play</text>
</g>
<!-- Pause -->
<g transform="translate(90, 340)">
<rect x="6" y="5" width="4" height="14" rx="1" fill="#E2E8F0" opacity="0.8"/>
<rect x="14" y="5" width="4" height="14" rx="1" fill="#E2E8F0" opacity="0.8"/>
<text x="12" y="34" class="lbl">Pause</text>
</g>
<!-- Filter / Funnel -->
<g transform="translate(150, 340)">
<path d="M 3,5 L 21,5 L 14,14 L 14,20 L 10,22 L 10,14 Z" fill="none" stroke="#94A3B8" stroke-width="1.2" stroke-linejoin="round"/>
<text x="12" y="34" class="lbl">Filter</text>
</g>
<!-- Search -->
<g transform="translate(210, 340)">
<circle cx="10" cy="10" r="7" fill="none" stroke="#94A3B8" stroke-width="1.3"/>
<line x1="15" y1="15" x2="21" y2="21" stroke="#94A3B8" stroke-width="1.5" stroke-linecap="round"/>
<text x="12" y="34" class="lbl">Search</text>
</g>
<!-- Eye / View -->
<g transform="translate(270, 340)">
<path d="M 2,12 Q 12,4 22,12 Q 12,20 2,12 Z" fill="none" stroke="#94A3B8" stroke-width="1.1"/>
<!-- Diamond pupil -->
<path d="M 12,8 L 15,12 L 12,16 L 9,12 Z" fill="#94A3B8" opacity="0.6"/>
<text x="12" y="34" class="lbl">View</text>
</g>
<!-- Expand -->
<g transform="translate(330, 340)">
<path d="M 4,4 L 10,4 M 4,4 L 4,10" stroke="#94A3B8" stroke-width="1.3" stroke-linecap="round"/>
<path d="M 20,4 L 14,4 M 20,4 L 20,10" stroke="#94A3B8" stroke-width="1.3" stroke-linecap="round"/>
<path d="M 4,20 L 10,20 M 4,20 L 4,14" stroke="#94A3B8" stroke-width="1.3" stroke-linecap="round"/>
<path d="M 20,20 L 14,20 M 20,20 L 20,14" stroke="#94A3B8" stroke-width="1.3" stroke-linecap="round"/>
<text x="12" y="34" class="lbl">Expand</text>
</g>
<!-- Clock / Timer -->
<g transform="translate(390, 340)">
<path d="M 12,2 L 18,5 L 21,11 L 18,17 L 12,20 L 6,17 L 3,11 L 6,5 Z" fill="none" stroke="#94A3B8" stroke-width="1"/>
<line x1="12" y1="7" x2="12" y2="11" stroke="#E2E8F0" stroke-width="1" stroke-linecap="round"/>
<line x1="12" y1="11" x2="16" y2="14" stroke="#E2E8F0" stroke-width="1" stroke-linecap="round"/>
<text x="12" y="34" class="lbl">Timer</text>
</g>
<!-- === ROW 6: SPECIAL PURPOSE === -->
<text x="20" y="400" font-size="9" fill="#475569" font-weight="600" letter-spacing="0.08em">SPECIAL PURPOSE</text>
<!-- Upgrade / Crown (prismatic animated) -->
<g transform="translate(30, 410)" filter="url(#gl)">
<path d="M 4,18 L 4,10 L 8,14 L 12,6 L 16,14 L 20,10 L 20,18 Z" fill="url(#gAme)" opacity="0.8">
<animate attributeName="opacity" values="0.7;0.95;0.7" dur="3s" repeatCount="indefinite"/>
</path>
<path d="M 4,10 L 8,14 L 12,6 L 16,14 L 20,10 Z" fill="#fff" opacity="0.1"/>
<text x="12" y="34" class="lbl">Premium</text>
</g>
<!-- Science / Beaker -->
<g transform="translate(90, 410)">
<path d="M 9,4 L 9,12 L 4,20 L 20,20 L 15,12 L 15,4" fill="none" stroke="#60A5FA" stroke-width="1.2" stroke-linejoin="round"/>
<line x1="7" y1="4" x2="17" y2="4" stroke="#60A5FA" stroke-width="1"/>
<circle cx="10" cy="16" r="1.5" fill="#60A5FA" opacity="0.4"/>
<circle cx="14" cy="18" r="1" fill="#60A5FA" opacity="0.3"/>
<text x="12" y="34" class="lbl">Science</text>
</g>
<!-- Habit / Loop (animated subtle rotation) -->
<g transform="translate(150, 410)">
<path d="M 12,4 A 8,8 0 1 1 4,12" fill="none" stroke="#10B981" stroke-width="1.3" stroke-linecap="round">
<animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="20s" repeatCount="indefinite"/>
</path>
<path d="M 12,4 L 14,7 L 10,7 Z" fill="#10B981"/>
<circle cx="12" cy="12" r="3" fill="none" stroke="#10B981" stroke-width="0.8" opacity="0.4"/>
<text x="12" y="34" class="lbl">Habit</text>
</g>
<!-- Breathe / Meditation -->
<g transform="translate(210, 410)">
<circle cx="12" cy="12" r="8" fill="none" stroke="#6366F1" stroke-width="1" opacity="0.4">
<animate attributeName="r" values="6;10;6" dur="4s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.2;0.5;0.2" dur="4s" repeatCount="indefinite"/>
</circle>
<circle cx="12" cy="12" r="3" fill="#818CF8" opacity="0.6">
<animate attributeName="r" values="2;4;2" dur="4s" repeatCount="indefinite"/>
</circle>
<text x="12" y="34" class="lbl">Breathe</text>
</g>
<!-- Evidence (diamond mosaic) -->
<g transform="translate(270, 410)" filter="url(#gl)">
<path d="M 8,6 L 12,3 L 16,6 L 12,9 Z" fill="#8B5CF6" opacity="0.6"/>
<path d="M 4,12 L 8,9 L 12,12 L 8,15 Z" fill="#3B82F6" opacity="0.5"/>
<path d="M 12,12 L 16,9 L 20,12 L 16,15 Z" fill="#10B981" opacity="0.5"/>
<path d="M 8,18 L 12,15 L 16,18 L 12,21 Z" fill="#F59E0B" opacity="0.5"/>
<text x="12" y="34" class="lbl">Evidence</text>
</g>
<!-- Fragment (the core ◇) -->
<g transform="translate(330, 410)" filter="url(#gl)">
<path d="M 12,2 L 20,12 L 12,22 L 4,12 Z" fill="url(#gAmb)" opacity="0.85"/>
<path d="M 12,2 L 20,12 L 4,12 Z" fill="#fff" opacity="0.12"/>
<line x1="4" y1="12" x2="20" y2="12" stroke="#fff" stroke-width="0.4" opacity="0.3"/>
<animate attributeName="opacity" values="0.8;1;0.8" dur="2.5s" repeatCount="indefinite"/>
<text x="12" y="34" class="lbl">Fragment</text>
</g>
<!-- Spectrum (prismatic bar) -->
<g transform="translate(390, 410)">
<rect x="4" y="8" width="4" height="8" rx="1" fill="#8B5CF6" opacity="0.7"/>
<rect x="9" y="6" width="4" height="12" rx="1" fill="#3B82F6" opacity="0.7"/>
<rect x="14" y="10" width="4" height="6" rx="1" fill="#10B981" opacity="0.7"/>
<rect x="4" y="18" width="14" height="2" rx="1" fill="#1C2240"/>
<text x="12" y="34" class="lbl">Spectrum</text>
</g>
<!-- Totals -->
<text x="280" y="480" font-size="9" fill="#475569" text-anchor="middle">38 icons — 24×24px each — Glow filters on primary actions — Animations on streak, breathe, rotate, notify</text>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,187 @@
<svg viewBox="0 0 560 320" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="gAmber" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="1.8" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<linearGradient id="amberGr" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FDE68A"/>
<stop offset="100%" stop-color="#D97706"/>
</linearGradient>
<style>
text { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; }
.lbl { font-size: 9px; fill: #94A3B8; text-anchor: middle; font-weight: 500; }
</style>
</defs>
<rect width="560" height="320" fill="#050508"/>
<text x="280" y="24" font-size="12" font-weight="600" fill="#94A3B8" text-anchor="middle" letter-spacing="0.12em">COGNITIVE DISTORTION ICONS</text>
<text x="280" y="38" font-size="9" fill="#475569" text-anchor="middle">10 fragment types — Amber (#F59E0B) default, each with unique crystalline geometry</text>
<!-- Row 1: 5 icons -->
<!-- Each icon is 24x24, rendered in a 100x100 cell with label -->
<!-- 1. CATASTROPHIZING — A downward-cascading shard breaking into pieces -->
<g transform="translate(28, 60)" filter="url(#gAmber)">
<g transform="translate(12,12)">
<!-- Main shard falling -->
<path d="M 0,-10 L 5,0 L 0,10 L -5,0 Z" fill="url(#amberGr)" opacity="0.9"/>
<path d="M 0,-10 L 5,0 L -5,0 Z" fill="#fff" opacity="0.15"/>
<!-- Smaller fragment broken off, lower-left -->
<path d="M -8,6 L -5,10 L -9,12 L -11,8 Z" fill="#F59E0B" opacity="0.5"/>
<!-- Smaller fragment, lower-right -->
<path d="M 7,8 L 10,12 L 8,14 L 5,11 Z" fill="#F59E0B" opacity="0.4"/>
<!-- Downward motion lines -->
<line x1="0" y1="11" x2="0" y2="16" stroke="#FCD34D" stroke-width="0.5" opacity="0.4"/>
<line x1="-3" y1="12" x2="-5" y2="17" stroke="#FCD34D" stroke-width="0.4" opacity="0.3"/>
<line x1="3" y1="12" x2="5" y2="17" stroke="#FCD34D" stroke-width="0.4" opacity="0.3"/>
</g>
<text x="12" y="42" class="lbl">Catastrophizing</text>
</g>
<!-- 2. BLACK-AND-WHITE — A diamond split in half: one side filled, one side outline -->
<g transform="translate(140, 60)" filter="url(#gAmber)">
<g transform="translate(12,12)">
<!-- Left half: filled -->
<path d="M 0,-10 L -7,0 L 0,10 L 0,0 Z" fill="url(#amberGr)" opacity="0.85"/>
<!-- Right half: outline only -->
<path d="M 0,-10 L 7,0 L 0,10 L 0,0 Z" fill="none" stroke="#F59E0B" stroke-width="1"/>
<!-- Center dividing line -->
<line x1="0" y1="-10" x2="0" y2="10" stroke="#FEF3C7" stroke-width="0.6" opacity="0.5"/>
<!-- Top facet highlight on filled side -->
<path d="M 0,-10 L -7,0 L 0,0 Z" fill="#fff" opacity="0.12"/>
</g>
<text x="12" y="42" class="lbl">Black-and-White</text>
</g>
<!-- 3. MIND READING — A hexagonal head with a small eye/diamond inside -->
<g transform="translate(252, 60)" filter="url(#gAmber)">
<g transform="translate(12,12)">
<!-- Hexagonal head outline -->
<path d="M 0,-10 L 8,-5 L 8,5 L 0,10 L -8,5 L -8,-5 Z" fill="none" stroke="#F59E0B" stroke-width="1" opacity="0.7"/>
<!-- Inner diamond (the "read" thought) -->
<path d="M 0,-4 L 4,0 L 0,4 L -4,0 Z" fill="url(#amberGr)" opacity="0.8"/>
<path d="M 0,-4 L 4,0 L -4,0 Z" fill="#fff" opacity="0.15"/>
<!-- Radiating lines from inner diamond (thought waves) -->
<line x1="5" y1="-3" x2="9" y2="-6" stroke="#FCD34D" stroke-width="0.4" opacity="0.35"/>
<line x1="5" y1="3" x2="9" y2="6" stroke="#FCD34D" stroke-width="0.4" opacity="0.35"/>
<line x1="-5" y1="-3" x2="-9" y2="-6" stroke="#FCD34D" stroke-width="0.4" opacity="0.35"/>
</g>
<text x="12" y="42" class="lbl">Mind Reading</text>
</g>
<!-- 4. FORTUNE TELLING — A crystal ball shape with forward-pointing shard -->
<g transform="translate(364, 60)" filter="url(#gAmber)">
<g transform="translate(12,12)">
<!-- Crystal ball: faceted circle (octagon) -->
<path d="M 0,-9 L 6,-6 L 9,0 L 6,6 L 0,9 L -6,6 L -9,0 L -6,-6 Z" fill="none" stroke="#F59E0B" stroke-width="0.8" opacity="0.6"/>
<!-- Inner glow -->
<circle cx="0" cy="0" r="4" fill="#F59E0B" opacity="0.15"/>
<!-- Forward arrow shard -->
<path d="M 2,0 L 10,-3 L 14,0 L 10,3 Z" fill="url(#amberGr)" opacity="0.8"/>
<path d="M 2,0 L 10,-3 L 14,0 Z" fill="#fff" opacity="0.12"/>
<!-- Base -->
<path d="M -5,9 L 5,9 L 3,12 L -3,12 Z" fill="#F59E0B" opacity="0.3"/>
</g>
<text x="12" y="42" class="lbl">Fortune Telling</text>
</g>
<!-- 5. PERSONALIZATION — Inward-pointing shard arrows converging on center -->
<g transform="translate(476, 60)" filter="url(#gAmber)">
<g transform="translate(12,12)">
<!-- Center dot -->
<circle cx="0" cy="0" r="2.5" fill="url(#amberGr)" opacity="0.8"/>
<!-- Four inward-pointing shards -->
<path d="M 0,-12 L 2,-6 L 0,-4 L -2,-6 Z" fill="#F59E0B" opacity="0.7"/>
<path d="M 12,0 L 6,2 L 4,0 L 6,-2 Z" fill="#F59E0B" opacity="0.6"/>
<path d="M 0,12 L -2,6 L 0,4 L 2,6 Z" fill="#F59E0B" opacity="0.6"/>
<path d="M -12,0 L -6,-2 L -4,0 L -6,2 Z" fill="#F59E0B" opacity="0.7"/>
<!-- Subtle connecting lines -->
<line x1="0" y1="-4" x2="0" y2="-2.5" stroke="#FCD34D" stroke-width="0.4" opacity="0.3"/>
<line x1="4" y1="0" x2="2.5" y2="0" stroke="#FCD34D" stroke-width="0.4" opacity="0.3"/>
</g>
<text x="12" y="42" class="lbl">Personalization</text>
</g>
<!-- Row 2: 5 icons -->
<!-- 6. DISCOUNTING POSITIVES — A star/gem shape with a line through it -->
<g transform="translate(28, 180)" filter="url(#gAmber)">
<g transform="translate(12,12)">
<!-- 6-pointed star -->
<path d="M 0,-10 L 3,-4 L 9,-4 L 5,1 L 7,7 L 0,4 L -7,7 L -5,1 L -9,-4 L -3,-4 Z" fill="url(#amberGr)" opacity="0.5"/>
<path d="M 0,-10 L 3,-4 L -3,-4 Z" fill="#fff" opacity="0.1"/>
<!-- Strike-through line (discounting) -->
<line x1="-10" y1="4" x2="10" y2="-4" stroke="#FEF3C7" stroke-width="1.2" opacity="0.7"/>
<!-- Dimmed effect on the star -->
<path d="M 0,-10 L 3,-4 L 9,-4 L 5,1 L 7,7 L 0,4 L -7,7 L -5,1 L -9,-4 L -3,-4 Z" fill="#050508" opacity="0.3"/>
</g>
<text x="12" y="42" class="lbl">Discounting +</text>
</g>
<!-- 7. EMOTIONAL REASONING — A heart shape made of angular geometry with = sign -->
<g transform="translate(140, 180)" filter="url(#gAmber)">
<g transform="translate(12,12)">
<!-- Angular heart: two triangles forming a V-heart -->
<path d="M 0,8 L -8,-1 L -5,-7 L 0,-3 L 5,-7 L 8,-1 Z" fill="url(#amberGr)" opacity="0.7"/>
<path d="M 0,-3 L -5,-7 L -8,-1 Z" fill="#fff" opacity="0.12"/>
<!-- Equals sign next to it -->
<line x1="9" y1="-2" x2="14" y2="-2" stroke="#FCD34D" stroke-width="1" opacity="0.6"/>
<line x1="9" y1="2" x2="14" y2="2" stroke="#FCD34D" stroke-width="1" opacity="0.6"/>
</g>
<text x="12" y="42" class="lbl">Emotional Reasoning</text>
</g>
<!-- 8. SHOULD STATEMENTS — A rigid angular ruler/bracket shape -->
<g transform="translate(252, 180)" filter="url(#gAmber)">
<g transform="translate(12,12)">
<!-- Rigid L-bracket -->
<path d="M -6,-10 L -6,10 L 6,10" fill="none" stroke="#F59E0B" stroke-width="1.2" stroke-linejoin="miter"/>
<!-- Tick marks along the ruler -->
<line x1="-6" y1="-6" x2="-3" y2="-6" stroke="#FCD34D" stroke-width="0.6" opacity="0.5"/>
<line x1="-6" y1="-2" x2="-3" y2="-2" stroke="#FCD34D" stroke-width="0.6" opacity="0.5"/>
<line x1="-6" y1="2" x2="-3" y2="2" stroke="#FCD34D" stroke-width="0.6" opacity="0.5"/>
<line x1="-6" y1="6" x2="-3" y2="6" stroke="#FCD34D" stroke-width="0.6" opacity="0.5"/>
<!-- Angular exclamation inside -->
<path d="M 2,-4 L 3,-1 L 1,-1 Z" fill="#FCD34D" opacity="0.6"/>
<circle cx="2" cy="1" r="0.8" fill="#FCD34D" opacity="0.6"/>
</g>
<text x="12" y="42" class="lbl">Should Statements</text>
</g>
<!-- 9. LABELING — An angular tag/label shape -->
<g transform="translate(364, 180)" filter="url(#gAmber)">
<g transform="translate(12,12)">
<!-- Tag shape: pentagon pointing right -->
<path d="M -8,-7 L 5,-7 L 10,0 L 5,7 L -8,7 Z" fill="url(#amberGr)" opacity="0.6"/>
<path d="M -8,-7 L 5,-7 L 10,0 Z" fill="#fff" opacity="0.1"/>
<!-- Hole in tag -->
<circle cx="-3" cy="0" r="2" fill="#050508" opacity="0.6" stroke="#FCD34D" stroke-width="0.5"/>
<!-- Inner line -->
<line x1="1" y1="-3" x2="1" y2="3" stroke="#FEF3C7" stroke-width="0.4" opacity="0.3"/>
</g>
<text x="12" y="42" class="lbl">Labeling</text>
</g>
<!-- 10. OVERGENERALIZATION — One dot replicating into many -->
<g transform="translate(476, 180)" filter="url(#gAmber)">
<g transform="translate(12,12)">
<!-- Single source diamond -->
<path d="M -10,0 L -7,-3 L -4,0 L -7,3 Z" fill="url(#amberGr)" opacity="0.9"/>
<path d="M -10,0 L -7,-3 L -4,0 Z" fill="#fff" opacity="0.15"/>
<!-- Arrow -->
<line x1="-3" y1="0" x2="0" y2="0" stroke="#FCD34D" stroke-width="0.5" opacity="0.4"/>
<!-- Multiple replicated diamonds (spreading out) -->
<path d="M 2,-6 L 4,-8 L 6,-6 L 4,-4 Z" fill="#F59E0B" opacity="0.7"/>
<path d="M 4,0 L 6,-2 L 8,0 L 6,2 Z" fill="#F59E0B" opacity="0.6"/>
<path d="M 2,6 L 4,4 L 6,6 L 4,8 Z" fill="#F59E0B" opacity="0.5"/>
<path d="M 8,-4 L 10,-6 L 12,-4 L 10,-2 Z" fill="#F59E0B" opacity="0.4"/>
<path d="M 8,4 L 10,2 L 12,4 L 10,6 Z" fill="#F59E0B" opacity="0.35"/>
</g>
<text x="12" y="42" class="lbl">Overgeneralization</text>
</g>
<!-- Color reference -->
<text x="280" y="278" font-size="9" fill="#475569" text-anchor="middle">Primary: #F59E0B (Amber) — Gradient: #FDE68A to #D97706 — Highlight: #FCD34D</text>
<text x="280" y="292" font-size="9" fill="#475569" text-anchor="middle">All icons 24x24px — Glow filter for active/detected state — Outlined for reference/guide</text>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,258 @@
<svg viewBox="0 0 520 480" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- Glow filters matched to soft-elegance: layered gaussian blur + source merge -->
<filter id="gAmethyst" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="2.5" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="gAmber" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="2.5" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="gEmerald" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="2.5" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="gSapphire" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="2.5" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="gSoft" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="2" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<!-- Gradients — mimicking the soft-elegance per-blade gradient approach -->
<linearGradient id="grAmethyst" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#C4B5FD"/>
<stop offset="100%" stop-color="#7C3AED"/>
</linearGradient>
<linearGradient id="grAmber" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FDE68A"/>
<stop offset="100%" stop-color="#D97706"/>
</linearGradient>
<linearGradient id="grEmerald" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#6EE7B7"/>
<stop offset="100%" stop-color="#047857"/>
</linearGradient>
<linearGradient id="grSapphire" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#93C5FD"/>
<stop offset="100%" stop-color="#1D4ED8"/>
</linearGradient>
<linearGradient id="grSoftLight" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#F1F5F9"/>
<stop offset="100%" stop-color="#CBD5E1"/>
</linearGradient>
<style>
text { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; }
</style>
</defs>
<rect width="520" height="480" fill="#050508"/>
<!-- Title -->
<text x="260" y="32" font-size="14" font-weight="600" fill="#94A3B8" text-anchor="middle" letter-spacing="0.12em">TAB BAR ICONS</text>
<!-- ================================================ -->
<!-- ROW 1: ACTIVE STATES -->
<!-- ================================================ -->
<text x="260" y="68" font-size="11" fill="#475569" text-anchor="middle" letter-spacing="0.08em">ACTIVE</text>
<!-- ◇ TURN — Active (Amethyst) -->
<g transform="translate(52, 100)">
<g filter="url(#gAmethyst)">
<!-- Outer diamond -->
<path d="M 24,2 L 44,24 L 24,46 L 4,24 Z" fill="url(#grAmethyst)" opacity="0.9"/>
<!-- Inner facet: horizontal midline creating top/bottom facets -->
<line x1="4" y1="24" x2="44" y2="24" stroke="#fff" stroke-width="0.5" opacity="0.35"/>
<!-- Inner facet: vertical center line -->
<line x1="24" y1="2" x2="24" y2="46" stroke="#fff" stroke-width="0.4" opacity="0.2"/>
<!-- Top facet highlight -->
<path d="M 24,2 L 44,24 L 4,24 Z" fill="#fff" opacity="0.12"/>
<!-- Specular glint -->
<circle cx="18" cy="18" r="2" fill="#fff" opacity="0.4"/>
<!-- Small rotating inner shard (suggests kaleidoscope turn) -->
<path d="M 24,12 L 30,24 L 24,36 L 18,24 Z" fill="none" stroke="#E9D5FF" stroke-width="0.6" opacity="0.5"/>
</g>
<text x="24" y="64" font-size="10" font-weight="600" fill="#C4B5FD" text-anchor="middle" letter-spacing="0.06em">TURN</text>
</g>
<!-- ✦ MIRROR — Active (Amber) -->
<g transform="translate(152, 100)">
<g filter="url(#gAmber)">
<!-- Hexagonal mirror shape -->
<path d="M 24,3 L 42,14 L 42,35 L 24,46 L 6,35 L 6,14 Z" fill="url(#grAmber)" opacity="0.9"/>
<!-- Horizontal reflection line -->
<line x1="6" y1="24.5" x2="42" y2="24.5" stroke="#fff" stroke-width="0.6" opacity="0.4"/>
<!-- Inner hexagon (mirror reflection) -->
<path d="M 24,10 L 35,17 L 35,32 L 24,39 L 13,32 L 13,17 Z" fill="none" stroke="#FEF3C7" stroke-width="0.5" opacity="0.4"/>
<!-- Top facet light -->
<path d="M 24,3 L 42,14 L 6,14 Z" fill="#fff" opacity="0.1"/>
<!-- Specular -->
<circle cx="19" cy="17" r="1.8" fill="#fff" opacity="0.35"/>
</g>
<text x="24" y="64" font-size="10" font-weight="600" fill="#FCD34D" text-anchor="middle" letter-spacing="0.06em">MIRROR</text>
</g>
<!-- ◎ LENS — Active (Emerald) -->
<g transform="translate(252, 100)">
<g filter="url(#gEmerald)">
<!-- Outer lens circle -->
<circle cx="24" cy="24" r="20" fill="none" stroke="url(#grEmerald)" stroke-width="2" opacity="0.9"/>
<!-- Middle ring -->
<circle cx="24" cy="24" r="13" fill="none" stroke="#6EE7B7" stroke-width="1" opacity="0.5"/>
<!-- Inner core (focus point) -->
<circle cx="24" cy="24" r="5" fill="url(#grEmerald)" opacity="0.8"/>
<!-- Cross-hair lines suggesting focus/precision -->
<line x1="24" y1="6" x2="24" y2="14" stroke="#A7F3D0" stroke-width="0.5" opacity="0.4"/>
<line x1="24" y1="34" x2="24" y2="42" stroke="#A7F3D0" stroke-width="0.5" opacity="0.4"/>
<line x1="6" y1="24" x2="14" y2="24" stroke="#A7F3D0" stroke-width="0.5" opacity="0.4"/>
<line x1="34" y1="24" x2="42" y2="24" stroke="#A7F3D0" stroke-width="0.5" opacity="0.4"/>
<!-- Specular -->
<circle cx="19" cy="19" r="2.5" fill="#fff" opacity="0.2"/>
</g>
<text x="24" y="64" font-size="10" font-weight="600" fill="#6EE7B7" text-anchor="middle" letter-spacing="0.06em">LENS</text>
</g>
<!-- ▦ GALLERY — Active (Sapphire) -->
<g transform="translate(352, 100)">
<g filter="url(#gSapphire)">
<!-- 2x2 grid of small faceted shapes -->
<!-- Top-left diamond -->
<path d="M 12,6 L 20,12 L 12,18 L 4,12 Z" fill="url(#grSapphire)" opacity="0.85"/>
<path d="M 12,6 L 20,12 L 4,12 Z" fill="#fff" opacity="0.1"/>
<!-- Top-right diamond -->
<path d="M 36,6 L 44,12 L 36,18 L 28,12 Z" fill="url(#grSapphire)" opacity="0.75"/>
<path d="M 36,6 L 44,12 L 28,12 Z" fill="#fff" opacity="0.08"/>
<!-- Bottom-left diamond -->
<path d="M 12,28 L 20,34 L 12,40 L 4,34 Z" fill="url(#grSapphire)" opacity="0.7"/>
<path d="M 12,28 L 20,34 L 4,34 Z" fill="#fff" opacity="0.08"/>
<!-- Bottom-right diamond -->
<path d="M 36,28 L 44,34 L 36,40 L 28,34 Z" fill="url(#grSapphire)" opacity="0.85"/>
<path d="M 36,28 L 44,34 L 28,34 Z" fill="#fff" opacity="0.1"/>
<!-- Thin connecting lines -->
<line x1="20" y1="12" x2="28" y2="12" stroke="#93C5FD" stroke-width="0.4" opacity="0.3"/>
<line x1="12" y1="18" x2="12" y2="28" stroke="#93C5FD" stroke-width="0.4" opacity="0.3"/>
<line x1="36" y1="18" x2="36" y2="28" stroke="#93C5FD" stroke-width="0.4" opacity="0.3"/>
<line x1="20" y1="34" x2="28" y2="34" stroke="#93C5FD" stroke-width="0.4" opacity="0.3"/>
</g>
<text x="24" y="64" font-size="10" font-weight="600" fill="#93C5FD" text-anchor="middle" letter-spacing="0.06em">GALLERY</text>
</g>
<!-- ● YOU — Active (Soft Light) -->
<g transform="translate(452, 100)">
<g filter="url(#gSoft)">
<!-- Angular avatar: hexagonal head + angular shoulders -->
<path d="M 24,4 L 32,10 L 32,20 L 24,26 L 16,20 L 16,10 Z" fill="url(#grSoftLight)" opacity="0.85"/>
<path d="M 24,4 L 32,10 L 16,10 Z" fill="#fff" opacity="0.12"/>
<!-- Shoulders: angular trapezoid -->
<path d="M 8,46 L 14,32 L 24,28 L 34,32 L 40,46 Z" fill="url(#grSoftLight)" opacity="0.65"/>
<path d="M 14,32 L 24,28 L 34,32 Z" fill="#fff" opacity="0.08"/>
<!-- Specular on face -->
<circle cx="20" cy="14" r="1.5" fill="#fff" opacity="0.3"/>
</g>
<text x="24" y="64" font-size="10" font-weight="600" fill="#E2E8F0" text-anchor="middle" letter-spacing="0.06em">YOU</text>
</g>
<!-- ================================================ -->
<!-- ROW 2: INACTIVE STATES -->
<!-- ================================================ -->
<text x="260" y="212" font-size="11" fill="#475569" text-anchor="middle" letter-spacing="0.08em">INACTIVE</text>
<!-- ◇ TURN — Inactive -->
<g transform="translate(52, 240)">
<path d="M 24,2 L 44,24 L 24,46 L 4,24 Z" fill="none" stroke="#475569" stroke-width="1.2"/>
<line x1="4" y1="24" x2="44" y2="24" stroke="#475569" stroke-width="0.4" opacity="0.3"/>
<path d="M 24,12 L 30,24 L 24,36 L 18,24 Z" fill="none" stroke="#475569" stroke-width="0.5" opacity="0.3"/>
<text x="24" y="64" font-size="10" font-weight="500" fill="#475569" text-anchor="middle" letter-spacing="0.06em">TURN</text>
</g>
<!-- ✦ MIRROR — Inactive -->
<g transform="translate(152, 240)">
<path d="M 24,3 L 42,14 L 42,35 L 24,46 L 6,35 L 6,14 Z" fill="none" stroke="#475569" stroke-width="1.2"/>
<line x1="6" y1="24.5" x2="42" y2="24.5" stroke="#475569" stroke-width="0.4" opacity="0.3"/>
<path d="M 24,10 L 35,17 L 35,32 L 24,39 L 13,32 L 13,17 Z" fill="none" stroke="#475569" stroke-width="0.4" opacity="0.25"/>
<text x="24" y="64" font-size="10" font-weight="500" fill="#475569" text-anchor="middle" letter-spacing="0.06em">MIRROR</text>
</g>
<!-- ◎ LENS — Inactive -->
<g transform="translate(252, 240)">
<circle cx="24" cy="24" r="20" fill="none" stroke="#475569" stroke-width="1.2"/>
<circle cx="24" cy="24" r="13" fill="none" stroke="#475569" stroke-width="0.5" opacity="0.3"/>
<circle cx="24" cy="24" r="5" fill="none" stroke="#475569" stroke-width="0.8" opacity="0.5"/>
<line x1="24" y1="6" x2="24" y2="14" stroke="#475569" stroke-width="0.4" opacity="0.25"/>
<line x1="24" y1="34" x2="24" y2="42" stroke="#475569" stroke-width="0.4" opacity="0.25"/>
<line x1="6" y1="24" x2="14" y2="24" stroke="#475569" stroke-width="0.4" opacity="0.25"/>
<line x1="34" y1="24" x2="42" y2="24" stroke="#475569" stroke-width="0.4" opacity="0.25"/>
<text x="24" y="64" font-size="10" font-weight="500" fill="#475569" text-anchor="middle" letter-spacing="0.06em">LENS</text>
</g>
<!-- ▦ GALLERY — Inactive -->
<g transform="translate(352, 240)">
<path d="M 12,6 L 20,12 L 12,18 L 4,12 Z" fill="none" stroke="#475569" stroke-width="1"/>
<path d="M 36,6 L 44,12 L 36,18 L 28,12 Z" fill="none" stroke="#475569" stroke-width="1"/>
<path d="M 12,28 L 20,34 L 12,40 L 4,34 Z" fill="none" stroke="#475569" stroke-width="1"/>
<path d="M 36,28 L 44,34 L 36,40 L 28,34 Z" fill="none" stroke="#475569" stroke-width="1"/>
<line x1="20" y1="12" x2="28" y2="12" stroke="#475569" stroke-width="0.3" opacity="0.25"/>
<line x1="12" y1="18" x2="12" y2="28" stroke="#475569" stroke-width="0.3" opacity="0.25"/>
<line x1="36" y1="18" x2="36" y2="28" stroke="#475569" stroke-width="0.3" opacity="0.25"/>
<line x1="20" y1="34" x2="28" y2="34" stroke="#475569" stroke-width="0.3" opacity="0.25"/>
<text x="24" y="64" font-size="10" font-weight="500" fill="#475569" text-anchor="middle" letter-spacing="0.06em">GALLERY</text>
</g>
<!-- ● YOU — Inactive -->
<g transform="translate(452, 240)">
<path d="M 24,4 L 32,10 L 32,20 L 24,26 L 16,20 L 16,10 Z" fill="none" stroke="#475569" stroke-width="1.2"/>
<path d="M 8,46 L 14,32 L 24,28 L 34,32 L 40,46 Z" fill="none" stroke="#475569" stroke-width="1" opacity="0.6"/>
<text x="24" y="64" font-size="10" font-weight="500" fill="#475569" text-anchor="middle" letter-spacing="0.06em">YOU</text>
</g>
<!-- ================================================ -->
<!-- ROW 3: SIMULATED TAB BAR (in-context preview) -->
<!-- ================================================ -->
<text x="260" y="356" font-size="11" fill="#475569" text-anchor="middle" letter-spacing="0.08em">TAB BAR PREVIEW (Turn active)</text>
<!-- Tab bar background -->
<rect x="35" y="370" width="450" height="80" rx="16" fill="#0A0E1A" stroke="#1C2240" stroke-width="1"/>
<line x1="35" y1="370" x2="485" y2="370" stroke="#1C2240" stroke-width="1"/>
<!-- Turn — Active -->
<g transform="translate(62, 380)">
<g filter="url(#gAmethyst)">
<path d="M 12,1 L 22,12 L 12,23 L 2,12 Z" fill="url(#grAmethyst)" opacity="0.9"/>
<path d="M 12,1 L 22,12 L 2,12 Z" fill="#fff" opacity="0.1"/>
<line x1="2" y1="12" x2="22" y2="12" stroke="#fff" stroke-width="0.4" opacity="0.25"/>
</g>
<text x="12" y="36" font-size="9" font-weight="600" fill="#C4B5FD" text-anchor="middle" letter-spacing="0.04em">Turn</text>
</g>
<!-- Mirror — Inactive -->
<g transform="translate(152, 380)">
<path d="M 12,1.5 L 21,7.5 L 21,17.5 L 12,23.5 L 3,17.5 L 3,7.5 Z" fill="none" stroke="#475569" stroke-width="1"/>
<text x="12" y="36" font-size="9" font-weight="500" fill="#475569" text-anchor="middle" letter-spacing="0.04em">Mirror</text>
</g>
<!-- Lens — Inactive -->
<g transform="translate(242, 380)">
<circle cx="12" cy="12" r="10" fill="none" stroke="#475569" stroke-width="1"/>
<circle cx="12" cy="12" r="3" fill="none" stroke="#475569" stroke-width="0.6" opacity="0.5"/>
<text x="12" y="36" font-size="9" font-weight="500" fill="#475569" text-anchor="middle" letter-spacing="0.04em">Lens</text>
</g>
<!-- Gallery — Inactive -->
<g transform="translate(327, 380)">
<path d="M 6,3 L 10,6 L 6,9 L 2,6 Z" fill="none" stroke="#475569" stroke-width="0.8"/>
<path d="M 18,3 L 22,6 L 18,9 L 14,6 Z" fill="none" stroke="#475569" stroke-width="0.8"/>
<path d="M 6,15 L 10,18 L 6,21 L 2,18 Z" fill="none" stroke="#475569" stroke-width="0.8"/>
<path d="M 18,15 L 22,18 L 18,21 L 14,18 Z" fill="none" stroke="#475569" stroke-width="0.8"/>
<text x="12" y="36" font-size="9" font-weight="500" fill="#475569" text-anchor="middle" letter-spacing="0.04em">Gallery</text>
</g>
<!-- You — Inactive -->
<g transform="translate(417, 380)">
<path d="M 12,2 L 16,5 L 16,10 L 12,13 L 8,10 L 8,5 Z" fill="none" stroke="#475569" stroke-width="0.9"/>
<path d="M 4,23 L 7,16 L 12,14 L 17,16 L 20,23 Z" fill="none" stroke="#475569" stroke-width="0.8" opacity="0.6"/>
<text x="12" y="36" font-size="9" font-weight="500" fill="#475569" text-anchor="middle" letter-spacing="0.04em">You</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,389 @@
<svg viewBox="0 0 700 820" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grAmethyst" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#C4B5FD"><animate attributeName="stop-color" values="#C4B5FD;#DDD6FE;#C4B5FD" dur="4s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#7C3AED"/>
</linearGradient>
<linearGradient id="grSapphire" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#93C5FD"/><stop offset="100%" stop-color="#2563EB"/>
</linearGradient>
<linearGradient id="grEmerald" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#6EE7B7"/><stop offset="100%" stop-color="#059669"/>
</linearGradient>
<linearGradient id="grAmber" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FDE68A"/><stop offset="100%" stop-color="#D97706"/>
</linearGradient>
<linearGradient id="grRose" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBCFE8"/><stop offset="100%" stop-color="#DB2777"/>
</linearGradient>
<linearGradient id="grIndigo" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#A5B4FC"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<linearGradient id="shimmerGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#1C2240" stop-opacity="0"/>
<stop offset="50%" stop-color="#2A3158" stop-opacity="1"/>
<stop offset="100%" stop-color="#1C2240" stop-opacity="0"/>
</linearGradient>
<radialGradient id="successGlow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#10B981" stop-opacity="0.4"/>
<stop offset="100%" stop-color="#10B981" stop-opacity="0"/>
</radialGradient>
<filter id="glowSm" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="1.5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowMd" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowLg" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="6" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="shimmer" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="2" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<style>
text { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; }
.lbl { font-size: 9px; fill: #94A3B8; text-anchor: middle; font-weight: 500; }
.section-lbl { font-size: 11px; fill: #64748B; font-weight: 600; letter-spacing: 0.08em; }
</style>
</defs>
<rect width="700" height="820" fill="#050508"/>
<text x="350" y="28" font-size="13" font-weight="700" fill="#94A3B8" text-anchor="middle" letter-spacing="0.12em">LOADING AND ANIMATION STATES</text>
<text x="350" y="44" font-size="9" fill="#475569" text-anchor="middle">Spinners, skeleton shimmers, Turn animation, AI thinking, success burst, breathing logo</text>
<!-- Row 1: Spinners -->
<text x="24" y="74" class="section-lbl">SPINNERS</text>
<line x1="24" y1="80" x2="670" y2="80" stroke="#1C2240" stroke-width="0.5"/>
<!-- 1. Fragment Spinner — rotating diamond with trail -->
<g transform="translate(100, 140)">
<g filter="url(#glowMd)">
<g>
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="1.5s" repeatCount="indefinite"/>
<!-- Trail fragments (fading) -->
<path d="M 0,-20 L 4,-16 L 0,-12 L -4,-16 Z" fill="url(#grAmethyst)" opacity="0.9"/>
<path d="M 0,-20 L 4,-16 L 0,-16 Z" fill="#fff" opacity="0.2"/>
<g transform="rotate(90)">
<path d="M 0,-20 L 4,-16 L 0,-12 L -4,-16 Z" fill="url(#grSapphire)" opacity="0.6"/>
</g>
<g transform="rotate(180)">
<path d="M 0,-20 L 4,-16 L 0,-12 L -4,-16 Z" fill="url(#grEmerald)" opacity="0.3"/>
</g>
<g transform="rotate(270)">
<path d="M 0,-20 L 4,-16 L 0,-12 L -4,-16 Z" fill="url(#grAmber)" opacity="0.15"/>
</g>
</g>
</g>
<text x="0" y="42" class="lbl">Fragment Spinner</text>
</g>
<!-- 2. Iris Spinner — mini kaleidoscope rotation -->
<g transform="translate(260, 140)">
<g filter="url(#glowMd)">
<g>
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="3s" repeatCount="indefinite"/>
<g style="mix-blend-mode: screen;">
<path d="M 0,0 L 3,-1 L -2,20 L -3,1 Z" fill="url(#grAmethyst)" opacity="0.6">
<animate attributeName="fill-opacity" values="0.4;0.7;0.4" dur="2s" repeatCount="indefinite"/>
</path>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(60)">
<path d="M 0,0 L 3,-1 L -2,20 L -3,1 Z" fill="url(#grSapphire)" opacity="0.5"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(120)">
<path d="M 0,0 L 3,-1 L -2,20 L -3,1 Z" fill="url(#grEmerald)" opacity="0.5"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(180)">
<path d="M 0,0 L 3,-1 L -2,20 L -3,1 Z" fill="url(#grAmber)" opacity="0.6"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(240)">
<path d="M 0,0 L 3,-1 L -2,20 L -3,1 Z" fill="url(#grRose)" opacity="0.5"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(300)">
<path d="M 0,0 L 3,-1 L -2,20 L -3,1 Z" fill="url(#grIndigo)" opacity="0.5"/>
</g>
</g>
<circle r="3" fill="#fff" opacity="0.5">
<animate attributeName="opacity" values="0.3;0.7;0.3" dur="1.5s" repeatCount="indefinite"/>
</circle>
</g>
<text x="0" y="42" class="lbl">Iris Spinner (mini logo)</text>
</g>
<!-- 3. Dot Pulse Loader -->
<g transform="translate(420, 140)">
<g filter="url(#glowSm)">
<circle cx="-16" cy="0" r="4" fill="url(#grAmethyst)" opacity="0.3">
<animate attributeName="opacity" values="0.3;0.9;0.3" dur="1.2s" begin="0s" repeatCount="indefinite"/>
<animate attributeName="r" values="3;5;3" dur="1.2s" begin="0s" repeatCount="indefinite"/>
</circle>
<circle cx="0" cy="0" r="4" fill="url(#grSapphire)" opacity="0.3">
<animate attributeName="opacity" values="0.3;0.9;0.3" dur="1.2s" begin="0.2s" repeatCount="indefinite"/>
<animate attributeName="r" values="3;5;3" dur="1.2s" begin="0.2s" repeatCount="indefinite"/>
</circle>
<circle cx="16" cy="0" r="4" fill="url(#grEmerald)" opacity="0.3">
<animate attributeName="opacity" values="0.3;0.9;0.3" dur="1.2s" begin="0.4s" repeatCount="indefinite"/>
<animate attributeName="r" values="3;5;3" dur="1.2s" begin="0.4s" repeatCount="indefinite"/>
</circle>
</g>
<text x="0" y="28" class="lbl">Dot Pulse</text>
</g>
<!-- 4. Fragment Orbit Loader -->
<g transform="translate(580, 140)">
<g filter="url(#shimmer)">
<!-- Orbit path -->
<circle r="18" fill="none" stroke="#1C2240" stroke-width="0.4"/>
<!-- Orbiting fragment -->
<g>
<path d="M 0,-4 L 4,0 L 0,4 L -4,0 Z" fill="url(#grAmethyst)" opacity="0.8">
<animate attributeName="opacity" values="0.5;1;0.5" dur="1.8s" repeatCount="indefinite"/>
</path>
<animateMotion dur="1.8s" repeatCount="indefinite" path="M0,-18 A18,18 0 1 1 -0.1,-18"/>
</g>
<!-- Ghost trail -->
<g>
<path d="M 0,-3 L 3,0 L 0,3 L -3,0 Z" fill="#8B5CF6" opacity="0.3">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="1.8s" begin="0.3s" repeatCount="indefinite"/>
</path>
<animateMotion dur="1.8s" repeatCount="indefinite" path="M0,-18 A18,18 0 1 1 -0.1,-18" begin="0.3s"/>
</g>
</g>
<text x="0" y="38" class="lbl">Fragment Orbit</text>
</g>
<!-- Row 2: Skeleton Shimmers -->
<text x="24" y="204" class="section-lbl">SKELETON SHIMMERS</text>
<line x1="24" y1="210" x2="670" y2="210" stroke="#1C2240" stroke-width="0.5"/>
<!-- Text skeleton -->
<g transform="translate(175, 250)">
<rect x="-120" y="-8" width="160" height="10" rx="5" fill="#121628"/>
<rect x="-120" y="-8" width="40" height="10" rx="5" fill="url(#shimmerGrad)" opacity="0.5">
<animate attributeName="x" values="-160;120" dur="1.5s" repeatCount="indefinite"/>
</rect>
<rect x="-120" y="8" width="200" height="10" rx="5" fill="#121628"/>
<rect x="-120" y="8" width="40" height="10" rx="5" fill="url(#shimmerGrad)" opacity="0.5">
<animate attributeName="x" values="-160;160" dur="1.5s" begin="0.2s" repeatCount="indefinite"/>
</rect>
<rect x="-120" y="24" width="120" height="10" rx="5" fill="#121628"/>
<rect x="-120" y="24" width="40" height="10" rx="5" fill="url(#shimmerGrad)" opacity="0.5">
<animate attributeName="x" values="-160;80" dur="1.5s" begin="0.4s" repeatCount="indefinite"/>
</rect>
<text x="-20" y="54" class="lbl">Text skeleton shimmer</text>
</g>
<!-- Card skeleton -->
<g transform="translate(500, 250)">
<rect x="-80" y="-30" width="160" height="80" rx="10" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.5"/>
<!-- Image placeholder -->
<rect x="-68" y="-20" width="40" height="40" rx="6" fill="#121628"/>
<rect x="-68" y="-20" width="20" height="40" rx="6" fill="url(#shimmerGrad)" opacity="0.4">
<animate attributeName="x" values="-88;-28" dur="1.5s" repeatCount="indefinite"/>
</rect>
<!-- Text lines -->
<rect x="-16" y="-16" width="80" height="8" rx="4" fill="#121628"/>
<rect x="-16" y="-16" width="20" height="8" rx="4" fill="url(#shimmerGrad)" opacity="0.4">
<animate attributeName="x" values="-36;64" dur="1.5s" begin="0.1s" repeatCount="indefinite"/>
</rect>
<rect x="-16" y="-2" width="60" height="8" rx="4" fill="#121628"/>
<rect x="-16" y="12" width="40" height="6" rx="3" fill="#121628"/>
<text x="0" y="66" class="lbl">Card skeleton shimmer</text>
</g>
<!-- Row 3: Turn Animation, AI Thinking -->
<text x="24" y="344" class="section-lbl">FEATURE ANIMATIONS</text>
<line x1="24" y1="350" x2="670" y2="350" stroke="#1C2240" stroke-width="0.5"/>
<!-- Turn Animation — kaleidoscope shift -->
<g transform="translate(175, 430)">
<g filter="url(#glowLg)">
<g>
<animateTransform attributeName="transform" type="rotate" from="0" to="60" dur="2s" repeatCount="indefinite"/>
<g style="mix-blend-mode: screen;">
<path d="M 0,0 L 6,-2 L -4,35 L -6,1 Z" fill="url(#grAmethyst)" opacity="0.5">
<animate attributeName="fill-opacity" values="0.3;0.6;0.3" dur="2s" repeatCount="indefinite"/>
</path>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(60)">
<path d="M 0,0 L 6,-2 L -4,35 L -6,1 Z" fill="url(#grSapphire)" opacity="0.45"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(120)">
<path d="M 0,0 L 6,-2 L -4,35 L -6,1 Z" fill="url(#grEmerald)" opacity="0.4"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(180)">
<path d="M 0,0 L 6,-2 L -4,35 L -6,1 Z" fill="url(#grAmber)" opacity="0.5"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(240)">
<path d="M 0,0 L 6,-2 L -4,35 L -6,1 Z" fill="url(#grRose)" opacity="0.45"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(300)">
<path d="M 0,0 L 6,-2 L -4,35 L -6,1 Z" fill="url(#grIndigo)" opacity="0.4"/>
</g>
</g>
<!-- Core pulse -->
<circle r="8" fill="#fff" opacity="0.4" filter="url(#glowMd)">
<animate attributeName="r" values="6;10;6" dur="2s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.3;0.6;0.3" dur="2s" repeatCount="indefinite"/>
</circle>
<circle r="3" fill="#fff" opacity="0.7"/>
</g>
<text x="0" y="60" class="lbl">Turn Animation (reframe moment)</text>
<text x="0" y="72" font-size="8" fill="#475569" text-anchor="middle">Rotates 60deg per cycle, pulses core</text>
</g>
<!-- AI Thinking — 3 fragments oscillating -->
<g transform="translate(475, 430)">
<g filter="url(#glowMd)">
<!-- Background bubble -->
<rect x="-50" y="-20" width="100" height="40" rx="20" fill="#121628" stroke="#1C2240" stroke-width="0.6"/>
<!-- Three oscillating fragments -->
<g transform="translate(-20, 0)">
<path d="M 0,-5 L 5,0 L 0,5 L -5,0 Z" fill="url(#grAmethyst)" opacity="0.4">
<animate attributeName="opacity" values="0.2;0.8;0.2" dur="1.5s" begin="0s" repeatCount="indefinite"/>
<animateTransform attributeName="transform" type="translate" values="-20,-3;-20,3;-20,-3" dur="1.5s" begin="0s" repeatCount="indefinite"/>
</path>
</g>
<g transform="translate(0, 0)">
<path d="M 0,-5 L 5,0 L 0,5 L -5,0 Z" fill="url(#grSapphire)" opacity="0.4">
<animate attributeName="opacity" values="0.2;0.8;0.2" dur="1.5s" begin="0.3s" repeatCount="indefinite"/>
<animateTransform attributeName="transform" type="translate" values="0,-3;0,3;0,-3" dur="1.5s" begin="0.3s" repeatCount="indefinite"/>
</path>
</g>
<g transform="translate(20, 0)">
<path d="M 0,-5 L 5,0 L 0,5 L -5,0 Z" fill="url(#grEmerald)" opacity="0.4">
<animate attributeName="opacity" values="0.2;0.8;0.2" dur="1.5s" begin="0.6s" repeatCount="indefinite"/>
<animateTransform attributeName="transform" type="translate" values="20,-3;20,3;20,-3" dur="1.5s" begin="0.6s" repeatCount="indefinite"/>
</path>
</g>
</g>
<text x="0" y="40" class="lbl">AI Thinking (Claude processing)</text>
</g>
<!-- Row 4: Success Burst, Breathing Logo -->
<text x="24" y="524" class="section-lbl">COMPLETION STATES</text>
<line x1="24" y1="530" x2="670" y2="530" stroke="#1C2240" stroke-width="0.5"/>
<!-- Success Burst -->
<g transform="translate(175, 610)">
<g filter="url(#glowLg)">
<!-- Burst ring -->
<circle r="30" fill="none" stroke="#10B981" stroke-width="2" opacity="0">
<animate attributeName="r" values="10;35;40" dur="1.5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.6;0.3;0" dur="1.5s" repeatCount="indefinite"/>
</circle>
<circle r="20" fill="none" stroke="#6EE7B7" stroke-width="1" opacity="0">
<animate attributeName="r" values="8;25;30" dur="1.5s" begin="0.2s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.4;0.2;0" dur="1.5s" begin="0.2s" repeatCount="indefinite"/>
</circle>
<!-- Central checkmark fragment -->
<circle r="16" fill="url(#successGlow)" opacity="0.6">
<animate attributeName="opacity" values="0.4;0.8;0.4" dur="2s" repeatCount="indefinite"/>
</circle>
<path d="M 0,-10 L 10,0 L 0,10 L -10,0 Z" fill="url(#grEmerald)" opacity="0.9"/>
<path d="M 0,-10 L 10,0 L 0,0 Z" fill="#fff" opacity="0.2"/>
<path d="M -4,0 L -1,4 L 5,-3" fill="none" stroke="#fff" stroke-width="1.5" stroke-linecap="round"/>
<!-- Particle shards -->
<g>
<path d="M 0,-22 L 2,-20 L 0,-18 L -2,-20 Z" fill="#6EE7B7" opacity="0">
<animate attributeName="opacity" values="0;0.8;0" dur="1.5s" repeatCount="indefinite"/>
</path>
<g transform="rotate(72)"><path d="M 0,-22 L 2,-20 L 0,-18 L -2,-20 Z" fill="#6EE7B7" opacity="0">
<animate attributeName="opacity" values="0;0.7;0" dur="1.5s" begin="0.1s" repeatCount="indefinite"/>
</path></g>
<g transform="rotate(144)"><path d="M 0,-22 L 2,-20 L 0,-18 L -2,-20 Z" fill="#A7F3D0" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="1.5s" begin="0.2s" repeatCount="indefinite"/>
</path></g>
<g transform="rotate(216)"><path d="M 0,-22 L 2,-20 L 0,-18 L -2,-20 Z" fill="#6EE7B7" opacity="0">
<animate attributeName="opacity" values="0;0.7;0" dur="1.5s" begin="0.3s" repeatCount="indefinite"/>
</path></g>
<g transform="rotate(288)"><path d="M 0,-22 L 2,-20 L 0,-18 L -2,-20 Z" fill="#A7F3D0" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="1.5s" begin="0.4s" repeatCount="indefinite"/>
</path></g>
</g>
</g>
<text x="0" y="56" class="lbl">Success Burst (Turn complete, goal achieved)</text>
</g>
<!-- Breathing Logo -->
<g transform="translate(475, 610)">
<g filter="url(#glowMd)">
<!-- Outer breathing aura -->
<circle r="30" fill="#8B5CF6" opacity="0.04">
<animate attributeName="r" values="25;35;25" dur="5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.02;0.08;0.02" dur="5s" repeatCount="indefinite"/>
</circle>
<!-- Mini 3-blade iris -->
<g>
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="60s" repeatCount="indefinite"/>
<g style="mix-blend-mode: screen;">
<path d="M 0,0 L 3,-1 L -2,22 L -3,1 Z" fill="url(#grAmethyst)" opacity="0.4">
<animate attributeName="fill-opacity" values="0.3;0.5;0.3" dur="5s" repeatCount="indefinite"/>
</path>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(120)">
<path d="M 0,0 L 3,-1 L -2,22 L -3,1 Z" fill="url(#grSapphire)" opacity="0.35"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(240)">
<path d="M 0,0 L 3,-1 L -2,22 L -3,1 Z" fill="url(#grEmerald)" opacity="0.35"/>
</g>
</g>
<circle r="4" fill="#fff" opacity="0.5" filter="url(#glowSm)">
<animate attributeName="opacity" values="0.3;0.7;0.3" dur="5s" repeatCount="indefinite"/>
<animate attributeName="r" values="3;5;3" dur="5s" repeatCount="indefinite"/>
</circle>
</g>
<text x="0" y="52" class="lbl">Breathing Logo (idle/splash)</text>
</g>
<!-- Row 5: Page Transition -->
<text x="24" y="700" class="section-lbl">TRANSITIONS</text>
<line x1="24" y1="706" x2="670" y2="706" stroke="#1C2240" stroke-width="0.5"/>
<!-- Page fade transition -->
<g transform="translate(175, 760)">
<g filter="url(#glowSm)">
<!-- "From" state -->
<rect x="-55" y="-20" width="40" height="40" rx="6" fill="#121628" stroke="#1C2240" stroke-width="0.5" opacity="0.4"/>
<text x="-35" y="2" font-size="7" fill="#475569" text-anchor="middle">From</text>
<!-- Arrow -->
<path d="M -8,0 L 8,0 M 4,-4 L 8,0 L 4,4" fill="none" stroke="#475569" stroke-width="0.8"/>
<!-- "To" state -->
<rect x="15" y="-20" width="40" height="40" rx="6" fill="#121628" stroke="#8B5CF6" stroke-width="0.5" opacity="0.8"/>
<text x="35" y="2" font-size="7" fill="#C4B5FD" text-anchor="middle">To</text>
</g>
<text x="0" y="40" class="lbl">Fade + slide up transition</text>
</g>
<!-- Fragment scatter transition -->
<g transform="translate(475, 760)">
<g filter="url(#glowSm)">
<!-- Scattered fragments converging -->
<path d="M -30,-15 L -26,-11 L -30,-7 L -34,-11 Z" fill="url(#grAmethyst)" opacity="0.3">
<animate attributeName="opacity" values="0;0.6;0" dur="2s" repeatCount="indefinite"/>
<animateTransform attributeName="transform" type="translate" values="-30,-15;0,0;-30,-15" dur="2s" repeatCount="indefinite"/>
</path>
<path d="M 25,-20 L 29,-16 L 25,-12 L 21,-16 Z" fill="url(#grSapphire)" opacity="0.3">
<animate attributeName="opacity" values="0;0.6;0" dur="2s" begin="0.2s" repeatCount="indefinite"/>
<animateTransform attributeName="transform" type="translate" values="25,-20;0,0;25,-20" dur="2s" begin="0.2s" repeatCount="indefinite"/>
</path>
<path d="M 20,18 L 24,22 L 20,26 L 16,22 Z" fill="url(#grEmerald)" opacity="0.3">
<animate attributeName="opacity" values="0;0.6;0" dur="2s" begin="0.4s" repeatCount="indefinite"/>
<animateTransform attributeName="transform" type="translate" values="20,18;0,0;20,18" dur="2s" begin="0.4s" repeatCount="indefinite"/>
</path>
<path d="M -28,12 L -24,16 L -28,20 L -32,16 Z" fill="url(#grAmber)" opacity="0.3">
<animate attributeName="opacity" values="0;0.6;0" dur="2s" begin="0.6s" repeatCount="indefinite"/>
<animateTransform attributeName="transform" type="translate" values="-28,12;0,0;-28,12" dur="2s" begin="0.6s" repeatCount="indefinite"/>
</path>
<!-- Center convergence point -->
<circle r="3" fill="#fff" opacity="0">
<animate attributeName="opacity" values="0;0.8;0" dur="2s" begin="0.8s" repeatCount="indefinite"/>
</circle>
</g>
<text x="0" y="40" class="lbl">Fragment scatter/converge transition</text>
</g>
<text x="350" y="812" font-size="8" fill="#334155" text-anchor="middle">All animations use SMIL for broad SVG compatibility — breathing, rotation, opacity, and transform animations</text>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,301 @@
<svg viewBox="0 0 700 740" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grAmethyst" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#C4B5FD"><animate attributeName="stop-color" values="#C4B5FD;#DDD6FE;#C4B5FD" dur="4s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#7C3AED"/>
</linearGradient>
<linearGradient id="grSapphire" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="4.5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#2563EB"/>
</linearGradient>
<linearGradient id="grEmerald" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#6EE7B7"/><stop offset="100%" stop-color="#059669"/>
</linearGradient>
<linearGradient id="grAmber" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FDE68A"/><stop offset="100%" stop-color="#D97706"/>
</linearGradient>
<linearGradient id="grRose" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBCFE8"/><stop offset="100%" stop-color="#DB2777"/>
</linearGradient>
<linearGradient id="grIndigo" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#A5B4FC"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<radialGradient id="coreGlow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#fff" stop-opacity="0.3"/>
<stop offset="50%" stop-color="#8B5CF6" stop-opacity="0.1"/>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<filter id="glowSm" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="1.5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowMd" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowLg" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="6" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<!-- Clip for circular pattern containers -->
<clipPath id="circClip60"><circle r="60"/></clipPath>
<clipPath id="circClip40"><circle r="40"/></clipPath>
<style>
text { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; }
.lbl { font-size: 9px; fill: #94A3B8; text-anchor: middle; font-weight: 500; }
.section-lbl { font-size: 11px; fill: #64748B; font-weight: 600; letter-spacing: 0.08em; }
</style>
</defs>
<rect width="700" height="740" fill="#050508"/>
<text x="350" y="28" font-size="13" font-weight="700" fill="#94A3B8" text-anchor="middle" letter-spacing="0.12em">KALEIDOSCOPE PATTERNS</text>
<text x="350" y="44" font-size="9" fill="#475569" text-anchor="middle">7 pattern variants for cards, Gallery, hero displays — each uses 6-fold symmetry from the logo</text>
<!-- Row 1: Turn, Mirror, Ritual -->
<text x="24" y="74" class="section-lbl">FEATURE PATTERNS</text>
<line x1="24" y1="80" x2="670" y2="80" stroke="#1C2240" stroke-width="0.5"/>
<!-- 1. TURN PATTERN (Amethyst) — 6 blades rotating slowly -->
<g transform="translate(120, 170)">
<circle r="62" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.5"/>
<g clip-path="url(#circClip60)">
<circle r="60" fill="#0A0E1A"/>
<g filter="url(#glowMd)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="60s" repeatCount="indefinite"/>
<g style="mix-blend-mode: screen;">
<path d="M 0,0 L 8,-2 L -5,55 L -8,2 Z" fill="url(#grAmethyst)" opacity="0.5">
<animate attributeName="fill-opacity" values="0.4;0.6;0.4" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 0,0 L 8,-2 L -5,55 Z" fill="#fff" opacity="0.08"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(60)">
<path d="M 0,0 L 8,-2 L -5,55 L -8,2 Z" fill="url(#grAmethyst)" opacity="0.45"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(120)">
<path d="M 0,0 L 8,-2 L -5,55 L -8,2 Z" fill="url(#grAmethyst)" opacity="0.4"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(180)">
<path d="M 0,0 L 8,-2 L -5,55 L -8,2 Z" fill="url(#grAmethyst)" opacity="0.5"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(240)">
<path d="M 0,0 L 8,-2 L -5,55 L -8,2 Z" fill="url(#grAmethyst)" opacity="0.45"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(300)">
<path d="M 0,0 L 8,-2 L -5,55 L -8,2 Z" fill="url(#grAmethyst)" opacity="0.4"/>
</g>
</g>
<!-- Core glow -->
<circle r="12" fill="url(#coreGlow)" opacity="0.8">
<animate attributeName="opacity" values="0.6;1;0.6" dur="3s" repeatCount="indefinite"/>
</circle>
<circle r="4" fill="#fff" opacity="0.5" filter="url(#glowSm)">
<animate attributeName="r" values="3;5;3" dur="3s" repeatCount="indefinite"/>
</circle>
</g>
<text x="0" y="82" class="lbl">Turn Pattern</text>
<text x="0" y="94" font-size="8" fill="#475569" text-anchor="middle">Amethyst blades</text>
</g>
<!-- 2. MIRROR PATTERN (Amber) — angular, reflective symmetry -->
<g transform="translate(350, 170)">
<circle r="62" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.5"/>
<g clip-path="url(#circClip60)">
<circle r="60" fill="#0A0E1A"/>
<g filter="url(#glowMd)">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="90s" repeatCount="indefinite"/>
<!-- Mirrored angular shards -->
<g style="mix-blend-mode: screen;">
<path d="M 0,0 L 6,-4 L 10,50 L -4,2 Z" fill="url(#grAmber)" opacity="0.45"/>
<path d="M 0,0 L -6,-4 L -10,50 L 4,2 Z" fill="url(#grAmber)" opacity="0.4"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(120)">
<path d="M 0,0 L 6,-4 L 10,50 L -4,2 Z" fill="url(#grAmber)" opacity="0.4"/>
<path d="M 0,0 L -6,-4 L -10,50 L 4,2 Z" fill="url(#grAmber)" opacity="0.35"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(240)">
<path d="M 0,0 L 6,-4 L 10,50 L -4,2 Z" fill="url(#grAmber)" opacity="0.45"/>
<path d="M 0,0 L -6,-4 L -10,50 L 4,2 Z" fill="url(#grAmber)" opacity="0.4"/>
</g>
</g>
<circle r="10" fill="url(#coreGlow)" opacity="0.7"/>
<circle r="3" fill="#FDE68A" opacity="0.5" filter="url(#glowSm)"/>
</g>
<text x="0" y="82" class="lbl">Mirror Pattern</text>
<text x="0" y="94" font-size="8" fill="#475569" text-anchor="middle">Amber shards, bilateral</text>
</g>
<!-- 3. RITUAL PATTERN (Emerald) — concentric rings with fragments -->
<g transform="translate(580, 170)">
<circle r="62" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.5"/>
<g clip-path="url(#circClip60)">
<circle r="60" fill="#0A0E1A"/>
<g filter="url(#glowMd)">
<!-- Concentric ring fragments -->
<circle r="45" fill="none" stroke="#10B981" stroke-width="0.8" opacity="0.2" stroke-dasharray="6 8"/>
<circle r="30" fill="none" stroke="#10B981" stroke-width="0.6" opacity="0.25" stroke-dasharray="4 6"/>
<!-- 6 fragments on outer ring -->
<g>
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="45s" repeatCount="indefinite"/>
<path d="M 0,-45 L 3,-42 L 0,-39 L -3,-42 Z" fill="url(#grEmerald)" opacity="0.6"/>
<path d="M 0,-45 L 3,-42 L 0,-42 Z" fill="#fff" opacity="0.1"/>
<g transform="rotate(60)"><path d="M 0,-45 L 3,-42 L 0,-39 L -3,-42 Z" fill="url(#grEmerald)" opacity="0.5"/></g>
<g transform="rotate(120)"><path d="M 0,-45 L 3,-42 L 0,-39 L -3,-42 Z" fill="url(#grEmerald)" opacity="0.55"/></g>
<g transform="rotate(180)"><path d="M 0,-45 L 3,-42 L 0,-39 L -3,-42 Z" fill="url(#grEmerald)" opacity="0.5"/></g>
<g transform="rotate(240)"><path d="M 0,-45 L 3,-42 L 0,-39 L -3,-42 Z" fill="url(#grEmerald)" opacity="0.6"/></g>
<g transform="rotate(300)"><path d="M 0,-45 L 3,-42 L 0,-39 L -3,-42 Z" fill="url(#grEmerald)" opacity="0.5"/></g>
</g>
<!-- Inner ring fragments -->
<g>
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="30s" repeatCount="indefinite"/>
<path d="M 0,-30 L 2,-28 L 0,-26 L -2,-28 Z" fill="#6EE7B7" opacity="0.5"/>
<g transform="rotate(90)"><path d="M 0,-30 L 2,-28 L 0,-26 L -2,-28 Z" fill="#6EE7B7" opacity="0.4"/></g>
<g transform="rotate(180)"><path d="M 0,-30 L 2,-28 L 0,-26 L -2,-28 Z" fill="#6EE7B7" opacity="0.5"/></g>
<g transform="rotate(270)"><path d="M 0,-30 L 2,-28 L 0,-26 L -2,-28 Z" fill="#6EE7B7" opacity="0.4"/></g>
</g>
</g>
<circle r="8" fill="url(#coreGlow)" opacity="0.6"/>
<circle r="3" fill="#6EE7B7" opacity="0.5" filter="url(#glowSm)"/>
</g>
<text x="0" y="82" class="lbl">Ritual Pattern</text>
<text x="0" y="94" font-size="8" fill="#475569" text-anchor="middle">Emerald concentric rings</text>
</g>
<!-- Row 2: Simple, Complex, Thumbnail, Hero -->
<text x="24" y="310" class="section-lbl">COMPLEXITY VARIANTS</text>
<line x1="24" y1="316" x2="670" y2="316" stroke="#1C2240" stroke-width="0.5"/>
<!-- 4. SIMPLE — minimal 3-blade -->
<g transform="translate(100, 400)">
<circle r="42" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.5"/>
<g clip-path="url(#circClip40)">
<circle r="40" fill="#0A0E1A"/>
<g filter="url(#glowSm)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="50s" repeatCount="indefinite"/>
<g style="mix-blend-mode: screen;">
<path d="M 0,0 L 5,-2 L -2,36 L -5,1 Z" fill="url(#grAmethyst)" opacity="0.45"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(120)">
<path d="M 0,0 L 5,-2 L -2,36 L -5,1 Z" fill="url(#grSapphire)" opacity="0.4"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(240)">
<path d="M 0,0 L 5,-2 L -2,36 L -5,1 Z" fill="url(#grEmerald)" opacity="0.4"/>
</g>
</g>
<circle r="3" fill="#fff" opacity="0.4" filter="url(#glowSm)"/>
</g>
<text x="0" y="60" class="lbl">Simple</text>
</g>
<!-- 5. COMPLEX — full 6-blade prismatic -->
<g transform="translate(270, 400)">
<circle r="42" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.5"/>
<g clip-path="url(#circClip40)">
<circle r="40" fill="#0A0E1A"/>
<g filter="url(#glowMd)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="70s" repeatCount="indefinite"/>
<g style="mix-blend-mode: screen;">
<path d="M 0,0 L 6,-2 L -4,38 L -6,1 Z" fill="url(#grAmethyst)" opacity="0.5"/>
<path d="M 0,0 L 6,-2 L -4,38 Z" fill="#fff" opacity="0.06"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(60)">
<path d="M 0,0 L 6,-2 L -4,38 L -6,1 Z" fill="url(#grSapphire)" opacity="0.45"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(120)">
<path d="M 0,0 L 6,-2 L -4,38 L -6,1 Z" fill="url(#grEmerald)" opacity="0.4"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(180)">
<path d="M 0,0 L 6,-2 L -4,38 L -6,1 Z" fill="url(#grAmber)" opacity="0.5"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(240)">
<path d="M 0,0 L 6,-2 L -4,38 L -6,1 Z" fill="url(#grRose)" opacity="0.45"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(300)">
<path d="M 0,0 L 6,-2 L -4,38 L -6,1 Z" fill="url(#grIndigo)" opacity="0.4"/>
</g>
</g>
<circle r="8" fill="url(#coreGlow)" opacity="0.7"/>
<circle r="3" fill="#fff" opacity="0.6" filter="url(#glowSm)">
<animate attributeName="r" values="2;4;2" dur="3s" repeatCount="indefinite"/>
</circle>
</g>
<text x="0" y="60" class="lbl">Complex</text>
</g>
<!-- 6. THUMBNAIL — tiny for list items -->
<g transform="translate(420, 400)">
<circle r="20" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.5"/>
<g>
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="40s" repeatCount="indefinite"/>
<g style="mix-blend-mode: screen;">
<path d="M 420,400 L 423,399 L 418,418 L 417,401 Z" fill="url(#grAmethyst)" opacity="0.4"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(120, 420, 400)">
<path d="M 420,400 L 423,399 L 418,418 L 417,401 Z" fill="url(#grSapphire)" opacity="0.35"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(240, 420, 400)">
<path d="M 420,400 L 423,399 L 418,418 L 417,401 Z" fill="url(#grEmerald)" opacity="0.35"/>
</g>
</g>
<circle cx="420" cy="400" r="2" fill="#fff" opacity="0.4"/>
<text x="0" y="40" class="lbl">Thumbnail</text>
</g>
<!-- 7. HERO — large, full prismatic with all effects -->
<text x="24" y="490" class="section-lbl">HERO VARIANT</text>
<line x1="24" y1="496" x2="670" y2="496" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(350, 610)">
<circle r="100" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.5"/>
<!-- Outer aura -->
<circle r="95" fill="#8B5CF6" opacity="0.03" filter="url(#glowLg)">
<animate attributeName="r" values="85;100;85" dur="6s" repeatCount="indefinite"/>
</circle>
<g>
<g filter="url(#glowLg)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="90s" repeatCount="indefinite"/>
<!-- Full 6-blade iris -->
<g style="mix-blend-mode: screen;">
<path d="M 350,610 L 358,608 L 340,690 L 342,612 Z" fill="url(#grAmethyst)" opacity="0.55">
<animate attributeName="fill-opacity" values="0.45;0.65;0.45" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 350,610 L 358,608 L 340,690 Z" fill="#fff" opacity="0.08"/>
<line x1="350" y1="610" x2="340" y2="690" stroke="#C4B5FD" stroke-width="0.8" opacity="0">
<animate attributeName="opacity" values="0;0.3;0" dur="5s" repeatCount="indefinite"/>
</line>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(60, 350, 610)">
<path d="M 350,610 L 358,608 L 340,690 L 342,612 Z" fill="url(#grSapphire)" opacity="0.5"/>
<line x1="350" y1="610" x2="340" y2="690" stroke="#93C5FD" stroke-width="0.8" opacity="0">
<animate attributeName="opacity" values="0;0.3;0" dur="5s" begin="0.8s" repeatCount="indefinite"/>
</line>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(120, 350, 610)">
<path d="M 350,610 L 358,608 L 340,690 L 342,612 Z" fill="url(#grEmerald)" opacity="0.45"/>
<line x1="350" y1="610" x2="340" y2="690" stroke="#6EE7B7" stroke-width="0.8" opacity="0">
<animate attributeName="opacity" values="0;0.3;0" dur="5s" begin="1.6s" repeatCount="indefinite"/>
</line>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(180, 350, 610)">
<path d="M 350,610 L 358,608 L 340,690 L 342,612 Z" fill="url(#grAmber)" opacity="0.55"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(240, 350, 610)">
<path d="M 350,610 L 358,608 L 340,690 L 342,612 Z" fill="url(#grRose)" opacity="0.5"/>
</g>
<g style="mix-blend-mode: screen;" transform="rotate(300, 350, 610)">
<path d="M 350,610 L 358,608 L 340,690 L 342,612 Z" fill="url(#grIndigo)" opacity="0.45"/>
</g>
</g>
</g>
<!-- Core -->
<circle r="20" fill="url(#coreGlow)" opacity="0.8" filter="url(#glowMd)">
<animate attributeName="opacity" values="0.6;1;0.6" dur="4s" repeatCount="indefinite"/>
</circle>
<circle r="6" fill="#fff" opacity="0.7" filter="url(#glowSm)">
<animate attributeName="r" values="5;8;5" dur="3s" repeatCount="indefinite"/>
</circle>
<circle cx="-3" cy="-3" r="2" fill="#fff" opacity="0.3"/>
<text x="0" y="120" class="lbl">Hero Pattern — full prismatic 6-blade iris with edge shimmers, core glow, breathing animation</text>
</g>
<text x="350" y="734" font-size="8" fill="#334155" text-anchor="middle">All patterns use 6-fold rotational symmetry, screen blend mode, and the soft-elegance crystalline visual language</text>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,186 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kalei SVG Asset Library — Preview</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Space+Grotesk:wght@400;500;600;700&display=swap');
body {
background: #050508;
color: #E2E8F0;
font-family: 'Inter', sans-serif;
padding: 40px;
}
h1 {
font-family: 'Space Grotesk', sans-serif;
font-size: 32px;
font-weight: 700;
margin-bottom: 8px;
background: linear-gradient(135deg, #8B5CF6, #3B82F6, #10B981, #F59E0B, #EC4899);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.subtitle { color: #94A3B8; font-size: 14px; margin-bottom: 40px; }
.section {
margin-bottom: 48px;
border-bottom: 1px solid rgba(28,34,64,0.5);
padding-bottom: 32px;
}
.section h2 {
font-size: 18px;
font-weight: 600;
color: #A78BFA;
margin-bottom: 8px;
letter-spacing: 0.03em;
}
.section .desc {
font-size: 13px;
color: #94A3B8;
margin-bottom: 16px;
}
.section .file-name {
font-size: 11px;
font-weight: 500;
color: #475569;
background: #121628;
display: inline-block;
padding: 3px 10px;
border-radius: 6px;
margin-bottom: 16px;
font-family: monospace;
}
.asset-frame {
background: #0A0E1A;
border: 1px solid #1C2240;
border-radius: 16px;
padding: 24px;
overflow: auto;
max-height: 600px;
}
.asset-frame object, .asset-frame img {
width: 100%;
max-width: 600px;
height: auto;
}
.grid-2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
@media (max-width: 900px) { .grid-2 { grid-template-columns: 1fr; } }
</style>
</head>
<body>
<h1>KALEI ASSET LIBRARY</h1>
<p class="subtitle">All SVG assets for the Kalei platform, derived from the soft-elegance logo visual language. 12 files, 100+ elements.</p>
<div class="section">
<h2>Tab Bar Icons</h2>
<div class="desc">5 navigation icons (Turn, Mirror, Lens, Gallery, You) in active + inactive states</div>
<div class="file-name">icons-tab-bar.svg</div>
<div class="asset-frame">
<object type="image/svg+xml" data="icons-tab-bar.svg"></object>
</div>
</div>
<div class="section">
<h2>Cognitive Distortion Icons</h2>
<div class="desc">10 fragment type icons for Mirror feature detection</div>
<div class="file-name">icons-distortions.svg</div>
<div class="asset-frame">
<object type="image/svg+xml" data="icons-distortions.svg"></object>
</div>
</div>
<div class="section">
<h2>Action & UI Icons</h2>
<div class="desc">30 icons for navigation, actions, status, and feature-specific use</div>
<div class="file-name">icons-actions.svg</div>
<div class="asset-frame">
<object type="image/svg+xml" data="icons-actions.svg"></object>
</div>
</div>
<div class="section">
<h2>Fragment Icons & Highlights</h2>
<div class="desc">The core ◇ fragment in 5 sizes, 8 color states, plus highlight effects</div>
<div class="file-name">fragment-icons.svg</div>
<div class="asset-frame">
<object type="image/svg+xml" data="fragment-icons.svg"></object>
</div>
</div>
<div class="section">
<h2>Decorative Shard Elements</h2>
<div class="desc">Background auras, floating shards, dividers, corner accents, edge shimmers</div>
<div class="file-name">decorative-shards.svg</div>
<div class="asset-frame">
<object type="image/svg+xml" data="decorative-shards.svg"></object>
</div>
</div>
<div class="grid-2">
<div class="section">
<h2>Kaleidoscope Patterns</h2>
<div class="desc">7 pattern variants for cards, Gallery, and hero displays</div>
<div class="file-name">patterns-kaleidoscope.svg</div>
<div class="asset-frame">
<object type="image/svg+xml" data="patterns-kaleidoscope.svg"></object>
</div>
</div>
<div class="section">
<h2>Progress Indicators</h2>
<div class="desc">Rings, bars, calendars, timers, counters</div>
<div class="file-name">progress-indicators.svg</div>
<div class="asset-frame">
<object type="image/svg+xml" data="progress-indicators.svg"></object>
</div>
</div>
</div>
<div class="section">
<h2>Evidence Wall</h2>
<div class="desc">Tile shapes, mosaic compositions (early/mid/full), empty state</div>
<div class="file-name">evidence-wall.svg</div>
<div class="asset-frame">
<object type="image/svg+xml" data="evidence-wall.svg"></object>
</div>
</div>
<div class="section">
<h2>Loading & Animation States</h2>
<div class="desc">Spinners, skeleton shimmers, Turn animation, AI thinking, success burst</div>
<div class="file-name">loading-animations.svg</div>
<div class="asset-frame">
<object type="image/svg+xml" data="loading-animations.svg"></object>
</div>
</div>
<div class="section">
<h2>Device Chrome</h2>
<div class="desc">Status bar, tab bar, nav header, keyboard, device frame, modal scrim, toast</div>
<div class="file-name">device-chrome.svg</div>
<div class="asset-frame">
<object type="image/svg+xml" data="device-chrome.svg"></object>
</div>
</div>
<div class="section">
<h2>Spectrum Visualizations</h2>
<div class="desc">The River, Your Glass, Turn Impact, Rhythm Detection, Growth Trajectory</div>
<div class="file-name">spectrum-visualizations.svg</div>
<div class="asset-frame">
<object type="image/svg+xml" data="spectrum-visualizations.svg"></object>
</div>
</div>
<div style="text-align: center; padding: 40px 0; color: #475569; font-size: 12px;">
Kalei Asset Library — 12 SVG files, 100+ elements, 1 CSS design system
</div>
</body>
</html>

View File

@ -0,0 +1,257 @@
<svg viewBox="0 0 700 700" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grAmethyst" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#C4B5FD"/><stop offset="100%" stop-color="#7C3AED"/>
</linearGradient>
<linearGradient id="grEmerald" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#6EE7B7"/><stop offset="100%" stop-color="#059669"/>
</linearGradient>
<linearGradient id="grAmber" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FDE68A"/><stop offset="100%" stop-color="#D97706"/>
</linearGradient>
<linearGradient id="grSapphire" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#93C5FD"/><stop offset="100%" stop-color="#2563EB"/>
</linearGradient>
<linearGradient id="prismaticH" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#3B82F6"><animate attributeName="stop-color" values="#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6;#3B82F6" dur="8s" repeatCount="indefinite"/></stop>
</linearGradient>
<filter id="glowSm" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="1.5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowMd" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowLg" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="6" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<style>
text { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; }
.lbl { font-size: 9px; fill: #94A3B8; text-anchor: middle; font-weight: 500; }
.section-lbl { font-size: 11px; fill: #64748B; font-weight: 600; letter-spacing: 0.08em; }
.val { font-size: 18px; fill: #E2E8F0; font-weight: 700; text-anchor: middle; }
.val-sm { font-size: 8px; fill: #64748B; text-anchor: middle; font-weight: 500; }
</style>
</defs>
<rect width="700" height="700" fill="#050508"/>
<text x="350" y="28" font-size="13" font-weight="700" fill="#94A3B8" text-anchor="middle" letter-spacing="0.12em">PROGRESS INDICATORS</text>
<text x="350" y="44" font-size="9" fill="#475569" text-anchor="middle">Rings, bars, calendars, timers, counters — all with prismatic styling</text>
<!-- Row 1: Large Ring, Small Ring -->
<text x="24" y="74" class="section-lbl">PROGRESS RINGS</text>
<line x1="24" y1="80" x2="670" y2="80" stroke="#1C2240" stroke-width="0.5"/>
<!-- Large Ring (72% complete) -->
<g transform="translate(140, 160)">
<!-- Background track -->
<circle r="50" fill="none" stroke="#1C2240" stroke-width="6" opacity="0.5"/>
<!-- Progress arc — 72% = ~259 degrees -->
<g filter="url(#glowMd)">
<circle r="50" fill="none" stroke="url(#grAmethyst)" stroke-width="6" stroke-linecap="round"
stroke-dasharray="226 314" stroke-dashoffset="0" transform="rotate(-90)">
<animate attributeName="stroke-dasharray" values="0 314;226 314" dur="1.5s" fill="freeze"/>
</circle>
</g>
<!-- End cap glow -->
<circle cx="0" cy="0" r="3" fill="#A78BFA" opacity="0.6" filter="url(#glowSm)"
transform="rotate(169) translate(50, 0)"/>
<!-- Center text -->
<text x="0" y="4" class="val">72%</text>
<text x="0" y="16" class="val-sm">COMPLETE</text>
<text x="0" y="74" class="lbl">Large Ring (Lens progress)</text>
</g>
<!-- Small Ring (3/6 steps) -->
<g transform="translate(340, 160)">
<circle r="28" fill="none" stroke="#1C2240" stroke-width="4" opacity="0.5"/>
<g filter="url(#glowSm)">
<circle r="28" fill="none" stroke="url(#grEmerald)" stroke-width="4" stroke-linecap="round"
stroke-dasharray="88 176" stroke-dashoffset="0" transform="rotate(-90)"/>
</g>
<text x="0" y="2" font-size="13" fill="#E2E8F0" font-weight="700" text-anchor="middle">3/6</text>
<text x="0" y="14" class="val-sm">STEPS</text>
<text x="0" y="52" class="lbl">Small Ring (step counter)</text>
</g>
<!-- Prismatic Ring (special/celebration) -->
<g transform="translate(540, 160)">
<circle r="40" fill="none" stroke="#1C2240" stroke-width="5" opacity="0.4"/>
<g filter="url(#glowMd)">
<circle r="40" fill="none" stroke="url(#prismaticH)" stroke-width="5" stroke-linecap="round"
stroke-dasharray="251 251" transform="rotate(-90)"/>
</g>
<!-- Orbiting mote -->
<circle r="2" fill="#fff" opacity="0" filter="url(#glowSm)">
<animateMotion dur="3s" repeatCount="indefinite" path="M0,-40 A40,40 0 1 1 -0.1,-40"/>
<animate attributeName="opacity" values="0;0.8;0;0" dur="3s" repeatCount="indefinite"/>
</circle>
<text x="0" y="4" class="val">100</text>
<text x="0" y="16" class="val-sm">COMPLETE</text>
<text x="0" y="64" class="lbl">Prismatic Ring (100% celebration)</text>
</g>
<!-- Row 2: Linear Bar, Step Dots -->
<text x="24" y="274" class="section-lbl">LINEAR INDICATORS</text>
<line x1="24" y1="280" x2="670" y2="280" stroke="#1C2240" stroke-width="0.5"/>
<!-- Linear Progress Bar -->
<g transform="translate(350, 310)">
<!-- Track -->
<rect x="-250" y="-4" width="500" height="8" rx="4" fill="#1C2240" opacity="0.6"/>
<!-- Fill -->
<g filter="url(#glowSm)">
<rect x="-250" y="-4" width="325" height="8" rx="4" fill="url(#grAmethyst)" opacity="0.8">
<animate attributeName="width" values="0;325" dur="1.2s" fill="freeze"/>
</rect>
</g>
<!-- Shimmer sweep -->
<rect x="-250" y="-4" width="40" height="8" rx="4" fill="#fff" opacity="0">
<animate attributeName="opacity" values="0;0.15;0" dur="2s" repeatCount="indefinite"/>
<animate attributeName="x" values="-250;75" dur="2s" repeatCount="indefinite"/>
</rect>
<!-- End glow -->
<circle cx="75" cy="0" r="4" fill="#A78BFA" opacity="0.4" filter="url(#glowSm)"/>
<text x="-250" y="-14" font-size="9" fill="#94A3B8" font-weight="500">Progress</text>
<text x="250" y="-14" font-size="9" fill="#C4B5FD" font-weight="600" text-anchor="end">65%</text>
<text x="0" y="28" class="lbl">Linear bar with shimmer sweep</text>
</g>
<!-- Step Dots (5 steps, 3 complete) -->
<g transform="translate(350, 380)">
<!-- Connecting line -->
<line x1="-120" y1="0" x2="120" y2="0" stroke="#1C2240" stroke-width="1.5"/>
<!-- Filled progress line -->
<line x1="-120" y1="0" x2="0" y2="0" stroke="url(#grEmerald)" stroke-width="1.5" filter="url(#glowSm)"/>
<!-- Step 1: complete -->
<g transform="translate(-120, 0)">
<circle r="8" fill="url(#grEmerald)" opacity="0.9" filter="url(#glowSm)"/>
<path d="M -3,0 L -1,3 L 4,-2" fill="none" stroke="#fff" stroke-width="1.2" stroke-linecap="round"/>
</g>
<!-- Step 2: complete -->
<g transform="translate(-60, 0)">
<circle r="8" fill="url(#grEmerald)" opacity="0.9" filter="url(#glowSm)"/>
<path d="M -3,0 L -1,3 L 4,-2" fill="none" stroke="#fff" stroke-width="1.2" stroke-linecap="round"/>
</g>
<!-- Step 3: complete -->
<g transform="translate(0, 0)">
<circle r="8" fill="url(#grEmerald)" opacity="0.9" filter="url(#glowSm)"/>
<path d="M -3,0 L -1,3 L 4,-2" fill="none" stroke="#fff" stroke-width="1.2" stroke-linecap="round"/>
</g>
<!-- Step 4: current -->
<g transform="translate(60, 0)">
<circle r="8" fill="#121628" stroke="#10B981" stroke-width="1.5"/>
<circle r="3" fill="#10B981" opacity="0.6">
<animate attributeName="opacity" values="0.4;0.8;0.4" dur="2s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Step 5: future -->
<g transform="translate(120, 0)">
<circle r="8" fill="#121628" stroke="#1C2240" stroke-width="1"/>
</g>
<text x="0" y="28" class="lbl">Step dots (Lens 6-step flow)</text>
</g>
<!-- Row 3: Streak Calendar, Ritual Bar -->
<text x="24" y="434" class="section-lbl">STREAK AND RITUAL</text>
<line x1="24" y1="440" x2="670" y2="440" stroke="#1C2240" stroke-width="0.5"/>
<!-- Streak Calendar (7-day week) -->
<g transform="translate(175, 500)">
<!-- Days of week -->
<g font-size="8" fill="#475569" text-anchor="middle" font-weight="500">
<text x="-90" y="-26">M</text><text x="-60" y="-26">T</text><text x="-30" y="-26">W</text>
<text x="0" y="-26">T</text><text x="30" y="-26">F</text><text x="60" y="-26">S</text><text x="90" y="-26">S</text>
</g>
<!-- Day circles -->
<!-- Mon: complete -->
<circle cx="-90" cy="0" r="12" fill="url(#grAmber)" opacity="0.8" filter="url(#glowSm)"/>
<path d="M -93,0 L -91,3 L -86,-2" fill="none" stroke="#fff" stroke-width="1" stroke-linecap="round" transform="translate(0,0)"/>
<!-- Tue: complete -->
<circle cx="-60" cy="0" r="12" fill="url(#grAmber)" opacity="0.8" filter="url(#glowSm)"/>
<path d="M -63,0 L -61,3 L -56,-2" fill="none" stroke="#fff" stroke-width="1" stroke-linecap="round"/>
<!-- Wed: complete -->
<circle cx="-30" cy="0" r="12" fill="url(#grAmber)" opacity="0.8" filter="url(#glowSm)"/>
<path d="M -33,0 L -31,3 L -26,-2" fill="none" stroke="#fff" stroke-width="1" stroke-linecap="round"/>
<!-- Thu: today, in progress -->
<circle cx="0" cy="0" r="12" fill="#121628" stroke="#F59E0B" stroke-width="1.5"/>
<circle cx="0" cy="0" r="4" fill="#F59E0B" opacity="0.5">
<animate attributeName="opacity" values="0.3;0.7;0.3" dur="2s" repeatCount="indefinite"/>
</circle>
<!-- Fri-Sun: future -->
<circle cx="30" cy="0" r="12" fill="#121628" stroke="#1C2240" stroke-width="0.8"/>
<circle cx="60" cy="0" r="12" fill="#121628" stroke="#1C2240" stroke-width="0.8"/>
<circle cx="90" cy="0" r="12" fill="#121628" stroke="#1C2240" stroke-width="0.8"/>
<!-- Streak count -->
<g filter="url(#glowSm)">
<path d="M 0,22 L 3,28 L 0,26 L -3,28 Z" fill="#F59E0B" opacity="0.7"/>
<text x="0" y="42" font-size="10" fill="#FDE68A" text-anchor="middle" font-weight="600">3 day streak</text>
</g>
<text x="0" y="58" class="lbl">Streak Calendar (weekly view)</text>
</g>
<!-- Ritual Progress Bar (3 of 5 steps in a ritual sequence) -->
<g transform="translate(500, 500)">
<!-- Ritual steps as connected fragments -->
<g filter="url(#glowSm)">
<!-- Step 1: done -->
<path d="M -80,0 L -72,-8 L -64,0 L -72,8 Z" fill="url(#grEmerald)" opacity="0.8"/>
<path d="M -72,-8 L -64,0 L -72,0 Z" fill="#fff" opacity="0.12"/>
<line x1="-64" y1="0" x2="-48" y2="0" stroke="#10B981" stroke-width="1" opacity="0.5"/>
<!-- Step 2: done -->
<path d="M -48,0 L -40,-8 L -32,0 L -40,8 Z" fill="url(#grEmerald)" opacity="0.8"/>
<line x1="-32" y1="0" x2="-16" y2="0" stroke="#10B981" stroke-width="1" opacity="0.5"/>
<!-- Step 3: done -->
<path d="M -16,0 L -8,-8 L 0,0 L -8,8 Z" fill="url(#grEmerald)" opacity="0.8"/>
<line x1="0" y1="0" x2="16" y2="0" stroke="#1C2240" stroke-width="1"/>
<!-- Step 4: current -->
<path d="M 16,0 L 24,-8 L 32,0 L 24,8 Z" fill="#121628" stroke="#10B981" stroke-width="1"/>
<circle cx="24" cy="0" r="2" fill="#10B981" opacity="0.5">
<animate attributeName="opacity" values="0.3;0.8;0.3" dur="2s" repeatCount="indefinite"/>
</circle>
<line x1="32" y1="0" x2="48" y2="0" stroke="#1C2240" stroke-width="1"/>
<!-- Step 5: future -->
<path d="M 48,0 L 56,-8 L 64,0 L 56,8 Z" fill="none" stroke="#1C2240" stroke-width="0.8"/>
</g>
<text x="-8" y="28" class="lbl">Ritual Bar (fragment-shaped steps)</text>
</g>
<!-- Row 4: Timer, Evidence Counter -->
<text x="24" y="584" class="section-lbl">TIMER AND COUNTERS</text>
<line x1="24" y1="590" x2="670" y2="590" stroke="#1C2240" stroke-width="0.5"/>
<!-- Timer Ring -->
<g transform="translate(175, 640)">
<circle r="30" fill="none" stroke="#1C2240" stroke-width="3" opacity="0.4"/>
<g filter="url(#glowSm)">
<circle r="30" fill="none" stroke="url(#grAmethyst)" stroke-width="3" stroke-linecap="round"
stroke-dasharray="141 188" transform="rotate(-90)">
<animate attributeName="stroke-dasharray" values="188 188;0 188" dur="60s" repeatCount="indefinite"/>
</circle>
</g>
<text x="0" y="2" font-size="14" fill="#E2E8F0" font-weight="600" text-anchor="middle">2:45</text>
<text x="0" y="52" class="lbl">Timer Ring (Rehearsal countdown)</text>
</g>
<!-- Evidence Counter -->
<g transform="translate(450, 640)">
<g filter="url(#glowMd)">
<rect x="-60" y="-24" width="120" height="48" rx="12" fill="#121628" stroke="#1C2240" stroke-width="0.8"/>
<!-- Inner glow -->
<rect x="-58" y="-22" width="116" height="44" rx="10" fill="#3B82F6" opacity="0.04"/>
<!-- Fragment icon -->
<g transform="translate(-32, 0)">
<path d="M 0,-8 L 8,0 L 0,8 L -8,0 Z" fill="url(#grSapphire)" opacity="0.8" filter="url(#glowSm)"/>
<path d="M 0,-8 L 8,0 L 0,0 Z" fill="#fff" opacity="0.15"/>
</g>
<!-- Count -->
<text x="14" y="4" font-size="16" fill="#E2E8F0" font-weight="700" text-anchor="middle">24</text>
<text x="14" y="16" font-size="7" fill="#64748B" text-anchor="middle" font-weight="500">EVIDENCE</text>
</g>
<text x="0" y="48" class="lbl">Evidence Counter (Evidence Wall)</text>
</g>
<text x="350" y="692" font-size="8" fill="#334155" text-anchor="middle">All indicators use jewel tone gradients, glow filters, and animated transitions from the Kalei design system</text>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,261 @@
<svg viewBox="0 0 700 900" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grAmethyst" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#C4B5FD"><animate attributeName="stop-color" values="#C4B5FD;#DDD6FE;#C4B5FD" dur="4s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#7C3AED"/>
</linearGradient>
<linearGradient id="grSapphire" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#93C5FD"/><stop offset="100%" stop-color="#2563EB"/>
</linearGradient>
<linearGradient id="grEmerald" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#6EE7B7"/><stop offset="100%" stop-color="#059669"/>
</linearGradient>
<linearGradient id="grAmber" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FDE68A"/><stop offset="100%" stop-color="#D97706"/>
</linearGradient>
<linearGradient id="grRose" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#FBCFE8"/><stop offset="100%" stop-color="#DB2777"/>
</linearGradient>
<linearGradient id="grIndigo" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#A5B4FC"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<!-- River flow gradient -->
<linearGradient id="riverGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#8B5CF6" stop-opacity="0.6"/>
<stop offset="30%" stop-color="#3B82F6" stop-opacity="0.5"/>
<stop offset="60%" stop-color="#10B981" stop-opacity="0.4"/>
<stop offset="100%" stop-color="#F59E0B" stop-opacity="0.6"/>
</linearGradient>
<linearGradient id="riverGradFill" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#8B5CF6" stop-opacity="0.15"/>
<stop offset="30%" stop-color="#3B82F6" stop-opacity="0.1"/>
<stop offset="60%" stop-color="#10B981" stop-opacity="0.08"/>
<stop offset="100%" stop-color="#F59E0B" stop-opacity="0.12"/>
</linearGradient>
<filter id="glowSm" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="1.5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowMd" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowLg" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<style>
text { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; }
.lbl { font-size: 9px; fill: #94A3B8; text-anchor: middle; font-weight: 500; }
.section-lbl { font-size: 11px; fill: #64748B; font-weight: 600; letter-spacing: 0.08em; }
.axis-lbl { font-size: 7px; fill: #475569; font-weight: 500; }
.data-lbl { font-size: 8px; fill: #94A3B8; font-weight: 500; text-anchor: middle; }
</style>
</defs>
<rect width="700" height="900" fill="#050508"/>
<text x="350" y="28" font-size="13" font-weight="700" fill="#94A3B8" text-anchor="middle" letter-spacing="0.12em">SPECTRUM VISUALIZATIONS</text>
<text x="350" y="44" font-size="9" fill="#475569" text-anchor="middle">5 analytics views: The River, Your Glass, Turn Impact, Rhythm Detection, Growth Trajectory</text>
<!-- 1. THE RIVER — emotional flow over time -->
<text x="24" y="74" class="section-lbl">THE RIVER</text>
<line x1="24" y1="80" x2="670" y2="80" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(350, 150)">
<rect x="-280" y="-50" width="560" height="100" rx="8" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.5"/>
<!-- X axis labels -->
<g class="axis-lbl" text-anchor="middle">
<text x="-240" y="60">Mon</text><text x="-160" y="60">Tue</text><text x="-80" y="60">Wed</text>
<text x="0" y="60">Thu</text><text x="80" y="60">Fri</text><text x="160" y="60">Sat</text><text x="240" y="60">Sun</text>
</g>
<!-- River band (area chart) -->
<g filter="url(#glowSm)">
<!-- Upper bound -->
<path d="M -260,-20 C -200,-30 -140,5 -80,-10 C -20,-25 40,10 100,-5 C 160,-20 220,0 260,-15"
fill="none" stroke="url(#riverGrad)" stroke-width="1.5" opacity="0.8"/>
<!-- Lower bound -->
<path d="M -260,15 C -200,25 -140,5 -80,20 C -20,30 40,10 100,18 C 160,25 220,8 260,20"
fill="none" stroke="url(#riverGrad)" stroke-width="1" opacity="0.5"/>
<!-- Fill between -->
<path d="M -260,-20 C -200,-30 -140,5 -80,-10 C -20,-25 40,10 100,-5 C 160,-20 220,0 260,-15
L 260,20 C 220,8 160,25 100,18 C 40,10 -20,30 -80,20 C -140,5 -200,25 -260,15 Z"
fill="url(#riverGradFill)" opacity="0.6"/>
<!-- Data point fragments -->
<g>
<path d="M -240,-18 L -237,-15 L -240,-12 L -243,-15 Z" fill="url(#grAmethyst)" opacity="0.7"/>
<path d="M -160,8 L -157,11 L -160,14 L -163,11 Z" fill="url(#grSapphire)" opacity="0.6"/>
<path d="M -80,-8 L -77,-5 L -80,-2 L -83,-5 Z" fill="url(#grEmerald)" opacity="0.7"/>
<path d="M 0,-22 L 3,-19 L 0,-16 L -3,-19 Z" fill="url(#grAmethyst)" opacity="0.8"/>
<path d="M 80,8 L 83,11 L 80,14 L 77,11 Z" fill="url(#grAmber)" opacity="0.6"/>
<path d="M 160,-18 L 163,-15 L 160,-12 L 157,-15 Z" fill="url(#grRose)" opacity="0.7"/>
<path d="M 240,-12 L 243,-9 L 240,-6 L 237,-9 Z" fill="url(#grIndigo)" opacity="0.7"/>
</g>
</g>
<text x="0" y="76" class="lbl">The River — emotional flow over time, prismatic gradient band</text>
</g>
<!-- 2. YOUR GLASS — distortion distribution -->
<text x="24" y="244" class="section-lbl">YOUR GLASS</text>
<line x1="24" y1="250" x2="670" y2="250" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(200, 360)">
<!-- Radar/spider chart -->
<g opacity="0.15">
<!-- Axis lines -->
<line x1="0" y1="0" x2="0" y2="-70" stroke="#475569" stroke-width="0.5"/>
<line x1="0" y1="0" x2="61" y2="-35" stroke="#475569" stroke-width="0.5"/>
<line x1="0" y1="0" x2="61" y2="35" stroke="#475569" stroke-width="0.5"/>
<line x1="0" y1="0" x2="0" y2="70" stroke="#475569" stroke-width="0.5"/>
<line x1="0" y1="0" x2="-61" y2="35" stroke="#475569" stroke-width="0.5"/>
<line x1="0" y1="0" x2="-61" y2="-35" stroke="#475569" stroke-width="0.5"/>
<!-- Concentric hex guides -->
<path d="M 0,-35 L 30,-17 L 30,17 L 0,35 L -30,17 L -30,-17 Z" fill="none" stroke="#475569" stroke-width="0.3"/>
<path d="M 0,-70 L 61,-35 L 61,35 L 0,70 L -61,35 L -61,-35 Z" fill="none" stroke="#475569" stroke-width="0.3"/>
</g>
<!-- Data shape (user's distortion profile) -->
<g filter="url(#glowMd)">
<path d="M 0,-55 L 40,-20 L 50,25 L 10,50 L -45,30 L -35,-25 Z"
fill="#F59E0B" fill-opacity="0.08" stroke="#F59E0B" stroke-width="1.2" opacity="0.6"/>
<!-- Vertex fragments -->
<path d="M 0,-55 L 3,-52 L 0,-49 L -3,-52 Z" fill="url(#grAmber)" opacity="0.8" filter="url(#glowSm)"/>
<path d="M 40,-20 L 43,-17 L 40,-14 L 37,-17 Z" fill="url(#grAmber)" opacity="0.7" filter="url(#glowSm)"/>
<path d="M 50,25 L 53,28 L 50,31 L 47,28 Z" fill="url(#grAmber)" opacity="0.7" filter="url(#glowSm)"/>
<path d="M 10,50 L 13,53 L 10,56 L 7,53 Z" fill="url(#grAmber)" opacity="0.6" filter="url(#glowSm)"/>
<path d="M -45,30 L -42,33 L -45,36 L -48,33 Z" fill="url(#grAmber)" opacity="0.7" filter="url(#glowSm)"/>
<path d="M -35,-25 L -32,-22 L -35,-19 L -38,-22 Z" fill="url(#grAmber)" opacity="0.7" filter="url(#glowSm)"/>
</g>
<!-- Labels -->
<g class="data-lbl">
<text x="0" y="-78">Catastrophizing</text>
<text x="72" y="-20">Black-White</text>
<text x="72" y="30">Mind Reading</text>
<text x="0" y="68">Fortune Telling</text>
<text x="-72" y="30">Personalization</text>
<text x="-72" y="-20">Should Stmts</text>
</g>
</g>
<!-- 3. TURN IMPACT — before/after bar chart -->
<g transform="translate(530, 360)">
<text x="0" y="-88" class="section-lbl" text-anchor="middle">TURN IMPACT</text>
<!-- Bar pairs (before/after) -->
<g filter="url(#glowSm)">
<!-- Pair 1: Distress -->
<rect x="-50" y="-40" width="14" height="40" rx="2" fill="#EF4444" opacity="0.4"/>
<rect x="-34" y="-60" width="14" height="60" rx="2" fill="url(#grEmerald)" opacity="0.6"/>
<text x="-36" y="14" class="data-lbl">Distress</text>
<!-- Pair 2: Clarity -->
<rect x="0" y="-25" width="14" height="25" rx="2" fill="#EF4444" opacity="0.4"/>
<rect x="16" y="-55" width="14" height="55" rx="2" fill="url(#grEmerald)" opacity="0.6"/>
<text x="14" y="14" class="data-lbl">Clarity</text>
<!-- Pair 3: Hope -->
<rect x="50" y="-20" width="14" height="20" rx="2" fill="#EF4444" opacity="0.4"/>
<rect x="66" y="-50" width="14" height="50" rx="2" fill="url(#grEmerald)" opacity="0.6"/>
<text x="64" y="14" class="data-lbl">Hope</text>
</g>
<!-- Legend -->
<g transform="translate(0, 30)">
<rect x="-30" y="0" width="8" height="8" rx="1" fill="#EF4444" opacity="0.4"/>
<text x="-18" y="7" font-size="7" fill="#94A3B8">Before</text>
<rect x="20" y="0" width="8" height="8" rx="1" fill="#10B981" opacity="0.6"/>
<text x="32" y="7" font-size="7" fill="#94A3B8">After</text>
</g>
<text x="10" y="56" class="lbl">Turn Impact — before/after comparison</text>
</g>
<!-- 4. RHYTHM DETECTION -->
<text x="24" y="470" class="section-lbl">RHYTHM DETECTION</text>
<line x1="24" y1="476" x2="670" y2="476" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(350, 560)">
<rect x="-280" y="-50" width="560" height="100" rx="8" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.5"/>
<!-- Time axis -->
<g class="axis-lbl" text-anchor="middle">
<text x="-220" y="60">6am</text><text x="-110" y="60">9am</text><text x="0" y="60">12pm</text>
<text x="110" y="60">3pm</text><text x="220" y="60">6pm</text>
</g>
<!-- Activity dots (when user engages) -->
<g filter="url(#glowSm)">
<!-- Morning cluster -->
<circle cx="-200" cy="-10" r="4" fill="url(#grAmethyst)" opacity="0.3"/>
<circle cx="-180" cy="-15" r="5" fill="url(#grAmethyst)" opacity="0.5"/>
<circle cx="-160" cy="-20" r="6" fill="url(#grAmethyst)" opacity="0.7">
<animate attributeName="opacity" values="0.5;0.8;0.5" dur="3s" repeatCount="indefinite"/>
</circle>
<circle cx="-140" cy="-12" r="4" fill="url(#grAmethyst)" opacity="0.4"/>
<!-- Midday lull -->
<circle cx="-40" cy="5" r="3" fill="url(#grSapphire)" opacity="0.2"/>
<circle cx="0" cy="0" r="3" fill="url(#grSapphire)" opacity="0.25"/>
<!-- Afternoon peak -->
<circle cx="100" cy="-25" r="7" fill="url(#grEmerald)" opacity="0.7">
<animate attributeName="opacity" values="0.5;0.8;0.5" dur="3.5s" repeatCount="indefinite"/>
</circle>
<circle cx="120" cy="-18" r="5" fill="url(#grEmerald)" opacity="0.5"/>
<circle cx="140" cy="-10" r="4" fill="url(#grEmerald)" opacity="0.4"/>
<!-- Evening -->
<circle cx="200" cy="10" r="4" fill="url(#grAmber)" opacity="0.3"/>
<circle cx="220" cy="5" r="5" fill="url(#grAmber)" opacity="0.4"/>
</g>
<!-- Pattern line (smoothed) -->
<path d="M -260,10 C -200,-10 -140,-20 -80,0 C -20,15 40,10 100,-25 C 160,-10 220,5 260,10"
fill="none" stroke="#8B5CF6" stroke-width="1" opacity="0.3" stroke-dasharray="4 4"/>
<!-- Peak labels -->
<g filter="url(#glowSm)">
<path d="M -160,-32 L -157,-29 L -160,-26 L -163,-29 Z" fill="url(#grAmethyst)" opacity="0.8"/>
<text x="-160" y="-38" font-size="7" fill="#C4B5FD" text-anchor="middle" font-weight="500">Morning Peak</text>
</g>
<g filter="url(#glowSm)">
<path d="M 100,-37 L 103,-34 L 100,-31 L 97,-34 Z" fill="url(#grEmerald)" opacity="0.8"/>
<text x="100" y="-43" font-size="7" fill="#6EE7B7" text-anchor="middle" font-weight="500">Afternoon Peak</text>
</g>
<text x="0" y="76" class="lbl">Rhythm Detection — engagement patterns over time of day, sized by intensity</text>
</g>
<!-- 5. GROWTH TRAJECTORY -->
<text x="24" y="660" class="section-lbl">GROWTH TRAJECTORY</text>
<line x1="24" y1="666" x2="670" y2="666" stroke="#1C2240" stroke-width="0.5"/>
<g transform="translate(350, 770)">
<rect x="-280" y="-70" width="560" height="140" rx="8" fill="#0A0E1A" stroke="#1C2240" stroke-width="0.5"/>
<!-- Axes -->
<line x1="-260" y1="55" x2="260" y2="55" stroke="#1C2240" stroke-width="0.5"/>
<line x1="-260" y1="55" x2="-260" y2="-55" stroke="#1C2240" stroke-width="0.5"/>
<!-- Month labels -->
<g class="axis-lbl" text-anchor="middle">
<text x="-200" y="68">Jan</text><text x="-110" y="68">Feb</text><text x="-20" y="68">Mar</text>
<text x="70" y="68">Apr</text><text x="160" y="68">May</text><text x="240" y="68">Jun</text>
</g>
<!-- Growth line -->
<g filter="url(#glowMd)">
<path d="M -220,40 C -180,35 -140,20 -80,10 C -20,0 40,-15 100,-25 C 160,-35 200,-40 240,-50"
fill="none" stroke="url(#grAmethyst)" stroke-width="2" stroke-linecap="round" opacity="0.8"/>
<!-- Fill under curve -->
<path d="M -220,40 C -180,35 -140,20 -80,10 C -20,0 40,-15 100,-25 C 160,-35 200,-40 240,-50 L 240,55 L -220,55 Z"
fill="#8B5CF6" opacity="0.04"/>
<!-- Data point fragments -->
<path d="M -220,40 L -217,43 L -220,46 L -223,43 Z" fill="url(#grAmethyst)" opacity="0.6" filter="url(#glowSm)"/>
<path d="M -110,18 L -107,21 L -110,24 L -113,21 Z" fill="url(#grAmethyst)" opacity="0.7" filter="url(#glowSm)"/>
<path d="M -20,4 L -17,7 L -20,10 L -23,7 Z" fill="url(#grAmethyst)" opacity="0.7" filter="url(#glowSm)"/>
<path d="M 70,-18 L 73,-15 L 70,-12 L 67,-15 Z" fill="url(#grAmethyst)" opacity="0.8" filter="url(#glowSm)"/>
<path d="M 160,-36 L 163,-33 L 160,-30 L 157,-33 Z" fill="url(#grAmethyst)" opacity="0.8" filter="url(#glowSm)"/>
<path d="M 240,-50 L 243,-47 L 240,-44 L 237,-47 Z" fill="url(#grAmethyst)" opacity="0.9" filter="url(#glowSm)">
<animate attributeName="opacity" values="0.7;1;0.7" dur="2s" repeatCount="indefinite"/>
</path>
</g>
<!-- Milestone markers -->
<g filter="url(#glowSm)">
<circle cx="-20" cy="4" r="8" fill="none" stroke="#10B981" stroke-width="0.8" opacity="0.4"/>
<text x="-20" y="-10" font-size="7" fill="#6EE7B7" text-anchor="middle">10th Turn</text>
</g>
<g filter="url(#glowSm)">
<circle cx="160" cy="-36" r="8" fill="none" stroke="#F59E0B" stroke-width="0.8" opacity="0.4"/>
<text x="160" y="-48" font-size="7" fill="#FDE68A" text-anchor="middle">30-day streak</text>
</g>
<!-- Y-axis label -->
<text x="-272" y="-10" font-size="7" fill="#475569" transform="rotate(-90, -272, -10)" text-anchor="middle">Resilience Score</text>
</g>
<text x="350" y="860" class="lbl">Growth Trajectory — resilience over months with milestone markers</text>
<text x="350" y="890" font-size="8" fill="#334155" text-anchor="middle">All Spectrum visualizations use fragment-shaped data points, jewel tone gradients, and glow effects</text>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,116 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kalei Core Options — Side by Side</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 30px 20px;
transition: background 0.4s, color 0.4s;
}
h1 { font-size: 24px; font-weight: 300; letter-spacing: 4px; text-transform: uppercase; margin-bottom: 4px; }
.subtitle { font-size: 13px; opacity: 0.5; margin-bottom: 30px; letter-spacing: 1px; }
.bg-toggle {
position: fixed; top: 16px; right: 16px;
display: flex; gap: 6px; z-index: 10;
}
.bg-toggle button {
padding: 6px 14px; border: 1px solid rgba(128,128,128,0.3); border-radius: 16px;
cursor: pointer; font-size: 11px; letter-spacing: 1px; text-transform: uppercase; transition: all 0.3s;
}
.bg-toggle button.active { font-weight: 700; }
body.dark { background: #0a0e1a; color: #e0e0e0; }
body.light { background: #f5f5f5; color: #1a1a1a; }
body.checker { background: repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%) 0 0 / 20px 20px; color: #1a1a1a; }
body.dark .bg-toggle button { background: #1a1f2e; color: #ccc; }
body.dark .bg-toggle button.active { background: #2a3040; border-color: #6366F1; color: #fff; }
body.light .bg-toggle button, body.checker .bg-toggle button { background: #fff; color: #333; }
body.light .bg-toggle button.active, body.checker .bg-toggle button.active { background: #e8e8e8; border-color: #6366F1; }
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
max-width: 900px;
width: 100%;
}
@media (max-width: 700px) { .grid { grid-template-columns: 1fr; } }
.card {
display: flex; flex-direction: column; align-items: center; gap: 10px;
padding: 16px; border-radius: 12px;
transition: background 0.3s;
}
body.dark .card { background: rgba(255,255,255,0.03); }
body.light .card { background: rgba(0,0,0,0.03); }
body.checker .card { background: rgba(255,255,255,0.6); }
.card object { width: 320px; height: 320px; }
.card-label {
font-size: 14px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase;
}
.card-desc {
font-size: 12px; opacity: 0.55; text-align: center; line-height: 1.5; max-width: 280px;
}
.original-ref {
margin-top: 30px; padding-top: 20px;
border-top: 1px solid rgba(128,128,128,0.2);
display: flex; flex-direction: column; align-items: center; gap: 10px;
opacity: 0.5;
}
.original-ref object { width: 200px; height: 200px; }
.original-ref span { font-size: 11px; letter-spacing: 1px; text-transform: uppercase; }
</style>
</head>
<body class="dark">
<div class="bg-toggle">
<button onclick="setBg('dark')" class="active">Dark</button>
<button onclick="setBg('light')">Light</button>
<button onclick="setBg('checker')">Transparent</button>
</div>
<h1>Kalei — Core Options</h1>
<p class="subtitle">Same iris blades, four different cores</p>
<div class="grid">
<div class="card">
<object type="image/svg+xml" data="kalei-gemini-core-A-prismatic-orb.svg"></object>
<span class="card-label">A — Prismatic Orb</span>
<span class="card-desc">Soft glowing crystal sphere with specular highlights and rainbow color cycling. Warm and luminous.</span>
</div>
<div class="card">
<object type="image/svg+xml" data="kalei-gemini-core-B-nebula-vortex.svg"></object>
<span class="card-label">B — Nebula Vortex</span>
<span class="card-desc">Overlapping color clouds counter-rotating to create a dreamy, organic swirl with twinkling stars.</span>
</div>
<div class="card">
<object type="image/svg+xml" data="kalei-gemini-core-C-starburst.svg"></object>
<span class="card-label">C — Starburst</span>
<span class="card-desc">Radiating light rays with staggered sparkle, like energy bursting through a prism. Bold and dynamic.</span>
</div>
<div class="card">
<object type="image/svg+xml" data="kalei-gemini-core-D-bloom.svg"></object>
<span class="card-label">D — Bloom Within</span>
<span class="card-desc">A miniature flower inside the iris that counter-rotates — fractal recursion echoing the kaleidoscope brand.</span>
</div>
</div>
<div class="original-ref">
<object type="image/svg+xml" data="kalei-gemini-animated.svg"></object>
<span>Original (hexagon core) for reference</span>
</div>
<script>
function setBg(mode) {
document.body.className = mode;
document.querySelectorAll('.bg-toggle button').forEach(b => b.classList.remove('active'));
event.target.classList.add('active');
}
</script>
</body>
</html>

View File

@ -0,0 +1,234 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kalei Logo Finalists</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
color: #e2e8f0;
min-height: 100vh;
}
.header {
text-align: center;
padding: 40px 20px 20px;
background: linear-gradient(135deg, #0f0a1a 0%, #1a1025 50%, #0f0a1a 100%);
}
.header h1 {
font-size: 2rem;
font-weight: 300;
letter-spacing: 0.15em;
background: linear-gradient(135deg, #C4B5FD, #93C5FD, #6EE7B7, #FDE68A, #FBCFE8);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 8px;
}
.header p {
font-size: 0.9rem;
color: #94a3b8;
font-weight: 300;
}
.comparison {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0;
min-height: calc(100vh - 120px);
}
.panel {
display: flex;
flex-direction: column;
align-items: center;
padding: 30px 20px 40px;
position: relative;
}
.panel:first-child { border-right: 1px solid rgba(139,92,246,0.15); }
.panel h2 {
font-size: 1.1rem;
font-weight: 400;
letter-spacing: 0.08em;
margin-bottom: 6px;
}
.panel .subtitle {
font-size: 0.75rem;
color: #64748b;
margin-bottom: 20px;
text-align: center;
line-height: 1.5;
}
.logo-container {
width: 320px;
height: 320px;
border-radius: 24px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 24px;
position: relative;
}
.logo-container object {
width: 300px;
height: 300px;
}
.changes {
max-width: 300px;
font-size: 0.72rem;
color: #94a3b8;
line-height: 1.6;
text-align: left;
}
.changes strong {
color: #C4B5FD;
font-weight: 500;
display: block;
margin-bottom: 4px;
font-size: 0.75rem;
letter-spacing: 0.05em;
}
.changes ul {
list-style: none;
padding: 0;
}
.changes ul li {
padding-left: 14px;
position: relative;
margin-bottom: 3px;
}
.changes ul li::before {
content: '';
position: absolute;
left: 0;
top: 7px;
width: 5px;
height: 5px;
border-radius: 50%;
background: linear-gradient(135deg, #C4B5FD, #93C5FD);
opacity: 0.6;
}
/* Background toggle */
.bg-toggle {
position: fixed;
bottom: 20px;
right: 20px;
display: flex;
gap: 6px;
background: rgba(15,10,26,0.9);
border: 1px solid rgba(139,92,246,0.2);
border-radius: 10px;
padding: 6px;
z-index: 100;
}
.bg-toggle button {
border: none;
padding: 6px 14px;
border-radius: 7px;
cursor: pointer;
font-size: 0.7rem;
font-weight: 500;
letter-spacing: 0.04em;
transition: all 0.2s;
color: #94a3b8;
background: transparent;
}
.bg-toggle button.active {
background: rgba(139,92,246,0.25);
color: #C4B5FD;
}
body.bg-dark { background: #0f0a1a; }
body.bg-dark .panel { background: transparent; }
body.bg-mid { background: #1e1b2e; }
body.bg-mid .panel { background: transparent; }
body.bg-light { background: #f8fafc; }
body.bg-light .panel { background: transparent; }
body.bg-light .header { background: linear-gradient(135deg, #f1f5f9, #e2e8f0); }
body.bg-light .header p { color: #64748b; }
body.bg-light .panel h2 { color: #1e293b; }
body.bg-light .panel .subtitle { color: #64748b; }
body.bg-light .panel:first-child { border-right-color: rgba(139,92,246,0.1); }
body.bg-light .changes { color: #475569; }
body.bg-light .changes strong { color: #7c3aed; }
body.bg-white { background: #ffffff; }
body.bg-white .panel { background: transparent; }
body.bg-white .header { background: #ffffff; }
body.bg-white .header p { color: #94a3b8; }
body.bg-white .panel h2 { color: #0f172a; }
body.bg-white .panel .subtitle { color: #94a3b8; }
body.bg-white .panel:first-child { border-right-color: rgba(0,0,0,0.06); }
body.bg-white .changes { color: #64748b; }
body.bg-white .changes strong { color: #7c3aed; }
</style>
</head>
<body class="bg-dark">
<div class="header">
<h1>KALEI FINALISTS</h1>
<p>Refined from semi-finalist round &mdash; white circle removed, details polished</p>
</div>
<div class="comparison">
<div class="panel">
<h2>Glass Facets</h2>
<p class="subtitle">Bloom variant &mdash; stained-glass petals</p>
<div class="logo-container">
<object type="image/svg+xml" data="glass-facets-final.svg"></object>
</div>
<div class="changes">
<strong>Changes from semi-finalist:</strong>
<ul>
<li>Removed dashed white counter-rotating ring (r=100)</li>
<li>Removed dashed white inner core ring (r=22)</li>
<li>Added soft prismatic inter-petal color wash for depth</li>
<li>Inner core ring now uses prismatic gradient instead of white</li>
<li>Rotating dot ring now color-tinted per brand palette</li>
<li>Added petal tip glow points at each apex</li>
<li>Refined refraction lines (softer, rounded caps)</li>
<li>Enhanced specular highlights with tertiary pinpoint</li>
<li>Slightly larger core for better presence</li>
</ul>
</div>
</div>
<div class="panel">
<h2>Soft Elegance</h2>
<p class="subtitle">Starburst variant &mdash; crystalline blades</p>
<div class="logo-container">
<object type="image/svg+xml" data="soft-elegance-final.svg"></object>
</div>
<div class="changes">
<strong>Changes from semi-finalist:</strong>
<ul>
<li>Removed hard white stroke circle (r=50) around core</li>
<li>Replaced with organic prismatic glow transition</li>
<li>Edge shimmers now color-tinted per blade (not plain white)</li>
<li>Added blade tip glow points at outer edges</li>
<li>Added warm amber specular accent in core</li>
<li>Core-to-blade transition now smooth radial gradient</li>
<li>Prismatic halo ring refined for subtlety</li>
</ul>
</div>
</div>
</div>
<div class="bg-toggle">
<button class="active" onclick="setBg('dark')">Dark</button>
<button onclick="setBg('mid')">Mid</button>
<button onclick="setBg('light')">Light</button>
<button onclick="setBg('white')">White</button>
</div>
<script>
function setBg(mode) {
document.body.className = 'bg-' + mode;
document.querySelectorAll('.bg-toggle button').forEach(b => b.classList.remove('active'));
event.target.classList.add('active');
}
</script>
</body>
</html>

Binary file not shown.

View File

@ -0,0 +1,219 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Petal gradients with animated color shifting -->
<linearGradient id="b1" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="4s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#6D28D9"><animate attributeName="stop-color" values="#6D28D9;#8B5CF6;#6D28D9" dur="4s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b2" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#60A5FA"><animate attributeName="stop-color" values="#60A5FA;#93C5FD;#60A5FA" dur="4.5s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#1E40AF"><animate attributeName="stop-color" values="#1E40AF;#3B82F6;#1E40AF" dur="4.5s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b3" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#34D399"><animate attributeName="stop-color" values="#34D399;#6EE7B7;#34D399" dur="5s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#065F46"><animate attributeName="stop-color" values="#065F46;#10B981;#065F46" dur="5s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b4" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.2s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#92400E"><animate attributeName="stop-color" values="#92400E;#D97706;#92400E" dur="4.2s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b5" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#F472B6"><animate attributeName="stop-color" values="#F472B6;#FBCFE8;#F472B6" dur="4.8s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#9D174D"><animate attributeName="stop-color" values="#9D174D;#EC4899;#9D174D" dur="4.8s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b6" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#818CF8"><animate attributeName="stop-color" values="#818CF8;#A5B4FC;#818CF8" dur="4.3s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#3730A3"><animate attributeName="stop-color" values="#3730A3;#6366F1;#3730A3" dur="4.3s" repeatCount="indefinite"/></stop></linearGradient>
<!-- Rotating prismatic gradient for core -->
<linearGradient id="prismatic" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#C4B5FD"><animate attributeName="stop-color" values="#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="25%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD;#93C5FD" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="50%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="75%" stop-color="#FDE68A"><animate attributeName="stop-color" values="#FDE68A;#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7;#FDE68A" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#FBCFE8"><animate attributeName="stop-color" values="#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8" dur="6s" repeatCount="indefinite"/></stop>
</linearGradient>
<!-- Outer aura gradient -->
<radialGradient id="aura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#C4B5FD" stop-opacity="0.15"><animate attributeName="stop-color" values="#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#C4B5FD" stop-opacity="0"/>
</radialGradient>
<!-- Inter-petal glow gradient (replaces dashed circle) -->
<radialGradient id="interPetalGlow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#C4B5FD" stop-opacity="0"/>
<stop offset="45%" stop-color="#A78BFA" stop-opacity="0.06"><animate attributeName="stop-color" values="#A78BFA;#60A5FA;#34D399;#FCD34D;#F472B6;#A78BFA" dur="10s" repeatCount="indefinite"/></stop>
<stop offset="65%" stop-color="#8B5CF6" stop-opacity="0.04"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#D97706;#EC4899;#8B5CF6" dur="10s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<!-- Glow filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="softGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="14" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="sparkle" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur stdDeviation="2" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="petalTipGlow" x="-200%" y="-200%" width="500%" height="500%">
<feGaussianBlur stdDeviation="4" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Breathing outer aura -->
<circle cx="200" cy="200" r="180" fill="url(#aura)">
<animate attributeName="r" values="160;185;160" dur="5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.6;1;0.6" dur="5s" repeatCount="indefinite"/>
</circle>
<!-- Main logo group with very slow rotation -->
<g transform="translate(200,200)">
<animateTransform attributeName="transform" type="rotate" from="0 200 200" to="360 200 200" dur="120s" repeatCount="indefinite" additive="replace"/>
<animateTransform attributeName="transform" type="translate" values="200,200" dur="120s" repeatCount="indefinite" additive="sum"/>
<!-- Soft inter-petal color wash (replaces old dashed circle) -->
<circle r="120" fill="url(#interPetalGlow)">
<animate attributeName="opacity" values="0.5;0.9;0.5" dur="6s" repeatCount="indefinite"/>
</circle>
<!-- Petals with stained-glass outlines and tighter spacing -->
<path d="M 0,-24 Q 48,-98 28,-168 Q -8,-168 -38,-138 Q -28,-78 0,-24" fill="url(#b1)" opacity="0.9" stroke="#fff" stroke-width="0.6" stroke-opacity="0.2">
<animate attributeName="opacity" values="0.85;1;0.85" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 48,-98 28,-168 Q -8,-168 -38,-138 Q -28,-78 0,-24" fill="url(#b2)" opacity="0.87" transform="rotate(60)" stroke="#fff" stroke-width="0.6" stroke-opacity="0.2">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 48,-98 28,-168 Q -8,-168 -38,-138 Q -28,-78 0,-24" fill="url(#b3)" opacity="0.87" transform="rotate(120)" stroke="#fff" stroke-width="0.6" stroke-opacity="0.2">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 48,-98 28,-168 Q -8,-168 -38,-138 Q -28,-78 0,-24" fill="url(#b4)" opacity="0.87" transform="rotate(180)" stroke="#fff" stroke-width="0.6" stroke-opacity="0.2">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 48,-98 28,-168 Q -8,-168 -38,-138 Q -28,-78 0,-24" fill="url(#b5)" opacity="0.87" transform="rotate(240)" stroke="#fff" stroke-width="0.6" stroke-opacity="0.2">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 48,-98 28,-168 Q -8,-168 -38,-138 Q -28,-78 0,-24" fill="url(#b6)" opacity="0.82" transform="rotate(300)" stroke="#fff" stroke-width="0.6" stroke-opacity="0.2">
<animate attributeName="opacity" values="0.78;0.95;0.78" dur="4.3s" repeatCount="indefinite"/>
</path>
<!-- Petal tip glow points — soft colored lights at each petal apex -->
<g filter="url(#petalTipGlow)">
<circle cx="-5" cy="-153" r="3" fill="#C4B5FD" opacity="0">
<animate attributeName="opacity" values="0;0.5;0" dur="4s" repeatCount="indefinite"/>
</circle>
<circle cx="-5" cy="-153" r="3" fill="#93C5FD" opacity="0" transform="rotate(60)">
<animate attributeName="opacity" values="0;0.5;0" dur="4.5s" begin="0.5s" repeatCount="indefinite"/>
</circle>
<circle cx="-5" cy="-153" r="3" fill="#6EE7B7" opacity="0" transform="rotate(120)">
<animate attributeName="opacity" values="0;0.5;0" dur="5s" begin="1s" repeatCount="indefinite"/>
</circle>
<circle cx="-5" cy="-153" r="3" fill="#FDE68A" opacity="0" transform="rotate(180)">
<animate attributeName="opacity" values="0;0.5;0" dur="4.2s" begin="1.5s" repeatCount="indefinite"/>
</circle>
<circle cx="-5" cy="-153" r="3" fill="#FBCFE8" opacity="0" transform="rotate(240)">
<animate attributeName="opacity" values="0;0.5;0" dur="4.8s" begin="2s" repeatCount="indefinite"/>
</circle>
<circle cx="-5" cy="-153" r="3" fill="#A5B4FC" opacity="0" transform="rotate(300)">
<animate attributeName="opacity" values="0;0.5;0" dur="4.3s" begin="2.5s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Subtle refraction light lines radiating from center (refined — softer, shorter) -->
<g opacity="0.18">
<line x1="0" y1="0" x2="0" y2="-140" stroke="#fff" stroke-width="0.4" stroke-linecap="round">
<animate attributeName="opacity" values="0.05;0.3;0.05" dur="3.5s" begin="0s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-140" stroke="#fff" stroke-width="0.4" stroke-linecap="round" transform="rotate(60)">
<animate attributeName="opacity" values="0.05;0.3;0.05" dur="3.5s" begin="0.58s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-140" stroke="#fff" stroke-width="0.4" stroke-linecap="round" transform="rotate(120)">
<animate attributeName="opacity" values="0.05;0.3;0.05" dur="3.5s" begin="1.16s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-140" stroke="#fff" stroke-width="0.4" stroke-linecap="round" transform="rotate(180)">
<animate attributeName="opacity" values="0.05;0.3;0.05" dur="3.5s" begin="1.75s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-140" stroke="#fff" stroke-width="0.4" stroke-linecap="round" transform="rotate(240)">
<animate attributeName="opacity" values="0.05;0.3;0.05" dur="3.5s" begin="2.33s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-140" stroke="#fff" stroke-width="0.4" stroke-linecap="round" transform="rotate(300)">
<animate attributeName="opacity" values="0.05;0.3;0.05" dur="3.5s" begin="2.91s" repeatCount="indefinite"/>
</line>
</g>
<!-- Pulsing prismatic core (slightly larger, richer glow) -->
<circle r="32" fill="url(#prismatic)" filter="url(#softGlow)">
<animate attributeName="r" values="30;35;30" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Core inner depth — soft concentric prismatic ring instead of dashed white circle -->
<circle r="22" fill="none" stroke="url(#prismatic)" stroke-width="1.2" opacity="0.25">
<animate attributeName="r" values="20;25;20" dur="3s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.15;0.35;0.15" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Rotating inner dot ring (8 dots — now prismatic-tinted, not white) -->
<g>
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="15s" repeatCount="indefinite"/>
<circle cx="18" cy="0" r="1" fill="#C4B5FD" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.3;0.1" dur="2.5s" begin="0s" repeatCount="indefinite"/>
</circle>
<circle cx="12.73" cy="12.73" r="1" fill="#93C5FD" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.3;0.1" dur="2.5s" begin="0.625s" repeatCount="indefinite"/>
</circle>
<circle cx="0" cy="18" r="1" fill="#6EE7B7" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.3;0.1" dur="2.5s" begin="1.25s" repeatCount="indefinite"/>
</circle>
<circle cx="-12.73" cy="12.73" r="1" fill="#FDE68A" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.3;0.1" dur="2.5s" begin="1.875s" repeatCount="indefinite"/>
</circle>
<circle cx="-18" cy="0" r="1" fill="#FBCFE8" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.3;0.1" dur="2.5s" begin="2.5s" repeatCount="indefinite"/>
</circle>
<circle cx="-12.73" cy="-12.73" r="1" fill="#A5B4FC" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.3;0.1" dur="2.5s" begin="3.125s" repeatCount="indefinite"/>
</circle>
<circle cx="0" cy="-18" r="1" fill="#C4B5FD" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.3;0.1" dur="2.5s" begin="3.75s" repeatCount="indefinite"/>
</circle>
<circle cx="12.73" cy="-12.73" r="1" fill="#93C5FD" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.3;0.1" dur="2.5s" begin="4.375s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Primary specular highlight on core (enhanced) -->
<circle cx="-7" cy="-9" r="9" fill="white" opacity="0.35">
<animate attributeName="opacity" values="0.25;0.5;0.25" dur="4s" repeatCount="indefinite"/>
<animate attributeName="r" values="8;10;8" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Secondary highlight -->
<circle cx="4" cy="6" r="4" fill="white" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.25;0.1" dur="3.5s" repeatCount="indefinite"/>
</circle>
<!-- Tertiary pinpoint highlight (new — adds glass depth) -->
<circle cx="-3" cy="3" r="1.5" fill="white" opacity="0.1">
<animate attributeName="opacity" values="0.05;0.2;0.05" dur="2.8s" repeatCount="indefinite"/>
</circle>
<!-- Floating sparkle particles orbiting the logo -->
<g filter="url(#sparkle)">
<circle r="2" fill="#C4B5FD" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 1 -0.1,-140"/>
<animate attributeName="opacity" values="0;0.8;0;0;0" dur="8s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;2.5;1" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#93C5FD" opacity="0">
<animateMotion dur="10s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 1 -0.1,-120"/>
<animate attributeName="opacity" values="0;0;0.7;0;0" dur="10s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;2;1" dur="10s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#6EE7B7" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.6;0;0.6;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#FDE68A" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.8;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#FBCFE8" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-145 A145,145 0 1 0 -0.1,-145"/>
<animate attributeName="opacity" values="0;0.7;0;0;0.5;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#fff" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-110 A110,110 0 1 1 -0.1,-110"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="6s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,329 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Blade Gradients: Amethyst (0°) -->
<linearGradient id="g0_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#A78BFA;#8B5CF6" dur="5s" repeatCount="indefinite"/></stop>
</linearGradient>
<linearGradient id="g0_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#8B5CF6"/><stop offset="100%" stop-color="#5B21B6"/>
</linearGradient>
<!-- Blade Gradients: Sapphire (60°) -->
<linearGradient id="g1_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="5.5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#3B82F6"/>
</linearGradient>
<linearGradient id="g1_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3B82F6"/><stop offset="100%" stop-color="#1D4ED8"/>
</linearGradient>
<!-- Blade Gradients: Emerald (120°) -->
<linearGradient id="g2_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#10B981"/>
</linearGradient>
<linearGradient id="g2_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#10B981"/><stop offset="100%" stop-color="#047857"/>
</linearGradient>
<!-- Blade Gradients: Amber (180°) -->
<linearGradient id="g3_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#F59E0B"/>
</linearGradient>
<linearGradient id="g3_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F59E0B"/><stop offset="100%" stop-color="#B45309"/>
</linearGradient>
<!-- Blade Gradients: Rose (240°) -->
<linearGradient id="g4_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F9A8D4"><animate attributeName="stop-color" values="#F9A8D4;#FBCFE8;#F9A8D4" dur="5.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"/>
</linearGradient>
<linearGradient id="g4_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#EC4899"/><stop offset="100%" stop-color="#BE185D"/>
</linearGradient>
<!-- Blade Gradients: Indigo (300°) -->
<linearGradient id="g5_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A5B4FC"><animate attributeName="stop-color" values="#A5B4FC;#C7D2FE;#A5B4FC" dur="5.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#6366F1"/>
</linearGradient>
<linearGradient id="g5_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6366F1"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<!-- Cycling Prismatic Core Gradient for halo -->
<radialGradient id="prismatic" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#FFFFFF"><animate attributeName="stop-color" values="#FFFFFF;#E0D5FF;#FFFFFF" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="40%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
</radialGradient>
<!-- Outer aura for transparent bg -->
<radialGradient id="outerAura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#8B5CF6" stop-opacity="0.08"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="10s" repeatCount="indefinite"/></stop>
<stop offset="70%" stop-color="#8B5CF6" stop-opacity="0.03"/>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<!-- Core transition glow (replaces hard white circle) -->
<radialGradient id="coreHalo" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#FFFFFF" stop-opacity="0"/>
<stop offset="60%" stop-color="#FFFFFF" stop-opacity="0"/>
<stop offset="80%" stop-color="#C4B5FD" stop-opacity="0.08"><animate attributeName="stop-color" values="#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD" dur="8s" repeatCount="indefinite"/><animate attributeName="stop-opacity" values="0.05;0.12;0.05" dur="4s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<!-- Filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="coreGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="12" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="shimmer" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="wideGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="18" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="bladeTipGlow" x="-200%" y="-200%" width="500%" height="500%">
<feGaussianBlur stdDeviation="5" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Subtle breathing aura -->
<circle cx="200" cy="200" r="190" fill="url(#outerAura)">
<animate attributeName="r" values="175;195;175" dur="6s" repeatCount="indefinite"/>
</circle>
<!-- The Iris — slow continuous rotation -->
<g transform="translate(200, 200)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="90s" repeatCount="indefinite" additive="sum"/>
<!-- Amethyst Blade (0°) with shimmer -->
<g transform="rotate(0)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g0_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g0_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.90;1;0.90" dur="4s" repeatCount="indefinite"/>
</path>
<!-- Edge shimmer with color tint -->
<line x1="40" y1="0" x2="-30" y2="160" stroke="#C4B5FD" stroke-width="1.2" opacity="0">
<animate attributeName="opacity" values="0;0.5;0" dur="5s" begin="0s" repeatCount="indefinite"/>
</line>
</g>
<!-- Sapphire Blade (60°) -->
<g transform="rotate(60)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g1_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g1_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#93C5FD" stroke-width="1.2" opacity="0">
<animate attributeName="opacity" values="0;0.5;0" dur="5s" begin="0.83s" repeatCount="indefinite"/>
</line>
</g>
<!-- Emerald Blade (120°) -->
<g transform="rotate(120)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g2_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g2_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#6EE7B7" stroke-width="1.2" opacity="0">
<animate attributeName="opacity" values="0;0.5;0" dur="5s" begin="1.66s" repeatCount="indefinite"/>
</line>
</g>
<!-- Amber Blade (180°) -->
<g transform="rotate(180)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g3_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g3_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#FDE68A" stroke-width="1.2" opacity="0">
<animate attributeName="opacity" values="0;0.5;0" dur="5s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Rose Blade (240°) -->
<g transform="rotate(240)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g4_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g4_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#FBCFE8" stroke-width="1.2" opacity="0">
<animate attributeName="opacity" values="0;0.5;0" dur="5s" begin="3.33s" repeatCount="indefinite"/>
</line>
</g>
<!-- Indigo Blade (300°) -->
<g transform="rotate(300)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g5_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.3s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g5_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#A5B4FC" stroke-width="1.2" opacity="0">
<animate attributeName="opacity" values="0;0.5;0" dur="5s" begin="4.16s" repeatCount="indefinite"/>
</line>
</g>
<!-- Blade tip glow points — soft colored pulses at outer tips of each blade -->
<g filter="url(#bladeTipGlow)">
<circle cx="-30" cy="160" r="4" fill="#A78BFA" opacity="0">
<animate attributeName="opacity" values="0;0.35;0" dur="4s" repeatCount="indefinite"/>
</circle>
<circle cx="-30" cy="160" r="4" fill="#3B82F6" opacity="0" transform="rotate(60)">
<animate attributeName="opacity" values="0;0.35;0" dur="4.5s" begin="0.5s" repeatCount="indefinite"/>
</circle>
<circle cx="-30" cy="160" r="4" fill="#10B981" opacity="0" transform="rotate(120)">
<animate attributeName="opacity" values="0;0.35;0" dur="5s" begin="1s" repeatCount="indefinite"/>
</circle>
<circle cx="-30" cy="160" r="4" fill="#F59E0B" opacity="0" transform="rotate(180)">
<animate attributeName="opacity" values="0;0.35;0" dur="4.2s" begin="1.5s" repeatCount="indefinite"/>
</circle>
<circle cx="-30" cy="160" r="4" fill="#EC4899" opacity="0" transform="rotate(240)">
<animate attributeName="opacity" values="0;0.35;0" dur="4.8s" begin="2s" repeatCount="indefinite"/>
</circle>
<circle cx="-30" cy="160" r="4" fill="#6366F1" opacity="0" transform="rotate(300)">
<animate attributeName="opacity" values="0;0.35;0" dur="4.3s" begin="2.5s" repeatCount="indefinite"/>
</circle>
</g>
<!-- THE KALEIDOSCOPE CORE - SOFT ELEGANCE FINALIST -->
<g filter="url(#coreGlow)">
<!-- Soft radial gradient halo with prismatic color cycling -->
<circle r="45" fill="url(#prismatic)" opacity="0.35">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="5s" repeatCount="indefinite"/>
</circle>
<!-- Organic core transition glow (replaces hard white circle) -->
<circle r="55" fill="url(#coreHalo)">
<animate attributeName="r" values="50;58;50" dur="4s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.6;1;0.6" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Secondary set of 6 thicker colored rays (per brand colors) rotating slowly -->
<g opacity="0.35">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="150s" repeatCount="indefinite"/>
<polygon points="0,0 2,35 -2,35" fill="#A78BFA">
<animate attributeName="opacity" values="0.20;0.40;0.20" dur="4s" repeatCount="indefinite"/>
</polygon>
<polygon points="0,0 2,35 -2,35" fill="#3B82F6" transform="rotate(60)">
<animate attributeName="opacity" values="0.20;0.40;0.20" dur="4.2s" begin="0.4s" repeatCount="indefinite"/>
</polygon>
<polygon points="0,0 2,35 -2,35" fill="#10B981" transform="rotate(120)">
<animate attributeName="opacity" values="0.20;0.40;0.20" dur="4.4s" begin="0.8s" repeatCount="indefinite"/>
</polygon>
<polygon points="0,0 2,35 -2,35" fill="#F59E0B" transform="rotate(180)">
<animate attributeName="opacity" values="0.20;0.40;0.20" dur="4s" begin="1.2s" repeatCount="indefinite"/>
</polygon>
<polygon points="0,0 2,35 -2,35" fill="#EC4899" transform="rotate(240)">
<animate attributeName="opacity" values="0.20;0.40;0.20" dur="4.3s" begin="1.6s" repeatCount="indefinite"/>
</polygon>
<polygon points="0,0 2,35 -2,35" fill="#6366F1" transform="rotate(300)">
<animate attributeName="opacity" values="0.20;0.40;0.20" dur="4.5s" begin="2s" repeatCount="indefinite"/>
</polygon>
</g>
<!-- Primary set of 12 thin white rays radiating outward, alternating lengths -->
<g opacity="0.3">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="75s" repeatCount="indefinite"/>
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.6" stroke-linecap="round" opacity="0">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="4s" begin="0s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.4" stroke-linecap="round" opacity="0" transform="rotate(30)">
<animate attributeName="opacity" values="0;0.20;0;0.10;0" dur="3.5s" begin="0.3s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.6" stroke-linecap="round" opacity="0" transform="rotate(60)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="4.2s" begin="0.6s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.4" stroke-linecap="round" opacity="0" transform="rotate(90)">
<animate attributeName="opacity" values="0;0.20;0;0.10;0" dur="3.8s" begin="0.9s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.6" stroke-linecap="round" opacity="0" transform="rotate(120)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="4s" begin="1.2s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.4" stroke-linecap="round" opacity="0" transform="rotate(150)">
<animate attributeName="opacity" values="0;0.20;0;0.10;0" dur="3.6s" begin="1.5s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.6" stroke-linecap="round" opacity="0" transform="rotate(180)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="4.3s" begin="1.8s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.4" stroke-linecap="round" opacity="0" transform="rotate(210)">
<animate attributeName="opacity" values="0;0.20;0;0.10;0" dur="3.7s" begin="2.1s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.6" stroke-linecap="round" opacity="0" transform="rotate(240)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="4.1s" begin="2.4s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.4" stroke-linecap="round" opacity="0" transform="rotate(270)">
<animate attributeName="opacity" values="0;0.20;0;0.10;0" dur="3.9s" begin="2.7s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.6" stroke-linecap="round" opacity="0" transform="rotate(300)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="4s" begin="3s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.4" stroke-linecap="round" opacity="0" transform="rotate(330)">
<animate attributeName="opacity" values="0;0.20;0;0.10;0" dur="3.8s" begin="3.3s" repeatCount="indefinite"/>
</line>
</g>
<!-- Central bright white-to-prismatic circle with heavy glow and pulsing -->
<circle r="12" fill="#ffffff" filter="url(#coreGlow)" opacity="0.95">
<animate attributeName="r" values="10;14;10" dur="3s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.85;1;0.85" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Inner refraction crescent -->
<circle cx="-4" cy="-4" r="6" fill="#ffffff" opacity="0.2">
<animate attributeName="opacity" values="0.2;0.35;0.2" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Tiny sharp specular highlight off-center -->
<circle cx="3" cy="-3" r="1.5" fill="#ffffff" opacity="0.9" filter="url(#glow)">
<animate attributeName="opacity" values="0.6;1;0.6" dur="1.5s" repeatCount="indefinite"/>
</circle>
<!-- Additional warm specular (new — adds dimension) -->
<circle cx="-2" cy="5" r="2" fill="#FDE68A" opacity="0">
<animate attributeName="opacity" values="0;0.15;0" dur="5s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Orbiting light motes -->
<g filter="url(#shimmer)">
<circle r="2" fill="#A78BFA" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#3B82F6" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 0 -0.1,-140"/>
<animate attributeName="opacity" values="0;0;0.8;0;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#10B981" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-165 A165,165 0 1 1 -0.1,-165"/>
<animate attributeName="opacity" values="0;0.7;0;0.5;0" dur="6s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#F59E0B" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.9;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#EC4899" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-150 A150,150 0 1 1 -0.1,-150"/>
<animate attributeName="opacity" values="0;0.8;0;0;0.6;0" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#fff" opacity="0">
<animateMotion dur="5s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 0 -0.1,-120"/>
<animate attributeName="opacity" values="0;1;0;0;0" dur="5s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

View File

@ -0,0 +1,271 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Dark-First Space Background -->
<radialGradient id="bgGlow" cx="50%" cy="50%" r="65%">
<stop offset="0%" stop-color="#0F1424" />
<stop offset="60%" stop-color="#0A0E1A" />
<stop offset="100%" stop-color="#050508" />
</radialGradient>
<!-- Prismatic Core Exact Brand Gradient -->
<linearGradient id="prismatic" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#8B5CF6"/>
<stop offset="25%" stop-color="#3B82F6"/>
<stop offset="50%" stop-color="#10B981"/>
<stop offset="75%" stop-color="#F59E0B"/>
<stop offset="100%" stop-color="#EC4899"/>
</linearGradient>
<!-- Blade 0: Amethyst -->
<linearGradient id="g0_F1" x1="30" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#C4B5FD"><animate attributeName="stop-color" values="#C4B5FD;#DDD6FE;#C4B5FD" dur="4s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6"/>
</linearGradient>
<linearGradient id="g0_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#8B5CF6"/>
<stop offset="100%" stop-color="#2E1065"/>
</linearGradient>
<!-- Blade 1: Sapphire -->
<linearGradient id="g1_F1" x1="30" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="4.5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#3B82F6"/>
</linearGradient>
<linearGradient id="g1_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3B82F6"/>
<stop offset="100%" stop-color="#172554"/>
</linearGradient>
<!-- Blade 2: Emerald -->
<linearGradient id="g2_F1" x1="30" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#10B981"/>
</linearGradient>
<linearGradient id="g2_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#10B981"/>
<stop offset="100%" stop-color="#022C22"/>
</linearGradient>
<!-- Blade 3: Amber -->
<linearGradient id="g3_F1" x1="30" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#FDE68A"><animate attributeName="stop-color" values="#FDE68A;#FEF3C7;#FDE68A" dur="4.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#F59E0B"/>
</linearGradient>
<linearGradient id="g3_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F59E0B"/>
<stop offset="100%" stop-color="#451A03"/>
</linearGradient>
<!-- Blade 4: Rose -->
<linearGradient id="g4_F1" x1="30" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#FBCFE8"><animate attributeName="stop-color" values="#FBCFE8;#FCE7F3;#FBCFE8" dur="4.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"/>
</linearGradient>
<linearGradient id="g4_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#EC4899"/>
<stop offset="100%" stop-color="#4C0519"/>
</linearGradient>
<!-- Blade 5: Indigo -->
<linearGradient id="g5_F1" x1="30" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#C7D2FE"><animate attributeName="stop-color" values="#C7D2FE;#E0E7FF;#C7D2FE" dur="5.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#6366F1"/>
</linearGradient>
<linearGradient id="g5_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6366F1"/>
<stop offset="100%" stop-color="#1E1B4B"/>
</linearGradient>
<!-- Ethereal Glow Filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="4" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="coreGlow" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur stdDeviation="12" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="wideGlow" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur stdDeviation="24" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Deep Dark Universe Background -->
<rect width="100%" height="100%" fill="url(#bgGlow)" />
<!-- Ambient Pulsing Backlight -->
<circle cx="200" cy="200" r="130" fill="url(#prismatic)" opacity="0.12" filter="url(#wideGlow)">
<animate attributeName="opacity" values="0.08;0.16;0.08" dur="6s" repeatCount="indefinite" />
</circle>
<!-- Main Iris Structure -->
<g transform="translate(200, 200)">
<!-- Outer rotation for the kaleidoscopic shards -->
<g>
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="150s" repeatCount="indefinite" />
<!-- Blade 0 (Amethyst) -->
<g transform="rotate(0)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g0_F2)" fill-opacity="0.9" stroke="#ffffff" stroke-width="0.8" stroke-opacity="0.25" stroke-linejoin="miter">
<animate attributeName="fill-opacity" values="0.85;0.95;0.85" dur="4s" repeatCount="indefinite" />
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g0_F1)" fill-opacity="1" stroke="#ffffff" stroke-width="0.8" stroke-opacity="0.45" stroke-linejoin="miter">
<animate attributeName="fill-opacity" values="0.9;1;0.9" dur="4s" repeatCount="indefinite" />
</path>
</g>
<!-- Blade 1 (Sapphire) -->
<g transform="rotate(60)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g1_F2)" fill-opacity="0.9" stroke="#ffffff" stroke-width="0.8" stroke-opacity="0.25" stroke-linejoin="miter">
<animate attributeName="fill-opacity" values="0.85;0.95;0.85" dur="4.5s" repeatCount="indefinite" />
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g1_F1)" fill-opacity="1" stroke="#ffffff" stroke-width="0.8" stroke-opacity="0.45" stroke-linejoin="miter">
<animate attributeName="fill-opacity" values="0.9;1;0.9" dur="4.5s" repeatCount="indefinite" />
</path>
</g>
<!-- Blade 2 (Emerald) -->
<g transform="rotate(120)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g2_F2)" fill-opacity="0.9" stroke="#ffffff" stroke-width="0.8" stroke-opacity="0.25" stroke-linejoin="miter">
<animate attributeName="fill-opacity" values="0.85;0.95;0.85" dur="5s" repeatCount="indefinite" />
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g2_F1)" fill-opacity="1" stroke="#ffffff" stroke-width="0.8" stroke-opacity="0.45" stroke-linejoin="miter">
<animate attributeName="fill-opacity" values="0.9;1;0.9" dur="5s" repeatCount="indefinite" />
</path>
</g>
<!-- Blade 3 (Amber) -->
<g transform="rotate(180)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g3_F2)" fill-opacity="0.9" stroke="#ffffff" stroke-width="0.8" stroke-opacity="0.25" stroke-linejoin="miter">
<animate attributeName="fill-opacity" values="0.85;0.95;0.85" dur="4.2s" repeatCount="indefinite" />
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g3_F1)" fill-opacity="1" stroke="#ffffff" stroke-width="0.8" stroke-opacity="0.45" stroke-linejoin="miter">
<animate attributeName="fill-opacity" values="0.9;1;0.9" dur="4.2s" repeatCount="indefinite" />
</path>
</g>
<!-- Blade 4 (Rose) -->
<g transform="rotate(240)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g4_F2)" fill-opacity="0.9" stroke="#ffffff" stroke-width="0.8" stroke-opacity="0.25" stroke-linejoin="miter">
<animate attributeName="fill-opacity" values="0.85;0.95;0.85" dur="4.8s" repeatCount="indefinite" />
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g4_F1)" fill-opacity="1" stroke="#ffffff" stroke-width="0.8" stroke-opacity="0.45" stroke-linejoin="miter">
<animate attributeName="fill-opacity" values="0.9;1;0.9" dur="4.8s" repeatCount="indefinite" />
</path>
</g>
<!-- Blade 5 (Indigo) -->
<g transform="rotate(300)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g5_F2)" fill-opacity="0.9" stroke="#ffffff" stroke-width="0.8" stroke-opacity="0.25" stroke-linejoin="miter">
<animate attributeName="fill-opacity" values="0.85;0.95;0.85" dur="5.2s" repeatCount="indefinite" />
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g5_F1)" fill-opacity="1" stroke="#ffffff" stroke-width="0.8" stroke-opacity="0.45" stroke-linejoin="miter">
<animate attributeName="fill-opacity" values="0.9;1;0.9" dur="5.2s" repeatCount="indefinite" />
</path>
</g>
</g>
<!-- The Core Aperture and Prismatic Light Source -->
<g>
<!-- Reverse rotation for the core to detach it optically from the blades -->
<animateTransform attributeName="transform" type="rotate" from="360" to="0" dur="100s" repeatCount="indefinite" />
<!-- Inner Dark Chamber to provide depth against the backlight -->
<polygon points="40,0 20,34.641 -20,34.641 -40,0 -20,-34.641 20,-34.641" fill="#0A0E1A" />
<!-- Core Prismatic Glow bleeding over the inner cut edges -->
<circle r="26" fill="url(#prismatic)" opacity="0.85" filter="url(#coreGlow)">
<animate attributeName="r" values="24;30;24" dur="4s" repeatCount="indefinite" />
<animate attributeName="opacity" values="0.65;0.95;0.65" dur="4s" repeatCount="indefinite" />
</circle>
<!-- Crisp Prismatic Hexagon Mirror inside the chamber -->
<polygon points="30,0 15,25.98 -15,25.98 -30,0 -15,-25.98 15,-25.98" fill="url(#prismatic)" opacity="0.9">
<animate attributeName="opacity" values="0.75;1;0.75" dur="3s" repeatCount="indefinite" />
</polygon>
<!-- Optical Lens Refractions (The Instrument) -->
<circle r="18" fill="none" stroke="#FFFFFF" stroke-width="0.5" opacity="0.4" />
<circle r="8" fill="none" stroke="#FFFFFF" stroke-width="1.5" opacity="0.8" filter="url(#glow)"/>
<!-- Central Blinding Transformation Point -->
<circle r="4" fill="#FFFFFF" filter="url(#glow)">
<animate attributeName="opacity" values="0.8;1;0.8" dur="2s" repeatCount="indefinite" />
<animate attributeName="r" values="3.5;5;3.5" dur="2s" repeatCount="indefinite" />
</circle>
<!-- 12 Optical Refraction Rays -->
<g opacity="0.6">
<line x1="0" y1="0" x2="0" y2="-45" stroke="#FFFFFF" stroke-width="1" transform="rotate(0)"/>
<line x1="0" y1="0" x2="0" y2="-28" stroke="#FFFFFF" stroke-width="0.6" opacity="0.6" transform="rotate(30)"/>
<line x1="0" y1="0" x2="0" y2="-45" stroke="#FFFFFF" stroke-width="1" transform="rotate(60)"/>
<line x1="0" y1="0" x2="0" y2="-28" stroke="#FFFFFF" stroke-width="0.6" opacity="0.6" transform="rotate(90)"/>
<line x1="0" y1="0" x2="0" y2="-45" stroke="#FFFFFF" stroke-width="1" transform="rotate(120)"/>
<line x1="0" y1="0" x2="0" y2="-28" stroke="#FFFFFF" stroke-width="0.6" opacity="0.6" transform="rotate(150)"/>
<line x1="0" y1="0" x2="0" y2="-45" stroke="#FFFFFF" stroke-width="1" transform="rotate(180)"/>
<line x1="0" y1="0" x2="0" y2="-28" stroke="#FFFFFF" stroke-width="0.6" opacity="0.6" transform="rotate(210)"/>
<line x1="0" y1="0" x2="0" y2="-45" stroke="#FFFFFF" stroke-width="1" transform="rotate(240)"/>
<line x1="0" y1="0" x2="0" y2="-28" stroke="#FFFFFF" stroke-width="0.6" opacity="0.6" transform="rotate(270)"/>
<line x1="0" y1="0" x2="0" y2="-45" stroke="#FFFFFF" stroke-width="1" transform="rotate(300)"/>
<line x1="0" y1="0" x2="0" y2="-28" stroke="#FFFFFF" stroke-width="0.6" opacity="0.6" transform="rotate(330)"/>
</g>
</g>
<!-- Floating Crystalline Sparkles (Motes) Orbiting the Instrument -->
<g filter="url(#glow)">
<!-- Counter-rotating orbit -->
<animateTransform attributeName="transform" type="rotate" from="360" to="0" dur="90s" repeatCount="indefinite" />
<!-- Amethyst Mote -->
<g transform="rotate(0) translate(0, -150)">
<polygon points="0,-4 1,-1 4,0 1,1 0,4 -1,1 -4,0 -1,-1" fill="#A78BFA">
<animate attributeName="opacity" values="0;1;0" dur="5s" begin="0s" repeatCount="indefinite" />
<animateTransform attributeName="transform" type="scale" values="0.5; 1.3; 0.5" dur="5s" begin="0s" repeatCount="indefinite" />
</polygon>
</g>
<!-- Sapphire Mote -->
<g transform="rotate(60) translate(0, -130)">
<polygon points="0,-4 1,-1 4,0 1,1 0,4 -1,1 -4,0 -1,-1" fill="#3B82F6">
<animate attributeName="opacity" values="0;1;0" dur="6s" begin="1s" repeatCount="indefinite" />
<animateTransform attributeName="transform" type="scale" values="0.5; 1.3; 0.5" dur="6s" begin="1s" repeatCount="indefinite" />
</polygon>
</g>
<!-- Emerald Mote -->
<g transform="rotate(120) translate(0, -160)">
<polygon points="0,-3 1,-1 3,0 1,1 0,3 -1,1 -3,0 -1,-1" fill="#10B981">
<animate attributeName="opacity" values="0;1;0" dur="4.5s" begin="2s" repeatCount="indefinite" />
<animateTransform attributeName="transform" type="scale" values="0.5; 1.3; 0.5" dur="4.5s" begin="2s" repeatCount="indefinite" />
</polygon>
</g>
<!-- Amber Mote -->
<g transform="rotate(180) translate(0, -145)">
<polygon points="0,-5 1,-1 5,0 1,1 0,5 -1,1 -5,0 -1,-1" fill="#F59E0B">
<animate attributeName="opacity" values="0;1;0" dur="5.5s" begin="3s" repeatCount="indefinite" />
<animateTransform attributeName="transform" type="scale" values="0.5; 1.3; 0.5" dur="5.5s" begin="3s" repeatCount="indefinite" />
</polygon>
</g>
<!-- Rose Mote -->
<g transform="rotate(240) translate(0, -135)">
<polygon points="0,-4 1,-1 4,0 1,1 0,4 -1,1 -4,0 -1,-1" fill="#EC4899">
<animate attributeName="opacity" values="0;1;0" dur="4.8s" begin="1.5s" repeatCount="indefinite" />
<animateTransform attributeName="transform" type="scale" values="0.5; 1.3; 0.5" dur="4.8s" begin="1.5s" repeatCount="indefinite" />
</polygon>
</g>
<!-- Indigo Mote -->
<g transform="rotate(300) translate(0, -155)">
<polygon points="0,-3 1,-1 3,0 1,1 0,3 -1,1 -3,0 -1,-1" fill="#818CF8">
<animate attributeName="opacity" values="0;1;0" dur="5.2s" begin="2.5s" repeatCount="indefinite" />
<animateTransform attributeName="transform" type="scale" values="0.5; 1.3; 0.5" dur="5.2s" begin="2.5s" repeatCount="indefinite" />
</polygon>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,152 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Petal gradients with animated color shifting -->
<linearGradient id="b1" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="4s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#6D28D9"><animate attributeName="stop-color" values="#6D28D9;#8B5CF6;#6D28D9" dur="4s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b2" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#60A5FA"><animate attributeName="stop-color" values="#60A5FA;#93C5FD;#60A5FA" dur="4.5s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#1E40AF"><animate attributeName="stop-color" values="#1E40AF;#3B82F6;#1E40AF" dur="4.5s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b3" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#34D399"><animate attributeName="stop-color" values="#34D399;#6EE7B7;#34D399" dur="5s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#065F46"><animate attributeName="stop-color" values="#065F46;#10B981;#065F46" dur="5s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b4" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.2s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#92400E"><animate attributeName="stop-color" values="#92400E;#D97706;#92400E" dur="4.2s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b5" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#F472B6"><animate attributeName="stop-color" values="#F472B6;#FBCFE8;#F472B6" dur="4.8s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#9D174D"><animate attributeName="stop-color" values="#9D174D;#EC4899;#9D174D" dur="4.8s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b6" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#818CF8"><animate attributeName="stop-color" values="#818CF8;#A5B4FC;#818CF8" dur="4.3s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#3730A3"><animate attributeName="stop-color" values="#3730A3;#6366F1;#3730A3" dur="4.3s" repeatCount="indefinite"/></stop></linearGradient>
<!-- Rotating prismatic gradient for core -->
<linearGradient id="prismatic" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#C4B5FD"><animate attributeName="stop-color" values="#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="25%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD;#93C5FD" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="50%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="75%" stop-color="#FDE68A"><animate attributeName="stop-color" values="#FDE68A;#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7;#FDE68A" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#FBCFE8"><animate attributeName="stop-color" values="#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8" dur="6s" repeatCount="indefinite"/></stop>
</linearGradient>
<!-- Outer aura gradient -->
<radialGradient id="aura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#C4B5FD" stop-opacity="0.15"><animate attributeName="stop-color" values="#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#C4B5FD" stop-opacity="0"/>
</radialGradient>
<!-- Glow filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="softGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="14" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="sparkle" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur stdDeviation="2" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Breathing outer aura -->
<circle cx="200" cy="200" r="180" fill="url(#aura)">
<animate attributeName="r" values="160;185;160" dur="5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.6;1;0.6" dur="5s" repeatCount="indefinite"/>
</circle>
<!-- Main logo group with very slow rotation -->
<g transform="translate(200,200)">
<animateTransform attributeName="transform" type="rotate" from="0 200 200" to="360 200 200" dur="120s" repeatCount="indefinite" additive="replace"/>
<animateTransform attributeName="transform" type="translate" values="200,200" dur="120s" repeatCount="indefinite" additive="sum"/>
<!-- Inner counter-rotating light ring -->
<circle r="100" fill="none" stroke="url(#prismatic)" stroke-width="0.5" opacity="0.3" stroke-dasharray="8 12">
<animateTransform attributeName="transform" type="rotate" from="360" to="0" dur="30s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.2;0.5;0.2" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Petals with staggered breathing opacity -->
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b1)" opacity="0.9">
<animate attributeName="opacity" values="0.85;1;0.85" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b2)" opacity="0.87" transform="rotate(60)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b3)" opacity="0.87" transform="rotate(120)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b4)" opacity="0.87" transform="rotate(180)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b5)" opacity="0.87" transform="rotate(240)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b6)" opacity="0.82" transform="rotate(300)">
<animate attributeName="opacity" values="0.78;0.95;0.78" dur="4.3s" repeatCount="indefinite"/>
</path>
<!-- Refraction light lines radiating from center -->
<g opacity="0.25">
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="0s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(60)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="0.5s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(120)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="1s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(180)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="1.5s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(240)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="2s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(300)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Pulsing prismatic core -->
<circle r="30" fill="url(#prismatic)" filter="url(#softGlow)">
<animate attributeName="r" values="28;33;28" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Inner core detail ring -->
<circle r="22" fill="none" stroke="#fff" stroke-width="0.8" opacity="0.4">
<animate attributeName="r" values="20;24;20" dur="3s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.3;0.6;0.3" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Specular highlight on core -->
<circle cx="-6" cy="-8" r="8" fill="white" opacity="0.3">
<animate attributeName="opacity" values="0.2;0.45;0.2" dur="4s" repeatCount="indefinite"/>
<animate attributeName="r" values="7;9;7" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Secondary highlight -->
<circle cx="4" cy="6" r="4" fill="white" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.25;0.1" dur="3.5s" repeatCount="indefinite"/>
</circle>
<!-- Floating sparkle particles orbiting the logo -->
<g filter="url(#sparkle)">
<circle r="2" fill="#C4B5FD" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 1 -0.1,-140"/>
<animate attributeName="opacity" values="0;0.8;0;0;0" dur="8s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;2.5;1" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#93C5FD" opacity="0">
<animateMotion dur="10s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 1 -0.1,-120"/>
<animate attributeName="opacity" values="0;0;0.7;0;0" dur="10s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;2;1" dur="10s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#6EE7B7" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.6;0;0.6;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#FDE68A" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.8;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#FBCFE8" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-145 A145,145 0 1 0 -0.1,-145"/>
<animate attributeName="opacity" values="0;0.7;0;0;0.5;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#fff" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-110 A110,110 0 1 1 -0.1,-110"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="6s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,229 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Blade Gradients: Amethyst (0°) -->
<linearGradient id="g0_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#A78BFA;#8B5CF6" dur="5s" repeatCount="indefinite"/></stop>
</linearGradient>
<linearGradient id="g0_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#8B5CF6"/><stop offset="100%" stop-color="#5B21B6"/>
</linearGradient>
<!-- Blade Gradients: Sapphire (60°) -->
<linearGradient id="g1_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="5.5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#3B82F6"/>
</linearGradient>
<linearGradient id="g1_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3B82F6"/><stop offset="100%" stop-color="#1D4ED8"/>
</linearGradient>
<!-- Blade Gradients: Emerald (120°) -->
<linearGradient id="g2_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#10B981"/>
</linearGradient>
<linearGradient id="g2_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#10B981"/><stop offset="100%" stop-color="#047857"/>
</linearGradient>
<!-- Blade Gradients: Amber (180°) -->
<linearGradient id="g3_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#F59E0B"/>
</linearGradient>
<linearGradient id="g3_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F59E0B"/><stop offset="100%" stop-color="#B45309"/>
</linearGradient>
<!-- Blade Gradients: Rose (240°) -->
<linearGradient id="g4_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F9A8D4"><animate attributeName="stop-color" values="#F9A8D4;#FBCFE8;#F9A8D4" dur="5.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"/>
</linearGradient>
<linearGradient id="g4_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#EC4899"/><stop offset="100%" stop-color="#BE185D"/>
</linearGradient>
<!-- Blade Gradients: Indigo (300°) -->
<linearGradient id="g5_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A5B4FC"><animate attributeName="stop-color" values="#A5B4FC;#C7D2FE;#A5B4FC" dur="5.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#6366F1"/>
</linearGradient>
<linearGradient id="g5_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6366F1"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<!-- Cycling Prismatic Core Gradient -->
<linearGradient id="prismatic" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="25%" stop-color="#3B82F6"><animate attributeName="stop-color" values="#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6;#3B82F6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="50%" stop-color="#10B981"><animate attributeName="stop-color" values="#10B981;#F59E0B;#EC4899;#8B5CF6;#3B82F6;#10B981" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="75%" stop-color="#F59E0B"><animate attributeName="stop-color" values="#F59E0B;#EC4899;#8B5CF6;#3B82F6;#10B981;#F59E0B" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"><animate attributeName="stop-color" values="#EC4899;#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899" dur="8s" repeatCount="indefinite"/></stop>
</linearGradient>
<!-- Outer aura for transparent bg -->
<radialGradient id="outerAura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#8B5CF6" stop-opacity="0.08"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="10s" repeatCount="indefinite"/></stop>
<stop offset="70%" stop-color="#8B5CF6" stop-opacity="0.03"/>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<!-- Filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="coreGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="12" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="shimmer" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="wideGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="18" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Subtle breathing aura (replaces dark bg) -->
<circle cx="200" cy="200" r="190" fill="url(#outerAura)">
<animate attributeName="r" values="175;195;175" dur="6s" repeatCount="indefinite"/>
</circle>
<!-- The Iris — slow continuous rotation -->
<g transform="translate(200, 200)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="90s" repeatCount="indefinite" additive="sum"/>
<!-- Amethyst Blade (0°) with shimmer -->
<g transform="rotate(0)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g0_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g0_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.90;1;0.90" dur="4s" repeatCount="indefinite"/>
</path>
<!-- Edge shimmer -->
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0s" repeatCount="indefinite"/>
</line>
</g>
<!-- Sapphire Blade (60°) -->
<g transform="rotate(60)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g1_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g1_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0.83s" repeatCount="indefinite"/>
</line>
</g>
<!-- Emerald Blade (120°) -->
<g transform="rotate(120)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g2_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g2_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="1.66s" repeatCount="indefinite"/>
</line>
</g>
<!-- Amber Blade (180°) -->
<g transform="rotate(180)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g3_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g3_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Rose Blade (240°) -->
<g transform="rotate(240)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g4_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g4_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="3.33s" repeatCount="indefinite"/>
</line>
</g>
<!-- Indigo Blade (300°) -->
<g transform="rotate(300)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g5_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.3s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g5_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="4.16s" repeatCount="indefinite"/>
</line>
</g>
<!-- THE KALEIDOSCOPE CORE -->
<g filter="url(#coreGlow)">
<!-- Pulsing prismatic hexagon -->
<polygon points="38,0 19,32.909 -19,32.909 -38,0 -19,-32.909 19,-32.909" fill="url(#prismatic)">
<animateTransform attributeName="transform" type="scale" values="1;1.06;1" dur="3s" repeatCount="indefinite"/>
</polygon>
<!-- Animated mirror lines with sequential flash -->
<line x1="-38" y1="0" x2="38" y2="0" stroke="#ffffff" stroke-width="1.5" opacity="0.6">
<animate attributeName="opacity" values="0.4;0.9;0.4" dur="2.5s" begin="0s" repeatCount="indefinite"/>
</line>
<line x1="-19" y1="-32.909" x2="19" y2="32.909" stroke="#ffffff" stroke-width="1.5" opacity="0.6">
<animate attributeName="opacity" values="0.4;0.9;0.4" dur="2.5s" begin="0.83s" repeatCount="indefinite"/>
</line>
<line x1="19" y1="-32.909" x2="-19" y2="32.909" stroke="#ffffff" stroke-width="1.5" opacity="0.6">
<animate attributeName="opacity" values="0.4;0.9;0.4" dur="2.5s" begin="1.66s" repeatCount="indefinite"/>
</line>
<!-- Pulsing center refraction point -->
<circle r="4" fill="#ffffff" filter="url(#glow)">
<animate attributeName="r" values="3;5.5;3" dur="2s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.8;1;0.8" dur="2s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Outer core edge with pulse -->
<polygon points="38,0 19,32.909 -19,32.909 -38,0 -19,-32.909 19,-32.909" fill="none" stroke="#ffffff" stroke-width="1" opacity="0.8">
<animate attributeName="opacity" values="0.6;1;0.6" dur="3s" repeatCount="indefinite"/>
<animateTransform attributeName="transform" type="scale" values="1;1.06;1" dur="3s" repeatCount="indefinite"/>
</polygon>
<!-- Orbiting light motes -->
<g filter="url(#shimmer)">
<circle r="2" fill="#A78BFA" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#3B82F6" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 0 -0.1,-140"/>
<animate attributeName="opacity" values="0;0;0.8;0;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#10B981" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-165 A165,165 0 1 1 -0.1,-165"/>
<animate attributeName="opacity" values="0;0.7;0;0.5;0" dur="6s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#F59E0B" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.9;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#EC4899" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-150 A150,150 0 1 1 -0.1,-150"/>
<animate attributeName="opacity" values="0;0.8;0;0;0.6;0" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#fff" opacity="0">
<animateMotion dur="5s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 0 -0.1,-120"/>
<animate attributeName="opacity" values="0;1;0;0;0" dur="5s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,260 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Blade Gradients: Amethyst (0°) -->
<linearGradient id="g0_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#A78BFA;#8B5CF6" dur="5s" repeatCount="indefinite"/></stop>
</linearGradient>
<linearGradient id="g0_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#8B5CF6"/><stop offset="100%" stop-color="#5B21B6"/>
</linearGradient>
<!-- Blade Gradients: Sapphire (60°) -->
<linearGradient id="g1_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="5.5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#3B82F6"/>
</linearGradient>
<linearGradient id="g1_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3B82F6"/><stop offset="100%" stop-color="#1D4ED8"/>
</linearGradient>
<!-- Blade Gradients: Emerald (120°) -->
<linearGradient id="g2_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#10B981"/>
</linearGradient>
<linearGradient id="g2_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#10B981"/><stop offset="100%" stop-color="#047857"/>
</linearGradient>
<!-- Blade Gradients: Amber (180°) -->
<linearGradient id="g3_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#F59E0B"/>
</linearGradient>
<linearGradient id="g3_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F59E0B"/><stop offset="100%" stop-color="#B45309"/>
</linearGradient>
<!-- Blade Gradients: Rose (240°) -->
<linearGradient id="g4_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F9A8D4"><animate attributeName="stop-color" values="#F9A8D4;#FBCFE8;#F9A8D4" dur="5.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"/>
</linearGradient>
<linearGradient id="g4_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#EC4899"/><stop offset="100%" stop-color="#BE185D"/>
</linearGradient>
<!-- Blade Gradients: Indigo (300°) -->
<linearGradient id="g5_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A5B4FC"><animate attributeName="stop-color" values="#A5B4FC;#C7D2FE;#A5B4FC" dur="5.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#6366F1"/>
</linearGradient>
<linearGradient id="g5_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6366F1"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<!-- Cycling Prismatic Core Gradient -->
<linearGradient id="prismatic" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="25%" stop-color="#3B82F6"><animate attributeName="stop-color" values="#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6;#3B82F6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="50%" stop-color="#10B981"><animate attributeName="stop-color" values="#10B981;#F59E0B;#EC4899;#8B5CF6;#3B82F6;#10B981" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="75%" stop-color="#F59E0B"><animate attributeName="stop-color" values="#F59E0B;#EC4899;#8B5CF6;#3B82F6;#10B981;#F59E0B" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"><animate attributeName="stop-color" values="#EC4899;#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899" dur="8s" repeatCount="indefinite"/></stop>
</linearGradient>
<!-- Warm inner glow halo for the orb -->
<radialGradient id="warmHalo" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#FCD34D" stop-opacity="0.4"><animate attributeName="stop-color" values="#FCD34D;#F59E0B;#FCD34D" dur="4s" repeatCount="indefinite"/></stop>
<stop offset="60%" stop-color="#F59E0B" stop-opacity="0.1"/>
<stop offset="100%" stop-color="#F59E0B" stop-opacity="0"/>
</radialGradient>
<!-- Soft glow filter for the orb -->
<filter id="softGlow" x="-60%" y="-60%" width="220%" height="220%">
<feGaussianBlur stdDeviation="8" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<!-- Outer aura for transparent bg -->
<radialGradient id="outerAura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#8B5CF6" stop-opacity="0.08"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="10s" repeatCount="indefinite"/></stop>
<stop offset="70%" stop-color="#8B5CF6" stop-opacity="0.03"/>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<!-- Filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="coreGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="12" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="shimmer" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="wideGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="18" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Subtle breathing aura (replaces dark bg) -->
<circle cx="200" cy="200" r="190" fill="url(#outerAura)">
<animate attributeName="r" values="175;195;175" dur="6s" repeatCount="indefinite"/>
</circle>
<!-- The Iris — slow continuous rotation -->
<g transform="translate(200, 200)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="90s" repeatCount="indefinite" additive="sum"/>
<!-- Amethyst Blade (0°) with shimmer -->
<g transform="rotate(0)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g0_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g0_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.90;1;0.90" dur="4s" repeatCount="indefinite"/>
</path>
<!-- Edge shimmer -->
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0s" repeatCount="indefinite"/>
</line>
</g>
<!-- Sapphire Blade (60°) -->
<g transform="rotate(60)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g1_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g1_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0.83s" repeatCount="indefinite"/>
</line>
</g>
<!-- Emerald Blade (120°) -->
<g transform="rotate(120)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g2_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g2_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="1.66s" repeatCount="indefinite"/>
</line>
</g>
<!-- Amber Blade (180°) -->
<g transform="rotate(180)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g3_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g3_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Rose Blade (240°) -->
<g transform="rotate(240)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g4_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g4_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="3.33s" repeatCount="indefinite"/>
</line>
</g>
<!-- Indigo Blade (300°) -->
<g transform="rotate(300)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g5_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.3s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g5_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="4.16s" repeatCount="indefinite"/>
</line>
</g>
<!-- THE KALEIDOSCOPE CORE: Prismatic Orb -->
<g filter="url(#coreGlow)">
<!-- Warm inner glow halo -->
<circle r="38" fill="url(#warmHalo)">
<animate attributeName="r" values="36;40;36" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Main pulsing prismatic orb -->
<circle r="38" fill="url(#prismatic)" filter="url(#softGlow)">
<animate attributeName="r" values="36;42;36" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Subtle breathing outer ring -->
<circle r="32" fill="none" stroke="#ffffff" stroke-width="1" opacity="0.4">
<animate attributeName="r" values="30;35;30" dur="3.2s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.3;0.6;0.3" dur="3.2s" repeatCount="indefinite"/>
</circle>
<!-- Specular highlight 1 (upper left) -->
<circle cx="-10" cy="-12" r="10" fill="white" opacity="0.25" filter="url(#glow)">
<animate attributeName="opacity" values="0.15;0.4;0.15" dur="4s" repeatCount="indefinite"/>
<animate attributeName="r" values="9;12;9" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Specular highlight 2 (lower right) -->
<circle cx="8" cy="10" r="6" fill="white" opacity="0.18" filter="url(#glow)">
<animate attributeName="opacity" values="0.1;0.28;0.1" dur="3.5s" repeatCount="indefinite"/>
<animate attributeName="r" values="5;7;5" dur="3.5s" repeatCount="indefinite"/>
</circle>
<!-- Specular highlight 3 (top) -->
<circle cx="0" cy="-15" r="5" fill="white" opacity="0.2">
<animate attributeName="opacity" values="0.12;0.32;0.12" dur="3.8s" repeatCount="indefinite"/>
<animate attributeName="r" values="4;6;4" dur="3.8s" repeatCount="indefinite"/>
</circle>
<!-- Pulsing center refraction point -->
<circle r="5" fill="#ffffff" filter="url(#glow)" opacity="0.9">
<animate attributeName="r" values="4;6.5;4" dur="2s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.8;1;0.8" dur="2s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Outer core edge with pulse (circular) -->
<circle r="38" fill="none" stroke="#ffffff" stroke-width="1.2" opacity="0.8">
<animate attributeName="opacity" values="0.6;1;0.6" dur="3s" repeatCount="indefinite"/>
<animate attributeName="r" values="38;42;38" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Orbiting light motes -->
<g filter="url(#shimmer)">
<circle r="2" fill="#A78BFA" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#3B82F6" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 0 -0.1,-140"/>
<animate attributeName="opacity" values="0;0;0.8;0;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#10B981" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-165 A165,165 0 1 1 -0.1,-165"/>
<animate attributeName="opacity" values="0;0.7;0;0.5;0" dur="6s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#F59E0B" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.9;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#EC4899" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-150 A150,150 0 1 1 -0.1,-150"/>
<animate attributeName="opacity" values="0;0.8;0;0;0.6;0" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#fff" opacity="0">
<animateMotion dur="5s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 0 -0.1,-120"/>
<animate attributeName="opacity" values="0;1;0;0;0" dur="5s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,265 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Blade Gradients: Amethyst (0°) -->
<linearGradient id="g0_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#A78BFA;#8B5CF6" dur="5s" repeatCount="indefinite"/></stop>
</linearGradient>
<linearGradient id="g0_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#8B5CF6"/><stop offset="100%" stop-color="#5B21B6"/>
</linearGradient>
<!-- Blade Gradients: Sapphire (60°) -->
<linearGradient id="g1_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="5.5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#3B82F6"/>
</linearGradient>
<linearGradient id="g1_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3B82F6"/><stop offset="100%" stop-color="#1D4ED8"/>
</linearGradient>
<!-- Blade Gradients: Emerald (120°) -->
<linearGradient id="g2_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#10B981"/>
</linearGradient>
<linearGradient id="g2_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#10B981"/><stop offset="100%" stop-color="#047857"/>
</linearGradient>
<!-- Blade Gradients: Amber (180°) -->
<linearGradient id="g3_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#F59E0B"/>
</linearGradient>
<linearGradient id="g3_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F59E0B"/><stop offset="100%" stop-color="#B45309"/>
</linearGradient>
<!-- Blade Gradients: Rose (240°) -->
<linearGradient id="g4_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F9A8D4"><animate attributeName="stop-color" values="#F9A8D4;#FBCFE8;#F9A8D4" dur="5.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"/>
</linearGradient>
<linearGradient id="g4_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#EC4899"/><stop offset="100%" stop-color="#BE185D"/>
</linearGradient>
<!-- Blade Gradients: Indigo (300°) -->
<linearGradient id="g5_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A5B4FC"><animate attributeName="stop-color" values="#A5B4FC;#C7D2FE;#A5B4FC" dur="5.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#6366F1"/>
</linearGradient>
<linearGradient id="g5_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6366F1"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<!-- Cycling Prismatic Core Gradient -->
<linearGradient id="prismatic" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="25%" stop-color="#3B82F6"><animate attributeName="stop-color" values="#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6;#3B82F6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="50%" stop-color="#10B981"><animate attributeName="stop-color" values="#10B981;#F59E0B;#EC4899;#8B5CF6;#3B82F6;#10B981" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="75%" stop-color="#F59E0B"><animate attributeName="stop-color" values="#F59E0B;#EC4899;#8B5CF6;#3B82F6;#10B981;#F59E0B" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"><animate attributeName="stop-color" values="#EC4899;#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899" dur="8s" repeatCount="indefinite"/></stop>
</linearGradient>
<!-- Outer aura for transparent bg -->
<radialGradient id="outerAura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#8B5CF6" stop-opacity="0.08"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="10s" repeatCount="indefinite"/></stop>
<stop offset="70%" stop-color="#8B5CF6" stop-opacity="0.03"/>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<!-- Dark nebula base gradient -->
<radialGradient id="nebulaDark" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#1a0a2e" stop-opacity="0.8"/>
<stop offset="100%" stop-color="#1a0a2e" stop-opacity="0"/>
</radialGradient>
<!-- Filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="coreGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="12" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="nebulaCoreGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="8" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="shimmer" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="wideGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="18" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Subtle breathing aura (replaces dark bg) -->
<circle cx="200" cy="200" r="190" fill="url(#outerAura)">
<animate attributeName="r" values="175;195;175" dur="6s" repeatCount="indefinite"/>
</circle>
<!-- The Iris — slow continuous rotation -->
<g transform="translate(200, 200)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="90s" repeatCount="indefinite" additive="sum"/>
<!-- Amethyst Blade (0°) with shimmer -->
<g transform="rotate(0)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g0_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g0_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.90;1;0.90" dur="4s" repeatCount="indefinite"/>
</path>
<!-- Edge shimmer -->
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0s" repeatCount="indefinite"/>
</line>
</g>
<!-- Sapphire Blade (60°) -->
<g transform="rotate(60)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g1_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g1_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0.83s" repeatCount="indefinite"/>
</line>
</g>
<!-- Emerald Blade (120°) -->
<g transform="rotate(120)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g2_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g2_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="1.66s" repeatCount="indefinite"/>
</line>
</g>
<!-- Amber Blade (180°) -->
<g transform="rotate(180)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g3_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g3_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Rose Blade (240°) -->
<g transform="rotate(240)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g4_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g4_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="3.33s" repeatCount="indefinite"/>
</line>
</g>
<!-- Indigo Blade (300°) -->
<g transform="rotate(300)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g5_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.3s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g5_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="4.16s" repeatCount="indefinite"/>
</line>
</g>
<!-- THE KALEIDOSCOPE CORE - Nebula Vortex -->
<g filter="url(#nebulaCoreGlow)">
<!-- Dark nebula base layer -->
<circle cx="0" cy="0" r="45" fill="url(#nebulaDark)" opacity="0.9"/>
<!-- Swirling nebula ellipses with counter-rotating motion -->
<!-- Violet ellipse - fast clockwise -->
<ellipse cx="0" cy="0" rx="32" ry="18" fill="#8B5CF6" opacity="0.5">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="8s" repeatCount="indefinite"/>
</ellipse>
<!-- Blue ellipse - slow counter-clockwise, rotated 30 degrees -->
<ellipse cx="0" cy="0" rx="28" ry="22" fill="#3B82F6" opacity="0.45">
<animateTransform attributeName="transform" type="rotate" from="30" to="-330" dur="12s" repeatCount="indefinite"/>
</ellipse>
<!-- Green ellipse - medium clockwise, rotated 60 degrees -->
<ellipse cx="0" cy="0" rx="25" ry="20" fill="#10B981" opacity="0.48">
<animateTransform attributeName="transform" type="rotate" from="60" to="420" dur="10s" repeatCount="indefinite"/>
</ellipse>
<!-- Pink ellipse - very slow counter-clockwise, rotated 90 degrees -->
<ellipse cx="0" cy="0" rx="30" ry="16" fill="#EC4899" opacity="0.42">
<animateTransform attributeName="transform" type="rotate" from="90" to="-270" dur="15s" repeatCount="indefinite"/>
</ellipse>
<!-- Twinkling star dots scattered inside -->
<circle cx="8" cy="-12" r="1.5" fill="#ffffff" opacity="0">
<animate attributeName="opacity" values="0;0.8;0;0.6;0" dur="3s" repeatCount="indefinite"/>
</circle>
<circle cx="-15" cy="6" r="1" fill="#ffffff" opacity="0">
<animate attributeName="opacity" values="0;0.7;0;0.8;0" dur="2.5s" repeatCount="indefinite"/>
</circle>
<circle cx="12" cy="8" r="1.5" fill="#ffffff" opacity="0">
<animate attributeName="opacity" values="0;0.9;0;0.5;0" dur="3.5s" repeatCount="indefinite"/>
</circle>
<circle cx="-8" cy="-10" r="1" fill="#ffffff" opacity="0">
<animate attributeName="opacity" values="0;0.75;0;0.7;0" dur="2.8s" repeatCount="indefinite"/>
</circle>
<circle cx="4" cy="14" r="1.2" fill="#ffffff" opacity="0">
<animate attributeName="opacity" values="0;0.8;0;0.6;0" dur="3.2s" repeatCount="indefinite"/>
</circle>
<!-- Soft white center glow with pulse -->
<circle cx="0" cy="0" r="8" fill="#ffffff" opacity="0.3" filter="url(#glow)">
<animate attributeName="r" values="6;8;6" dur="2.5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.25;0.5;0.25" dur="2.5s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Outer core edge with pulse -->
<circle cx="0" cy="0" r="43" fill="none" stroke="#ffffff" stroke-width="1.2" opacity="0.7">
<animate attributeName="opacity" values="0.5;0.9;0.5" dur="3s" repeatCount="indefinite"/>
<animate attributeName="r" values="43;45;43" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Orbiting light motes -->
<g filter="url(#shimmer)">
<circle r="2" fill="#A78BFA" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#3B82F6" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 0 -0.1,-140"/>
<animate attributeName="opacity" values="0;0;0.8;0;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#10B981" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-165 A165,165 0 1 1 -0.1,-165"/>
<animate attributeName="opacity" values="0;0.7;0;0.5;0" dur="6s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#F59E0B" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.9;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#EC4899" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-150 A150,150 0 1 1 -0.1,-150"/>
<animate attributeName="opacity" values="0;0.8;0;0;0.6;0" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#fff" opacity="0">
<animateMotion dur="5s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 0 -0.1,-120"/>
<animate attributeName="opacity" values="0;1;0;0;0" dur="5s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,302 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Blade Gradients: Amethyst (0°) -->
<linearGradient id="g0_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#A78BFA;#8B5CF6" dur="5s" repeatCount="indefinite"/></stop>
</linearGradient>
<linearGradient id="g0_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#8B5CF6"/><stop offset="100%" stop-color="#5B21B6"/>
</linearGradient>
<!-- Blade Gradients: Sapphire (60°) -->
<linearGradient id="g1_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="5.5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#3B82F6"/>
</linearGradient>
<linearGradient id="g1_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3B82F6"/><stop offset="100%" stop-color="#1D4ED8"/>
</linearGradient>
<!-- Blade Gradients: Emerald (120°) -->
<linearGradient id="g2_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#10B981"/>
</linearGradient>
<linearGradient id="g2_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#10B981"/><stop offset="100%" stop-color="#047857"/>
</linearGradient>
<!-- Blade Gradients: Amber (180°) -->
<linearGradient id="g3_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#F59E0B"/>
</linearGradient>
<linearGradient id="g3_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F59E0B"/><stop offset="100%" stop-color="#B45309"/>
</linearGradient>
<!-- Blade Gradients: Rose (240°) -->
<linearGradient id="g4_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F9A8D4"><animate attributeName="stop-color" values="#F9A8D4;#FBCFE8;#F9A8D4" dur="5.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"/>
</linearGradient>
<linearGradient id="g4_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#EC4899"/><stop offset="100%" stop-color="#BE185D"/>
</linearGradient>
<!-- Blade Gradients: Indigo (300°) -->
<linearGradient id="g5_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A5B4FC"><animate attributeName="stop-color" values="#A5B4FC;#C7D2FE;#A5B4FC" dur="5.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#6366F1"/>
</linearGradient>
<linearGradient id="g5_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6366F1"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<!-- Cycling Prismatic Core Gradient for halo -->
<radialGradient id="prismatic" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#FFFFFF"><animate attributeName="stop-color" values="#FFFFFF;#E0D5FF;#FFFFFF" dur="4s" repeatCount="indefinite"/></stop>
<stop offset="40%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
</radialGradient>
<!-- Outer aura for transparent bg -->
<radialGradient id="outerAura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#8B5CF6" stop-opacity="0.08"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="10s" repeatCount="indefinite"/></stop>
<stop offset="70%" stop-color="#8B5CF6" stop-opacity="0.03"/>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<!-- Filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="coreGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="12" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="shimmer" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="wideGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="18" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Subtle breathing aura (replaces dark bg) -->
<circle cx="200" cy="200" r="190" fill="url(#outerAura)">
<animate attributeName="r" values="175;195;175" dur="6s" repeatCount="indefinite"/>
</circle>
<!-- The Iris — slow continuous rotation -->
<g transform="translate(200, 200)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="90s" repeatCount="indefinite" additive="sum"/>
<!-- Amethyst Blade (0°) with shimmer -->
<g transform="rotate(0)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g0_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g0_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.90;1;0.90" dur="4s" repeatCount="indefinite"/>
</path>
<!-- Edge shimmer -->
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0s" repeatCount="indefinite"/>
</line>
</g>
<!-- Sapphire Blade (60°) -->
<g transform="rotate(60)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g1_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g1_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0.83s" repeatCount="indefinite"/>
</line>
</g>
<!-- Emerald Blade (120°) -->
<g transform="rotate(120)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g2_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g2_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="1.66s" repeatCount="indefinite"/>
</line>
</g>
<!-- Amber Blade (180°) -->
<g transform="rotate(180)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g3_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g3_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Rose Blade (240°) -->
<g transform="rotate(240)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g4_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g4_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="3.33s" repeatCount="indefinite"/>
</line>
</g>
<!-- Indigo Blade (300°) -->
<g transform="rotate(300)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g5_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.3s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g5_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="4.16s" repeatCount="indefinite"/>
</line>
</g>
<!-- THE KALEIDOSCOPE CORE - STARBURST VARIANT -->
<g filter="url(#coreGlow)">
<!-- Soft radial gradient halo with prismatic color cycling -->
<circle r="45" fill="url(#prismatic)" opacity="0.4">
<animate attributeName="opacity" values="0.3;0.5;0.3" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Secondary set of 6 thicker colored rays (per brand colors) rotating slowly -->
<g opacity="0.35">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="120s" repeatCount="indefinite"/>
<!-- Violet ray -->
<polygon points="0,0 2,35 -2,35" fill="#A78BFA">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4s" repeatCount="indefinite"/>
</polygon>
<!-- Blue ray (60°) -->
<polygon points="0,0 2,35 -2,35" fill="#3B82F6" transform="rotate(60)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4.2s" begin="0.4s" repeatCount="indefinite"/>
</polygon>
<!-- Green ray (120°) -->
<polygon points="0,0 2,35 -2,35" fill="#10B981" transform="rotate(120)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4.4s" begin="0.8s" repeatCount="indefinite"/>
</polygon>
<!-- Amber ray (180°) -->
<polygon points="0,0 2,35 -2,35" fill="#F59E0B" transform="rotate(180)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4s" begin="1.2s" repeatCount="indefinite"/>
</polygon>
<!-- Pink ray (240°) -->
<polygon points="0,0 2,35 -2,35" fill="#EC4899" transform="rotate(240)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4.3s" begin="1.6s" repeatCount="indefinite"/>
</polygon>
<!-- Indigo ray (300°) -->
<polygon points="0,0 2,35 -2,35" fill="#6366F1" transform="rotate(300)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4.5s" begin="2s" repeatCount="indefinite"/>
</polygon>
</g>
<!-- Primary set of 12 thin white rays radiating outward, alternating lengths -->
<g opacity="0.3">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="60s" repeatCount="indefinite"/>
<!-- Ray 0: long (0°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4s" begin="0s" repeatCount="indefinite"/>
</line>
<!-- Ray 1: short (30°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(30)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.5s" begin="0.3s" repeatCount="indefinite"/>
</line>
<!-- Ray 2: long (60°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(60)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4.2s" begin="0.6s" repeatCount="indefinite"/>
</line>
<!-- Ray 3: short (90°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(90)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.8s" begin="0.9s" repeatCount="indefinite"/>
</line>
<!-- Ray 4: long (120°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(120)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4s" begin="1.2s" repeatCount="indefinite"/>
</line>
<!-- Ray 5: short (150°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(150)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.6s" begin="1.5s" repeatCount="indefinite"/>
</line>
<!-- Ray 6: long (180°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(180)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4.3s" begin="1.8s" repeatCount="indefinite"/>
</line>
<!-- Ray 7: short (210°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(210)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.7s" begin="2.1s" repeatCount="indefinite"/>
</line>
<!-- Ray 8: long (240°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(240)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4.1s" begin="2.4s" repeatCount="indefinite"/>
</line>
<!-- Ray 9: short (270°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(270)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.9s" begin="2.7s" repeatCount="indefinite"/>
</line>
<!-- Ray 10: long (300°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(300)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4s" begin="3s" repeatCount="indefinite"/>
</line>
<!-- Ray 11: short (330°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(330)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.8s" begin="3.3s" repeatCount="indefinite"/>
</line>
</g>
<!-- Central bright white-to-prismatic circle with heavy glow and pulsing -->
<circle r="12" fill="#ffffff" filter="url(#coreGlow)" opacity="0.95">
<animate attributeName="r" values="10;14;10" dur="2.5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.85;1;0.85" dur="2.5s" repeatCount="indefinite"/>
</circle>
<!-- Tiny sharp specular highlight off-center -->
<circle cx="3" cy="-3" r="1.5" fill="#ffffff" opacity="0.9" filter="url(#glow)">
<animate attributeName="opacity" values="0.6;1;0.6" dur="1.5s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Outer core edge with pulse (adjusted for starburst radius) -->
<circle r="50" fill="none" stroke="#ffffff" stroke-width="0.8" opacity="0.6">
<animate attributeName="opacity" values="0.4;0.8;0.4" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Orbiting light motes -->
<g filter="url(#shimmer)">
<circle r="2" fill="#A78BFA" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#3B82F6" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 0 -0.1,-140"/>
<animate attributeName="opacity" values="0;0;0.8;0;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#10B981" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-165 A165,165 0 1 1 -0.1,-165"/>
<animate attributeName="opacity" values="0;0.7;0;0.5;0" dur="6s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#F59E0B" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.9;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#EC4899" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-150 A150,150 0 1 1 -0.1,-150"/>
<animate attributeName="opacity" values="0;0.8;0;0;0.6;0" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#fff" opacity="0">
<animateMotion dur="5s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 0 -0.1,-120"/>
<animate attributeName="opacity" values="0;1;0;0;0" dur="5s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,296 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Blade Gradients: Amethyst (0°) -->
<linearGradient id="g0_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#A78BFA;#8B5CF6" dur="5s" repeatCount="indefinite"/></stop>
</linearGradient>
<linearGradient id="g0_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#8B5CF6"/><stop offset="100%" stop-color="#5B21B6"/>
</linearGradient>
<!-- Blade Gradients: Sapphire (60°) -->
<linearGradient id="g1_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="5.5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#3B82F6"/>
</linearGradient>
<linearGradient id="g1_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3B82F6"/><stop offset="100%" stop-color="#1D4ED8"/>
</linearGradient>
<!-- Blade Gradients: Emerald (120°) -->
<linearGradient id="g2_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#10B981"/>
</linearGradient>
<linearGradient id="g2_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#10B981"/><stop offset="100%" stop-color="#047857"/>
</linearGradient>
<!-- Blade Gradients: Amber (180°) -->
<linearGradient id="g3_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#F59E0B"/>
</linearGradient>
<linearGradient id="g3_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F59E0B"/><stop offset="100%" stop-color="#B45309"/>
</linearGradient>
<!-- Blade Gradients: Rose (240°) -->
<linearGradient id="g4_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F9A8D4"><animate attributeName="stop-color" values="#F9A8D4;#FBCFE8;#F9A8D4" dur="5.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"/>
</linearGradient>
<linearGradient id="g4_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#EC4899"/><stop offset="100%" stop-color="#BE185D"/>
</linearGradient>
<!-- Blade Gradients: Indigo (300°) -->
<linearGradient id="g5_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A5B4FC"><animate attributeName="stop-color" values="#A5B4FC;#C7D2FE;#A5B4FC" dur="5.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#6366F1"/>
</linearGradient>
<linearGradient id="g5_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6366F1"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<!-- Cycling Prismatic Core Gradient -->
<linearGradient id="prismatic" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="25%" stop-color="#3B82F6"><animate attributeName="stop-color" values="#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6;#3B82F6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="50%" stop-color="#10B981"><animate attributeName="stop-color" values="#10B981;#F59E0B;#EC4899;#8B5CF6;#3B82F6;#10B981" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="75%" stop-color="#F59E0B"><animate attributeName="stop-color" values="#F59E0B;#EC4899;#8B5CF6;#3B82F6;#10B981;#F59E0B" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"><animate attributeName="stop-color" values="#EC4899;#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899" dur="8s" repeatCount="indefinite"/></stop>
</linearGradient>
<!-- Outer aura for transparent bg -->
<radialGradient id="outerAura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#8B5CF6" stop-opacity="0.08"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="10s" repeatCount="indefinite"/></stop>
<stop offset="70%" stop-color="#8B5CF6" stop-opacity="0.03"/>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<!-- Bloom halo gradient (subtle soft glow) -->
<radialGradient id="bloomHalo" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#ffffff" stop-opacity="0.15"/>
<stop offset="100%" stop-color="#ffffff" stop-opacity="0"/>
</radialGradient>
<!-- Filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="coreGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="12" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="shimmer" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="wideGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="18" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Subtle breathing aura (replaces dark bg) -->
<circle cx="200" cy="200" r="190" fill="url(#outerAura)">
<animate attributeName="r" values="175;195;175" dur="6s" repeatCount="indefinite"/>
</circle>
<!-- The Iris — slow continuous rotation -->
<g transform="translate(200, 200)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="90s" repeatCount="indefinite" additive="sum"/>
<!-- Amethyst Blade (0°) with shimmer -->
<g transform="rotate(0)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g0_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g0_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.90;1;0.90" dur="4s" repeatCount="indefinite"/>
</path>
<!-- Edge shimmer -->
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0s" repeatCount="indefinite"/>
</line>
</g>
<!-- Sapphire Blade (60°) -->
<g transform="rotate(60)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g1_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g1_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0.83s" repeatCount="indefinite"/>
</line>
</g>
<!-- Emerald Blade (120°) -->
<g transform="rotate(120)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g2_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g2_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="1.66s" repeatCount="indefinite"/>
</line>
</g>
<!-- Amber Blade (180°) -->
<g transform="rotate(180)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g3_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g3_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Rose Blade (240°) -->
<g transform="rotate(240)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g4_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g4_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="3.33s" repeatCount="indefinite"/>
</line>
</g>
<!-- Indigo Blade (300°) -->
<g transform="rotate(300)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g5_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.3s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g5_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="4.16s" repeatCount="indefinite"/>
</line>
</g>
<!-- THE KALEIDOSCOPE CORE - MINIATURE BLOOM DESIGN -->
<g filter="url(#coreGlow)">
<!-- Bloom halo (subtle soft glow behind petals) -->
<circle cx="0" cy="0" r="45" fill="url(#bloomHalo)" opacity="0.6">
<animate attributeName="opacity" values="0.4;0.7;0.4" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Mini-petals rotating OPPOSITE to outer iris (counter-rotate) -->
<!-- Each petal uses scaled bezier curve from original: M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24 -->
<!-- Scaled by ~0.23 to fit within r=40 -->
<g transform="rotate(0)" style="mix-blend-mode: screen;">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="20s" repeatCount="indefinite" additive="sum"/>
<!-- Violet petal (0°) -->
<path d="M 0,-5.5 Q 11.5,-23 6.9,-39 Q -2.3,-39 -9.2,-32.2 Q -6.9,-18.4 0,-5.5" fill="#A78BFA" fill-opacity="0.7" stroke="none"/>
<!-- Blue petal (60°) -->
<path d="M 4.75,-2.75 Q 15.75,-16.5 17.25,-30.5 Q 11,-37.25 2.3,-36.5 Q -2.3,-24.75 4.75,-2.75" fill="#60A5FA" fill-opacity="0.7" stroke="none"/>
<!-- Green petal (120°) -->
<path d="M 4.75,2.75 Q 15.75,16.5 17.25,30.5 Q 11,37.25 2.3,36.5 Q -2.3,24.75 4.75,2.75" fill="#34D399" fill-opacity="0.7" stroke="none"/>
<!-- Amber petal (180°) -->
<path d="M 0,5.5 Q 11.5,23 6.9,39 Q -2.3,39 -9.2,32.2 Q -6.9,18.4 0,5.5" fill="#FCD34D" fill-opacity="0.7" stroke="none"/>
<!-- Pink petal (240°) -->
<path d="M -4.75,2.75 Q -15.75,16.5 -17.25,30.5 Q -11,37.25 -2.3,36.5 Q 2.3,24.75 -4.75,2.75" fill="#F472B6" fill-opacity="0.7" stroke="none"/>
<!-- Indigo petal (300°) -->
<path d="M -4.75,-2.75 Q -15.75,-16.5 -17.25,-30.5 Q -11,-37.25 -2.3,-36.5 Q 2.3,-24.75 -4.75,-2.75" fill="#818CF8" fill-opacity="0.7" stroke="none"/>
</g>
<!-- Individual petal breathing animations (staggered) -->
<g transform="rotate(0)">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="20s" repeatCount="indefinite" additive="sum"/>
<path d="M 0,-5.5 Q 11.5,-23 6.9,-39 Q -2.3,-39 -9.2,-32.2 Q -6.9,-18.4 0,-5.5" fill="#A78BFA" fill-opacity="0.7" stroke="none">
<animate attributeName="fill-opacity" values="0.5;0.9;0.5" dur="3s" begin="0s" repeatCount="indefinite"/>
</path>
</g>
<g transform="rotate(60)">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="20s" repeatCount="indefinite" additive="sum"/>
<path d="M 0,-5.5 Q 11.5,-23 6.9,-39 Q -2.3,-39 -9.2,-32.2 Q -6.9,-18.4 0,-5.5" fill="#60A5FA" fill-opacity="0.7" stroke="none">
<animate attributeName="fill-opacity" values="0.5;0.9;0.5" dur="3s" begin="0.5s" repeatCount="indefinite"/>
</path>
</g>
<g transform="rotate(120)">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="20s" repeatCount="indefinite" additive="sum"/>
<path d="M 0,-5.5 Q 11.5,-23 6.9,-39 Q -2.3,-39 -9.2,-32.2 Q -6.9,-18.4 0,-5.5" fill="#34D399" fill-opacity="0.7" stroke="none">
<animate attributeName="fill-opacity" values="0.5;0.9;0.5" dur="3s" begin="1s" repeatCount="indefinite"/>
</path>
</g>
<g transform="rotate(180)">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="20s" repeatCount="indefinite" additive="sum"/>
<path d="M 0,-5.5 Q 11.5,-23 6.9,-39 Q -2.3,-39 -9.2,-32.2 Q -6.9,-18.4 0,-5.5" fill="#FCD34D" fill-opacity="0.7" stroke="none">
<animate attributeName="fill-opacity" values="0.5;0.9;0.5" dur="3s" begin="1.5s" repeatCount="indefinite"/>
</path>
</g>
<g transform="rotate(240)">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="20s" repeatCount="indefinite" additive="sum"/>
<path d="M 0,-5.5 Q 11.5,-23 6.9,-39 Q -2.3,-39 -9.2,-32.2 Q -6.9,-18.4 0,-5.5" fill="#F472B6" fill-opacity="0.7" stroke="none">
<animate attributeName="fill-opacity" values="0.5;0.9;0.5" dur="3s" begin="2s" repeatCount="indefinite"/>
</path>
</g>
<g transform="rotate(300)">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="20s" repeatCount="indefinite" additive="sum"/>
<path d="M 0,-5.5 Q 11.5,-23 6.9,-39 Q -2.3,-39 -9.2,-32.2 Q -6.9,-18.4 0,-5.5" fill="#818CF8" fill-opacity="0.7" stroke="none">
<animate attributeName="fill-opacity" values="0.5;0.9;0.5" dur="3s" begin="2.5s" repeatCount="indefinite"/>
</path>
</g>
<!-- Glowing prismatic center dot with color cycling -->
<circle cx="0" cy="0" r="8" fill="url(#prismatic)" filter="url(#glow)">
<animate attributeName="r" values="6;10;6" dur="2.5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.7;1;0.7" dur="2.5s" repeatCount="indefinite"/>
</circle>
<!-- Specular white highlight on center dot -->
<circle cx="-2" cy="-2" r="3" fill="#ffffff" opacity="0.8" filter="url(#glow)">
<animate attributeName="opacity" values="0.6;1;0.6" dur="2s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Outer core edge polygon (updated for bloom design) -->
<circle cx="0" cy="0" r="45" fill="none" stroke="#ffffff" stroke-width="1" opacity="0.7">
<animate attributeName="opacity" values="0.5;1;0.5" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Orbiting light motes -->
<g filter="url(#shimmer)">
<circle r="2" fill="#A78BFA" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#3B82F6" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 0 -0.1,-140"/>
<animate attributeName="opacity" values="0;0;0.8;0;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#10B981" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-165 A165,165 0 1 1 -0.1,-165"/>
<animate attributeName="opacity" values="0;0.7;0;0.5;0" dur="6s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#F59E0B" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.9;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#EC4899" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-150 A150,150 0 1 1 -0.1,-150"/>
<animate attributeName="opacity" values="0;0.8;0;0;0.6;0" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#fff" opacity="0">
<animateMotion dur="5s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 0 -0.1,-120"/>
<animate attributeName="opacity" values="0;1;0;0;0" dur="5s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

117
logo-mockups/preview.html Normal file
View File

@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kalei Logo Mockups — Animated Preview</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 40px 20px;
transition: background 0.4s;
}
h1 {
font-size: 28px;
font-weight: 300;
letter-spacing: 4px;
text-transform: uppercase;
margin-bottom: 8px;
}
.subtitle {
font-size: 14px;
opacity: 0.6;
margin-bottom: 40px;
letter-spacing: 1px;
}
.bg-toggle {
position: fixed;
top: 20px;
right: 20px;
display: flex;
gap: 8px;
z-index: 10;
}
.bg-toggle button {
padding: 8px 16px;
border: 1px solid rgba(128,128,128,0.3);
border-radius: 20px;
cursor: pointer;
font-size: 12px;
letter-spacing: 1px;
text-transform: uppercase;
transition: all 0.3s;
}
.bg-toggle button.active { font-weight: 700; }
body.dark { background: #0a0e1a; color: #e0e0e0; }
body.light { background: #f5f5f5; color: #1a1a1a; }
body.checker {
background: repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%) 0 0 / 20px 20px;
color: #1a1a1a;
}
body.dark .bg-toggle button { background: #1a1f2e; color: #ccc; }
body.dark .bg-toggle button.active { background: #2a3040; border-color: #6366F1; color: #fff; }
body.light .bg-toggle button { background: #fff; color: #333; }
body.light .bg-toggle button.active { background: #e8e8e8; border-color: #6366F1; }
body.checker .bg-toggle button { background: #fff; color: #333; }
body.checker .bg-toggle button.active { background: #e8e8e8; border-color: #6366F1; }
.logos {
display: flex;
gap: 60px;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.logo-card {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
.logo-card object, .logo-card img {
width: 360px;
height: 360px;
}
.logo-label {
font-size: 13px;
letter-spacing: 2px;
text-transform: uppercase;
opacity: 0.7;
}
</style>
</head>
<body class="dark">
<div class="bg-toggle">
<button onclick="setBg('dark')" class="active">Dark</button>
<button onclick="setBg('light')">Light</button>
<button onclick="setBg('checker')">Transparent</button>
</div>
<h1>Kalei</h1>
<p class="subtitle">Animated Logo Mockups</p>
<div class="logos">
<div class="logo-card">
<object type="image/svg+xml" data="kalei-claude-animated.svg"></object>
<span class="logo-label">Claude Version — Prismatic Bloom</span>
</div>
<div class="logo-card">
<object type="image/svg+xml" data="kalei-gemini-animated.svg"></object>
<span class="logo-label">Gemini Version — Crystalline Iris</span>
</div>
</div>
<script>
function setBg(mode) {
document.body.className = mode;
document.querySelectorAll('.bg-toggle button').forEach(b => b.classList.remove('active'));
event.target.classList.add('active');
}
</script>
</body>
</html>

View File

@ -0,0 +1,162 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Petal gradients with animated color shifting - DEEPER SATURATED COLORS -->
<linearGradient id="b1" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#9575F5"><animate attributeName="stop-color" values="#9575F5;#B89EFF;#9575F5" dur="4s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#6D28D9"><animate attributeName="stop-color" values="#6D28D9;#8B5CF6;#6D28D9" dur="4s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b2" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#4B96F5"><animate attributeName="stop-color" values="#4B96F5;#7DB8FF;#4B96F5" dur="4.5s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#1E40AF"><animate attributeName="stop-color" values="#1E40AF;#3B82F6;#1E40AF" dur="4.5s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b3" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#22C589"><animate attributeName="stop-color" values="#22C589;#52E0AC;#22C589" dur="5s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#065F46"><animate attributeName="stop-color" values="#065F46;#10B981;#065F46" dur="5s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b4" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#F5C030"><animate attributeName="stop-color" values="#F5C030;#FFDD6B;#F5C030" dur="4.2s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#92400E"><animate attributeName="stop-color" values="#92400E;#D97706;#92400E" dur="4.2s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b5" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#EF5BA5"><animate attributeName="stop-color" values="#EF5BA5;#FFA0CC;#EF5BA5" dur="4.8s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#9D174D"><animate attributeName="stop-color" values="#9D174D;#EC4899;#9D174D" dur="4.8s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b6" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#6E7BF5"><animate attributeName="stop-color" values="#6E7BF5;#9BA8FF;#6E7BF5" dur="4.3s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#3730A3"><animate attributeName="stop-color" values="#3730A3;#6366F1;#3730A3" dur="4.3s" repeatCount="indefinite"/></stop></linearGradient>
<!-- Rotating prismatic gradient for core -->
<linearGradient id="prismatic" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#C4B5FD"><animate attributeName="stop-color" values="#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="25%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD;#93C5FD" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="50%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="75%" stop-color="#FDE68A"><animate attributeName="stop-color" values="#FDE68A;#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7;#FDE68A" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#FBCFE8"><animate attributeName="stop-color" values="#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8" dur="6s" repeatCount="indefinite"/></stop>
</linearGradient>
<!-- Outer aura gradient -->
<radialGradient id="aura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#C4B5FD" stop-opacity="0.15"><animate attributeName="stop-color" values="#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#C4B5FD" stop-opacity="0"/>
</radialGradient>
<!-- Glow filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="softGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="14" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="sparkle" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur stdDeviation="2" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Breathing outer aura -->
<circle cx="200" cy="200" r="180" fill="url(#aura)">
<animate attributeName="r" values="160;185;160" dur="5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.6;1;0.6" dur="5s" repeatCount="indefinite"/>
</circle>
<!-- Main logo group with slightly slower rotation -->
<g transform="translate(200,200)">
<animateTransform attributeName="transform" type="rotate" from="0 200 200" to="360 200 200" dur="150s" repeatCount="indefinite" additive="replace"/>
<animateTransform attributeName="transform" type="translate" values="200,200" dur="150s" repeatCount="indefinite" additive="sum"/>
<!-- Inner counter-rotating light ring -->
<circle r="100" fill="none" stroke="url(#prismatic)" stroke-width="0.5" opacity="0.3" stroke-dasharray="8 12">
<animateTransform attributeName="transform" type="rotate" from="360" to="0" dur="30s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.2;0.5;0.2" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Petals with staggered breathing opacity -->
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b1)" opacity="0.9">
<animate attributeName="opacity" values="0.85;1;0.85" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b2)" opacity="0.87" transform="rotate(60)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b3)" opacity="0.87" transform="rotate(120)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b4)" opacity="0.87" transform="rotate(180)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b5)" opacity="0.87" transform="rotate(240)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b6)" opacity="0.82" transform="rotate(300)">
<animate attributeName="opacity" values="0.78;0.95;0.78" dur="4.3s" repeatCount="indefinite"/>
</path>
<!-- Refraction light lines radiating from center -->
<g opacity="0.25">
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="0s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(60)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="0.5s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(120)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="1s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(180)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="1.5s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(240)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="2s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(300)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Pulsing prismatic core - SMALLER -->
<circle r="26" fill="url(#prismatic)" filter="url(#softGlow)">
<animate attributeName="r" values="24;29;24" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Brighter center hotspot overlay - NEW -->
<circle r="14" fill="white" opacity="0.25">
<animate attributeName="opacity" values="0.15;0.35;0.15" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Inner core detail ring -->
<circle r="22" fill="none" stroke="#fff" stroke-width="0.8" opacity="0.4">
<animate attributeName="r" values="20;24;20" dur="3s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.3;0.6;0.3" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Specular highlight on core -->
<circle cx="-6" cy="-8" r="8" fill="white" opacity="0.3">
<animate attributeName="opacity" values="0.2;0.45;0.2" dur="4s" repeatCount="indefinite"/>
<animate attributeName="r" values="7;9;7" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Secondary highlight -->
<circle cx="4" cy="6" r="4" fill="white" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.25;0.1" dur="3.5s" repeatCount="indefinite"/>
</circle>
<!-- Tertiary highlight - NEW -->
<circle cx="8" cy="-3" r="3" fill="white" opacity="0.1">
<animate attributeName="opacity" values="0.05;0.18;0.05" dur="2.8s" repeatCount="indefinite"/>
</circle>
<!-- Floating sparkle particles orbiting the logo -->
<g filter="url(#sparkle)">
<circle r="2" fill="#C4B5FD" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 1 -0.1,-140"/>
<animate attributeName="opacity" values="0;0.8;0;0;0" dur="8s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;2.5;1" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#93C5FD" opacity="0">
<animateMotion dur="10s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 1 -0.1,-120"/>
<animate attributeName="opacity" values="0;0;0.7;0;0" dur="10s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;2;1" dur="10s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#6EE7B7" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.6;0;0.6;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#FDE68A" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.8;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#FBCFE8" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-145 A145,145 0 1 0 -0.1,-145"/>
<animate attributeName="opacity" values="0;0.7;0;0;0.5;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#fff" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-110 A110,110 0 1 1 -0.1,-110"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="6s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,136 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Petal gradients with animated color shifting - lighter, more pastel -->
<linearGradient id="b1" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#C4B5FD"><animate attributeName="stop-color" values="#C4B5FD;#DDD3FF;#C4B5FD" dur="4s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#9F7AEA"><animate attributeName="stop-color" values="#9F7AEA;#B794F6;#9F7AEA" dur="4s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b2" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BAD9FF;#93C5FD" dur="4.5s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#60A5FA"><animate attributeName="stop-color" values="#60A5FA;#93C5FD;#60A5FA" dur="4.5s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b3" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="5s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#34D399"><animate attributeName="stop-color" values="#34D399;#6EE7B7;#34D399" dur="5s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b4" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#FDE68A"><animate attributeName="stop-color" values="#FDE68A;#FEF3C7;#FDE68A" dur="4.2s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.2s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b5" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#F9A8D4"><animate attributeName="stop-color" values="#F9A8D4;#FECDD6;#F9A8D4" dur="4.8s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#F472B6"><animate attributeName="stop-color" values="#F472B6;#F9A8D4;#F472B6" dur="4.8s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b6" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#A5B4FC"><animate attributeName="stop-color" values="#A5B4FC;#C7D2FE;#A5B4FC" dur="4.3s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#818CF8"><animate attributeName="stop-color" values="#818CF8;#A5B4FC;#818CF8" dur="4.3s" repeatCount="indefinite"/></stop></linearGradient>
<!-- Rotating prismatic gradient for core -->
<linearGradient id="prismatic" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#C4B5FD"><animate attributeName="stop-color" values="#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="25%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD;#93C5FD" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="50%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="75%" stop-color="#FDE68A"><animate attributeName="stop-color" values="#FDE68A;#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7;#FDE68A" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#FBCFE8"><animate attributeName="stop-color" values="#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8" dur="6s" repeatCount="indefinite"/></stop>
</linearGradient>
<!-- Outer aura gradient -->
<radialGradient id="aura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#C4B5FD" stop-opacity="0.15"><animate attributeName="stop-color" values="#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#C4B5FD" stop-opacity="0"/>
</radialGradient>
<!-- Glow filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="softGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="18" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="sparkle" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur stdDeviation="2" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Breathing outer aura - larger breath -->
<circle cx="200" cy="200" r="180" fill="url(#aura)">
<animate attributeName="r" values="155;190;155" dur="5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.5;1;0.5" dur="5s" repeatCount="indefinite"/>
</circle>
<!-- Main logo group with very slow rotation -->
<g transform="translate(200,200)">
<animateTransform attributeName="transform" type="rotate" from="0 200 200" to="360 200 200" dur="120s" repeatCount="indefinite" additive="replace"/>
<animateTransform attributeName="transform" type="translate" values="200,200" dur="120s" repeatCount="indefinite" additive="sum"/>
<!-- Inner counter-rotating light ring -->
<circle r="100" fill="none" stroke="url(#prismatic)" stroke-width="0.5" opacity="0.3" stroke-dasharray="8 12">
<animateTransform attributeName="transform" type="rotate" from="360" to="0" dur="30s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.2;0.5;0.2" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Petals with staggered breathing opacity -->
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b1)" opacity="0.9">
<animate attributeName="opacity" values="0.85;1;0.85" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b2)" opacity="0.87" transform="rotate(60)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b3)" opacity="0.87" transform="rotate(120)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b4)" opacity="0.87" transform="rotate(180)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b5)" opacity="0.87" transform="rotate(240)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b6)" opacity="0.82" transform="rotate(300)">
<animate attributeName="opacity" values="0.78;0.95;0.78" dur="4.3s" repeatCount="indefinite"/>
</path>
<!-- Subtle connecting arcs between petal tips -->
<circle r="165" fill="none" stroke="#fff" stroke-width="0.4" opacity="0.15" stroke-dasharray="20 68">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="45s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.12;0.25;0.12" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Pulsing prismatic core - larger, dreamier -->
<circle r="35" fill="url(#prismatic)" filter="url(#softGlow)">
<animate attributeName="r" values="32;38;32" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Inner core detail ring -->
<circle r="22" fill="none" stroke="#fff" stroke-width="0.8" opacity="0.4">
<animate attributeName="r" values="20;24;20" dur="3s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.3;0.6;0.3" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Specular highlight on core -->
<circle cx="-6" cy="-8" r="8" fill="white" opacity="0.3">
<animate attributeName="opacity" values="0.2;0.45;0.2" dur="4s" repeatCount="indefinite"/>
<animate attributeName="r" values="7;9;7" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Secondary highlight -->
<circle cx="4" cy="6" r="4" fill="white" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.25;0.1" dur="3.5s" repeatCount="indefinite"/>
</circle>
<!-- Floating sparkle particles orbiting the logo -->
<g filter="url(#sparkle)">
<circle r="2" fill="#C4B5FD" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 1 -0.1,-140"/>
<animate attributeName="opacity" values="0;0.8;0;0;0" dur="8s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;2.5;1" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#93C5FD" opacity="0">
<animateMotion dur="10s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 1 -0.1,-120"/>
<animate attributeName="opacity" values="0;0;0.7;0;0" dur="10s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;2;1" dur="10s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#6EE7B7" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.6;0;0.6;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#FDE68A" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.8;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#FBCFE8" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-145 A145,145 0 1 0 -0.1,-145"/>
<animate attributeName="opacity" values="0;0.7;0;0;0.5;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#fff" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-110 A110,110 0 1 1 -0.1,-110"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="6s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,181 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Petal gradients with animated color shifting -->
<linearGradient id="b1" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="4s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#6D28D9"><animate attributeName="stop-color" values="#6D28D9;#8B5CF6;#6D28D9" dur="4s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b2" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#60A5FA"><animate attributeName="stop-color" values="#60A5FA;#93C5FD;#60A5FA" dur="4.5s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#1E40AF"><animate attributeName="stop-color" values="#1E40AF;#3B82F6;#1E40AF" dur="4.5s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b3" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#34D399"><animate attributeName="stop-color" values="#34D399;#6EE7B7;#34D399" dur="5s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#065F46"><animate attributeName="stop-color" values="#065F46;#10B981;#065F46" dur="5s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b4" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.2s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#92400E"><animate attributeName="stop-color" values="#92400E;#D97706;#92400E" dur="4.2s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b5" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#F472B6"><animate attributeName="stop-color" values="#F472B6;#FBCFE8;#F472B6" dur="4.8s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#9D174D"><animate attributeName="stop-color" values="#9D174D;#EC4899;#9D174D" dur="4.8s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b6" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#818CF8"><animate attributeName="stop-color" values="#818CF8;#A5B4FC;#818CF8" dur="4.3s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#3730A3"><animate attributeName="stop-color" values="#3730A3;#6366F1;#3730A3" dur="4.3s" repeatCount="indefinite"/></stop></linearGradient>
<!-- Rotating prismatic gradient for core -->
<linearGradient id="prismatic" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#C4B5FD"><animate attributeName="stop-color" values="#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="25%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD;#93C5FD" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="50%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="75%" stop-color="#FDE68A"><animate attributeName="stop-color" values="#FDE68A;#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7;#FDE68A" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#FBCFE8"><animate attributeName="stop-color" values="#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8" dur="6s" repeatCount="indefinite"/></stop>
</linearGradient>
<!-- Outer aura gradient -->
<radialGradient id="aura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#C4B5FD" stop-opacity="0.15"><animate attributeName="stop-color" values="#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#C4B5FD" stop-opacity="0"/>
</radialGradient>
<!-- Glow filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="softGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="14" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="sparkle" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur stdDeviation="2" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Breathing outer aura -->
<circle cx="200" cy="200" r="180" fill="url(#aura)">
<animate attributeName="r" values="160;185;160" dur="5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.6;1;0.6" dur="5s" repeatCount="indefinite"/>
</circle>
<!-- Main logo group with very slow rotation -->
<g transform="translate(200,200)">
<animateTransform attributeName="transform" type="rotate" from="0 200 200" to="360 200 200" dur="120s" repeatCount="indefinite" additive="replace"/>
<animateTransform attributeName="transform" type="translate" values="200,200" dur="120s" repeatCount="indefinite" additive="sum"/>
<!-- Inner counter-rotating light ring -->
<circle r="100" fill="none" stroke="url(#prismatic)" stroke-width="1.0" stroke-dasharray="4 3" opacity="0.3">
<animateTransform attributeName="transform" type="rotate" from="360" to="0" dur="30s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.2;0.5;0.2" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Petals with stained-glass outlines and tighter spacing -->
<path d="M 0,-24 Q 48,-98 28,-168 Q -8,-168 -38,-138 Q -28,-78 0,-24" fill="url(#b1)" opacity="0.9" stroke="#fff" stroke-width="0.6" stroke-opacity="0.2">
<animate attributeName="opacity" values="0.85;1;0.85" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 48,-98 28,-168 Q -8,-168 -38,-138 Q -28,-78 0,-24" fill="url(#b2)" opacity="0.87" transform="rotate(60)" stroke="#fff" stroke-width="0.6" stroke-opacity="0.2">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 48,-98 28,-168 Q -8,-168 -38,-138 Q -28,-78 0,-24" fill="url(#b3)" opacity="0.87" transform="rotate(120)" stroke="#fff" stroke-width="0.6" stroke-opacity="0.2">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 48,-98 28,-168 Q -8,-168 -38,-138 Q -28,-78 0,-24" fill="url(#b4)" opacity="0.87" transform="rotate(180)" stroke="#fff" stroke-width="0.6" stroke-opacity="0.2">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 48,-98 28,-168 Q -8,-168 -38,-138 Q -28,-78 0,-24" fill="url(#b5)" opacity="0.87" transform="rotate(240)" stroke="#fff" stroke-width="0.6" stroke-opacity="0.2">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 48,-98 28,-168 Q -8,-168 -38,-138 Q -28,-78 0,-24" fill="url(#b6)" opacity="0.82" transform="rotate(300)" stroke="#fff" stroke-width="0.6" stroke-opacity="0.2">
<animate attributeName="opacity" values="0.78;0.95;0.78" dur="4.3s" repeatCount="indefinite"/>
</path>
<!-- Refraction light lines radiating from center -->
<g opacity="0.25">
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="0s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(60)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="0.5s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(120)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="1s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(180)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="1.5s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(240)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="2s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(300)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Pulsing prismatic core -->
<circle r="30" fill="url(#prismatic)" filter="url(#softGlow)">
<animate attributeName="r" values="28;33;28" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Inner core detail ring -->
<circle r="22" fill="none" stroke="#fff" stroke-width="1.0" stroke-dasharray="4 3" opacity="0.4">
<animate attributeName="r" values="20;24;20" dur="3s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.3;0.6;0.3" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Rotating inner dot ring (8 dots arranged in circle at r=18, rotating opposite to main) -->
<g>
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="15s" repeatCount="indefinite"/>
<circle cx="18" cy="0" r="1" fill="#fff" opacity="0.2">
<animate attributeName="opacity" values="0.15;0.3;0.15" dur="2.5s" begin="0s" repeatCount="indefinite"/>
</circle>
<circle cx="12.73" cy="12.73" r="1" fill="#fff" opacity="0.2">
<animate attributeName="opacity" values="0.15;0.3;0.15" dur="2.5s" begin="0.625s" repeatCount="indefinite"/>
</circle>
<circle cx="0" cy="18" r="1" fill="#fff" opacity="0.2">
<animate attributeName="opacity" values="0.15;0.3;0.15" dur="2.5s" begin="1.25s" repeatCount="indefinite"/>
</circle>
<circle cx="-12.73" cy="12.73" r="1" fill="#fff" opacity="0.2">
<animate attributeName="opacity" values="0.15;0.3;0.15" dur="2.5s" begin="1.875s" repeatCount="indefinite"/>
</circle>
<circle cx="-18" cy="0" r="1" fill="#fff" opacity="0.2">
<animate attributeName="opacity" values="0.15;0.3;0.15" dur="2.5s" begin="2.5s" repeatCount="indefinite"/>
</circle>
<circle cx="-12.73" cy="-12.73" r="1" fill="#fff" opacity="0.2">
<animate attributeName="opacity" values="0.15;0.3;0.15" dur="2.5s" begin="3.125s" repeatCount="indefinite"/>
</circle>
<circle cx="0" cy="-18" r="1" fill="#fff" opacity="0.2">
<animate attributeName="opacity" values="0.15;0.3;0.15" dur="2.5s" begin="3.75s" repeatCount="indefinite"/>
</circle>
<circle cx="12.73" cy="-12.73" r="1" fill="#fff" opacity="0.2">
<animate attributeName="opacity" values="0.15;0.3;0.15" dur="2.5s" begin="4.375s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Specular highlight on core -->
<circle cx="-6" cy="-8" r="8" fill="white" opacity="0.3">
<animate attributeName="opacity" values="0.2;0.45;0.2" dur="4s" repeatCount="indefinite"/>
<animate attributeName="r" values="7;9;7" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Secondary highlight -->
<circle cx="4" cy="6" r="4" fill="white" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.25;0.1" dur="3.5s" repeatCount="indefinite"/>
</circle>
<!-- Floating sparkle particles orbiting the logo -->
<g filter="url(#sparkle)">
<circle r="2" fill="#C4B5FD" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 1 -0.1,-140"/>
<animate attributeName="opacity" values="0;0.8;0;0;0" dur="8s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;2.5;1" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#93C5FD" opacity="0">
<animateMotion dur="10s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 1 -0.1,-120"/>
<animate attributeName="opacity" values="0;0;0.7;0;0" dur="10s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;2;1" dur="10s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#6EE7B7" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.6;0;0.6;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#FDE68A" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.8;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#FBCFE8" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-145 A145,145 0 1 0 -0.1,-145"/>
<animate attributeName="opacity" values="0;0.7;0;0;0.5;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#fff" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-110 A110,110 0 1 1 -0.1,-110"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="6s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,152 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Petal gradients with animated color shifting -->
<linearGradient id="b1" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="4s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#6D28D9"><animate attributeName="stop-color" values="#6D28D9;#8B5CF6;#6D28D9" dur="4s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b2" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#60A5FA"><animate attributeName="stop-color" values="#60A5FA;#93C5FD;#60A5FA" dur="4.5s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#1E40AF"><animate attributeName="stop-color" values="#1E40AF;#3B82F6;#1E40AF" dur="4.5s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b3" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#34D399"><animate attributeName="stop-color" values="#34D399;#6EE7B7;#34D399" dur="5s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#065F46"><animate attributeName="stop-color" values="#065F46;#10B981;#065F46" dur="5s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b4" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.2s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#92400E"><animate attributeName="stop-color" values="#92400E;#D97706;#92400E" dur="4.2s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b5" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#F472B6"><animate attributeName="stop-color" values="#F472B6;#FBCFE8;#F472B6" dur="4.8s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#9D174D"><animate attributeName="stop-color" values="#9D174D;#EC4899;#9D174D" dur="4.8s" repeatCount="indefinite"/></stop></linearGradient>
<linearGradient id="b6" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#818CF8"><animate attributeName="stop-color" values="#818CF8;#A5B4FC;#818CF8" dur="4.3s" repeatCount="indefinite"/></stop><stop offset="100%" stop-color="#3730A3"><animate attributeName="stop-color" values="#3730A3;#6366F1;#3730A3" dur="4.3s" repeatCount="indefinite"/></stop></linearGradient>
<!-- Rotating prismatic gradient for core -->
<linearGradient id="prismatic" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#C4B5FD"><animate attributeName="stop-color" values="#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="25%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD;#93C5FD" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="50%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="75%" stop-color="#FDE68A"><animate attributeName="stop-color" values="#FDE68A;#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7;#FDE68A" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#FBCFE8"><animate attributeName="stop-color" values="#FBCFE8;#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8" dur="6s" repeatCount="indefinite"/></stop>
</linearGradient>
<!-- Outer aura gradient -->
<radialGradient id="aura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#C4B5FD" stop-opacity="0.15"><animate attributeName="stop-color" values="#C4B5FD;#93C5FD;#6EE7B7;#FDE68A;#FBCFE8;#C4B5FD" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#C4B5FD" stop-opacity="0"/>
</radialGradient>
<!-- Glow filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="softGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="14" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="sparkle" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur stdDeviation="2" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Breathing outer aura -->
<circle cx="200" cy="200" r="180" fill="url(#aura)">
<animate attributeName="r" values="160;185;160" dur="5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.6;1;0.6" dur="5s" repeatCount="indefinite"/>
</circle>
<!-- Main logo group with very slow rotation -->
<g transform="translate(200,200)">
<animateTransform attributeName="transform" type="rotate" from="0 200 200" to="360 200 200" dur="120s" repeatCount="indefinite" additive="replace"/>
<animateTransform attributeName="transform" type="translate" values="200,200" dur="120s" repeatCount="indefinite" additive="sum"/>
<!-- Inner counter-rotating light ring -->
<circle r="100" fill="none" stroke="url(#prismatic)" stroke-width="0.5" opacity="0.3" stroke-dasharray="8 12">
<animateTransform attributeName="transform" type="rotate" from="360" to="0" dur="30s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.2;0.5;0.2" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Petals with staggered breathing opacity -->
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b1)" opacity="0.9">
<animate attributeName="opacity" values="0.85;1;0.85" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b2)" opacity="0.87" transform="rotate(60)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b3)" opacity="0.87" transform="rotate(120)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b4)" opacity="0.87" transform="rotate(180)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b5)" opacity="0.87" transform="rotate(240)">
<animate attributeName="opacity" values="0.82;0.97;0.82" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 0,-24 Q 50,-100 30,-170 Q -10,-170 -40,-140 Q -30,-80 0,-24" fill="url(#b6)" opacity="0.82" transform="rotate(300)">
<animate attributeName="opacity" values="0.78;0.95;0.78" dur="4.3s" repeatCount="indefinite"/>
</path>
<!-- Refraction light lines radiating from center -->
<g opacity="0.25">
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="0s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(60)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="0.5s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(120)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="1s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(180)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="1.5s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(240)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="2s" repeatCount="indefinite"/>
</line>
<line x1="0" y1="0" x2="0" y2="-165" stroke="#fff" stroke-width="0.5" transform="rotate(300)">
<animate attributeName="opacity" values="0.1;0.4;0.1" dur="3s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Pulsing prismatic core -->
<circle r="30" fill="url(#prismatic)" filter="url(#softGlow)">
<animate attributeName="r" values="28;33;28" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Inner core detail ring -->
<circle r="22" fill="none" stroke="#fff" stroke-width="0.8" opacity="0.4">
<animate attributeName="r" values="20;24;20" dur="3s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.3;0.6;0.3" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Specular highlight on core -->
<circle cx="-6" cy="-8" r="8" fill="white" opacity="0.3">
<animate attributeName="opacity" values="0.2;0.45;0.2" dur="4s" repeatCount="indefinite"/>
<animate attributeName="r" values="7;9;7" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Secondary highlight -->
<circle cx="4" cy="6" r="4" fill="white" opacity="0.15">
<animate attributeName="opacity" values="0.1;0.25;0.1" dur="3.5s" repeatCount="indefinite"/>
</circle>
<!-- Floating sparkle particles orbiting the logo -->
<g filter="url(#sparkle)">
<circle r="2" fill="#C4B5FD" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 1 -0.1,-140"/>
<animate attributeName="opacity" values="0;0.8;0;0;0" dur="8s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;2.5;1" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#93C5FD" opacity="0">
<animateMotion dur="10s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 1 -0.1,-120"/>
<animate attributeName="opacity" values="0;0;0.7;0;0" dur="10s" repeatCount="indefinite"/>
<animate attributeName="r" values="1;2;1" dur="10s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#6EE7B7" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.6;0;0.6;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#FDE68A" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.8;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#FBCFE8" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-145 A145,145 0 1 0 -0.1,-145"/>
<animate attributeName="opacity" values="0;0.7;0;0;0.5;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#fff" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-110 A110,110 0 1 1 -0.1,-110"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="6s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kalei Logo Finalists — Polished Variants</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
min-height: 100vh;
display: flex; flex-direction: column; align-items: center;
padding: 30px 20px 60px;
transition: background 0.4s, color 0.4s;
}
h1 { font-size: 22px; font-weight: 300; letter-spacing: 5px; text-transform: uppercase; margin-bottom: 4px; }
.subtitle { font-size: 12px; opacity: 0.45; margin-bottom: 10px; letter-spacing: 1px; }
.controls {
position: fixed; top: 14px; right: 14px;
display: flex; gap: 6px; z-index: 10;
}
.controls button {
padding: 5px 12px; border: 1px solid rgba(128,128,128,0.3); border-radius: 14px;
cursor: pointer; font-size: 10px; letter-spacing: 1px; text-transform: uppercase; transition: all 0.3s;
}
.controls button.active { font-weight: 700; }
body.dark { background: #0a0e1a; color: #e0e0e0; }
body.light { background: #f5f5f5; color: #1a1a1a; }
body.checker { background: repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%) 0 0 / 18px 18px; color: #1a1a1a; }
body.dark .controls button { background: #1a1f2e; color: #ccc; }
body.dark .controls button.active { background: #2a3040; border-color: #6366F1; color: #fff; }
body.light .controls button, body.checker .controls button { background: #fff; color: #333; }
body.light .controls button.active, body.checker .controls button.active { background: #e8e8e8; border-color: #6366F1; }
.section-title {
font-size: 13px; font-weight: 600; letter-spacing: 3px; text-transform: uppercase;
margin: 28px 0 14px; opacity: 0.6;
border-bottom: 1px solid rgba(128,128,128,0.2); padding-bottom: 6px;
width: 100%; max-width: 1100px; text-align: center;
}
.row {
display: flex; gap: 16px; flex-wrap: wrap; justify-content: center;
max-width: 1100px; width: 100%;
}
.card {
display: flex; flex-direction: column; align-items: center; gap: 8px;
padding: 12px; border-radius: 10px; transition: background 0.3s;
flex: 0 1 auto;
}
body.dark .card { background: rgba(255,255,255,0.03); }
body.light .card { background: rgba(0,0,0,0.03); }
body.checker .card { background: rgba(255,255,255,0.6); }
.card object { width: 240px; height: 240px; }
.card.original object { width: 180px; height: 180px; opacity: 0.6; }
.card-label { font-size: 12px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; }
.card-desc { font-size: 11px; opacity: 0.5; text-align: center; line-height: 1.45; max-width: 220px; }
.card.original .card-label { opacity: 0.5; font-size: 10px; }
.badge {
display: inline-block; padding: 2px 8px; border-radius: 8px; font-size: 9px;
letter-spacing: 1px; text-transform: uppercase; font-weight: 600; margin-bottom: 2px;
}
body.dark .badge { background: rgba(99,102,241,0.15); color: #A5B4FC; }
body.light .badge, body.checker .badge { background: rgba(99,102,241,0.1); color: #4338CA; }
</style>
</head>
<body class="dark">
<div class="controls">
<button onclick="setBg('dark')" class="active">Dark</button>
<button onclick="setBg('light')">Light</button>
<button onclick="setBg('checker')">Transparency</button>
</div>
<h1>Kalei Finalists</h1>
<p class="subtitle">Subtle polish variants of both logos</p>
<!-- STARBURST SECTION -->
<div class="section-title">Starburst (Gemini Iris)</div>
<div class="row">
<div class="card original">
<object type="image/svg+xml" data="starburst-original.svg"></object>
<span class="card-label">Original</span>
</div>
<div class="card">
<span class="badge">S1</span>
<object type="image/svg+xml" data="starburst-S1-warm-radiance.svg"></object>
<span class="card-label">Warm Radiance</span>
<span class="card-desc">Warmer gold-toned halo, larger core orb, subtle dashed inner ring, softer colored rays</span>
</div>
<div class="card">
<span class="badge">S2</span>
<object type="image/svg+xml" data="starburst-S2-soft-elegance.svg"></object>
<span class="card-label">Soft Elegance</span>
<span class="card-desc">Rounded softer rays, slower animations, prismatic ring detail, inner refraction crescent</span>
</div>
<div class="card">
<span class="badge">S3</span>
<object type="image/svg+xml" data="starburst-S3-prismatic-diamond.svg"></object>
<span class="card-label">Prismatic Diamond</span>
<span class="card-desc">Diamond-cut center, crisper rays, faint rotating hex wireframe, dual specular highlights</span>
</div>
</div>
<!-- BLOOM SECTION -->
<div class="section-title">Prismatic Bloom (Claude Flower)</div>
<div class="row">
<div class="card original">
<object type="image/svg+xml" data="bloom-original.svg"></object>
<span class="card-label">Original</span>
</div>
<div class="card">
<span class="badge">C1</span>
<object type="image/svg+xml" data="bloom-C1-deep-saturation.svg"></object>
<span class="card-label">Deep Saturation</span>
<span class="card-desc">Richer petal colors, tighter brighter core with hotspot, triple specular highlights, stately pace</span>
</div>
<div class="card">
<span class="badge">C2</span>
<object type="image/svg+xml" data="bloom-C2-ethereal-light.svg"></object>
<span class="card-label">Ethereal Light</span>
<span class="card-desc">Pastel petals, larger dreamy core, deeper aura breathing, connecting arcs, no refraction lines</span>
</div>
<div class="card">
<span class="badge">C3</span>
<object type="image/svg+xml" data="bloom-C3-glass-facets.svg"></object>
<span class="card-label">Glass Facets</span>
<span class="card-desc">Stained-glass petal outlines, rotating dot ring, tighter spacing, faceted inner ring</span>
</div>
</div>
<script>
function setBg(mode) {
document.body.className = mode;
document.querySelectorAll('.controls button').forEach(b => b.classList.remove('active'));
event.target.classList.add('active');
}
</script>
</body>
</html>

View File

@ -0,0 +1,307 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Blade Gradients: Amethyst (0°) -->
<linearGradient id="g0_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#A78BFA;#8B5CF6" dur="5s" repeatCount="indefinite"/></stop>
</linearGradient>
<linearGradient id="g0_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#8B5CF6"/><stop offset="100%" stop-color="#5B21B6"/>
</linearGradient>
<!-- Blade Gradients: Sapphire (60°) -->
<linearGradient id="g1_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="5.5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#3B82F6"/>
</linearGradient>
<linearGradient id="g1_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3B82F6"/><stop offset="100%" stop-color="#1D4ED8"/>
</linearGradient>
<!-- Blade Gradients: Emerald (120°) -->
<linearGradient id="g2_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#10B981"/>
</linearGradient>
<linearGradient id="g2_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#10B981"/><stop offset="100%" stop-color="#047857"/>
</linearGradient>
<!-- Blade Gradients: Amber (180°) -->
<linearGradient id="g3_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#F59E0B"/>
</linearGradient>
<linearGradient id="g3_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F59E0B"/><stop offset="100%" stop-color="#B45309"/>
</linearGradient>
<!-- Blade Gradients: Rose (240°) -->
<linearGradient id="g4_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F9A8D4"><animate attributeName="stop-color" values="#F9A8D4;#FBCFE8;#F9A8D4" dur="5.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"/>
</linearGradient>
<linearGradient id="g4_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#EC4899"/><stop offset="100%" stop-color="#BE185D"/>
</linearGradient>
<!-- Blade Gradients: Indigo (300°) -->
<linearGradient id="g5_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A5B4FC"><animate attributeName="stop-color" values="#A5B4FC;#C7D2FE;#A5B4FC" dur="5.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#6366F1"/>
</linearGradient>
<linearGradient id="g5_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6366F1"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<!-- Cycling Prismatic Core Gradient for halo - WARM RADIANCE VARIANT -->
<radialGradient id="prismatic" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#FDE68A"><animate attributeName="stop-color" values="#FDE68A;#F3E8FF;#FDE68A" dur="4s" repeatCount="indefinite"/></stop>
<stop offset="40%" stop-color="#F59E0B"><animate attributeName="stop-color" values="#F59E0B;#A78BFA;#3B82F6;#10B981;#F59E0B" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#F59E0B" stop-opacity="0"><animate attributeName="stop-color" values="#F59E0B;#A78BFA;#3B82F6;#10B981;#F59E0B" dur="8s" repeatCount="indefinite"/></stop>
</radialGradient>
<!-- Outer aura for transparent bg -->
<radialGradient id="outerAura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#8B5CF6" stop-opacity="0.08"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="10s" repeatCount="indefinite"/></stop>
<stop offset="70%" stop-color="#8B5CF6" stop-opacity="0.03"/>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<!-- Filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="coreGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="12" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="shimmer" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="wideGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="18" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Subtle breathing aura (replaces dark bg) -->
<circle cx="200" cy="200" r="190" fill="url(#outerAura)">
<animate attributeName="r" values="175;195;175" dur="6s" repeatCount="indefinite"/>
</circle>
<!-- The Iris — slow continuous rotation -->
<g transform="translate(200, 200)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="90s" repeatCount="indefinite" additive="sum"/>
<!-- Amethyst Blade (0°) with shimmer -->
<g transform="rotate(0)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g0_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g0_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.90;1;0.90" dur="4s" repeatCount="indefinite"/>
</path>
<!-- Edge shimmer -->
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0s" repeatCount="indefinite"/>
</line>
</g>
<!-- Sapphire Blade (60°) -->
<g transform="rotate(60)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g1_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g1_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0.83s" repeatCount="indefinite"/>
</line>
</g>
<!-- Emerald Blade (120°) -->
<g transform="rotate(120)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g2_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g2_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="1.66s" repeatCount="indefinite"/>
</line>
</g>
<!-- Amber Blade (180°) -->
<g transform="rotate(180)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g3_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g3_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Rose Blade (240°) -->
<g transform="rotate(240)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g4_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g4_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="3.33s" repeatCount="indefinite"/>
</line>
</g>
<!-- Indigo Blade (300°) -->
<g transform="rotate(300)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g5_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.3s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g5_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="4.16s" repeatCount="indefinite"/>
</line>
</g>
<!-- THE KALEIDOSCOPE CORE - WARM RADIANCE VARIANT -->
<g filter="url(#coreGlow)">
<!-- Soft radial gradient halo with warm prismatic color cycling -->
<circle r="45" fill="url(#prismatic)" opacity="0.4">
<animate attributeName="opacity" values="0.3;0.5;0.3" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Secondary set of 6 thicker colored rays (per brand colors) rotating slowly - SOFTENED -->
<g opacity="0.25">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="120s" repeatCount="indefinite"/>
<!-- Violet ray -->
<polygon points="0,0 2,35 -2,35" fill="#A78BFA">
<animate attributeName="opacity" values="0.20;0.38;0.20" dur="4s" repeatCount="indefinite"/>
</polygon>
<!-- Blue ray (60°) -->
<polygon points="0,0 2,35 -2,35" fill="#3B82F6" transform="rotate(60)">
<animate attributeName="opacity" values="0.20;0.38;0.20" dur="4.2s" begin="0.4s" repeatCount="indefinite"/>
</polygon>
<!-- Green ray (120°) -->
<polygon points="0,0 2,35 -2,35" fill="#10B981" transform="rotate(120)">
<animate attributeName="opacity" values="0.20;0.38;0.20" dur="4.4s" begin="0.8s" repeatCount="indefinite"/>
</polygon>
<!-- Amber ray (180°) -->
<polygon points="0,0 2,35 -2,35" fill="#F59E0B" transform="rotate(180)">
<animate attributeName="opacity" values="0.20;0.38;0.20" dur="4s" begin="1.2s" repeatCount="indefinite"/>
</polygon>
<!-- Pink ray (240°) -->
<polygon points="0,0 2,35 -2,35" fill="#EC4899" transform="rotate(240)">
<animate attributeName="opacity" values="0.20;0.38;0.20" dur="4.3s" begin="1.6s" repeatCount="indefinite"/>
</polygon>
<!-- Indigo ray (300°) -->
<polygon points="0,0 2,35 -2,35" fill="#6366F1" transform="rotate(300)">
<animate attributeName="opacity" values="0.20;0.38;0.20" dur="4.5s" begin="2s" repeatCount="indefinite"/>
</polygon>
</g>
<!-- Primary set of 12 thin white rays radiating outward, alternating lengths -->
<g opacity="0.3">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="60s" repeatCount="indefinite"/>
<!-- Ray 0: long (0°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4s" begin="0s" repeatCount="indefinite"/>
</line>
<!-- Ray 1: short (30°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(30)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.5s" begin="0.3s" repeatCount="indefinite"/>
</line>
<!-- Ray 2: long (60°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(60)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4.2s" begin="0.6s" repeatCount="indefinite"/>
</line>
<!-- Ray 3: short (90°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(90)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.8s" begin="0.9s" repeatCount="indefinite"/>
</line>
<!-- Ray 4: long (120°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(120)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4s" begin="1.2s" repeatCount="indefinite"/>
</line>
<!-- Ray 5: short (150°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(150)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.6s" begin="1.5s" repeatCount="indefinite"/>
</line>
<!-- Ray 6: long (180°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(180)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4.3s" begin="1.8s" repeatCount="indefinite"/>
</line>
<!-- Ray 7: short (210°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(210)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.7s" begin="2.1s" repeatCount="indefinite"/>
</line>
<!-- Ray 8: long (240°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(240)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4.1s" begin="2.4s" repeatCount="indefinite"/>
</line>
<!-- Ray 9: short (270°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(270)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.9s" begin="2.7s" repeatCount="indefinite"/>
</line>
<!-- Ray 10: long (300°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(300)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4s" begin="3s" repeatCount="indefinite"/>
</line>
<!-- Ray 11: short (330°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(330)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.8s" begin="3.3s" repeatCount="indefinite"/>
</line>
</g>
<!-- Central bright white-to-prismatic circle with heavy glow and pulsing - ENLARGED -->
<circle r="15" fill="#ffffff" filter="url(#coreGlow)" opacity="0.95">
<animate attributeName="r" values="13;17;13" dur="2.5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.85;1;0.85" dur="2.5s" repeatCount="indefinite"/>
</circle>
<!-- Tiny sharp specular highlight off-center -->
<circle cx="3" cy="-3" r="1.5" fill="#ffffff" opacity="0.9" filter="url(#glow)">
<animate attributeName="opacity" values="0.6;1;0.6" dur="1.5s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Outer core edge with pulse (adjusted for starburst radius) -->
<circle r="50" fill="none" stroke="#ffffff" stroke-width="0.8" opacity="0.6">
<animate attributeName="opacity" values="0.4;0.8;0.4" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Second concentric dashed ring - SUBTLE STRUCTURE -->
<circle r="42" fill="none" stroke="#ffffff" stroke-width="0.4" opacity="0.15" stroke-dasharray="3 6">
<animate attributeName="opacity" values="0.15;0.35;0.15" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Orbiting light motes -->
<g filter="url(#shimmer)">
<circle r="2" fill="#A78BFA" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#3B82F6" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 0 -0.1,-140"/>
<animate attributeName="opacity" values="0;0;0.8;0;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#10B981" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-165 A165,165 0 1 1 -0.1,-165"/>
<animate attributeName="opacity" values="0;0.7;0;0.5;0" dur="6s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#F59E0B" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.9;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#EC4899" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-150 A150,150 0 1 1 -0.1,-150"/>
<animate attributeName="opacity" values="0;0.8;0;0;0.6;0" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#fff" opacity="0">
<animateMotion dur="5s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 0 -0.1,-120"/>
<animate attributeName="opacity" values="0;1;0;0;0" dur="5s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,312 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Blade Gradients: Amethyst (0°) -->
<linearGradient id="g0_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#A78BFA;#8B5CF6" dur="5s" repeatCount="indefinite"/></stop>
</linearGradient>
<linearGradient id="g0_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#8B5CF6"/><stop offset="100%" stop-color="#5B21B6"/>
</linearGradient>
<!-- Blade Gradients: Sapphire (60°) -->
<linearGradient id="g1_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="5.5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#3B82F6"/>
</linearGradient>
<linearGradient id="g1_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3B82F6"/><stop offset="100%" stop-color="#1D4ED8"/>
</linearGradient>
<!-- Blade Gradients: Emerald (120°) -->
<linearGradient id="g2_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#10B981"/>
</linearGradient>
<linearGradient id="g2_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#10B981"/><stop offset="100%" stop-color="#047857"/>
</linearGradient>
<!-- Blade Gradients: Amber (180°) -->
<linearGradient id="g3_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#F59E0B"/>
</linearGradient>
<linearGradient id="g3_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F59E0B"/><stop offset="100%" stop-color="#B45309"/>
</linearGradient>
<!-- Blade Gradients: Rose (240°) -->
<linearGradient id="g4_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F9A8D4"><animate attributeName="stop-color" values="#F9A8D4;#FBCFE8;#F9A8D4" dur="5.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"/>
</linearGradient>
<linearGradient id="g4_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#EC4899"/><stop offset="100%" stop-color="#BE185D"/>
</linearGradient>
<!-- Blade Gradients: Indigo (300°) -->
<linearGradient id="g5_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A5B4FC"><animate attributeName="stop-color" values="#A5B4FC;#C7D2FE;#A5B4FC" dur="5.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#6366F1"/>
</linearGradient>
<linearGradient id="g5_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6366F1"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<!-- Cycling Prismatic Core Gradient for halo -->
<radialGradient id="prismatic" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#FFFFFF"><animate attributeName="stop-color" values="#FFFFFF;#E0D5FF;#FFFFFF" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="40%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
</radialGradient>
<!-- Outer aura for transparent bg -->
<radialGradient id="outerAura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#8B5CF6" stop-opacity="0.08"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="10s" repeatCount="indefinite"/></stop>
<stop offset="70%" stop-color="#8B5CF6" stop-opacity="0.03"/>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<!-- Filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="coreGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="12" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="shimmer" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="wideGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="18" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Subtle breathing aura (replaces dark bg) -->
<circle cx="200" cy="200" r="190" fill="url(#outerAura)">
<animate attributeName="r" values="175;195;175" dur="6s" repeatCount="indefinite"/>
</circle>
<!-- The Iris — slow continuous rotation -->
<g transform="translate(200, 200)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="90s" repeatCount="indefinite" additive="sum"/>
<!-- Amethyst Blade (0°) with shimmer -->
<g transform="rotate(0)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g0_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g0_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.90;1;0.90" dur="4s" repeatCount="indefinite"/>
</path>
<!-- Edge shimmer -->
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0s" repeatCount="indefinite"/>
</line>
</g>
<!-- Sapphire Blade (60°) -->
<g transform="rotate(60)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g1_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g1_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0.83s" repeatCount="indefinite"/>
</line>
</g>
<!-- Emerald Blade (120°) -->
<g transform="rotate(120)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g2_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g2_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="1.66s" repeatCount="indefinite"/>
</line>
</g>
<!-- Amber Blade (180°) -->
<g transform="rotate(180)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g3_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g3_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Rose Blade (240°) -->
<g transform="rotate(240)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g4_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g4_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="3.33s" repeatCount="indefinite"/>
</line>
</g>
<!-- Indigo Blade (300°) -->
<g transform="rotate(300)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g5_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.3s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g5_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="4.16s" repeatCount="indefinite"/>
</line>
</g>
<!-- THE KALEIDOSCOPE CORE - STARBURST VARIANT (REFINED S2) -->
<g filter="url(#coreGlow)">
<!-- Soft radial gradient halo with prismatic color cycling -->
<circle r="45" fill="url(#prismatic)" opacity="0.35">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="5s" repeatCount="indefinite"/>
</circle>
<!-- Subtle second prismatic halo ring (new) -->
<circle r="38" fill="none" stroke="url(#prismatic)" stroke-width="0.6" opacity="0.2">
<animate attributeName="opacity" values="0.2;0.4;0.2" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Secondary set of 6 thicker colored rays (per brand colors) rotating slowly -->
<g opacity="0.35">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="150s" repeatCount="indefinite"/>
<!-- Violet ray -->
<polygon points="0,0 2,35 -2,35" fill="#A78BFA">
<animate attributeName="opacity" values="0.20;0.40;0.20" dur="4s" repeatCount="indefinite"/>
</polygon>
<!-- Blue ray (60°) -->
<polygon points="0,0 2,35 -2,35" fill="#3B82F6" transform="rotate(60)">
<animate attributeName="opacity" values="0.20;0.40;0.20" dur="4.2s" begin="0.4s" repeatCount="indefinite"/>
</polygon>
<!-- Green ray (120°) -->
<polygon points="0,0 2,35 -2,35" fill="#10B981" transform="rotate(120)">
<animate attributeName="opacity" values="0.20;0.40;0.20" dur="4.4s" begin="0.8s" repeatCount="indefinite"/>
</polygon>
<!-- Amber ray (180°) -->
<polygon points="0,0 2,35 -2,35" fill="#F59E0B" transform="rotate(180)">
<animate attributeName="opacity" values="0.20;0.40;0.20" dur="4s" begin="1.2s" repeatCount="indefinite"/>
</polygon>
<!-- Pink ray (240°) -->
<polygon points="0,0 2,35 -2,35" fill="#EC4899" transform="rotate(240)">
<animate attributeName="opacity" values="0.20;0.40;0.20" dur="4.3s" begin="1.6s" repeatCount="indefinite"/>
</polygon>
<!-- Indigo ray (300°) -->
<polygon points="0,0 2,35 -2,35" fill="#6366F1" transform="rotate(300)">
<animate attributeName="opacity" values="0.20;0.40;0.20" dur="4.5s" begin="2s" repeatCount="indefinite"/>
</polygon>
</g>
<!-- Primary set of 12 thin white rays radiating outward, alternating lengths - REFINED SOFT ELEGANCE -->
<g opacity="0.3">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="75s" repeatCount="indefinite"/>
<!-- Ray 0: long (0°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.6" stroke-linecap="round" opacity="0">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="4s" begin="0s" repeatCount="indefinite"/>
</line>
<!-- Ray 1: short (30°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.4" stroke-linecap="round" opacity="0" transform="rotate(30)">
<animate attributeName="opacity" values="0;0.20;0;0.10;0" dur="3.5s" begin="0.3s" repeatCount="indefinite"/>
</line>
<!-- Ray 2: long (60°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.6" stroke-linecap="round" opacity="0" transform="rotate(60)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="4.2s" begin="0.6s" repeatCount="indefinite"/>
</line>
<!-- Ray 3: short (90°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.4" stroke-linecap="round" opacity="0" transform="rotate(90)">
<animate attributeName="opacity" values="0;0.20;0;0.10;0" dur="3.8s" begin="0.9s" repeatCount="indefinite"/>
</line>
<!-- Ray 4: long (120°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.6" stroke-linecap="round" opacity="0" transform="rotate(120)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="4s" begin="1.2s" repeatCount="indefinite"/>
</line>
<!-- Ray 5: short (150°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.4" stroke-linecap="round" opacity="0" transform="rotate(150)">
<animate attributeName="opacity" values="0;0.20;0;0.10;0" dur="3.6s" begin="1.5s" repeatCount="indefinite"/>
</line>
<!-- Ray 6: long (180°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.6" stroke-linecap="round" opacity="0" transform="rotate(180)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="4.3s" begin="1.8s" repeatCount="indefinite"/>
</line>
<!-- Ray 7: short (210°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.4" stroke-linecap="round" opacity="0" transform="rotate(210)">
<animate attributeName="opacity" values="0;0.20;0;0.10;0" dur="3.7s" begin="2.1s" repeatCount="indefinite"/>
</line>
<!-- Ray 8: long (240°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.6" stroke-linecap="round" opacity="0" transform="rotate(240)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="4.1s" begin="2.4s" repeatCount="indefinite"/>
</line>
<!-- Ray 9: short (270°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.4" stroke-linecap="round" opacity="0" transform="rotate(270)">
<animate attributeName="opacity" values="0;0.20;0;0.10;0" dur="3.9s" begin="2.7s" repeatCount="indefinite"/>
</line>
<!-- Ray 10: long (300°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.6" stroke-linecap="round" opacity="0" transform="rotate(300)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="4s" begin="3s" repeatCount="indefinite"/>
</line>
<!-- Ray 11: short (330°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.4" stroke-linecap="round" opacity="0" transform="rotate(330)">
<animate attributeName="opacity" values="0;0.20;0;0.10;0" dur="3.8s" begin="3.3s" repeatCount="indefinite"/>
</line>
</g>
<!-- Central bright white-to-prismatic circle with heavy glow and pulsing - REFINED SLOWER PULSE -->
<circle r="12" fill="#ffffff" filter="url(#coreGlow)" opacity="0.95">
<animate attributeName="r" values="10;14;10" dur="3s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.85;1;0.85" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Inner refraction crescent (new) -->
<circle cx="-4" cy="-4" r="6" fill="#ffffff" opacity="0.2">
<animate attributeName="opacity" values="0.2;0.35;0.2" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Tiny sharp specular highlight off-center -->
<circle cx="3" cy="-3" r="1.5" fill="#ffffff" opacity="0.9" filter="url(#glow)">
<animate attributeName="opacity" values="0.6;1;0.6" dur="1.5s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Outer core edge with pulse (adjusted for starburst radius) -->
<circle r="50" fill="none" stroke="#ffffff" stroke-width="0.8" opacity="0.6">
<animate attributeName="opacity" values="0.4;0.8;0.4" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Orbiting light motes -->
<g filter="url(#shimmer)">
<circle r="2" fill="#A78BFA" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#3B82F6" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 0 -0.1,-140"/>
<animate attributeName="opacity" values="0;0;0.8;0;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#10B981" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-165 A165,165 0 1 1 -0.1,-165"/>
<animate attributeName="opacity" values="0;0.7;0;0.5;0" dur="6s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#F59E0B" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.9;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#EC4899" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-150 A150,150 0 1 1 -0.1,-150"/>
<animate attributeName="opacity" values="0;0.8;0;0;0.6;0" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#fff" opacity="0">
<animateMotion dur="5s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 0 -0.1,-120"/>
<animate attributeName="opacity" values="0;1;0;0;0" dur="5s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,308 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Blade Gradients: Amethyst (0°) -->
<linearGradient id="g0_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#A78BFA;#8B5CF6" dur="5s" repeatCount="indefinite"/></stop>
</linearGradient>
<linearGradient id="g0_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#8B5CF6"/><stop offset="100%" stop-color="#5B21B6"/>
</linearGradient>
<!-- Blade Gradients: Sapphire (60°) -->
<linearGradient id="g1_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="5.5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#3B82F6"/>
</linearGradient>
<linearGradient id="g1_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3B82F6"/><stop offset="100%" stop-color="#1D4ED8"/>
</linearGradient>
<!-- Blade Gradients: Emerald (120°) -->
<linearGradient id="g2_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#10B981"/>
</linearGradient>
<linearGradient id="g2_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#10B981"/><stop offset="100%" stop-color="#047857"/>
</linearGradient>
<!-- Blade Gradients: Amber (180°) -->
<linearGradient id="g3_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#F59E0B"/>
</linearGradient>
<linearGradient id="g3_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F59E0B"/><stop offset="100%" stop-color="#B45309"/>
</linearGradient>
<!-- Blade Gradients: Rose (240°) -->
<linearGradient id="g4_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F9A8D4"><animate attributeName="stop-color" values="#F9A8D4;#FBCFE8;#F9A8D4" dur="5.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"/>
</linearGradient>
<linearGradient id="g4_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#EC4899"/><stop offset="100%" stop-color="#BE185D"/>
</linearGradient>
<!-- Blade Gradients: Indigo (300°) -->
<linearGradient id="g5_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A5B4FC"><animate attributeName="stop-color" values="#A5B4FC;#C7D2FE;#A5B4FC" dur="5.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#6366F1"/>
</linearGradient>
<linearGradient id="g5_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6366F1"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<!-- Cycling Prismatic Core Gradient for halo -->
<radialGradient id="prismatic" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#FFFFFF"><animate attributeName="stop-color" values="#FFFFFF;#E0D5FF;#FFFFFF" dur="4s" repeatCount="indefinite"/></stop>
<stop offset="40%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
</radialGradient>
<!-- Outer aura for transparent bg -->
<radialGradient id="outerAura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#8B5CF6" stop-opacity="0.08"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="10s" repeatCount="indefinite"/></stop>
<stop offset="70%" stop-color="#8B5CF6" stop-opacity="0.03"/>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<!-- Filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="coreGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="12" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="shimmer" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="wideGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="18" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Subtle breathing aura (replaces dark bg) -->
<circle cx="200" cy="200" r="190" fill="url(#outerAura)">
<animate attributeName="r" values="175;195;175" dur="6s" repeatCount="indefinite"/>
</circle>
<!-- The Iris — slow continuous rotation -->
<g transform="translate(200, 200)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="90s" repeatCount="indefinite" additive="sum"/>
<!-- Amethyst Blade (0°) with shimmer -->
<g transform="rotate(0)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g0_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g0_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.90;1;0.90" dur="4s" repeatCount="indefinite"/>
</path>
<!-- Edge shimmer -->
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0s" repeatCount="indefinite"/>
</line>
</g>
<!-- Sapphire Blade (60°) -->
<g transform="rotate(60)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g1_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g1_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0.83s" repeatCount="indefinite"/>
</line>
</g>
<!-- Emerald Blade (120°) -->
<g transform="rotate(120)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g2_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g2_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="1.66s" repeatCount="indefinite"/>
</line>
</g>
<!-- Amber Blade (180°) -->
<g transform="rotate(180)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g3_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g3_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Rose Blade (240°) -->
<g transform="rotate(240)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g4_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g4_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="3.33s" repeatCount="indefinite"/>
</line>
</g>
<!-- Indigo Blade (300°) -->
<g transform="rotate(300)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g5_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.3s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g5_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="4.16s" repeatCount="indefinite"/>
</line>
</g>
<!-- THE KALEIDOSCOPE CORE - STARBURST VARIANT (REFINED S3) -->
<g filter="url(#coreGlow)">
<!-- Soft radial gradient halo with prismatic color cycling -->
<circle r="45" fill="url(#prismatic)" opacity="0.4">
<animate attributeName="opacity" values="0.3;0.5;0.3" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Secondary set of 6 thicker colored rays (per brand colors) rotating slowly -->
<g opacity="0.35">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="120s" repeatCount="indefinite"/>
<!-- Violet ray -->
<polygon points="0,0 2,35 -2,35" fill="#A78BFA">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4s" repeatCount="indefinite"/>
</polygon>
<!-- Blue ray (60°) -->
<polygon points="0,0 2,35 -2,35" fill="#3B82F6" transform="rotate(60)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4.2s" begin="0.4s" repeatCount="indefinite"/>
</polygon>
<!-- Green ray (120°) -->
<polygon points="0,0 2,35 -2,35" fill="#10B981" transform="rotate(120)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4.4s" begin="0.8s" repeatCount="indefinite"/>
</polygon>
<!-- Amber ray (180°) -->
<polygon points="0,0 2,35 -2,35" fill="#F59E0B" transform="rotate(180)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4s" begin="1.2s" repeatCount="indefinite"/>
</polygon>
<!-- Pink ray (240°) -->
<polygon points="0,0 2,35 -2,35" fill="#EC4899" transform="rotate(240)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4.3s" begin="1.6s" repeatCount="indefinite"/>
</polygon>
<!-- Indigo ray (300°) -->
<polygon points="0,0 2,35 -2,35" fill="#6366F1" transform="rotate(300)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4.5s" begin="2s" repeatCount="indefinite"/>
</polygon>
</g>
<!-- Primary set of 12 thin white rays radiating outward, alternating lengths -->
<g opacity="0.3">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="60s" repeatCount="indefinite"/>
<!-- Ray 0: long (0°) - increased peak opacity from 0.35 to 0.40 -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0">
<animate attributeName="opacity" values="0;0.40;0;0.2;0" dur="4s" begin="0s" repeatCount="indefinite"/>
</line>
<!-- Ray 1: short (30°) - increased peak opacity from 0.25 to 0.30 -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(30)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="3.5s" begin="0.3s" repeatCount="indefinite"/>
</line>
<!-- Ray 2: long (60°) - increased peak opacity from 0.35 to 0.40 -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(60)">
<animate attributeName="opacity" values="0;0.40;0;0.2;0" dur="4.2s" begin="0.6s" repeatCount="indefinite"/>
</line>
<!-- Ray 3: short (90°) - increased peak opacity from 0.25 to 0.30 -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(90)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="3.8s" begin="0.9s" repeatCount="indefinite"/>
</line>
<!-- Ray 4: long (120°) - increased peak opacity from 0.35 to 0.40 -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(120)">
<animate attributeName="opacity" values="0;0.40;0;0.2;0" dur="4s" begin="1.2s" repeatCount="indefinite"/>
</line>
<!-- Ray 5: short (150°) - increased peak opacity from 0.25 to 0.30 -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(150)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="3.6s" begin="1.5s" repeatCount="indefinite"/>
</line>
<!-- Ray 6: long (180°) - increased peak opacity from 0.35 to 0.40 -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(180)">
<animate attributeName="opacity" values="0;0.40;0;0.2;0" dur="4.3s" begin="1.8s" repeatCount="indefinite"/>
</line>
<!-- Ray 7: short (210°) - increased peak opacity from 0.25 to 0.30 -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(210)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="3.7s" begin="2.1s" repeatCount="indefinite"/>
</line>
<!-- Ray 8: long (240°) - increased peak opacity from 0.35 to 0.40 -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(240)">
<animate attributeName="opacity" values="0;0.40;0;0.2;0" dur="4.1s" begin="2.4s" repeatCount="indefinite"/>
</line>
<!-- Ray 9: short (270°) - increased peak opacity from 0.25 to 0.30 -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(270)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="3.9s" begin="2.7s" repeatCount="indefinite"/>
</line>
<!-- Ray 10: long (300°) - increased peak opacity from 0.35 to 0.40 -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(300)">
<animate attributeName="opacity" values="0;0.40;0;0.2;0" dur="4s" begin="3s" repeatCount="indefinite"/>
</line>
<!-- Ray 11: short (330°) - increased peak opacity from 0.25 to 0.30 -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(330)">
<animate attributeName="opacity" values="0;0.30;0;0.15;0" dur="3.8s" begin="3.3s" repeatCount="indefinite"/>
</line>
</g>
<!-- Very faint hexagonal wireframe - subtle callback to hex without dominating -->
<polygon points="30,0 15,25.98 -15,25.98 -30,0 -15,-25.98 15,-25.98" fill="none" stroke="#fff" stroke-width="0.3" opacity="0.1">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="45s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.05;0.15;0.05" dur="6s" repeatCount="indefinite"/>
</polygon>
<!-- Diamond center instead of circle: rotated square with pulsing animations -->
<rect x="-10" y="-10" width="20" height="20" rx="2" fill="#ffffff" filter="url(#coreGlow)" opacity="0.95" transform="rotate(45)">
<animate attributeName="opacity" values="0.85;1;0.85" dur="2.5s" repeatCount="indefinite"/>
<animateTransform attributeName="transform" type="scale" values="0.9;1.1;0.9" dur="2.5s" repeatCount="indefinite" additive="sum"/>
</rect>
<!-- Primary specular highlight: increased radius from 1.5 to 2, peak opacity 1 to 0.95 -->
<circle cx="3" cy="-3" r="2" fill="#ffffff" opacity="0.9" filter="url(#glow)">
<animate attributeName="opacity" values="0.6;0.95;0.6" dur="1.5s" repeatCount="indefinite"/>
</circle>
<!-- Secondary tiny highlight for gem-like effect: pulsing 0.4-0.7 dur 2s -->
<circle cx="-2" cy="2" r="1" fill="#ffffff" opacity="0.4" filter="url(#glow)">
<animate attributeName="opacity" values="0.4;0.7;0.4" dur="2s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Orbiting light motes -->
<g filter="url(#shimmer)">
<circle r="2" fill="#A78BFA" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#3B82F6" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 0 -0.1,-140"/>
<animate attributeName="opacity" values="0;0;0.8;0;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#10B981" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-165 A165,165 0 1 1 -0.1,-165"/>
<animate attributeName="opacity" values="0;0.7;0;0.5;0" dur="6s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#F59E0B" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.9;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#EC4899" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-150 A150,150 0 1 1 -0.1,-150"/>
<animate attributeName="opacity" values="0;0.8;0;0;0.6;0" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#fff" opacity="0">
<animateMotion dur="5s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 0 -0.1,-120"/>
<animate attributeName="opacity" values="0;1;0;0;0" dur="5s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,302 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<defs>
<!-- Blade Gradients: Amethyst (0°) -->
<linearGradient id="g0_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A78BFA"><animate attributeName="stop-color" values="#A78BFA;#C4B5FD;#A78BFA" dur="5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#A78BFA;#8B5CF6" dur="5s" repeatCount="indefinite"/></stop>
</linearGradient>
<linearGradient id="g0_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#8B5CF6"/><stop offset="100%" stop-color="#5B21B6"/>
</linearGradient>
<!-- Blade Gradients: Sapphire (60°) -->
<linearGradient id="g1_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="5.5s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#3B82F6"/>
</linearGradient>
<linearGradient id="g1_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#3B82F6"/><stop offset="100%" stop-color="#1D4ED8"/>
</linearGradient>
<!-- Blade Gradients: Emerald (120°) -->
<linearGradient id="g2_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="6s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#10B981"/>
</linearGradient>
<linearGradient id="g2_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#10B981"/><stop offset="100%" stop-color="#047857"/>
</linearGradient>
<!-- Blade Gradients: Amber (180°) -->
<linearGradient id="g3_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#FCD34D"><animate attributeName="stop-color" values="#FCD34D;#FDE68A;#FCD34D" dur="4.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#F59E0B"/>
</linearGradient>
<linearGradient id="g3_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F59E0B"/><stop offset="100%" stop-color="#B45309"/>
</linearGradient>
<!-- Blade Gradients: Rose (240°) -->
<linearGradient id="g4_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#F9A8D4"><animate attributeName="stop-color" values="#F9A8D4;#FBCFE8;#F9A8D4" dur="5.2s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#EC4899"/>
</linearGradient>
<linearGradient id="g4_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#EC4899"/><stop offset="100%" stop-color="#BE185D"/>
</linearGradient>
<!-- Blade Gradients: Indigo (300°) -->
<linearGradient id="g5_F1" x1="20" y1="17" x2="-30" y2="160" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#A5B4FC"><animate attributeName="stop-color" values="#A5B4FC;#C7D2FE;#A5B4FC" dur="5.8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#6366F1"/>
</linearGradient>
<linearGradient id="g5_F2" x1="40" y1="0" x2="140" y2="60" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#6366F1"/><stop offset="100%" stop-color="#4338CA"/>
</linearGradient>
<!-- Cycling Prismatic Core Gradient for halo -->
<radialGradient id="prismatic" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#FFFFFF"><animate attributeName="stop-color" values="#FFFFFF;#E0D5FF;#FFFFFF" dur="4s" repeatCount="indefinite"/></stop>
<stop offset="40%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="8s" repeatCount="indefinite"/></stop>
</radialGradient>
<!-- Outer aura for transparent bg -->
<radialGradient id="outerAura" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#8B5CF6" stop-opacity="0.08"><animate attributeName="stop-color" values="#8B5CF6;#3B82F6;#10B981;#F59E0B;#EC4899;#8B5CF6" dur="10s" repeatCount="indefinite"/></stop>
<stop offset="70%" stop-color="#8B5CF6" stop-opacity="0.03"/>
<stop offset="100%" stop-color="#8B5CF6" stop-opacity="0"/>
</radialGradient>
<!-- Filters -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="coreGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="12" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="shimmer" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="wideGlow" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="18" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- Subtle breathing aura (replaces dark bg) -->
<circle cx="200" cy="200" r="190" fill="url(#outerAura)">
<animate attributeName="r" values="175;195;175" dur="6s" repeatCount="indefinite"/>
</circle>
<!-- The Iris — slow continuous rotation -->
<g transform="translate(200, 200)">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="90s" repeatCount="indefinite" additive="sum"/>
<!-- Amethyst Blade (0°) with shimmer -->
<g transform="rotate(0)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g0_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g0_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.90;1;0.90" dur="4s" repeatCount="indefinite"/>
</path>
<!-- Edge shimmer -->
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0s" repeatCount="indefinite"/>
</line>
</g>
<!-- Sapphire Blade (60°) -->
<g transform="rotate(60)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g1_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g1_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="0.83s" repeatCount="indefinite"/>
</line>
</g>
<!-- Emerald Blade (120°) -->
<g transform="rotate(120)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g2_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="5s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g2_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="1.66s" repeatCount="indefinite"/>
</line>
</g>
<!-- Amber Blade (180°) -->
<g transform="rotate(180)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g3_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.2s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g3_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="2.5s" repeatCount="indefinite"/>
</line>
</g>
<!-- Rose Blade (240°) -->
<g transform="rotate(240)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g4_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.8s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g4_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="3.33s" repeatCount="indefinite"/>
</line>
</g>
<!-- Indigo Blade (300°) -->
<g transform="rotate(300)" style="mix-blend-mode: screen;">
<path d="M 40,0 L -30,160 L 140,60 Z" fill="url(#g5_F2)" fill-opacity="0.80" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.4" stroke-linejoin="round">
<animate attributeName="fill-opacity" values="0.75;0.90;0.75" dur="4.3s" repeatCount="indefinite"/>
</path>
<path d="M 40,0 L 20,34.641 L -30,160 Z" fill="url(#g5_F1)" fill-opacity="0.95" stroke="#ffffff" stroke-width="0.5" stroke-opacity="0.6" stroke-linejoin="round"/>
<line x1="40" y1="0" x2="-30" y2="160" stroke="#fff" stroke-width="1" opacity="0">
<animate attributeName="opacity" values="0;0.6;0" dur="5s" begin="4.16s" repeatCount="indefinite"/>
</line>
</g>
<!-- THE KALEIDOSCOPE CORE - STARBURST VARIANT -->
<g filter="url(#coreGlow)">
<!-- Soft radial gradient halo with prismatic color cycling -->
<circle r="45" fill="url(#prismatic)" opacity="0.4">
<animate attributeName="opacity" values="0.3;0.5;0.3" dur="4s" repeatCount="indefinite"/>
</circle>
<!-- Secondary set of 6 thicker colored rays (per brand colors) rotating slowly -->
<g opacity="0.35">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="120s" repeatCount="indefinite"/>
<!-- Violet ray -->
<polygon points="0,0 2,35 -2,35" fill="#A78BFA">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4s" repeatCount="indefinite"/>
</polygon>
<!-- Blue ray (60°) -->
<polygon points="0,0 2,35 -2,35" fill="#3B82F6" transform="rotate(60)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4.2s" begin="0.4s" repeatCount="indefinite"/>
</polygon>
<!-- Green ray (120°) -->
<polygon points="0,0 2,35 -2,35" fill="#10B981" transform="rotate(120)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4.4s" begin="0.8s" repeatCount="indefinite"/>
</polygon>
<!-- Amber ray (180°) -->
<polygon points="0,0 2,35 -2,35" fill="#F59E0B" transform="rotate(180)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4s" begin="1.2s" repeatCount="indefinite"/>
</polygon>
<!-- Pink ray (240°) -->
<polygon points="0,0 2,35 -2,35" fill="#EC4899" transform="rotate(240)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4.3s" begin="1.6s" repeatCount="indefinite"/>
</polygon>
<!-- Indigo ray (300°) -->
<polygon points="0,0 2,35 -2,35" fill="#6366F1" transform="rotate(300)">
<animate attributeName="opacity" values="0.25;0.45;0.25" dur="4.5s" begin="2s" repeatCount="indefinite"/>
</polygon>
</g>
<!-- Primary set of 12 thin white rays radiating outward, alternating lengths -->
<g opacity="0.3">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="60s" repeatCount="indefinite"/>
<!-- Ray 0: long (0°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4s" begin="0s" repeatCount="indefinite"/>
</line>
<!-- Ray 1: short (30°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(30)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.5s" begin="0.3s" repeatCount="indefinite"/>
</line>
<!-- Ray 2: long (60°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(60)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4.2s" begin="0.6s" repeatCount="indefinite"/>
</line>
<!-- Ray 3: short (90°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(90)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.8s" begin="0.9s" repeatCount="indefinite"/>
</line>
<!-- Ray 4: long (120°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(120)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4s" begin="1.2s" repeatCount="indefinite"/>
</line>
<!-- Ray 5: short (150°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(150)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.6s" begin="1.5s" repeatCount="indefinite"/>
</line>
<!-- Ray 6: long (180°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(180)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4.3s" begin="1.8s" repeatCount="indefinite"/>
</line>
<!-- Ray 7: short (210°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(210)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.7s" begin="2.1s" repeatCount="indefinite"/>
</line>
<!-- Ray 8: long (240°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(240)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4.1s" begin="2.4s" repeatCount="indefinite"/>
</line>
<!-- Ray 9: short (270°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(270)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.9s" begin="2.7s" repeatCount="indefinite"/>
</line>
<!-- Ray 10: long (300°) -->
<line x1="0" y1="0" x2="0" y2="50" stroke="#ffffff" stroke-width="0.8" opacity="0" transform="rotate(300)">
<animate attributeName="opacity" values="0;0.35;0;0.2;0" dur="4s" begin="3s" repeatCount="indefinite"/>
</line>
<!-- Ray 11: short (330°) -->
<line x1="0" y1="0" x2="25" y2="43.301" stroke="#ffffff" stroke-width="0.6" opacity="0" transform="rotate(330)">
<animate attributeName="opacity" values="0;0.25;0;0.15;0" dur="3.8s" begin="3.3s" repeatCount="indefinite"/>
</line>
</g>
<!-- Central bright white-to-prismatic circle with heavy glow and pulsing -->
<circle r="12" fill="#ffffff" filter="url(#coreGlow)" opacity="0.95">
<animate attributeName="r" values="10;14;10" dur="2.5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.85;1;0.85" dur="2.5s" repeatCount="indefinite"/>
</circle>
<!-- Tiny sharp specular highlight off-center -->
<circle cx="3" cy="-3" r="1.5" fill="#ffffff" opacity="0.9" filter="url(#glow)">
<animate attributeName="opacity" values="0.6;1;0.6" dur="1.5s" repeatCount="indefinite"/>
</circle>
</g>
<!-- Outer core edge with pulse (adjusted for starburst radius) -->
<circle r="50" fill="none" stroke="#ffffff" stroke-width="0.8" opacity="0.6">
<animate attributeName="opacity" values="0.4;0.8;0.4" dur="3s" repeatCount="indefinite"/>
</circle>
<!-- Orbiting light motes -->
<g filter="url(#shimmer)">
<circle r="2" fill="#A78BFA" opacity="0">
<animateMotion dur="7s" repeatCount="indefinite" path="M0,-155 A155,155 0 1 1 -0.1,-155"/>
<animate attributeName="opacity" values="0;0.9;0;0;0" dur="7s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#3B82F6" opacity="0">
<animateMotion dur="9s" repeatCount="indefinite" path="M0,-140 A140,140 0 1 0 -0.1,-140"/>
<animate attributeName="opacity" values="0;0;0.8;0;0" dur="9s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#10B981" opacity="0">
<animateMotion dur="6s" repeatCount="indefinite" path="M0,-165 A165,165 0 1 1 -0.1,-165"/>
<animate attributeName="opacity" values="0;0.7;0;0.5;0" dur="6s" repeatCount="indefinite"/>
</circle>
<circle r="2" fill="#F59E0B" opacity="0">
<animateMotion dur="11s" repeatCount="indefinite" path="M0,-130 A130,130 0 1 0 -0.1,-130"/>
<animate attributeName="opacity" values="0;0;0;0.9;0" dur="11s" repeatCount="indefinite"/>
</circle>
<circle r="1" fill="#EC4899" opacity="0">
<animateMotion dur="8s" repeatCount="indefinite" path="M0,-150 A150,150 0 1 1 -0.1,-150"/>
<animate attributeName="opacity" values="0;0.8;0;0;0.6;0" dur="8s" repeatCount="indefinite"/>
</circle>
<circle r="1.5" fill="#fff" opacity="0">
<animateMotion dur="5s" repeatCount="indefinite" path="M0,-120 A120,120 0 1 0 -0.1,-120"/>
<animate attributeName="opacity" values="0;1;0;0;0" dur="5s" repeatCount="indefinite"/>
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB