import { For, createEffect, createSignal, onCleanup, onMount, type JSX } from "solid-js"; import { IslandPill, AgentDotGrid, CALM, WARM, ACCENT, CRITICAL, ModuleCard, FakeCursor } from "./IslandMock"; import { Campfire, type CampfireState } from "./Campfire"; import { ApprovalCardMock, SessionRowMock, CLAUDE, CODEX } from "./ModuleMocks"; import { useDemoLoop } from "./useDemoLoop"; import { TerminalReplyDemo, MixerDemo, CaptureDemo, FloatingActionsDemo } from "./MoreDemos"; /** * Detailed feature breakdowns: alternating copy + live-demo sections. * Each demo stages the real interaction loop: attention flares, approval * resolves, fans throttle, the charge ceiling holds, meetings surface, * the camera wakes. Newer demos live in * MoreDemos.tsx; app-anatomy pieces in ModuleMocks.tsx. */ /* Scroll-triggered reveal: adds `in` once the element crosses 25%. */ function useReveal() { const [el, setEl] = createSignal(); onMount(() => { const node = el(); if (!node) return; const observer = new IntersectionObserver( (entries) => { for (const entry of entries) { if (entry.isIntersecting) { node.classList.add("in"); observer.disconnect(); } } }, { threshold: 0.25 } ); observer.observe(node); onCleanup(() => observer.disconnect()); }); return [setEl, el] as const; } function BreakdownSection(props: { kicker: string; title: string; body: string; bullets: string[]; reversed?: boolean; children: JSX.Element; }) { const [ref] = useReveal(); return (

{props.kicker}

{props.title}

{props.body}

    {(bullet) => (
  • {bullet}
  • )}
{props.children}
); } /* ── Demo 1: the fleet loop — attention flares, then resolves ─────── */ function FleetDemo() { const [phase, setPhase] = createSignal<"watch" | "flare" | "resolve">( "watch" ); onMount(() => { const timers: ReturnType[] = []; const loop = () => { setPhase("watch"); timers.push(setTimeout(() => setPhase("flare"), 3200)); timers.push(setTimeout(() => setPhase("resolve"), 6400)); }; loop(); const interval = setInterval(loop, 9600); onCleanup(() => { clearInterval(interval); timers.forEach(clearTimeout); }); }); const states = () => { switch (phase()) { case "watch": return ["running", "running", "ready", "running", "idle"] as const; case "flare": return ["running", "attention", "ready", "running", "idle"] as const; case "resolve": return ["running", "ready", "ready", "running", "idle"] as const; } }; return (
} />

{phase() === "flare" ? "Codex needs your input" : phase() === "resolve" ? "Answer delivered — agents back to work" : "Fleet running calmly"}

{phase() === "flare" ? "question · in the island now" : "\u00a0"}

); } /* ── Demo 2: an approval surfaces the island; Allow resumes the run ── */ function ApprovalDemo() { const [phase, setPhase] = createSignal<"calm" | "ask" | "press" | "resumed">("calm"); useDemoLoop(10400, [ [0, () => setPhase("calm")], [1400, () => setPhase("ask")], [4600, () => setPhase("press")], [4950, () => setPhase("resumed")], [8800, () => setPhase("calm")] ]); const asking = () => phase() === "ask" || phase() === "press"; const open = () => phase() !== "calm"; return (
} /> {/* the island opens: approval pinned above the session rows */}
); } /* ── Demo 3: fans throttle up under load, then back down ──────────── */ /* Spark pool: deterministic pseudo-random, count gated by fan speed. */ const sparkRand = (i: number, k: number) => { const x = Math.sin(i * 127.1 + k * 311.7) * 43758.5453; return x - Math.floor(x); }; const SPARKS = Array.from({ length: 20 }, (_, i) => ({ sx: `${Math.round(10 + sparkRand(i, 1) * 26)}px`, sy: `${Math.round(18 + sparkRand(i, 2) * 30)}px`, sd: `${(0.4 + sparkRand(i, 3) * 0.25).toFixed(2)}s`, sdel: `${(sparkRand(i, 4) * 1.2).toFixed(2)}s`, size: sparkRand(i, 5) > 0.5 ? 3 : 2 })); function FansDemo() { const [rpm, setRpm] = createSignal(1270); const [maxed, setMaxed] = createSignal(false); onMount(() => { let frame = 0; const timers: ReturnType[] = []; const ramp = (target: number, durationMs: number) => { cancelAnimationFrame(frame); const start = rpm(); const startTime = performance.now(); const step = (now: number) => { const t = Math.min((now - startTime) / durationMs, 1); setRpm(Math.round(start + (target - start) * t)); if (t < 1) frame = requestAnimationFrame(step); }; frame = requestAnimationFrame(step); }; const loop = () => { setMaxed(true); ramp(5960, 1200); timers.push( setTimeout(() => { setMaxed(false); ramp(1270, 1600); }, 5200) ); }; loop(); const interval = setInterval(loop, 10400); onCleanup(() => { clearInterval(interval); timers.forEach(clearTimeout); cancelAnimationFrame(frame); }); }); const fans = () => [ { rpm: rpm(), frac: rpm() / 6000 }, { rpm: Math.round(rpm() * 0.96), frac: (rpm() * 0.96) / 6000 } ]; const shakeIntensity = () => Math.max(0, Math.min(1, (rpm() - 2500) / (6000 - 2500))); /* 5 sparks when the shake starts, ~20 at max speed. */ const sparkCount = () => shakeIntensity() > 0 ? 5 + Math.floor(shakeIntensity() * 15) : 0; return (
{(f, i) => (
Fan {i() + 1}
{Math.round(f.rpm)} RPM
)}
{maxed() ? "MAX" : "Auto"} {maxed() ? "cooling session active" : "curve in control"}
0 ? "1" : "0", transition: "opacity 0.3s" }} > {(s) => ( )}
); } /* ── Demo 4: the charge ceiling holds, top-up overrules ───── */ function BatteryDemo() { const [level, setLevel] = createSignal(62); const [phase, setPhase] = createSignal<"charge" | "held" | "topup">("charge"); onMount(() => { let frame = 0; const timers: ReturnType[] = []; const ramp = (target: number, durationMs: number) => { cancelAnimationFrame(frame); const start = level(); const startTime = performance.now(); const tick = (now: number) => { const t = Math.min((now - startTime) / durationMs, 1); setLevel(start + (target - start) * t); if (t < 1) frame = requestAnimationFrame(tick); }; frame = requestAnimationFrame(tick); }; const loop = () => { setLevel(62); setPhase("charge"); ramp(80, 2600); timers.push(setTimeout(() => setPhase("held"), 2800)); timers.push( setTimeout(() => { setPhase("topup"); ramp(100, 2600); }, 5200) ); }; loop(); const interval = setInterval(loop, 9600); onCleanup(() => { clearInterval(interval); timers.forEach(clearTimeout); cancelAnimationFrame(frame); }); }); const pct = () => Math.round(level()); const watts = () => (phase() === "held" ? null : pct() >= 100 ? 9 : 38); const subline = () => phase() === "held" ? "charging paused — at the limit" : pct() >= 100 ? "topped up — re-arms on unplug" : phase() === "topup" ? `${watts()} W · top-up past the limit` : `${watts()} W · ${Math.max(1, Math.round((100 - pct()) * 1.5))} min to full`; return (
Battery Limit 80%
{pct()}% {subline()}
80 ? WARM : CALM, transition: "background 0.4s" }} />

Top-up mode

charge past the limit while plugged in

{phase() === "held" ? "holding — the pack stays young longer" : phase() === "topup" ? "topping up — re-arms when you unplug" : "on the way to the ceiling"}
); } /* ── Demo 5: the slot counts down, then opens the day ──────── */ const WEEK_LETTERS = ["S", "M", "T", "W", "T", "F", "S"]; const DAY_EVENTS = [ { time: "09:30–09:45", title: "Standup", loc: "Daily", meeting: true }, { time: "15:30–16:00", title: "Design review", loc: "4th floor", meeting: false } ]; function CalendarDemo() { const [mins, setMins] = createSignal(14); const [today, setToday] = createSignal(new Date()); onMount(() => { setToday(new Date()); const interval = setInterval( () => setMins((m) => (m <= 0 ? 14 : m - 1)), 900 ); onCleanup(() => clearInterval(interval)); }); const imminent = () => mins() <= 5; const dialDays = () => { const base = today(); return [-4, -3, -2, -1, 0, 1, 2, 3, 4].map((off) => { const d = new Date( base.getFullYear(), base.getMonth(), base.getDate() + off ); return { letter: WEEK_LETTERS[d.getDay()], num: d.getDate(), today: off === 0, past: off < 0, dots: (d.getDate() * 7 + d.getDay() * 3) % 4 }; }); }; return ( /* Fixed height: the day panel expands into reserved space, never shifts the page (matters most on mobile's stacked layout). */
{mins() === 0 ? "now" : `${mins()}m`}
} /> {/* the island opening onto the day panel */}
Calendar +
{(d) => (
{d.letter} {d.num} {() => ( )}
)}
{(ev) => (

{ev.time}

{ev.title}

{ev.loc &&

{ev.loc}

}
{ev.meeting && ( Open )}
)}
); } /* ── Demo 6: the lens only wakes for a click ──────────────── */ function CameraDemo() { const [phase, setPhase] = createSignal<"idle" | "press" | "live">("idle"); let videoRef: HTMLVideoElement | undefined; onMount(() => { const timers: ReturnType[] = []; const loop = () => { setPhase("idle"); timers.push(setTimeout(() => setPhase("press"), 2600)); timers.push(setTimeout(() => setPhase("live"), 3000)); }; loop(); const interval = setInterval(loop, 8800); onCleanup(() => { clearInterval(interval); timers.forEach(clearTimeout); }); }); createEffect(() => { if (phase() === "live" && videoRef) { videoRef.currentTime = 0; // play() rejects with AbortError when interrupted by pause() (the loop // resetting to "idle") or when the browser pauses background media to // save power. Swallow it — the rejection is expected, not a failure. void videoRef.play().catch(() => {}); } else { videoRef?.pause(); } }); return (
Camera FaceTime HD Camera ▾
{/* inert dashed start button */}
Start camera
{/* live preview */}

{phase() === "live" ? "live — stops the moment you leave the panel" : "inert — the lens stays dark until you click"}

); } /* ── Demo 8: campfire states ───────────────────────────────────────── */ function CampfireDemo() { const states: CampfireState[] = [ "running", "question", "ready", "idle", "error" ]; const labels = [ "fleet running", "pending question", "ready to review", "all quiet", "something failed" ]; return (
{(state, i) => (

{labels[i()]}

)}
); } export default function FeatureBreakdowns() { return (
); }