Files
nucleic/website/iphone.html
T

850 lines
47 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Nucleic for iPhone — The cockpit, in your pocket.</title>
<meta name="description" content="Your Mac's fleet of coding agents, projected to your iPhone. Watch sessions stream, answer approvals with Face ID, and send the next prompt from wherever you are. End-to-end encrypted." />
<meta property="og:title" content="Nucleic for iPhone — The cockpit, in your pocket." />
<meta property="og:description" content="Watch, approve, and steer your fleet of coding agents. From your iPhone." />
<meta name="theme-color" content="#faf7f3" />
<!-- atom mark, reused as favicon -->
<link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><g fill='none' stroke-width='7'><ellipse cx='50' cy='50' rx='17' ry='40' transform='rotate(80 50 50)' stroke='%237AA7DD'/><ellipse cx='50' cy='50' rx='17' ry='40' transform='rotate(20 50 50)' stroke='%23DF619B'/><ellipse cx='50' cy='50' rx='17' ry='40' transform='rotate(140 50 50)' stroke='%23C5826F'/></g></svg>" />
<!-- Self-hosted fonts (latin subset). The woff2 binaries live in fonts/ and are
preloaded so they download in parallel with the HTML; @font-face is inlined
(no render-blocking stylesheet) and the page never contacts Google. -->
<link rel="preload" href="fonts/space-grotesk.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="fonts/jetbrains-mono.woff2" as="font" type="font/woff2" crossorigin />
<style>
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:400 700;font-display:swap;src:url(fonts/space-grotesk.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:400 500;font-display:swap;src:url(fonts/jetbrains-mono.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
</style>
<style>
:root{
--ink:#181520; /* warm near-black */
--ink-soft:#5b5560; /* muted body text */
--ink-faint:#8b8590; /* captions */
--paper:#faf7f3; /* warm off-white */
--panel:#fffdfb;
--panel-2:#f3ede6;
--line:#e6ded4;
--line-2:#efe9e1;
--blue:#5e9bd8;
--pink:#db5f97;
--magenta:#c264ad;
--rust:#c47e69;
--green:#5fa775;
--amber:#d7a23f;
--sans:"Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
--mono:"JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
--maxw:1080px;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
margin:0;
overflow-x:clip;
font-family:var(--sans);
color:var(--ink);
background:var(--paper);
/* faint graph-paper dotting — instrument, not glow */
background-image:radial-gradient(var(--line) 1px, transparent 1px);
background-size:26px 26px;
background-position:-13px -13px;
-webkit-font-smoothing:antialiased;
line-height:1.5;
}
a{color:inherit}
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 24px}
.mono{font-family:var(--mono)}
.kicker{
font-family:var(--mono);
font-size:11.5px;letter-spacing:.16em;text-transform:uppercase;
color:var(--ink-faint);
}
/* ---------- selection ----------
Chrome that isn't prose stays unselectable; only the page's actual copy
(headlines, paragraphs, captions) is worth selecting. The iPhone mock
scopes its own user-select:none below. */
.btn,.brand,.kicker,.hero-badge,.card .no,.dotsep{
-webkit-user-select:none;user-select:none;
}
/* ---------- top bar ---------- */
header{
position:sticky;top:0;z-index:20;
backdrop-filter:saturate(1.1) blur(8px);
background:color-mix(in srgb, var(--paper) 82%, transparent);
border-bottom:1px solid var(--line-2);
}
.bar{display:flex;align-items:center;justify-content:space-between;height:62px}
.brand{display:flex;align-items:center;gap:11px;font-weight:600;letter-spacing:-.01em;font-size:17px;text-decoration:none}
.brand .mk{width:26px;height:26px;display:block}
.tag{
font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;
color:var(--ink-faint);border:1px solid var(--line);border-radius:999px;padding:3px 8px;
}
.nav{display:flex;align-items:center;gap:22px;font-size:14px;color:var(--ink-soft)}
.nav a{text-decoration:none}
.nav .lk:hover{color:var(--ink)}
.btn{
font-family:var(--sans);font-size:14px;font-weight:500;
text-decoration:none;cursor:pointer;border:0;
padding:9px 16px;border-radius:10px;
color:#fff;background:var(--ink);
transition:transform .12s ease, opacity .12s ease;
white-space:nowrap;-webkit-tap-highlight-color:transparent;
}
.btn:link,.btn:visited,.btn:hover,.btn:focus,.btn:active{color:#fff}
.btn:hover{opacity:.9;transform:translateY(-1px)}
.btn.ghost,.btn.ghost:link,.btn.ghost:visited{background:transparent;color:var(--ink);border:1px solid var(--line)}
/* TestFlight CTA — TestFlight mark + label, inline */
.btn.appstore{display:inline-flex;align-items:center;gap:8px}
.btn.appstore svg{width:16px;height:16px;flex:none;margin-top:-2px}
/* Mac link + TestFlight CTA are hidden until the hero's TestFlight button has
scrolled out of view above the viewport — until then the hero carries the
CTA and the bar stays uncluttered (mirrors index.html's top bar). */
#nav-mac,#nav-dl{opacity:0;visibility:hidden;pointer-events:none;transform:translateY(-6px);transition:opacity .2s ease, transform .2s ease, visibility .2s ease}
#nav-mac.show,#nav-dl.show{opacity:1;visibility:visible;pointer-events:auto;transform:none}
@media (max-width:720px){ .nav .lk{display:none} .brand .tag{display:none} .bar{gap:12px} }
/* ---------- hero ---------- */
.hero{padding:74px 0 48px}
.hero-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:48px;align-items:center}
.hero-grid>*{min-width:0}
h1{
font-size:clamp(34px,5.4vw,60px);line-height:1.02;letter-spacing:-.03em;
font-weight:600;margin:18px 0 0;
}
h1 .em,.em{
background:linear-gradient(100deg,var(--rust),var(--pink) 45%,var(--magenta) 70%,var(--blue));
-webkit-background-clip:text;background-clip:text;color:transparent;
}
.sub{margin:22px 0 0;font-size:18px;color:var(--ink-soft);max-width:40ch}
.cta-row{display:flex;align-items:center;gap:14px;margin-top:30px;flex-wrap:wrap}
.cta-note{font-family:var(--mono);font-size:12px;color:var(--ink-faint)}
.hero-ip{font-size:14px;color:var(--ink-soft);text-decoration:none;border-bottom:1px solid var(--line)}
.hero-ip:hover{color:var(--ink);border-bottom-color:var(--ink)}
.hero-badge{
display:inline-block;
font-size:12.5px;font-weight:500;color:var(--ink);line-height:1.3;
background:color-mix(in srgb,var(--pink) 10%, var(--panel));
border:1px solid color-mix(in srgb,var(--pink) 38%, var(--line));
border-radius:999px;padding:6px 13px;margin:0 0 6px;
}
.phone-wrap{display:flex;flex-direction:column;align-items:center;gap:16px;min-width:0}
@media (max-width:820px){
.hero{padding:48px 0 36px}
.hero-grid{grid-template-columns:1fr;gap:36px}
}
/* ---------- premise band ---------- */
.band{border-top:1px solid var(--line-2);border-bottom:1px solid var(--line-2);background:color-mix(in srgb,var(--panel) 60%, transparent)}
.band .wrap{padding:34px 24px;display:flex;gap:40px;align-items:baseline;flex-wrap:wrap}
.band h2{font-size:clamp(20px,2.6vw,27px);font-weight:500;letter-spacing:-.02em;margin:0;max-width:24ch}
.band p{margin:0;color:var(--ink-soft);font-size:15.5px;max-width:46ch}
.band .lede{color:var(--ink)}
/* ---------- features ---------- */
.features{padding:52px 0 24px}
.sechead{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;margin-bottom:30px;flex-wrap:wrap}
.sechead h2{font-size:clamp(24px,3.4vw,34px);font-weight:600;letter-spacing:-.025em;margin:8px 0 0;max-width:18ch}
.sechead p{margin:0;color:var(--ink-soft);max-width:34ch;font-size:15px}
.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line-2);border:1px solid var(--line-2);border-radius:14px;overflow:hidden}
@media (max-width:860px){.grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.grid{grid-template-columns:1fr}}
.card{background:var(--panel);padding:24px 22px 26px;position:relative;transition:background .15s ease}
.card:hover{background:var(--panel-2)}
.card .no{font-family:var(--mono);font-size:11px;color:var(--ink-faint)}
.card .accent{position:absolute;top:24px;right:22px;width:22px;height:22px}
.card h3{font-size:17px;font-weight:600;letter-spacing:-.01em;margin:16px 0 7px}
.card p{margin:0;color:var(--ink-soft);font-size:14px;line-height:1.55}
/* ---------- built like the Mac app ---------- */
.native{padding:34px 0 10px}
.native .head{max-width:52ch;margin:0 0 28px}
.native .head h2{font-size:clamp(24px,3.4vw,34px);font-weight:600;letter-spacing:-.025em;margin:8px 0 12px}
.native .head p{margin:0;color:var(--ink-soft);font-size:15.5px;max-width:50ch}
.native-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
@media (max-width:760px){.native-grid{grid-template-columns:1fr}}
.ncard{border:1px solid var(--line);border-radius:14px;background:var(--panel);padding:22px 20px}
.ncard .ic{width:24px;height:24px;display:block;margin-bottom:14px}
.ncard h3{font-size:16px;font-weight:600;letter-spacing:-.01em;margin:0 0 6px}
.ncard p{margin:0;color:var(--ink-soft);font-size:13.5px;line-height:1.55}
.native .foot-note{margin:22px 0 0;font-family:var(--mono);font-size:12px;color:var(--ink-faint);text-align:center}
/* ---------- trust line (inside the access card) ---------- */
.panel-trust{max-width:80ch;margin:22px auto 0;font-size:12.5px;color:var(--ink-soft);letter-spacing:.01em;line-height:1.6}
/* ---------- access / footer ---------- */
.access{padding:88px 0}
.access .panel{
border:1px solid var(--line);border-radius:18px;background:
radial-gradient(120% 140% at 0% 0%, color-mix(in srgb,var(--blue) 9%,transparent), transparent 42%),
radial-gradient(120% 140% at 100% 100%, color-mix(in srgb,var(--pink) 9%,transparent), transparent 42%),
var(--panel);
padding:48px 40px;text-align:center;
}
.access h2{font-size:clamp(26px,3.8vw,38px);font-weight:600;letter-spacing:-.025em;margin:10px 0 0}
.access p{color:var(--ink-soft);margin:14px auto 0;max-width:44ch;font-size:15.5px}
.access .cta-row{justify-content:center}
footer{border-top:1px solid var(--line-2);padding:30px 0 50px}
.foot{display:flex;align-items:center;justify-content:space-between;gap:18px;flex-wrap:wrap;color:var(--ink-faint);font-size:13px}
.foot .mono{font-size:12px}
.foot-end{display:flex;flex-direction:column;align-items:flex-end;gap:4px;text-align:right}
.foot-links{display:flex;gap:18px;flex-wrap:wrap}
.foot-links a{text-decoration:none;color:var(--ink-soft)}
.foot-links a:hover{color:var(--ink)}
@media (max-width:720px){
.foot{justify-content:flex-start}
.foot-end{flex-basis:100%;align-items:flex-start;text-align:left}
}
.dotsep{color:var(--line)}
/* ===== iPhone app surface (data-nuc-ios) — faithful web port of the iOS app's
Home tab (ios/NucleicRemote); scoped under .nuc-ios with its own variables.
Same block as index.html / cockpit-mobile.html — here it is the hero visual,
shown on every viewport. ================================================== */
.nuc-ios{
/* Surfaces — iOS light system colors (UX_IOS / Theme.swift CardBackground) */
--bg:#ffffff; /* systemBackground — the Home ScrollView */
--card:#f2f2f7; /* secondarySystemBackground — .card() surfaces */
--field:#ffffff; /* .roundedBorder text field fill */
--hair:rgba(0,0,0,.07); /* Color.primary.opacity(.06) card hairline */
--field-hair:rgba(0,0,0,.16);
--tabbar:rgba(249,249,249,.94);
/* Text — iOS semantic label tiers (light) */
--label:#000000; /* UIColor.label */
--label2:rgba(60,60,67,.6); /* secondaryLabel */
--label3:rgba(60,60,67,.3); /* tertiaryLabel */
--tab-off:#999a9f; /* unselected tab item */
/* Palette.swift — the mobile categorical palette (exact sRGB) */
--accent:#0a8580; /* deep teal — Palette.accent (.04,.52,.50) */
--active:#338cf2; /* blue — running (.20,.55,.95) */
--attention:#ffa626;/* amber — awaiting approval (1,.65,.15) */
--success:#4dcc73; /* green — finished/done (.30,.80,.45) */
--paused:#9e7ded; /* purple — interrupted (.62,.49,.93) */
--danger:#eb5757; /* red — error / badge (.92,.34,.34) */
--frozen:#42a3f5; /* iced streak-freeze blue (.26,.64,.96) */
--orchestra:#e6a829;/* orchestra gold (.90,.66,.16) */
/* ActivityGrid shades — Palette.activity(intensity): success.opacity(i),
empty = secondary.opacity(.15) */
--a0:#e3e3e8;
--a1:rgba(77,204,115,.4);
--a2:rgba(77,204,115,.65);
--a3:rgba(77,204,115,.82);
--a4:#4dcc73;
--mono:"JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
/* surface geometry — a borderless app card (no device frame) held to a real
iPhone screen proportion (390×844); overflow clips like a scrolled app.
Fits any viewport (max-width:100%). */
--w:360px;
font-family:-apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", system-ui, "Space Grotesk", Arial, sans-serif;
color:var(--label);
display:flex;justify-content:center;
/* illustrative chrome — keep its text unselectable */
-webkit-user-select:none;user-select:none;
}
.nuc-ios *{box-sizing:border-box}
.nuc-ios svg{display:block}
/* ---- borderless app surface (no device bezel, status bar, Dynamic Island, or
home indicator — only the app's own chrome) ------------------------------- */
.nuc-ios .ios-phone{
position:relative;
width:var(--w);max-width:100%;
aspect-ratio:390/844; /* real iPhone screen proportion */
display:flex;flex-direction:column;
background:var(--bg);
border:1px solid var(--hair);
border-radius:16px;overflow:hidden;
box-shadow:0 1px 0 rgba(255,255,255,.7) inset,
0 30px 70px -40px rgba(40,30,50,.40);
}
/* ---- Home content (no title bar — content starts at the top; scrolling locked,
the phone's fixed aspect ratio clips the overflow under the tab bar, reading
as a mid-scroll app surface) ------------------------------------------------ */
.nuc-ios .ios-content{
flex:1;min-height:0;overflow:hidden;
padding:22px 16px 120px; /* bottom room for the chip + tab bar */
display:flex;flex-direction:column;gap:22px;
}
/* greeting + streak (HomeView header HStack) */
.nuc-ios .ios-hi{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}
.nuc-ios .ios-hi h1{margin:0;font-size:27px;font-weight:700;letter-spacing:-.02em;line-height:1.05}
.nuc-ios .ios-hi .sub{margin:5px 0 0;font-size:14px;color:var(--label2);max-width:none}
.nuc-ios .ios-streak{
flex:none;display:inline-flex;align-items:center;gap:7px;
background:var(--card);border-radius:999px;padding:7px 11px;
}
.nuc-ios .ios-streak .bolt{color:var(--frozen);filter:drop-shadow(0 0 4px rgba(66,163,245,.5))}
.nuc-ios .ios-streak .col{display:flex;flex-direction:column;line-height:1}
.nuc-ios .ios-streak .n{font-size:16px;font-weight:600;font-variant-numeric:tabular-nums}
.nuc-ios .ios-streak .lbl{font-size:10px;color:var(--label2);margin-top:2px}
.nuc-ios .ios-streak .fz{display:inline-flex;align-items:center;gap:2px;color:var(--frozen);font-size:12px;font-weight:600}
.nuc-ios .ios-streak .fz svg{width:12px;height:12px}
/* StatCard row — five across, like HomeView.statCards (tight at phone width,
exactly as the app is; labels wrap like SwiftUI Text, value never wraps) */
.nuc-ios .ios-stats{display:flex;gap:7px;align-items:stretch}
.nuc-ios .ios-stat{
flex:1 1 0;min-width:0;
background:var(--card);border:1px solid var(--hair);border-radius:13px;
padding:8px 7px;display:flex;flex-direction:column;gap:3px;
}
.nuc-ios .ios-stat .ic{color:var(--accent)}
.nuc-ios .ios-stat .ic svg{width:15px;height:15px}
.nuc-ios .ios-stat .n{font-size:15px;font-weight:600;font-family:var(--mono);letter-spacing:-.03em;white-space:nowrap}
.nuc-ios .ios-stat .l{font-size:9.5px;line-height:1.12;color:var(--label2);overflow-wrap:break-word}
/* a .card() block (CardBackground modifier) */
.nuc-ios .ios-card{background:var(--card);border:1px solid var(--hair);border-radius:14px;padding:14px}
.nuc-ios .ios-card-h{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
.nuc-ios .ios-card-h .h{font-size:16px;font-weight:600;letter-spacing:-.01em}
.nuc-ios .ios-card-h .cnt{font-size:15px;color:var(--label2);font-variant-numeric:tabular-nums}
/* ActivityGrid (no legend on iOS — just the grid) */
.nuc-ios .ios-grid{display:flex;gap:3px;flex-wrap:nowrap;overflow:hidden}
.nuc-ios .ios-grid .col{display:flex;flex-direction:column;gap:3px}
.nuc-ios .ios-grid i{width:13px;height:13px;border-radius:2px;background:var(--a0);display:block}
.nuc-ios .ios-grid i.l1{background:var(--a1)} .nuc-ios .ios-grid i.l2{background:var(--a2)}
.nuc-ios .ios-grid i.l3{background:var(--a3)} .nuc-ios .ios-grid i.l4{background:var(--a4)}
.nuc-ios .ios-grid i.fz{background:var(--frozen)}
/* SessionRow */
.nuc-ios .ios-srow{display:flex;align-items:center;gap:12px;padding:3px 0}
.nuc-ios .ios-srow .sym{width:24px;flex:none;display:flex;justify-content:center}
.nuc-ios .ios-srow .sym svg{width:21px;height:21px}
.nuc-ios .ios-srow .sc{flex:1;min-width:0}
.nuc-ios .ios-srow .st{font-size:16px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nuc-ios .ios-srow .sp{font-size:12px;color:var(--label2);margin-top:1px}
.nuc-ios .ios-srow .diff{font-size:12px;font-family:var(--mono);color:var(--label2);flex:none}
/* QuickTodos */
.nuc-ios .ios-capture{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.nuc-ios .ios-input{
flex:1;min-width:0;background:var(--field);border:1px solid var(--field-hair);border-radius:8px;
padding:8px 11px;font-size:14px;color:var(--label3);
}
.nuc-ios .ios-addbtn{color:var(--accent);flex:none;display:flex}
.nuc-ios .ios-addbtn svg{width:24px;height:24px}
.nuc-ios .ios-todo{display:flex;align-items:center;gap:10px;padding:6px 0}
.nuc-ios .ios-todo .box{color:var(--label3);flex:none;display:flex}
.nuc-ios .ios-todo .box svg{width:18px;height:18px}
.nuc-ios .ios-todo .tt{flex:1;min-width:0;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nuc-ios .ios-todo .pn{font-size:11px;color:var(--label2);flex:none}
/* StartChatComposer */
.nuc-ios .ios-comp-row{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:10px}
.nuc-ios .ios-menu{display:inline-flex;align-items:center;gap:5px;font-size:14px;color:var(--label)}
.nuc-ios .ios-menu svg{width:15px;height:15px;color:var(--label2)}
.nuc-ios .ios-tint{display:inline-flex;align-items:center;gap:4px;font-size:13px;color:var(--accent);font-weight:500}
.nuc-ios .ios-tint svg{width:14px;height:14px}
.nuc-ios .ios-tint .badge{color:var(--label3);font-weight:400}
.nuc-ios .ios-auto{
display:inline-flex;align-items:center;gap:5px;font-size:13px;color:var(--label2);
border:1px solid var(--field-hair);border-radius:8px;padding:5px 9px;font-weight:500;
}
.nuc-ios .ios-auto svg{width:14px;height:14px}
.nuc-ios .ios-comp-field{display:flex;align-items:flex-end;gap:8px}
.nuc-ios .ios-comp-field .ios-input{padding:10px 12px;font-size:15px}
.nuc-ios .ios-send{color:var(--accent);flex:none;display:flex}
.nuc-ios .ios-send svg{width:30px;height:30px}
/* ConnectionChip — floating, pinned above the tab bar */
.nuc-ios .ios-chip{
position:absolute;left:50%;bottom:72px;transform:translateX(-50%);z-index:5;
display:inline-flex;align-items:center;gap:6px;
background:rgba(255,255,255,.74);
-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
border:1px solid var(--hair);border-radius:999px;padding:6px 12px;
font-size:13px;font-weight:500;color:var(--label);
box-shadow:0 6px 18px -10px rgba(0,0,0,.35);
}
.nuc-ios .ios-chip .dot{width:8px;height:8px;border-radius:50%;background:#34c759}
/* ---- tab bar (RootView TabView) ------------------------------------------- */
.nuc-ios .ios-tabbar{
position:absolute;left:0;right:0;bottom:0;z-index:4;
display:flex;align-items:center;padding:6px 6px;height:60px;
background:var(--tabbar);
-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);
border-top:1px solid var(--hair);
}
.nuc-ios .ios-tab{
flex:1;display:flex;flex-direction:column;align-items:center;gap:3px;
color:var(--tab-off);position:relative;
}
.nuc-ios .ios-tab svg{width:25px;height:25px}
.nuc-ios .ios-tab .tl{font-size:10px;font-weight:500;letter-spacing:.01em}
.nuc-ios .ios-tab.on{color:var(--accent)}
.nuc-ios .ios-tab .tbadge{
position:absolute;top:-3px;left:calc(50% + 7px);
min-width:16px;height:16px;padding:0 4px;border-radius:999px;
background:var(--danger);color:#fff;font-size:10px;font-weight:700;
display:flex;align-items:center;justify-content:center;font-variant-numeric:tabular-nums;
}
</style>
</head>
<body>
<!-- TestFlight app mark — defined once, referenced by the CTA buttons via <use>. -->
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
<symbol id="tf-icon" viewBox="6 5.5 12 12">
<g transform="matrix(0.31 0 0 0.31 12 12)" fill="currentColor" stroke="currentColor" stroke-width="2.3" stroke-linejoin="round" stroke-linecap="round">
<g transform="matrix(1 0 0 1 -0.5 -9.99)">
<path transform=" translate(-31.5, -24.01)" d="M 30.729 32.318 C 30.729 32.318 31.151999999999997 33.052 31.999 32.997 C 32.846000000000004 32.942 33.092999999999996 32.236 33.163 31.964 C 33.233 31.692 34.01 22.208 34.01 21.746 C 34.01 21.284 33.622 20.333 33.445 19.735 C 33.268 19.137 32.269 16.012 32.104 15.631 C 31.785999999999998 14.897 30.128 14.625 29.881 15.957 C 29.675 17.077 29 26.258 29 26.258 C 29 26.258 29 27.046 29.318 28.079 C 29.635 29.111 30.729 32.318 30.729 32.318 z"/>
</g>
<g transform="matrix(1 0 0 1 -10.11 7.69)">
<path transform=" translate(-23.39, -38.69)" d="M 30.846 34.962 C 30.846 34.962 31.247 34.216 30.756 33.524 C 30.265 32.832 29.534 32.994 29.265 33.077 C 28.997 33.16 20.522 37.488 20.129 37.730999999999995 C 19.736 37.974 19.131 38.803999999999995 18.716 39.26899999999999 C 18.301000000000002 39.73399999999999 16.168 42.22699999999999 15.931000000000001 42.56799999999999 C 15.474 43.22399999999999 16.115000000000002 44.776999999999994 17.378 44.28699999999999 C 18.439 43.87499999999999 26.602 39.61999999999999 26.602 39.61999999999999 C 26.602 39.61999999999999 27.272000000000002 39.20499999999999 27.984 38.39199999999999 C 28.694 37.579 30.846 34.962 30.846 34.962 z"/>
</g>
<g transform="matrix(1 0 0 1 10.11 7.69)">
<path transform=" translate(-40.61, -38.69)" d="M 33.154 34.962 C 33.154 34.962 32.753 34.216 33.24400000000001 33.524 C 33.735000000000014 32.832 34.46600000000001 32.994 34.73500000000001 33.077 C 35.00300000000001 33.16 43.47800000000001 37.488 43.87100000000001 37.730999999999995 C 44.26400000000001 37.974 44.86900000000001 38.803999999999995 45.284000000000006 39.26899999999999 C 45.699000000000005 39.73399999999999 47.83200000000001 42.22699999999999 48.069 42.56799999999999 C 48.526 43.22399999999999 47.885000000000005 44.776999999999994 46.622 44.28699999999999 C 45.561 43.87499999999999 37.397999999999996 39.61999999999999 37.397999999999996 39.61999999999999 C 37.397999999999996 39.61999999999999 36.727999999999994 39.20499999999999 36.016 38.39199999999999 C 35.304 37.578999999999986 33.154 34.962 33.154 34.962 z"/>
</g>
</g>
</symbol>
</svg>
<!-- ===== top bar ===== -->
<header>
<div class="wrap bar">
<a class="brand" href="/">
<svg class="mk" viewBox="0 0 100 100" aria-hidden="true">
<g fill="none" stroke-width="7">
<ellipse cx="50" cy="50" rx="17" ry="40" transform="rotate(80 50 50)" stroke="#7AA7DD"/>
<ellipse cx="50" cy="50" rx="17" ry="40" transform="rotate(20 50 50)" stroke="#DF619B"/>
<ellipse cx="50" cy="50" rx="17" ry="40" transform="rotate(140 50 50)" stroke="#C5826F"/>
</g>
</svg>
Nucleic
<span class="tag">iPhone</span>
</a>
<nav class="nav">
<a class="lk" id="nav-mac" href="/">Mac app</a>
<a class="btn appstore" id="nav-dl" href="https://updates.nucleic.blakeslee.xyz/testflight/beta" target="_blank" rel="noopener noreferrer" title="Join the Nucleic beta on TestFlight">
<svg viewBox="0 0 24 24" aria-hidden="true"><use href="#tf-icon"/></svg>
Available on TestFlight
</a>
</nav>
</div>
</header>
<!-- ===== hero ===== -->
<section class="hero">
<div class="wrap hero-grid">
<div>
<span class="hero-badge">Native iPhone companion</span>
<h1>The cockpit,<br/><span class="em">in your pocket.</span></h1>
<p class="sub">Your Mac's fleet, projected to your phone. Watch sessions stream, answer approvals, and send the next prompt from wherever you are — end-to-end encrypted.</p>
<div class="cta-row">
<a class="btn appstore" id="hero-dl" href="https://updates.nucleic.blakeslee.xyz/testflight/beta" target="_blank" rel="noopener noreferrer" title="Join the Nucleic beta on TestFlight">
<svg viewBox="0 0 24 24" aria-hidden="true"><use href="#tf-icon"/></svg>
Available on TestFlight
</a>
</div>
<div class="cta-row" style="margin-top:16px"><a class="hero-ip" href="/">It starts on your Mac. Meet the desktop cockpit →</a></div>
<div class="cta-row"><span class="cta-note">Pairs with the Mac app by QR · private by design · end-to-end encrypted</span></div>
</div>
<div class="phone-wrap">
<!-- ===== iPhone app surface (data-nuc-ios) ===== -->
<div class="nuc-ios" aria-label="The Nucleic iPhone app — Home tab">
<div class="ios-phone">
<!-- Home content (HomeView) -->
<div class="ios-content">
<!-- greeting + StreakBadge -->
<div class="ios-hi">
<div>
<h1>Good morning</h1>
<p class="sub">2 active of 5 chats · 2 projects</p>
</div>
<span class="ios-streak">
<svg class="bolt" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M13 2 4 14h6l-1 8 9-12h-6z"/></svg>
<span class="col"><span class="n">15</span><span class="lbl">day streak</span></span>
<span class="fz">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M12 2v20M3.5 7l17 10M20.5 7l-17 10"/><path d="M12 6l2.2-2.2M12 6 9.8 3.8M12 18l2.2 2.2M12 18l-2.2 2.2"/></svg>
1
</span>
</span>
</div>
<!-- five StatCards -->
<div class="ios-stats">
<div class="ios-stat">
<span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><path d="M3 7a2 2 0 0 1 2-2h3.5l2 2H19a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg></span>
<span class="n">2</span><span class="l">Projects</span>
</div>
<div class="ios-stat">
<span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><circle cx="12" cy="12" r="9"/><path d="M12 3a9 9 0 0 0 0 18z" fill="currentColor" stroke="none"/></svg></span>
<span class="n">1</span><span class="l">In progress</span>
</div>
<div class="ios-stat">
<span class="ic"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M13 2 4 14h6l-1 8 9-12h-6z"/></svg></span>
<span class="n">2</span><span class="l">Active</span>
</div>
<div class="ios-stat">
<span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"><path d="M21 3 10 14M21 3l-7 18-4-7-7-4z"/></svg></span>
<span class="n">142</span><span class="l">Messages</span>
</div>
<div class="ios-stat">
<span class="ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M4 8h7M4 12h11M4 16h6"/></svg></span>
<span class="n">1.3M</span><span class="l">Tokens</span>
</div>
</div>
<!-- Activity card -->
<div class="ios-card">
<div class="ios-card-h"><span class="h">Activity</span></div>
<div class="ios-grid" aria-hidden="true"><!-- cells injected by the scoped script --></div>
</div>
<!-- In progress card -->
<div class="ios-card">
<div class="ios-card-h"><span class="h">In progress</span><span class="cnt">1</span></div>
<div class="ios-srow">
<span class="sym" style="color:var(--active)">
<!-- circle.lefthalf.filled (running) -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><circle cx="12" cy="12" r="9"/><path d="M12 3a9 9 0 0 0 0 18z" fill="currentColor" stroke="none"/></svg>
</span>
<span class="sc"><div class="st">flaky-tests</div><div class="sp">nucleic</div></span>
<span class="diff">+88/12</span>
</div>
</div>
<!-- To-dos card (QuickTodos) -->
<div class="ios-card">
<div class="ios-card-h"><span class="h">To-dos</span><span class="cnt">3</span></div>
<div class="ios-capture">
<span class="ios-input">Capture an idea…</span>
<span class="ios-addbtn"><svg viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="12" r="10"/><path d="M12 8v8M8 12h8" fill="none" stroke="#fff" stroke-width="1.8" stroke-linecap="round"/></svg></span>
</div>
<div class="ios-todo">
<span class="box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><circle cx="12" cy="12" r="9"/></svg></span>
<span class="tt">Dark mode in settings</span>
<span class="pn">website</span>
</div>
<div class="ios-todo">
<span class="box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><circle cx="12" cy="12" r="9"/></svg></span>
<span class="tt">Sync server memory leak</span>
<span class="pn">nucleic</span>
</div>
<div class="ios-todo">
<span class="box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><circle cx="12" cy="12" r="9"/></svg></span>
<span class="tt">Write release notes</span>
</div>
</div>
<!-- New chat composer (StartChatComposer) -->
<div class="ios-card">
<div class="ios-card-h"><span class="h">New chat</span></div>
<div class="ios-comp-row">
<span class="ios-menu"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><path d="M3 7a2 2 0 0 1 2-2h3.5l2 2H19a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>nucleic</span>
<span class="ios-auto"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"><path d="M13 2 4 14h6l-1 8 9-12h-6z"/><path d="M3 3l18 18"/></svg>Auto</span>
</div>
<div class="ios-comp-row">
<span class="ios-tint"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><rect x="4" y="4" width="16" height="16" rx="2"/><rect x="8.5" y="8.5" width="7" height="7" rx="1"/><path d="M9 1.5v2.5M15 1.5v2.5M9 20v2.5M15 20v2.5M1.5 9H4M1.5 15H4M20 9h2.5M20 15h2.5"/></svg>Default model</span>
<span class="ios-tint"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"><path d="M4 6h10M18 6h2M4 12h2M10 12h10M4 18h8M16 18h4"/><circle cx="16" cy="6" r="2.2" fill="#fff"/><circle cx="8" cy="12" r="2.2" fill="#fff"/><circle cx="14" cy="18" r="2.2" fill="#fff"/></svg>high</span>
</div>
<div class="ios-comp-field">
<span class="ios-input">Describe a task…</span>
<span class="ios-send"><svg viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="12" r="11"/><path d="M12 17V8M8 11l4-4 4 4" fill="none" stroke="#fff" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</div>
</div>
</div>
<!-- ConnectionChip -->
<span class="ios-chip"><span class="dot"></span>Connected · LAN</span>
<!-- tab bar -->
<nav class="ios-tabbar">
<span class="ios-tab on">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 11.2 12 4l9 7.2V20a1.4 1.4 0 0 1-1.4 1.4h-4.1V15h-3v6.4H4.4A1.4 1.4 0 0 1 3 20z"/></svg>
<span class="tl">Home</span>
</span>
<span class="ios-tab">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"><path d="M4 9.5 12 6l8 3.5-8 3.5z"/><path d="M5 13l7 3 7-3M5 16.5l7 3 7-3"/></svg>
<span class="tl">Sessions</span>
<span class="tbadge">2</span>
</span>
<span class="ios-tab">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><path d="M3 7a2 2 0 0 1 2-2h3.5l2 2H19a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>
<span class="tl">Projects</span>
</span>
<span class="ios-tab">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6l1.6 1.6L8.5 4.7M11 6h9M4 12l1.6 1.6L8.5 10.7M11 12h9M4 18l1.6 1.6L8.5 16.7M11 18h9"/></svg>
<span class="tl">To-dos</span>
</span>
<span class="ios-tab">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="3.2"/><path d="M12 2.5v3M12 18.5v3M2.5 12h3M18.5 12h3M5.2 5.2l2.1 2.1M16.7 16.7l2.1 2.1M18.8 5.2l-2.1 2.1M7.3 16.7l-2.1 2.1"/></svg>
<span class="tl">Settings</span>
</span>
</nav>
</div>
</div>
<!-- ===== end iPhone app surface ===== -->
<span class="cta-note">The Nucleic iPhone app — Home tab. Illustrative.</span>
</div>
</div>
</section>
<!-- ===== premise ===== -->
<section class="band">
<div class="wrap">
<h2 class="lede">Agents don't stop when you stand up.</h2>
<p>The fleet keeps working after you leave your desk — right up until it needs an approval or the next instruction. Then everything waits on you.</p>
<p>The iPhone remote keeps you in command: every session, approval, transcript, and diff, live from your Mac. <strong>Answer in seconds. From anywhere.</strong></p>
</div>
</section>
<!-- ===== features ===== -->
<section class="features" id="features">
<div class="wrap">
<div class="sechead">
<div>
<div class="kicker">What it does</div>
<h2>Keep the fleet moving. From anywhere.</h2>
</div>
<p>A pure projection of your Mac. Read everything. Approve anything. Miss nothing.</p>
</div>
<div class="grid">
<div class="card">
<span class="no">01</span>
<svg class="accent" viewBox="0 0 24 24" fill="none" stroke="var(--amber)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l7 3v5c0 4.5-3 8-7 10-4-2-7-5.5-7-10V6z"/><path d="m9 12 2 2 4-4"/></svg>
<h3>Answer approvals</h3>
<p>The whole point. Risk-labeled cards show the full command and its context — allow or deny in one tap, with Face&nbsp;ID standing guard on the risky ones.</p>
</div>
<div class="card">
<span class="no">02</span>
<svg class="accent" viewBox="0 0 24 24" fill="none" stroke="var(--blue)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M2.5 12S6 5.5 12 5.5 21.5 12 21.5 12 18 18.5 12 18.5 2.5 12 2.5 12z"/></svg>
<h3>Watch the work</h3>
<p>Transcripts stream in live, tool calls fold away, and diffs are one tap deep. Sessions sort attention-first — what needs you is always on top.</p>
</div>
<div class="card">
<span class="no">03</span>
<svg class="accent" viewBox="0 0 24 24" fill="none" stroke="var(--pink)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 3 10 14M21 3l-7 18-4-7-7-4z"/></svg>
<h3>Send the next prompt</h3>
<p>An agent waiting on input is a fleet standing still. Type the follow-up from your phone, and it's back to work before you're back at your desk.</p>
</div>
<div class="card">
<span class="no">04</span>
<svg class="accent" viewBox="0 0 24 24" fill="none" stroke="var(--green)" stroke-width="2"><rect x="3" y="3" width="8" height="8" rx="1.5"/><rect x="13" y="3" width="8" height="8" rx="1.5"/><rect x="3" y="13" width="8" height="8" rx="1.5"/><rect x="13" y="13" width="8" height="8" rx="1.5"/></svg>
<h3>A glanceable home</h3>
<p>Stat cards, the activity grid, your streak, and quick to-dos — the same dashboard your Mac shows, sized for the moment between moments.</p>
</div>
<div class="card">
<span class="no">05</span>
<svg class="accent" viewBox="0 0 24 24" fill="none" stroke="var(--magenta)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5v14"/></svg>
<h3>Start and steer</h3>
<p>Kick off a new chat — project, model, effort, go. And capture ideas into the inbox the moment they strike.</p>
</div>
<div class="card">
<span class="no">06</span>
<svg class="accent" viewBox="0 0 24 24" fill="none" stroke="var(--rust)" stroke-width="2"><rect x="5" y="11" width="14" height="9" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/></svg>
<h3>Private by design</h3>
<p>Paired with a QR scan and encrypted end to end. Your Mac stays the single source of truth — the phone holds no code and makes nothing up.</p>
</div>
</div>
</div>
</section>
<!-- ===== built like the Mac app ===== -->
<section class="native" id="pair">
<div class="wrap">
<div class="head">
<div class="kicker">Built like the Mac app</div>
<h2>A real iPhone app, <span class="em">not a web view</span>.</h2>
<p>100% Swift and SwiftUI, with the same status glyphs, palette, and semantics as the Mac cockpit. Two devices, one language.</p>
</div>
<div class="native-grid">
<div class="ncard">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="var(--blue)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="7" y="3" width="10" height="18" rx="2"/><path d="M11 18h2"/></svg>
<h3>Pure Swift &amp; SwiftUI</h3>
<p>Native navigation, native performance, featherweight on battery. It feels like it came with your iPhone.</p>
</div>
<div class="ncard">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="var(--magenta)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="2"/><rect x="8.5" y="8.5" width="7" height="7" rx="1"/><path d="M9 1.5v2.5M15 1.5v2.5M9 20v2.5M15 20v2.5M1.5 9H4M1.5 15H4M20 9h2.5M20 15h2.5"/></svg>
<h3>Paired in seconds</h3>
<p>Open Nucleic on your Mac, choose Add&nbsp;iPhone, scan the code. Encrypted from the first byte. No account, no setup, nothing else.</p>
</div>
<div class="ncard">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="var(--green)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4.5 13.5a7.5 7.5 0 0 1 15 0"/><circle cx="12" cy="17" r="2"/><path d="M8 17h2M14 17h2"/></svg>
<h3>Honest connectivity</h3>
<p>Phones roam. So stale data is always labeled, and actions disable instead of silently failing. You always know exactly what you're looking at.</p>
</div>
</div>
<p class="foot-note">pairs with Nucleic for Mac <span class="dotsep">·</span> QR pairing <span class="dotsep">·</span> end-to-end encrypted</p>
</div>
</section>
<!-- ===== how it connects ===== -->
<section class="native" id="connect">
<div class="wrap">
<div class="head">
<div class="kicker">How it reaches your Mac</div>
<h2>On your WiFi, or <span class="em">across the world</span>.</h2>
<p>You never choose a connection or think about where you are. The phone finds your Mac on its own and keeps up as you move — from the couch to the car to another continent — always over the fastest private path, always end-to-end encrypted, with no code or diffs ever left on the phone.</p>
</div>
<div class="native-grid">
<div class="ncard">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="var(--green)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12.5a10 10 0 0 1 14 0"/><path d="M8.4 16a5 5 0 0 1 7.2 0"/><circle cx="12" cy="19.2" r="1"/></svg>
<h3>At your desk</h3>
<p>On the same WiFi, your phone connects straight to your Mac. Nothing to set up, nothing to sign into.</p>
</div>
<div class="ncard">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="var(--blue)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M3 12h18"/><path d="M12 3c2.7 2.7 2.7 15.3 0 18M12 3c-2.7 2.7-2.7 15.3 0 18"/></svg>
<h3>Out in the world</h3>
<p>Leave the house and it keeps up — your Mac stays reachable over your own private network.</p>
</div>
<div class="ncard">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="var(--rust)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M7 18a4 4 0 0 1-.4-8A5 5 0 0 1 16.5 8.6 3.7 3.7 0 0 1 18 18z"/><path d="M9.5 13.5 12 11l2.5 2.5"/></svg>
<h3>Anywhere at all</h3>
<p>Hotel WiFi, a locked-down office, a train. Covalence gets through, and only your devices can read what crosses it.</p>
</div>
</div>
<p class="foot-note">end-to-end encrypted on every path</p>
</div>
</section>
<!-- ===== access ===== -->
<section class="access" id="access">
<div class="wrap">
<div class="panel">
<div class="kicker">Open beta</div>
<h2>Take the cockpit with you.</h2>
<p>The iPhone remote ships alongside the Nucleic beta. Download the Mac app, then pair your phone from Nucleic&nbsp;▸ Settings&nbsp;▸ Add&nbsp;iPhone.</p>
<div class="cta-row">
<a class="btn" href="https://updates.nucleic.blakeslee.xyz/beta/latest" target="_blank" rel="noopener noreferrer">Download Nucleic for Mac</a>
<a class="btn ghost" href="/">Learn about Nucleic</a>
</div>
<div class="panel-trust mono"><strong style="color:var(--ink);font-weight:600">No account required</strong> <span class="dotsep">·</span> private by design <span class="dotsep">·</span> end-to-end encrypted</div>
</div>
</div>
</section>
<footer>
<div class="wrap foot">
<a class="brand" href="/" style="font-size:15px">
<svg class="mk" viewBox="0 0 100 100" aria-hidden="true">
<g fill="none" stroke-width="7">
<ellipse cx="50" cy="50" rx="17" ry="40" transform="rotate(80 50 50)" stroke="#7AA7DD"/>
<ellipse cx="50" cy="50" rx="17" ry="40" transform="rotate(20 50 50)" stroke="#DF619B"/>
<ellipse cx="50" cy="50" rx="17" ry="40" transform="rotate(140 50 50)" stroke="#C5826F"/>
</g>
</svg>
Nucleic
</a>
<div class="foot-links">
<a href="/support.html">Support</a>
<a href="/privacy.html">Privacy</a>
<a href="/terms.html">Terms</a>
</div>
<div class="foot-end">
<div class="mono">© 2026 Andrew Blakeslee&nbsp;Moore</div>
<div class="mono">Made with Nucleic</div>
</div>
</div>
</footer>
<!-- Hidden frame: starts the Mac download in the background — no new tab, no
navigation. Falls back to target="_blank" if JavaScript is unavailable. -->
<iframe id="dl-frame" title="Download" aria-hidden="true" tabindex="-1" style="position:absolute;width:0;height:0;border:0;left:-9999px"></iframe>
<script>
(function () {
var frame = document.getElementById("dl-frame");
Array.prototype.forEach.call(
// Mac download links load into the hidden frame; the TestFlight link is
// a redirect meant to open in a new tab, so leave it to navigate normally.
document.querySelectorAll('a[href^="https://updates.nucleic.blakeslee.xyz/"]:not([href*="/testflight/"])'),
function (a) {
a.addEventListener("click", function (e) {
e.preventDefault();
frame.src = a.getAttribute("href");
});
}
);
})();
</script>
<!-- ===== iPhone app surface: paint its activity grid (data-nuc-ios) ===== -->
<script data-nuc-ios>
(function () {
// Paint the activity grid ONCE with a fixed column count sized to the 360px
// card — no live width measuring and no resize rebuild, so it never reflows or
// "jumps" on load. Deterministic (seeded); recent weeks (right) trend busier,
// with two streak-freeze cells in the iced blue. The grid's overflow:hidden
// clips the rightmost column gracefully on phones narrower than the card.
var COLS = 19, ROWS = 7;
function build(grid) {
grid.textContent = '';
var seed = 20260629;
function rnd() { seed = (seed * 1103515245 + 12345) & 0x7fffffff; return seed / 0x7fffffff; }
var frozen = {};
frozen[(COLS - 7) + ',2'] = 1;
frozen[(COLS - 3) + ',5'] = 1;
for (var c = 0; c < COLS; c++) {
var col = document.createElement('div');
col.className = 'col';
var recency = c / (COLS - 1);
for (var r = 0; r < ROWS; r++) {
var i = document.createElement('i');
if (frozen[c + ',' + r]) {
i.className = 'fz';
} else {
var p = rnd() * 0.55 + recency * 0.6;
var lvl = p < 0.3 ? 0 : p < 0.52 ? 1 : p < 0.73 ? 2 : p < 0.9 ? 3 : 4;
if (lvl) i.className = 'l' + lvl;
}
col.appendChild(i);
}
grid.appendChild(col);
}
}
function fill() { document.querySelectorAll('.nuc-ios .ios-grid').forEach(build); }
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', fill);
else fill();
})();
</script>
<script>
// Reveal the top-bar Mac link and App Store button only once the hero's own
// App Store button has scrolled out of view above the viewport — until then
// the hero carries the CTA and the bar stays uncluttered (mirrors index.html).
(function () {
var navBtn = document.getElementById("nav-dl");
var navMac = document.getElementById("nav-mac");
var heroBtn = document.getElementById("hero-dl");
var items = [navBtn, navMac].filter(Boolean);
if (!items.length || !heroBtn) return;
function set(show) { items.forEach(function (el) { el.classList.toggle("show", show); }); }
if (!("IntersectionObserver" in window)) { set(true); return; }
var io = new IntersectionObserver(function (entries) {
set(!entries[0].isIntersecting);
}, { threshold: 0 });
io.observe(heroBtn);
})();
</script>
</body>
</html>