vertical_credit_card 0.0.3 copy "vertical_credit_card: ^0.0.3" to clipboard
vertical_credit_card: ^0.0.3 copied to clipboard

A modern, customizable vertical credit/debit card UI widget for Flutter fintech apps with 3D flip, metallic, glassmorphic, and frozen card states.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:vertical_credit_card/vertical_credit_card.dart';

void main() {
  runApp(const VerticalCardDemoApp());
}

class VerticalCardDemoApp extends StatelessWidget {
  const VerticalCardDemoApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Vertical Credit Card Showcase',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        brightness: Brightness.dark,
        scaffoldBackgroundColor: const Color(0xFF0A0C10),
        colorScheme: const ColorScheme.dark(
          primary: Colors.cyanAccent,
          secondary: Colors.amberAccent,
          surface: Color(0xFF141722),
        ),
        useMaterial3: true,
      ),
      home: const CardShowcaseScreen(),
    );
  }
}

class CardShowcaseScreen extends StatefulWidget {
  const CardShowcaseScreen({super.key});

  @override
  State<CardShowcaseScreen> createState() => _CardShowcaseScreenState();
}

class _CardShowcaseScreenState extends State<CardShowcaseScreen> {
  int _selectedNavIndex =
      0; // 0: 3D Showcase, 1: Apple Wallet, 2: Checkout Form, 3: Studio
  int _selectedPresetIndex = 12; // Default to 🇨🇴 Nequi in Regional category

  static const List<Map<String, String>> _showcaseCategories = [
    {'id': 'Regional', 'label': '🌐 Regional', 'desc': 'Fintech & Neobanks'},
    {
      'id': 'Materials',
      'label': '💎 Materials',
      'desc': 'Bamboo, Steel & Ceramic'
    },
    {'id': 'Gamer', 'label': '🎮 Gamer RGB', 'desc': 'Chroma & Cyber PCB'},
    {'id': 'Crypto', 'label': '🪙 Crypto Web3', 'desc': 'Ledger & Solana'},
    {'id': 'Neobank', 'label': '🏦 Neobanks', 'desc': 'Global Digital Banks'},
    {'id': 'Luxury', 'label': '👑 Luxury Metal', 'desc': 'Apple & Amex'},
    {'id': 'Cyber', 'label': '⚡ Cyberpunk', 'desc': 'Neon & Glowing'},
    {'id': 'Artistic', 'label': '🎨 Artistic 3D', 'desc': 'Holo & Patterns'},
    {'id': 'All', 'label': '✨ All', 'desc': 'All 40 Presets'},
  ];
  String _selectedShowcaseCategory = 'Regional';

  List<Map<String, dynamic>> get _filteredShowcasePresets {
    if (_selectedShowcaseCategory == 'All') return _presets;
    return _presets
        .where((p) => p['family'] == _selectedShowcaseCategory)
        .toList();
  }

  // 3D Showcase state
  bool _isFrozen = false;
  bool _isExpired = false;
  bool _isPrivacyMode = false;
  bool _enable3DTilt = true;
  bool _isBackVisible = false;

  // Checkout Form state
  String _formCardNumber = '';
  String _formCardHolder = '';
  String _formExpiry = '';
  String _formCvv = '';
  CardBrand _formBrand = CardBrand.generic;
  bool _isCheckoutFlipped = false;

  // Studio state
  double _studioWidth = 240.0;
  double _studioBorderRadius = 16.0;
  double _studioMaxTiltAngle = 0.24;
  MetalType _studioMetal = MetalType.gold;
  final ChipColor _studioChip = ChipColor.gold;
  CardTextFinish _studioTextFinish = CardTextFinish.goldFoil;
  bool _studioEdgeGlow = false;
  bool _studioDiamondDust = true;
  bool _studioPaymentPulse = true;
  bool _studioHolo = false;
  bool _studioTilt = true;
  final bool _studioGlare = true;
  bool _studioBankingView = false;
  bool _studioIsFrozen = false;
  bool _studioPrivacy = false;
  bool _hideBankingBalance = false;
  String _studioCountryCode = 'GLOBAL';
  String _dynamicCvv = '842';

  void _regenerateDynamicCvv() {
    setState(() {
      final randomNum = 100 + (DateTime.now().microsecondsSinceEpoch % 900);
      _dynamicCvv = randomNum.toString();
    });
  }

  final List<Map<String, dynamic>> _presets = [
    {'name': 'Nubank', 'family': 'Neobank', 'theme': CardPresets.nubank},
    {'name': 'Wise', 'family': 'Neobank', 'theme': CardPresets.wise},
    {
      'name': 'Revolut Fluid',
      'family': 'Neobank',
      'theme': CardPresets.revolutChromatic,
    },
    {
      'name': 'Apple Card',
      'family': 'Luxury',
      'theme': CardPresets.appleTitanium,
    },
    {
      'name': 'Amex Black',
      'family': 'Luxury',
      'theme': CardPresets.amexCenturion,
    },
    {
      'name': 'Gold Prestige',
      'family': 'Luxury',
      'theme': CardPresets.goldPrestige,
    },
    {'name': 'Neon Cyber', 'family': 'Cyber', 'theme': CardPresets.neonCyan},
    {
      'name': 'Matrix Green',
      'family': 'Cyber',
      'theme': CardPresets.matrixGreen,
    },
    {
      'name': 'Holo Infinite',
      'family': 'Artistic',
      'theme': CardPresets.holoInfinite,
    },
    {
      'name': 'Painterly Globe',
      'family': 'Artistic',
      'theme': CardPresets.painterlyGlobe,
    },
    {
      'name': 'Topographic Gold',
      'family': 'Artistic',
      'theme': CardPresets.topographicGold,
    },
    {
      'name': 'Carbon Stealth',
      'family': 'Artistic',
      'theme': CardPresets.carbonStealth,
    },
    {
      'name': 'Alpine Horizon',
      'family': 'Artistic',
      'theme': CardPresets.alpineHorizon,
    },
    {
      'name': 'Solar Eclipse',
      'family': 'Artistic',
      'theme': CardPresets.solarEclipse,
    },
    {
      'name': 'Desert Dune',
      'family': 'Artistic',
      'theme': CardPresets.desertDune,
    },
    {
      'name': 'The Great Wave',
      'family': 'Artistic',
      'theme': CardPresets.greatWave,
    },
    {
      'name': 'Golden Kintsugi',
      'family': 'Artistic',
      'theme': CardPresets.goldenKintsugi,
    },
    {
      'name': 'Cosmos Constellation',
      'family': 'Artistic',
      'theme': CardPresets.cosmosConstellation,
    },
    {
      'name': 'Art Déco Gatsby',
      'family': 'Artistic',
      'theme': CardPresets.artDecoGold,
    },
    // Regional & Global Fintech Flagships
    {
      'name': '🇨🇴 Nequi',
      'family': 'Regional',
      'theme': CardPresets.nequi,
    },
    {
      'name': '🇨🇴 Bancolombia',
      'family': 'Regional',
      'theme': CardPresets.bancolombia,
    },
    {
      'name': '🇲🇽 Mercado Pago',
      'family': 'Regional',
      'theme': CardPresets.mercadoPago,
    },
    {
      'name': '🇲🇽 Hey Banco',
      'family': 'Regional',
      'theme': CardPresets.heyBanco,
    },
    {
      'name': '🇧🇷 Nu Ultravioleta',
      'family': 'Regional',
      'theme': CardPresets.nubankUltravioleta,
    },
    {
      'name': '🇧🇷 Banco Inter',
      'family': 'Regional',
      'theme': CardPresets.bancoInter,
    },
    {
      'name': '🇦🇷 Lemon Cash',
      'family': 'Regional',
      'theme': CardPresets.lemonCash,
    },
    {
      'name': '🇦🇷 Ualá',
      'family': 'Regional',
      'theme': CardPresets.uala,
    },
    {
      'name': '🇪🇸 N26 Glass',
      'family': 'Regional',
      'theme': CardPresets.n26,
    },
    {
      'name': '🇵🇪 Yape',
      'family': 'Regional',
      'theme': CardPresets.yape,
    },
    {
      'name': '🇨🇱 Tenpo',
      'family': 'Regional',
      'theme': CardPresets.tenpo,
    },
    {
      'name': '🇬🇧 Monzo Hot Coral',
      'family': 'Regional',
      'theme': CardPresets.monzoHotCoral,
    },
    {
      'name': '🇺🇸 Robinhood Gold',
      'family': 'Regional',
      'theme': CardPresets.robinhoodGold,
    },
    {
      'name': '🇺🇸 Cash App',
      'family': 'Regional',
      'theme': CardPresets.cashApp,
    },
    // Exotic Physical Materials
    {
      'name': 'Skeleton NFC',
      'family': 'Materials',
      'theme': CardPresets.skeletonNfc,
    },
    {
      'name': 'Bamboo Eco',
      'family': 'Materials',
      'theme': CardPresets.bambooEco,
    },
    {
      'name': 'Damascus Steel',
      'family': 'Materials',
      'theme': CardPresets.damascusSteel,
    },
    {
      'name': 'White Ceramic',
      'family': 'Materials',
      'theme': CardPresets.whiteCeramic,
    },
    // Gamer & Esports RGB
    {
      'name': 'Razer Chroma RGB',
      'family': 'Gamer',
      'theme': CardPresets.razerChroma,
    },
    {
      'name': 'Cyber PCB',
      'family': 'Gamer',
      'theme': CardPresets.cyberPcb,
    },
    // Crypto & Web3 Hardware
    {
      'name': 'Ledger Obsidian',
      'family': 'Crypto',
      'theme': CardPresets.ledgerObsidian,
    },
    {
      'name': 'Solana Aurora',
      'family': 'Crypto',
      'theme': CardPresets.solanaAurora,
    },
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          'Vertical Credit Card',
          style: TextStyle(
              fontWeight: FontWeight.w900, letterSpacing: 1.5, fontSize: 18),
        ),
        backgroundColor: Colors.transparent,
        elevation: 0,
        centerTitle: true,
        actions: [
          if (_selectedNavIndex == 0)
            IconButton(
              tooltip: _isPrivacyMode
                  ? 'Disable Privacy Mode'
                  : 'Enable Privacy Mode',
              icon: Icon(
                _isPrivacyMode
                    ? Icons.visibility_off_rounded
                    : Icons.visibility_rounded,
                color: _isPrivacyMode ? Colors.amberAccent : Colors.white70,
              ),
              onPressed: () {
                setState(() {
                  _isPrivacyMode = !_isPrivacyMode;
                });
              },
            ),
        ],
      ),
      body: SafeArea(
        child: IndexedStack(
          index: _selectedNavIndex,
          children: [
            _buildShowcaseView(),
            _buildWalletView(),
            _buildCheckoutFormView(),
            _buildStudioView(),
          ],
        ),
      ),
      bottomNavigationBar: NavigationBar(
        selectedIndex: _selectedNavIndex,
        onDestinationSelected: (index) =>
            setState(() => _selectedNavIndex = index),
        backgroundColor: const Color(0xFF0F1118),
        indicatorColor: Colors.cyanAccent.withValues(alpha: 0.18),
        destinations: const [
          NavigationDestination(
            icon: Icon(Icons.threed_rotation_rounded),
            label: 'Showcase',
          ),
          NavigationDestination(
            icon: Icon(Icons.wallet_rounded),
            label: 'Wallet',
          ),
          NavigationDestination(
            icon: Icon(Icons.payment_rounded),
            label: 'Checkout',
          ),
          NavigationDestination(
            icon: Icon(Icons.tune_rounded),
            label: 'Studio',
          ),
        ],
      ),
    );
  }

  // ---------------------------------------------------------------------------
  // 1. 3D SHOWCASE VIEW
  // ---------------------------------------------------------------------------
  Widget _buildShowcaseSelector() {
    final filtered = _filteredShowcasePresets;
    final activePreset = _presets[_selectedPresetIndex];
    final activeIndexInFiltered = filtered.indexOf(activePreset);

    return Column(
      children: [
        // 1. Categories Pill Bar
        SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          physics: const BouncingScrollPhysics(),
          padding: const EdgeInsets.symmetric(horizontal: 16),
          child: Row(
            children: _showcaseCategories.map((cat) {
              final isSelected = _selectedShowcaseCategory == cat['id'];
              return Padding(
                padding: const EdgeInsets.only(right: 6.0),
                child: InkWell(
                  borderRadius: BorderRadius.circular(20),
                  onTap: () {
                    setState(() {
                      _selectedShowcaseCategory = cat['id']!;
                      final newFiltered = _filteredShowcasePresets;
                      if (!newFiltered
                          .contains(_presets[_selectedPresetIndex])) {
                        _selectedPresetIndex =
                            _presets.indexOf(newFiltered.first);
                      }
                    });
                  },
                  child: AnimatedContainer(
                    duration: const Duration(milliseconds: 200),
                    curve: Curves.easeOutCubic,
                    padding:
                        const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
                    decoration: BoxDecoration(
                      color: isSelected
                          ? Colors.cyanAccent.withValues(alpha: 0.18)
                          : const Color(0xFF141824),
                      borderRadius: BorderRadius.circular(20),
                      border: Border.all(
                        color: isSelected
                            ? Colors.cyanAccent
                            : Colors.white.withValues(alpha: 0.08),
                        width: isSelected ? 1.2 : 0.8,
                      ),
                      boxShadow: isSelected
                          ? [
                              BoxShadow(
                                color:
                                    Colors.cyanAccent.withValues(alpha: 0.25),
                                blurRadius: 8,
                              ),
                            ]
                          : null,
                    ),
                    child: Text(
                      cat['label']!,
                      style: TextStyle(
                        fontSize: 11.5,
                        fontWeight:
                            isSelected ? FontWeight.w800 : FontWeight.w600,
                        color: isSelected ? Colors.cyanAccent : Colors.white70,
                      ),
                    ),
                  ),
                ),
              );
            }).toList(),
          ),
        ),

        const SizedBox(height: 6),

        // 2. Filtered Cards Row with Quick Steppers (< and >)
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 8.0),
          child: Row(
            children: [
              IconButton(
                tooltip: 'Previous Card',
                icon: const Icon(Icons.chevron_left_rounded, size: 24),
                color: Colors.white70,
                visualDensity: VisualDensity.compact,
                onPressed: filtered.isEmpty
                    ? null
                    : () {
                        setState(() {
                          final currentIdx = activeIndexInFiltered >= 0
                              ? activeIndexInFiltered
                              : 0;
                          final prevIdx = (currentIdx - 1 + filtered.length) %
                              filtered.length;
                          _selectedPresetIndex =
                              _presets.indexOf(filtered[prevIdx]);
                        });
                      },
              ),
              Expanded(
                child: SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  physics: const BouncingScrollPhysics(),
                  child: Row(
                    children: filtered.map((preset) {
                      final isSelected =
                          _presets[_selectedPresetIndex] == preset;
                      final isRegional = preset['family'] == 'Regional';
                      final isHolo = preset['family'] == 'Artistic';

                      return Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 3.0),
                        child: ChoiceChip(
                          avatar: isHolo
                              ? const Icon(Icons.auto_awesome_rounded,
                                  size: 14, color: Colors.purpleAccent)
                              : (isRegional
                                  ? const Icon(Icons.account_balance_rounded,
                                      size: 13, color: Colors.cyanAccent)
                                  : null),
                          label: Text(preset['name'] as String),
                          selected: isSelected,
                          selectedColor:
                              Colors.cyanAccent.withValues(alpha: 0.2),
                          labelStyle: TextStyle(
                            color:
                                isSelected ? Colors.cyanAccent : Colors.white70,
                            fontWeight: isSelected
                                ? FontWeight.bold
                                : FontWeight.normal,
                            fontSize: 12,
                          ),
                          side: BorderSide(
                            color:
                                isSelected ? Colors.cyanAccent : Colors.white12,
                          ),
                          onSelected: (selected) {
                            if (selected) {
                              setState(() {
                                _selectedPresetIndex = _presets.indexOf(preset);
                              });
                            }
                          },
                        ),
                      );
                    }).toList(),
                  ),
                ),
              ),
              IconButton(
                tooltip: 'Next Card',
                icon: const Icon(Icons.chevron_right_rounded, size: 24),
                color: Colors.white70,
                visualDensity: VisualDensity.compact,
                onPressed: filtered.isEmpty
                    ? null
                    : () {
                        setState(() {
                          final currentIdx = activeIndexInFiltered >= 0
                              ? activeIndexInFiltered
                              : 0;
                          final nextIdx = (currentIdx + 1) % filtered.length;
                          _selectedPresetIndex =
                              _presets.indexOf(filtered[nextIdx]);
                        });
                      },
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget _buildShowcaseView() {
    final activePreset = _presets[_selectedPresetIndex];

    return LayoutBuilder(
      builder: (context, constraints) {
        return SingleChildScrollView(
          child: ConstrainedBox(
            constraints: BoxConstraints(minHeight: constraints.maxHeight),
            child: IntrinsicHeight(
              child: Column(
                children: [
                  const SizedBox(height: 6),

                  // Categorized Presets Carousel & Stepper
                  _buildShowcaseSelector(),

                  const SizedBox(height: 10),

                  // Gesture Instruction Banner
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(
                        Icons.swipe_outlined,
                        size: 15,
                        color: Colors.white.withValues(alpha: 0.45),
                      ),
                      const SizedBox(width: 6),
                      Text(
                        _isBackVisible
                            ? 'Tap to flip FRONT  •  Drag to TILT in 3D'
                            : 'Tap to FLIP 3D  •  Drag to TILT with light reflection',
                        style: TextStyle(
                          color: Colors.white.withValues(alpha: 0.45),
                          fontSize: 11.5,
                        ),
                      ),
                    ],
                  ),

                  const Spacer(),

                  // The Active Vertical Card
                  _buildActiveCard(activePreset),

                  const Spacer(),

                  // Interactive Bottom Controls Panel
                  Container(
                    padding: const EdgeInsets.symmetric(
                        horizontal: 16, vertical: 12),
                    margin: const EdgeInsets.symmetric(
                        horizontal: 18, vertical: 10),
                    decoration: BoxDecoration(
                      color: const Color(0xFF14171E),
                      borderRadius: BorderRadius.circular(16),
                      border: Border.all(
                          color: Colors.white.withValues(alpha: 0.07)),
                    ),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: [
                        // 3D Tilt toggle button
                        _buildControlItem(
                          icon: Icons.threed_rotation_rounded,
                          label: '3D Tilt',
                          isActive: _enable3DTilt,
                          activeColor: Colors.purpleAccent,
                          onTap: () =>
                              setState(() => _enable3DTilt = !_enable3DTilt),
                        ),

                        // Privacy mode toggle
                        _buildControlItem(
                          icon: _isPrivacyMode
                              ? Icons.visibility_off_rounded
                              : Icons.visibility_rounded,
                          label: 'Privacy',
                          isActive: _isPrivacyMode,
                          activeColor: Colors.amberAccent,
                          onTap: () =>
                              setState(() => _isPrivacyMode = !_isPrivacyMode),
                        ),

                        // Freeze card button
                        _buildControlItem(
                          icon: Icons.ac_unit_rounded,
                          label: 'Freeze',
                          isActive: _isFrozen,
                          activeColor: Colors.cyanAccent,
                          onTap: () => setState(() => _isFrozen = !_isFrozen),
                        ),

                        // Expire card button
                        _buildControlItem(
                          icon: Icons.timer_off_outlined,
                          label: 'Expired',
                          isActive: _isExpired,
                          activeColor: Colors.redAccent,
                          onTap: () => setState(() => _isExpired = !_isExpired),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      },
    );
  }

  Widget _buildControlItem({
    required IconData icon,
    required String label,
    required bool isActive,
    required Color activeColor,
    required VoidCallback onTap,
  }) {
    return InkWell(
      onTap: onTap,
      borderRadius: BorderRadius.circular(10),
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Container(
              padding: const EdgeInsets.all(8),
              decoration: BoxDecoration(
                shape: BoxShape.circle,
                color: isActive
                    ? activeColor.withValues(alpha: 0.20)
                    : Colors.white.withValues(alpha: 0.05),
                border: Border.all(
                  color: isActive ? activeColor : Colors.white12,
                  width: 1.2,
                ),
              ),
              child: Icon(
                icon,
                size: 18,
                color: isActive ? activeColor : Colors.white54,
              ),
            ),
            const SizedBox(height: 5),
            Text(
              label,
              style: TextStyle(
                color: isActive ? activeColor : Colors.white54,
                fontSize: 10.5,
                fontWeight: isActive ? FontWeight.bold : FontWeight.normal,
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildActiveCard(Map<String, dynamic> preset) {
    final theme = preset['theme'] as VerticalCardTheme;
    final name = preset['name'] as String;

    String? bankName;
    CardBrand? brand;
    Widget? bankLogo;

    if (name == 'Painterly Globe') {
      bankName = 'CREDIT AGRICOLE';
      brand = CardBrand.mastercard;
      bankLogo = Container(
        width: 32,
        height: 32,
        decoration: const BoxDecoration(
          color: Colors.white,
          shape: BoxShape.circle,
        ),
        child: const Center(
          child: Text(
            'ca',
            style: TextStyle(
              color: Color(0xFF074585),
              fontWeight: FontWeight.w900,
              fontSize: 18,
              letterSpacing: -1.0,
            ),
          ),
        ),
      );
    } else if (name == 'Holo Infinite') {
      bankName = 'HOLO INFINITE';
      brand = CardBrand.visa;
    } else if (name == 'Topographic Gold') {
      bankName = 'GOLD VAULT';
      brand = CardBrand.visa;
    } else if (name == 'Carbon Stealth') {
      bankName = 'STEALTH RS';
      brand = CardBrand.mastercard;
    } else if (name == 'Apple Card') {
      bankName = 'APPLE';
      brand = CardBrand.generic;
    } else if (name == 'Amex Black') {
      bankName = 'CENTURION';
      brand = CardBrand.americanExpress;
    } else if (name == 'Wise') {
      bankName = 'WISE';
      brand = CardBrand.visa;
    }

    return VerticalCard(
      cardNumber: '5412 8888 1024 4321',
      cardHolder: 'ALEXANDER WRIGHT',
      expiryDate: '09/29',
      cvv: '719',
      bankName: bankName,
      brand: brand,
      cardTheme: theme,
      isFrozen: _isFrozen,
      isExpired: _isExpired,
      isPrivacyMode: _isPrivacyMode,
      enable3DTilt: _enable3DTilt,
      enableSpecularGlare: true,
      onFlipChange: (isBack) => setState(() => _isBackVisible = isBack),
      onPrivacyChange: (isPrivate) =>
          setState(() => _isPrivacyMode = isPrivate),
      bankLogo: bankLogo,
    );
  }

  // ---------------------------------------------------------------------------
  // 2. APPLE WALLET CASCADE VIEW
  // ---------------------------------------------------------------------------
  Widget _buildWalletView() {
    final walletCards = [
      VerticalCard.preset(
        preset: CardPresets.holoInfinite,
        cardNumber: '4532 9812 3456 7890',
        cardHolder: 'DIMAS CLEVES',
        expiryDate: '12/28',
        cvv: '942',
        bankName: 'HOLO INFINITE',
        enableFlip: false,
      ),
      VerticalCard.preset(
        preset: CardPresets.painterlyGlobe,
        cardNumber: '5412 8888 1024 4321',
        cardHolder: 'DIMAS CLEVES',
        expiryDate: '08/29',
        cvv: '821',
        bankName: 'CREDIT AGRICOLE',
        enableFlip: false,
      ),
      VerticalCard.preset(
        preset: CardPresets.topographicGold,
        cardNumber: '4000 1234 5678 9010',
        cardHolder: 'DIMAS CLEVES',
        expiryDate: '05/30',
        cvv: '333',
        bankName: 'GOLD ELEVATION',
        enableFlip: false,
      ),
      VerticalCard.preset(
        preset: CardPresets.carbonStealth,
        cardNumber: '3782 822468 005',
        cardHolder: 'DIMAS CLEVES',
        expiryDate: '11/27',
        cvv: '714',
        bankName: 'CARBON STEALTH',
        enableFlip: false,
      ),
    ];

    return SingleChildScrollView(
      padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 16),
      child: Column(
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Icon(Icons.touch_app_rounded,
                  size: 16, color: Colors.cyanAccent),
              const SizedBox(width: 8),
              Text(
                'Tap any card to expand / focus wallet',
                style: TextStyle(
                  color: Colors.white.withValues(alpha: 0.6),
                  fontSize: 13,
                  fontWeight: FontWeight.w500,
                ),
              ),
            ],
          ),
          const SizedBox(height: 18),
          Center(
            child: VerticalCardStack(
              cards: walletCards,
              cardSpacing: 62.0,
              cardHeight: 380.0,
            ),
          ),
        ],
      ),
    );
  }

  // ---------------------------------------------------------------------------
  // 3. SYNCHRONIZED CHECKOUT FORM (WITH CVV AUTO-FLIP)
  // ---------------------------------------------------------------------------
  Widget _buildCheckoutFormView() {
    return SingleChildScrollView(
      padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
      child: Column(
        children: [
          // Live synchronized card preview
          Center(
            child: VerticalCard.preset(
              preset: CardPresets.holoInfinite,
              cardNumber: _formCardNumber.isEmpty
                  ? '0000 0000 0000 0000'
                  : _formCardNumber,
              cardHolder:
                  _formCardHolder.isEmpty ? 'YOUR NAME' : _formCardHolder,
              expiryDate: _formExpiry.isEmpty ? 'MM/YY' : _formExpiry,
              cvv: _formCvv.isEmpty ? '•••' : _formCvv,
              brand: _formBrand == CardBrand.generic ? null : _formBrand,
              bankName: 'NEXUS BANK',
              isFlipped: _isCheckoutFlipped,
            ),
          ),

          const SizedBox(height: 20),

          // Instruction badge
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
            decoration: BoxDecoration(
              color: Colors.cyanAccent.withValues(alpha: 0.1),
              borderRadius: BorderRadius.circular(10),
              border:
                  Border.all(color: Colors.cyanAccent.withValues(alpha: 0.3)),
            ),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                const Icon(Icons.auto_awesome,
                    size: 16, color: Colors.cyanAccent),
                const SizedBox(width: 8),
                Text(
                  'Focus CVV field to watch the 3D auto-flip!',
                  style: TextStyle(
                    color: Colors.cyanAccent.withValues(alpha: 0.9),
                    fontSize: 12.5,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ],
            ),
          ),

          const SizedBox(height: 24),

          // The interactive form widget
          VerticalCardInputForm(
            onCardNumberChanged: (val) => setState(() => _formCardNumber = val),
            onCardHolderChanged: (val) => setState(() => _formCardHolder = val),
            onExpiryChanged: (val) => setState(() => _formExpiry = val),
            onCvvChanged: (val) => setState(() => _formCvv = val),
            onBrandChanged: (val) => setState(() => _formBrand = val),
            onCvvFocusChanged: (hasFocus) {
              setState(() => _isCheckoutFlipped = hasFocus);
            },
          ),
          const SizedBox(height: 30),
        ],
      ),
    );
  }

  // ---------------------------------------------------------------------------
  // 4. LIVE CARD CUSTOMIZER STUDIO
  // ---------------------------------------------------------------------------
  Widget _buildStudioView() {
    return SingleChildScrollView(
      padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // Mode Switcher: Free Canvas vs Banking App
          Center(
            child: SegmentedButton<bool>(
              segments: const [
                ButtonSegment<bool>(
                  value: false,
                  icon: Icon(Icons.palette_outlined, size: 18),
                  label: Text('Free Canvas',
                      style: TextStyle(fontWeight: FontWeight.w600)),
                ),
                ButtonSegment<bool>(
                  value: true,
                  icon: Icon(Icons.phone_iphone_rounded, size: 18),
                  label: Text('Banking App',
                      style: TextStyle(fontWeight: FontWeight.w600)),
                ),
              ],
              selected: {_studioBankingView},
              onSelectionChanged: (newSelection) {
                setState(() {
                  _studioBankingView = newSelection.first;
                });
              },
            ),
          ),

          if (_studioBankingView) ...[
            const SizedBox(height: 14),
            Center(
              child: _buildCountrySelector(),
            ),
          ],

          const SizedBox(height: 20),

          // Live customized preview (Canvas vs Banking App Mockup)
          if (!_studioBankingView)
            Center(
              child: VerticalCard(
                cardNumber: '4000 1234 5678 9010',
                cardHolder: 'DIMAS CLEVES',
                expiryDate: '12/30',
                cvv: '888',
                bankName: 'CUSTOM CARD',
                width: _studioWidth,
                enable3DTilt: _studioTilt,
                enableSpecularGlare: _studioGlare,
                enableHolographicFoil: _studioHolo,
                maxTiltAngle: _studioMaxTiltAngle,
                textFinish: _studioTextFinish,
                enableEdgeGlow: _studioEdgeGlow,
                enableDiamondDust: _studioDiamondDust,
                enablePaymentPulse: _studioPaymentPulse,
                cardTheme: VerticalCardTheme.metallic(
                  metalType: _studioMetal,
                  chipColor: _studioChip,
                  borderRadius: BorderRadius.circular(_studioBorderRadius),
                ),
              ),
            )
          else
            _buildBankingAppMockup(),

          const SizedBox(height: 24),

          // Sliders & Controls
          Text(
            'Card Width: ${_studioWidth.toInt()} px',
            style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13),
          ),
          Slider(
            value: _studioWidth,
            min: 200,
            max: 280,
            activeColor: Colors.cyanAccent,
            onChanged: (val) => setState(() => _studioWidth = val),
          ),

          Text(
            'Border Radius: ${_studioBorderRadius.toInt()} px',
            style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13),
          ),
          Slider(
            value: _studioBorderRadius,
            min: 8,
            max: 28,
            activeColor: Colors.cyanAccent,
            onChanged: (val) => setState(() => _studioBorderRadius = val),
          ),

          Text(
            'Max Tilt Angle: ${(_studioMaxTiltAngle * 180 / 3.14159).toStringAsFixed(1)}°',
            style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13),
          ),
          Slider(
            value: _studioMaxTiltAngle,
            min: 0.10,
            max: 0.45,
            activeColor: Colors.cyanAccent,
            onChanged: (val) => setState(() => _studioMaxTiltAngle = val),
          ),

          const SizedBox(height: 12),

          // Typography Finish selector
          const Text('Typography 3D Finish:',
              style: TextStyle(fontWeight: FontWeight.bold, fontSize: 13)),
          const SizedBox(height: 8),
          Wrap(
            spacing: 8,
            children: CardTextFinish.values.map((finish) {
              final isSelected = _studioTextFinish == finish;
              return ChoiceChip(
                label: Text(finish.name),
                selected: isSelected,
                selectedColor: Colors.amberAccent.withValues(alpha: 0.3),
                onSelected: (sel) {
                  if (sel) setState(() => _studioTextFinish = finish);
                },
              );
            }).toList(),
          ),

          const SizedBox(height: 14),

          // Metal Type selector
          const Text('Metal Finish:',
              style: TextStyle(fontWeight: FontWeight.bold, fontSize: 13)),
          const SizedBox(height: 8),
          Wrap(
            spacing: 8,
            children: MetalType.values.map((metal) {
              final isSelected = _studioMetal == metal;
              return ChoiceChip(
                label: Text(metal.name),
                selected: isSelected,
                selectedColor: Colors.cyanAccent.withValues(alpha: 0.25),
                onSelected: (sel) {
                  if (sel) setState(() => _studioMetal = metal);
                },
              );
            }).toList(),
          ),

          const SizedBox(height: 16),

          // Toggles
          SwitchListTile(
            title: const Text('✨ Diamond Dust / Micro-Glitter'),
            value: _studioDiamondDust,
            activeThumbColor: Colors.amberAccent,
            onChanged: (val) => setState(() => _studioDiamondDust = val),
          ),
          SwitchListTile(
            title: const Text('⚡ Cyber Edge Glow (Perimeter Beam)'),
            value: _studioEdgeGlow,
            activeThumbColor: Colors.cyanAccent,
            onChanged: (val) => setState(() => _studioEdgeGlow = val),
          ),
          SwitchListTile(
            title: const Text('📡 NFC Contactless Tap Pulse'),
            value: _studioPaymentPulse,
            activeThumbColor: const Color(0xFF00FFC2),
            onChanged: (val) => setState(() => _studioPaymentPulse = val),
          ),
          SwitchListTile(
            title: const Text('🌈 Holographic Rainbow Foil'),
            value: _studioHolo,
            activeThumbColor: Colors.purpleAccent,
            onChanged: (val) => setState(() => _studioHolo = val),
          ),
          SwitchListTile(
            title: const Text('🕹️ 3D Tilt Physics'),
            value: _studioTilt,
            activeThumbColor: Colors.cyanAccent,
            onChanged: (val) => setState(() => _studioTilt = val),
          ),

          const SizedBox(height: 20),

          // Copy Dart Code button
          SizedBox(
            width: double.infinity,
            height: 48,
            child: ElevatedButton.icon(
              style: ElevatedButton.styleFrom(
                backgroundColor: Colors.cyanAccent,
                foregroundColor: Colors.black,
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(12)),
              ),
              icon: const Icon(Icons.copy_rounded, size: 18),
              label: const Text('Copy Dart Code',
                  style: TextStyle(fontWeight: FontWeight.bold)),
              onPressed: () {
                final code = '''
VerticalCard(
  cardNumber: '4000 1234 5678 9010',
  cardHolder: 'DIMAS CLEVES',
  expiryDate: '12/30',
  cvv: '888',
  width: $_studioWidth,
  enable3DTilt: $_studioTilt,
  enableSpecularGlare: $_studioGlare,
  enableHolographicFoil: $_studioHolo,
  textFinish: CardTextFinish.${_studioTextFinish.name},
  enableEdgeGlow: $_studioEdgeGlow,
  enableDiamondDust: $_studioDiamondDust,
  enablePaymentPulse: $_studioPaymentPulse,
  cardTheme: VerticalCardTheme.metallic(
    metalType: MetalType.${_studioMetal.name},
    chipColor: ChipColor.${_studioChip.name},
    borderRadius: BorderRadius.circular($_studioBorderRadius),
  ),
)''';
                Clipboard.setData(ClipboardData(text: code));
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(
                    content: const Text('✅ Dart code copied to clipboard!'),
                    backgroundColor: Colors.teal[800],
                    behavior: SnackBarBehavior.floating,
                  ),
                );
              },
            ),
          ),
          const SizedBox(height: 30),
        ],
      ),
    );
  }

  // ---------------------------------------------------------------------------
  // 5. REGIONAL FINTECH SELECTOR & BANKING APP MOCKUP
  // ---------------------------------------------------------------------------
  void _showAccountSelectorSheet(BuildContext context) {
    final accounts = [
      {
        'code': 'GLOBAL',
        'country': 'Global (USA / International)',
        'currency': 'USD',
        'flag': '🌎',
        'account': 'Primary Global Account',
        'card': 'Nexus Black Metal',
        'color': Colors.amberAccent,
      },
      {
        'code': 'CO',
        'country': 'Colombia',
        'currency': 'COP',
        'flag': '🇨🇴',
        'account': 'Cuenta Nequi Ahorros',
        'card': 'Nequi Magenta Neon',
        'color': const Color(0xFFFF007A),
      },
      {
        'code': 'MX',
        'country': 'México',
        'currency': 'MXN',
        'flag': '🇲🇽',
        'account': 'Débito Digital SPEI',
        'card': 'Mercado Pago Blue',
        'color': const Color(0xFF009EE3),
      },
      {
        'code': 'BR',
        'country': 'Brasil',
        'currency': 'BRL',
        'flag': '🇧🇷',
        'account': 'Nu Ultravioleta Black',
        'card': 'Nubank Ultravioleta',
        'color': const Color(0xFFC084FC),
      },
      {
        'code': 'AR',
        'country': 'Argentina',
        'currency': 'ARS',
        'flag': '🇦🇷',
        'account': 'Lemon Crypto & Pesos',
        'card': 'Lemon Cash Cyber',
        'color': const Color(0xFF00FF7F),
      },
      {
        'code': 'ES',
        'country': 'España / Europa',
        'currency': 'EUR',
        'flag': '🇪🇸',
        'account': 'N26 Metal IBAN',
        'card': 'N26 Frosted Glass',
        'color': const Color(0xFF00D4B2),
      },
      {
        'code': 'PE',
        'country': 'Perú',
        'currency': 'PEN',
        'flag': '🇵🇪',
        'account': 'Yape BCP Digital',
        'card': 'Yape Royal Purple',
        'color': const Color(0xFF862799),
      },
      {
        'code': 'CL',
        'country': 'Chile',
        'currency': 'CLP',
        'flag': '🇨🇱',
        'account': 'Cuenta Prepago Tenpo',
        'card': 'Tenpo Petrol & Teal',
        'color': const Color(0xFF00C9A7),
      },
      {
        'code': 'UK',
        'country': 'United Kingdom',
        'currency': 'GBP',
        'flag': '🇬🇧',
        'account': 'Monzo Current Account',
        'card': 'Monzo Hot Coral',
        'color': const Color(0xFFFF483B),
      },
      {
        'code': 'US',
        'country': 'United States',
        'currency': 'USD',
        'flag': '🇺🇸',
        'account': 'Robinhood Gold Cash',
        'card': 'Robinhood Gold Metal',
        'color': const Color(0xFFD4AF37),
      },
    ];

    showModalBottomSheet<void>(
      context: context,
      backgroundColor: const Color(0xFF0F1420),
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
      ),
      builder: (BuildContext sheetContext) {
        return SafeArea(
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Center(
                  child: Container(
                    width: 38,
                    height: 4,
                    decoration: BoxDecoration(
                      color: Colors.white24,
                      borderRadius: BorderRadius.circular(2),
                    ),
                  ),
                ),
                const SizedBox(height: 16),
                const Row(
                  children: [
                    Icon(Icons.account_balance_wallet_rounded,
                        size: 20, color: Colors.cyanAccent),
                    SizedBox(width: 8),
                    Text(
                      'Select Active Account & Region',
                      style: TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.w800,
                        color: Colors.white,
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 4),
                const Text(
                  'Switching accounts updates currency, live card and local merchant transactions.',
                  style: TextStyle(fontSize: 12, color: Colors.white54),
                ),
                const SizedBox(height: 14),
                Flexible(
                  child: ListView.separated(
                    shrinkWrap: true,
                    itemCount: accounts.length,
                    separatorBuilder: (_, __) => const SizedBox(height: 6),
                    itemBuilder: (context, index) {
                      final acc = accounts[index];
                      final isSelected = _studioCountryCode == acc['code'];
                      final color = acc['color'] as Color;

                      return InkWell(
                        borderRadius: BorderRadius.circular(14),
                        onTap: () {
                          setState(() {
                            _studioCountryCode = acc['code'] as String;
                          });
                          Navigator.pop(sheetContext);
                        },
                        child: Container(
                          padding: const EdgeInsets.symmetric(
                              horizontal: 14, vertical: 10),
                          decoration: BoxDecoration(
                            color: isSelected
                                ? color.withValues(alpha: 0.12)
                                : const Color(0xFF141926),
                            borderRadius: BorderRadius.circular(14),
                            border: Border.all(
                              color: isSelected
                                  ? color
                                  : Colors.white.withValues(alpha: 0.06),
                              width: isSelected ? 1.2 : 0.8,
                            ),
                          ),
                          child: Row(
                            children: [
                              Text(
                                acc['flag'] as String,
                                style: const TextStyle(fontSize: 22),
                              ),
                              const SizedBox(width: 12),
                              Expanded(
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: [
                                    Text(
                                      acc['country'] as String,
                                      style: TextStyle(
                                        fontSize: 13,
                                        fontWeight: FontWeight.w800,
                                        color:
                                            isSelected ? color : Colors.white,
                                      ),
                                    ),
                                    const SizedBox(height: 2),
                                    Text(
                                      '${acc['account']} · ${acc['card']}',
                                      style: const TextStyle(
                                        fontSize: 11,
                                        color: Colors.white54,
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                              Container(
                                padding: const EdgeInsets.symmetric(
                                    horizontal: 8, vertical: 4),
                                decoration: BoxDecoration(
                                  color: color.withValues(alpha: 0.15),
                                  borderRadius: BorderRadius.circular(6),
                                ),
                                child: Text(
                                  acc['currency'] as String,
                                  style: TextStyle(
                                    fontSize: 11,
                                    fontWeight: FontWeight.w800,
                                    color: color,
                                  ),
                                ),
                              ),
                              if (isSelected) ...[
                                const SizedBox(width: 8),
                                Icon(Icons.check_circle_rounded,
                                    size: 18, color: color),
                              ],
                            ],
                          ),
                        ),
                      );
                    },
                  ),
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  Widget _buildCountrySelector() {
    final countries = [
      {'code': 'GLOBAL', 'label': 'Global', 'flag': '🌎'},
      {'code': 'CO', 'label': 'Colombia', 'flag': '🇨🇴'},
      {'code': 'MX', 'label': 'México', 'flag': '🇲🇽'},
      {'code': 'BR', 'label': 'Brasil', 'flag': '🇧🇷'},
      {'code': 'AR', 'label': 'Argentina', 'flag': '🇦🇷'},
      {'code': 'ES', 'label': 'España', 'flag': '🇪🇸'},
      {'code': 'PE', 'label': 'Perú', 'flag': '🇵🇪'},
      {'code': 'CL', 'label': 'Chile', 'flag': '🇨🇱'},
      {'code': 'UK', 'label': 'UK', 'flag': '🇬🇧'},
      {'code': 'US', 'label': 'USA', 'flag': '🇺🇸'},
    ];

    return SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      physics: const BouncingScrollPhysics(),
      child: Row(
        children: countries.map((country) {
          final isSelected = _studioCountryCode == country['code'];
          return Padding(
            padding: const EdgeInsets.only(right: 6.0),
            child: InkWell(
              borderRadius: BorderRadius.circular(20),
              onTap: () {
                setState(() {
                  _studioCountryCode = country['code']!;
                });
              },
              child: AnimatedContainer(
                duration: const Duration(milliseconds: 220),
                curve: Curves.easeOutCubic,
                padding:
                    const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
                decoration: BoxDecoration(
                  color: isSelected
                      ? Colors.cyanAccent.withValues(alpha: 0.18)
                      : const Color(0xFF141824),
                  borderRadius: BorderRadius.circular(20),
                  border: Border.all(
                    color: isSelected
                        ? Colors.cyanAccent
                        : Colors.white.withValues(alpha: 0.08),
                    width: isSelected ? 1.2 : 0.8,
                  ),
                  boxShadow: isSelected
                      ? [
                          BoxShadow(
                            color: Colors.cyanAccent.withValues(alpha: 0.25),
                            blurRadius: 8,
                            spreadRadius: 0.5,
                          ),
                        ]
                      : null,
                ),
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Text(
                      country['flag']!,
                      style: const TextStyle(fontSize: 13),
                    ),
                    const SizedBox(width: 5),
                    Text(
                      country['label']!,
                      style: TextStyle(
                        fontSize: 11,
                        fontWeight:
                            isSelected ? FontWeight.w800 : FontWeight.w600,
                        color: isSelected ? Colors.cyanAccent : Colors.white70,
                      ),
                    ),
                  ],
                ),
              ),
            ),
          );
        }).toList(),
      ),
    );
  }

  Widget _buildBankingAppMockup() {
    final cardMockupWidth = _studioWidth.clamp(190.0, 225.0);

    final String currency;
    final String balance;
    final String trend;
    final String accountType;
    final String accountTag;
    final Color accountTagColor;
    final String bankName;
    final String cardHolder;
    final String cardNumber;
    final VerticalCardTheme activeCardTheme;
    final List<Map<String, dynamic>> transactions;

    switch (_studioCountryCode) {
      case 'CO':
        currency = 'COP';
        balance = r'$4.850.000';
        trend = '+5.2% este mes';
        accountTag = 'COLOMBIA FINTECH';
        accountTagColor = const Color(0xFFFF007A);
        accountType = 'Cuenta Nequi Ahorros';
        bankName = 'NEQUI';
        cardHolder = 'DIMAS CLEVES';
        cardNumber = '4512 8839 0192 4812';
        activeCardTheme = CardPresets.nequi.copyWith(
          borderRadius: BorderRadius.circular(_studioBorderRadius),
        );
        transactions = [
          {
            'title': 'Rappi Prime',
            'subtitle': 'Domicilio Gourmet · Nequi',
            'amount': r'-$34.900',
            'time': 'Hoy, 1:45 PM',
            'isIncome': false,
            'icon': Icons.delivery_dining_rounded,
            'iconBg': const Color(0xFF2C1A24),
          },
          {
            'title': 'Éxito Wow Poblado',
            'subtitle': 'Supermercado · Contactless',
            'amount': r'-$185.400',
            'time': 'Hoy, 11:20 AM',
            'isIncome': false,
            'icon': Icons.shopping_bag_outlined,
            'iconBg': const Color(0xFF2B2818),
          },
          {
            'title': 'Bancolombia Nómina',
            'subtitle': 'Transferencia directa recibida',
            'amount': r'+$1.200.000',
            'time': 'Ayer',
            'isIncome': true,
            'icon': Icons.account_balance_rounded,
            'iconBg': const Color(0xFF162529),
          },
          {
            'title': 'Spotify Premium',
            'subtitle': 'Suscripción mensual',
            'amount': r'-$16.900',
            'time': '15 Sep',
            'isIncome': false,
            'icon': Icons.music_note_rounded,
            'iconBg': const Color(0xFF172B1E),
          },
        ];
        break;

      case 'MX':
        currency = 'MXN';
        balance = r'$28,500.00';
        trend = '+4.1% este mes';
        accountTag = 'MÉXICO FINTECH';
        accountTagColor = const Color(0xFF009EE3);
        accountType = 'Débito Digital SPEI';
        bankName = 'MERCADO PAGO';
        cardHolder = 'DIMAS CLEVES';
        cardNumber = '5256 7102 9940 1834';
        activeCardTheme = CardPresets.mercadoPago.copyWith(
          borderRadius: BorderRadius.circular(_studioBorderRadius),
        );
        transactions = [
          {
            'title': 'Mercado Libre',
            'subtitle': 'Auriculares Sony WH-1000XM5',
            'amount': r'-$1,499.00',
            'time': 'Hoy, 3:15 PM',
            'isIncome': false,
            'icon': Icons.shopping_cart_outlined,
            'iconBg': const Color(0xFF162535),
          },
          {
            'title': 'OXXO Gas',
            'subtitle': 'Gasolina Premium · Contactless',
            'amount': r'-$650.00',
            'time': 'Hoy, 9:30 AM',
            'isIncome': false,
            'icon': Icons.local_gas_station_rounded,
            'iconBg': const Color(0xFF2C1919),
          },
          {
            'title': 'SPEI Nómina Directa',
            'subtitle': 'Fintech Hub SA · SPEI',
            'amount': r'+$14,250.00',
            'time': 'Ayer',
            'isIncome': true,
            'icon': Icons.account_balance_rounded,
            'iconBg': const Color(0xFF162A20),
          },
          {
            'title': 'Cinépolis VIP',
            'subtitle': 'Entradas y combos · Cine',
            'amount': r'-$320.00',
            'time': '14 Sep',
            'isIncome': false,
            'icon': Icons.movie_creation_outlined,
            'iconBg': const Color(0xFF1E212E),
          },
        ];
        break;

      case 'BR':
        currency = 'BRL';
        balance = r'R$ 8.450,00';
        trend = '+6.5% este mês';
        accountTag = 'BRASIL FINTECH';
        accountTagColor = const Color(0xFFC084FC);
        accountType = 'Nu Ultravioleta Black';
        bankName = 'NUBANK BR';
        cardHolder = 'DIMAS CLEVES';
        cardNumber = '5409 3321 8765 4019';
        activeCardTheme = CardPresets.nubankUltravioleta.copyWith(
          borderRadius: BorderRadius.circular(_studioBorderRadius),
        );
        transactions = [
          {
            'title': 'iFood Delivery',
            'subtitle': 'Restaurante Fogo de Chão',
            'amount': r'-R$ 74,90',
            'time': 'Hoje, 13:10',
            'isIncome': false,
            'icon': Icons.fastfood_rounded,
            'iconBg': const Color(0xFF2C1A1D),
          },
          {
            'title': 'Mercado Livre Brasil',
            'subtitle': 'Eletrônicos & Casa',
            'amount': r'-R$ 289,00',
            'time': 'Hoje, 10:04',
            'isIncome': false,
            'icon': Icons.shopping_bag_outlined,
            'iconBg': const Color(0xFF2B2818),
          },
          {
            'title': 'Transferência PIX Recebida',
            'subtitle': 'De: Lucas Santos · PIX chave',
            'amount': r'+R$ 2.500,00',
            'time': 'Ontem',
            'isIncome': true,
            'icon': Icons.bolt_rounded,
            'iconBg': const Color(0xFF162C24),
          },
          {
            'title': 'Uber Viagens',
            'subtitle': 'Corrida São Paulo · Apple Pay',
            'amount': r'-R$ 32,50',
            'time': '16 Set',
            'isIncome': false,
            'icon': Icons.directions_car_rounded,
            'iconBg': const Color(0xFF20232B),
          },
        ];
        break;

      case 'AR':
        currency = 'ARS';
        balance = r'$1.250.000';
        trend = '+12.4% este mes';
        accountTag = 'ARGENTINA CRYPTO';
        accountTagColor = const Color(0xFF00FF7F);
        accountType = 'Lemon Crypto & Pesos';
        bankName = 'LEMON CASH';
        cardHolder = 'DIMAS CLEVES';
        cardNumber = '4123 9087 6543 2100';
        activeCardTheme = CardPresets.lemonCash.copyWith(
          borderRadius: BorderRadius.circular(_studioBorderRadius),
        );
        transactions = [
          {
            'title': 'PedidosYa Gourmet',
            'subtitle': 'Almuerzo Hamburguesería',
            'amount': r'-$14.500',
            'time': 'Hoy, 13:50',
            'isIncome': false,
            'icon': Icons.moped_rounded,
            'iconBg': const Color(0xFF2C191E),
          },
          {
            'title': 'Coto Digital',
            'subtitle': 'Supermercado semanal · QR',
            'amount': r'-$68.200',
            'time': 'Hoy, 10:15',
            'isIncome': false,
            'icon': Icons.local_grocery_store_outlined,
            'iconBg': const Color(0xFF1B262C),
          },
          {
            'title': 'Lemon Earn Cashback',
            'subtitle': 'Cashback 2% en Bitcoin (BTC)',
            'amount': r'+$12.350',
            'time': 'Ayer',
            'isIncome': true,
            'icon': Icons.currency_bitcoin_rounded,
            'iconBg': const Color(0xFF252B14),
          },
          {
            'title': 'Steam Games LatAm',
            'subtitle': 'Videojuegos PC · Digital',
            'amount': r'-$9.800',
            'time': '15 Sep',
            'isIncome': false,
            'icon': Icons.sports_esports_outlined,
            'iconBg': const Color(0xFF1B202D),
          },
        ];
        break;

      case 'ES':
        currency = 'EUR';
        balance = r'€12.350,00';
        trend = '+2.9% this month';
        accountTag = 'EUROPE BANK';
        accountTagColor = const Color(0xFF00D4B2);
        accountType = 'N26 Metal IBAN';
        bankName = 'N26';
        cardHolder = 'DIMAS CLEVES';
        cardNumber = '4921 5432 1098 7654';
        activeCardTheme = CardPresets.n26.copyWith(
          borderRadius: BorderRadius.circular(_studioBorderRadius),
        );
        transactions = [
          {
            'title': 'El Corte Inglés',
            'subtitle': 'Moda y Accesorios · Contactless',
            'amount': r'-€129,50',
            'time': 'Hoy, 16:30',
            'isIncome': false,
            'icon': Icons.storefront_rounded,
            'iconBg': const Color(0xFF1C2B22),
          },
          {
            'title': 'Mercadona',
            'subtitle': 'Alimentación · Pago móvil',
            'amount': r'-€64,20',
            'time': 'Hoy, 12:10',
            'isIncome': false,
            'icon': Icons.shopping_cart_outlined,
            'iconBg': const Color(0xFF1B2827),
          },
          {
            'title': 'SEPA Payroll Transfer',
            'subtitle': 'Empresa Tecnológica SL',
            'amount': r'+€2.850,00',
            'time': 'Ayer',
            'isIncome': true,
            'icon': Icons.account_balance_outlined,
            'iconBg': const Color(0xFF16252A),
          },
          {
            'title': 'Glovo Prime',
            'subtitle': 'Envío express farmacia',
            'amount': r'-€18,90',
            'time': '16 Sep',
            'isIncome': false,
            'icon': Icons.delivery_dining_rounded,
            'iconBg': const Color(0xFF2B2519),
          },
        ];
        break;

      case 'PE':
        currency = 'PEN';
        balance = r'S/. 4,280.50';
        trend = '+5.8% este mes';
        accountTag = 'PERÚ FINTECH';
        accountTagColor = const Color(0xFF862799);
        accountType = 'Yape Cuenta Digital BCP';
        bankName = 'YAPE BCP';
        cardHolder = 'DIMAS CLEVES';
        cardNumber = '4218 9032 1145 7820';
        activeCardTheme = CardPresets.yape.copyWith(
          borderRadius: BorderRadius.circular(_studioBorderRadius),
        );
        transactions = [
          {
            'title': 'Bembos Gourmet',
            'subtitle': 'Combo La Clásica · Delivery Yape',
            'amount': r'-S/. 38.50',
            'time': 'Hoy, 2:10 PM',
            'isIncome': false,
            'icon': Icons.fastfood_rounded,
            'iconBg': const Color(0xFF2E1A2B),
          },
          {
            'title': 'Metro Cencosud',
            'subtitle': 'Supermercado · Pago QR',
            'amount': r'-S/. 142.00',
            'time': 'Hoy, 10:45 AM',
            'isIncome': false,
            'icon': Icons.shopping_basket_outlined,
            'iconBg': const Color(0xFF1E2829),
          },
          {
            'title': 'Transferencia Yape Directa',
            'subtitle': 'De: Carlos M. · Celular Yape',
            'amount': r'+S/. 350.00',
            'time': 'Ayer',
            'isIncome': true,
            'icon': Icons.bolt_rounded,
            'iconBg': const Color(0xFF192B28),
          },
          {
            'title': 'Cineplanet Prime',
            'subtitle': 'Entradas San Miguel · Tarjeta',
            'amount': r'-S/. 45.00',
            'time': '16 Sep',
            'isIncome': false,
            'icon': Icons.movie_creation_outlined,
            'iconBg': const Color(0xFF28192A),
          },
        ];
        break;

      case 'CL':
        currency = 'CLP';
        balance = r'$840.000';
        trend = '+7.2% este mes';
        accountTag = 'CHILE FINTECH';
        accountTagColor = const Color(0xFF00C9A7);
        accountType = 'Cuenta Prepago Tenpo';
        bankName = 'TENPO';
        cardHolder = 'DIMAS CLEVES';
        cardNumber = '5109 2384 9012 3456';
        activeCardTheme = CardPresets.tenpo.copyWith(
          borderRadius: BorderRadius.circular(_studioBorderRadius),
        );
        transactions = [
          {
            'title': 'Jumbo La Dehesa',
            'subtitle': 'Supermercado · Contactless',
            'amount': r'-$64.990',
            'time': 'Hoy, 12:40 PM',
            'isIncome': false,
            'icon': Icons.local_grocery_store_outlined,
            'iconBg': const Color(0xFF162B28),
          },
          {
            'title': 'Uber Eats Santiago',
            'subtitle': 'Sushi Roll · Tenpo Mastercard',
            'amount': r'-$14.500',
            'time': 'Hoy, 1:15 PM',
            'isIncome': false,
            'icon': Icons.delivery_dining_rounded,
            'iconBg': const Color(0xFF2B221A),
          },
          {
            'title': 'Transferencia TEF Recibida',
            'subtitle': 'Fintech Chile SpA · TEF',
            'amount': r'+$450.000',
            'time': 'Ayer',
            'isIncome': true,
            'icon': Icons.account_balance_rounded,
            'iconBg': const Color(0xFF142922),
          },
          {
            'title': 'Copec Pronto',
            'subtitle': 'Combustible 95 · Pago App',
            'amount': r'-$25.000',
            'time': '15 Sep',
            'isIncome': false,
            'icon': Icons.local_gas_station_rounded,
            'iconBg': const Color(0xFF2A1F18),
          },
        ];
        break;

      case 'UK':
        currency = 'GBP';
        balance = r'£3,420.80';
        trend = '+3.4% this month';
        accountTag = 'UK NEOBANK';
        accountTagColor = const Color(0xFFFF483B);
        accountType = 'Monzo Current Account';
        bankName = 'MONZO';
        cardHolder = 'DIMAS CLEVES';
        cardNumber = '5355 2201 9845 6712';
        activeCardTheme = CardPresets.monzoHotCoral.copyWith(
          borderRadius: BorderRadius.circular(_studioBorderRadius),
        );
        transactions = [
          {
            'title': 'Pret A Manger London',
            'subtitle': 'Organic Flat White & Sandwich',
            'amount': r'-£6.45',
            'time': 'Today, 1:05 PM',
            'isIncome': false,
            'icon': Icons.coffee_rounded,
            'iconBg': const Color(0xFF2B1919),
          },
          {
            'title': 'Sainsbury’s Local',
            'subtitle': 'Groceries · Apple Pay',
            'amount': r'-£24.80',
            'time': 'Today, 11:15 AM',
            'isIncome': false,
            'icon': Icons.shopping_bag_outlined,
            'iconBg': const Color(0xFF2A2016),
          },
          {
            'title': 'Faster Payments Salary',
            'subtitle': 'Monzo Labs UK · Direct Credit',
            'amount': r'+£2,850.00',
            'time': 'Yesterday',
            'isIncome': true,
            'icon': Icons.account_balance_rounded,
            'iconBg': const Color(0xFF162A22),
          },
          {
            'title': 'Transport for London (TfL)',
            'subtitle': 'Contactless Tube / Underground',
            'amount': r'-£3.40',
            'time': '16 Sep',
            'isIncome': false,
            'icon': Icons.train_rounded,
            'iconBg': const Color(0xFF1B232E),
          },
        ];
        break;

      case 'US':
        currency = 'USD';
        balance = r'$9,250.00';
        trend = '+8.1% this month';
        accountTag = 'USA WEALTH & CASH';
        accountTagColor = const Color(0xFFD4AF37);
        accountType = 'Robinhood Gold Cash Account';
        bankName = 'ROBINHOOD';
        cardHolder = 'DIMAS CLEVES';
        cardNumber = '4929 1845 0092 3819';
        activeCardTheme = CardPresets.robinhoodGold.copyWith(
          borderRadius: BorderRadius.circular(_studioBorderRadius),
        );
        transactions = [
          {
            'title': 'Whole Foods Market',
            'subtitle': 'Organic Groceries · Gold Card',
            'amount': r'-$78.20',
            'time': 'Today, 2:40 PM',
            'isIncome': false,
            'icon': Icons.shopping_basket_outlined,
            'iconBg': const Color(0xFF262615),
          },
          {
            'title': 'Blue Bottle Coffee',
            'subtitle': 'Hayes Valley Espresso',
            'amount': r'-$7.50',
            'time': 'Today, 9:20 AM',
            'isIncome': false,
            'icon': Icons.coffee_rounded,
            'iconBg': const Color(0xFF1A232D),
          },
          {
            'title': 'High-Yield Cash Interest',
            'subtitle': '5.0% APY Monthly Sweep',
            'amount': r'+$38.50',
            'time': 'Yesterday',
            'isIncome': true,
            'icon': Icons.trending_up_rounded,
            'iconBg': const Color(0xFF162B1D),
          },
          {
            'title': 'Target Superstore',
            'subtitle': 'Electronics & Home Goods',
            'amount': r'-$42.10',
            'time': '15 Sep',
            'isIncome': false,
            'icon': Icons.storefront_rounded,
            'iconBg': const Color(0xFF2C1818),
          },
        ];
        break;

      case 'GLOBAL':
      default:
        currency = 'USD';
        balance = r'$14,850.50';
        trend = '+3.8% this month';
        accountTag = 'BLACK METAL';
        accountTagColor = Colors.amberAccent;
        accountType = 'Primary Global Account';
        bankName = 'NEXUS BLACK';
        cardHolder = 'DIMAS CLEVES';
        cardNumber = '4000 1234 5678 9010';
        activeCardTheme = VerticalCardTheme.metallic(
          metalType: _studioMetal,
          chipColor: _studioChip,
          borderRadius: BorderRadius.circular(_studioBorderRadius),
        );
        transactions = [
          {
            'title': 'Apple Store',
            'subtitle': 'iPhone 16 Pro 256GB · Card',
            'amount': r'-$1,199.00',
            'time': 'Today, 2:20 PM',
            'isIncome': false,
            'icon': Icons.apple_rounded,
            'iconBg': const Color(0xFF1E2433),
          },
          {
            'title': 'Starbucks Reserve',
            'subtitle': 'Caramel Macchiato · Contactless',
            'amount': r'-$6.80',
            'time': 'Today, 9:15 AM',
            'isIncome': false,
            'icon': Icons.coffee_rounded,
            'iconBg': const Color(0xFF1A2621),
          },
          {
            'title': 'Payroll Deposit',
            'subtitle': 'Google LLC · Direct Deposit',
            'amount': r'+$3,450.00',
            'time': 'Yesterday',
            'isIncome': true,
            'icon': Icons.work_outline_rounded,
            'iconBg': const Color(0xFF172C24),
          },
          {
            'title': 'Netflix 4K Ultra',
            'subtitle': 'Monthly Subscription',
            'amount': r'-$19.99',
            'time': 'Sep 15',
            'isIncome': false,
            'icon': Icons.movie_outlined,
            'iconBg': const Color(0xFF2C1A22),
          },
        ];
        break;
    }

    return Center(
      child: Container(
        width: double.infinity,
        constraints: const BoxConstraints(maxWidth: 360),
        decoration: BoxDecoration(
          color: const Color(0xFF0C0F17),
          borderRadius: BorderRadius.circular(28),
          border: Border.all(
            color: const Color(0xFF232838),
            width: 1.5,
          ),
          boxShadow: [
            BoxShadow(
              color: Colors.black.withValues(alpha: 0.55),
              blurRadius: 28,
              offset: const Offset(0, 12),
            ),
            BoxShadow(
              color: Colors.cyanAccent.withValues(alpha: 0.04),
              blurRadius: 20,
              spreadRadius: 2,
            ),
          ],
        ),
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // Status Bar & Dynamic Island
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                const Text(
                  '9:41',
                  style: TextStyle(
                    fontSize: 12,
                    fontWeight: FontWeight.w700,
                    letterSpacing: 0.2,
                    color: Colors.white,
                  ),
                ),
                Container(
                  width: 76,
                  height: 18,
                  decoration: BoxDecoration(
                    color: const Color(0xFF05070A),
                    borderRadius: BorderRadius.circular(10),
                    border: Border.all(
                      color: Colors.white.withValues(alpha: 0.08),
                    ),
                  ),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Container(
                        width: 6,
                        height: 6,
                        decoration: const BoxDecoration(
                          color: Color(0xFF00FFC2),
                          shape: BoxShape.circle,
                        ),
                      ),
                      const SizedBox(width: 8),
                      Container(
                        width: 8,
                        height: 8,
                        decoration: BoxDecoration(
                          color: Colors.white.withValues(alpha: 0.2),
                          shape: BoxShape.circle,
                        ),
                      ),
                    ],
                  ),
                ),
                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Icon(
                      Icons.signal_cellular_alt_rounded,
                      size: 13,
                      color: Colors.white.withValues(alpha: 0.85),
                    ),
                    const SizedBox(width: 4),
                    Icon(
                      Icons.wifi_rounded,
                      size: 13,
                      color: Colors.white.withValues(alpha: 0.85),
                    ),
                    const SizedBox(width: 4),
                    const Icon(
                      Icons.battery_5_bar_rounded,
                      size: 15,
                      color: Color(0xFF00FFC2),
                    ),
                  ],
                ),
              ],
            ),

            const SizedBox(height: 14),

            // User Profile Header
            Row(
              children: [
                Stack(
                  children: [
                    Container(
                      width: 38,
                      height: 38,
                      decoration: BoxDecoration(
                        shape: BoxShape.circle,
                        gradient: const LinearGradient(
                          colors: [Color(0xFF00E5FF), Color(0xFF7C4DFF)],
                          begin: Alignment.topLeft,
                          end: Alignment.bottomRight,
                        ),
                        boxShadow: [
                          BoxShadow(
                            color: Colors.cyanAccent.withValues(alpha: 0.3),
                            blurRadius: 8,
                          ),
                        ],
                      ),
                      child: const Center(
                        child: Text(
                          'DC',
                          style: TextStyle(
                            color: Colors.black,
                            fontWeight: FontWeight.w900,
                            fontSize: 13,
                          ),
                        ),
                      ),
                    ),
                    Positioned(
                      right: 0,
                      bottom: 0,
                      child: Container(
                        width: 9,
                        height: 9,
                        decoration: BoxDecoration(
                          color: const Color(0xFF00FFC2),
                          shape: BoxShape.circle,
                          border: Border.all(
                            color: const Color(0xFF0C0F17),
                            width: 1.5,
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
                const SizedBox(width: 10),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const Text(
                        'Hello, Dimas 👋',
                        style: TextStyle(
                          fontSize: 14.5,
                          fontWeight: FontWeight.w800,
                          color: Colors.white,
                        ),
                      ),
                      const SizedBox(height: 2),
                      InkWell(
                        borderRadius: BorderRadius.circular(6),
                        onTap: () => _showAccountSelectorSheet(context),
                        child: Padding(
                          padding: const EdgeInsets.symmetric(vertical: 2.0),
                          child: Row(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              Container(
                                padding: const EdgeInsets.symmetric(
                                  horizontal: 6,
                                  vertical: 1.5,
                                ),
                                decoration: BoxDecoration(
                                  color:
                                      accountTagColor.withValues(alpha: 0.15),
                                  borderRadius: BorderRadius.circular(4),
                                  border: Border.all(
                                    color:
                                        accountTagColor.withValues(alpha: 0.4),
                                    width: 0.6,
                                  ),
                                ),
                                child: Text(
                                  accountTag,
                                  style: TextStyle(
                                    fontSize: 8.5,
                                    fontWeight: FontWeight.w800,
                                    color: accountTagColor,
                                    letterSpacing: 0.6,
                                  ),
                                ),
                              ),
                              const SizedBox(width: 6),
                              Flexible(
                                child: Text(
                                  accountType,
                                  overflow: TextOverflow.ellipsis,
                                  style: const TextStyle(
                                    fontSize: 11,
                                    color: Colors.white70,
                                  ),
                                ),
                              ),
                              const SizedBox(width: 4),
                              Icon(
                                Icons.keyboard_arrow_down_rounded,
                                size: 14,
                                color: accountTagColor.withValues(alpha: 0.9),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
                Container(
                  width: 34,
                  height: 34,
                  decoration: BoxDecoration(
                    color: const Color(0xFF161A26),
                    borderRadius: BorderRadius.circular(10),
                    border: Border.all(
                      color: Colors.white.withValues(alpha: 0.08),
                    ),
                  ),
                  child: Stack(
                    alignment: Alignment.center,
                    children: [
                      Icon(
                        Icons.notifications_outlined,
                        size: 18,
                        color: Colors.white.withValues(alpha: 0.8),
                      ),
                      Positioned(
                        top: 6,
                        right: 7,
                        child: Container(
                          width: 6,
                          height: 6,
                          decoration: const BoxDecoration(
                            color: Colors.redAccent,
                            shape: BoxShape.circle,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),

            const SizedBox(height: 14),

            // Account Balance Card
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
              decoration: BoxDecoration(
                gradient: const LinearGradient(
                  colors: [Color(0xFF141926), Color(0xFF0F131E)],
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight,
                ),
                borderRadius: BorderRadius.circular(16),
                border: Border.all(
                  color: Colors.white.withValues(alpha: 0.08),
                ),
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Text(
                        'TOTAL AVAILABLE BALANCE',
                        style: TextStyle(
                          fontSize: 9.5,
                          fontWeight: FontWeight.w700,
                          letterSpacing: 0.8,
                          color: Colors.white.withValues(alpha: 0.55),
                        ),
                      ),
                      InkWell(
                        borderRadius: BorderRadius.circular(12),
                        onTap: () {
                          setState(() {
                            _hideBankingBalance = !_hideBankingBalance;
                          });
                        },
                        child: Padding(
                          padding: const EdgeInsets.all(2.0),
                          child: Icon(
                            _hideBankingBalance
                                ? Icons.visibility_off_rounded
                                : Icons.visibility_rounded,
                            size: 16,
                            color: Colors.cyanAccent.withValues(alpha: 0.8),
                          ),
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 6),
                  Wrap(
                    alignment: WrapAlignment.spaceBetween,
                    crossAxisAlignment: WrapCrossAlignment.center,
                    spacing: 8,
                    runSpacing: 4,
                    children: [
                      Row(
                        mainAxisSize: MainAxisSize.min,
                        crossAxisAlignment: CrossAxisAlignment.baseline,
                        textBaseline: TextBaseline.alphabetic,
                        children: [
                          Text(
                            _hideBankingBalance ? '••••••••' : balance,
                            style: const TextStyle(
                              fontSize: 22,
                              fontWeight: FontWeight.w900,
                              letterSpacing: -0.5,
                              color: Colors.white,
                            ),
                          ),
                          const SizedBox(width: 6),
                          InkWell(
                            borderRadius: BorderRadius.circular(6),
                            onTap: () => _showAccountSelectorSheet(context),
                            child: Padding(
                              padding: const EdgeInsets.symmetric(
                                  horizontal: 3, vertical: 1),
                              child: Row(
                                mainAxisSize: MainAxisSize.min,
                                children: [
                                  Text(
                                    currency,
                                    style: const TextStyle(
                                      fontSize: 12,
                                      fontWeight: FontWeight.w700,
                                      color: Colors.cyanAccent,
                                    ),
                                  ),
                                  const SizedBox(width: 2),
                                  Icon(
                                    Icons.keyboard_arrow_down_rounded,
                                    size: 14,
                                    color: Colors.cyanAccent
                                        .withValues(alpha: 0.8),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ],
                      ),
                      Container(
                        padding: const EdgeInsets.symmetric(
                          horizontal: 7,
                          vertical: 3.5,
                        ),
                        decoration: BoxDecoration(
                          color:
                              const Color(0xFF00FFC2).withValues(alpha: 0.12),
                          borderRadius: BorderRadius.circular(8),
                          border: Border.all(
                            color:
                                const Color(0xFF00FFC2).withValues(alpha: 0.35),
                            width: 0.8,
                          ),
                        ),
                        child: Row(
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            const Icon(
                              Icons.trending_up_rounded,
                              size: 13,
                              color: Color(0xFF00FFC2),
                            ),
                            const SizedBox(width: 4),
                            Text(
                              trend,
                              style: const TextStyle(
                                fontSize: 10,
                                fontWeight: FontWeight.w800,
                                color: Color(0xFF00FFC2),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ),

            const SizedBox(height: 14),

            // Live Customized Vertical Card Embedded
            Center(
              child: VerticalCard(
                cardNumber: cardNumber,
                cardHolder: cardHolder,
                expiryDate: '12/30',
                cvv: _dynamicCvv,
                bankName: bankName,
                width: cardMockupWidth,
                isFrozen: _studioIsFrozen,
                isPrivacyMode: _studioPrivacy,
                enable3DTilt: _studioTilt,
                enableSpecularGlare: _studioGlare,
                enableHolographicFoil: _studioHolo,
                maxTiltAngle: _studioMaxTiltAngle,
                textFinish: _studioTextFinish,
                enableEdgeGlow: _studioEdgeGlow,
                enableDiamondDust: _studioDiamondDust,
                enablePaymentPulse: _studioPaymentPulse,
                cardTheme: activeCardTheme,
              ),
            ),

            const SizedBox(height: 10),

            // Dynamic Security CVV Odometer Banner
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
              decoration: BoxDecoration(
                color: const Color(0xFF141926),
                borderRadius: BorderRadius.circular(10),
                border: Border.all(
                  color: Colors.cyanAccent.withValues(alpha: 0.25),
                  width: 0.8,
                ),
              ),
              child: Row(
                children: [
                  const Icon(
                    Icons.shield_outlined,
                    size: 14,
                    color: Colors.cyanAccent,
                  ),
                  const SizedBox(width: 5),
                  const Text(
                    'CVV: ',
                    style: TextStyle(
                      fontSize: 10.5,
                      fontWeight: FontWeight.w700,
                      color: Colors.white70,
                    ),
                  ),
                  RollingDigitText(
                    text: _dynamicCvv,
                    style: const TextStyle(
                      fontSize: 12.5,
                      fontWeight: FontWeight.w900,
                      color: Colors.cyanAccent,
                      letterSpacing: 1.0,
                    ),
                  ),
                  const Spacer(),
                  InkWell(
                    borderRadius: BorderRadius.circular(6),
                    onTap: _regenerateDynamicCvv,
                    child: Container(
                      padding: const EdgeInsets.symmetric(
                        horizontal: 8,
                        vertical: 3,
                      ),
                      decoration: BoxDecoration(
                        color: Colors.cyanAccent.withValues(alpha: 0.12),
                        borderRadius: BorderRadius.circular(6),
                        border: Border.all(
                          color: Colors.cyanAccent.withValues(alpha: 0.4),
                          width: 0.8,
                        ),
                      ),
                      child: const Row(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          Icon(
                            Icons.refresh_rounded,
                            size: 12,
                            color: Colors.cyanAccent,
                          ),
                          SizedBox(width: 3),
                          Text(
                            'Rotate CVV',
                            style: TextStyle(
                              fontSize: 10,
                              fontWeight: FontWeight.w800,
                              color: Colors.cyanAccent,
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            ),

            const SizedBox(height: 10),

            // Card Interactive Action Controls
            Row(
              children: [
                Expanded(
                  child: _buildActionButton(
                    icon: _studioIsFrozen
                        ? Icons.ac_unit_rounded
                        : Icons.lock_outline_rounded,
                    label: _studioIsFrozen ? 'Unfreeze' : 'Freeze',
                    isActive: _studioIsFrozen,
                    activeColor: Colors.cyanAccent,
                    onTap: () {
                      setState(() {
                        _studioIsFrozen = !_studioIsFrozen;
                      });
                    },
                  ),
                ),
                const SizedBox(width: 8),
                Expanded(
                  child: _buildActionButton(
                    icon: Icons.contactless_rounded,
                    label: _studioPaymentPulse ? 'NFC Active' : 'Tap to Pay',
                    isActive: _studioPaymentPulse,
                    activeColor: const Color(0xFF00FFC2),
                    onTap: () {
                      setState(() {
                        _studioPaymentPulse = !_studioPaymentPulse;
                      });
                      ScaffoldMessenger.of(context).showSnackBar(
                        SnackBar(
                          content: Text(
                            _studioPaymentPulse
                                ? '📡 Contactless payment radar activated'
                                : '⏸️ Contactless payment paused',
                          ),
                          backgroundColor: Colors.teal[800],
                          duration: const Duration(milliseconds: 1200),
                          behavior: SnackBarBehavior.floating,
                        ),
                      );
                    },
                  ),
                ),
                const SizedBox(width: 8),
                Expanded(
                  child: _buildActionButton(
                    icon: _studioPrivacy
                        ? Icons.visibility_off_rounded
                        : Icons.visibility_rounded,
                    label: _studioPrivacy ? 'Show' : 'Hide',
                    isActive: _studioPrivacy,
                    activeColor: Colors.amberAccent,
                    onTap: () {
                      setState(() {
                        _studioPrivacy = !_studioPrivacy;
                      });
                    },
                  ),
                ),
              ],
            ),

            const SizedBox(height: 16),

            // Recent Transactions Section
            Row(
              children: [
                const Expanded(
                  child: Text(
                    'Recent Transactions',
                    style: TextStyle(
                      fontSize: 13,
                      fontWeight: FontWeight.w800,
                      color: Colors.white,
                    ),
                  ),
                ),
                Text(
                  'See all',
                  style: TextStyle(
                    fontSize: 11,
                    fontWeight: FontWeight.w600,
                    color: Colors.cyanAccent.withValues(alpha: 0.8),
                  ),
                ),
              ],
            ),

            const SizedBox(height: 10),

            ...transactions.map(
              (tx) => Padding(
                padding: const EdgeInsets.only(bottom: 6.0),
                child: _buildTransactionTile(
                  title: tx['title'] as String,
                  subtitle: tx['subtitle'] as String,
                  amount: tx['amount'] as String,
                  time: tx['time'] as String,
                  isIncome: tx['isIncome'] as bool,
                  icon: tx['icon'] as IconData,
                  iconBg: tx['iconBg'] as Color,
                ),
              ),
            ),

            const SizedBox(height: 14),

            // Home Bar Indicator
            Center(
              child: Container(
                width: 110,
                height: 4,
                decoration: BoxDecoration(
                  color: Colors.white.withValues(alpha: 0.2),
                  borderRadius: BorderRadius.circular(2),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildActionButton({
    required IconData icon,
    required String label,
    required bool isActive,
    required Color activeColor,
    required VoidCallback onTap,
  }) {
    return InkWell(
      onTap: onTap,
      borderRadius: BorderRadius.circular(12),
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 200),
        padding: const EdgeInsets.symmetric(vertical: 8),
        decoration: BoxDecoration(
          color: isActive
              ? activeColor.withValues(alpha: 0.18)
              : const Color(0xFF161A26),
          borderRadius: BorderRadius.circular(12),
          border: Border.all(
            color: isActive
                ? activeColor.withValues(alpha: 0.6)
                : Colors.white.withValues(alpha: 0.08),
            width: 1,
          ),
        ),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(
              icon,
              size: 17,
              color: isActive ? activeColor : Colors.white70,
            ),
            const SizedBox(height: 4),
            Text(
              label,
              style: TextStyle(
                fontSize: 10,
                fontWeight: isActive ? FontWeight.w700 : FontWeight.w500,
                color: isActive ? activeColor : Colors.white70,
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildTransactionTile({
    required String title,
    required String subtitle,
    required String amount,
    required String time,
    required bool isIncome,
    required IconData icon,
    required Color iconBg,
  }) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
      decoration: BoxDecoration(
        color: const Color(0xFF121622),
        borderRadius: BorderRadius.circular(12),
        border: Border.all(
          color: Colors.white.withValues(alpha: 0.05),
        ),
      ),
      child: Row(
        children: [
          Container(
            width: 36,
            height: 36,
            decoration: BoxDecoration(
              color: iconBg,
              borderRadius: BorderRadius.circular(10),
            ),
            child: Icon(
              icon,
              size: 18,
              color: isIncome ? const Color(0xFF00FFC2) : Colors.white70,
            ),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  title,
                  style: const TextStyle(
                    fontSize: 12.5,
                    fontWeight: FontWeight.w700,
                    color: Colors.white,
                  ),
                ),
                const SizedBox(height: 2),
                Text(
                  subtitle,
                  style: TextStyle(
                    fontSize: 10,
                    color: Colors.white.withValues(alpha: 0.45),
                  ),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
              ],
            ),
          ),
          Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              Text(
                amount,
                style: TextStyle(
                  fontSize: 12.5,
                  fontWeight: FontWeight.w800,
                  color: isIncome ? const Color(0xFF00FFC2) : Colors.white,
                ),
              ),
              const SizedBox(height: 2),
              Text(
                time,
                style: TextStyle(
                  fontSize: 9.5,
                  color: Colors.white.withValues(alpha: 0.4),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}
2
likes
0
points
189
downloads

Publisher

unverified uploader

Weekly Downloads

A modern, customizable vertical credit/debit card UI widget for Flutter fintech apps with 3D flip, metallic, glassmorphic, and frozen card states.

Repository (GitHub)
View/report issues

Topics

#credit-card #fintech #vertical-card #card-wallet #wallet

License

unknown (license)

Dependencies

flutter

More

Packages that depend on vertical_credit_card