feat(site): rewrite the landing page around verified facts and accessible controls
- Replace claims that contradicted the app: the default hotkey is Right Alt (hold to talk), local features are free with no daily cap, there is no 14-day trial, Team/SSO/SCIM/ZDR are not offered, and the repository is not public. Remove invented metrics, status badges, the competitor table, the ad-mediation changelog, the hash calculator and the duplicate demo. - Seven sections: hero with one labelled example, features, how it works, privacy, pricing (Free / Pro 2,900 / Pro+ 8,900 KRW a month), download, FAQ. Footer links the privacy policy, terms and account deletion pages. - All copy moves into i18n and every one of the 10 locales is translated. Pricing and cloud quotas come from site/src/pricing.ts. - Accessibility: skip link, labelled sections, aria-expanded with Esc and focus return for the menu, language list and FAQ, live status for the example, reduced-motion support, 44px targets, AA contrast on the primary button. Korean keep-all line breaking is scoped to :lang(ko) because Tailwind's break-keep blocked wrapping in Japanese and Chinese. - JS 111 -> 98 KB gzip, CSS 7.8 -> 5.2 KB gzip.
This commit is contained in:
parent
ad6bb70c20
commit
e689683b72
44 changed files with 2198 additions and 3782 deletions
49
site/src/components/icons.tsx
Normal file
49
site/src/components/icons.tsx
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// 사이트 공용 아이콘. 모두 장식이므로 aria-hidden 이고, 의미는 옆 텍스트가 전달한다.
|
||||
|
||||
interface IconProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export function DownloadIcon({ className = 'h-4 w-4' }: IconProps) {
|
||||
return (
|
||||
<svg aria-hidden="true" className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
|
||||
<polyline points="7 10 12 15 17 10" />
|
||||
<line x1="12" y1="15" x2="12" y2="3" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function ExternalIcon({ className = 'h-3.5 w-3.5' }: IconProps) {
|
||||
return (
|
||||
<svg aria-hidden="true" className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M7 17 17 7" />
|
||||
<path d="M8 7h9v9" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function CheckIcon({ className = 'h-4 w-4' }: IconProps) {
|
||||
return (
|
||||
<svg aria-hidden="true" className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.25" strokeLinecap="round" strokeLinejoin="round">
|
||||
<polyline points="20 6 9 17 4 12" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function PlusIcon({ className = 'h-4 w-4' }: IconProps) {
|
||||
return (
|
||||
<svg aria-hidden="true" className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
||||
<line x1="12" y1="5" x2="12" y2="19" />
|
||||
<line x1="5" y1="12" x2="19" y2="12" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export function PlayIcon({ className = 'h-3.5 w-3.5' }: IconProps) {
|
||||
return (
|
||||
<svg aria-hidden="true" className={className} viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M7 4.5v15l13-7.5z" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue