---
layout: full
---
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Diesel: Work at the speed of thought</title>
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,400;12..96,600;12..96,800&family=Atkinson+Hyperlegible:wght@400;700&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
<style>
:root{
--paper:#f4f7fb; --card:#ffffff; --ink:#1c2340; --soft:#5b6380; --line:#dfe5ef;
--sun:#f2b84b; --leaf:#2f9a6f; --indigo:#5550d8; --slate:#4e6a86; --attn:#7a7fc9;
--sun-bg:#fff6e0; --indigo-bg:#eeedff; --slate-bg:#e9f0f6;
--display:'Bricolage Grotesque',system-ui,sans-serif;
--body:'Atkinson Hyperlegible',system-ui,-apple-system,'Segoe UI',sans-serif;
--mono:'JetBrains Mono',ui-monospace,Menlo,Consolas,monospace;
}
@media (prefers-color-scheme: dark){
:root{
--paper:#141a2b; --card:#1c2338; --ink:#eef1fa; --soft:#a4acc6; --line:#2c3552;
--sun-bg:#2e2816; --indigo-bg:#24234a; --slate-bg:#1e2a38;
--indigo:#8d88ff; --slate:#8fb0cf; --leaf:#4cc392; --attn:#9296f5;
}
}
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--body);font-size:17px;line-height:1.55;
padding:env(safe-area-inset-top,0px) 0 env(safe-area-inset-bottom,0px)}
a{color:inherit}
.wrap{max-width:1080px;margin:0 auto;padding:0 clamp(16px,4vw,32px)}
:focus-visible{outline:3px solid var(--indigo);outline-offset:3px;border-radius:6px}
/* top bar */
.bar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:18px 0}
.mark{display:flex;align-items:center;gap:10px;font-family:var(--display);font-weight:800;font-size:22px;text-decoration:none;letter-spacing:-.01em}
.mark svg{width:30px;height:30px}
.mark svg.wm{width:auto;height:30px}
@keyframes d2blink{50%{opacity:0}}.d2cur{animation:d2blink 1.1s steps(1) infinite}
@media (prefers-reduced-motion:reduce){.d2cur{animation:none}}
.bar nav{display:flex;gap:4px;flex-wrap:wrap}
.bar nav a{text-decoration:none;color:var(--soft);padding:6px 10px;border-radius:999px;font-size:15px}
.bar nav a:hover{color:var(--ink);background:var(--card)}
.bar nav a.btn.login{color:var(--paper,#fff);padding:6px 16px;font-size:15px;margin-left:6px}
.bar nav a.btn.login:hover{color:var(--paper,#fff);background:var(--ink)}
.bar nav a.btn.signup{background:transparent;color:var(--ink);padding:6px 16px;font-size:15px;box-shadow:inset 0 0 0 2px var(--line)}
.bar nav a.btn.signup:hover{box-shadow:inset 0 0 0 2px var(--ink)}
/* hero */
.hero{display:grid;grid-template-columns:1.05fr 1fr;gap:clamp(20px,4vw,48px);align-items:center;padding:clamp(20px,5vw,56px) 0 clamp(40px,6vw,72px)}
.hero h1{font-family:var(--display);font-weight:800;font-size:clamp(32px,4.6vw,52px);line-height:1.02;letter-spacing:-.025em;margin:0 0 18px;min-height:3.1em}
.hero p.lede{font-size:19px;color:var(--soft);max-width:34em;margin:0 0 26px;min-height:4.8em}
.swap{transition:opacity .25s ease}
.swap.fade{opacity:0}
.doors{display:flex;flex-wrap:wrap;gap:10px}
.btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;text-decoration:none;font:600 16px var(--body);
padding:12px 18px;border-radius:14px;background:var(--ink);color:var(--paper)}
.btn.ghost{background:transparent;color:var(--ink);box-shadow:inset 0 0 0 2px var(--line)}
.btn.ghost:hover{box-shadow:inset 0 0 0 2px var(--ink)}
.btn.tier{display:inline-flex;flex-direction:column;align-items:center;line-height:1.15}.btn.tier small{font-size:12px;font-weight:600;opacity:.75;margin-top:2px}
/* the three-lens card: the one bold element */
.lens{background:var(--card);border-radius:26px;padding:14px;box-shadow:0 1px 0 var(--line),0 18px 40px -24px rgba(28,35,64,.35);position:relative}
.lens .tabs{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;background:var(--paper);border-radius:16px;padding:5px} /* scoped: the Master section has its own .tabs (P-131) */
.tab{border:0;background:transparent;border-radius:12px;padding:9px 6px;font:600 15px var(--body);color:var(--soft);cursor:pointer}
.tab[aria-selected="true"]{background:var(--card);color:var(--ink);box-shadow:0 1px 3px rgba(28,35,64,.14)}
.tab .dot{display:inline-block;width:9px;height:9px;border-radius:50%;margin-right:7px;vertical-align:1px}
.view{padding:18px 10px 8px;min-height:292px}
.view[hidden]{display:none}
.caption{font-size:14px;color:var(--soft);margin:12px 4px 2px}
/* notebook view */
.note h3{font-family:var(--display);font-size:22px;margin:0 0 4px}
.note .when{font-size:14px;color:var(--soft);margin-bottom:12px}
.note p{margin:0 0 12px;font-size:16px}
.rows{border-radius:14px;overflow:hidden;border:1px solid var(--line)}
.row{display:grid;grid-template-columns:1fr 4.2em auto;align-items:center;gap:10px;padding:10px 12px;border-top:1px solid var(--line);font-size:15px}
.row:first-child{border-top:0}
.row b{font-weight:700}
.row .up,.row .down{text-align:right}
.up{color:var(--leaf);font-weight:700}
.down{color:#d0506a;font-weight:700}
.pill{font-size:13px;padding:3px 9px;border-radius:999px;background:var(--sun-bg);white-space:nowrap}
/* model view */
.model svg{width:100%;height:auto;display:block}
.model .box rect{fill:var(--indigo-bg);stroke:var(--indigo);stroke-width:2}
.model .box text{fill:var(--ink);font:600 15px var(--body)}
.model .box .attr{font:400 12px var(--mono);fill:var(--soft)}
.model .edge{stroke:var(--indigo);stroke-width:2;fill:none}
.model .elabel{font:400 12px var(--mono);fill:var(--indigo)}
/* source view */
pre.src{margin:0;background:var(--slate-bg);border-radius:16px;padding:16px;overflow-x:auto;font:400 13.5px/1.6 var(--mono);color:var(--ink)}
.src .k{color:var(--slate);font-weight:600}
.src .c{color:var(--soft)}
.src .s{color:var(--leaf)}
/* door sections */
section.door{padding:clamp(36px,6vw,64px) 0;border-top:1px solid var(--line)}
.door .grid{display:grid;grid-template-columns:.9fr 1.1fr;gap:clamp(20px,4vw,48px);align-items:start}
.door h2{font-family:var(--display);font-weight:800;font-size:clamp(28px,3.8vw,42px);line-height:1.05;letter-spacing:-.02em;margin:0 0 14px}
.door .who{font-size:16px;color:var(--soft);margin:0 0 6px}
.door p{max-width:36em}
.badge{display:inline-flex;align-items:center;gap:8px;font-weight:700;font-size:15px;padding:6px 12px;border-radius:999px;margin-bottom:14px}
.t2 .badge{background:var(--sun-bg)}
.t3 .badge{background:var(--indigo-bg);color:var(--indigo)}
.t1 .badge{background:var(--slate-bg);color:var(--slate)}
.verbs{display:grid;gap:12px;margin:0;padding:0;list-style:none}
.verbs li{background:var(--card);border-radius:18px;padding:16px 18px;border:1px solid var(--line)}
.verbs li strong{display:block;font-family:var(--display);font-size:21px;margin-bottom:2px}
.t2 .verbs li strong{color:#b27a0e}
@media (prefers-color-scheme: dark){ .t2 .verbs li strong{color:var(--sun)} }
.t3 .verbs li strong{color:var(--indigo)}
.t1 .verbs li strong{color:var(--slate)}
.chips{display:flex;flex-wrap:wrap;gap:8px;margin:18px 0 22px}
.chip{background:var(--card);border:1px solid var(--line);border-radius:999px;padding:6px 12px;font-size:15px}
.soon{font-size:14px;color:var(--soft);margin-top:10px}
.stat{display:flex;align-items:baseline;gap:14px;margin:18px 0 22px;flex-wrap:wrap}
.stat .big{font-family:var(--display);font-weight:800;font-size:48px;line-height:1;color:var(--indigo)}
.stat .small{color:var(--soft);max-width:18em}
/* modeller stage: tap a class, see the screens it already has */
.stage{background:var(--card);border-radius:22px;border:1px solid var(--line);padding:14px;overflow:hidden}
.stage svg.mini{width:100%;height:auto;display:block}
.stage .node{cursor:pointer}
.stage .node rect{fill:var(--indigo-bg);stroke:var(--indigo);stroke-width:2;transition:fill .2s}
.stage .node text{fill:var(--ink);font:600 14px var(--body);pointer-events:none}
.stage .node.on rect{fill:var(--indigo)}
.stage .node.on text{fill:#fff}
.stage .node:focus{outline:none}
.stage .node:focus-visible rect{stroke-width:4}
.stage .link{stroke:var(--indigo);stroke-width:2;stroke-dasharray:5 5;fill:none}
.stage .ltxt{font:400 11px var(--mono);fill:var(--soft)}
.frame{margin-top:10px;border:1px solid var(--line);border-radius:14px;overflow:hidden;background:var(--paper)}
.frame .chrome{display:flex;align-items:center;gap:6px;padding:8px 10px;border-bottom:1px solid var(--line);background:var(--card)}
.frame .chrome i{width:9px;height:9px;border-radius:50%;background:var(--line);display:inline-block}
.frame .chrome .url{margin-left:8px;font:400 12px var(--mono);color:var(--soft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.screen{padding:12px;min-height:208px}
.screen h4{margin:0 0 8px;font-family:var(--display);font-size:18px;display:flex;justify-content:space-between;align-items:center}
.screen h4 small{font:400 12px var(--body);color:var(--soft)}
.tools{display:flex;gap:6px;margin-bottom:8px;flex-wrap:wrap}
.tools span{font-size:12px;padding:3px 9px;border-radius:999px;border:1px solid var(--line);background:var(--card)}
.tools span.act{border-color:var(--indigo);color:var(--indigo)}
.gl{display:grid;gap:4px}
.gr{display:grid;grid-template-columns:1.4fr 1fr auto;gap:8px;align-items:center;background:var(--card);border-radius:10px;padding:7px 10px;font-size:14px}
.ref{font:400 12px var(--mono);color:var(--indigo);background:var(--indigo-bg);padding:2px 7px;border-radius:6px;justify-self:start}
.stg{font-size:12px;padding:2px 8px;border-radius:999px;background:var(--sun-bg)}
.map{position:relative;height:150px;border-radius:10px;background:
radial-gradient(circle at 30% 40%, rgba(47,154,111,.18) 0 22%, transparent 23%),
radial-gradient(circle at 70% 60%, rgba(47,154,111,.14) 0 26%, transparent 27%),
var(--slate-bg);margin-bottom:6px}
.map b{position:absolute;width:14px;height:14px;border-radius:50%;border:3px solid var(--card);box-shadow:0 1px 3px rgba(0,0,0,.3)}
.map em{position:absolute;font:600 11px var(--body);font-style:normal;background:var(--card);padding:1px 6px;border-radius:6px;transform:translate(10px,-4px)}
.stage .hint{font-size:14px;color:var(--soft);margin:10px 2px 0}
.minis{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:22px}
.minis div{font-size:15px}
.minis strong{display:block;font-family:var(--display);font-size:19px;color:var(--indigo)}
@media (max-width:820px){ .minis{grid-template-columns:1fr} }
/* notebook stage */
.nstage{background:var(--card);border-radius:22px;border:1px solid var(--line);padding:14px}
.seg{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;background:var(--sun-bg);border-radius:14px;padding:5px}
.seg button{border:0;background:transparent;border-radius:10px;padding:8px 4px;font:600 15px var(--body);color:var(--soft);cursor:pointer}
.seg button[aria-pressed="true"]{background:var(--card);color:var(--ink);box-shadow:0 1px 3px rgba(28,35,64,.14)}
.scene{min-height:300px;padding:14px 4px 4px}
.bub{max-width:82%;padding:9px 13px;border-radius:16px;margin:0 0 8px;font-size:15px}
.bub.me{margin-left:auto;background:var(--ink);color:var(--paper);border-bottom-right-radius:5px}
.bub.ai{background:var(--paper);border:1px solid var(--line);border-bottom-left-radius:5px}
.saved{display:flex;gap:10px;align-items:center;margin-top:12px;background:var(--sun-bg);border-radius:14px;padding:10px 12px;font-size:15px}
.saved .ic{width:30px;height:30px;border-radius:9px;background:var(--sun);display:grid;place-items:center;font-weight:800;color:#1c2340;flex:none}
.saved small{display:block;color:var(--soft);font-size:13px}
.web{position:relative;height:280px}
.web svg{position:absolute;inset:0;width:100%;height:100%}
.web svg path{vector-effect:non-scaling-stroke;stroke:var(--sun);stroke-width:2.5;fill:none;stroke-linecap:round}
.web .n{position:absolute;transform:translate(-50%,-50%);background:var(--card);border:2px solid var(--line);border-radius:14px;padding:7px 11px;font-size:14px;white-space:nowrap;box-shadow:0 2px 6px rgba(28,35,64,.08)}
.web .n small{display:block;color:var(--soft);font-size:12px}
.web .n.hub{border-color:var(--sun);background:var(--sun-bg);font-weight:700}
.live{background:var(--paper);border:1px solid var(--line);border-radius:16px;padding:14px}
.live h5{margin:0;font-family:var(--display);font-size:19px}
.live .sub{font-size:13px;color:var(--soft);margin-bottom:8px}
.live .px{display:flex;align-items:baseline;gap:10px;margin:4px 0}
.live .px b{font-family:var(--display);font-size:32px}
.live svg{width:100%;height:70px;display:block}
.live svg path{stroke:var(--leaf);stroke-width:2.5;fill:none}
.toast{display:flex;gap:10px;align-items:flex-start;margin-top:12px;background:var(--card);border:2px solid var(--sun);border-radius:14px;padding:10px 12px;font-size:15px}
.toast .ic{flex:none;width:26px;height:26px;border-radius:50%;background:var(--sun);display:grid;place-items:center;font-weight:800;color:#1c2340}
.ticker{margin-top:10px}
.pop{animation:pop .35s ease}
@keyframes pop{from{transform:scale(.96);opacity:.4}to{transform:none;opacity:1}}
@media (prefers-reduced-motion: reduce){ .pop{animation:none} }
.t2 .minis strong{color:#b27a0e}
@media (prefers-color-scheme: dark){ .t2 .minis strong{color:var(--sun)} }
/* obsidian band */
.obs{padding:clamp(36px,6vw,64px) 0;border-top:1px solid var(--line);background:linear-gradient(180deg,var(--paper),var(--card))}
.obs .grid{display:grid;grid-template-columns:1fr 1.1fr;gap:clamp(20px,4vw,48px);align-items:center}
.obs h2{font-family:var(--display);font-weight:800;font-size:clamp(26px,3.4vw,38px);line-height:1.08;letter-spacing:-.02em;margin:0 0 12px}
.obs .badge{background:#efe9ff;color:#6b4fd8}
@media (prefers-color-scheme: dark){ .obs .badge{background:#2c2550;color:#b9a8ff} }
.facts{list-style:none;padding:0;margin:16px 0 22px;display:grid;gap:8px}
.facts li{padding-left:28px;position:relative}
.facts li::before{content:"";position:absolute;left:4px;top:.45em;width:12px;height:12px;border-radius:4px;background:var(--sun)}
.sync{display:grid;grid-template-columns:1fr auto 1fr;gap:10px;align-items:center}
.pane{background:var(--card);border:1px solid var(--line);border-radius:18px;padding:12px;font-size:14px;min-width:0}
.pane h6{margin:0 0 8px;font:700 13px var(--body);color:var(--soft)}
.tree{font:400 13px/1.8 var(--mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tree .hl{background:var(--sun-bg);border-radius:6px;padding:1px 5px;font-weight:600}
.pg h5{margin:0 0 4px;font-family:var(--display);font-size:17px}
.pg p{margin:0 0 8px;color:var(--soft);font-size:13px}
.pg .bar2{height:8px;border-radius:4px;background:var(--line);margin:6px 0}
.pg .bar2.s{width:70%}
.pg .bar2.t{width:45%}
.arrows{display:grid;gap:6px;justify-items:center;color:var(--ink)}
.arrows svg{width:44px;height:22px}
.arrows small{font-size:12px;color:var(--soft)}
@media (max-width:820px){ .obs .grid{grid-template-columns:1fr} }
@media (max-width:480px){ .sync{grid-template-columns:1fr} .arrows{transform:rotate(90deg);margin:4px 0} .arrows small{display:none} }
footer{border-top:1px solid var(--line);padding:32px 0 48px;color:var(--soft);font-size:15px}
footer a{color:var(--ink)}
@media (max-width:820px){
.hero,.door .grid{grid-template-columns:1fr}
.hero h1{min-height:0}
.hero p.lede{min-height:0}
}
@media (prefers-reduced-motion: reduce){ .swap{transition:none} html{scroll-behavior:auto} }
/* hero2: imagine, model, create live */
.hero2{padding:clamp(20px,5vw,56px) 0 clamp(40px,6vw,72px)}
.ladder{margin:0 0 clamp(36px,6vw,64px)}.ladder .tag{font-family:var(--display);font-weight:800;font-size:clamp(20px,2.6vw,28px);margin:0 0 4px}.ladder .sub{color:var(--soft);margin:0 0 14px}
.ladder .rungs{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}.rung{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:baseline;column-gap:8px;text-decoration:none;color:var(--ink);border:1px solid var(--line);border-radius:14px;padding:8px 14px 6px;background:var(--card)}
.rung .lv{grid-column:2;grid-row:1;justify-self:end;font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--soft)}.rung .sp{grid-column:1;grid-row:1;font-size:20px;font-weight:800;color:var(--indigo);margin:0;line-height:1.2}.rung.plain .sp{color:var(--indigo)}.rung .rl{grid-column:1/-1;grid-row:2;font-size:14px;line-height:1.3;color:var(--soft)}
.rung.hi{border:2px solid var(--indigo)}@media (max-width:700px){.ladder .rungs{grid-template-columns:1fr 1fr}}
.hero2 h1{font-family:var(--display);font-weight:800;font-size:clamp(34px,5.4vw,64px);line-height:1;letter-spacing:-.03em;margin:0 0 16px;max-width:14em}
.hero2 p.lede{font-size:19px;color:var(--soft);max-width:36em;margin:0 0 clamp(36px,6vw,64px)}
.steps{list-style:none;padding:0;margin:0 0 28px;display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(12px,2vw,22px)}
.step{position:relative;display:flex;flex-direction:column}
.step .num{position:absolute;top:-2px;left:0;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;font:800 15px var(--display);color:#1c2340}
.s1 .num{background:var(--sun)} .s2 .num{background:var(--indigo);color:#fff} .s3 .num{background:var(--leaf);color:#fff}
.step h3{font-family:var(--display);font-weight:800;font-size:24px;margin:0 0 12px;padding-left:40px;line-height:30px}
.step .card{flex:1;background:var(--card);border-radius:22px;padding:16px;box-shadow:0 1px 0 var(--line),0 18px 40px -26px rgba(28,35,64,.35)}
.step .cap{font-size:14px;color:var(--soft);margin:10px 4px 0}
.step:not(:last-child)::after{content:"";position:absolute;top:13px;right:calc(-1 * clamp(12px,2vw,22px) + 2px);width:clamp(8px,1.4vw,16px);height:2px;background:var(--line)}
.say{max-width:600px;margin:16px 0 6px;padding:12px 16px;border-radius:16px;border-bottom-right-radius:5px;background:var(--sun-bg);color:var(--ink);font-size:17px;line-height:1.45}
.say::before{content:"You: ";font-weight:700}.saycap{color:var(--soft);font-size:15px;margin-top:4px}
.imag{display:flex;flex-direction:column;gap:10px;justify-content:center}
.imag .bub{border-radius:16px;padding:10px 13px;font-size:15px;max-width:92%}
.imag .bub.me{align-self:flex-end;background:var(--sun-bg);color:var(--ink)}
.imag .bub.ai{align-self:flex-start;background:var(--paper)}
.card.note h4{font-family:var(--display);font-size:20px;margin:0 0 2px}
.card.note .row{grid-template-columns:1fr auto;font-size:14px}
.card.note .row .pill{grid-column:1 / -1;justify-self:start}
.card.model{position:relative;padding-top:40px}
.aitag{position:absolute;top:10px;right:12px;font-size:12.5px;font-weight:700;color:var(--indigo);background:var(--indigo-bg);border-radius:999px;padding:3px 10px}
@media (max-width:820px){ .steps{grid-template-columns:1fr} .step:not(:last-child)::after{display:none} }
.t1 .minis strong{color:var(--slate)}
section.extras{padding:clamp(40px,6vw,72px) 0 0;border-top:6px solid var(--line)}
section.extras h2{font-family:var(--display);font-weight:800;font-size:clamp(26px,3.2vw,36px);margin:0 0 4px}
section.extras p{color:var(--soft);margin:0}
section.door.extra{border-top:0}
#hero.door{border-top:0;padding-top:clamp(18px,3vw,32px)}
#hero.door h2{font-size:clamp(22px,2.8vw,32px)}
/* hero door app mockups */
.chips.pick .chip{font:inherit;font-size:15px;color:var(--ink);cursor:pointer}
.chips.pick .chip:hover{border-color:var(--ink)}
.chips.pick .chip[aria-pressed="true"]{background:var(--sun);border-color:var(--sun);color:#1c2340;font-weight:700}
.hs{min-height:260px;font-size:14px}
.hs .kpi{display:flex;align-items:baseline;gap:10px;margin:0 0 10px}
.hs .kpi b{font:800 26px var(--display)}
.hs .muted{color:var(--soft);font-size:12.5px}
.hs .alloc{display:flex;height:10px;border-radius:999px;overflow:hidden;margin:0 0 6px}
.hs .legend{display:flex;gap:12px;flex-wrap:wrap;font-size:12px;color:var(--soft);margin-bottom:10px}
.hs .legend i{display:inline-block;width:9px;height:9px;border-radius:50%;margin-right:5px;vertical-align:0}
.hs .gr{grid-template-columns:1fr auto auto}
.hs .dn{color:var(--rose,#c8435f);font-weight:700}
.hs .news{margin-top:10px;display:grid;gap:5px}.hs .nw{display:flex;justify-content:space-between;align-items:center;gap:8px;font-size:13px}
.hs .bars{display:grid;gap:9px}
.hs .bar3 .lab{display:flex;justify-content:space-between;font-size:13px;margin-bottom:3px}
.hs .bar3 .trk{height:9px;border-radius:999px;background:var(--line);overflow:hidden}
.hs .bar3 .fil{height:100%;border-radius:999px;background:var(--leaf)}
.hs .bar3.over .fil{background:var(--rose,#c8435f)}
.hs .note2{margin-top:10px;background:var(--sun-bg);border-radius:10px;padding:8px 10px;font-size:13px}
.hs .trails{position:relative;height:118px;border-radius:10px;background:var(--slate-bg);overflow:hidden;margin-bottom:8px}
.hs .trails svg{width:100%;height:100%;display:block}
.hs .tag{font-size:11.5px;padding:2px 8px;border-radius:999px;background:var(--card);border:1px solid var(--line);white-space:nowrap}
.hs .tag.ok{color:var(--leaf);border-color:var(--leaf)}
.hs .tag.warn{color:#b27a0e;border-color:#e3b04f}
.hs .beds{display:grid;grid-template-columns:repeat(4,1fr);gap:5px;margin-bottom:8px}
.hs .beds div{background:var(--card);border-radius:8px;padding:6px 4px;text-align:center;font-size:18px;line-height:1.1}
.hs .beds small{display:block;font-size:10.5px;color:var(--soft)}
.hs .beds .dry{box-shadow:inset 0 0 0 2px #e3b04f}
.hs .coins{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-bottom:8px}
.hs .coins div{background:var(--card);border-radius:10px;padding:8px;text-align:center;font-size:12px}
.hs .coins .c{width:34px;height:34px;border-radius:50%;margin:0 auto 5px;background:radial-gradient(circle at 35% 30%,#fff,#c9ced8 45%,#8c93a3);box-shadow:inset 0 0 0 2px rgba(0,0,0,.08)}
.hs .coins .c.au{background:radial-gradient(circle at 35% 30%,#fff3c4,#f2b84b 45%,#b27a0e)}
.hs .coins b{display:block;font-size:12.5px}
.hs .cal{display:grid;gap:5px}
.hs .ev{display:grid;grid-template-columns:44px 1fr auto;gap:10px;align-items:center;background:var(--card);border-radius:10px;padding:7px 10px}
.hs .ev .d{text-align:center;font:800 17px/1 var(--display)}
.hs .ev .d small{display:block;font:600 10.5px var(--body);color:var(--soft);margin-bottom:2px}
.hs .ev.you{box-shadow:inset 3px 0 0 var(--sun)}
</style>
<link rel="icon" href="/favicon.ico" sizes="48x48"><link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@600;700;800&display=swap" rel="stylesheet">
<style id="d2style" data-name="stylesheet-orange1">:root{--paper:#fbfaf7;--card:#ffffff;--ink:#1d1d1b;--soft:#6b6a66;--line:#e4e1da;--indigo:#9a4b12;--indigo-bg:#f5e8dc;--slate:#6b6a66;--slate-bg:#f3f1ec;--sun:#d99a2b;--sun-bg:#fbf1dc;--leaf:#3f7d4e;--rose:#b23a48;--rose-bg:#f8e6e6;--god:#7b3fb8;--god-bg:#f2eafb;--admin:#1f7a8c;--admin-bg:#e3f2f5;--attn:#7a7fc9;--display:'Manrope',system-ui,-apple-system,'Segoe UI',sans-serif;--body:system-ui,-apple-system,'Segoe UI',sans-serif;--mono:ui-monospace,Menlo,Consolas,monospace;color-scheme:light dark}
@media (prefers-color-scheme:dark){:root{--review:#9296f5;--paper:#141413;--card:#1d1d1b;--ink:#ecebe6;--soft:#9c9a93;--line:#33322f;--indigo:#f0a35e;--indigo-bg:#2e2419;--slate:#9c9a93;--slate-bg:#22211f;--sun:#e5b454;--sun-bg:#2c2515;--leaf:#6cc08a;--rose:#f08a92;--rose-bg:#3a2022;--god:#c5a0f5;--god-bg:#2a2038;--admin:#6cc3d5;--admin-bg:#17292d;--attn:#9296f5}}
</style>
<script>
/* Landing demos start when scrolled into view, pause when scrolled away, replay on return */
window.lpView=function(el,enter,leave){if(!el||!('IntersectionObserver' in window))return enter();var on=false;
new IntersectionObserver(function(es){var v=es[0].isIntersecting;if(v===on)return;on=v;if(v)enter();else if(leave)leave()},{rootMargin:'0px 0px -30% 0px',threshold:0}).observe(el)};
</script>
</head>
<body>
<div class="wrap">
<div class="bar">
<a class="mark" href="/" aria-label="Diesel home"><svg class="wm" viewBox="0 0 140 36" aria-hidden="true"><path fill="var(--ink)" d="M5.18 24.2Q3.54 24.2 2.56 23.08Q1.58 21.96 1.58 20.06V16.96Q1.58 15.04 2.56 13.92Q3.54 12.8 5.18 12.8Q6.36 12.8 7.17 13.4Q7.98 14 8.22 15.08L8.16 12.54V9.4H10.32V24H8.18V21.92Q7.96 23 7.17 23.6Q6.38 24.2 5.18 24.2ZM5.94 22.32Q6.98 22.32 7.57 21.69Q8.16 21.06 8.16 19.9V17.08Q8.16 15.94 7.57 15.31Q6.98 14.68 5.94 14.68Q4.9 14.68 4.32 15.23Q3.74 15.78 3.74 16.98V20Q3.74 21.22 4.32 21.77Q4.9 22.32 5.94 22.32ZM13.62 24V22.04H17.44V14.96H14.02V13H19.6V22.04H23.14V24ZM18.34 11.1Q17.64 11.1 17.22 10.73Q16.8 10.36 16.8 9.74Q16.8 9.1 17.22 8.73Q17.64 8.36 18.34 8.36Q19.04 8.36 19.46 8.73Q19.88 9.1 19.88 9.74Q19.88 10.36 19.46 10.73Q19.04 11.1 18.34 11.1ZM30 15.96Q29.16 15.96 28.7 15.53Q28.24 15.1 28.24 14.38Q28.24 13.66 28.7 13.23Q29.16 12.8 30 12.8Q30.84 12.8 31.3 13.23Q31.76 13.66 31.76 14.38Q31.76 15.1 31.3 15.53Q30.84 15.96 30 15.96ZM30 24.2Q29.16 24.2 28.7 23.77Q28.24 23.34 28.24 22.62Q28.24 21.9 28.7 21.47Q29.16 21.04 30 21.04Q30.84 21.04 31.3 21.47Q31.76 21.9 31.76 22.62Q31.76 23.34 31.3 23.77Q30.84 24.2 30 24.2ZM42 24.2Q39.98 24.2 38.76 23.02Q37.54 21.84 37.54 19.8V17.2Q37.54 15.16 38.76 13.98Q39.98 12.8 42 12.8Q43.36 12.8 44.36 13.33Q45.36 13.86 45.91 14.82Q46.46 15.78 46.46 17.06V19.04H39.62V19.94Q39.62 21.1 40.26 21.74Q40.9 22.38 42 22.38Q42.9 22.38 43.5 22.05Q44.1 21.72 44.22 21.14H46.36Q46.14 22.54 44.95 23.37Q43.76 24.2 42 24.2ZM39.62 17.06V17.52H44.38V17.04Q44.38 15.82 43.76 15.16Q43.14 14.5 42 14.5Q40.86 14.5 40.24 15.17Q39.62 15.84 39.62 17.06ZM53.56 24.18Q51.66 24.18 50.58 23.32Q49.5 22.46 49.5 20.92H51.64Q51.64 21.62 52.14 22.01Q52.64 22.4 53.56 22.4H54.44Q55.38 22.4 55.9 22.01Q56.42 21.62 56.42 20.9Q56.42 19.64 55.08 19.46L52.18 19.06Q50.96 18.9 50.29 18.09Q49.62 17.28 49.62 15.98Q49.62 14.48 50.64 13.65Q51.66 12.82 53.52 12.82H54.42Q56.14 12.82 57.21 13.64Q58.28 14.46 58.34 15.8H56.18Q56.14 15.26 55.67 14.91Q55.2 14.56 54.42 14.56H53.52Q52.66 14.56 52.19 14.94Q51.72 15.32 51.72 15.96Q51.72 16.98 52.86 17.14L55.58 17.5Q58.52 17.9 58.52 20.88Q58.52 22.46 57.46 23.32Q56.4 24.18 54.44 24.18ZM66 15.96Q65.16 15.96 64.7 15.53Q64.24 15.1 64.24 14.38Q64.24 13.66 64.7 13.23Q65.16 12.8 66 12.8Q66.84 12.8 67.3 13.23Q67.76 13.66 67.76 14.38Q67.76 15.1 67.3 15.53Q66.84 15.96 66 15.96ZM66 24.2Q65.16 24.2 64.7 23.77Q64.24 23.34 64.24 22.62Q64.24 21.9 64.7 21.47Q65.16 21.04 66 21.04Q66.84 21.04 67.3 21.47Q67.76 21.9 67.76 22.62Q67.76 23.34 67.3 23.77Q66.84 24.2 66 24.2ZM78 24.2Q75.98 24.2 74.76 23.02Q73.54 21.84 73.54 19.8V17.2Q73.54 15.16 74.76 13.98Q75.98 12.8 78 12.8Q79.36 12.8 80.36 13.33Q81.36 13.86 81.91 14.82Q82.46 15.78 82.46 17.06V19.04H75.62V19.94Q75.62 21.1 76.26 21.74Q76.9 22.38 78 22.38Q78.9 22.38 79.5 22.05Q80.1 21.72 80.22 21.14H82.36Q82.14 22.54 80.95 23.37Q79.76 24.2 78 24.2ZM75.62 17.06V17.52H80.38V17.04Q80.38 15.82 79.76 15.16Q79.14 14.5 78 14.5Q76.86 14.5 76.24 15.17Q75.62 15.84 75.62 17.06ZM91.7 24Q90.14 24 89.21 23.09Q88.28 22.18 88.28 20.66V11.36H84.58V9.4H90.44V20.62Q90.44 21.28 90.8 21.66Q91.16 22.04 91.78 22.04H95.1V24Z"/><rect class="d2cur" x="98" y="7" width="2.2" height="21" fill="#3cc2ae"/><path fill="var(--soft)" d="M109.42 15.8Q108.68 15.8 108.29 15.39Q107.9 14.98 108 14.3Q108.1 13.62 108.63 13.21Q109.16 12.8 109.9 12.8Q110.66 12.8 111.04 13.21Q111.42 13.62 111.32 14.3Q111.22 14.98 110.7 15.39Q110.18 15.8 109.42 15.8ZM108.08 24.2Q107.34 24.2 106.95 23.79Q106.56 23.38 106.66 22.7Q106.76 22.02 107.29 21.61Q107.82 21.2 108.56 21.2Q109.32 21.2 109.7 21.61Q110.08 22.02 109.98 22.7Q109.88 23.38 109.36 23.79Q108.84 24.2 108.08 24.2ZM119.1 24.2Q118.12 24.2 117.44 23.68Q116.76 23.16 116.49 22.24Q116.22 21.32 116.4 20.12L116.9 16.9Q117.1 15.68 117.68 14.76Q118.26 13.84 119.1 13.32Q119.94 12.8 120.92 12.8Q122.04 12.8 122.68 13.43Q123.32 14.06 123.28 15.1H123.34L123.64 13H125.44L124.1 21.46Q124.04 21.86 124.26 22.11Q124.48 22.36 124.86 22.36H125.76L125.5 24H124.5Q123.52 24 123 23.36Q122.48 22.72 122.62 21.78Q122.24 22.88 121.29 23.54Q120.34 24.2 119.1 24.2ZM119.96 22.64Q120.96 22.64 121.65 21.93Q122.34 21.22 122.54 20L123 17Q123.18 15.78 122.71 15.07Q122.24 14.36 121.26 14.36Q120.26 14.36 119.56 15.07Q118.86 15.78 118.68 17L118.22 20Q118.04 21.22 118.51 21.93Q118.98 22.64 119.96 22.64ZM127.72 24 127.98 22.36H131.88L133.1 14.64H129.7L129.96 13H135.16L133.68 22.36H137.38L137.12 24ZM134.48 11.02Q133.82 11.02 133.5 10.68Q133.18 10.34 133.26 9.76Q133.36 9.16 133.79 8.81Q134.22 8.46 134.88 8.46Q135.54 8.46 135.87 8.81Q136.2 9.16 136.1 9.76Q136.02 10.34 135.58 10.68Q135.14 11.02 134.48 11.02Z"/></svg></a>
<nav aria-label="Site">
<a class="btn signup" href="/signup?next=/home">Sign up</a><a class="btn login" id="login" href="/sso/login?next=/home">Log in</a>
</nav>
</div>
<header class="hero2" style="padding-top:4px;padding-bottom:0">
<div class="ladder" aria-label="How fast" style="margin-bottom:8px">
<div class="rungs">
<a class="rung plain" href="/app/Landing-hero"><span class="lv">Hero</span><span class="sp">Hobby apps</span><span class="rl">Your AI makes your app</span></a>
<a class="rung" href="/app/Landing-creator"><span class="lv">Creator</span><span class="sp">10x</span><span class="rl">Bigger apps, no code</span></a>
<a class="rung" href="/"><span class="lv">Pro</span><span class="sp">50x</span><span class="rl">For architects and teams</span></a>
<a class="rung hi" href="#d2-master-sec"><span class="lv">Master</span><span class="sp">?x</span><span class="rl">How fast can a team of agents go?</span></a>
</div>
<p class="sub" style="margin:12px 0 0">Your AI builds working apps, with their data, in minutes. You pick the complexity. Start below to <a href="/app/Landing-hero">learn</a>, <a href="/app/Landing-creator">play</a> or <a href="/">work</a>.</p>
</div>
</header>
</div>
<style>
/* P-1284: a level's header kept small over its animation (razie 2026-10-11: heading and gray on the left, start/watch under) */
.lp-top{margin:0 0 14px;display:grid;grid-template-columns:1fr auto;gap:12px 32px;align-items:end}
.lp-top .stat{margin:0;flex-direction:column;gap:2px;align-items:flex-start}
.lp-top .stat .big{font-size:calc(30px*var(--fz,1))}
.lp-top .stat .small{font-size:calc(13px*var(--fz,1))}
@media(max-width:700px){.lp-top{grid-template-columns:1fr}}
.door .lp-top h2,#hero.door .lp-top h2,#creator.door .lp-top h2,#pro.door .lp-top h2,#d2-master-sec .lp-top h2{font-size:clamp(20px,2.3vw,26px);line-height:1.15;margin:0 0 4px}
.door .lp-top .who,#d2-master-sec .lp-top .who{font-size:calc(15px*var(--fz,1));margin:0 0 10px}
#d2-master-sec .lp-top .cta{margin-top:10px}
.lp-top .doors{margin:0;display:flex;gap:8px;flex-wrap:wrap}
.lp-top .doors .btn{padding:6px 14px;font-size:calc(14px*var(--fz,1))}
/* one column: heading, gray line, then buttons left and the stat right on one row (razie 2026-10-11: "finish hero") */
.lp-top.lp-one{display:block}
.lp-one .lp-row{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px 24px}
.lp-one .stat{flex-direction:row;align-items:baseline;gap:10px;flex-wrap:wrap}
.lp-one .stat .big{font-size:calc(24px*var(--fz,1))}
.lp-one .stat .small{max-width:none}
</style>
<style>
/* testimonials as a coloured blockquote (razie 2026-10-11: "like a blockquote thing? add some color to it somehow") */
.lp-quote{position:relative;margin:0;max-width:820px;padding:18px 22px 18px 56px;border-left:4px solid var(--indigo);border-radius:0 14px 14px 0;background:color-mix(in srgb,var(--indigo) 12%,transparent)}
.lp-quote::before{content:"\201C";position:absolute;left:14px;top:-6px;font-family:var(--display);font-weight:800;font-size:calc(72px*var(--fz,1));line-height:1;color:var(--indigo)}
.lp-quote q{quotes:none}
.lp-quote + .who{margin:10px 0 0 4px;color:var(--indigo)}
</style>
<style>
/* a full-page animation in its own frame: fixed height, since it sizes itself to the frame (100vh) */
.lp-anim{height:640px}
@media(max-width:760px){.lp-anim{height:1000px}}
</style>
<span id="master"></span>
<!-- d2 landing, Master section (designer, 2026-09-28, Razie approved option B + tabs; Manage tab added 2026-09-28).
Self-contained: scoped to #d2-master-sec. The copy side uses the landing's own colours
(CSS vars with fallbacks); the picture side is always dark. Wire the two buttons' hrefs. -->
<section id="d2-master-sec" aria-labelledby="d2ms-h">
<style>
#d2-master-sec{padding:40px 16px}
#d2-master-sec .card{max-width:1080px;margin:0 auto;display:flex;flex-wrap:wrap;gap:28px;align-items:flex-start}
#d2-master-sec .copy{flex:1 1 300px;min-width:0}
#d2-master-sec .pic{flex:1 1 360px;min-width:0}
#d2-master-sec .card[style] .pic{max-width:820px;margin:0 auto}
#d2-master-sec .kick{font-size:13px;letter-spacing:.08em;text-transform:uppercase;color:var(--soft,#777);margin:0 0 8px}
#d2-master-sec h2{font-size:clamp(26px,4vw,36px);font-weight:700;line-height:1.15;margin:0 0 16px;color:var(--ink,#1d1d1b)}
#d2-master-sec ul{list-style:none;margin:0 0 22px;padding:0}
#d2-master-sec li{font-size:16px;line-height:1.5;margin:0 0 12px;color:var(--ink,#1d1d1b)}
#d2-master-sec li b{font-weight:700}
#d2-master-sec .cta{display:flex;gap:10px;flex-wrap:wrap}
#d2-master-sec .cta a{display:inline-block;padding:10px 18px;border-radius:999px;font-size:15px;text-decoration:none;border:1.5px solid var(--sun,#f2b84b);color:var(--ink,#1d1d1b)}
#d2-master-sec .cta a.primary{background:var(--sun,#f2b84b);color:#1d1d1b}
#d2-master-sec .dark{background:#16181d;border-radius:16px;padding:14px;color:#eceae4;font-family:system-ui,-apple-system,sans-serif;color-scheme:dark}
#d2-master-sec .tabs{display:flex;gap:6px;flex-wrap:wrap;margin:0 0 12px}
#d2-master-sec .tabs button{background:transparent;border:1px solid #3a3f4a;color:#a8abb2;font:inherit;font-size:13px;padding:5px 12px;border-radius:999px;min-height:32px;cursor:pointer}
#d2-master-sec .tabs button[aria-selected="true"]{background:#23265a;border-color:#9296f5;color:#eceae4}
#d2-master-sec .body{min-height:280px}
#d2-master-sec svg{width:100%;height:auto;display:block}
#d2-master-sec .msg{border-radius:12px;padding:10px 12px;margin:0 0 10px;font-size:14px;line-height:1.5}
#d2-master-sec .who{font-size:12px;color:#a8abb2;margin-bottom:3px}
#d2-master-sec .you{background:#3a2a0e;border:1px solid #f2b84b;margin-left:28px}
#d2-master-sec .ag{background:#23265a;border:1px solid #9296f5;margin-right:28px}
#d2-master-sec .gd{background:#10291f;border:1px solid #46c48e;margin-right:28px}
#d2-master-sec .try{display:inline-block;margin-top:4px;font-size:13px;color:#9296f5}
#d2-master-sec .pm{margin:0 0 10px}
#d2-master-sec .rows{display:flex;flex-direction:column;gap:6px;font-size:13px;line-height:1.4}
#d2-master-sec .row{border:1px solid #2c3039;border-radius:10px;padding:8px 10px;display:flex;gap:8px;align-items:flex-start}
#d2-master-sec .row .t{flex:1;min-width:0}
#d2-master-sec .row .m{color:#a8abb2;font-size:11px}
#d2-master-sec .ps{border-radius:999px;padding:1px 8px;font-size:11px;white-space:nowrap}
#d2-master-sec .ps-rv{background:#5a1f3a;color:#f4a6c6}#d2-master-sec .ps-ip{background:#1f4a38;color:#8fe0b8}#d2-master-sec .ps-wt{background:#4a3510;color:#f2c46b}#d2-master-sec .ps-nw{background:#2c3039;color:#c9ccd2}
#d2-master-sec .ok{border:1px solid #3a3f4a;border-radius:6px;padding:0 7px;color:#46c48e}
#d2-master-sec .pk{color:#a8abb2;font-size:12px;padding:2px 4px}
#d2-master-sec{padding-bottom:0!important}
</style>
<div class="wrap"><div class="lp-top" style="margin:0">
<div>
<h2 id="d2ms-h">Work at the speed of thought.</h2>
<p class="who">Set up your team of AI agents, point them, and step in any time.</p>
<div class="cta"><a class="primary" href="https://d2master.aiputty.com" data-wire="see-it-live">See it live</a><a href="/sso/login?next=/home%3Flevel%3Dmaster" data-wire="start-master">Start a Master project</a></div>
</div>
</div></div>
</section>
<!-- Voice to a running app (designer, Razie approved 2026-10-05, from Landing3 Artifact 6). Self-contained iframe. -->
<section id="voice-to-app" style="max-width:1080px;margin:24px auto 8px;padding:0 16px">
<iframe id="v2a-f" title="From voice to a running app" style="width:100%;border:0;display:block;height:760px;background:transparent" srcdoc="<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>From voice to a running app</title>
<style>
:root{--paper:#fbfaf7;--card:#ffffff;--ink:#1d1d1b;--soft:#6b6a66;--line:#e4e1da;--indigo:#9a4b12;--sun:#d99a2b;--sun-bg:#fbf1dc;--leaf:#3f7d4e;--rose:#b23a48;--attn:#5b5fd6;--me:#5b5fd6}
@media (prefers-color-scheme:dark){:root{--paper:#141413;--card:#1d1d1b;--ink:#ecebe6;--soft:#9c9a93;--line:#33322f;--indigo:#f0a35e;--sun:#e5b454;--sun-bg:#2c2515;--leaf:#6cc08a;--rose:#f08a92;--attn:#9296f5;--me:#6b6fe0}}
*{box-sizing:border-box}
html,body{margin:0;background:var(--paper);color:var(--ink);font:14px/1.45 system-ui,-apple-system,'Segoe UI',sans-serif}
.w{max-width:1040px;margin:0 auto;padding:14px}
.top{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);gap:14px;align-items:stretch}
.chat{background:var(--card);border:1px solid var(--line);border-radius:18px;padding:12px;display:flex;flex-direction:column}
.hd{font:600 11px system-ui;color:var(--soft);letter-spacing:.05em;text-transform:uppercase;margin:0 2px 8px}
.tk{display:flex;flex-direction:column;gap:7px;height:190px;flex:none;overflow-y:auto;scroll-behavior:smooth;padding-right:2px}
.tk>*{flex:none}
.b{max-width:92%;padding:8px 12px;border-radius:15px;font-size:13.5px;line-height:1.35;animation:pop .35s ease-out}
.b.me{align-self:flex-end;background:var(--me);color:#fff;border-bottom-right-radius:5px}
.b.ai{align-self:flex-start;background:var(--paper);border:1px solid var(--line);border-bottom-left-radius:5px}
.b.ai small{display:block;font-size:11px;color:var(--soft)}
.mic{display:flex;align-items:center;gap:10px;margin-top:10px;padding:6px 10px;border:1px solid var(--line);border-radius:999px;background:var(--paper)}
.mic .mb{flex:none;width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--card);border:1px solid var(--line);color:var(--soft)}
.mic.on .mb{background:#e5484d;border-color:#e5484d;color:#fff;animation:mp 1.2s ease-out infinite}
.mic .wave{flex:1;display:flex;align-items:center;gap:3px;height:24px}
.mic .wave i{flex:1;max-width:5px;height:4px;border-radius:3px;background:var(--line)}
.mic.on .wave i{background:var(--attn);animation:mbar .9s ease-in-out infinite}
.mic .ml{flex:none;font:600 11px system-ui;color:var(--soft);min-width:64px;text-align:right}
@keyframes mbar{0%,100%{height:4px}50%{height:var(--h,20px)}}
@keyframes mp{0%{box-shadow:0 0 0 0 rgba(229,72,77,.5)}100%{box-shadow:0 0 0 9px rgba(229,72,77,0)}}
@keyframes pop{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.agents{background:var(--card);border:1px solid var(--line);border-radius:18px;padding:12px 12px 6px;margin-left:12px;display:flex;flex-direction:column}
.agents svg{width:100%;height:auto;display:block}
.msg{min-height:26px;margin-top:4px;display:flex;justify-content:center}
.msg span{display:inline-flex;align-items:center;gap:8px;padding:3px 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--attn) 55%,transparent);background:color-mix(in srgb,var(--attn) 12%,var(--card));font-size:12px;opacity:0;transition:opacity .35s}
.msg span.on{opacity:1}
.msg i{width:7px;height:7px;border-radius:50%;background:var(--attn);animation:pl 1s ease-in-out infinite}
@keyframes pl{50%{opacity:.3}}
.low{position:relative;margin-top:14px;height:330px}
.board{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}
.col{background:color-mix(in srgb,var(--line) 35%,var(--paper));border:1px solid var(--line);border-radius:10px;padding:8px;height:330px;overflow:hidden;transition:opacity .6s}
.board.half .c3,.board.half .c4{opacity:0}
.board.gone .c1,.board.gone .c2{opacity:0}
.col h4{margin:0 0 8px;font-size:12.5px;display:flex;justify-content:space-between}
.col h4 small{color:var(--soft);font-weight:400}
.cards{display:flex;flex-direction:column;gap:7px}
.card{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:7px 9px;font-size:12px;animation:pop .4s ease-out;transition:opacity .45s,transform .45s}
.card.out{opacity:0;transform:translateX(30px)}
.card .h{display:flex;align-items:center;gap:6px}
.card .id{font:600 11px ui-monospace,Menlo,monospace;color:var(--indigo)}
.card .st{margin-left:auto;font-size:10px;color:var(--soft)}
.card .t{font-weight:600;margin-top:2px}
.card.work{background:color-mix(in srgb,var(--leaf) 9%,var(--card))}
.card.done .st{color:var(--leaf);font-weight:600}
.side{position:absolute;top:0;right:0;bottom:0;width:calc(50% - 5px);background:var(--card);border:1px solid var(--line);border-radius:12px;padding:12px;opacity:0;transition:opacity .6s;overflow:hidden}
.side.on{opacity:1}
.pane{position:absolute;inset:12px;transition:opacity .6s}
.pane.off{opacity:0}
.doc{border:1px solid var(--line);border-radius:10px;padding:10px 12px;background:var(--paper)}
.doc .ti{font-weight:700;font-size:14px;margin-bottom:8px}
.sec{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:10px;border:1px solid var(--line);background:var(--card);margin-top:8px;animation:pop .45s ease-out}
.sec .tag{flex:none;font:600 10.5px system-ui;padding:2px 8px;border-radius:999px;color:#fff}
.sec .tx{flex:1;font-size:13px}
.sec .cnt{font-weight:700;font-variant-numeric:tabular-nums}
.ln{height:7px;border-radius:4px;background:var(--line);margin:6px 0;width:0;transition:width .7s}
.dm svg{width:100%;height:auto;display:block}
.dm .draw{stroke-dasharray:200;stroke-dashoffset:200;animation:dr 1s ease-out forwards}
@keyframes dr{to{stroke-dashoffset:0}}
.dm .bx{opacity:0;animation:pop .45s ease-out forwards}
.side h5{margin:0 0 10px;font-size:12.5px;display:flex;justify-content:space-between;align-items:center}
.side h5 small{font-weight:400;color:var(--soft)}
.ent{border:1.5px solid var(--sun);background:var(--sun-bg);border-radius:9px;padding:6px 9px;margin-bottom:8px;animation:pop .45s ease-out}
.ent b{font-size:12.5px}
.ent .f{font-size:11.5px;color:var(--soft)}
.ent .f span{animation:pop .4s ease-out}
.lk{font-size:11px;color:var(--indigo);margin:-4px 0 8px 10px;animation:pop .4s ease-out}
.tr{display:flex;align-items:center;gap:8px;padding:6px 0;border-bottom:1px solid var(--line);font-size:12.5px;animation:pop .35s ease-out}
.tr .r{flex:none;width:20px;height:20px;border-radius:50%;border:2px solid var(--line);border-top-color:var(--attn);animation:sp .8s linear infinite}
.tr.ok .r{animation:none;border:none;background:var(--leaf);color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px}
.tr.ok .r:after{content:"✓"}
.tr .x{flex:1}
.sum{margin-top:10px;font-size:12.5px;font-weight:600;color:var(--leaf);opacity:0;transition:opacity .4s}
.sum.on{opacity:1}
@keyframes sp{to{transform:rotate(360deg)}}
.app{position:absolute;top:0;left:0;bottom:0;width:calc(50% - 5px);border:1px solid var(--line);border-radius:12px;overflow:hidden;background:var(--card);display:flex;flex-direction:column;opacity:0;transform:scale(1.02);transition:opacity .7s,transform .7s;pointer-events:none}
.app.on{opacity:1;transform:none;pointer-events:auto}
.chrome{display:flex;align-items:center;gap:8px;padding:7px 10px;border-bottom:1px solid var(--line);font-size:11.5px;color:var(--soft)}
.chrome .dt{width:8px;height:8px;border-radius:50%;background:var(--line)}
.chrome .pill{margin-left:auto;font:600 10.5px system-ui;padding:2px 9px;border-radius:999px;background:#3ecf8e;color:#06120c}
.ap{padding:16px;flex:1;background:color-mix(in srgb,var(--attn) 5%,var(--card))}
.ap .k{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--soft)}
.ap h3{margin:2px 0 4px;font-size:19px}
.ap .meta{font-size:12.5px;color:var(--soft);margin-bottom:12px}
.full{display:inline-block;font:600 11px system-ui;padding:2px 9px;border-radius:999px;background:color-mix(in srgb,var(--rose) 15%,var(--card));color:var(--rose);margin-left:6px}
.place{border:1.5px solid var(--attn);border-radius:12px;padding:12px;background:var(--card)}
.place .n{font-size:28px;font-weight:700;color:var(--attn);line-height:1}
.place .s{font-size:12.5px;color:var(--soft)}
.line{display:flex;gap:6px;margin:10px 0 2px}
.line i{flex:1;height:8px;border-radius:4px;background:var(--line)}
.line i.me{background:var(--attn)}
.offer{margin-top:12px;border:1px dashed var(--leaf);border-radius:10px;padding:9px 11px;font-size:12.5px;opacity:0;transition:opacity .5s}
.offer.on{opacity:1}
.offer b{color:var(--leaf)}
.btn{display:inline-block;margin-top:8px;padding:6px 14px;border-radius:999px;background:var(--attn);color:#fff;font:600 12.5px system-ui}
.ctl{display:flex;justify-content:flex-end;margin-top:10px}
.ctl button{border:1px solid var(--line);background:var(--card);color:var(--ink);font:600 12.5px system-ui;padding:5px 14px;border-radius:999px;cursor:pointer;min-height:32px}
@media (max-width:700px){.top{grid-template-columns:minmax(0,1fr)}.agents{margin-left:0}.board{grid-template-columns:repeat(2,minmax(0,1fr))}.c3,.c4{display:none}.low{height:690px}.side{top:auto;height:340px;width:100%}.app{bottom:auto;height:340px;width:100%}}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
</style></head><body><div class="w">
<div class="top">
<div class="chat"><div class="hd">You and your AI</div><div class="tk" id="tk"></div>
<div class="mic" id="mic"><span class="mb"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="9" y="3" width="6" height="11" rx="3"/><path d="M5 11a7 7 0 0 0 14 0M12 18v3"/></svg></span><span class="wave" id="wave"></span><span class="ml" id="ml">tap to talk</span></div>
</div>
<div class="agents"><div class="hd">Your agents</div><div id="map"></div><div class="msg"><span id="msg"><i></i><b id="msgt"></b></span></div></div>
</div>
<div class="low">
<div class="board" id="board">
<div class="col c1"><h4>New <small id="n0"></small></h4><div class="cards" id="c0"></div></div>
<div class="col c2"><h4>In progress <small id="n1"></small></h4><div class="cards" id="c1"></div></div>
<div class="col c3"><h4>Review <small id="n2"></small></h4><div class="cards" id="c2"></div></div>
<div class="col c4"><h4>Done <small id="n3"></small></h4><div class="cards" id="c3"></div></div>
</div>
<div class="side" id="side"><div class="pane" id="pSpec"></div><div class="pane off" id="pDm"></div><div class="pane off" id="pTest"></div></div>
<div class="app" id="app">
<div class="chrome"><span class="dt"></span><span class="dt"></span><span class="dt"></span><span>northconf.aiputty.com/sessions/agents</span><span class="pill">live</span></div>
<div class="ap"><div class="k">NorthConf · AI agents in practice · Thu 2 pm</div><h3>Join the Waitlist<span class="full">Full</span></h3><div class="meta">Room B · 120 seats · 14 on the waitlist</div>
<div class="place"><div class="s">You're on the waitlist</div><div class="n">#2</div><div class="s">in line</div><div class="line"><i></i><i class="me"></i><i></i><i></i><i></i><i></i></div></div>
<div class="offer" id="offer"><b>A seat just freed up.</b> It's yours for 24 hours.<br><span class="btn">Take the seat</span></div>
</div>
</div>
</div>
<div class="ctl"><button id="rp" type="button">Watch it again</button></div>
</div>
<script>
(function(){
var $=function(i){return document.getElementById(i)};
var wave=$('wave');for(var i=0;i<16;i++){var b=document.createElement('i');b.style.setProperty('--h',(8+Math.round(Math.abs(Math.sin(i*1.7))*16))+'px');b.style.animationDelay=(i*0.06)+'s';wave.appendChild(b)}
var COL={you:['#fbf1dc','#d99a2b','#633806'],up:'#6b7fd7',idle:'#9aa3b2',working:'#2f9a6f',listening:'#2f9a6f',waiting:'#d9a520',done:'#1f6b4c'};
var NS='http://www.w3.org/2000/svg';
function el(n,a,t){var e=document.createElementNS(NS,n);for(var k in a)e.setAttribute(k,a[k]);if(t!=null)e.textContent=t;return e}
function map(st){var h=$('map');h.innerHTML='';var svg=el('svg',{viewBox:'0 0 380 110',role:'img','aria-label':'You, designer, coder and guardian'});
var d=el('defs',{}),m=el('marker',{id:'ar',viewBox:'0 0 10 10',refX:8,refY:5,markerWidth:6,markerHeight:6,orient:'auto'});m.appendChild(el('path',{d:'M0 0L10 5L0 10z',fill:'#9c9a93'}));d.appendChild(m);svg.appendChild(d);
var N=[['you','you',st.you],['designer','D',st.designer],['coder','C',st.coder],['guardian','G',st.guardian]],x=40;
N.forEach(function(n,i){var cx=40+i*100;if(i)svg.appendChild(el('path',{d:'M'+(cx-75)+' 44H'+(cx-27),stroke:'#9c9a93','stroke-width':1.5,fill:'none','marker-end':'url(#ar)'}));
var s=n[2];
if(i===0)svg.appendChild(el('circle',{cx:cx,cy:44,r:23,fill:COL.you[0],stroke:COL.you[1],'stroke-width':1.5}));
else if(s)svg.appendChild(el('circle',{cx:cx,cy:44,r:23,fill:COL[s]||'#9aa3b2'}));
else svg.appendChild(el('circle',{cx:cx,cy:44,r:23,fill:'none',stroke:'#9c9a93','stroke-width':1.5,'stroke-dasharray':'3 3'}));
if(s==='working'&&i){var r=el('circle',{cx:cx,cy:44,r:23,fill:'none',stroke:COL.working,'stroke-width':2});r.appendChild(el('animate',{attributeName:'r',values:'23;31',dur:'1.4s',repeatCount:'indefinite'}));r.appendChild(el('animate',{attributeName:'opacity',values:'.8;0',dur:'1.4s',repeatCount:'indefinite'}));svg.appendChild(r)}
svg.appendChild(el('text',{x:cx,y:48,'text-anchor':'middle','font-size':12,fill:i===0?COL.you[2]:(s?'#fff':'#9c9a93')},n[1]));
svg.appendChild(el('text',{x:cx,y:86,'text-anchor':'middle','font-size':12,fill:'currentColor'},i===0?'you':n[0]));
svg.appendChild(el('text',{x:cx,y:101,'text-anchor':'middle','font-size':11,fill:i===0?COL.you[1]:(s?COL[s]:'#9c9a93')},i===0?(s||''):(s||'not started')));
});h.appendChild(svg)}
var IT={a:['P-21','Waitlist: sessions and seats'],b:['P-22','Offer a freed seat for 24 h'],c:['P-23','Show your place in line'],
s1:['P-17','Speaker badges with QR check-in'],s2:['P-14','Room map on the schedule'],s3:['P-12','Ticket refunds'],s4:['P-11','Session feedback form'],s5:['P-9','Schedule export to calendar']};
var cards={};
function counts(){for(var i=0;i<4;i++)$('n'+i).textContent=$('c'+i).children.length||''}
function card(k,c,st,cls){var d=cards[k];if(d&&d.parentNode)d.parentNode.removeChild(d);d=document.createElement('div');d.className='card '+(cls||'');d.innerHTML='<div class="h"><span class="id">'+IT[k][0]+'</span><span class="st">'+st+'</span></div><div class="t">'+IT[k][1]+'</div>';$(c).appendChild(d);cards[k]=d;counts();return d}
function say(t){var s=$('msg');$('msgt').textContent=t;s.classList.add('on')}
function bub(cls,t,who){var b=document.createElement('div');b.className='b '+cls;b.innerHTML=(who?'<small>'+who+'</small>':'')+t;var tk=$('tk');tk.appendChild(b);tk.scrollTop=tk.scrollHeight}
function mic(on,l){$('mic').classList.toggle('on',on);$('ml').textContent=l}
function pane(id){['pSpec','pDm','pTest'].forEach(function(p){$(p).classList.toggle('off',p!==id)})}
function sec(tag,col,txt,n){var d=document.createElement('div');d.className='sec';d.innerHTML='<span class="tag" style="background:'+col+'">'+tag+'</span><span class="tx">'+txt+'</span><span class="cnt">0</span>';$('specDoc').appendChild(d);var c=d.querySelector('.cnt'),i=0;var t=setInterval(function(){i++;c.textContent=i;if(i>=n)clearInterval(t)},260)}
function specInit(){$('pSpec').innerHTML='<div class="hd">Designer · writing it up</div><div class="doc" id="specDoc"><div class="ti">Waitlist</div><div class="ln" id="l1"></div><div class="ln" id="l2"></div></div>'}
function dmDraw(){$('pDm').innerHTML='<div class="hd">Domain model</div><div class="dm"><svg viewBox="0 0 320 250" font-family="system-ui,sans-serif">'+
'<g stroke="var(--indigo)" stroke-width="1.5" fill="none"><path class="draw" style="animation-delay:.9s" d="M110 52H200"/><path class="draw" style="animation-delay:1.3s" d="M70 76V150"/><path class="draw" style="animation-delay:1.7s" d="M110 174H200"/></g>'+
'<g font-size="10" fill="var(--indigo)"><text x="155" y="46" text-anchor="middle" class="bx" style="animation-delay:1.1s">seats *</text><text x="76" y="118" class="bx" style="animation-delay:1.5s">waitlist *</text><text x="155" y="168" text-anchor="middle" class="bx" style="animation-delay:1.9s">attendee</text></g>'+
box(20,28,'Session','title, room, seats',0)+box(200,28,'Seat','attendee',.3)+box(20,150,'WaitlistEntry','place, offeredUntil',.6)+box(200,150,'Attendee','name, email',.9)+
'</svg></div>'}
function box(x,y,n,f,dl){return '<g class="bx" style="animation-delay:'+dl+'s"><rect x="'+x+'" y="'+y+'" width="'+(n.length>8?118:100)+'" height="48" rx="9" fill="var(--sun-bg)" stroke="var(--sun)" stroke-width="1.5"/><text x="'+(x+10)+'" y="'+(y+20)+'" font-size="13" font-weight="700" fill="var(--ink)">'+n+'</text><text x="'+(x+10)+'" y="'+(y+37)+'" font-size="10.5" fill="var(--soft)">'+f+'</text></g>'}
function test(t){var r=document.createElement('div');r.className='tr';r.innerHTML='<span class="r"></span><span class="x">'+t+'</span>';$('pTest').appendChild(r);return r}
var TESTS=['A full session takes a waitlist entry','A freed seat goes to the next in line','The offer expires after 24 hours','Your place in line updates','Nobody is offered the same seat twice'];
var trs=[];
var S=[
[900,function(){mic(true,'listening…');map({you:'',designer:'listening',coder:'idle',guardian:''});say('designer is listening')}],
[1500,function(){bub('me','Our sessions keep selling out. Add a waitlist.')}],
[1500,function(){mic(false,'thinking…');bub('ai','When a seat frees up, offer it to the next person for 24 hours?','designer')}],
[1600,function(){mic(true,'listening…')}],
[1300,function(){bub('me','Yes. And show people their place in line.')}],
[1300,function(){mic(false,'tap to talk');bub('ai','Got it. Three items for the team.','designer');map({you:'',designer:'working',coder:'idle',guardian:''});say('designer is filing the items')}],
[600,function(){card('a','c0','new')}],[500,function(){card('b','c0','new')}],[500,function(){card('c','c0','new')}],
[1000,function(){map({you:'',designer:'working',coder:'idle',guardian:''});say('designer is writing the spec');$('board').classList.add('half');specInit();pane('pSpec');$('side').classList.add('on')}],
[500,function(){$('l1').style.width='80%'}],[400,function(){$('l2').style.width='55%'}],
[700,function(){sec('Spec','#5b5fd6','1 feature added',1)}],
[1100,function(){sec('Design','#b06a1c','4 behaviours added',4)}],
[1500,function(){sec('Test','#2f9a6f','5 tests added',5)}],
[2200,function(){dmDraw();pane('pDm');say('designer drafts the domain model')}],
[3200,function(){map({you:'',designer:'done',coder:'working',guardian:''});say('coder took P-21, P-22, P-23');['a','b','c'].forEach(function(k){card(k,'c1','in progress','work')});$('pTest').innerHTML='<div class="hd">Tests · run by the coder</div>';pane('pTest');trs=[]}],
[500,function(){trs.push(test(TESTS[0]))}],[450,function(){trs.push(test(TESTS[1]))}],[450,function(){trs.push(test(TESTS[2]))}],[450,function(){trs.push(test(TESTS[3]))}],[450,function(){trs.push(test(TESTS[4]))}],
[700,function(){trs[0].classList.add('ok')}],[420,function(){trs[1].classList.add('ok')}],[420,function(){trs[2].classList.add('ok')}],[420,function(){trs[3].classList.add('ok')}],[420,function(){trs[4].classList.add('ok');var s=document.createElement('div');s.className='sum';s.textContent='5 of 5 pass';$('pTest').appendChild(s);setTimeout(function(){s.classList.add('on')},30)}],
[900,function(){map({you:'',designer:'done',coder:'done',guardian:'working'});say('guardian: app and tests match the spec')}],
[1200,function(){['a','b','c'].forEach(function(k){card(k,'c1','done','done')})}],
[800,function(){['a','b','c'].forEach(function(k,i){setTimeout(function(){cards[k].classList.add('out')},i*220)})}],
[1000,function(){['a','b','c'].forEach(function(k){var c=cards[k];if(c&&c.parentNode)c.parentNode.removeChild(c)});counts();$('board').classList.add('gone');$('app').classList.add('on');map({you:'1 to look at',designer:'done',coder:'done',guardian:'done'});say('live: the waitlist is in the app')}],
[2200,function(){$('offer').classList.add('on')}],
[6000,null]
];
function seed(){card('s1','c0','new');card('s2','c1','in progress','work');card('s3','c2','review');card('s4','c3','done','done');card('s5','c3','done','done')}
var k=0,tm=null;
function reset(){clearTimeout(tm);k=0;$('tk').innerHTML='';['c0','c1','c2','c3'].forEach(function(c){$(c).innerHTML=''});cards={};seed();$('side').classList.remove('on');pane('pSpec');$('board').classList.remove('half');$('board').classList.remove('gone');$('app').classList.remove('on');$('offer').classList.remove('on');$('msg').classList.remove('on');mic(false,'tap to talk');map({you:'',designer:'idle',coder:'idle',guardian:''})}
function run(){if(k>=S.length){reset();tm=setTimeout(run,800);return}var s=S[k];tm=setTimeout(function(){if(s[1])s[1]();k++;run()},s[0])}
$('rp').addEventListener('click',function(){reset();run()});
reset();run();
})();
</script></body></html>
"></iframe>
<script>(function(){var f=document.getElementById("v2a-f");function fit(){try{var d=f.contentDocument;if(d&&d.body)f.style.height=(d.documentElement.scrollHeight+4)+"px"}catch(e){}}f.addEventListener("load",function(){fit();setInterval(fit,1500)})})()</script>
</section>
<!-- Pro: System view, new animation (P-1284, razie 2026-10-11: "for pro add smth about systemview: spec/design… test in sync, indexed - start from a feature in a ticket say, open system view and line up spec/design/ui behavior and test") -->
<section class="door t1 extra" id="pro-systemview">
<div class="wrap">
<span class="badge">System view</span>
<h2>Spec-driven. Every layer, lined up.</h2>
<p>Spec, design, pages and tests stay in sync, indexed by one code per behaviour. Start from a feature in a ticket, open the <b>System view</b>, and every layer lines up on one row: what it should do, how it's designed, where it shows in the app, and the test that proves it. Change one and the rest show what's out of step.</p>
<div style="margin-top:16px">
<div id="sva">
<style>
#sva{font:13px/1.4 system-ui,-apple-system,Segoe UI,sans-serif;color:#ecebe6;background:#141413;border:1px solid #33322f;border-radius:14px;padding:14px;max-width:900px;margin:auto;position:relative;overflow:hidden;min-height:330px;box-sizing:border-box}
#sva *{box-sizing:border-box}
#sva .tk{display:flex;align-items:center;gap:10px;border:1px solid #33322f;background:#1d1d1b;border-radius:10px;padding:8px 10px}
#sva .tk .id{color:#9c9a93;font-size:12px}#sva .tk b{flex:1}
#sva .chip{display:inline-block;border-radius:999px;padding:1px 8px;font-size:11px;border:1px solid #4a4945;color:#cfcdc6}
#sva .chip.f{border-color:#c47a3a;color:#f0a868}
#sva .btn{border:1px solid #4a4945;border-radius:7px;padding:3px 10px;font-size:12px;background:#22211f;color:#ecebe6;transition:transform .15s,background .3s}
#sva .btn.press{transform:scale(.9);background:#3a2a1c}
#sva .sv{margin-top:12px;opacity:0;transform:translateY(8px);transition:all .5s}
#sva .sv.on{opacity:1;transform:none}
#sva .hd{display:flex;align-items:center;gap:8px;margin-bottom:8px;color:#9c9a93;font-size:11px;letter-spacing:.06em}
#sva .grid{display:grid;grid-template-columns:110px repeat(4,minmax(0,1fr));gap:6px}
#sva .ch{font-size:10px;letter-spacing:.08em;color:#9c9a93;padding:0 4px}
#sva .code{font:12px ui-monospace,Menlo,monospace;color:#f0a868;padding:8px 4px;align-self:center}
#sva .cell{background:#1d1d1b;border:1px solid #33322f;border-radius:8px;padding:7px 8px;font-size:12px;min-height:52px;opacity:0;transform:translateX(-14px);transition:all .45s}
#sva .cell.in{opacity:1;transform:none}
#sva .cell small{display:block;color:#9c9a93;font-size:10px;margin-bottom:2px}
#sva .cell.ok{border-color:#3b6d41}#sva .cell.warn{border-color:#c99a2e;background:#2a2312}
#sva .mk{float:right;font-size:11px}
#sva .row-hl{outline:2px solid #c47a3a;outline-offset:2px;border-radius:8px}
#sva .st{margin-top:10px;font-size:12px;color:#9c9a93;min-height:18px}
#sva .st b{color:#8fd19a}#sva .st i{color:#e5c06a;font-style:normal}
@media(max-width:640px){#sva .grid{grid-template-columns:70px repeat(2,minmax(0,1fr))}#sva .c3,#sva .c4{display:none}}
</style>
<div class="tk"><span class="id">P-1290</span><b>Refunds: allow partial refunds</b><span class="chip f">#refund</span><span class="btn" id="sva-open">System view</span></div>
<div class="sv" id="sva-sv">
<div class="hd">SYSTEM VIEW · FEATURE <span class="chip f">#refund</span></div>
<div class="grid" id="sva-g">
<div></div><div class="ch">SPEC</div><div class="ch">DESIGN</div><div class="ch c3">UI</div><div class="ch c4">TEST</div>
</div>
<div class="st" id="sva-st"></div>
</div>
<script type="text/lazy">
(()=>{const $=i=>document.getElementById("sva-"+i),sl=ms=>new Promise(r=>setTimeout(r,ms));
const rows=[["^refund-1",["A paid order can be refunded.","Order.state paid → refunded; one rule.","Order page: Refund button.","REFUND-1 paid order refunds"]],
["^refund-2",["A refund puts the items back in stock.","OrderLine.qty → Product.stock +qty.","Stock column updates live.","REFUND-2 stock goes back up"]]];
const L=["SPEC","DESIGN","UI","TEST"];
async function press(b){b.classList.add("press");await sl(220);b.classList.remove("press")}
async function run(){for(;;){
const g=$("g");while(g.children.length>5)g.lastChild.remove();$("sv").classList.remove("on");$("st").innerHTML="";
await sl(900);await press($("open"));$("sv").classList.add("on");await sl(500);
const cells=[];
for(const [code,cs] of rows){const c=document.createElement("div");c.className="code";c.textContent=code;g.appendChild(c);const r=[];
cs.forEach((t,k)=>{const d=document.createElement("div");d.className="cell c"+(k+1);d.innerHTML="<small>"+L[k]+"</small>"+t+'<span class="mk"></span>';g.appendChild(d);r.push(d)});cells.push(r)}
for(const r of cells){for(const d of r){await sl(260);d.classList.add("in")}await sl(300)}
$("st").innerHTML="Every behaviour has its code in every layer: <b>✓ in sync</b>";for(const r of cells)for(const d of r){d.classList.add("ok");d.querySelector(".mk").textContent="✓"}
await sl(2200);
const s=cells[1][0];s.innerHTML='<small>SPEC</small>A refund puts <u>only the refunded</u> items back in stock.<span class="mk">✎</span>';s.classList.remove("ok");s.classList.add("warn");
$("st").innerHTML="The ticket changes ^refund-2 in the spec: <i>design, UI and test show what's out of step</i>";await sl(900);
for(const d of cells[1].slice(1)){d.classList.remove("ok");d.classList.add("warn");d.querySelector(".mk").textContent="!";await sl(350)}
await sl(2000);
const nx=["OrderLine.refundQty → stock +refundQty.","Stock goes up by the refunded qty.","REFUND-2 partial refund restocks part"];
for(let k=1;k<4;k++){const d=cells[1][k];d.innerHTML="<small>"+L[k]+"</small>"+nx[k-1]+'<span class="mk">✓</span>';d.classList.remove("warn");d.classList.add("ok");await sl(600)}
s.classList.remove("warn");s.classList.add("ok");s.querySelector(".mk").textContent="✓";$("st").innerHTML="Built and tested: <b>✓ back in sync</b>, one row per behaviour";
await sl(3200)}}
run()})();
</script>
</div>
</div>
</div>
</section>
<!-- Testimonial before the thoughts sections (P-1284, razie 2026-10-11: "before thoughts - bold statement: when you see how we interact with AI you'll only start claude to check usage"; "make it a customer feedback like thing") -->
<section class="door t2 extra" id="bold-usage">
<div class="wrap">
<blockquote class="lp-quote" style="font-family:var(--display);font-weight:700;font-size:clamp(22px,3vw,30px);line-height:1.3">Once I saw how to work with AI here, now I only start Claude to check my usage.</blockquote>
<p class="who">Only start Claude to check usage</p>
</div>
</section>
<!-- Pro: Mind Meld mockup review, new animation (P-1284, razie 2026-10-11: "mind meld mockups - turn on mind meld, turn on voice, start review of a functional page from the actual app they're making, make mockup, some changes, lock it down. send tickets, pipeline, checkbox pass") -->
<section class="door t1 extra" id="pro-mindmeld">
<div class="wrap">
<span class="badge">Mind Meld</span>
<h2>Review your app out loud. Watch it change.</h2>
<p>Turn on <b>Mind Meld</b> and your voice, open a page of the app you're building and say what's wrong. Your designer copies it into a mockup beside you and changes it as you talk; when it looks right, <b>lock it in</b>. The changes go out as tickets, move through the pipeline, and come back with their tests ticked.</p>
<div style="margin-top:16px">
<div id="mma">
<style>
#mma{font:13px/1.4 system-ui,-apple-system,Segoe UI,sans-serif;color:#ecebe6;background:#141413;border:1px solid #33322f;border-radius:14px;padding:12px;max-width:940px;margin:auto;position:relative;overflow:hidden;box-sizing:border-box}
#mma *{box-sizing:border-box}
#mma .bar{display:flex;gap:8px;align-items:center;margin-bottom:10px;font-size:12px;color:#9c9a93}
#mma .tg{display:inline-flex;align-items:center;gap:6px;border:1px solid #4a4945;border-radius:999px;padding:2px 10px 2px 4px;transition:all .3s}
#mma .tg i{width:26px;height:15px;border-radius:999px;background:#33322f;position:relative;transition:background .3s}
#mma .tg i::after{content:"";position:absolute;left:2px;top:2px;width:11px;height:11px;border-radius:50%;background:#9c9a93;transition:all .3s}
#mma .tg.on{border-color:#c47a3a;color:#f0a868}#mma .tg.on i{background:#c47a3a}#mma .tg.on i::after{left:13px;background:#fff}
#mma .lay{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(0,1fr);gap:10px}
#mma .fr{border:1px solid #33322f;border-radius:10px;background:#1b1b1a;overflow:hidden;min-height:250px;position:relative}
#mma .url{display:flex;gap:6px;align-items:center;padding:6px 10px;border-bottom:1px solid #33322f;font:11px ui-monospace,Menlo,monospace;color:#9c9a93}
#mma .url .pl{margin-left:auto;font:600 10px system-ui;border-radius:999px;padding:1px 8px;background:#2a2312;color:#e5c06a;opacity:0;transition:opacity .3s}
#mma .url .pl.on{opacity:1}#mma .url .pl.lk{background:#1f3d22;color:#8fd19a}
#mma .pg{padding:12px}
#mma .pg h4{margin:0 0 8px;font-size:15px}
#mma .ord{display:flex;align-items:center;gap:8px;border:1px solid #33322f;border-radius:8px;padding:7px 9px;margin-bottom:6px;transition:all .4s}
#mma .ord b{flex:1;font-weight:500}#mma .ord .tot{color:#cfcdc6;transition:all .4s}
#mma .ord .tot.big{font-size:16px;font-weight:800;color:#f0a868}
#mma .rf{border:1px solid #c47a3a;color:#f0a868;border-radius:6px;padding:1px 8px;font-size:11px;display:none}
#mma .rf.on{display:inline-block;animation:mmain .4s}
#mma .flt{display:none;gap:6px;margin-bottom:8px}#mma .flt.on{display:flex;animation:mmain .4s}
#mma .flt span{border:1px solid #4a4945;border-radius:999px;padding:1px 9px;font-size:11px}#mma .flt span:first-child{border-color:#c47a3a;color:#f0a868}
@keyframes mmain{from{opacity:0;transform:scale(.9)}}
#mma .ch{border:1px solid #33322f;border-radius:10px;background:#1d1d1b;display:flex;flex-direction:column;min-height:250px}
#mma .ch .hd{padding:6px 10px;border-bottom:1px solid #33322f;font-size:12px;color:#9c9a93}
#mma .ms{flex:1;padding:8px;display:flex;flex-direction:column;gap:6px;overflow:hidden}
#mma .b{border-radius:10px;padding:6px 9px;font-size:12px;max-width:92%;animation:mmain .3s}
#mma .b.me{align-self:flex-end;background:#3a2a1c;color:#f6dcc2}#mma .b.ai{background:#22211f;border:1px solid #33322f}
#mma .b.me::before{content:"🎤 ";opacity:.8}
#mma .pp{margin-top:10px;display:grid;grid-template-columns:repeat(3,1fr);gap:8px;opacity:.35;transition:opacity .4s}
#mma .pp.on{opacity:1}
#mma .col{border:1px solid #33322f;border-radius:9px;padding:6px;min-height:76px;background:#1b1b1a}
#mma .col>div:first-child{font-size:10px;letter-spacing:.08em;color:#9c9a93;margin-bottom:4px}
#mma .tk{border:1px solid #33322f;border-left:3px solid #3b82f6;border-radius:6px;padding:4px 6px;font-size:11px;margin-bottom:4px;background:#22211f;animation:mmain .3s}
#mma .tk .ck{float:right;color:#8fd19a;font-weight:700}
@media(max-width:700px){#mma .lay{grid-template-columns:1fr}#mma .ch{min-height:150px}}
#mma .mic{display:inline-flex;align-items:center;gap:6px;margin-left:6px;opacity:.35;transition:opacity .3s}
#mma .mic .mb{width:22px;height:22px;border-radius:50%;display:grid;place-items:center;background:#22211f;border:1px solid #4a4945;font-size:11px;transition:all .3s}
#mma .mic .wv{display:flex;align-items:center;gap:2px;height:16px}
#mma .mic .wv i{width:3px;height:3px;border-radius:2px;background:#4a4945}
#mma .mic.on{opacity:1}
#mma .mic.talk .mb{background:#e5484d;border-color:#e5484d;animation:mmapulse 1.2s ease-out infinite}
#mma .mic.talk .wv i{background:#f0a868;animation:mmabar .9s ease-in-out infinite}
#mma .mic.talk .wv i:nth-child(2){animation-delay:.15s;--h:14px}#mma .mic.talk .wv i:nth-child(3){animation-delay:.3s;--h:9px}#mma .mic.talk .wv i:nth-child(4){animation-delay:.45s;--h:15px}#mma .mic.talk .wv i:nth-child(5){animation-delay:.6s}
@keyframes mmapulse{0%{box-shadow:0 0 0 0 rgba(229,72,77,.5)}100%{box-shadow:0 0 0 9px rgba(229,72,77,0)}}
@keyframes mmabar{0%,100%{height:3px}50%{height:var(--h,12px)}}
</style>
<div class="bar"><span class="tg" id="mma-tm"><i></i>Mind Meld</span><span class="tg" id="mma-tv"><i></i>Voice</span><span class="mic" id="mma-mic"><span class="mb">🎤</span><span class="wv"><i></i><i></i><i></i><i></i><i></i></span></span><span style="margin-left:auto" id="mma-cap"></span></div>
<div class="lay">
<div class="fr"><div class="url"><span id="mma-u">shop.aiputty.com/Orders</span><span class="pl" id="mma-pl">mockup</span></div>
<div class="pg"><h4>Orders</h4>
<div class="flt" id="mma-flt"><span>Paid</span><span>Shipped</span><span>Refunded</span></div>
<div class="ord"><b>o-1004 · Ana Souza</b><span class="tot">$58.00</span><span class="rf">Refund</span></div>
<div class="ord"><b>o-1003 · Ben Ito</b><span class="tot">$24.50</span><span class="rf">Refund</span></div>
<div class="ord"><b>o-1002 · Chen Wei</b><span class="tot">$112.00</span><span class="rf">Refund</span></div>
</div></div>
<div class="ch"><div class="hd">designer · listening</div><div class="ms" id="mma-ms"></div></div>
</div>
<div class="pp" id="mma-pp"><div class="col"><div>NEW</div><div id="mma-c0"></div></div><div class="col"><div>BUILDING</div><div id="mma-c1"></div></div><div class="col"><div>DONE · TESTED</div><div id="mma-c2"></div></div></div>
<script type="text/lazy">
(()=>{const $=i=>document.getElementById("mma-"+i),q=s=>document.querySelectorAll("#mma "+s),sl=ms=>new Promise(r=>setTimeout(r,ms));
async function say(t,me){const b=document.createElement("div");b.className="b "+(me?"me":"ai");const m=$("ms");m.appendChild(b);while(m.children.length>5)m.firstChild.remove();
if(!me){b.textContent=t;return}const mic=$("mic");mic.classList.add("talk");for(const c of t){b.textContent+=c;await sl(38)}await sl(250);mic.classList.remove("talk")}
function tk(id,t){const d=document.createElement("div");d.className="tk";d.innerHTML="<b>"+id+"</b> "+t+'<span class="ck"></span>';return d}
async function run(){for(;;){
$("ms").innerHTML="";for(const i of [0,1,2])$("c"+i).innerHTML="";$("tm").classList.remove("on");$("tv").classList.remove("on");$("mic").className="mic";$("pl").className="pl";$("u").textContent="shop.aiputty.com/Orders";$("pp").classList.remove("on");$("flt").classList.remove("on");
q(".tot").forEach(e=>e.classList.remove("big"));q(".rf").forEach(e=>e.classList.remove("on"));$("cap").textContent="";
await sl(800);$("tm").classList.add("on");await sl(500);$("tv").classList.add("on");$("mic").classList.add("on");await sl(600);
await say("Let's review the Orders page.",1);await sl(1100);
await say("I see it. Copied it into a mockup beside you.");$("u").textContent="shop.aiputty.com/app/Mockup-orders";$("pl").classList.add("on");$("pl").textContent="mockup";await sl(1400);
await say("Make the totals stand out.",1);await sl(900);q(".tot").forEach(e=>e.classList.add("big"));await sl(1100);
await say("And a refund button on each order.",1);await sl(900);q(".rf").forEach(e=>e.classList.add("on"));await sl(1100);
await say("Filter by status at the top.",1);await sl(900);$("flt").classList.add("on");await sl(1300);
await say("Looks right. Lock it in and send it.",1);await sl(900);$("pl").textContent="🔒 locked in";$("pl").classList.add("lk");$("u").textContent="shop.aiputty.com/Orders · draft";
await say("Locked in. Three tickets, with their tests.");$("pp").classList.add("on");
const ts=[tk("P-1301","totals stand out"),tk("P-1302","refund button"),tk("P-1303","status filter")];
for(const t of ts){$("c0").appendChild(t);await sl(350)}await sl(900);
for(const t of ts){$("c1").appendChild(t);await sl(500)}await sl(1000);
for(const t of ts){$("c2").appendChild(t);await sl(450);t.querySelector(".ck").textContent="✓ tests"}
await say("All three built. Tests pass: ORDERS-4, -5, -6 ✓");await sl(3500)}}
run()})();
</script>
</div>
</div>
</div>
</section>
<!-- Pro and Master: thoughts become pipeline tasks, from Blurb#streaks (P-1284, razie 2026-10-11: "for pro and master, they should have agents") -->
<section class="door t2 extra" id="sprint-thoughts">
<div class="wrap">
<span class="badge">Thoughts</span>
<h2>Talk in a sprint. Get tasks back.</h2>
<p>Dictate in one long breath and let the words do the sorting: <i>new bug…</i>, <i>new idea…</i>, <i>new blurb…</i> split it into thoughts as you save, each one tagged. <b>Send</b> hands them all to your designer in one message, and they come back as pipeline tasks, each thought archiving itself with a link to its task.</p>
<div style="margin-top:16px">
<div id="bst">
<style>
#bst{font:14px/1.4 system-ui,-apple-system,Segoe UI,sans-serif;color:#ecebe6;background:#141413;border:1px solid #33322f;border-radius:14px;padding:14px;max-width:720px;margin:auto;position:relative;overflow:hidden;min-height:310px;box-sizing:border-box}
#bst *{box-sizing:border-box}
#bst .box{border:1px solid #4a4945;border-radius:9px;background:#1d1d1b;padding:8px 10px;min-height:40px;font-size:13px}
#bst .cur{display:inline-block;width:2px;height:14px;background:#6aa3ff;vertical-align:-2px;animation:bstb 1s steps(1) infinite}
@keyframes bstb{50%{opacity:0}}
#bst .btn{display:inline-block;border:1px solid #4a4945;border-radius:7px;padding:3px 10px;font-size:12px;background:#22211f;color:#ecebe6;transition:transform .15s}
#bst .btn.p{background:#3b82f6;border-color:#3b82f6;color:#fff}
#bst .btn.press{transform:scale(.9)}
#bst .card{background:#1d1d1b;border:1px solid #33322f;border-radius:9px;padding:7px 9px;font-size:12px;transition:all .5s;opacity:1}
#bst .card.in{animation:bstin .5s ease}
@keyframes bstin{from{opacity:0;transform:translateY(-12px) scale(.9)}}
#bst .t{font-size:11px;margin-right:5px}
#bst .bug{color:#e0a050}#bst .idea{color:#e0a050}#bst .blurb{color:#e0a050}
#bst .chip{display:inline-block;border-radius:999px;padding:0 7px;font-size:11px;margin-right:4px}
#bst .sent{border:1px dashed #6b6963;color:#9c9a93}
#bst .aq{border:1px solid #d0605a;color:#f09590}
#bst .wt{border:1px solid #c99a2e;color:#e5c06a}
#bst .go{background:#1f3d22;color:#8fd19a;border:1px solid #3b6d41}
#bst .sec{font-size:10px;letter-spacing:.08em;color:#9c9a93;margin:8px 0 4px}
#bst .ck{display:inline-block;width:12px;height:12px;border-radius:3px;border:1.5px solid #8a8880;vertical-align:-2px;margin-right:6px}
#bst .ck.on{background:#3b82f6;border-color:#3b82f6}
#bst .fade{opacity:0!important;transform:scale(.85)}
#bst .lay{display:grid;grid-template-columns:1fr 150px;gap:12px;margin-top:10px}
#bst .head{display:flex;justify-content:space-between;align-items:center}
#bst .card{margin-bottom:6px}
#bst .pipe{border:1px solid #33322f;border-radius:9px;padding:6px;min-height:170px}
#bst .task{font-size:11px;border-left:3px solid #3b82f6;background:#1a2233;border-radius:0 6px 6px 0;padding:4px 6px;margin-bottom:5px}
#bst .mic{display:inline-block;width:8px;height:8px;border-radius:50%;background:#d0605a;margin-right:6px;animation:bstp 1s infinite}
@keyframes bstp{50%{opacity:.3}}
#bst .fly{transition:all .8s ease-in}#bst .fly.gone{transform:translateX(220px) scale(.3);opacity:0}
</style>
<div class="box"><span class="mic"></span><span id="bst-tx"></span><span class="cur"></span></div>
<div class="lay"><div><div class="head"><span class="sec">INBOX</span><span class="btn p" id="bst-send">Send (<span id="bst-n">0</span>)</span></div><div id="bst-st"></div></div><div class="pipe"><div class="sec">PIPELINE</div><div id="bst-pl"></div></div></div>
<script type="text/lazy">
(()=>{const $=i=>document.getElementById("bst-"+i),sl=ms=>new Promise(r=>setTimeout(r,ms));
async function type(el,s,ms){el.textContent="";for(const c of s){el.textContent+=c;await sl(ms||32)}}
async function press(b){b.classList.add("press");await sl(200);b.classList.remove("press")}
function mk(h,c){const d=document.createElement("div");d.className=c||"card in";d.innerHTML=h;return d}
const said="ok new bug the drafts page is slow ok new idea levels get their own pages ok new blurb sprints save tokens ok new bug export drops the last row";
const parts=[["bug","the drafts page is slow"],["idea","levels get their own pages"],["blurb","sprints save tokens"],["bug","export drops the last row"]];
async function run(){for(;;){$("st").innerHTML="";$("pl").innerHTML="";$("n").textContent=0;await type($("tx"),said,26);await sl(700);$("tx").textContent="";
let i=0;for(const [k,s] of parts){const c=mk('<span class="ck on"></span><span class="t '+k+'">#'+k+'</span>'+s,"card in fly");$("st").append(c);$("n").textContent=++i;await sl(450)}
await sl(1400);await press($("send"));let p=1201;for(const c of [...$("st").children]){c.classList.add("gone");await sl(250)}
await sl(700);$("st").innerHTML="";$("n").textContent=0;const T=[["P-"+p,"drafts page speed + export row"],["P-"+(p+1),"levels pages (design)"],["P-"+(p+2),"blurb: sprints save tokens"]];
for(const [id,s] of T){$("pl").append(mk('<b style="color:#6aa3ff">'+id+'</b> '+s,"task card in"));await sl(500)}await sl(3000)}}
run()})();
</script>
</div>
</div>
</div>
</section>
<!-- Pro and Master: permissions, from Blurb#permissions-freedom (P-1284, razie 2026-10-11: "for pro and master add the blurb and anim on letting agents loose, with permissions") -->
<section class="door t1 extra" id="pro-permissions">
<div class="wrap">
<span class="badge">Permissions</span>
<h2>Give your AI as much freedom as you want. Interfere as little as you want.</h2>
<p>One row per kind of move, and you slide each to where you're comfortable: <b>you</b> do it yourself, it <b>asks</b> and you tap Go, it <b>tells</b> you after, or it's <b>free</b> to just do it. Tokens, the vault and deleting a project stay yours, always. Then it just works: free moves happen, tells moves report, and the big ones wait for one tap.</p>
<div style="margin-top:16px">
<iframe id="pm-f" title="Permissions demo" class="lp-anim" style="width:100%;border:0;display:block;height:660px" data-srcdoc="<div>
<style>:root{--paper:#141413;--card:#1d1d1b;--ink:#ecebe6;--soft:#9c9a93;--line:#33322f;--accent:#f0a35e;--accent-bg:#2e2419;--leaf:#6cc08a;--me:#22283a;--display:system-ui,-apple-system,"Segoe UI",sans-serif;--body:system-ui,-apple-system,"Segoe UI",sans-serif}
*{box-sizing:border-box}html,body{margin:0;background:var(--paper);color:var(--ink);font:14px/1.45 var(--body)}
.top{display:flex;align-items:center;gap:12px;padding:10px 18px;border-bottom:1px solid var(--line)}.top b{font:800 18px var(--display)}.top .sp{flex:1}
.ctl button{font:600 13px var(--body);border:1px solid var(--line);background:var(--card);color:var(--ink);border-radius:8px;padding:5px 10px;cursor:pointer}
.cap{min-height:22px;color:var(--soft);font-size:13px;padding:6px 18px}
.stage{position:relative;display:grid;grid-template-columns:minmax(0,2fr) minmax(300px,1fr);gap:16px;padding:6px 18px 18px;height:calc(100vh - 92px);min-height:520px}
.left{overflow:auto;padding-left:clamp(0px,2vw,30px)}
.chat{background:var(--card);border:1px solid var(--line);border-radius:14px;display:flex;flex-direction:column;overflow:hidden}
.chat .hd{padding:10px 12px;border-bottom:1px solid var(--line);display:flex;gap:8px;align-items:center}.dot{width:8px;height:8px;border-radius:50%;background:var(--leaf)}
.chat .hd .sp{flex:1}.chip{font-size:12px;border:1px solid var(--line);border-radius:999px;padding:2px 8px}
.msgs{flex:1;overflow:auto;padding:10px;display:flex;flex-direction:column;gap:8px}
.b{max-width:92%;padding:8px 10px;border-radius:12px;background:var(--paper);border:1px solid var(--line);opacity:0;transform:translateY(6px);transition:all .35s}
.b.in{opacity:1;transform:none}.b.me{align-self:flex-end;background:var(--me);white-space:pre-wrap}
.b .who{font-size:11px;color:var(--soft);margin-bottom:3px}
.inp{border-top:1px solid var(--line);padding:8px;display:flex;gap:6px}.inp div{flex:1;border:1px solid var(--line);border-radius:10px;padding:6px 8px;color:var(--soft)}
.grp{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:10px 12px;margin:8px 0;transition:opacity .4s}
.b .grp{background:var(--card);padding:8px 10px;margin:6px 0}
.grp h4{font:700 14px/1.2 var(--display);margin:0 0 4px}.grp.done{opacity:.45}.grp.done h4::after{content:" · sent";color:var(--leaf);font-weight:400}
.opt{display:flex;gap:8px;align-items:flex-start;padding:4px;border-radius:7px}.opt .bx{width:17px;height:17px;flex:none;border:2px solid var(--soft);border-radius:4px;margin-top:1px;display:grid;place-items:center;font-size:12px;color:#fff;transition:all .15s}
.opt .bx.r{border-radius:50%}.opt.on .bx{background:var(--accent);border-color:var(--accent)}.opt.on .bx::after{content:"✓"}.opt.on .bx.r::after{content:"•";font-size:16px;line-height:1}
.opt.hl{background:var(--accent-bg)}
.btn{display:block;width:100%;text-align:left;font:600 14px var(--body);padding:8px 12px;margin:5px 0;border-radius:10px;border:1px solid var(--accent);background:var(--accent-bg);color:var(--ink);transition:all .15s}
.btn.hl{background:var(--accent);color:#fff}
.note{display:flex;gap:6px;margin-top:4px}.note .ed{flex:1;min-height:30px;border:1px solid var(--line);border-radius:9px;padding:5px 8px;white-space:pre-wrap}.note .ed:empty::before{content:attr(data-ph);color:var(--soft)}.note .mic{border:1px solid var(--line);border-radius:9px;padding:4px 9px}
.go{font:700 14px var(--display);letter-spacing:.04em;padding:8px 20px;border-radius:10px;border:0;background:var(--accent);color:#fff;margin-top:4px;transition:transform .1s}.go.hl{transform:scale(.94)}
.cur{position:absolute;left:0;top:0;width:22px;height:22px;pointer-events:none;z-index:9;transition:left .6s cubic-bezier(.4,.1,.2,1),top .6s cubic-bezier(.4,.1,.2,1)}
.cur::before{content:"";position:absolute;inset:0;background:no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4 2l15 11-7 1 4 8-3 1-4-8-5 5z' fill='%23111' stroke='%23fff' stroke-width='1.2'/%3E%3C/svg%3E")}
.cur.tap::after{content:"";position:absolute;left:-8px;top:-8px;width:20px;height:20px;border-radius:50%;border:2px solid var(--accent);animation:tap .4s ease-out}
@keyframes tap{from{transform:scale(.3);opacity:1}to{transform:scale(1.6);opacity:0}}
.flash{animation:fl 1.2s}@keyframes fl{0%{box-shadow:0 0 0 3px var(--accent)}100%{box-shadow:0 0 0 0 transparent}}
@media (max-width:760px){.stage{grid-template-columns:1fr;height:auto}.chat{min-height:420px}}
html,body{background:#141413}.stage{height:480px;min-height:0;padding:12px}@media (max-width:620px){.stage{grid-template-columns:1fr;height:auto}.chat{min-height:380px}}.stage{height:600px!important;min-height:0!important}
</style>
<script>// a tiny timeline: steps run in order, the loop restarts; Pause/Restart buttons
const $=s=>document.querySelector(s),sleep=ms=>new Promise(r=>setTimeout(r,ms*SPEED));let SPEED=1,RUN=0,PAUSED=false;
const cap=t=>{};
async function wait(ms){const id=RUN;let t=0;while(t<ms){await new Promise(r=>setTimeout(r,50));if(!PAUSED)t+=50/SPEED;if(id!==RUN)throw "stop"}}
async function moveTo(el,dx=14,dy=10){const st=$(".stage").getBoundingClientRect(),r=el.getBoundingClientRect(),c=$("#cur");c.style.left=(r.left-st.left+Math.min(dx,r.width-6))+"px";c.style.top=(r.top-st.top+Math.min(dy,r.height-4))+"px";await wait(700)}
async function tap(el,dx,dy){await moveTo(el,dx,dy);const c=$("#cur");c.classList.remove("tap");void c.offsetWidth;c.classList.add("tap");el.classList.add("hl");await wait(250);el.classList.remove("hl")}
async function typeInto(el,text,ms=45){el.textContent="";for(const ch of text){el.textContent+=ch;await wait(ms)}}
function bubble(html,me,who){const b=document.createElement("div");b.className="b"+(me?" me":"");b.innerHTML=(who?'<div class="who">'+who+'</div>':"")+html;$("#msgs").appendChild(b);requestAnimationFrame(()=>b.classList.add("in"));$("#msgs").scrollTop=1e6;return b}
async function loop(fn){for(;;){const id=++RUN;try{await fn()}catch(e){if(e!=="stop")console.error(e);if(id!==RUN)return}}}
function controls(fn){loop(fn)}
</script>
<div class="stage">
<div class="left" id="left"></div>
<div class="chat"><div class="hd"><span class="dot"></span><b>designer-90</b><span class="sp"></span><span class="chip">+ New</span><span class="chip">+Pad</span></div>
<div class="msgs" id="msgs"></div><div class="inp"><div>Message…</div></div></div>
<div class="cur" id="cur" style="left:60%;top:60%"></div>
</div>
<style>
.prow{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:10px;align-items:center;padding:8px 10px;border:1px solid var(--line);border-radius:10px;background:var(--card);margin:6px 0;transition:box-shadow .4s}
.prow .t{font-weight:600}.prow .d{font-size:12px;color:var(--soft)}
.seg{display:inline-flex;border:1px solid var(--line);border-radius:999px;overflow:hidden}
.seg span{font-size:12px;padding:4px 10px;color:var(--soft);transition:all .2s}.seg span.on{background:var(--accent);color:#fff}
.seg span.hl{background:var(--accent-bg)}
.lock{font-size:12px;color:var(--soft)}
.gobtn{display:inline-block;margin-top:6px;font:700 13px var(--body);padding:5px 14px;border-radius:8px;background:var(--accent);color:#fff;transition:transform .1s}.gobtn.hl{transform:scale(.92)}
</style>
<script>
const L=["you","asks","tells","free"];
const row=(id,t,d,v)=>`<div class="prow" id="r${id}"><div><div class="t">${t}</div><div class="d">${d}</div></div><div class="seg" id="s${id}">${L.map((x,i)=>`<span data-v="${i}"${i===v?' class="on"':""}>${x}</span>`).join("")}</div></div>`;
async function setv(id,v){const s=$("#s"+id),sp=s.children[v];await tap(sp,10,8);[...s.children].forEach((c,i)=>c.classList.toggle("on",i===v));$("#r"+id).classList.add("flash");await wait(500);$("#r"+id).classList.remove("flash")}
async function run(){
$("#msgs").innerHTML="";
$("#left").innerHTML=`<div style="color:var(--soft);font-size:12px">Settings · Permissions · what your AI may do on this project</div>
<h2 style="font:800 22px/1.2 var(--display);margin:4px 0 4px">Your AI's freedom</h2>
<div style="font-size:12px;color:var(--soft);margin-bottom:6px"><b>you</b> only you do it · <b>asks</b> it asks, you tap Go · <b>tells</b> it does it and tells you · <b>free</b> it just does it</div>
${row(1,"Small design changes","wording, a defect, a page tweak",1)}
${row(2,"Publish drafts","pages, Help, styles",0)}
${row(3,"Start big work","large tickets to the coders",1)}
${row(4,"Deploy and release","ship what is built",0)}
${row(5,"Move your browser tab","Mind Meld, to show you things",1)}
<div class="prow" style="opacity:.7"><div><div class="t">🔒 Tokens, vault, deleting projects</div><div class="d">always yours, on every project</div></div><span class="lock">locked</span></div>`;
cap("1 · One row per kind of move. Slide each to as much freedom as you like.");await wait(1500);
await setv(1,3);await setv(2,2);await setv(5,3);
cap("2 · Keep a hand on the big ones: the AI asks, you tap Go.");
await setv(4,1);await wait(500);
cap("3 · Then it just works: free moves happen, tells moves report, asks wait for one tap.");
bubble("Fixed the typo on the pricing page (free).",false,"designer-90");await wait(1100);
bubble("Published Help:TurboChat; it's live (tells).",false,"designer-90");await wait(1100);
const b=bubble('Release 0.274 is ready: 3 tickets, all green. Deploy?<br><span class="gobtn" id="gb">Go</span>',false,"designer-90");await wait(1300);
await tap($("#gb"));bubble("Go",true);await wait(800);
bubble("Deployed 0.274. ✓",false,"designer-90");
cap("As much freedom as you want. As little interfering as you want.");await wait(4000);
}
controls(run);
</script>
</div>"></iframe>
</div>
</div>
</section>
<!-- Pro and Master: Tap, don't type, with the ticket review animation from Blurb#ticket-review-pad (P-1284, razie 2026-10-11: "for tap don't type put the ticket review one") -->
<section class="door t3 extra" id="pro-turbochat">
<div class="wrap">
<span class="badge">TurboChat</span>
<h2>Tap, don't type.</h2>
<p>Your designer asks with options, not paragraphs: a button when one tap is enough, ticks and picks for the bigger calls, a note box you can talk into. One tap, or one <b>CONTINUE</b>, and it's answered. Bigger choices open the pad page, with the chat docked beside it.</p>
<div style="margin-top:16px">
<iframe id="tr-f" title="Ticket review demo" class="lp-anim" style="width:100%;border:0;display:block;height:740px" data-srcdoc="<div>
<style>:root{--paper:#141413;--card:#1d1d1b;--ink:#ecebe6;--soft:#9c9a93;--line:#33322f;--accent:#f0a35e;--accent-bg:#2e2419;--leaf:#6cc08a;--me:#22283a;--display:system-ui,-apple-system,"Segoe UI",sans-serif;--body:system-ui,-apple-system,"Segoe UI",sans-serif}
*{box-sizing:border-box}html,body{margin:0;background:var(--paper);color:var(--ink);font:14px/1.45 var(--body)}
.top{display:flex;align-items:center;gap:12px;padding:10px 18px;border-bottom:1px solid var(--line)}.top b{font:800 18px var(--display)}.top .sp{flex:1}
.ctl button{font:600 13px var(--body);border:1px solid var(--line);background:var(--card);color:var(--ink);border-radius:8px;padding:5px 10px;cursor:pointer}
.cap{min-height:22px;color:var(--soft);font-size:13px;padding:6px 18px}
.stage{position:relative;display:grid;grid-template-columns:minmax(0,2fr) minmax(300px,1fr);gap:16px;padding:6px 18px 18px;height:calc(100vh - 92px);min-height:520px}
.left{overflow:auto;padding-left:clamp(0px,2vw,30px)}
.chat{background:var(--card);border:1px solid var(--line);border-radius:14px;display:flex;flex-direction:column;overflow:hidden}
.chat .hd{padding:10px 12px;border-bottom:1px solid var(--line);display:flex;gap:8px;align-items:center}.dot{width:8px;height:8px;border-radius:50%;background:var(--leaf)}
.chat .hd .sp{flex:1}.chip{font-size:12px;border:1px solid var(--line);border-radius:999px;padding:2px 8px}
.msgs{flex:1;overflow:auto;padding:10px;display:flex;flex-direction:column;gap:8px}
.b{max-width:92%;padding:8px 10px;border-radius:12px;background:var(--paper);border:1px solid var(--line);opacity:0;transform:translateY(6px);transition:all .35s}
.b.in{opacity:1;transform:none}.b.me{align-self:flex-end;background:var(--me);white-space:pre-wrap}
.b .who{font-size:11px;color:var(--soft);margin-bottom:3px}
.inp{border-top:1px solid var(--line);padding:8px;display:flex;gap:6px}.inp div{flex:1;border:1px solid var(--line);border-radius:10px;padding:6px 8px;color:var(--soft)}
.grp{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:10px 12px;margin:8px 0;transition:opacity .4s}
.b .grp{background:var(--card);padding:8px 10px;margin:6px 0}
.grp h4{font:700 14px/1.2 var(--display);margin:0 0 4px}.grp.done{opacity:.45}.grp.done h4::after{content:" · sent";color:var(--leaf);font-weight:400}
.opt{display:flex;gap:8px;align-items:flex-start;padding:4px;border-radius:7px}.opt .bx{width:17px;height:17px;flex:none;border:2px solid var(--soft);border-radius:4px;margin-top:1px;display:grid;place-items:center;font-size:12px;color:#fff;transition:all .15s}
.opt .bx.r{border-radius:50%}.opt.on .bx{background:var(--accent);border-color:var(--accent)}.opt.on .bx::after{content:"✓"}.opt.on .bx.r::after{content:"•";font-size:16px;line-height:1}
.opt.hl{background:var(--accent-bg)}
.btn{display:block;width:100%;text-align:left;font:600 14px var(--body);padding:8px 12px;margin:5px 0;border-radius:10px;border:1px solid var(--accent);background:var(--accent-bg);color:var(--ink);transition:all .15s}
.btn.hl{background:var(--accent);color:#fff}
.note{display:flex;gap:6px;margin-top:4px}.note .ed{flex:1;min-height:30px;border:1px solid var(--line);border-radius:9px;padding:5px 8px;white-space:pre-wrap}.note .ed:empty::before{content:attr(data-ph);color:var(--soft)}.note .mic{border:1px solid var(--line);border-radius:9px;padding:4px 9px}
.go{font:700 14px var(--display);letter-spacing:.04em;padding:8px 20px;border-radius:10px;border:0;background:var(--accent);color:#fff;margin-top:4px;transition:transform .1s}.go.hl{transform:scale(.94)}
.cur{position:absolute;left:0;top:0;width:22px;height:22px;pointer-events:none;z-index:9;transition:left .6s cubic-bezier(.4,.1,.2,1),top .6s cubic-bezier(.4,.1,.2,1)}
.cur::before{content:"";position:absolute;inset:0;background:no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4 2l15 11-7 1 4 8-3 1-4-8-5 5z' fill='%23111' stroke='%23fff' stroke-width='1.2'/%3E%3C/svg%3E")}
.cur.tap::after{content:"";position:absolute;left:-8px;top:-8px;width:20px;height:20px;border-radius:50%;border:2px solid var(--accent);animation:tap .4s ease-out}
@keyframes tap{from{transform:scale(.3);opacity:1}to{transform:scale(1.6);opacity:0}}
.flash{animation:fl 1.2s}@keyframes fl{0%{box-shadow:0 0 0 3px var(--accent)}100%{box-shadow:0 0 0 0 transparent}}
@media (max-width:760px){.stage{grid-template-columns:1fr;height:auto}.chat{min-height:420px}}
html,body{background:#141413}.stage{height:440px;min-height:0;padding:12px}@media (max-width:620px){.stage{grid-template-columns:1fr;height:auto}.chat{min-height:380px}}.stage{height:680px!important;min-height:0!important}
</style>
<script>// a tiny timeline: steps run in order, the loop restarts; Pause/Restart buttons
const $=s=>document.querySelector(s),sleep=ms=>new Promise(r=>setTimeout(r,ms*SPEED));let SPEED=1,RUN=0,PAUSED=false;
const cap=t=>{};
async function wait(ms){const id=RUN;let t=0;while(t<ms){await new Promise(r=>setTimeout(r,50));if(!PAUSED)t+=50/SPEED;if(id!==RUN)throw "stop"}}
async function moveTo(el,dx=14,dy=10){const st=$(".stage").getBoundingClientRect(),r=el.getBoundingClientRect(),c=$("#cur");c.style.left=(r.left-st.left+Math.min(dx,r.width-6))+"px";c.style.top=(r.top-st.top+Math.min(dy,r.height-4))+"px";await wait(700)}
async function tap(el,dx,dy){await moveTo(el,dx,dy);const c=$("#cur");c.classList.remove("tap");void c.offsetWidth;c.classList.add("tap");el.classList.add("hl");await wait(250);el.classList.remove("hl")}
async function typeInto(el,text,ms=45){el.textContent="";for(const ch of text){el.textContent+=ch;await wait(ms)}}
function bubble(html,me,who){const b=document.createElement("div");b.className="b"+(me?" me":"");b.innerHTML=(who?'<div class="who">'+who+'</div>':"")+html;$("#msgs").appendChild(b);requestAnimationFrame(()=>b.classList.add("in"));$("#msgs").scrollTop=1e6;return b}
async function loop(fn){for(;;){const id=++RUN;try{await fn()}catch(e){if(e!=="stop")console.error(e);if(id!==RUN)return}}}
function controls(fn){loop(fn)}
</script>
<div class="stage">
<div class="left" id="left"></div>
<div class="chat"><div class="hd"><span class="dot"></span><b>designer-90</b><span class="sp"></span><span class="chip">+ New</span><span class="chip">+Pad</span></div>
<div class="msgs" id="msgs"></div><div class="inp"><div>Message…</div></div></div>
<div class="cur" id="cur" style="left:60%;top:60%"></div>
</div>
<script>
const opt=(id,t,r)=>`<div class="opt" id="${id}"><span class="bx${r?" r":""}"></span><span>${t}</span></div>`;
async function run(){
$("#msgs").innerHTML="";
$("#left").innerHTML=`<div style="color:var(--soft);font-size:12px">P-1263 · design · <span id="st" style="color:var(--accent);font-weight:700">waiting on you</span></div>
<h2 style="font:800 22px/1.2 var(--display);margin:4px 0 6px">Skill review: dispatcher and coder</h2>
<div id="qs">
<div class="grp" id="q6"><h4>D6. Release checks nobody can run</h4>${opt("a6","a. Optional, each release says \"skipped: why\" (my pick)",1)}${opt("b6","b. Grant what's missing, keep them required",1)}</div>
<div class="grp" id="q7"><h4>D7. Which tests are official?</h4>${opt("a7","a. test:full + test:box (my pick)",1)}${opt("b7","b. test:gate + test:late",1)}</div>
<div class="grp" id="q11"><h4>D11. May coders run the full suite?</h4>${opt("a11","a. Once after merge (my pick)",1)}${opt("b11","b. Keep the ban",1)}${opt("c11","c. Only for shell or /system tickets",1)}
<div class="note"><div class="ed" id="n11" data-ph="Note (optional)"></div><span class="mic">🎤</span></div></div>
</div>
<button class="go" id="go">CONTINUE</button>`;
cap("1 · The ticket waits on you: its questions are a pad.");
bubble("P-1263 is ready for you: 3 calls, (a) is my pick each time.",false,"designer-90");await wait(1600);
cap("2 · Pick per question, add a note if you like.");
await tap($("#a6"),8,8);$("#a6").classList.add("on");
await tap($("#a7"),8,8);$("#a7").classList.add("on");
cap("3 · While you look, the designer adds a question: the page redraws, your picks stay.");
bubble("One more just came up (D14), adding it to the ticket.",false,"designer-90");await wait(900);
const g=document.createElement("div");g.className="grp flash";g.id="q14";g.innerHTML=`<h4>D14. Push a killed coder's tree to its branch first?</h4><div class="btn" id="y14">Yes</div><div class="btn" id="n14b">No</div>`;$("#qs").appendChild(g);
await wait(1500);
cap("4 · A button answers that one at once.");
await tap($("#y14"));g.classList.add("done");bubble("D14: Yes",true);await wait(900);
cap("5 · Finish the rest and CONTINUE: it answers the ticket, like the Answer box.");
await tap($("#c11"),8,8);$("#c11").classList.add("on");
await tap($("#n11"));await typeInto($("#n11"),"plus anything touching page()",50);
await wait(300);await tap($("#go"));
["#q6","#q7","#q11"].forEach(s=>$(s).classList.add("done"));$("#st").textContent="answered · back with the designer";$("#st").style.color="var(--leaf)";
bubble("Answered P-1263: D6 a, D7 a, D11 c (\"plus anything touching page()\"), D14 yes.",true);await wait(1200);
bubble("Thanks. Drafting the skill edits for D6, D7, D11 and D14 now.",false,"designer-90");
cap("Ticket review without typing: picks, buttons, a note, done.");await wait(3800);
}
controls(run);
</script>
</div>"></iframe>
</div>
</div>
</section>
<!-- Creator: ThoughtFlow, from Blurb#thoughtflow (P-1284, razie 2026-10-11: its blurb, then the animation) -->
<section class="door t3 extra" id="creator-thoughtflow">
<div class="wrap">
<span class="badge">ThoughtFlow</span>
<h2>Think out loud. Your agents answer in place.</h2>
<p>Turn on <b>ThoughtFlow</b> and your thoughts sort themselves into <b>Chats</b>, <b>Inbox</b> and <b>Others</b>. Write <code>@designer</code> and <b>Send</b>: the answer lands inside the thought, and the whole card becomes a chat on that topic that you can pick up any time. Get your AI's opinion, ask a question on that topic, and see the answer in the same place. The card turns amber when it's your turn; happy with it? Tick it and it goes as <i>ok, go</i>.</p>
<div style="margin-top:16px">
<div id="btf">
<style>
#btf{font:14px/1.4 system-ui,-apple-system,Segoe UI,sans-serif;color:#ecebe6;background:#141413;border:1px solid #33322f;border-radius:14px;padding:14px;max-width:720px;margin:auto;position:relative;overflow:hidden;min-height:310px;box-sizing:border-box}
#btf *{box-sizing:border-box}
#btf .box{border:1px solid #4a4945;border-radius:9px;background:#1d1d1b;padding:8px 10px;min-height:40px;font-size:13px}
#btf .cur{display:inline-block;width:2px;height:14px;background:#6aa3ff;vertical-align:-2px;animation:btfb 1s steps(1) infinite}
@keyframes btfb{50%{opacity:0}}
#btf .btn{display:inline-block;border:1px solid #4a4945;border-radius:7px;padding:3px 10px;font-size:12px;background:#22211f;color:#ecebe6;transition:transform .15s}
#btf .btn.p{background:#3b82f6;border-color:#3b82f6;color:#fff}
#btf .btn.press{transform:scale(.9)}
#btf .card{background:#1d1d1b;border:1px solid #33322f;border-radius:9px;padding:7px 9px;font-size:12px;transition:all .5s;opacity:1}
#btf .card.in{animation:btfin .5s ease}
@keyframes btfin{from{opacity:0;transform:translateY(-12px) scale(.9)}}
#btf .t{font-size:11px;margin-right:5px}
#btf .bug{color:#e0a050}#btf .idea{color:#e0a050}#btf .blurb{color:#e0a050}
#btf .chip{display:inline-block;border-radius:999px;padding:0 7px;font-size:11px;margin-right:4px}
#btf .sent{border:1px dashed #6b6963;color:#9c9a93}
#btf .aq{border:1px solid #d0605a;color:#f09590}
#btf .wt{border:1px solid #c99a2e;color:#e5c06a}
#btf .go{background:#1f3d22;color:#8fd19a;border:1px solid #3b6d41}
#btf .sec{font-size:10px;letter-spacing:.08em;color:#9c9a93;margin:8px 0 4px}
#btf .ck{display:inline-block;width:12px;height:12px;border-radius:3px;border:1.5px solid #8a8880;vertical-align:-2px;margin-right:6px}
#btf .ck.on{background:#3b82f6;border-color:#3b82f6}
#btf .fade{opacity:0!important;transform:scale(.85)}
#btf .row{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;margin-top:10px}
#btf .col{min-height:200px;border:1px dashed #2c2b28;border-radius:9px;padding:6px}
#btf .col .card{margin-bottom:6px}
#btf .ans{margin-top:5px;padding:5px 7px;background:#262523;border-radius:6px;color:#cfcdc6;font-size:11px}
#btf .ans i{font-style:normal;color:#6aa3ff}
#btf .card.you{border:2px solid #c99a2e}
</style>
<div class="box"><span id="btf-tx"></span><span class="cur"></span></div><div style="margin-top:6px;text-align:right"><span class="btn" id="btf-save">Save it</span> <span class="btn p" id="btf-send">Send → @designer</span></div>
<div class="row"><div class="col"><div class="sec">CHATS</div><div id="btf-chats"></div></div><div class="col"><div class="sec">INBOX</div><div id="btf-streak"></div></div><div class="col"><div class="sec">OTHERS</div><div id="btf-others"></div></div></div>
<script type="text/lazy">
(()=>{const $=i=>document.getElementById("btf-"+i),sl=ms=>new Promise(r=>setTimeout(r,ms));
async function type(el,s,ms){el.textContent="";for(const c of s){el.textContent+=c;await sl(ms||32)}}
async function press(b){b.classList.add("press");await sl(200);b.classList.remove("press")}
function mk(h,c){const d=document.createElement("div");d.className=c||"card in";d.innerHTML=h;return d}
async function run(){for(;;){for(const k of["chats","streak","others"])$(k).innerHTML="";
await type($("tx"),"#bug search misses archived thoughts");await press($("save"));$("tx").textContent="";$("streak").prepend(mk('<span class="ck on"></span><span class="t bug">#bug</span>search misses archived thoughts'));await sl(900);
await type($("tx"),"#note call the bank about the card");await press($("save"));$("tx").textContent="";$("others").prepend(mk('<span class="t" style="color:#9c9a93">#note</span>call the bank about the card'));await sl(900);
await type($("tx"),"@designer should Focus have its own help page?");await sl(300);await press($("send"));$("tx").textContent="";
const c=mk('<div>should Focus have its own help page?</div><div style="margin-top:4px"><span class="chip sent">#sent</span><span style="font-size:11px;color:#9c9a93">waiting on designer</span></div>');$("chats").prepend(c);await sl(2400);
c.className="card in you";c.innerHTML='<div><span class="ck"></span>should Focus have its own help page?</div><div class="ans"><i>designer:</i> yes, a short one linked from the ⓘ on the Focus title. Go?</div><div style="margin-top:4px"><span class="chip aq">#ai-question</span></div>';await sl(2600);
c.querySelector(".ck").classList.add("on");c.querySelector(".chip").insertAdjacentHTML("beforebegin",'<span class="chip go">✓ go</span>');await sl(2400)}}
run()})();
</script>
</div>
</div>
</div>
</section>
<!-- Creator: Focus, from Blurb#focus-all (P-1284, razie 2026-10-11: its blurb, then the animation) -->
<section class="door t3 extra" id="creator-focus">
<div class="wrap">
<span class="badge">Focus</span>
<h2>Gather it, think it through, send it as tasks.</h2>
<p>Search and tick what belongs together; it goes <i>poof</i> into a Focus and the map spins up. Add your thoughts one by one, and each lights what it names. Ask one question with <b>Thread now</b> and the answer comes back into that thought. Ask for a mockup and your designer shows it on the spot; the one you like joins. <b>Send focus</b>, split by feature, and it lands in the pipeline as tasks.</p>
<div style="margin-top:16px">
<div id="bfc">
<style>
#bfc{font:14px/1.4 system-ui,-apple-system,Segoe UI,sans-serif;color:#ecebe6;background:#141413;border:1px solid #33322f;border-radius:14px;padding:14px;max-width:660px;margin:auto;position:relative;overflow:hidden}
#bfc *{box-sizing:border-box}
#bfc .cap{min-height:20px;font-size:13px;color:#9c9a93;margin:0 0 10px}
#bfc .cap b{color:#ecebe6}
#bfc .stage{position:relative;height:440px}
#bfc .sc{position:absolute;inset:0;opacity:0;pointer-events:none;transition:opacity .45s}
#bfc .sc.on{opacity:1}
#bfc .bar{display:flex;align-items:center;gap:8px;border:1px solid #4a4945;border-radius:9px;background:#1d1d1b;padding:7px 10px}
#bfc .bar i{color:#9c9a93;font-style:normal}
#bfc .cur{display:inline-block;width:2px;height:14px;background:#6aa3ff;vertical-align:-2px;animation:bfcb 1s steps(1) infinite}
@keyframes bfcb{50%{opacity:0}}
#bfc .res{margin-top:10px;display:grid;gap:6px}
#bfc .row{display:flex;align-items:center;gap:9px;border:1px solid #33322f;border-radius:9px;background:#1d1d1b;padding:7px 10px;opacity:0;transform:translateY(6px);transition:opacity .3s,transform .3s,border-color .2s,background .2s}
#bfc .row.in{opacity:1;transform:none}
#bfc .row.pick{border-color:#3b82f6;background:#17233a}
#bfc .ck{flex:0 0 15px;height:15px;border-radius:4px;border:1.5px solid #6b6a66;position:relative}
#bfc .row.pick .ck{background:#3b82f6;border-color:#3b82f6}
#bfc .row.pick .ck:after{content:"";position:absolute;left:4px;top:1px;width:4px;height:8px;border:solid #fff;border-width:0 2px 2px 0;transform:rotate(45deg)}
#bfc .kind{font-size:10px;letter-spacing:.06em;color:#9c9a93;width:52px}
#bfc .kind.t{color:#e0a050}
#bfc .tools{display:flex;gap:8px;align-items:center;margin-top:10px}
#bfc .btn{display:inline-block;border:1px solid #4a4945;border-radius:7px;padding:3px 10px;font-size:12px;background:#22211f;color:#ecebe6;transition:transform .15s}
#bfc .btn.p{background:#3b82f6;border-color:#3b82f6;color:#fff}
#bfc .btn.press{transform:scale(.9)}
#bfc .menu{border:1px solid #4a4945;border-radius:9px;background:#1d1d1b;padding:6px 10px;font-size:12px;opacity:0;transition:opacity .25s}
#bfc .menu.on{opacity:1}
#bfc .fly{position:absolute;border:1px solid #3b82f6;border-radius:9px;background:#17233a;padding:7px 10px;font-size:13px;white-space:nowrap;overflow:hidden;transition:all .7s cubic-bezier(.6,-.2,.7,1);z-index:3}
#bfc .fly.go{left:calc(50% - 22px)!important;top:110px!important;width:44px!important;height:44px!important;border-radius:50%;opacity:0;color:transparent;background:#6aa3ff}
#bfc .orb{position:absolute;left:calc(50% - 38px);top:94px;width:76px;height:76px;border-radius:50%;background:#6aa3ff;color:#0d1b33;font-weight:700;display:flex;align-items:center;justify-content:center;text-align:center;font-size:13px;line-height:1.1;transform:scale(0);transition:transform .45s cubic-bezier(.3,1.6,.5,1);z-index:2}
#bfc .orb.on{transform:scale(1)}
#bfc .puff{position:absolute;width:10px;height:10px;border-radius:50%;background:#9fc2ff;left:calc(50% - 5px);top:127px;opacity:.9;transition:transform .6s ease-out,opacity .6s;z-index:1}
#bfc svg{display:block;width:100%;height:200px}
#bfc .lobe{fill:#1d1d1b;stroke:#33322f}
#bfc .spk{stroke:#4a4945;stroke-width:1.4;transition:opacity .4s}
#bfc .lnk{stroke:#6b6a66;stroke-width:1.2;stroke-dasharray:4 4;fill:none;transition:opacity .4s}
#bfc .nd{opacity:0;transition:opacity .4s}
#bfc .nd.on{opacity:1}
#bfc .nd text{fill:#9c9a93;font-size:11px;text-anchor:middle}
#bfc .nd.hot text{fill:#ecebe6;font-weight:700}
#bfc .nd.hot circle,#bfc .nd.hot rect{stroke-width:3.5}
#bfc .spin{transform-origin:360px 100px;transition:transform 1.6s cubic-bezier(.2,.8,.2,1)}
#bfc .spark{fill:#9fc2ff}
#bfc .lo{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:4px}
#bfc .notes{border:1px solid #3b82f6;border-radius:9px;background:#1d1d1b;padding:7px 9px;font-size:12.5px;min-height:96px}
#bfc .nhead{font:600 10px ui-monospace,Menlo,monospace;letter-spacing:.08em;color:#6aa3ff;margin-bottom:4px;display:flex;justify-content:space-between;align-items:center;gap:6px}
#bfc .newt{border:1px dashed #4a4945;border-radius:7px;padding:5px 7px;margin-top:6px;min-height:28px;font-size:12.5px}
#bfc .cards{display:flex;flex-direction:column;gap:5px}
#bfc .card{border:1px solid #33322f;border-radius:10px;background:#1d1d1b;padding:6px 9px;font-size:12px;opacity:0;transform:translateY(8px);transition:opacity .4s,transform .4s,border-color .4s,background .4s,box-shadow .4s}
#bfc .card.in{opacity:1;transform:none}
#bfc .card b{font-weight:600}
#bfc .card .m{display:flex;gap:5px;align-items:center;margin-top:3px;font-size:10.5px;color:#9c9a93}
#bfc .st{border:1px solid currentColor;border-radius:999px;padding:0 6px;white-space:nowrap}
#bfc .st.sent{color:#9c9a93;border-style:dashed}#bfc .st.ask{color:#f08a92}#bfc .st.done{color:#6cc08a}#bfc .st.mock{color:#e0a050}
#bfc .card.amber{border-color:#d99a00;box-shadow:inset 3px 0 0 #d99a00;background:#2a2416}
#bfc .ans{max-height:0;opacity:0;overflow:hidden;transition:max-height .5s,opacity .5s;margin-top:3px;padding-left:7px;border-left:2px solid #33322f;font-size:11.5px}
#bfc .ans.on{max-height:40px;opacity:1}
#bfc .esp{position:absolute;left:50%;top:6px;transform:translate(-50%,-10px);border:1px solid #c5a0f5;border-radius:999px;background:#2a2038;color:#ecebe6;font-size:12px;padding:5px 12px;opacity:0;transition:opacity .3s,transform .3s;z-index:5;white-space:nowrap}
#bfc .esp.on{opacity:1;transform:translate(-50%,0)}
#bfc .mock{position:absolute;left:18%;right:18%;top:40px;height:150px;border:2px solid #c5a0f5;border-radius:12px;background:#1d1d1b;padding:10px;opacity:0;transform:scale(.9);transition:all .5s;z-index:4}
#bfc .mock.on{opacity:1;transform:none}
#bfc .mock.away{opacity:0;transform:translate(160px,-40px) scale(.2)}
#bfc .mk1{height:18px;border-radius:5px;background:#33322f;margin-bottom:8px;width:60%}
#bfc .mk2{height:52px;border-radius:8px;background:#2e2419;border:1px solid #e0a050;margin-bottom:8px;display:flex;align-items:center;justify-content:center;color:#e0a050;font-size:12px}
#bfc .mk3{height:12px;border-radius:5px;background:#33322f;width:80%}
#bfc .ask{position:absolute;left:50%;top:110px;transform:translate(-50%,8px);width:320px;border:1px solid #4a4945;border-radius:12px;background:#22211f;padding:12px 14px;box-shadow:0 10px 30px rgba(0,0,0,.5);opacity:0;transition:opacity .3s,transform .3s;z-index:6}
#bfc .ask.on{opacity:1;transform:translate(-50%,0)}
#bfc .sw{display:inline-flex;border:1px solid #4a4945;border-radius:999px;overflow:hidden;font-size:11px;margin:8px 0}
#bfc .sw span{padding:3px 9px;transition:background .25s,color .25s}
#bfc .sw .on{background:#2e2419;color:#f0a35e;font-weight:700}
#bfc .shrink{transition:transform .7s,opacity .7s}
#bfc .shrink.go{transform:scale(.2);opacity:0}
#bfc .sentmsg{position:absolute;left:24px;top:150px;font-size:15px;color:#8fd19a;opacity:0;transition:opacity .5s}
#bfc .sentmsg.on{opacity:1}
#bfc .sentmsg small{display:block;color:#9c9a93;font-size:12px;margin-top:4px}
#bfc .pipe{position:absolute;right:0;top:20px;width:230px;bottom:10px;border-left:1px dashed #33322f;padding-left:12px;opacity:0;transition:opacity .4s}
#bfc .ph{font-size:10px;letter-spacing:.08em;color:#9c9a93;margin-bottom:8px}
#bfc .task{border:1px solid #3b6d41;background:#1f3d22;color:#8fd19a;border-radius:8px;padding:7px 9px;font-size:12px;margin-bottom:8px;opacity:0;transform:translateX(-180px) scale(.6);transition:all .7s cubic-bezier(.2,.8,.2,1)}
#bfc .task.on{opacity:1;transform:none}
#bfc .task b{color:#6aa3ff;font-weight:600;margin-right:4px}
</style>
<p class="cap" id="bfc-cap"></p>
<div class="stage" id="bfc-stage">
<div class="sc" id="bfc-s1">
<div class="bar"><i>⌕</i><span id="bfc-q"></span><span class="cur"></span></div>
<div class="res" id="bfc-res"></div>
<div class="tools"><span class="btn" id="bfc-addf">Add to a Focus ▾</span><span class="menu" id="bfc-menu">+ New Focus: <b id="bfc-fname"></b></span></div>
</div>
<div class="orb" id="bfc-orb">invite<br>flow</div>
<div class="sc" id="bfc-s3"><div class="shrink" id="bfc-mapw">
<svg viewBox="0 0 720 200"><g class="spin" id="bfc-spin">
<ellipse class="lobe" cx="215" cy="100" rx="160" ry="92"/><ellipse class="lobe" cx="505" cy="100" rx="160" ry="92"/>
<g id="bfc-edges"></g><g id="bfc-nodes"></g>
<circle cx="360" cy="100" r="34" fill="#6aa3ff"/><text x="360" y="96" text-anchor="middle" font-size="12" font-weight="700" fill="#0d1b33">invite</text><text x="360" y="110" text-anchor="middle" font-size="12" font-weight="700" fill="#0d1b33">flow</text>
<circle class="spark" id="bfc-spark" r="3" cx="360" cy="100" opacity="0"/>
</g></svg>
<div class="lo">
<div class="notes"><div class="nhead"><span>FOCUS · NEW THOUGHT</span><span><span class="btn" id="bfc-add">Add</span> <span class="btn p" id="bfc-send">Send focus</span></span></div><div class="newt"><span id="bfc-nt"></span><span class="cur"></span></div></div>
<div class="cards" id="bfc-cards"></div>
</div>
</div>
<div class="esp" id="bfc-esp">ESP · your designer is showing you: <b>Mockup · welcome card v1</b></div>
<div class="mock" id="bfc-mock"><div class="mk1"></div><div class="mk2">Welcome to Acme! Here's who to ask.</div><div class="mk3"></div></div>
<div class="ask" id="bfc-ask">Send this Focus to your designer: 5 thoughts, 3 topics and your notes?<br><span class="sw"><span id="bfc-one" class="on">one task</span><span id="bfc-split">split by feature</span></span><div style="text-align:right"><span class="btn p" id="bfc-go">Send</span></div></div>
<div class="sentmsg" id="bfc-sent">✓ <b>invite flow</b> sent<small>split by feature: one task each</small></div>
<div class="pipe" id="bfc-pipe"><div class="ph">PIPELINE</div><div class="task" id="bfc-t1"><b>P-1201</b>invites: what to do when one expires</div><div class="task" id="bfc-t2"><b>P-1202</b>onboarding: the welcome card, as in the mockup</div><div class="task" id="bfc-t3"><b>P-1203</b>email: invites pass Gmail's checks</div></div>
</div>
</div>
<script type="text/lazy">
(()=>{const $=i=>document.getElementById("bfc-"+i),sl=ms=>new Promise(r=>setTimeout(r,ms)),NS="http://www.w3.org/2000/svg";
const cap=h=>{$("cap").innerHTML=h};
async function type(el,s,ms){el.textContent="";for(const c of s){el.textContent+=c;await sl(ms||42)}}
async function press(b){b.classList.add("press");await sl(220);b.classList.remove("press")}
const R=[["THOUGHT","expired invite shows a raw error",1],["TOPIC","Invites",1],["THOUGHT","invite emails land in spam",0],["THOUGHT","welcome card after joining",1],["TOPIC","Invite settings",0]];
// the map: topics right; the model left (violet classes, teal features); [kind,label,x,y,shown from the start]
const N=[["t","Invites",500,38,1],["t","Onboarding",610,135,1],["c","Invite",170,40,1],["c","Member",108,112,1],["f","Joining a project",290,48,1],["c","Project",210,172,0],["f","Email",470,170,0],["t","Mockup v1",640,60,0]];
const col={t:"#e0a050",c:"#a98ae8",f:"#4fb8a8"};
function draw(){const e=$("edges"),n=$("nodes");e.innerHTML="";n.innerHTML="";
N.forEach((x,i)=>{const l=document.createElementNS(NS,"line");l.setAttribute("class","spk");l.setAttribute("x1",360);l.setAttribute("y1",100);l.setAttribute("x2",x[2]);l.setAttribute("y2",x[3]);l.style.opacity=0;l.id="bfc-l"+i;e.appendChild(l);
const g=document.createElementNS(NS,"g");g.setAttribute("class","nd");g.id="bfc-n"+i;
g.innerHTML=(x[0]==="t"?`<rect x="${x[2]-12}" y="${x[3]-12}" width="24" height="24" rx="6" fill="#1d1d1b" stroke="${col.t}" stroke-width="2"/>`:`<circle cx="${x[2]}" cy="${x[3]}" r="9" fill="#1d1d1b" stroke="${col[x[0]]}" stroke-width="2"/>`)+`<text x="${x[2]}" y="${x[3]+(x[3]<100?-16:24)}">${x[1]}</text>`;n.appendChild(g)})}
const show=i=>{$("l"+i).style.opacity=1;$("n"+i).classList.add("on")};
async function spark(i){const s=$("spark"),x=N[i];s.setAttribute("opacity",1);for(let k=0;k<=10;k++){s.setAttribute("cx",360+(x[2]-360)*k/10);s.setAttribute("cy",100+(x[3]-100)*k/10);await sl(26)}s.setAttribute("opacity",0)}
function hot(names){N.forEach((x,i)=>$("n"+i).classList.toggle("hot",names.includes(x[1])))}
function card(t,st,sc){const c=document.createElement("div");c.className="card";c.innerHTML=`<b>${t}</b><div class="ans"></div><div class="m"><span class="st ${sc||"sent"}">${st}</span></div>`;$("cards").prepend(c);setTimeout(()=>c.classList.add("in"),30);while($("cards").children.length>4)$("cards").lastChild.remove();return c}
async function run(){for(;;){
["s1","s3"].forEach(s=>$(s).classList.remove("on"));$("orb").classList.remove("on");["ask","esp","mock","sent"].forEach(k=>$(k).classList.remove("on"));$("mock").classList.remove("away");$("pipe").style.opacity=0;["t1","t2","t3"].forEach(t=>$(t).classList.remove("on"));
$("mapw").classList.remove("go");$("res").innerHTML="";$("menu").classList.remove("on");$("fname").textContent="";$("nt").textContent="";$("q").textContent="";$("cards").innerHTML="";$("one").className="on";$("split").className="";
draw();$("spin").style.transition="none";$("spin").style.transform="rotate(-140deg) scale(.4)";
// 1 search, tick, add to a new Focus
$("s1").classList.add("on");cap("<b>1 · Search</b> for what's on your mind");await sl(500);await type($("q"),"invite",100);await sl(300);
const rows=R.map(r=>{const d=document.createElement("div");d.className="row";d.innerHTML=`<span class="ck"></span><span class="kind${r[0]==="TOPIC"?" t":""}">${r[0]}</span><span>${r[1]}</span>`;$("res").appendChild(d);return d});
for(const d of rows){d.classList.add("in");await sl(130)}await sl(400);
cap("<b>2 · Tick</b> what belongs together");for(let i=0;i<R.length;i++)if(R[i][2]){rows[i].classList.add("pick");await sl(480)}
await sl(250);cap("<b>3 · Add to a Focus</b>, a new one");await press($("addf"));$("menu").classList.add("on");await sl(350);await type($("fname"),"invite flow",65);await sl(500);
// poof
const st=$("stage"),box=st.getBoundingClientRect(),fl=[];
rows.forEach((d,i)=>{if(!R[i][2])return;const r=d.getBoundingClientRect(),f=document.createElement("div");f.className="fly";f.textContent=d.textContent.replace(/^(THOUGHT|TOPIC)/,"");f.style.left=(r.left-box.left)+"px";f.style.top=(r.top-box.top)+"px";f.style.width=r.width+"px";f.style.height=r.height+"px";st.appendChild(f);fl.push(f)});
$("s1").classList.remove("on");await sl(60);fl.forEach((f,i)=>setTimeout(()=>f.classList.add("go"),i*110));await sl(780);
$("orb").classList.add("on");const pf=[];for(let k=0;k<10;k++){const p=document.createElement("div");p.className="puff";st.appendChild(p);pf.push(p)}
await sl(30);pf.forEach((p,k)=>{const a=k/10*6.283;p.style.transform=`translate(${Math.cos(a)*70}px,${Math.sin(a)*70}px) scale(.3)`;p.style.opacity=0});
cap("<b>Poof:</b> they're one Focus now");await sl(850);fl.concat(pf).forEach(x=>x.remove());
// the map spins in
$("orb").classList.remove("on");$("s3").classList.add("on");await sl(50);$("spin").style.transition="";$("spin").style.transform="rotate(0) scale(1)";
card("welcome card after joining","in focus");card("expired invite shows a raw error","in focus");
cap("<b>4 · The map</b>: its topics on the right, the model they name on the left");await sl(700);
for(let i=0;i<N.length;i++)if(N[i][4]){show(i);await sl(200)}await spark(0);await spark(2);await sl(300);
// three new thoughts, each joins and lights the map
const T=[["a new Member should see who to ask",["Member"],[]],["the Project's welcome card names its admin",["Project"],[5]],["invite email: say when the link expires",["Email","Invite"],[6]]];
let k=0;for(const [t,h,add] of T){k++;cap(`<b>5 · Think it through:</b> thought ${k} of 3 joins the Focus, and lights what it names`);
await type($("nt"),t,34);await sl(250);await press($("add"));$("nt").textContent="";card(t,"in focus");for(const i of add){show(i);spark(i)}hot(h);await sl(1100)}hot([]);
// thread now on one; the answer comes back into it
cap("<b>6 · One question?</b> Thread now on that thought: the answer comes back into it");
const c=$("cards").children[0];c.querySelector(".st").textContent="with designer";await sl(1400);
const a=c.querySelector(".ans");a.innerHTML="<b>designer:</b> say it in the email and on the page?";a.classList.add("on");c.classList.add("amber");c.querySelector(".st").className="st ask";c.querySelector(".st").textContent="ai-question";await sl(1800);
// a mockup, shown with ESP, joins
cap("<b>7 · Ask for a mockup:</b> your designer shows it to you on the spot");$("esp").classList.add("on");await sl(500);$("mock").classList.add("on");await sl(2000);
cap("<b>Like it?</b> It joins the Focus");$("esp").classList.remove("on");$("mock").classList.add("away");await sl(500);show(7);spark(7);hot(["Mockup v1"]);card("Mockup · welcome card v1","topic","mock");await sl(1300);hot([]);
// send it, split by feature
cap("<b>8 · Send focus</b>: as one task, or split by feature");await press($("send"));$("ask").classList.add("on");await sl(1100);
$("one").className="";$("split").className="on";await sl(900);await press($("go"));$("ask").classList.remove("on");
$("mapw").classList.add("go");$("pipe").style.opacity=1;$("sent").classList.add("on");await sl(500);cap("<b>9 · Pipeline</b>: one task per feature, picked up by your agents");
for(const t of ["t1","t2","t3"]){$(t).classList.add("on");await sl(550)}await sl(3600)}}
run()})();
</script>
</div>
</div>
</div>
</section>
<script>
/* P-1284 (razie 2026-10-11: "the animations should start when scrolling into frame"): a section's animation starts the first time it scrolls into view */
document.querySelectorAll('section').forEach(function(sec){
var ss=sec.querySelectorAll('script[type="text/lazy"]'),fs=sec.querySelectorAll('iframe[data-srcdoc]');if(!ss.length&&!fs.length)return;var done=false;
window.lpView(sec,function(){if(done)return;done=true;
fs.forEach(function(f){f.srcdoc=f.getAttribute('data-srcdoc')});
ss.forEach(function(o){var n=document.createElement('script');n.textContent=o.textContent;o.parentNode.replaceChild(n,o)})});
});
</script>
<footer>
<div class="wrap">
This page is an early sketch; the notebook isn't open yet.
</div>
</footer>
<script>
(function(){
// source view built in JS so no line of this page starts with a DSL marker
var D = String.fromCharCode(36);
var src = [
'<span class="c">// a holding, and a rule that watches it</span>',
D + '<span class="k">class</span> Holding (portfolio: <>Portfolio,',
' company: <>Company, shares: Number)',
'',
D + '<span class="k">when</span> price.changed (company, move) {',
' <span class="k">if</span> (move > 5) {',
' notify (text = company.name + <span class="s">" moved "</span> + move + <span class="s">"%"</span>)',
' }',
'}',
'',
D + '<span class="k">send</span> price.changed (company = <span class="s">"FRST"</span>, move = 4.2)',
D + '<span class="k">expect</span> (notified is false)'
].join('\n');
var pre = document.getElementById('srcpre'); if (pre) pre.innerHTML = src; // the source view was removed from the page; don't let its leftover script stop the rest
// hero door: see the talk-it-into-existence section (its own script)
// modeller stage
var screens = {
co: ['/app/Company', '<h4>Companies <small>3 records</small></h4>' +
'<div class="tools"><span class="act">List</span><span>Group by stage</span><span>Map</span><span>+ New</span></div>' +
'<div class="gl">' +
'<div class="gr"><b>Frostline Resources</b><span class="ref">2 deposits</span><span class="stg">explorer</span></div>' +
'<div class="gr"><b>Copperhead Mining</b><span class="ref">1 deposit</span><span class="stg">producer</span></div>' +
'<div class="gr"><b>North Royalty & Streaming</b><span class="ref">5 royalties</span><span class="stg">royalty</span></div>' +
'</div>'],
dep: ['/app/Deposit?view=map', '<h4>Deposits <small>on a map, because they have lat and lon</small></h4>' +
'<div class="map">' +
'<b style="left:24%;top:30%;background:#f2b84b"></b><em style="left:24%;top:30%">Aurora (Au)</em>' +
'<b style="left:58%;top:58%;background:#c46a3a"></b><em style="left:58%;top:58%">Red Creek (Cu)</em>' +
'<b style="left:44%;top:18%;background:#f2b84b"></b><em style="left:44%;top:18%">Frost Ridge (Au)</em>' +
'</div>' +
'<div class="tools"><span>List</span><span class="act">Map</span><span>Filter by commodity</span></div>'],
hold: ['/app/Holding', '<h4>Holdings <small>references become links</small></h4>' +
'<div class="tools"><span class="act">List</span><span>Sum by company</span><span>+ New</span></div>' +
'<div class="gl">' +
'<div class="gr"><span>1,200 shares</span><span class="ref">Company: Frostline</span><span class="stg">+4.2%</span></div>' +
'<div class="gr"><span>800 shares</span><span class="ref">Company: Copperhead</span><span class="stg">−1.1%</span></div>' +
'<div class="gr"><span>350 shares</span><span class="ref">Company: North Royalty</span><span class="stg">+0.6%</span></div>' +
'</div>']
};
var nodes = document.querySelectorAll('#stage .node');
var screen = document.getElementById('screen'), url = document.getElementById('url');
function show(c){
nodes.forEach(function(n){ n.classList.toggle('on', n.getAttribute('data-c') === c); n.setAttribute('aria-pressed', n.getAttribute('data-c') === c ? 'true' : 'false'); });
url.textContent = screens[c][0]; screen.innerHTML = screens[c][1];
}
nodes.forEach(function(n){
n.addEventListener('click', function(){ show(n.getAttribute('data-c')); });
n.addEventListener('keydown', function(e){ if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); show(n.getAttribute('data-c')); } });
});
if (url && screen) show('co'); // the modeller stage was removed from the page
// notebook stage
var price = 1.42, series = [1.18,1.21,1.2,1.26,1.24,1.3,1.29,1.35,1.33,1.42];
function spark(){
var mn = Math.min.apply(null, series), mx = Math.max.apply(null, series), w = 300, h = 60;
return series.map(function(v, i){
var x = (i / (series.length - 1)) * w, y = h - ((v - mn) / ((mx - mn) || 1)) * (h - 8) - 4;
return (i ? 'L' : 'M') + x.toFixed(1) + ' ' + y.toFixed(1);
}).join(' ');
}
var scenes = {
cap: function(){ return '' +
'<div class="bub me">Why did I buy Frostline again?</div>' +
'<div class="bub ai">You liked the drill results at Frost Ridge and planned to add more before the October assays.</div>' +
'<div class="bub me">Keep that somewhere, please.</div>' +
'<div class="saved pop"><span class="ic">✓</span><div>Saved to <b>My gold juniors</b><small>with the chat it came from, no copy and paste</small></div></div>'; },
con: function(){ return '' +
'<div class="web"><svg viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true">' +
'<path d="M50 50 L20 18"/><path d="M50 50 L82 20"/><path d="M50 50 L18 84"/><path d="M50 50 L82 82"/></svg>' +
'<div class="n hub" style="left:50%;top:50%">My gold juniors</div>' +
'<div class="n" style="left:22%;top:16%">Frostline Resources<small>a company you track</small></div>' +
'<div class="n" style="left:78%;top:18%">Tuesday\'s chat<small>where the idea came from</small></div>' +
'<div class="n" style="left:22%;top:84%">October assays<small>on your calendar</small></div>' +
'<div class="n" style="left:78%;top:84%">Buying rules<small>your own guide</small></div>' +
'</div>'; },
alive: function(){ return '' +
'<div class="live"><h5>Frostline Resources</h5><div class="sub">in My gold juniors, updated just now</div>' +
'<div class="px"><b id="px">$' + price.toFixed(2) + '</b><span class="up" id="chg">+' + ((price / 1.35 - 1) * 100).toFixed(1) + '% today</span></div>' +
'<svg viewBox="0 0 300 64" preserveAspectRatio="none" aria-hidden="true"><path id="spk" d="' + spark() + '"/></svg></div>' +
'<div class="toast pop"><span class="ic">!</span><div><b>Up more than 5% today.</b> You asked to hear about big moves before the assays.</div></div>' +
'<div class="ticker"><button type="button" class="btn ghost" id="tick">Refresh prices</button></div>'; }
};
var scene = document.getElementById('scene');
var segs = document.querySelectorAll('.seg button');
function showScene(k){
segs.forEach(function(b){ b.setAttribute('aria-pressed', b.getAttribute('data-s') === k ? 'true' : 'false'); });
scene.innerHTML = scenes[k]();
var t = document.getElementById('tick');
if (t) t.addEventListener('click', function(){
price = Math.round((price + (Math.random() * 0.08 - 0.02)) * 100) / 100;
series.push(price); series.shift();
document.getElementById('px').textContent = '$' + price.toFixed(2);
document.getElementById('chg').textContent = '+' + ((price / 1.35 - 1) * 100).toFixed(1) + '% today';
document.getElementById('spk').setAttribute('d', spark());
});
}
segs.forEach(function(b){ b.addEventListener('click', function(){ showScene(b.getAttribute('data-s')); }); });
showScene('cap');
})();
</script>
<script>document.querySelectorAll('a[aria-disabled="true"]').forEach(a=>a.addEventListener("click",e=>e.preventDefault()))</script><script>
// signed in? the landing's Log in becomes My home (what the server did for builtin:landing)
fetch('/api/v2/me',{credentials:'same-origin'}).then(function(r){return r.ok?r.json():null;}).then(function(me){
var u=me&&(me.user||me.data||me); if(!u||!(u.email||u.id||u.name)) return;
var l=document.getElementById('login'); if(l){l.textContent='My home';l.href='/home';}
var s=document.querySelector('nav[aria-label="Site"] .signup'); if(s) s.remove();
}).catch(function(){});
</script>
</body>
</html>