Files
zeekay ac64d5d7dd Folds say one line: every first screen keeps its heading and a single lede
The owner's spec for a landing page is the models bento's: monochrome, the
words left and the art right, no extra prose. The folds carried two to four
sentences under each heading, and some a claim, a lede and a list besides.
Each now says one line: ProductLanding the tagline where a page states one
(the lede still describes it to search), a claim alone where the claim is
the line (/payments, /treasury, /zap, the extension), and elsewhere the
sentence that says what the thing is. /philosophy's two points, /dns' claim
that repeated its title, /calculator's capabilities line and the
Spare clauses on /research and /learn go.
2026-10-30 06:42:40 -07:00

901 lines
32 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
/**
* /startups — the credits programme, and the form that applies to it.
*
* NO TAILWIND AND NO STYLE OBJECTS. @hanzo/ui's marketing components carry the
* type and the controls (`Display`, `Lede`, `Title`, `Chip`, `Action`), `Grid`
* wraps on the width a column actually has, and everything left is gui props
* over @hanzo/design's tokens: `Label` is the line over a field, `Card` a
* pillar, `Check` the box a choice ticks.
*
* NOT `Band`. This page's sections carry no rule, its gutter steps 16/32/48
* where every band on the site steps 16/24/32, and its rhythm (112/40, 32,
* 56, 96) is not on the band's ladder. A form page is not a product page, and
* borrowing the product band would restate all three.
*
* - `Field`/`Note` are gui's `Input`, because a placeholder's colour lives on
* `::placeholder` and `placeholderTextColor` is the prop that reaches it;
* without it the ink falls to @hanzo/design's `--text-disabled` (white at
* 30%) instead of gui's `$placeholderColor`, design's `--text-tertiary`.
* The two selects are @hanzo/ui's `Picker` in the same box.
* - `Cell` on `Toggle` — the site's surface whose ground answers a pointer.
* It adds no geometry, so an option in a multi-select wears it exactly as a
* grid tile does, and both grounds are its properties.
* - the privacy link says NOTHING. @hanzo/design's base already underlines a
* link inside a paragraph on approach, which is what every prose link on
* this site does; `More` is the wrong shape for one inside a sentence, since
* it is `inline-flex` at `text-sm` and stretching a link inside a line tears
* it.
*/
import React, { useState, type ReactNode } from 'react'
import { Fold } from '@/components/marketing/fold'
import { Steps } from '@/components/preview/steps'
import { motion } from '@/components/motion'
import Link from 'next/link'
import {
Rocket,
ArrowRight,
CheckCircle2,
Coins,
Cpu,
Gift,
Building2,
Globe,
User,
Mail,
Briefcase,
Users,
Banknote,
Boxes,
Send,
type LucideIcon,
} from 'lucide-react'
import { Box, Picker, Text, View, XStack, YStack } from '@hanzo/ui'
import { Input, type GetProps } from '@hanzo/gui'
import { Grid } from '@hanzo/ui/grid'
import { Action, Title, Cell, Line } from '@hanzo/ui/marketing'
import { mix } from '@hanzo/app/lib/mix'
import { api } from '@hanzo/app/lib/api'
import { phrase } from '@hanzo/i18n'
import { useI18n } from '@hanzo/i18n/react'
// Canonical cloud intake endpoint (public startup-program application), on the
// gateway of the host this page is open on.
const apply = () => `${api()}/v1/crm/applications`
/** How narrow a column may get before the grid drops one. */
const DUO = { min: 260, max: 2 } as const
const MUTED = 'var(--muted-foreground)'
/** The two small rungs, each on the leading its utility paired it with: a ratio,
* so it follows the reader's type scale. `Line` takes it as written. */
const XS = { fontSize: '$1', lineHeight: '1.3333' } as const
const SM = { fontSize: '$2', lineHeight: '1.4286' } as const
/** The line over a field: its mark and its words, `htmlFor` where it names one control. */
const Label = ({ htmlFor, icon: Icon, children }: { htmlFor?: string; icon: LucideIcon; children: ReactNode }) => (
<Line
render="label"
htmlFor={htmlFor}
display="flex"
items="center"
gap={8}
mb={8}
{...SM}
fontWeight="500"
color="var(--foreground)"
>
<View render={<Icon width={14} height={14} color={MUTED} />} shrink={0} />
{children}
</Line>
)
/** The quiet half of a label — "(optional)", "(funds, angels)". */
const Aside = ({ children }: { children: ReactNode }) => (
<Text fontWeight="400" color={MUTED}>
{children}
</Text>
)
/** The tick itself, drawn in the ground's ink. */
const Tick = ({ size }: { size: number }) => (
<svg width={size} height={size} fill="none" viewBox="0 0 24 24" stroke="var(--background)" strokeWidth={3}>
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
</svg>
)
/** The box a choice ticks, at the two sizes this page ticks one: filled in the ink when on. */
const Check = ({ on, size, mt }: { on: boolean; size: 16 | 20; mt?: number }) => (
<View
render="span"
display="inline-flex"
width={size}
height={size}
shrink={0}
items="center"
justify="center"
mt={mt}
rounded="var(--radius)"
borderWidth={1}
borderStyle="solid"
transition="quickest"
bg={on ? 'var(--foreground)' : undefined}
borderColor={on ? 'var(--foreground)' : mix('var(--muted-foreground)', 40)}
>
{on && <Tick size={size === 16 ? 10 : 12} />}
</View>
)
/**
* One option in a multi-select, ticked or not.
*
* ONE ground on approach, for both the fund list and the use-case list — they
* were the same eleven utilities written twice, differing only in how far the
* tick sits from the top and how much room the row has.
*/
const Toggle = ({
on,
onClick,
align,
pad,
children,
}: {
on: boolean
onClick: () => void
align: 'center' | 'flex-start'
pad: number
children: React.ReactNode
}) => (
<Cell
render="button"
type="button"
onClick={onClick}
display="flex"
items={align}
gap={12}
p={pad}
rounded="var(--radius-lg)"
borderWidth={1}
borderStyle="solid"
text="left"
{...(on ? CHOSEN : CHOICE)}
>
<Check on={on} size={16} mt={align === 'flex-start' ? 2 : undefined} />
{children}
</Cell>
)
/** A choice in the form: its edge and its ground at rest and on approach. The
* chosen one holds its ground under the pointer. */
const CHOICE = {
borderColor: 'var(--border)',
bg: mix('var(--secondary)', 30),
hoverStyle: { bg: mix('var(--secondary)', 60) },
} as const
const CHOSEN = {
borderColor: mix('var(--pure-white)', 40),
bg: mix('var(--primary)', 10),
hoverStyle: { bg: mix('var(--primary)', 10) },
} as const
/** The box every field here is drawn in. `unstyled` zeroes the outline, so
* the focus ring @hanzo/design draws on every control is given its width back. */
const ENTRY = {
unstyled: true,
width: '100%',
px: 16,
py: 12,
rounded: 'var(--radius-lg)',
borderWidth: 1,
borderColor: 'var(--border)',
bg: 'var(--secondary)',
fontSize: '$2',
lineHeight: '$2',
color: 'var(--foreground)',
placeholderTextColor: '$placeholderColor',
focusVisibleStyle: { outlineWidth: 2 },
} as const
/** The two controls a form is made of: a line, and the same field `rows` tall. */
const Field = (props: GetProps<typeof Input>) => <Input {...ENTRY} {...props} />
const Note = (props: GetProps<typeof Input>) => <Input render="textarea" {...ENTRY} {...props} />
/** The platform's own select in the fields' box. */
const Choose = (props: React.ComponentProps<typeof Picker>) => (
<Picker
pl={16}
pr={16}
py={12}
minH={0}
rounded="var(--radius-lg)"
borderWidth={1}
borderColor="var(--border)"
bg="var(--secondary)"
fontSize="$2"
$platform-web={{ lineHeight: '1.4286' }}
color="var(--foreground)"
{...props}
/>
)
const STAGES = [
{ id: 'idea', label: phrase('Idea') },
{ id: 'pre-seed', label: phrase('Pre-seed') },
{ id: 'seed', label: phrase('Seed') },
{ id: 'series-a', label: phrase('Series A') },
{ id: 'series-b-plus', label: phrase('Series B+') },
]
// Tier-1 funds recognized for the credits program. Free-text field captures any others.
const TIER1_FUNDS = [
'Andreessen Horowitz (a16z)',
'Sequoia',
'Benchmark',
'Greylock',
'Accel',
'Founders Fund',
'Lightspeed',
'Index Ventures',
'Bessemer',
'Khosla Ventures',
'GV (Google Ventures)',
'Techstars',
]
const USE_CASES = [
{ id: 'ai', label: phrase('AI & inference'), description: phrase('Models, agents, RAG, one API for every model') },
{ id: 'deploy', label: phrase('Deploy'), description: phrase('Apps, functions, edge, machines') },
{ id: 'data', label: phrase('Data'), description: phrase('Vector, SQL, KV, object storage') },
{ id: 'compute', label: phrase('Compute'), description: phrase('GPUs, training, batch jobs') },
]
// Each option is also the value filed with the application, so it stays English there.
const HEARD_OPTIONS = [
phrase('Search'),
'X / Twitter',
'LinkedIn',
phrase('A friend or colleague'),
phrase('A Techstars connection'),
phrase('An investor'),
phrase('An event or conference'),
phrase('Hanzo docs or GitHub'),
phrase('Other'),
]
const PILLARS = [
{
icon: Coins,
title: phrase('Start in minutes'),
body: phrase('Creating an account is free. Add funds when you are ready and pay only for what you use — no subscription, no minimums.'),
},
{
icon: Cpu,
title: phrase('Bring your own compute'),
body: phrase('Connect your own GPUs and machines. Run cheap on hardware you already have — we meter the platform, not your iron.'),
},
{
icon: Gift,
title: phrase('Up to $150,000 in credits'),
body: phrase('For venture-backed startups. Application required, and tier-1 VC backing is required for the credits program.'),
},
] as const
interface FormData {
company: string
website: string
contactName: string
email: string
role: string
stage: string
investors: string
tier1Investors: string[]
amountRaised: string
teamSize: string
building: string
useCases: string[]
infraSpend: string
byoCompute: boolean
byoHardware: string
techstarsBatch: string
heardVia: string
// Honeypot: must stay empty. Real users never see or fill this.
hp: string
}
const INITIAL_FORM: FormData = {
company: '',
website: '',
contactName: '',
email: '',
role: '',
stage: '',
investors: '',
tier1Investors: [],
amountRaised: '',
teamSize: '',
building: '',
useCases: [],
infraSpend: '',
byoCompute: false,
byoHardware: '',
techstarsBatch: '',
heardVia: '',
hp: '',
}
export default function StartupsPage() {
const { t } = useI18n()
const [formData, setFormData] = useState<FormData>(INITIAL_FORM)
const [isSubmitting, setIsSubmitting] = useState(false)
const [submitted, setSubmitted] = useState(false)
const [error, setError] = useState<string | null>(null)
const handleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>
) => {
setFormData({ ...formData, [e.target.name]: e.target.value })
}
const toggleInArray = (key: 'tier1Investors' | 'useCases', value: string) => {
setFormData((prev) => ({
...prev,
[key]: prev[key].includes(value)
? prev[key].filter((v) => v !== value)
: [...prev[key], value],
}))
}
const validate = (): string | null => {
if (!formData.company.trim()) return t('Company name is required.')
if (!formData.contactName.trim()) return t('Your name is required.')
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) return t('A valid email is required.')
if (!formData.stage) return t('Please select your company stage.')
if (!formData.building.trim()) return t('Tell us what you are building.')
return null
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
const validationError = validate()
if (validationError) {
setError(validationError)
return
}
setIsSubmitting(true)
setError(null)
try {
const res = await fetch(apply(), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ...formData, submittedAt: new Date().toISOString() }),
})
if (!res.ok) {
throw new Error(t('Request failed ({status})', { status: res.status }))
}
setSubmitted(true)
} catch (err) {
setError(
err instanceof Error ? err.message : t('Something went wrong. Please try again.')
)
} finally {
setIsSubmitting(false)
}
}
return (
<Box minH="100vh" $platform-web={{ color: 'var(--foreground)' }}>
<Box render="main">
<Fold
label="Techstars ’17 — built for founders"
mark={<Rocket width={12} height={12} color="currentColor" aria-hidden />}
title="The Hanzo Startup Program"
lede="Everyone starts free. Venture-backed teams get up to $150,000 in credits."
actions={
<>
<Action href="#apply" fill>
{t('Apply for credits')}
<ArrowRight width={16} height={16} data-i18n-mirror />
</Action>
<Action href="https://platform.hanzo.ai" borderColor="var(--border)">
{t('Start building free')}
</Action>
</>
}
preview={<Steps title="The program" icon={<Rocket size={12} color="currentColor" />} steps={PILLARS.map((p) => ({ title: p.title, body: p.body }))} />}
/>
<Box render="section" pb={32} px={16} $md={{ px: 32 }} $lg={{ px: 48 }}>
{/* Techstars note */}
<Box width="100%" maxW={1024} mx="auto" mt={16}>
<XStack
items="flex-start"
gap={12}
p={20}
rounded="var(--radius-xl)"
borderWidth={1}
borderColor="var(--border)"
bg="$hover"
>
<View render={<Rocket width={16} height={16} color={mix('var(--foreground)', 70)} />} mt={2} shrink={0} />
<Line render="p" display="block" fontSize="$2" color={MUTED} lineHeight="var(--leading-relaxed)">
{t('{label} Hanzo is a Techstars company. We offer perks tailored to each portfolio brand — mention your batch when you apply and we will match it.', {
label: (
<Text color="var(--foreground)" fontWeight="500">
{t('Techstars founders:')}
</Text>
),
})}
</Line>
</XStack>
</Box>
</Box>
{/* Application form */}
<Box render="section" id="apply" py={56} px={16} $md={{ px: 32 }} $lg={{ px: 48 }} $platform-web={{ scrollMarginTop: '96px' }}>
<Box width="100%" maxW={672} mx="auto">
<Box mb={40} $platform-web={{ textAlign: 'center' }}>
<Title quiet mb={12}>
{t('Apply to the program')}
</Title>
<Text render="p" display="block" color={MUTED}>
{t('We review applications weekly. The more you share, the faster we can match you to the right tier.')}
</Text>
</Box>
{submitted ? (
<Box
render={<motion.div initial={{ opacity: 0, scale: 0.95 }} animate={{ opacity: 1, scale: 1 }} transition={{ duration: 0.4 }} />}
p={40}
rounded="var(--radius-xl)"
borderWidth={1}
borderColor="var(--border)"
bg={mix('var(--primary)', 5)}
$platform-web={{ textAlign: 'center' }}
>
<XStack
items="center"
justify="center"
width={56}
height={56}
mx="auto"
mb={20}
rounded="var(--radius-full)"
bg="$raised"
>
<CheckCircle2 width={28} height={28} color={mix('var(--foreground)', 70)} />
</XStack>
<Title quiet mb={12}>
{t('Application received')}
</Title>
<Text render="p" display="block" mb={8} color={MUTED}>
{t('Thanks — we review applications weekly and will be in touch by email.')}
</Text>
<Line render="p" display="block" mb={32} {...SM} color={MUTED}>
{t('Want to start building today? Create an account and pay only for what you use — no subscription required.')}
</Line>
<XStack flexWrap="wrap" justify="center" gap={16}>
<Action href="https://platform.hanzo.ai" fill>
{t('Start free')}
<ArrowRight width={16} height={16} data-i18n-mirror />
</Action>
<Action href="/" borderColor="var(--border)">
{t('Back to Home')}
</Action>
</XStack>
</Box>
) : (
<YStack
render={<motion.form onSubmit={handleSubmit} initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.5, delay: 0.1 }} />}
gap={24}
>
{/* Company + website */}
<Grid columns={DUO} gap={16}>
<Box>
<Label htmlFor="company" icon={Building2}>
{t('Company name')}
</Label>
<Field
type="text"
id="company"
name="company"
value={formData.company}
onChange={handleChange}
required
placeholder="Acme AI"
/>
</Box>
<Box>
<Label htmlFor="website" icon={Globe}>
{t('Website')}
</Label>
<Field
type="text"
id="website"
name="website"
value={formData.website}
onChange={handleChange}
placeholder="https://acme.ai"
/>
</Box>
</Grid>
{/* Contact name + email */}
<Grid columns={DUO} gap={16}>
<Box>
<Label htmlFor="contactName" icon={User}>
{t('Your name')}
</Label>
<Field
type="text"
id="contactName"
name="contactName"
value={formData.contactName}
onChange={handleChange}
required
placeholder="Jane Smith"
/>
</Box>
<Box>
<Label htmlFor="email" icon={Mail}>
{t('Work email')}
</Label>
<Field
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
required
placeholder="[email protected]"
/>
</Box>
</Grid>
{/* Role + stage */}
<Grid columns={DUO} gap={16}>
<Box>
<Label htmlFor="role" icon={Briefcase}>
{t('Your role')}
</Label>
<Field
type="text"
id="role"
name="role"
value={formData.role}
onChange={handleChange}
placeholder={t('Co-founder & CEO')}
/>
</Box>
<Box>
<Label htmlFor="stage" icon={Rocket}>
{t('Company stage')}
</Label>
<Choose
id="stage"
name="stage"
value={formData.stage}
onChange={handleChange}
required
>
<option value="" disabled>
{t('Select stage')}
</option>
{STAGES.map((s) => (
<option key={s.id} value={s.id}>
{t(s.label)}
</option>
))}
</Choose>
</Box>
</Grid>
{/* Investors free text */}
<Box>
<Label htmlFor="investors" icon={Banknote}>
{t('Who are your investors?')}{' '}
<Aside>{t('(funds, angels)')}</Aside>
</Label>
<Field
type="text"
id="investors"
name="investors"
value={formData.investors}
onChange={handleChange}
placeholder={t('e.g. Sequoia, plus a few angels')}
/>
</Box>
{/* Tier-1 checkboxes */}
<Box>
<Label icon={CheckCircle2}>
{t('Backed by any of these?')}{' '}
<Aside>
{t('(tier-1 backing qualifies you for the credits program)')}
</Aside>
</Label>
<Grid columns={DUO} gap={8}>
{TIER1_FUNDS.map((fund) => (
<Toggle
key={fund}
on={formData.tier1Investors.includes(fund)}
onClick={() => toggleInArray('tier1Investors', fund)}
align="center"
pad={10}
>
<Line {...SM} color="var(--foreground)">{fund}</Line>
</Toggle>
))}
</Grid>
</Box>
{/* Raised + team size */}
<Grid columns={DUO} gap={16}>
<Box>
<Label htmlFor="amountRaised" icon={Banknote}>
{t('Amount raised')}{' '}
<Aside>{t('(optional)')}</Aside>
</Label>
<Field
type="text"
id="amountRaised"
name="amountRaised"
value={formData.amountRaised}
onChange={handleChange}
placeholder="$2M"
/>
</Box>
<Box>
<Label htmlFor="teamSize" icon={Users}>
{t('Team size')}
</Label>
<Field
type="text"
id="teamSize"
name="teamSize"
value={formData.teamSize}
onChange={handleChange}
placeholder="5"
/>
</Box>
</Grid>
{/* Building */}
<Box>
<Label htmlFor="building" icon={Boxes}>
{t('What are you building?')}
</Label>
<Note
id="building"
name="building"
value={formData.building}
onChange={handleChange}
required
rows={4}
placeholder={t('Describe your product, who it is for, and where you are today...')}
/>
</Box>
{/* Use cases */}
<Box>
<Label icon={Cpu}>
{t('How will you use Hanzo?')}
</Label>
<Grid columns={DUO} gap={8}>
{USE_CASES.map((uc) => (
<Toggle
key={uc.id}
on={formData.useCases.includes(uc.id)}
onClick={() => toggleInArray('useCases', uc.id)}
align="flex-start"
pad={12}
>
<span>
<Line {...SM} fontWeight="500" color="var(--foreground)">{t(uc.label)}</Line>
<Line render="p" display="block" mt={2} {...XS} color={MUTED}>{t(uc.description)}</Line>
</span>
</Toggle>
))}
</Grid>
</Box>
{/* Infra spend */}
<Box>
<Label htmlFor="infraSpend" icon={Banknote}>
{t('Current infra / compute spend per month')}{' '}
<Aside>{t('(optional)')}</Aside>
</Label>
<Field
type="text"
id="infraSpend"
name="infraSpend"
value={formData.infraSpend}
onChange={handleChange}
placeholder="$3,000 / mo"
/>
</Box>
{/* BYO compute */}
<YStack
gap={16}
p={20}
rounded="var(--radius-xl)"
borderWidth={1}
borderColor="var(--border)"
bg="$panel"
>
<XStack
render={<button type="button" onClick={() => setFormData((p) => ({ ...p, byoCompute: !p.byoCompute }))} />}
items="flex-start"
gap={12}
width="100%"
$platform-web={{ textAlign: 'left' }}
>
<Check on={formData.byoCompute} size={20} mt={2} />
<span>
<Line display="flex" items="center" gap={8} {...SM} fontWeight="500" color="var(--foreground)">
<Cpu width={14} height={14} color={MUTED} />
{t('I want to bring my own compute')}
</Line>
<Line display="block" mt={4} {...XS} color={MUTED}>
{t('Connect your own GPUs or machines and run on hardware you already own.')}
</Line>
</span>
</XStack>
{formData.byoCompute && (
<Box>
<Line render="label" htmlFor="byoHardware" display="block" mb={8} {...XS} fontWeight="500" color={MUTED}>
{t('What hardware do you have?')}
</Line>
<Field
type="text"
id="byoHardware"
name="byoHardware"
value={formData.byoHardware}
onChange={handleChange}
placeholder={t('e.g. 8x H100, a few Mac Studios, on-prem cluster')}
/>
</Box>
)}
</YStack>
{/* Techstars + heard */}
<Grid columns={DUO} gap={16}>
<Box>
<Label htmlFor="techstarsBatch" icon={Rocket}>
{t('Techstars affiliation')}{' '}
<Aside>{t('(optional)')}</Aside>
</Label>
<Field
type="text"
id="techstarsBatch"
name="techstarsBatch"
value={formData.techstarsBatch}
onChange={handleChange}
placeholder={t('Batch / program, e.g. NYC W17')}
/>
</Box>
<Box>
<Label htmlFor="heardVia" icon={Globe}>
{t('How did you hear about us?')}
</Label>
<Choose
id="heardVia"
name="heardVia"
value={formData.heardVia}
onChange={handleChange}
>
<option value="">{t('Select one')}</option>
{HEARD_OPTIONS.map((h) => (
<option key={h} value={h}>
{t(h)}
</option>
))}
</Choose>
</Box>
</Grid>
{/* Honeypot: visually hidden, off-screen, not tab-reachable. */}
<Box aria-hidden="true" position="absolute" l={-9999} t={-9999} width={0} height={0} overflow="hidden">
<label htmlFor="hp">Do not fill this in</label>
<input
type="text"
id="hp"
name="hp"
value={formData.hp}
onChange={handleChange}
tabIndex={-1}
autoComplete="off"
/>
</Box>
{/* Error */}
{error && (
<Line
render="div"
display="block"
p={16}
rounded="var(--radius-lg)"
borderWidth={1}
fontSize="$2"
color="var(--state-error-text)"
lineHeight="1.4286" borderColor={mix('var(--state-error)', 30)}
bg={mix('var(--state-error)', 10)}
>
{error}
</Line>
)}
{/* Submit.
`alignItems` is what `w-full sm:w-auto` was asking for: the
control stretches on a phone and shrinks to its words from
640, which is a property of the COLUMN and not of the button. */}
<YStack pt={8} items="stretch" $sm={{ items: 'flex-start' }}>
<Action
render="button"
type="submit"
disabled={isSubmitting}
fill
justify="center"
opacity={isSubmitting ? 0.5 : undefined}
>
{isSubmitting ? (
t('Submitting...')
) : (
<>
<Send width={16} height={16} />
{t('Submit application')}
</>
)}
</Action>
</YStack>
<Line render="p" display="block" fontSize="$1" lineHeight="1.3333" color={mix('var(--muted-foreground)', 60)}>
{/* Nothing of its own: @hanzo/design's base underlines a link
inside a paragraph on approach, which is this site's whole
treatment for a link in a sentence. */}
{t('By submitting, you agree to Hanzo’s {link}.', {
link: <Link href="/legal/privacy">{t('Privacy Policy')}</Link>,
})}{' '}
{t('We use your information only to review this application.')}
</Line>
</YStack>
)}
</Box>
</Box>
{/* Fallback CTA for everyone */}
<Box render="section" pb={96} px={16} $md={{ px: 32 }} $lg={{ px: 48 }}>
<Box
width="100%"
maxW={768}
mx="auto"
p={32}
$sm={{ p: 40 }}
rounded="var(--radius-2xl)"
borderWidth={1}
borderColor="var(--border)"
bg="$panel"
$platform-web={{ textAlign: 'center' }}
>
<Title quiet mb={12}>
{t('Not venture-backed yet?')}
</Title>
<Text render="p" display="block" mb={24} width="100%" maxW={576} mx="auto" color={MUTED}>
{t('You do not need to qualify to build. Create an account, pay only for what you use, and apply for credits when you raise.')}
</Text>
<Action href="https://platform.hanzo.ai" fill>
{t('Start free')}
<ArrowRight width={16} height={16} data-i18n-mirror />
</Action>
</Box>
</Box>
</Box>
</Box>
)
}