@@ -5,8 +5,8 @@ import { useTheme } from '@/hooks/useTheme';
55import { usePanelCollapse } from '@/hooks/usePanelCollapse' ;
66import { Header } from '@/components/Header/Header' ;
77import { InputCard , CardChevron } from '@/components/InputCard/InputCard' ;
8+ import { FundingModelSection } from '@/components/FundingModelSection/FundingModelSection' ;
89import { RegionPicker } from '@/components/RegionPicker/RegionPicker' ;
9- import { FundingToggle } from '@/components/FundingToggle/FundingToggle' ;
1010import { PopularFlows } from '@/components/PopularFlows/PopularFlows' ;
1111import { CurrencyPicker } from '@/components/CurrencyPicker/CurrencyPicker' ;
1212import { EmptyCanvas } from '@/components/EmptyCanvas/EmptyCanvas' ;
@@ -17,8 +17,7 @@ import { Agentation } from 'agentation';
1717
1818import { IconArrowLeft } from '@central-icons-react/round-outlined-radius-3-stroke-1.5/IconArrowLeft' ;
1919import { IconArrowRight } from '@central-icons-react/round-outlined-radius-3-stroke-1.5/IconArrowRight' ;
20- import { currencies } from '@/data/currencies' ;
21- import { useState , useEffect , useCallback , useMemo , useRef } from 'react' ;
20+ import { useState , useEffect , useCallback , useRef } from 'react' ;
2221import clsx from 'clsx' ;
2322import styles from './page.module.scss' ;
2423
@@ -31,8 +30,8 @@ export default function Home() {
3130 setReceive,
3231 setSendNetwork,
3332 setReceiveNetwork,
34- toggleSendInternal ,
35- toggleReceiveInternal ,
33+ setSourceFundingMode ,
34+ setSourceRail ,
3635 swap,
3736 setSourceRegion,
3837 setDestRegion,
@@ -41,12 +40,10 @@ export default function Home() {
4140 closePicker,
4241 } = useFlowBuilder ( ) ;
4342
44- // Region picker state — opens after crypto source is selected.
45- // We hold the pending selection until the user picks a region, then commit both together.
43+ // Region picker state — opened from the inline Region row on crypto cards
4644 const [ regionTarget , setRegionTarget ] = useState < 'send' | 'receive' | null > ( null ) ;
47- const [ pendingCryptoSend , setPendingCryptoSend ] = useState < ReturnType < typeof lookupCurrency > > ( null ) ;
48- const regionCryptoCode = pendingCryptoSend ?. code
49- ?? ( regionTarget === 'send' ? state . send ?. code : undefined ) ;
45+ const regionCryptoCode = regionTarget === 'send' ? state . send ?. code : undefined ;
46+
5047 const [ showAgentation , setShowAgentation ] = useState ( false ) ;
5148 const [ isEmbed , setIsEmbed ] = useState ( false ) ;
5249 useEffect ( ( ) => {
@@ -90,15 +87,13 @@ export default function Home() {
9087
9188 const { theme, setTheme } = useTheme ( ) ;
9289
93- // Theme change handler: also posts to parent when embedded
9490 const handleThemeChange = useCallback ( ( t : 'light' | 'dark' ) => {
9591 setTheme ( t ) ;
9692 if ( isEmbed ) {
9793 window . parent . postMessage ( { type : 'theme-sync' , theme : t } , '*' ) ;
9894 }
9995 } , [ setTheme , isEmbed ] ) ;
10096
101- // Listen for theme sync from parent frame when embedded
10297 useEffect ( ( ) => {
10398 if ( ! isEmbed ) return ;
10499 const handler = ( e : MessageEvent ) => {
@@ -107,7 +102,6 @@ export default function Home() {
107102 }
108103 } ;
109104 window . addEventListener ( 'message' , handler ) ;
110- // Tell parent we're ready to receive theme
111105 window . parent . postMessage ( { type : 'theme-request' } , '*' ) ;
112106 return ( ) => window . removeEventListener ( 'message' , handler ) ;
113107 } , [ isEmbed , setTheme ] ) ;
@@ -122,39 +116,14 @@ export default function Home() {
122116 : ( isDark ? style . getPropertyValue ( '--color-gray-950' ) : style . getPropertyValue ( '--surface-primary' ) ) ;
123117 const trimmed = color . trim ( ) ;
124118 if ( ! trimmed ) return ;
125- // Update both media-specific meta tags so the correct one applies
126119 document . querySelectorAll < HTMLMetaElement > ( 'meta[name="theme-color"]' ) . forEach ( meta => {
127120 meta . content = trimmed ;
128121 } ) ;
129122 } , [ mobileView , theme ] ) ;
123+
130124 const { flowExpanded, codeExpanded, toggleFlow, toggleCode } =
131125 usePanelCollapse ( ) ;
132126
133- const [ overrideFunding , setOverrideFunding ] = useState < 'jit' | 'pre-funded' | null > ( null ) ;
134-
135- const effectiveFundingModel = overrideFunding ?? fundingModel ;
136-
137- const handleFundingToggle = useCallback ( ( ) => {
138- setOverrideFunding ( ( prev ) => {
139- if ( prev === null ) {
140- // First toggle: flip from inferred value
141- return fundingModel === 'jit' ? 'pre-funded' : 'jit' ;
142- }
143- return prev === 'jit' ? 'pre-funded' : 'jit' ;
144- } ) ;
145- } , [ fundingModel ] ) ;
146-
147- // Reset funding override when source currency changes (not on internal toggle — it hides anyway)
148- useEffect ( ( ) => {
149- setOverrideFunding ( null ) ;
150- } , [ state . send ?. code ] ) ;
151-
152- const sourceInstantRails = useMemo ( ( ) => {
153- if ( ! state . send || state . send . type !== 'fiat' ) return [ ] ;
154- const fiat = currencies . find ( ( c ) => c . code === state . send ! . code ) ;
155- return fiat ?. instantRails ?? [ ] ;
156- } , [ state . send ] ) ;
157-
158127 return (
159128 < main className = { styles . layout } data-mobile-view = { mobileView } >
160129 { /* Left sidebar */ }
@@ -182,18 +151,20 @@ export default function Home() {
182151 ) }
183152
184153 < div className = { styles . sidebarContent } >
185- < div className = { styles . sidebarContentInner } >
154+ < div className = { styles . sidebarContentInner } >
186155 < Header />
187156
188- < div style = { { display : 'flex' , flexDirection : 'column' , gap : 'var(--spacing-xs )' } } >
189- < div style = { { display : 'flex' , flexDirection : 'column' } } >
157+ < div style = { { display : 'flex' , flexDirection : 'column' , gap : 'var(--spacing-md )' } } >
158+ < div style = { { display : 'flex' , flexDirection : 'column' , isolation : 'isolate' } } >
190159 < InputCard
191160 label = "Source"
192161 selection = { state . send }
193162 region = { state . sourceRegion }
163+ rail = { state . sourceRail }
194164 onCardClick = { ( ) => openPicker ( 'send' ) }
195- onToggleInternal = { toggleSendInternal }
196165 onNetworkChange = { setSendNetwork }
166+ onRailChange = { setSourceRail }
167+ onRegionClick = { ( ) => setRegionTarget ( 'send' ) }
197168 />
198169 < div style = { { position : 'relative' , height : '8px' } } >
199170 < CardChevron onSwap = { state . send || state . receive ? swap : undefined } />
@@ -202,18 +173,15 @@ export default function Home() {
202173 label = "Destination"
203174 selection = { state . receive }
204175 onCardClick = { ( ) => openPicker ( 'receive' ) }
205- onToggleInternal = { toggleReceiveInternal }
206176 onNetworkChange = { setReceiveNetwork }
207177 />
208178 </ div >
209179
210- { state . send && (
211- < FundingToggle
212- fundingModel = { effectiveFundingModel }
213- jitEligible = { state . send . jitEligible }
214- isInternal = { state . send . isInternal }
215- onToggle = { handleFundingToggle }
216- instantRails = { sourceInstantRails }
180+ { state . send && state . receive && (
181+ < FundingModelSection
182+ source = { state . send }
183+ selectedMode = { state . sourceFundingMode }
184+ onModeChange = { setSourceFundingMode }
217185 />
218186 ) }
219187 </ div >
@@ -239,12 +207,14 @@ export default function Home() {
239207 </ button >
240208 ) }
241209
242- < PopularFlows onSelect = { ( sendCode , receiveCode ) => {
243- const s = lookupCurrency ( sendCode ) ;
244- const r = lookupCurrency ( receiveCode ) ;
245- if ( s ) setSend ( s ) ;
246- if ( r ) setReceive ( r ) ;
247- } } />
210+ < div style = { { marginTop : isComplete ? '10px' : '24px' } } >
211+ < PopularFlows onSelect = { ( sendCode , receiveCode ) => {
212+ const s = lookupCurrency ( sendCode ) ;
213+ const r = lookupCurrency ( receiveCode ) ;
214+ if ( s ) setSend ( s ) ;
215+ if ( r ) setReceive ( r ) ;
216+ } } />
217+ </ div >
248218 </ div >
249219 </ div >
250220
@@ -264,13 +234,15 @@ export default function Home() {
264234 receive = { state . receive ! }
265235 sourceRegion = { state . sourceRegion }
266236 destRegion = { state . destRegion }
237+ sourceRail = { state . sourceRail }
267238 expanded = { flowExpanded }
268239 onToggle = { toggleFlow }
269240 />
270241 < CodePanel
271242 send = { state . send ! }
272243 receive = { state . receive ! }
273- fundingModel = { effectiveFundingModel }
244+ fundingModel = { fundingModel }
245+ sourceRail = { state . sourceRail }
274246 audience = { state . audience }
275247 onAudienceChange = { setAudience }
276248 expanded = { codeExpanded }
@@ -287,13 +259,7 @@ export default function Home() {
287259 onSelect = { ( sel ) => {
288260 const target = state . pickerTarget ;
289261 if ( target === 'send' ) {
290- if ( sel . type === 'crypto' ) {
291- // Don't commit yet — need region first
292- setPendingCryptoSend ( sel ) ;
293- setRegionTarget ( 'send' ) ;
294- } else {
295- setSend ( sel ) ;
296- }
262+ setSend ( sel ) ;
297263 } else {
298264 setReceive ( sel ) ;
299265 }
@@ -307,22 +273,17 @@ export default function Home() {
307273 }
308274 />
309275
310- { /* Region picker modal — opens after crypto source is selected */ }
276+ { /* Region picker modal — opens from crypto card Region row */ }
311277 < RegionPicker
312278 open = { regionTarget !== null }
313279 cryptoCode = { regionCryptoCode }
314- onClose = { ( ) => {
315- // User dismissed without picking — discard pending selection
316- setPendingCryptoSend ( null ) ;
317- setRegionTarget ( null ) ;
318- } }
280+ onClose = { ( ) => setRegionTarget ( null ) }
319281 onSelect = { ( regionCode ) => {
320- // Commit the pending crypto selection + region together
321- if ( pendingCryptoSend ) {
322- setSend ( pendingCryptoSend ) ;
282+ if ( regionTarget === 'send' ) {
283+ setSourceRegion ( regionCode ) ;
284+ } else if ( regionTarget === 'receive' ) {
285+ setDestRegion ( regionCode ) ;
323286 }
324- setSourceRegion ( regionCode ) ;
325- setPendingCryptoSend ( null ) ;
326287 setRegionTarget ( null ) ;
327288 } }
328289 />
@@ -338,7 +299,7 @@ export default function Home() {
338299 </ div >
339300 ) }
340301
341- { /* Mobile results view: floating pill — hides on scroll down, shows on scroll up */ }
302+ { /* Mobile results view: floating pill */ }
342303 { isComplete && mobileView === 'results' && (
343304 < button
344305 className = { clsx (
0 commit comments