@@ -7,7 +7,7 @@ import { PlotOfTheDayTerminal } from './PlotOfTheDayTerminal';
77import type { PlotOfTheDayData } from '../hooks/usePlotOfTheDay' ;
88
99interface HeroSectionProps {
10- stats : { specs : number ; plots : number ; libraries : number } | null ;
10+ stats : { specs : number ; plots : number ; libraries : number ; lines_of_code ?: number } | null ;
1111 potd ?: PlotOfTheDayData | null ;
1212}
1313
@@ -35,8 +35,7 @@ export function HeroSection({ stats, potd = null }: HeroSectionProps) {
3535 animation : 'rise 0.8s cubic-bezier(0.2, 0.8, 0.2, 1) backwards' ,
3636 fontFamily : typography . mono ,
3737 fontSize : '11px' ,
38- textTransform : 'uppercase' ,
39- letterSpacing : '0.15em' ,
38+ letterSpacing : '0.08em' ,
4039 color : colors . primary ,
4140 mb : 3 ,
4241 display : 'flex' ,
@@ -51,7 +50,7 @@ export function HeroSection({ stats, potd = null }: HeroSectionProps) {
5150 } ,
5251 } }
5352 >
54- Data Visualization Catalogue
53+ the open plot catalogue
5554 </ Box >
5655
5756 < Box
@@ -65,7 +64,7 @@ export function HeroSection({ stats, potd = null }: HeroSectionProps) {
6564 letterSpacing : '-0.03em' ,
6665 color : 'var(--ink)' ,
6766 m : 0 ,
68- mb : 4 ,
67+ mb : 3 ,
6968 } }
7069 >
7170 < Box
@@ -93,28 +92,59 @@ export function HeroSection({ stats, potd = null }: HeroSectionProps) {
9392 < Box component = "span" sx = { { fontWeight : 400 , opacity : 0.45 } } > ()</ Box >
9493 </ Box >
9594 < br />
96- < Box component = "span" sx = { { fontFamily : typography . serif , fontWeight : 400 } } >
95+ < Box
96+ component = "span"
97+ sx = { {
98+ fontFamily : typography . serif ,
99+ fontWeight : 400 ,
100+ fontStyle : 'italic' ,
101+ fontFeatureSettings : '"ss02"' ,
102+ whiteSpace : 'nowrap' ,
103+ fontSize : '0.75em' ,
104+ } }
105+ >
97106 — any library.
98107 </ Box >
99108 </ Box >
100109
110+ < Box
111+ component = "p"
112+ sx = { {
113+ animation : 'rise 0.8s cubic-bezier(0.2, 0.8, 0.2, 1) 0.15s backwards' ,
114+ fontFamily : typography . serif ,
115+ fontSize : { xs : '0.9375rem' , sm : '1rem' , md : '1.125rem' } ,
116+ lineHeight : 1.4 ,
117+ color : 'var(--ink)' ,
118+ mt : 0 ,
119+ mb : 2.5 ,
120+ fontWeight : 500 ,
121+ letterSpacing : '-0.005em' ,
122+ whiteSpace : 'nowrap' ,
123+ } }
124+ >
125+ one spec · every library · always current.
126+ </ Box >
127+
101128 < Box
102129 sx = { {
103130 animation : 'rise 0.8s cubic-bezier(0.2, 0.8, 0.2, 1) 0.2s backwards' ,
104131 fontFamily : typography . serif ,
105132 fontSize : { xs : '1rem' , md : '1.1875rem' } ,
106- lineHeight : 1.5 ,
133+ lineHeight : 1.55 ,
107134 color : 'var(--ink-soft)' ,
108135 mb : 4 ,
109136 fontWeight : 300 ,
110137 } }
111138 >
112- A curated catalogue of visualization examples — human ideas,
113- AI-drafted specs, open implementations across nine Python libraries.
139+ every plot begins as a library-agnostic spec. ai drafts implementations across every
140+ supported library, validates them against quality criteria, and keeps them current. you
141+ discover, copy, and adapt — plug in < em > your</ em >
142+ { ' ' } data. that's it.
114143 </ Box >
115144
116145 < TypewriterText
117- lines = { [ 'get inspired.' , 'grab the code.' , 'make it yours.' ] }
146+ lines = { [ 'steal like an artist.' ] }
147+ charDelay = { 68 }
118148 sx = { {
119149 animation : 'rise 0.8s cubic-bezier(0.2, 0.8, 0.2, 1) 0.25s backwards' ,
120150 fontFamily : typography . serif ,
@@ -130,55 +160,19 @@ export function HeroSection({ stats, potd = null }: HeroSectionProps) {
130160 < Box
131161 sx = { {
132162 display : 'flex' ,
133- gap : 1.5 ,
163+ alignItems : 'center' ,
164+ gap : 2.5 ,
134165 flexWrap : 'wrap' ,
135166 animation : 'rise 0.8s cubic-bezier(0.2, 0.8, 0.2, 1) 0.3s backwards' ,
136167 } }
137168 >
138- < PrimaryCta to = "/plots" label = "Browse the catalogue" />
139- < GhostCta to = "/mcp" label = "use via MCP" />
169+ < PrimaryCta to = "/plots" label = "browse plots" />
170+ < Box sx = { { display : 'flex' , flexDirection : 'column' , gap : 0.25 } } >
171+ < SecondaryLink to = "/mcp" label = "or connect via mcp" />
172+ < SecondaryLink href = "https://github.com/MarkusNeusinger/anyplot" label = "or clone on github" external />
173+ </ Box >
140174 </ Box >
141175
142- { stats && (
143- < Box
144- sx = { {
145- mt : 5 ,
146- pt : 3 ,
147- borderTop : '1px solid var(--rule)' ,
148- display : 'flex' ,
149- gap : 4 ,
150- flexWrap : 'wrap' ,
151- fontFamily : typography . mono ,
152- fontSize : '11px' ,
153- color : 'var(--ink-muted)' ,
154- textTransform : 'uppercase' ,
155- letterSpacing : '0.1em' ,
156- } }
157- >
158- { [
159- { value : String ( stats . specs ) , label : 'specs' } ,
160- { value : stats . plots . toLocaleString ( ) , label : 'implementations' } ,
161- { value : String ( stats . libraries ) , label : 'libraries' } ,
162- ] . map ( ( item , i ) => (
163- < Box key = { i } >
164- < Box
165- sx = { {
166- color : 'var(--ink)' ,
167- fontWeight : 500 ,
168- fontSize : { xs : '1.25rem' , md : '1.625rem' } ,
169- letterSpacing : '-0.02em' ,
170- textTransform : 'none' ,
171- mb : 0.5 ,
172- fontFamily : typography . serif ,
173- } }
174- >
175- { item . value }
176- </ Box >
177- { item . label }
178- </ Box >
179- ) ) }
180- </ Box >
181- ) }
182176 </ Box >
183177
184178 { /* Right: terminal plot */ }
@@ -217,24 +211,40 @@ function PrimaryCta({ to, label }: { to: string; label: string }) {
217211 ) ;
218212}
219213
220- function GhostCta ( { to, label } : { to : string ; label : string } ) {
214+ function SecondaryLink ( {
215+ to,
216+ href,
217+ label,
218+ external,
219+ } : {
220+ to ?: string ;
221+ href ?: string ;
222+ label : string ;
223+ external ?: boolean ;
224+ } ) {
225+ const linkProps = external
226+ ? { component : 'a' as const , href, target : '_blank' , rel : 'noopener noreferrer' }
227+ : { component : RouterLink , to } ;
228+
221229 return (
222230 < Box
223- component = { RouterLink }
224- to = { to }
231+ { ...linkProps }
225232 sx = { {
226233 textDecoration : 'none' ,
227234 fontFamily : typography . mono ,
228235 fontSize : '13px' ,
229- padding : '13px 22px' ,
230- borderRadius : '99px' ,
231- border : '1px solid var(--rule)' ,
232- color : 'var(--ink)' ,
233- transition : 'all 0.2s' ,
234- '&:hover' : { borderColor : 'var(--ink)' } ,
236+ color : 'var(--ink-soft)' ,
237+ display : 'inline-flex' ,
238+ alignItems : 'center' ,
239+ gap : 0.5 ,
240+ transition : 'color 0.2s' ,
241+ '& .arrow' : { transition : 'transform 0.2s' } ,
242+ '&:hover' : { color : colors . primary } ,
243+ '&:hover .arrow' : { transform : 'translateX(3px)' } ,
244+ '&:focus-visible' : { outline : `2px solid ${ colors . primary } ` , outlineOffset : 2 , borderRadius : '2px' } ,
235245 } }
236246 >
237- { label }
247+ { label } < Box component = "span" className = "arrow" > → </ Box >
238248 </ Box >
239249 ) ;
240250}
0 commit comments