import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react'; // ============================================================================= // THE WINNER'S CODE — COMPANION APP · v2 // Architecture-grade encoding tool for the permanent shift from losing mind to // winner's identity. Companion to The Winner's Code self-paced course. // // v2 additions: // · Claude-powered Reframe Engine — Sascha's voice in the operator's pocket // · Multi-horizon Compound view — daily, weekly, quarterly, decade // · Pattern Insights — the operator's own data teaches them // · Audio recording — Identity Statement read in operator's own voice // · Decade Architecture timeline visualization // · Honest session tracking via Visibility API // · Quarter-aware Today rail with drift detection // · Export to printable HTML for 1:1 sessions // · PWA meta + notifications + haptic feedback // // Works for operators with or without ADHD. // ============================================================================= const NAVY = '#0A0F1E'; const NAVY_2 = '#0E1428'; const NAVY_3 = '#131A33'; const NAVY_4 = '#1A2240'; const GOLD = '#C9A84C'; const GOLD_DEEP = '#B89438'; const GOLD_BRIGHT = '#E5C77A'; const IVORY = '#F5F1E8'; const IVORY_DIM = '#E8E0CC'; const GREY_1 = '#D4CDB8'; const GREY_2 = '#8B8675'; const GREY_3 = '#5C5848'; const RED_SOFT = '#D88A8A'; const LINE = 'rgba(201, 168, 76, 0.18)'; const LINE_BRIGHT = 'rgba(201, 168, 76, 0.4)'; const LINE_FAINT = 'rgba(201, 168, 76, 0.08)'; const SERIF = "'Cormorant Garamond', 'Garamond', 'Times New Roman', serif"; const DISPLAY = "'Syne', 'Helvetica Neue', sans-serif"; // ============================================================================= // STORAGE // ============================================================================= const storage = { async get(key, fallback = null) { try { const result = await window.storage.get(key); if (!result) return fallback; try { return JSON.parse(result.value); } catch { return result.value; } } catch { return fallback; } }, async set(key, value) { try { const v = typeof value === 'string' ? value : JSON.stringify(value); await window.storage.set(key, v); return true; } catch (e) { console.error('Storage set failed:', e); return false; } }, async list(prefix) { try { return (await window.storage.list(prefix))?.keys || []; } catch { return []; } }, }; // ============================================================================= // UTILITIES // ============================================================================= const todayKey = (offset = 0) => { const d = new Date(); d.setDate(d.getDate() + offset); return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`; }; const fmtDate = (iso, opts = {}) => { const d = new Date(iso); return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: opts.year ? 'numeric' : undefined }); }; const fmtTime = (iso) => { const d = new Date(iso); return d.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' }); }; const fmtDuration = (ms) => { const m = Math.floor(ms / 60000); const h = Math.floor(m / 60); if (h > 24) return `${Math.floor(h / 24)}d`; if (h > 0) return `${h}h ${m % 60}m`; return `${m}m`; }; const startOfQuarter = (d = new Date()) => { const q = Math.floor(d.getMonth() / 3); return new Date(d.getFullYear(), q * 3, 1); }; const quarterLabel = (d = new Date()) => { const q = Math.floor(d.getMonth() / 3) + 1; return `Q${q} · ${d.getFullYear()}`; }; const haptic = (pattern = 10) => { try { if (navigator.vibrate) navigator.vibrate(pattern); } catch {} }; // ============================================================================= // CLAUDE API — the architectural intelligence // ============================================================================= const SASCHA_SYSTEM_PROMPT = `You are the architectural intelligence of The Winner's Code, the self-paced winning mindset course authored by Sascha Gorokhoff. You speak in Sascha's voice — sovereign, sophisticated, behaviorally precise, architecturally rigorous. Never motivational. Never therapeutic. Never moralizing. Architectural only. THE FRAMEWORK: LOSER → CONTENDER → CHAMPION → UNDEFEATED. What each stage installs: - LOSER: honest excavation of the architecture of defeat the operator inherited; identity inventory; the permanent, deliberate separation from what was. - CONTENDER: the winner's identity installed; standards reset at executive register; the engineered environment of champions. - CHAMPION: daily discipline; performance under pressure; the compound mind that turns days into decades. - UNDEFEATED: inner sovereignty; the long game; the permanent code held alive across years. CORE DISTINCTIONS: - Architecture is structural and replaceable. Mood is a state. The work is architectural. - Improvement leaves the architecture in place. Separation replaces it. - A preference is what one likes. A goal is what one moves toward. A standard is what one operates — unconditionally, continuously. - Identity is intermittent attention. Environment is relentless input. Architecture is decided by the relentless, not the intermittent. - Willpower decides every morning. Discipline decided once. - Pressure does not create performance. Pressure measures architecture. - Breakthroughs are seductive but rarely durable. Compounding is undramatic but architecturally devastating. - The losing mind is architecture, not feeling. ADHD is terrain, not architecture. VOICE RULES (non-negotiable): - Use: architecture, operator, seated court, sovereign, compounding, deposit, terrain, install, engineered, register, cut. - Refuse: "you got this," "amazing," "great job," "I believe in you," "you are enough," "you deserve." - No exclamation marks. No emojis. No therapeutic register. No self-help register. - Pull-quote-grade prose. Each sentence earns its weight. - Address the operator with respect, not with cheer. The Swiss aristocratic register: measured, precise, refined, quietly sovereign. THE TASK: The operator has captured a losing-mind thought. You produce a four-part architectural analysis. Return ONLY a valid JSON object — no other text, no markdown code blocks, no preamble. Exactly these four keys: { "identity_firing": "[ONE precise sentence naming whose voice this is — the critic, the wounded operator, the inherited fear, the conditioned identity, the family voice never refused, etc. Specific. Architectural.]", "architecture_built": "[TWO TO THREE sentences naming what architecture this thought, repeated, has built across years — the standards it has set, the limits it has drawn, the trajectory it has authored. Diagnostic. Honest.]", "sovereign_reframe": "[THREE TO FIVE sentences. The reframe from the seated court. Not denial. Not platitude. The architecturally honest truth, in the operator's voice, addressed to the operator. Pull-quote-grade prose. Begin with what is actually true beneath the storm. End with what the architecture authorizes the operator to operate from now.]", "deposit_note": "[ONE short sentence naming what depositing this reframe to the ledger represents architecturally.]" } Return only the JSON. No other text whatsoever.`; const PATTERN_SYSTEM_PROMPT = `You are the pattern intelligence of The Winner's Code companion app. You analyze the operator's own data — reframes deposited, storms survived, daily code execution, hyperfocus sessions — and surface architectural insight in Sascha Gorokhoff's voice. Voice: sovereign, architectural, precise. No motivation. No cheer. No moralizing. Pull-quote-grade prose. Refer to "the operator," "the architecture," "the data," "the pattern." The operator is reading the insight in their own app. Speak with respect, not with reassurance. Honor what the data shows, including what is not yet operating. Return ONLY valid JSON, no markdown, no preamble. Exactly this structure: { "headline": "[ONE sentence stating the architectural pattern the data reveals. Direct.]", "observation": "[TWO TO FOUR sentences elaborating the pattern with reference to specific numbers from the data. Architectural, not statistical. What the data means architecturally.]", "calibration": "[ONE TO TWO sentences naming what the architecture would calibrate next, given the pattern. Suggestion, not prescription.]" }`; async function callClaude(prompt, systemPrompt = SASCHA_SYSTEM_PROMPT, maxTokens = 1000) { const response = await fetch("https://api.anthropic.com/v1/messages", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model: "claude-sonnet-4-20250514", max_tokens: maxTokens, system: systemPrompt, messages: [{ role: "user", content: prompt }], }) }); if (!response.ok) { const errText = await response.text(); throw new Error(`API ${response.status}: ${errText.slice(0, 200)}`); } const data = await response.json(); const text = data.content?.filter(c => c.type === 'text').map(c => c.text).join('') || ''; return text; } function parseJSON(text) { let cleaned = text.trim().replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/i, ''); try { return JSON.parse(cleaned); } catch {} const firstBrace = cleaned.indexOf('{'); const lastBrace = cleaned.lastIndexOf('}'); if (firstBrace >= 0 && lastBrace > firstBrace) { try { return JSON.parse(cleaned.slice(firstBrace, lastBrace + 1)); } catch {} } return null; } // ============================================================================= // UI PRIMITIVES // ============================================================================= const Eyebrow = ({ children, color = GOLD, style = {} }) => (
{children}
); const Prose = ({ children, style = {} }) => ({children}
); const Btn = ({ children, onClick, kind = 'primary', size = 'md', disabled = false, full = false, style = {} }) => { const sizes = { sm: { fontSize: 10, padding: '9px 18px' }, md: { fontSize: 11, padding: '13px 26px' }, lg: { fontSize: 12, padding: '17px 36px' }, }; const kinds = { primary: { background: GOLD, color: NAVY, borderColor: GOLD }, ghost: { background: 'transparent', color: GOLD, borderColor: LINE_BRIGHT }, quiet: { background: 'transparent', color: GREY_1, borderColor: LINE }, danger: { background: 'transparent', color: RED_SOFT, borderColor: 'rgba(216, 138, 138, 0.3)' }, }; return ( ); }; const Card = ({ children, padding = 28, style = {}, onClick = null }) => (