diff --git a/src/app/globals.css b/src/app/globals.css index f16de78e..08872813 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -8,17 +8,38 @@ @layer base { html { scroll-behavior: smooth; + /* Prevent horizontal overflow on mobile */ + overflow-x: hidden; } body { background-attachment: fixed; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + /* Prevent horizontal scroll */ + overflow-x: hidden; + /* Better overscroll on mobile */ + overscroll-behavior-y: contain; + /* Remove tap highlight color on mobile */ + -webkit-tap-highlight-color: transparent; + } + + /* Touch-friendly interactive elements */ + button, a, [role="button"] { + min-height: 44px; + min-width: 44px; + touch-action: manipulation; + } + + /* Exception for inline/icon elements */ + button.inline-btn { + min-height: unset; + min-width: unset; } /* Modern Scrollbar */ ::-webkit-scrollbar { - width: 6px; + width: 4px; } ::-webkit-scrollbar-track { @@ -27,9 +48,11 @@ ::-webkit-scrollbar-thumb { border-radius: 3px; + background: rgba(148, 163, 184, 0.3); } ::-webkit-scrollbar-thumb:hover { + background: rgba(148, 163, 184, 0.5); } } @@ -256,28 +279,34 @@ @layer utilities { /* Modern Spacing System */ .container-modern { - @apply max-w-7xl mx-auto px-6 sm:px-8 lg:px-12; + @apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-12; } .section-modern { - @apply py-20 md:py-28 lg:py-32; + @apply py-12 md:py-20 lg:py-28; } .section-compact { - @apply py-12 md:py-16; + @apply py-8 md:py-12 lg:py-16; } /* Modern Grid Systems */ .grid-modern-2 { - @apply grid grid-cols-1 md:grid-cols-2 gap-8; + @apply grid grid-cols-1 sm:grid-cols-2 gap-4 md:gap-8; } .grid-modern-3 { - @apply grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8; + @apply grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-8; } .grid-modern-4 { - @apply grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6; + @apply grid grid-cols-2 md:grid-cols-4 gap-3 md:gap-6; + } + + /* Mobile-first safe area padding */ + .safe-area-x { + padding-left: max(1rem, env(safe-area-inset-left)); + padding-right: max(1rem, env(safe-area-inset-right)); } /* Modern Backgrounds */ @@ -326,6 +355,16 @@ .responsive-padding { @apply px-4 sm:px-6 md:px-8; } + + /* Mobile-optimized card */ + .card-mobile { + @apply rounded-2xl p-4 sm:p-6 md:p-8; + } + + /* Mobile table wrapper */ + .table-scroll { + @apply overflow-x-auto -mx-4 px-4; + } } /* Modern Mobile Menu */ @@ -341,3 +380,35 @@ .mobile-menu-modern.open { @apply translate-x-0 opacity-100; } + +/* Mobile Modal improvements */ +.modal-mobile { + @apply fixed inset-0 bg-black/70 flex items-end sm:items-center justify-center z-50 p-0 sm:p-4; +} + +.modal-content-mobile { + @apply bg-white rounded-t-3xl sm:rounded-2xl w-full sm:max-w-md p-6 pb-8 sm:pb-6; + @apply max-h-[90vh] overflow-y-auto; +} + +/* Tier filter scroll container */ +.filter-scroll { + @apply flex gap-2 overflow-x-auto pb-2; + scrollbar-width: none; + -ms-overflow-style: none; +} + +.filter-scroll::-webkit-scrollbar { + display: none; +} + +/* Stats grid that works better on small phones */ +@media (max-width: 360px) { + .grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .text-2xl { + font-size: 1.25rem; + } +} diff --git a/src/app/layout.js b/src/app/layout.js index 6b71b548..a8129eef 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -6,7 +6,7 @@ import ErrorBoundary from "../components/ErrorBoundary"; import Footer from "../components/Footer"; const inter = Inter({ subsets: ["latin"] }); -const montserrat = Montserrat({ +const montserrat = Montserrat({ subsets: ["latin"], display: 'swap', variable: '--font-montserrat' @@ -36,8 +36,8 @@ export const metadata = { export default function RootLayout({ children }) { return ( - - + + diff --git a/src/app/page.js b/src/app/page.js index 6c0a706b..79e70109 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -745,14 +745,13 @@ export default function RiskScoringApp() { {/* Analysis Mode Toggle */} -
+
+ )}
)} @@ -1083,8 +1078,8 @@ export default function RiskScoringApp() { {riskScore <= 30 ? "Low Risk" : riskScore <= 70 - ? "Medium Risk" - : "High Risk"} + ? "Medium Risk" + : "High Risk"}
@@ -1261,13 +1256,12 @@ export default function RiskScoringApp() { step="0.01" value={collateralAmount} onChange={handleCollateralChange} - className={`input-modern ${ - collateralAmount && - (isNaN(parseFloat(collateralAmount)) || - parseFloat(collateralAmount) < 0) + className={`input-modern ${collateralAmount && + (isNaN(parseFloat(collateralAmount)) || + parseFloat(collateralAmount) < 0) ? "border-red-500/50 focus:border-red-500" : "" - }`} + }`} placeholder="0.00" />
@@ -1289,13 +1283,12 @@ export default function RiskScoringApp() {
tier = {getTier(riskScore).name} diff --git a/src/components/BlendDashboard.jsx b/src/components/BlendDashboard.jsx index 8d8fbc8a..06197a34 100644 --- a/src/components/BlendDashboard.jsx +++ b/src/components/BlendDashboard.jsx @@ -283,8 +283,8 @@ export default function BlendDashboard({ kit, walletAddress, riskScore }) { const riskRecommendations = getRiskBasedRecommendations(); return ( -
-

+
+

🌊 Blend DeFi Protocol Testnet @@ -294,15 +294,14 @@ export default function BlendDashboard({ kit, walletAddress, riskScore }) { {/* Enhanced Pool Status Display */} {selectedPool?.isActive && selectedPool?.status && (
@@ -358,30 +357,28 @@ export default function BlendDashboard({ kit, walletAddress, riskScore }) {

{selectedPool.description}

-
+

Pool Capabilities:

    @@ -398,11 +395,10 @@ export default function BlendDashboard({ kit, walletAddress, riskScore }) {
    {selectedPool.health?.contract ? "✓" : "✗"} @@ -410,11 +406,10 @@ export default function BlendDashboard({ kit, walletAddress, riskScore }) {
    {selectedPool.health?.network ? "✓" : "✗"} @@ -422,11 +417,10 @@ export default function BlendDashboard({ kit, walletAddress, riskScore }) {
    {selectedPool.health?.ledger ? "✓" : "✗"} @@ -459,25 +453,23 @@ export default function BlendDashboard({ kit, walletAddress, riskScore }) {
    )} - {/* Tab Navigation */} -
    + {/* Tab Navigation - horizontally scrollable on mobile */} +
    @@ -486,33 +478,30 @@ export default function BlendDashboard({ kit, walletAddress, riskScore }) { {/* Risk-Based Recommendations */} {riskRecommendations && (

    🎯 DeFi Recommendations Based on Your Risk Score ({riskRecommendations.level})

      {riskRecommendations.recommendations.map((rec, index) => (
    • {rec}
    • @@ -538,11 +527,10 @@ export default function BlendDashboard({ kit, walletAddress, riskScore }) { {availablePools.map((pool) => (
      setSelectedPool(pool)} >
      @@ -718,13 +706,12 @@ export default function BlendDashboard({ kit, walletAddress, riskScore }) {

{userPosition.healthFactor !== null ? (
1.5 + className={`text-2xl font-bold ${userPosition.healthFactor > 1.5 ? "text-green-600" : userPosition.healthFactor > 1.2 - ? "text-yellow-600" - : "text-red-600" - }`} + ? "text-yellow-600" + : "text-red-600" + }`} > {userPosition.healthFactor === Infinity ? "∞" @@ -762,13 +749,12 @@ export default function BlendDashboard({ kit, walletAddress, riskScore }) { {/* Message Display */} {message && (

{message}

diff --git a/src/components/EnhancedLiquidityPools.jsx b/src/components/EnhancedLiquidityPools.jsx index c17d2c1b..5ba731c9 100644 --- a/src/components/EnhancedLiquidityPools.jsx +++ b/src/components/EnhancedLiquidityPools.jsx @@ -190,9 +190,8 @@ function EnhancedLiquidityPools() { return { level: "FULL", borrowLimit: limit.borrowLimit, - message: `Full access with ${ - limit.borrowLimit * 100 - }% max borrow ratio`, + message: `Full access with ${limit.borrowLimit * 100 + }% max borrow ratio`, }; } @@ -374,7 +373,7 @@ function EnhancedLiquidityPools() {
{/* Header with Risk Profile */}
-
+

Risk-Based Liquidity Pools @@ -385,7 +384,7 @@ function EnhancedLiquidityPools() {

{userRiskData && ( -
+
Your Risk Profile
@@ -408,31 +407,31 @@ function EnhancedLiquidityPools() { {/* Liquidity Statistics */} {liquidityStats && ( -
-
-
Tier 1 Pools
-
+
+
+
Tier 1 Pools
+
{liquidityStats.TIER_1 || 0}
≥$1M TVL
-
-
Tier 2 Pools
-
+
+
Tier 2 Pools
+
{liquidityStats.TIER_2 || 0}
$250K-1M TVL
-
-
Tier 3 Pools
-
+
+
Tier 3 Pools
+
{liquidityStats.TIER_3 || 0}
<$250K TVL
-
-
Total Pools
-
+
+
Total Pools
+
{liquidityStats.total || 0}
All tiers
@@ -440,17 +439,16 @@ function EnhancedLiquidityPools() {
)} - {/* Tier Filter */} -
+ {/* Tier Filter - horizontally scrollable on mobile */} +
{["ALL", "TIER_1", "TIER_2", "TIER_3"].map((tier) => ( @@ -553,20 +551,19 @@ function EnhancedLiquidityPools() { {/* Action Button */} {/* Pool Metadata */} @@ -608,45 +605,45 @@ function EnhancedLiquidityPools() {
- {/* Risk Warning Modal */} + {/* Risk Warning Modal - bottom sheet on mobile */} {showRiskWarning && selectedPool && ( -
-
+
+
-
⚠️
+
⚠️

- Yüksek Risk Uyarısı + High Risk Warning

- Bu havuz düşük likiditeye sahip ve yüksek risk taşımaktadır. + This pool has low liquidity and carries high risk.

- Potansiyel Riskler: + Potential Risks:

    -
  • • Yüksek volatilite ve değer kaybı riski
  • -
  • • Düşük likidite nedeniyle çıkış zorluğu
  • -
  • • Potansiyel kayıplar yüksek olabilir
  • +
  • • High volatility and risk of value loss
  • +
  • • Difficulty exiting due to low liquidity
  • +
  • • Potential losses can be significant

- Devam etmek istediğinizden emin misiniz? + Are you sure you want to continue?

@@ -654,15 +651,16 @@ function EnhancedLiquidityPools() {
)} - {/* Pool Details Modal */} + {/* Pool Details Modal - bottom sheet on mobile */} {showPoolDetails && selectedPool && ( -
-
+
+
-

Pool Details

+

Pool Details

@@ -671,7 +669,7 @@ function EnhancedLiquidityPools() {
{/* Pool Header */}
-
+

Pool #{selectedPool.poolId?.slice(-8) || "Unknown"}

@@ -685,7 +683,7 @@ function EnhancedLiquidityPools() { {selectedPool.riskStatus === "OPPORTUNITY" && " 💎"}
-
+
{formatTVL(selectedPool.tvl)}
Total Value Locked
@@ -710,9 +708,8 @@ function EnhancedLiquidityPools() {
@@ -763,17 +760,16 @@ function EnhancedLiquidityPools() {
@@ -126,20 +128,20 @@ const LandingPage = () => { {/* Hero Stats */}
-
-
+
+
AI
Risk Analysis
-
-
+
+
DeFi
Blend Integration
-
-
+
+
3
Wallet Support
@@ -158,13 +160,13 @@ const LandingPage = () => {

-
+
{/* Step 1 */}
-
- 1 +
+ 1
-

Connect Wallet

+

Connect Wallet

Connect your Stellar wallet using Albedo, xBull, or Freighter

@@ -172,10 +174,10 @@ const LandingPage = () => { {/* Step 2 */}
-
- 2 +
+ 2
-

AI Analysis

+

AI Analysis

Our AI analyzes your transaction history and patterns

@@ -183,10 +185,10 @@ const LandingPage = () => { {/* Step 3 */}
-
- 3 +
+ 3
-

Get Score

+

Get Score

Receive your credit score and unlock new DeFi capabilities

diff --git a/src/components/UserRiskProfile.jsx b/src/components/UserRiskProfile.jsx index 47047b01..289d29c2 100644 --- a/src/components/UserRiskProfile.jsx +++ b/src/components/UserRiskProfile.jsx @@ -121,11 +121,11 @@ const UserRiskProfile = ({ walletAddress, riskScore, onTierSelect }) => { // Risk confirmation modal const RiskConfirmationModal = () => ( -
-
+
+
-
- +
+

High-Risk Tier Acknowledgment @@ -143,7 +143,7 @@ const UserRiskProfile = ({ walletAddress, riskScore, onTierSelect }) => {
@@ -152,9 +152,9 @@ const UserRiskProfile = ({ walletAddress, riskScore, onTierSelect }) => { setShowRiskModal(false); onTierSelect?.(selectedTier); }} - className="flex-1 px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700" + className="flex-1 px-4 py-3 bg-red-600 text-white rounded-lg hover:bg-red-700" > - Acknowledge & Proceed + Acknowledge & Proceed

@@ -219,14 +219,13 @@ const UserRiskProfile = ({ walletAddress, riskScore, onTierSelect }) => { {Object.entries(tierAccess).map(([tier, access]) => (
handleTierSelect(tier)} > -
+
{access.icon} @@ -246,7 +245,7 @@ const UserRiskProfile = ({ walletAddress, riskScore, onTierSelect }) => {
-
+
{access.status}
diff --git a/src/lib/riskTierClient.ts b/src/lib/riskTierClient.ts index 24796458..96310ff2 100644 --- a/src/lib/riskTierClient.ts +++ b/src/lib/riskTierClient.ts @@ -26,7 +26,7 @@ export type TierLevel = "TIER_1" | "TIER_2" | "TIER_3"; // Contract configuration export const RISK_TIER_CONTRACT_CONFIG = { - contractId: process.env.NEXT_PUBLIC_RISK_TIER_CONTRACT_ID || "", + contractId: process.env.NEXT_PUBLIC_RISK_TIER_CONTRACT_ID || "CACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", network: "TESTNET", rpcUrl: "https://soroban-testnet.stellar.org", };