1---
2import { getImage } from "astro:assets";
3import desktopScreenshot from "../assets/app-desktop.webp";
4import Layout from "../layouts/Layout.astro";
5import {
6 ANDROID_PLAY_STORE_URL,
7 GITHUB_REPOSITORY_URL,
8 IOS_APP_STORE_URL,
9 MARKETING_STATS,
10} from "../lib/site";
11import { tweets } from "../lib/tweets";
12
13const screenshot = await getImage({
14 src: desktopScreenshot,
15 widths: [864, 1180, 1728, 2360],
16 format: "webp",
17 quality: 90,
18});
19
20const desktopEndorsementRows = [
21 tweets.filter((_, index) => index % 2 === 0),
22 tweets.filter((_, index) => index % 2 === 1),
23];
24
25const mobileEndorsementRows = [
26 tweets.filter((_, index) => index % 3 === 0),
27 tweets.filter((_, index) => index % 3 === 1),
28 tweets.filter((_, index) => index % 3 === 2),
29];
30---
31
32<Layout>
33 <!-- ── Hero ──────────────────────────────────────────────────── -->
34 <section class="hero">
35 <div class="hero-grid" aria-hidden="true"></div>
36
37 <div class="hero-float" aria-hidden="true">
38 {[
39 { key: "opencode", icon: "/harnesses/opencode-dark.svg", cls: "hf-opencode" },
40 { key: "antigravity", icon: "/harnesses/antigravity.svg", cls: "hf-antigravity" },
41 { key: "claude", icon: "/harnesses/claude-ai-icon.svg", cls: "hf-claude" },
42 { key: "codex", icon: "/harnesses/openai_dark.svg", cls: "hf-codex" },
43 { key: "grok", icon: "/harnesses/grok-dark.svg", cls: "hf-grok" },
44 { key: "cursor", icon: "/harnesses/cursor_light.svg", cls: "hf-cursor" },
45 ].map((m) => (
46 <span class:list={["hero-float-mark", m.cls]}>
47 <span class="hero-float-card"><img src={m.icon} alt="" /></span>
48 </span>
49 ))}
50 </div>
51
52 <div class="container hero-inner">
53 <h1 class="hero-title display">
54 <span data-rise>The open-source</span><br /><span data-rise style="--d:90ms">control plane</span><br /><span data-rise style="--d:180ms">for coding agents.</span>
55 </h1>
56
57 <p class="hero-sub" data-rise style="--d:300ms">
58 Orchestrate Claude Code, Codex, Antigravity, OpenCode, Cursor, and Grok from one surface.
59 Bring your own subscription. Fork the whole thing.
60 </p>
61
62 <div class="hero-actions" data-rise style="--d:400ms">
63 <a
64 id="download-btn"
65 href="https://github.com/pingdotgg/t3code/releases"
66 class="btn btn-primary btn-lg"
67 >
68 <svg class="dl-icon dl-icon--apple" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 814 1000" aria-hidden="true"><path fill="currentColor" d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/></svg>
69 <svg class="dl-icon dl-icon--windows" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88 88" aria-hidden="true"><path fill="currentColor" d="m0 12.402 35.687-4.86.016 34.423-35.67.203zm35.67 33.529.028 34.453L.028 75.48.026 45.7zm4.326-39.025L87.314 0v41.527l-47.318.376zm47.329 39.349-.011 41.34-47.318-6.678-.066-34.739z"/></svg>
70 <svg class="dl-icon dl-icon--linux" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M12.504 0c-.155 0-.315.008-.48.021-4.226.333-3.105 4.807-3.17 6.298-.076 1.092-.3 1.953-1.05 3.02-.885 1.051-2.127 2.75-2.716 4.521-.278.832-.41 1.684-.287 2.489a.424.424 0 00-.11.135c-.26.268-.45.6-.663.839-.199.199-.485.267-.797.4-.313.136-.658.269-.864.68-.09.189-.136.394-.132.602 0 .199.027.4.055.536.058.399.116.728.04.97-.249.68-.28 1.145-.106 1.484.174.334.535.47.94.601.81.2 1.91.135 2.774.6.926.466 1.866.67 2.616.47.526-.116.97-.464 1.208-.946.587-.003 1.23-.269 2.26-.334.699-.058 1.574.267 2.577.2.025.134.063.198.114.333l.003.003c.391.778 1.113 1.132 1.884 1.071.771-.06 1.592-.536 2.257-1.306.631-.765 1.683-1.084 2.378-1.503.348-.199.629-.469.649-.853.023-.4-.2-.811-.714-1.376v-.097l-.003-.003c-.17-.2-.25-.535-.338-.926-.085-.401-.182-.786-.492-1.046h-.003c-.059-.054-.123-.067-.188-.135a.357.357 0 00-.19-.064c.431-1.278.264-2.55-.173-3.694-.533-1.41-1.465-2.638-2.175-3.483-.796-1.005-1.576-1.957-1.56-3.368.026-2.152.236-6.133-3.544-6.139zm.529 3.405h.013c.213 0 .396.062.584.198.19.135.33.332.438.533.105.259.158.459.166.724 0-.02.006-.04.006-.06v.105a.086.086 0 01-.004-.021l-.004-.024a1.807 1.807 0 01-.15.706.953.953 0 01-.213.335.71.71 0 00-.088-.042c-.104-.045-.198-.064-.284-.133a1.312 1.312 0 00-.22-.066c.05-.06.146-.133.183-.198.053-.128.082-.264.088-.402v-.02a1.21 1.21 0 00-.061-.4c-.045-.134-.101-.2-.183-.333-.084-.066-.167-.132-.267-.132h-.016c-.093 0-.176.03-.262.132a.8.8 0 00-.205.334 1.18 1.18 0 00-.09.4v.019c.002.089.008.179.02.267-.193-.067-.438-.135-.607-.202a1.635 1.635 0 01-.018-.2v-.02a1.772 1.772 0 01.15-.768c.082-.22.232-.406.43-.533a.985.985 0 01.594-.2zm-2.962.059h.036c.142 0 .27.048.399.135.146.129.264.288.344.465.09.199.14.4.153.667v.004c.007.134.006.2-.002.266v.08c-.03.007-.056.018-.083.024-.152.055-.274.135-.393.2.012-.09.013-.18.003-.267v-.015c-.012-.133-.04-.2-.082-.333a.613.613 0 00-.166-.267.248.248 0 00-.183-.064h-.021c-.071.006-.13.04-.186.132a.552.552 0 00-.12.27.944.944 0 00-.023.33v.015c.012.135.037.2.08.334.046.134.098.2.166.268.01.009.02.018.034.024-.07.057-.117.07-.176.136a.304.304 0 01-.131.068 2.62 2.62 0 01-.275-.402 1.772 1.772 0 01-.155-.667 1.759 1.759 0 01.08-.668 1.43 1.43 0 01.283-.535c.128-.133.26-.2.418-.2zm1.37 1.706c.332 0 .733.065 1.216.399.293.2.523.269 1.052.468h.003c.255.136.405.266.478.399v-.131a.571.571 0 01.016.47c-.123.31-.516.643-1.063.842v.002c-.268.135-.501.333-.775.465-.276.135-.588.292-1.012.267a1.139 1.139 0 01-.448-.067 3.566 3.566 0 01-.322-.198c-.195-.135-.363-.332-.612-.465v-.005h-.005c-.4-.246-.616-.512-.686-.71-.07-.268-.005-.47.193-.6.224-.135.38-.271.483-.336.104-.074.143-.102.176-.131h.002v-.003c.169-.202.436-.47.839-.601.139-.036.294-.065.466-.065zm2.8 2.142c.358 1.417 1.196 3.475 1.735 4.473.286.534.855 1.659 1.102 3.024.156-.005.33.018.513.064.646-1.671-.546-3.467-1.089-3.966-.22-.2-.232-.335-.123-.335.59.534 1.365 1.572 1.646 2.757.13.535.16 1.104.021 1.67.067.028.135.06.205.067 1.032.534 1.413.938 1.23 1.537v-.043c-.06-.003-.12 0-.18 0h-.016c.151-.467-.182-.825-1.065-1.224-.915-.4-1.646-.336-1.77.465-.008.043-.013.066-.018.135-.068.023-.139.053-.209.064-.43.268-.662.669-.793 1.187-.13.533-.17 1.156-.205 1.869v.003c-.02.334-.17.838-.319 1.35-1.5 1.072-3.58 1.538-5.348.334a2.645 2.645 0 00-.402-.533 1.45 1.45 0 00-.275-.333c.182 0 .338-.03.465-.067a.615.615 0 00.314-.334c.108-.267 0-.697-.345-1.163-.345-.467-.931-.995-1.788-1.521-.63-.4-.986-.87-1.15-1.396-.165-.534-.143-1.085-.015-1.645.245-1.07.873-2.11 1.274-2.763.107-.065.037.135-.408.974-.396.751-1.14 2.497-.122 3.854a8.123 8.123 0 01.647-2.876c.564-1.278 1.743-3.504 1.836-5.268.048.036.217.135.289.202.218.133.38.333.59.465.21.201.477.335.876.335.039.003.075.006.11.006.412 0 .73-.134.997-.268.29-.134.52-.334.74-.4h.005c.467-.135.835-.402 1.044-.7zm2.185 8.958c.037.6.343 1.245.882 1.377.588.134 1.434-.333 1.791-.765l.211-.01c.315-.007.577.01.847.268l.003.003c.208.199.305.53.391.876.085.4.154.78.409 1.066.486.527.645.906.636 1.14l.003-.007v.018l-.003-.012c-.015.262-.185.396-.498.595-.63.401-1.746.712-2.457 1.57-.618.737-1.37 1.14-2.036 1.191-.664.053-1.237-.2-1.574-.898l-.005-.003c-.21-.4-.12-1.025.056-1.69.176-.668.428-1.344.463-1.897.037-.714.076-1.335.195-1.814.12-.465.308-.797.641-.984l.045-.022zm-10.814.049h.01c.053 0 .105.005.157.014.376.055.706.333 1.023.752l.91 1.664.003.003c.243.533.754 1.064 1.189 1.637.434.598.77 1.131.729 1.57v.006c-.057.744-.48 1.148-1.125 1.294-.645.135-1.52.002-2.395-.464-.968-.536-2.118-.469-2.857-.602-.369-.066-.61-.2-.723-.4-.11-.2-.113-.602.123-1.23v-.004l.002-.003c.117-.334.03-.752-.027-1.118-.055-.401-.083-.71.043-.94.16-.334.396-.4.69-.533.294-.135.64-.202.915-.47h.002v-.002c.256-.268.445-.601.668-.838.19-.201.38-.336.663-.336zm7.159-9.074c-.435.201-.945.535-1.488.535-.542 0-.97-.267-1.28-.466-.154-.134-.28-.268-.373-.335-.164-.134-.144-.333-.074-.333.109.016.129.134.199.2.096.066.215.2.36.333.292.2.68.467 1.167.467.485 0 1.053-.267 1.398-.466.195-.135.445-.334.648-.467.156-.136.149-.267.279-.267.128.016.034.134-.147.332a8.097 8.097 0 01-.69.468zm-1.082-1.583V5.64c-.006-.02.013-.042.029-.05.074-.043.18-.027.26.004.063 0 .16.067.15.135-.006.049-.085.066-.135.066-.055 0-.092-.043-.141-.068-.052-.018-.146-.008-.163-.065zm-.551 0c-.02.058-.113.049-.166.066-.047.025-.086.068-.14.068-.05 0-.13-.02-.136-.068-.01-.066.088-.133.15-.133.08-.031.184-.047.259-.005.019.009.036.03.03.05v.02h.003z"/></svg>
71 <span id="download-label">Download for macOS</span>
72 </a>
73 <a class="hero-source-link" href={GITHUB_REPOSITORY_URL} target="_blank" rel="noopener noreferrer">
74 <svg class="hero-source-mark" width="15" height="15" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
75 <path d="M12 .5C5.65.5.5 5.65.5 12a11.5 11.5 0 007.86 10.93c.58.1.79-.25.79-.56v-2c-3.2.69-3.88-1.37-3.88-1.37-.52-1.33-1.27-1.69-1.27-1.69-1.04-.71.08-.7.08-.7 1.15.08 1.76 1.18 1.76 1.18 1.02 1.76 2.68 1.25 3.33.96.1-.75.4-1.25.72-1.54-2.55-.29-5.24-1.27-5.24-5.67 0-1.25.45-2.28 1.18-3.08-.12-.29-.51-1.45.11-3.02 0 0 .96-.31 3.15 1.18a10.96 10.96 0 015.74 0c2.19-1.49 3.15-1.18 3.15-1.18.62 1.57.23 2.73.11 3.02.74.8 1.18 1.83 1.18 3.08 0 4.41-2.7 5.38-5.27 5.66.41.36.78 1.06.78 2.13v3.16c0 .31.21.67.8.56A11.5 11.5 0 0023.5 12C23.5 5.65 18.35.5 12 .5z"/>
76 </svg>
77 <span>Steal our code (legally)</span>
78 <svg class="hero-source-arrow" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M7 17L17 7M8 7h9v9"/></svg>
79 </a>
80 <p class="hero-mobile-line">
81 Also on your phone:
82 <a href={IOS_APP_STORE_URL} target="_blank" rel="noopener noreferrer">iOS</a>
83 <span aria-hidden="true">·</span>
84 <a href={ANDROID_PLAY_STORE_URL} target="_blank" rel="noopener noreferrer">Android</a>
85 </p>
86 </div>
87
88 <!-- The rise wrapper is separate so its animated transform does not override the preview tilt. -->
89 <div data-rise style="--d:520ms">
90 <div class="hero-preview">
91 <figure class="hero-screenshot-frame">
92 <picture>
93 <!-- Match the hidden mobile layout without requesting a screenshot. -->
94 <source
95 media="(max-width: 820px)"
96 srcset="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
97 />
98 <img
99 src={desktopScreenshot.src}
100 srcset={`${screenshot.srcSet.attribute}, ${desktopScreenshot.src} ${desktopScreenshot.width}w`}
101 sizes="(max-width: 960px) min(864px, calc(100vw - 20px)), min(1180px, calc(100vw - 60px))"
102 alt="T3 Code with a settled thread beside its pull request diff"
103 width={desktopScreenshot.width}
104 height={desktopScreenshot.height}
105 loading="eager"
106 decoding="async"
107 />
108 </picture>
109 </figure>
110 </div>
111 </div>
112 </div>
113 </section>
114
115 <!-- ── Endorsements ─────────────────────────────────────────── -->
116 <section id="endorsements" class="sec-endorsements" aria-labelledby="endorsements-title">
117 <div class="container">
118 <div class="endorsements-head">
119 <h2 id="endorsements-title">Tolerated by over <span class="endorsements-count">{MARKETING_STATS.users}</span> devs</h2>
120 <p>Some of them even tweeted about it.</p>
121 </div>
122 </div>
123
124 <div class="endorsement-carousel endorsement-carousel--desktop" aria-label="Developer endorsements">
125 {
126 desktopEndorsementRows.map((row, rowIndex) => (
127 <div class:list={["endorsement-row", rowIndex === 1 && "is-reverse"]}>
128 <div class="endorsement-track">
129 {[0, 1].map((groupIndex) => (
130 <div class="endorsement-track-group" aria-hidden={groupIndex === 1 ? "true" : undefined}>
131 {row.map((tweet) => (
132 <a
133 class="endorsement-card"
134 href={tweet.link}
135 target="_blank"
136 rel="noopener noreferrer"
137 aria-label={`Read ${tweet.handle}'s post on X`}
138 tabindex={groupIndex === 1 ? "-1" : undefined}
139 >
140 <div class="endorsement-author">
141 <img
142 src={`/pfps/${tweet.handle}.webp`}
143 alt=""
144 width="28"
145 height="28"
146 loading="lazy"
147 decoding="async"
148 />
149 <div class="endorsement-handle">@{tweet.handle}</div>
150 </div>
151 <p>{tweet.excerpt ?? tweet.content}</p>
152 </a>
153 ))}
154 </div>
155 ))}
156 </div>
157 </div>
158 ))
159 }
160 </div>
161
162 <div class="endorsement-carousel endorsement-carousel--mobile" aria-label="Developer endorsements">
163 {
164 mobileEndorsementRows.map((row, rowIndex) => (
165 <div class:list={["endorsement-row", rowIndex === 1 && "is-reverse"]}>
166 <div class="endorsement-track">
167 {[0, 1].map((groupIndex) => (
168 <div class="endorsement-track-group" aria-hidden={groupIndex === 1 ? "true" : undefined}>
169 {row.map((tweet) => (
170 <a
171 class="endorsement-card"
172 href={tweet.link}
173 target="_blank"
174 rel="noopener noreferrer"
175 aria-label={`Read ${tweet.handle}'s post on X`}
176 tabindex={groupIndex === 1 ? "-1" : undefined}
177 >
178 <div class="endorsement-author">
179 <img
180 src={`/pfps/${tweet.handle}.webp`}
181 alt=""
182 width="28"
183 height="28"
184 loading="lazy"
185 decoding="async"
186 />
187 <div class="endorsement-handle">@{tweet.handle}</div>
188 </div>
189 <p>{tweet.excerpt ?? tweet.content}</p>
190 </a>
191 ))}
192 </div>
193 ))}
194 </div>
195 </div>
196 ))
197 }
198 </div>
199 </section>
200
201 <!-- ── Harnesses ─────────────────────────────────────────────── -->
202 <section id="harnesses" class="sec-harness">
203 <div class="container">
204 <div class="section-head">
205 <h2>Bring your own sub</h2>
206 <p>
207 T3 Code doesn't resell tokens. Plug in Claude Code, Codex, Antigravity,
208 OpenCode, Cursor, or Grok with the credentials you already have. We
209 orchestrate them, you keep your plan.
210 </p>
211 </div>
212
213 <div class="harness-grid">
214 <div class="harness">
215 <div class="harness-mark"><img src="/harnesses/claude-ai-icon.svg" alt="" /></div>
216 <div class="harness-meta">
217 <div class="harness-name">Claude Code</div>
218 <div class="harness-tag">claude auth login</div>
219 </div>
220 </div>
221 <div class="harness">
222 <div class="harness-mark"><img src="/harnesses/openai_dark.svg" alt="" /></div>
223 <div class="harness-meta">
224 <div class="harness-name">Codex CLI</div>
225 <div class="harness-tag">codex login</div>
226 </div>
227 </div>
228 <div class="harness">
229 <div class="harness-mark"><img src="/harnesses/opencode-dark.svg" alt="" /></div>
230 <div class="harness-meta">
231 <div class="harness-name">OpenCode</div>
232 <div class="harness-tag">opencode auth</div>
233 </div>
234 </div>
235 <div class="harness">
236 <div class="harness-mark"><img src="/harnesses/cursor_light.svg" alt="" /></div>
237 <div class="harness-meta">
238 <div class="harness-name">Cursor</div>
239 <div class="harness-tag">@cursor/sdk</div>
240 </div>
241 </div>
242 <div class="harness">
243 <div class="harness-mark"><img src="/harnesses/grok-dark.svg" alt="" /></div>
244 <div class="harness-meta">
245 <div class="harness-name">Grok CLI</div>
246 <div class="harness-tag">grok login</div>
247 </div>
248 </div>
249 <div class="harness">
250 <div class="harness-mark"><img src="/harnesses/antigravity.svg" alt="" /></div>
251 <div class="harness-meta">
252 <div class="harness-name">Antigravity</div>
253 <div class="harness-tag">Google sign-in</div>
254 </div>
255 </div>
256 </div>
257
258 <div class="harness-footer">
259 <div class="harness-footer-item"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> No keys resold. No quota caps.</div>
260 <div class="harness-footer-item"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> Switch models mid-thread.</div>
261 <div class="harness-footer-item"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> More harnesses shipping weekly.</div>
262 </div>
263 </div>
264 </section>
265
266 <!-- ── Git ──────────────────────────────────────────────────── -->
267 <section id="git" class="sec-git">
268 <div class="container git-inner">
269 <div
270 class="git-visual"
271 role="img"
272 aria-label="Illustration of the T3 Code Git workflow: review a diff, commit and push changes, and open a pull request."
273 >
274 <div class="pr-card tile">
275 <div class="pr-head">
276 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.2"/><circle cx="6" cy="18" r="2.2"/><circle cx="18" cy="6" r="2.2"/><path d="M6 8v8M18 8v5a3 3 0 01-3 3h-3M13 13l-2 3 2 3"/></svg>
277 <span class="pr-title">Add marketing hero animation</span>
278 <span class="pr-status">Ready</span>
279 </div>
280 <div class="pr-meta">
281 <span><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.2"/><circle cx="6" cy="18" r="2.2"/><circle cx="18" cy="6" r="2.2"/><path d="M6 8v8M6 12a6 6 0 006-6h6"/></svg> feat/marketing-hero → main</span>
282 <span>+142 −38</span>
283 <span>3 commits</span>
284 </div>
285 <div class="pr-files">
286 <div><code>apps/marketing/src/pages/index.astro</code> <span>+14 −2</span></div>
287 <div><code>apps/marketing/src/layouts/Layout.astro</code> <span>+8 −0</span></div>
288 <div><code>apps/marketing/public/hero.css</code> <span>+120 −36</span></div>
289 </div>
290 <div class="pr-foot">
291 <span class="btn btn-ghost" style="font-size:12px;padding:6px 10px">View diff</span>
292 <span class="btn btn-primary" style="font-size:12px;padding:6px 12px">
293 <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 .5C5.65.5.5 5.65.5 12a11.5 11.5 0 007.86 10.93c.58.1.79-.25.79-.56v-2c-3.2.69-3.88-1.37-3.88-1.37-.52-1.33-1.27-1.69-1.27-1.69-1.04-.71.08-.7.08-.7 1.15.08 1.76 1.18 1.76 1.18 1.02 1.76 2.68 1.25 3.33.96.1-.75.4-1.25.72-1.54-2.55-.29-5.24-1.27-5.24-5.67 0-1.25.45-2.28 1.18-3.08-.12-.29-.51-1.45.11-3.02 0 0 .96-.31 3.15 1.18a10.96 10.96 0 015.74 0c2.19-1.49 3.15-1.18 3.15-1.18.62 1.57.23 2.73.11 3.02.74.8 1.18 1.83 1.18 3.08 0 4.41-2.7 5.38-5.27 5.66.41.36.78 1.06.78 2.13v3.16c0 .31.21.67.8.56A11.5 11.5 0 0023.5 12C23.5 5.65 18.35.5 12 .5z"/></svg>
294 Open pull request
295 </span>
296 </div>
297 </div>
298 <div class="pr-trail">
299 <div class="pr-trail-dot"></div>
300 <div class="pr-trail-line"></div>
301 <div class="pr-trail-dot"></div>
302 </div>
303 <div class="pr-button-shell">
304 <span class="pr-button">
305 <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.2"/><circle cx="6" cy="18" r="2.2"/><circle cx="18" cy="6" r="2.2"/><path d="M6 8v8M18 8v5a3 3 0 01-3 3h-3M13 13l-2 3 2 3"/></svg>
306 Commit &amp; push
307 <span id="pr-button-kbd" class="pr-button-kbd">⌘⏎</span>
308 </span>
309 </div>
310 </div>
311
312 <div class="git-copy">
313 <div class="section-head" style="margin-bottom:0">
314 <h2>One button to commit, push, and make a PR.</h2>
315 <p>
316 Every agent thread writes to its own branch. When it's good, one
317 button opens the PR on GitHub with a generated title, body and
318 changelog. No terminal dance required.
319 </p>
320 <ul class="checklist" style="margin-top:24px">
321 <li><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> Auto-generated PR titles &amp; bodies</li>
322 <li><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> Inline diff review before you push</li>
323 <li><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> Draft PRs, stack PRs, amend PRs</li>
324 <li><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l5 5L20 6"/></svg> Works with your existing GitHub auth</li>
325 </ul>
326 </div>
327 </div>
328 </div>
329 </section>
330
331 <!-- ── Open source ───────────────────────────────────────────── -->
332 <section id="open" class="sec-open">
333 <div class="container">
334 <div class="section-head open-head">
335 <div class="eyebrow">Open source</div>
336 <h2>If you don't like something, fork it.</h2>
337 </div>
338
339 <div class="open-grid">
340 <div class="tile open-term">
341 <div class="open-term-head">
342 <span></span><span></span><span></span>
343 <span class="open-term-title">~/code</span>
344 </div>
345 <div class="open-term-body">
346 <div><span class="prompt">$</span> gh repo fork pingdotgg/t3code --clone</div>
347 <div class="dim">✓ Cloned t3code into ./t3code</div>
348 <div><span class="prompt">$</span> cd t3code &amp;&amp; vp install</div>
349 <div class="dim">✓ 1 284 packages installed in 4.2s</div>
350 <div><span class="prompt">$</span> vp run dev</div>
351 <div class="dim">▲ T3 Code dev server → <span class="accent">http://localhost:4001</span></div>
352 <div class="cursor"><span class="prompt">$</span><span class="caret"></span></div>
353 </div>
354 </div>
355
356 <div class="tile open-pitch">
357 <div class="open-pitch-copy">
358 <ul class="open-pitch-list">
359 <li>
360 <span class="open-pitch-mark" aria-hidden="true"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span>
361 <span><strong>Change the UI.</strong> Restyle every surface to match your taste.</span>
362 </li>
363 <li>
364 <span class="open-pitch-mark" aria-hidden="true"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span>
365 <span><strong>Add an agent.</strong> Wire in your own tools, models, and flows.</span>
366 </li>
367 <li>
368 <span class="open-pitch-mark" aria-hidden="true"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span>
369 <span><strong>Ship your own build.</strong> Self-host it or distribute it as your own.</span>
370 </li>
371 </ul>
372 </div>
373
374 <div class="open-pitch-footer">
375 <div class="open-pitch-meta">
376 <span>MIT licensed</span>
377 <span aria-hidden="true">·</span>
378 <span>{MARKETING_STATS.githubStars} stars</span>
379 </div>
380
381 <div class="open-pitch-actions">
382 <a class="btn btn-primary" href="https://github.com/pingdotgg/t3code/fork" target="_blank" rel="noopener noreferrer">
383 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="6" cy="5" r="2.2"/><circle cx="18" cy="5" r="2.2"/><circle cx="12" cy="19" r="2.2"/><path d="M6 7.2v2A3 3 0 009 12.2h6A3 3 0 0018 9.2v-2M12 14v2.8"/></svg>
384 Fork on GitHub
385 </a>
386 <a class="open-source-link" href={GITHUB_REPOSITORY_URL} target="_blank" rel="noopener noreferrer">
387 Browse source
388 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M7 17L17 7M8 7h9v9"/></svg>
389 </a>
390 </div>
391 </div>
392 </div>
393 </div>
394 </div>
395 </section>
396
397 <!-- ── Final CTA ─────────────────────────────────────────────── -->
398 <section id="download" class="sec-cta">
399 <div class="container cta-inner">
400 <h2 class="display cta-title">
401 Your agents deserve better than a terminal.
402 </h2>
403 <p class="cta-sub">
404 T3 Code is free, open source and fast. Install it, plug in the harness
405 you already pay for, and let your agents get to work.
406 </p>
407 <div class="cta-actions">
408 <a id="cta-download-btn" class="btn btn-primary btn-lg" href="https://github.com/pingdotgg/t3code/releases">
409 <svg class="dl-icon dl-icon--apple" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 814 1000" aria-hidden="true"><path fill="currentColor" d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/></svg>
410 <svg class="dl-icon dl-icon--windows" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88 88" aria-hidden="true"><path fill="currentColor" d="m0 12.402 35.687-4.86.016 34.423-35.67.203zm35.67 33.529.028 34.453L.028 75.48.026 45.7zm4.326-39.025L87.314 0v41.527l-47.318.376zm47.329 39.349-.011 41.34-47.318-6.678-.066-34.739z"/></svg>
411 <svg class="dl-icon dl-icon--linux" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M12.504 0c-.155 0-.315.008-.48.021-4.226.333-3.105 4.807-3.17 6.298-.076 1.092-.3 1.953-1.05 3.02-.885 1.051-2.127 2.75-2.716 4.521-.278.832-.41 1.684-.287 2.489a.424.424 0 00-.11.135c-.26.268-.45.6-.663.839-.199.199-.485.267-.797.4-.313.136-.658.269-.864.68-.09.189-.136.394-.132.602 0 .199.027.4.055.536.058.399.116.728.04.97-.249.68-.28 1.145-.106 1.484.174.334.535.47.94.601.81.2 1.91.135 2.774.6.926.466 1.866.67 2.616.47.526-.116.97-.464 1.208-.946.587-.003 1.23-.269 2.26-.334.699-.058 1.574.267 2.577.2.025.134.063.198.114.333l.003.003c.391.778 1.113 1.132 1.884 1.071.771-.06 1.592-.536 2.257-1.306.631-.765 1.683-1.084 2.378-1.503.348-.199.629-.469.649-.853.023-.4-.2-.811-.714-1.376v-.097l-.003-.003c-.17-.2-.25-.535-.338-.926-.085-.401-.182-.786-.492-1.046h-.003c-.059-.054-.123-.067-.188-.135a.357.357 0 00-.19-.064c.431-1.278.264-2.55-.173-3.694-.533-1.41-1.465-2.638-2.175-3.483-.796-1.005-1.576-1.957-1.56-3.368.026-2.152.236-6.133-3.544-6.139zm.529 3.405h.013c.213 0 .396.062.584.198.19.135.33.332.438.533.105.259.158.459.166.724 0-.02.006-.04.006-.06v.105a.086.086 0 01-.004-.021l-.004-.024a1.807 1.807 0 01-.15.706.953.953 0 01-.213.335.71.71 0 00-.088-.042c-.104-.045-.198-.064-.284-.133a1.312 1.312 0 00-.22-.066c.05-.06.146-.133.183-.198.053-.128.082-.264.088-.402v-.02a1.21 1.21 0 00-.061-.4c-.045-.134-.101-.2-.183-.333-.084-.066-.167-.132-.267-.132h-.016c-.093 0-.176.03-.262.132a.8.8 0 00-.205.334 1.18 1.18 0 00-.09.4v.019c.002.089.008.179.02.267-.193-.067-.438-.135-.607-.202a1.635 1.635 0 01-.018-.2v-.02a1.772 1.772 0 01.15-.768c.082-.22.232-.406.43-.533a.985.985 0 01.594-.2zm-2.962.059h.036c.142 0 .27.048.399.135.146.129.264.288.344.465.09.199.14.4.153.667v.004c.007.134.006.2-.002.266v.08c-.03.007-.056.018-.083.024-.152.055-.274.135-.393.2.012-.09.013-.18.003-.267v-.015c-.012-.133-.04-.2-.082-.333a.613.613 0 00-.166-.267.248.248 0 00-.183-.064h-.021c-.071.006-.13.04-.186.132a.552.552 0 00-.12.27.944.944 0 00-.023.33v.015c.012.135.037.2.08.334.046.134.098.2.166.268.01.009.02.018.034.024-.07.057-.117.07-.176.136a.304.304 0 01-.131.068 2.62 2.62 0 01-.275-.402 1.772 1.772 0 01-.155-.667 1.759 1.759 0 01.08-.668 1.43 1.43 0 01.283-.535c.128-.133.26-.2.418-.2zm1.37 1.706c.332 0 .733.065 1.216.399.293.2.523.269 1.052.468h.003c.255.136.405.266.478.399v-.131a.571.571 0 01.016.47c-.123.31-.516.643-1.063.842v.002c-.268.135-.501.333-.775.465-.276.135-.588.292-1.012.267a1.139 1.139 0 01-.448-.067 3.566 3.566 0 01-.322-.198c-.195-.135-.363-.332-.612-.465v-.005h-.005c-.4-.246-.616-.512-.686-.71-.07-.268-.005-.47.193-.6.224-.135.38-.271.483-.336.104-.074.143-.102.176-.131h.002v-.003c.169-.202.436-.47.839-.601.139-.036.294-.065.466-.065zm2.8 2.142c.358 1.417 1.196 3.475 1.735 4.473.286.534.855 1.659 1.102 3.024.156-.005.33.018.513.064.646-1.671-.546-3.467-1.089-3.966-.22-.2-.232-.335-.123-.335.59.534 1.365 1.572 1.646 2.757.13.535.16 1.104.021 1.67.067.028.135.06.205.067 1.032.534 1.413.938 1.23 1.537v-.043c-.06-.003-.12 0-.18 0h-.016c.151-.467-.182-.825-1.065-1.224-.915-.4-1.646-.336-1.77.465-.008.043-.013.066-.018.135-.068.023-.139.053-.209.064-.43.268-.662.669-.793 1.187-.13.533-.17 1.156-.205 1.869v.003c-.02.334-.17.838-.319 1.35-1.5 1.072-3.58 1.538-5.348.334a2.645 2.645 0 00-.402-.533 1.45 1.45 0 00-.275-.333c.182 0 .338-.03.465-.067a.615.615 0 00.314-.334c.108-.267 0-.697-.345-1.163-.345-.467-.931-.995-1.788-1.521-.63-.4-.986-.87-1.15-1.396-.165-.534-.143-1.085-.015-1.645.245-1.07.873-2.11 1.274-2.763.107-.065.037.135-.408.974-.396.751-1.14 2.497-.122 3.854a8.123 8.123 0 01.647-2.876c.564-1.278 1.743-3.504 1.836-5.268.048.036.217.135.289.202.218.133.38.333.59.465.21.201.477.335.876.335.039.003.075.006.11.006.412 0 .73-.134.997-.268.29-.134.52-.334.74-.4h.005c.467-.135.835-.402 1.044-.7zm2.185 8.958c.037.6.343 1.245.882 1.377.588.134 1.434-.333 1.791-.765l.211-.01c.315-.007.577.01.847.268l.003.003c.208.199.305.53.391.876.085.4.154.78.409 1.066.486.527.645.906.636 1.14l.003-.007v.018l-.003-.012c-.015.262-.185.396-.498.595-.63.401-1.746.712-2.457 1.57-.618.737-1.37 1.14-2.036 1.191-.664.053-1.237-.2-1.574-.898l-.005-.003c-.21-.4-.12-1.025.056-1.69.176-.668.428-1.344.463-1.897.037-.714.076-1.335.195-1.814.12-.465.308-.797.641-.984l.045-.022zm-10.814.049h.01c.053 0 .105.005.157.014.376.055.706.333 1.023.752l.91 1.664.003.003c.243.533.754 1.064 1.189 1.637.434.598.77 1.131.729 1.57v.006c-.057.744-.48 1.148-1.125 1.294-.645.135-1.52.002-2.395-.464-.968-.536-2.118-.469-2.857-.602-.369-.066-.61-.2-.723-.4-.11-.2-.113-.602.123-1.23v-.004l.002-.003c.117-.334.03-.752-.027-1.118-.055-.401-.083-.71.043-.94.16-.334.396-.4.69-.533.294-.135.64-.202.915-.47h.002v-.002c.256-.268.445-.601.668-.838.19-.201.38-.336.663-.336zm7.159-9.074c-.435.201-.945.535-1.488.535-.542 0-.97-.267-1.28-.466-.154-.134-.28-.268-.373-.335-.164-.134-.144-.333-.074-.333.109.016.129.134.199.2.096.066.215.2.36.333.292.2.68.467 1.167.467.485 0 1.053-.267 1.398-.466.195-.135.445-.334.648-.467.156-.136.149-.267.279-.267.128.016.034.134-.147.332a8.097 8.097 0 01-.69.468zm-1.082-1.583V5.64c-.006-.02.013-.042.029-.05.074-.043.18-.027.26.004.063 0 .16.067.15.135-.006.049-.085.066-.135.066-.055 0-.092-.043-.141-.068-.052-.018-.146-.008-.163-.065zm-.551 0c-.02.058-.113.049-.166.066-.047.025-.086.068-.14.068-.05 0-.13-.02-.136-.068-.01-.066.088-.133.15-.133.08-.031.184-.047.259-.005.019.009.036.03.03.05v.02h.003z"/></svg>
412
413 <span id="cta-download-label">Download for macOS</span>
414 </a>
415 <a class="btn btn-ghost btn-lg" href="/download">Windows · Linux · other</a>
416 </div>
417 </div>
418 </section>
419</Layout>
420
421<script>
422 import { fetchLatestRelease, RELEASES_URL, type ReleaseAsset } from "../lib/releases";
423 import { startHomeMotion } from "../lib/homeMotion";
424
425 type Platform = { os: "mac" | "win" | "linux"; label: string };
426
427 function detectPlatform(): Platform | null {
428 const ua = navigator.userAgent;
429 if (/Win/i.test(ua)) return { os: "win", label: "Download for Windows" };
430 if (/Mac/i.test(ua)) return { os: "mac", label: "Download for macOS" };
431 if (/Linux/i.test(ua)) return { os: "linux", label: "Download for Linux" };
432 return null;
433 }
434
435 // Macs always get the arm64 build. Browsers cannot reliably tell Apple Silicon
436 // from Intel (the UA lies, GPU strings lie), and a wrong guess hands an Apple
437 // Silicon user a broken app. Intel users pick their build on /download.
438 // Do NOT add arch detection back here.
439 function pickAsset(assets: ReleaseAsset[], platform: Platform): string | null {
440 if (platform.os === "win") {
441 return assets.find((a) => a.name.endsWith("-x64.exe"))?.browser_download_url ?? null;
442 }
443 if (platform.os === "mac") {
444 return assets.find((a) => a.name.endsWith("-arm64.dmg"))?.browser_download_url ?? null;
445 }
446 if (platform.os === "linux") {
447 return assets.find((a) => a.name.endsWith("-x86_64.AppImage"))?.browser_download_url ?? null;
448 }
449 return null;
450 }
451
452 async function init() {
453 const btn = document.getElementById("download-btn") as HTMLAnchorElement | null;
454 const label = document.getElementById("download-label");
455 const ctaBtn = document.getElementById("cta-download-btn") as HTMLAnchorElement | null;
456 const ctaLabel = document.getElementById("cta-download-label");
457 const kbd = document.getElementById("pr-button-kbd");
458
459 const platform = detectPlatform();
460 if (!platform) return;
461 document.documentElement.dataset.platform = platform.os;
462 if (label) label.textContent = platform.label;
463 if (ctaLabel) ctaLabel.textContent = platform.label;
464 if (kbd && platform.os !== "mac") kbd.textContent = "Ctrl ⏎";
465
466 try {
467 const release = await fetchLatestRelease();
468 const url = pickAsset(release.assets ?? [], platform);
469 if (url) {
470 if (btn) {
471 btn.href = url;
472 btn.removeAttribute("target");
473 btn.removeAttribute("rel");
474 }
475 if (ctaBtn) {
476 ctaBtn.href = url;
477 ctaBtn.removeAttribute("target");
478 ctaBtn.removeAttribute("rel");
479 }
480 }
481 } catch {
482 if (btn) btn.href = RELEASES_URL;
483 if (ctaBtn) ctaBtn.href = RELEASES_URL;
484 }
485 }
486
487 init();
488
489 const hero = document.querySelector<HTMLElement>(".hero");
490 const field = document.querySelector<HTMLElement>(".hero-float");
491 const tracks = Array.from(document.querySelectorAll<HTMLElement>(".endorsement-track"));
492 const caret = document.querySelector<HTMLElement>(".caret");
493 if (hero && field && caret) {
494 startHomeMotion({ hero, field, tracks, caret });
495 }
496</script>
497
498<style>
499 /* ── Section base ─────────────────────────────────────────── */
500 section {
501 position: relative;
502 padding: 96px 0;
503 border-top: 1px solid var(--border);
504 }
505
506 .section-head {
507 margin-bottom: 56px;
508 max-width: 720px;
509 }
510
511 .section-head .eyebrow {
512 margin-bottom: 14px;
513 display: block;
514 }
515
516 .section-head h2 {
517 font-size: clamp(32px, 4vw, 48px);
518 font-weight: 500;
519 letter-spacing: -0.035em;
520 line-height: 1.05;
521 margin-bottom: 18px;
522 }
523
524 .section-head p {
525 color: var(--fg-muted);
526 font-size: 18px;
527 max-width: 620px;
528 letter-spacing: -0.005em;
529 }
530
531 .checklist {
532 list-style: none;
533 display: flex;
534 flex-direction: column;
535 gap: 12px;
536 }
537
538 .checklist li {
539 display: flex;
540 align-items: center;
541 gap: 10px;
542 color: var(--fg-muted);
543 font-size: 15px;
544 }
545
546 .checklist li svg {
547 color: var(--ok);
548 flex-shrink: 0;
549 }
550
551 /* ── Hero ─────────────────────────────────────────────────── */
552 .hero {
553 padding: 72px 0 60px;
554 position: relative;
555 overflow: hidden;
556 border-top: 0;
557 }
558
559 .hero-grid {
560 position: absolute;
561 inset: 0;
562 pointer-events: none;
563 background-image:
564 linear-gradient(to right, rgba(255, 255, 255, 0.035) 1px, transparent 1px),
565 linear-gradient(to bottom, rgba(255, 255, 255, 0.035) 1px, transparent 1px);
566 background-size: 48px 48px;
567 mask-image: radial-gradient(ellipse 80% 60% at 50% 40%, black 40%, transparent 100%);
568 -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 40%, black 40%, transparent 100%);
569 }
570
571 .hero-inner {
572 position: relative;
573 text-align: center;
574 }
575
576 .hero-title {
577 font-size: clamp(38px, 5.6vw, 76px);
578 margin: 48px auto 22px;
579 max-width: 20ch;
580 text-wrap: balance;
581 }
582 /* Inline boxes ignore transforms, so each rising line needs its own block. */
583 .hero-title span { display: inline-block; }
584
585 .hero-sub {
586 color: var(--fg-muted);
587 font-size: clamp(16px, 1.4vw, 19px);
588 max-width: 640px;
589 margin: 0 auto 36px;
590 letter-spacing: -0.005em;
591 line-height: 1.55;
592 }
593
594 .hero-actions {
595 display: flex;
596 flex-direction: column;
597 align-items: center;
598 gap: 16px;
599 margin-bottom: 56px;
600 }
601
602 .hero-source-link {
603 display: inline-flex;
604 align-items: center;
605 gap: 8px;
606 color: var(--fg-muted);
607 font-size: 14px;
608 font-weight: 500;
609 letter-spacing: -0.01em;
610 transition: color 0.18s ease;
611 }
612
613 .hero-source-link:hover {
614 color: var(--fg);
615 }
616
617 .hero-source-mark {
618 flex-shrink: 0;
619 }
620
621 .hero-source-arrow {
622 flex-shrink: 0;
623 opacity: 0.6;
624 transition: transform 0.18s ease, opacity 0.18s ease;
625 }
626
627 .hero-source-link:hover .hero-source-arrow {
628 transform: translate(2px, -2px);
629 opacity: 1;
630 }
631
632 .hero-mobile-line {
633 display: inline-flex;
634 align-items: center;
635 gap: 6px;
636 color: var(--fg-dim);
637 font-size: 13px;
638 letter-spacing: -0.005em;
639 }
640
641 .hero-mobile-line a {
642 color: var(--fg-muted);
643 text-decoration: underline;
644 text-decoration-color: rgba(161, 161, 170, 0.4);
645 text-underline-offset: 3px;
646 transition: color 0.18s ease, text-decoration-color 0.18s ease;
647 }
648
649 .hero-mobile-line a:hover {
650 color: var(--fg);
651 text-decoration-color: var(--fg);
652 }
653
654 /* Download button icons (platform-aware) */
655 .dl-icon {
656 display: none;
657 width: 14px;
658 height: 14px;
659 flex-shrink: 0;
660 }
661
662 :global([data-platform="mac"]) .dl-icon--apple { display: block; }
663 :global([data-platform="win"]) .dl-icon--windows { display: block; }
664 :global([data-platform="linux"]) .dl-icon--linux { display: block; }
665 :global(html:not([data-platform])) .dl-icon--apple { display: block; }
666
667 /* Marks enter once, then drift while visible and lean toward the pointer. */
668 .hero-float {
669 position: absolute;
670 inset: 0;
671 pointer-events: none;
672 z-index: 1;
673 --px: 0px;
674 --py: 0px;
675 }
676
677 .hero-float-mark {
678 position: absolute;
679 left: calc(50% + var(--x));
680 top: var(--y);
681 width: var(--s);
682 height: var(--s);
683 margin-left: calc(var(--s) / -2);
684 translate: calc(var(--px) * var(--depth)) calc(var(--py) * var(--depth));
685 transition: translate var(--parallax-duration, 0s) cubic-bezier(0.2, 0.7, 0.2, 1);
686 }
687
688 .hero-float-card {
689 display: grid;
690 place-items: center;
691 width: 100%;
692 height: 100%;
693 border-radius: 25%;
694 background: radial-gradient(circle at 30% 25%, var(--tint, rgba(255, 255, 255, 0.08)), rgba(20, 20, 24, 0.92) 65%);
695 border: 1px solid var(--border);
696 box-shadow:
697 0 20px 48px -16px rgba(0, 0, 0, 0.65),
698 0 2px 0 0 rgba(255, 255, 255, 0.04) inset;
699 animation:
700 mark-in 1s cubic-bezier(0.2, 0.7, 0.2, 1) var(--d) both,
701 mark-drift var(--dur) ease-in-out calc(var(--d) + 1s) infinite;
702 animation-play-state: running, var(--home-motion-state, paused);
703 }
704
705 .hero-float-card img {
706 width: 56%;
707 height: 56%;
708 display: block;
709 object-fit: contain;
710 }
711
712 @keyframes mark-in {
713 from { opacity: 0; transform: translate(var(--fx), var(--fy)) rotate(calc(var(--rot) + 24deg)) scale(0.6); }
714 to { opacity: 1; transform: translate(0, 0) rotate(var(--rot)) scale(1); }
715 }
716 @keyframes mark-drift {
717 0%, 100% { transform: translate(0, 0) rotate(var(--rot)); }
718 50% { transform: translate(var(--dx), var(--dy)) rotate(calc(var(--rot) + var(--wob))); }
719 }
720
721 .hf-opencode { --x: max(-300px, -19vw); --y: 20px; --s: 64px; --rot: 6deg; --depth: 0.6; --d: 620ms; --dur: 8.5s; --dx: 2px; --dy: -8px; --wob: 3deg; --fx: -40px; --fy: -80px; }
722 .hf-antigravity { --x: min(300px, 19vw); --y: 20px; --s: 64px; --rot: -5deg; --depth: 0.6; --d: 580ms; --dur: 9.8s; --dx: -2px; --dy: -9px; --wob: -3deg; --fx: 40px; --fy: -80px; }
723 .hf-claude { --x: max(-560px, -38vw); --y: 128px; --s: 96px; --rot: -8deg; --depth: 1.2; --d: 380ms; --dur: 10.5s; --dx: 4px; --dy: -12px; --wob: -2deg; --fx: -160px; --fy: -40px; --tint: rgba(217, 119, 87, 0.22); }
724 .hf-codex { --x: min(560px, 38vw); --y: 128px; --s: 96px; --rot: 7deg; --depth: 1.2; --d: 460ms; --dur: 9.2s; --dx: -4px; --dy: -10px; --wob: 2deg; --fx: 160px; --fy: -40px; }
725 .hf-grok { --x: max(-440px, -30vw); --y: 440px; --s: 80px; --rot: 4deg; --depth: 0.9; --d: 540ms; --dur: 11.5s; --dx: 3px; --dy: -9px; --wob: -3deg; --fx: -120px; --fy: 80px; }
726 .hf-cursor { --x: min(440px, 30vw); --y: 440px; --s: 80px; --rot: -5deg; --depth: 0.9; --d: 700ms; --dur: 7.8s; --dx: -3px; --dy: -11px; --wob: 3deg; --fx: 120px; --fy: 80px; }
727
728 @media (prefers-reduced-motion: reduce) {
729 .hero-float-card { animation: none; transform: rotate(var(--rot)); }
730 .hero-float-mark { translate: none; transition: none; }
731 }
732
733 @media (max-width: 1180px) {
734 .hf-claude, .hf-codex { --s: 80px; }
735 .hf-grok, .hf-cursor { --s: 68px; --y: 420px; }
736 }
737
738 @media (max-width: 820px) {
739 .hero {
740 padding-top: 132px;
741 }
742
743 .hero-title {
744 font-size: clamp(40px, 11vw, 56px);
745 margin-top: 14px;
746 }
747
748 .hero-actions {
749 margin-bottom: 96px;
750 }
751
752 /* Four above the headline, two beside the CTA. Keeps the copy clear. */
753 .hf-claude { --x: -37vw; --y: 44px; --s: 64px; --rot: -10deg; }
754 .hf-opencode { --x: -12vw; --y: 52px; --s: 56px; --rot: -4deg; }
755 .hf-antigravity { --x: 12vw; --y: 52px; --s: 56px; --rot: 5deg; }
756 .hf-codex { --x: 37vw; --y: 44px; --s: 64px; --rot: 8deg; }
757 .hf-grok { --x: -36vw; --y: 474px; --s: 64px; --rot: -6deg; }
758 .hf-cursor { --x: 36vw; --y: 474px; --s: 64px; --rot: 7deg; }
759 }
760
761 @media (max-width: 340px) {
762 .hf-opencode, .hf-antigravity, .hf-grok, .hf-cursor { --s: 48px; }
763 .hf-grok, .hf-cursor { --y: 580px; }
764 }
765
766 .hero-preview {
767 max-width: 1180px;
768 margin: 0 auto;
769 transform: perspective(2000px) rotateX(2deg);
770 transition: transform 0.6s ease;
771 }
772
773 .hero-preview:hover {
774 transform: perspective(2000px) rotateX(0deg);
775 }
776
777 .hero-screenshot-frame {
778 position: relative;
779 overflow: hidden;
780 aspect-ratio: 2880 / 1800;
781 border-radius: 14px;
782 background: #0a0a0c;
783 box-shadow: 0 28px 64px -28px rgba(0, 0, 0, 0.75);
784 }
785
786 .hero-screenshot-frame picture {
787 display: block;
788 width: 100%;
789 height: 100%;
790 }
791
792 .hero-screenshot-frame img {
793 width: calc(100% + 4px);
794 height: calc(100% + 4px);
795 margin: -2px;
796 object-fit: cover;
797 object-position: center top;
798 }
799
800 /* ── Harnesses ─────────────────────────────────────────── */
801 .sec-harness { background: #09090b; }
802
803 .harness-grid {
804 display: grid;
805 grid-template-columns: repeat(6, 1fr);
806 gap: 0;
807 border: 1px solid var(--border);
808 border-radius: var(--radius);
809 overflow: hidden;
810 }
811
812 .harness {
813 padding: 22px 20px;
814 display: flex; align-items: center; gap: 14px;
815 border-right: 1px solid var(--border);
816 background: linear-gradient(180deg, rgba(255, 255, 255, 0.015), transparent);
817 transition: background 0.2s ease;
818 }
819 .harness:last-child { border-right: 0; }
820 .harness:hover { background: rgba(255, 255, 255, 0.025); }
821
822 .harness-mark {
823 color: var(--fg); opacity: 0.95;
824 flex-shrink: 0; width: 28px; height: 28px;
825 display: grid; place-items: center;
826 }
827 .harness-mark img { width: 22px; height: 22px; object-fit: contain; }
828
829 .harness-meta { flex: 1; min-width: 0; }
830 .harness-name {
831 font-size: 14px; font-weight: 500;
832 letter-spacing: -0.01em; margin-bottom: 2px;
833 }
834 .harness-tag {
835 font-family: var(--font-mono);
836 font-size: 11px; color: var(--fg-dim);
837 }
838
839 .harness-footer {
840 display: flex; gap: 24px; flex-wrap: wrap;
841 margin-top: 28px; padding-top: 24px;
842 border-top: 1px dashed var(--border);
843 font-size: 13px; color: var(--fg-muted);
844 }
845 .harness-footer-item {
846 display: inline-flex; gap: 8px; align-items: center;
847 color: var(--fg-muted);
848 }
849 .harness-footer-item svg { color: var(--ok); }
850
851 /* ── Endorsements ─────────────────────────────────────── */
852 .sec-endorsements {
853 overflow: hidden;
854 }
855
856 .endorsements-head {
857 max-width: 720px;
858 margin-bottom: 56px;
859 }
860
861 .endorsements-head h2 {
862 font-size: clamp(32px, 4vw, 48px);
863 font-weight: 500;
864 letter-spacing: -0.035em;
865 line-height: 1.05;
866 margin-bottom: 18px;
867 }
868
869 .endorsements-count {
870 font-weight: 600;
871 font-variant-numeric: tabular-nums;
872 }
873
874 .endorsements-head p {
875 color: var(--fg-muted);
876 font-size: 18px;
877 max-width: 620px;
878 letter-spacing: -0.005em;
879 }
880
881 /* Two marquee rows scrolling in opposite directions. Each track holds the
882 row twice so a -50% translate loops seamlessly. The animation only runs
883 while a track is on screen (see homeMotion), and pauses on hover/focus. */
884 .endorsement-carousel {
885 position: relative;
886 display: flex;
887 flex-direction: column;
888 gap: 12px;
889 }
890
891 .endorsement-carousel--mobile {
892 display: none;
893 }
894
895 .endorsement-carousel::before,
896 .endorsement-carousel::after {
897 content: "";
898 position: absolute;
899 top: 0;
900 bottom: 0;
901 z-index: 2;
902 width: max(48px, calc((100vw - 1240px) / 2 + 56px));
903 pointer-events: none;
904 }
905
906 .endorsement-carousel::before {
907 left: 0;
908 background: linear-gradient(90deg, var(--bg), transparent);
909 }
910
911 .endorsement-carousel::after {
912 right: 0;
913 background: linear-gradient(270deg, var(--bg), transparent);
914 }
915
916 .endorsement-row {
917 overflow: hidden;
918 }
919
920 .endorsement-track {
921 width: max-content;
922 display: flex;
923 animation: endorsementMarquee 76s linear infinite;
924 animation-play-state: var(--home-motion-state, paused);
925 will-change: transform;
926 }
927
928 .endorsement-track-group {
929 display: flex;
930 gap: 12px;
931 padding-right: 12px;
932 }
933
934 .endorsement-row.is-reverse .endorsement-track {
935 animation-direction: reverse;
936 animation-duration: 84s;
937 }
938
939 .endorsement-carousel:hover .endorsement-track,
940 .endorsement-carousel:focus-within .endorsement-track {
941 animation-play-state: paused;
942 }
943
944 @media (prefers-reduced-motion: reduce) {
945 .endorsement-track { animation: none; }
946 }
947
948 @keyframes endorsementMarquee {
949 from { transform: translateX(0); }
950 to { transform: translateX(-50%); }
951 }
952
953 .endorsement-card {
954 position: relative;
955 width: clamp(264px, 22vw, 308px);
956 height: 132px;
957 padding: 14px 16px;
958 display: flex;
959 flex-direction: column;
960 gap: 10px;
961 border: 1px solid var(--border);
962 border-radius: 10px;
963 background: rgba(255, 255, 255, 0.012);
964 transition:
965 border-color 0.18s ease,
966 background 0.18s ease;
967 }
968
969 .endorsement-card:hover {
970 border-color: var(--border-strong);
971 background: rgba(255, 255, 255, 0.03);
972 }
973
974 .endorsement-author {
975 display: flex;
976 align-items: center;
977 gap: 8px;
978 min-width: 0;
979 }
980
981 .endorsement-author img {
982 width: 28px;
983 height: 28px;
984 border-radius: 50%;
985 object-fit: cover;
986 flex-shrink: 0;
987 }
988
989 .endorsement-handle {
990 color: var(--fg-muted);
991 font-size: 13px;
992 font-weight: 500;
993 letter-spacing: -0.005em;
994 overflow: hidden;
995 text-overflow: ellipsis;
996 white-space: nowrap;
997 }
998
999 .endorsement-card p {
1000 color: var(--fg);
1001 font-size: 13.5px;
1002 line-height: 1.4;
1003 letter-spacing: -0.003em;
1004 display: -webkit-box;
1005 overflow: hidden;
1006 -webkit-box-orient: vertical;
1007 -webkit-line-clamp: 3;
1008 }
1009
1010 /* ── Git ──────────────────────────────────────────────── */
1011 .git-inner {
1012 display: grid;
1013 grid-template-columns: 1.1fr 1fr;
1014 gap: 64px; align-items: center;
1015 }
1016
1017 .git-visual {
1018 position: relative;
1019 display: flex; flex-direction: column;
1020 align-items: stretch; gap: 20px;
1021 }
1022
1023 .git-visual .btn {
1024 line-height: normal;
1025 pointer-events: none;
1026 }
1027
1028 .pr-card { padding: 20px; }
1029 .pr-head {
1030 display: flex; align-items: center; gap: 10px;
1031 margin-bottom: 12px;
1032 }
1033 .pr-head svg { color: var(--ok); }
1034 .pr-title { font-weight: 500; font-size: 15px; flex: 1; }
1035 .pr-status {
1036 font-family: var(--font-mono); font-size: 10px;
1037 color: var(--ok); padding: 2px 8px;
1038 border: 1px solid var(--ok); border-radius: 999px;
1039 letter-spacing: 0.08em; text-transform: uppercase;
1040 }
1041 .pr-meta {
1042 display: flex; gap: 14px;
1043 font-family: var(--font-mono); font-size: 11px;
1044 color: var(--fg-dim); margin-bottom: 14px; flex-wrap: wrap;
1045 }
1046 .pr-meta span { display: inline-flex; align-items: center; gap: 5px; }
1047 .pr-files {
1048 border: 1px solid var(--border); border-radius: 8px;
1049 overflow: hidden; margin-bottom: 16px;
1050 }
1051 .pr-files > div {
1052 display: flex; justify-content: space-between;
1053 padding: 8px 12px; font-family: var(--font-mono);
1054 font-size: 11px; border-top: 1px solid var(--border);
1055 color: var(--fg-muted);
1056 }
1057 .pr-files > div:first-child { border-top: 0; }
1058 .pr-files span { color: var(--fg-dim); }
1059 .pr-foot { display: flex; justify-content: flex-end; gap: 8px; }
1060
1061 .pr-trail {
1062 display: flex; flex-direction: column;
1063 align-items: center; justify-content: center;
1064 gap: 0; margin: -4px 0;
1065 }
1066 .pr-trail-dot {
1067 width: 8px; height: 8px; border-radius: 999px;
1068 background: var(--border-strong);
1069 }
1070 .pr-trail-line {
1071 width: 1px; height: 28px;
1072 background: linear-gradient(180deg, var(--border-strong), var(--accent));
1073 }
1074
1075 .pr-button-shell { display: flex; justify-content: center; }
1076 .pr-button {
1077 display: inline-flex; align-items: center; gap: 10px;
1078 padding: 12px 20px;
1079 background: var(--fg); color: #09090b;
1080 font-weight: 600; font-size: 13px;
1081 line-height: normal;
1082 border-radius: 10px;
1083 box-shadow: 0 8px 24px -8px rgba(255, 255, 255, 0.2);
1084 }
1085 .pr-button-kbd {
1086 font-family: var(--font-mono); font-size: 10px;
1087 background: rgba(0, 0, 0, 0.1);
1088 padding: 2px 6px; border-radius: 4px;
1089 }
1090
1091 /* ── Open source ──────────────────────────────────────── */
1092 .open-head {
1093 text-align: center;
1094 margin: 0 auto 56px;
1095 }
1096
1097 .open-grid {
1098 display: grid;
1099 grid-template-columns: 1.25fr 1fr;
1100 gap: 20px;
1101 }
1102
1103 .open-term { padding: 0; overflow: hidden; }
1104 .open-term-head {
1105 display: flex; align-items: center; gap: 6px;
1106 padding: 10px 14px; border-bottom: 1px solid var(--border);
1107 background: rgba(255, 255, 255, 0.02);
1108 }
1109 .open-term-head span {
1110 width: 10px; height: 10px; border-radius: 999px;
1111 background: #2a2a30; display: block;
1112 }
1113 .open-term-title {
1114 margin-left: 10px;
1115 font-family: var(--font-mono); font-size: 11px;
1116 color: var(--fg-dim); flex: 1; text-align: center;
1117 background: transparent !important;
1118 width: auto !important; height: auto !important;
1119 border-radius: 0 !important;
1120 }
1121
1122 .open-term-body {
1123 padding: 20px 22px;
1124 font-family: var(--font-mono); font-size: 13px;
1125 line-height: 1.7; color: var(--fg);
1126 }
1127 .open-term-body > div {
1128 white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
1129 }
1130 .open-term-body .prompt { color: var(--accent); margin-right: 8px; }
1131 .open-term-body .dim { color: var(--fg-dim); }
1132 .open-term-body .accent { color: var(--accent); }
1133 .open-term-body .cursor { display: flex; align-items: center; }
1134 .caret {
1135 display: inline-block;
1136 width: 7px; height: 14px;
1137 background: var(--fg);
1138 margin-left: 4px;
1139 animation: blink 1s steps(2) infinite;
1140 animation-play-state: var(--home-motion-state, paused);
1141 }
1142
1143 @keyframes blink {
1144 50% { opacity: 0; }
1145 }
1146
1147 @media (prefers-reduced-motion: reduce) {
1148 .caret { animation: none; }
1149 }
1150
1151 .open-pitch {
1152 padding: 32px;
1153 display: flex;
1154 flex-direction: column;
1155 justify-content: center;
1156 gap: 32px;
1157 background:
1158 radial-gradient(110% 75% at 100% 0%, var(--accent-dim), transparent 60%),
1159 linear-gradient(180deg, rgba(255, 255, 255, 0.02), transparent);
1160 }
1161
1162 .open-pitch-list {
1163 list-style: none;
1164 display: flex;
1165 flex-direction: column;
1166 gap: 16px;
1167 }
1168
1169 .open-pitch-list li {
1170 display: flex;
1171 align-items: flex-start;
1172 gap: 12px;
1173 font-size: 15px;
1174 line-height: 1.5;
1175 color: var(--fg-muted);
1176 }
1177
1178 .open-pitch-list strong {
1179 color: var(--fg);
1180 font-weight: 600;
1181 }
1182
1183 .open-pitch-mark {
1184 flex: none;
1185 display: grid;
1186 place-items: center;
1187 width: 22px;
1188 height: 22px;
1189 margin-top: 1px;
1190 border-radius: 7px;
1191 color: var(--accent);
1192 background: var(--accent-dim);
1193 border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
1194 }
1195
1196 .open-pitch-footer {
1197 display: flex;
1198 flex-direction: column;
1199 gap: 18px;
1200 }
1201
1202 .open-pitch-meta {
1203 display: flex;
1204 align-items: center;
1205 gap: 8px;
1206 color: var(--fg-dim);
1207 font-family: var(--font-mono);
1208 font-size: 11px;
1209 }
1210
1211 .open-pitch-actions {
1212 display: flex;
1213 align-items: center;
1214 gap: 16px;
1215 flex-wrap: wrap;
1216 }
1217
1218 .open-source-link {
1219 display: inline-flex;
1220 align-items: center;
1221 gap: 6px;
1222 color: var(--fg-muted);
1223 font-size: 13px;
1224 font-weight: 500;
1225 transition: color 0.18s ease;
1226 }
1227
1228 .open-source-link:hover {
1229 color: var(--fg);
1230 }
1231
1232 /* ── Final CTA ────────────────────────────────────────── */
1233 .sec-cta {
1234 text-align: center;
1235 padding: 120px 0;
1236 position: relative;
1237 overflow: hidden;
1238 }
1239 .sec-cta::before {
1240 content: "";
1241 position: absolute;
1242 inset: auto 0 -50% 0;
1243 height: 60%;
1244 background: radial-gradient(ellipse at center, var(--accent-dim) 0%, transparent 60%);
1245 pointer-events: none;
1246 opacity: 0.6;
1247 }
1248 .cta-inner { position: relative; }
1249 .cta-title {
1250 font-size: clamp(40px, 6vw, 72px);
1251 }
1252 .cta-sub {
1253 color: var(--fg-muted);
1254 font-size: 18px;
1255 max-width: 560px;
1256 margin: 20px auto 36px;
1257 line-height: 1.55;
1258 letter-spacing: -0.005em;
1259 }
1260 .cta-actions {
1261 display: flex; gap: 10px;
1262 justify-content: center; flex-wrap: wrap;
1263 margin-bottom: 24px;
1264 }
1265
1266 /* ── Responsive ────────────────────────────────────────── */
1267 @media (max-width: 960px) {
1268 .hero-preview {
1269 width: min(860px, calc(100vw - 24px));
1270 margin-left: 50%;
1271 transform: translateX(-50%) perspective(1600px) rotateX(1.5deg);
1272 }
1273 .hero-preview:hover {
1274 transform: translateX(-50%) perspective(1600px) rotateX(0deg);
1275 }
1276 .harness-grid { grid-template-columns: 1fr 1fr; }
1277 .harness { border-right: 0; border-bottom: 1px solid var(--border); }
1278 .harness:nth-child(odd) { border-right: 1px solid var(--border); }
1279 .harness:nth-child(even) { border-right: 0; }
1280 .git-inner { grid-template-columns: 1fr; gap: 40px; }
1281 .open-grid { grid-template-columns: 1fr; }
1282 }
1283
1284 @media (max-width: 820px) {
1285 section { padding: 64px 0; }
1286 .sec-cta { padding: 96px 0; }
1287 .container { padding-left: 20px; padding-right: 20px; }
1288 .hero-preview { display: none; }
1289 .endorsements-head {
1290 margin-bottom: 40px;
1291 }
1292 .endorsement-carousel--desktop {
1293 display: none;
1294 }
1295 .endorsement-carousel--mobile {
1296 display: flex;
1297 }
1298 .endorsement-carousel::before,
1299 .endorsement-carousel::after {
1300 width: 28px;
1301 }
1302 .endorsement-track {
1303 animation-duration: 68s;
1304 }
1305 .endorsement-row.is-reverse .endorsement-track {
1306 animation-duration: 76s;
1307 }
1308 .endorsement-card {
1309 width: 268px;
1310 padding: 14px;
1311 }
1312 .endorsement-card p {
1313 font-size: 13px;
1314 }
1315 }
1316</style>