import dayjs from 'dayjs';

import ChallengeProgressCard from '@/components/challenges/ChallengeProgressCard';
import { ConfirmationSheet } from '@/components/ui/ConfirmationSheet';
import { Colors } from '@/constants/Colors';
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
import { useAuthGuard } from '@/hooks/useAuthGuard';
import { useColorScheme } from '@/hooks/useColorScheme';
import { useI18n } from '@/hooks/useI18n';
import {
  fetchChallenges,
  joinChallengeByCode,
  resetJoinByCodeState,
  selectChallengeCards,
  selectChallengesListError,
  selectChallengesListStatus,
  selectCustomChallengeCards,
  selectJoinByCodeError,
  selectJoinByCodeStatus,
  selectOfficialChallengeCards,
  type ChallengeCardViewModel,
} from '@/store/challengesSlice';
import { Toast } from '@/utils/toast.utils';
import { Ionicons } from '@expo/vector-icons';
import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect';
import { Image } from 'expo-image';
import { LinearGradient } from 'expo-linear-gradient';
import { useRouter } from 'expo-router';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
  ActivityIndicator,
  Animated,
  FlatList,
  ScrollView,
  StyleSheet,
  Text,
  TextInput,
  TouchableOpacity,
  View,
  useWindowDimensions
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

const AVATAR_SIZE = 36;
const CARD_IMAGE_WIDTH = 132;
const CARD_IMAGE_HEIGHT = 96;

const CAROUSEL_ITEM_SPACING = 16;
const MIN_CAROUSEL_CARD_WIDTH = 280;
const DOT_BASE_SIZE = 6;

export default function ChallengesScreen() {
  const theme = (useColorScheme() ?? 'light') as 'light' | 'dark';
  const insets = useSafeAreaInsets();
  const { t } = useI18n();

  const { ensureLoggedIn } = useAuthGuard();

  const colorTokens = Colors[theme];
  const router = useRouter();
  const dispatch = useAppDispatch();
  const glassAvailable = isLiquidGlassAvailable();
  const allChallenges = useAppSelector(selectChallengeCards);
  const customChallenges = useAppSelector(selectCustomChallengeCards);

  
  const officialChallenges = useAppSelector(selectOfficialChallengeCards);
  const joinedCustomChallenges = useMemo(
    () => customChallenges.filter((item) => item.isJoined),
    [customChallenges]
  );
  const listStatus = useAppSelector(selectChallengesListStatus);
  const listError = useAppSelector(selectChallengesListError);
  const joinByCodeStatus = useAppSelector(selectJoinByCodeStatus);
  const joinByCodeError = useAppSelector(selectJoinByCodeError);
  const [joinModalVisible, setJoinModalVisible] = useState(false);
  const [shareCodeInput, setShareCodeInput] = useState('');
  const ongoingChallenges = useMemo(() => {
    const now = dayjs();
    return allChallenges.filter((challenge) => {
      if (challenge.status !== 'ongoing' || !challenge.isJoined || !challenge.progress) {
        return false;
      }

      if (challenge.endAt) {
        const endDate = dayjs(challenge.endAt);
        if (endDate.isValid() && endDate.isBefore(now)) {
          return false;
        }
      }

      return true;
    });
  }, [allChallenges]);
  const progressTrackColor = theme === 'dark' ? 'rgba(255, 255, 255, 0.08)' : '#eceffa';
  const progressInactiveColor = theme === 'dark' ? 'rgba(255, 255, 255, 0.24)' : '#dfe4f6';

  useEffect(() => {
    if (listStatus === 'idle') {
      dispatch(fetchChallenges());
    }
  }, [dispatch, listStatus]);

  const gradientColors: [string, string] =
    theme === 'dark'
      ? ['#1f2230', '#10131e']
      : [colorTokens.backgroundGradientStart, colorTokens.backgroundGradientEnd];

  useEffect(() => {
    if (!joinModalVisible) {
      dispatch(resetJoinByCodeState());
      setShareCodeInput('');
    }
  }, [dispatch, joinModalVisible]);

  const handleCreatePress = useCallback(async () => {
    const ok = await ensureLoggedIn();
    if (!ok) return;
    router.push('/challenges/create-custom');
  }, [ensureLoggedIn, router]);

  const handleOpenJoin = useCallback(async () => {
    const ok = await ensureLoggedIn();
    if (!ok) return;
    setJoinModalVisible(true);
  }, [ensureLoggedIn]);

  const isJoiningByCode = joinByCodeStatus === 'loading';

  const handleSubmitShareCode = useCallback(async () => {
    if (isJoiningByCode) return;
    const ok = await ensureLoggedIn();
    if (!ok) return;
    if (!shareCodeInput.trim()) {
      Toast.warning(t('challenges.invalidInviteCode'));
      return;
    }
    const formatted = shareCodeInput.trim().toUpperCase();
    try {
      const result = await dispatch(joinChallengeByCode(formatted)).unwrap();
      await dispatch(fetchChallenges());
      setJoinModalVisible(false);
      Toast.success(t('challenges.joinSuccess'));
      router.push({ pathname: '/challenges/[id]', params: { id: result.challenge.id } });
    } catch (error) {
      const message = typeof error === 'string' ? error : t('challenges.joinFailed');
      Toast.error(message);
    }
  }, [dispatch, ensureLoggedIn, isJoiningByCode, router, shareCodeInput]);

  const renderChallenges = () => {
    if (listStatus === 'loading' && allChallenges.length === 0) {
      return (
        <View style={styles.stateContainer}>
          <ActivityIndicator color={colorTokens.primary} />
          <Text style={[styles.stateText, { color: colorTokens.textSecondary }]}>{t('challenges.loading')}</Text>
        </View>
      );
    }

    if (listStatus === 'failed' && allChallenges.length === 0) {
      return (
        <View style={styles.stateContainer}>
          <Text style={[styles.stateText, { color: colorTokens.textSecondary }]}>
            {listError ?? t('challenges.loadFailed')}
          </Text>
          <TouchableOpacity
            style={[styles.retryButton, { borderColor: colorTokens.primary }]}
            activeOpacity={0.9}
            onPress={() => dispatch(fetchChallenges())}
          >
            <Text style={[styles.retryText, { color: colorTokens.primary }]}>{t('challenges.retry')}</Text>
          </TouchableOpacity>
        </View>
      );
    }

    if (customChallenges.length === 0 && officialChallenges.length === 0) {
      return (
        <View style={styles.stateContainer}>
          <Text style={[styles.stateText, { color: colorTokens.textSecondary }]}>{t('challenges.empty')}</Text>
        </View>
      );
    }

    return (
      <View style={styles.cardGroups}>
        {joinedCustomChallenges.length ? (
          <>
            <View style={styles.sectionHeaderRow}>
              <Text style={[styles.sectionHeaderText, { color: colorTokens.text }]}>{t('challenges.customChallenges')}</Text>
            </View>
            <View style={styles.cardsContainer}>
              {joinedCustomChallenges.map((challenge) => (
                <ChallengeCard
                  key={challenge.id}
                  challenge={challenge}
                  surfaceColor={colorTokens.surface}
                  textColor={colorTokens.text}
                  mutedColor={colorTokens.textSecondary}
                  onPress={() =>
                    router.push({ pathname: '/challenges/[id]', params: { id: challenge.id } })
                  }
                />
              ))}
            </View>
          </>
        ) : null}

        <View style={[styles.sectionHeaderRow, { marginTop: joinedCustomChallenges.length ? 12 : 0 }]}>
          <Text style={[styles.sectionHeaderText, { color: colorTokens.text }]}>{t('challenges.officialChallengesTitle')}</Text>
        </View>
        {officialChallenges.length ? (
          <View style={styles.cardsContainer}>
            {officialChallenges.map((challenge) => (
              <ChallengeCard
                key={challenge.id}
                challenge={challenge}
                surfaceColor={colorTokens.surface}
                textColor={colorTokens.text}
                mutedColor={colorTokens.textSecondary}
                onPress={() =>
                  router.push({ pathname: '/challenges/[id]', params: { id: challenge.id } })
                }
              />
            ))}
          </View>
        ) : (
          <View style={[styles.stateContainer, styles.customEmpty]}>
            <Text style={[styles.stateText, { color: colorTokens.textSecondary }]}>{t('challenges.officialChallenges')}</Text>
          </View>
        )}
      </View>
    );
  };

  return (
    <View style={[styles.screen, { backgroundColor: colorTokens.pageBackgroundEmphasis }]}>
      <LinearGradient colors={gradientColors} style={StyleSheet.absoluteFillObject} />
      <ScrollView
        contentContainerStyle={[styles.scrollContent, {
          paddingTop: insets.top,
        }]}
        showsVerticalScrollIndicator={false}
        bounces
      >
        <View style={styles.headerRow}>
          <View>
            <Text style={[styles.title, { color: colorTokens.text }]}>{t('challenges.title')}</Text>
            <Text style={[styles.subtitle, { color: colorTokens.textSecondary }]}>{t('challenges.subtitle')}</Text>
          </View>
          <View style={styles.headerActions}>
            <TouchableOpacity activeOpacity={0.85} onPress={handleOpenJoin}>
              {glassAvailable ? (
                <GlassView
                  style={styles.joinButtonGlass}
                  glassEffectStyle="regular"
                  tintColor="rgba(255,255,255,0.18)"
                  isInteractive
                >
                  <Text style={styles.joinButtonLabel}>{t('challenges.join')}</Text>
                </GlassView>
              ) : (
                <View style={[styles.joinButtonGlass, styles.joinButtonFallback]}>
                  <Text style={[styles.joinButtonLabel, { color: colorTokens.text }]}>{t('challenges.join')}</Text>
                </View>
              )}
            </TouchableOpacity>
            <TouchableOpacity activeOpacity={0.9} onPress={handleCreatePress} style={{ marginLeft: 10 }}>
              {glassAvailable ? (
                <GlassView
                  style={styles.createButton}
                  tintColor="rgba(255,255,255,0.22)"
                  isInteractive
                >
                  <Ionicons name="add" size={18} color="#0f1528" />
                </GlassView>
              ) : (
                <View style={[styles.createButton, styles.createButtonFallback]}>
                  <Ionicons name="add" size={18} color={colorTokens.text} />
                </View>
              )}
            </TouchableOpacity>
          </View>
        </View>

        {ongoingChallenges.length ? (
          <OngoingChallengesCarousel
            challenges={ongoingChallenges}
            colorTokens={colorTokens}
            trackColor={progressTrackColor}
            inactiveColor={progressInactiveColor}
            onPress={(challenge) =>
              router.push({ pathname: '/challenges/[id]', params: { id: challenge.id } })
            }
          />
        ) : null}

        <View style={styles.cardsContainer}>{renderChallenges()}</View>
      </ScrollView>
      <ConfirmationSheet
        visible={joinModalVisible}
        onClose={() => setJoinModalVisible(false)}
        onConfirm={handleSubmitShareCode}
        title={t('challenges.joinModal.title')}
        description={t('challenges.joinModal.description')}
        confirmText={isJoiningByCode ? t('challenges.joinModal.joining') : t('challenges.joinModal.confirm')}
        cancelText={t('challenges.joinModal.cancel')}
        loading={isJoiningByCode}
        content={
          <View style={styles.modalInputWrapper}>
            <TextInput
              style={styles.modalInput}
              placeholder={t('challenges.joinModal.placeholder')}
              placeholderTextColor="#9ca3af"
              value={shareCodeInput}
              onChangeText={(text) => setShareCodeInput(text.toUpperCase())}
              autoCapitalize="characters"
              autoCorrect={false}
              keyboardType="default"
              maxLength={12}
            />
            {joinByCodeError && joinModalVisible ? (
              <Text style={styles.modalError}>{joinByCodeError}</Text>
            ) : null}
          </View>
        }
      />
    </View>
  );
}

type ChallengeCardProps = {
  challenge: ChallengeCardViewModel;
  surfaceColor: string;
  textColor: string;
  mutedColor: string;
  onPress: () => void;
};

function ChallengeCard({ challenge, surfaceColor, textColor, mutedColor, onPress }: ChallengeCardProps) {
  const { t } = useI18n();
  const statusLabel = t(`challenges.statusLabels.${challenge.status}`) ?? challenge.status;

  return (
    <TouchableOpacity
      activeOpacity={0.92}
      onPress={onPress}
      style={[
        styles.card,
        {
          backgroundColor: surfaceColor,
          shadowColor: 'rgba(15, 23, 42, 0.18)',
        },
      ]}
    >
      <View style={styles.cardInner}>
        <View style={styles.cardMedia}>
          <Image
            source={{ uri: challenge.image }}
            style={styles.cardImage}
            cachePolicy={'memory-disk'}
          />

          <>
            <LinearGradient
              pointerEvents="none"
              colors={['rgba(17, 21, 32, 0.05)', 'rgba(13, 17, 28, 0.4)']}
              style={styles.cardImageOverlay}
            />
            <View style={styles.expiredBadge}>
              <Text style={styles.expiredBadgeText}>{statusLabel}</Text>
            </View>
          </>
        </View>

        <View style={styles.cardContent}>
          <Text
            style={[styles.cardTitle, { color: textColor }]}
            numberOfLines={1}
          >
            {challenge.title}
          </Text>
          <Text
            style={[styles.cardDate, { color: mutedColor }]}
          >
            {challenge.dateRange}
          </Text>
          <Text
            style={[styles.cardParticipants, { color: mutedColor }]}
          >
            {challenge.participantsLabel}
            {challenge.isJoined ? ` · ${t('challenges.joined')}` : ''}
          </Text>
          {challenge.avatars.length ? (
            <AvatarStack avatars={challenge.avatars} borderColor={surfaceColor} />
          ) : null}
        </View>
      </View>

    </TouchableOpacity>
  );
}

type ThemeColorTokens = (typeof Colors)['light'] | (typeof Colors)['dark'];

type OngoingChallengesCarouselProps = {
  challenges: ChallengeCardViewModel[];
  colorTokens: ThemeColorTokens;
  trackColor: string;
  inactiveColor: string;
  onPress: (challenge: ChallengeCardViewModel) => void;
};

function OngoingChallengesCarousel({
  challenges,
  colorTokens,
  trackColor,
  inactiveColor,
  onPress,
}: OngoingChallengesCarouselProps) {
  const { width } = useWindowDimensions();
  const cardWidth = Math.max(width - 40, MIN_CAROUSEL_CARD_WIDTH);
  const snapInterval = cardWidth + CAROUSEL_ITEM_SPACING;
  const scrollX = useRef(new Animated.Value(0)).current;
  const listRef = useRef<FlatList<ChallengeCardViewModel> | null>(null);

  useEffect(() => {
    scrollX.setValue(0);
    listRef.current?.scrollToOffset({ offset: 0, animated: false });
  }, [scrollX, challenges.length]);

  const onScroll = useMemo(
    () =>
      Animated.event(
        [
          {
            nativeEvent: {
              contentOffset: { x: scrollX },
            },
          },
        ],
        { useNativeDriver: true }
      ),
    [scrollX]
  );

  const renderItem = useCallback(
    ({ item, index }: { item: ChallengeCardViewModel; index: number }) => {
      const inputRange = [
        (index - 1) * snapInterval,
        index * snapInterval,
        (index + 1) * snapInterval,
      ];
      const scale = scrollX.interpolate({
        inputRange,
        outputRange: [0.94, 1, 0.94],
        extrapolate: 'clamp',
      });
      const translateY = scrollX.interpolate({
        inputRange,
        outputRange: [10, 0, 10],
        extrapolate: 'clamp',
      });

      return (
        <Animated.View
          style={[
            styles.carouselCard,
            {
              width: cardWidth,
              transform: [{ scale }, { translateY }],
            },
          ]}
        >
          <TouchableOpacity
            activeOpacity={0.92}
            style={styles.carouselTouchable}
            onPress={() => onPress(item)}
          >
            <ChallengeProgressCard
              title={item.title}
              endAt={item.endAt as string}
              progress={item.progress}
              style={styles.carouselProgressCard}
              backgroundColors={[colorTokens.card, colorTokens.card]}
              titleColor={colorTokens.text}
              subtitleColor={colorTokens.textSecondary}
              metaColor={colorTokens.primary}
              metaSuffixColor={colorTokens.textSecondary}
              accentColor={colorTokens.primary}
              trackColor={trackColor}
              inactiveColor={inactiveColor}
            />
          </TouchableOpacity>
        </Animated.View>
      );
    },
    [cardWidth, colorTokens, inactiveColor, onPress, scrollX, snapInterval, trackColor]
  );

  return (
    <View style={styles.carouselContainer}>
      <Animated.FlatList
        ref={listRef}
        data={challenges}
        keyExtractor={(item) => item.id}
        horizontal
        showsHorizontalScrollIndicator={false}
        bounces
        decelerationRate="fast"
        snapToAlignment="start"
        snapToInterval={snapInterval}

        ItemSeparatorComponent={() => <View style={{ width: CAROUSEL_ITEM_SPACING }} />}
        onScroll={onScroll}
        scrollEventThrottle={16}
        overScrollMode="never"
        renderItem={renderItem}
      />

      {challenges.length > 1 ? (
        <View style={styles.carouselIndicators}>
          {challenges.map((challenge, index) => {
            const inputRange = [
              (index - 1) * snapInterval,
              index * snapInterval,
              (index + 1) * snapInterval,
            ];
            const scaleX = scrollX.interpolate({
              inputRange,
              outputRange: [1, 2.6, 1],
              extrapolate: 'clamp',
            });
            const dotOpacity = scrollX.interpolate({
              inputRange,
              outputRange: [0.35, 1, 0.35],
              extrapolate: 'clamp',
            });

            return (
              <Animated.View
                key={challenge.id}
                style={[
                  styles.carouselDot,
                  {
                    opacity: dotOpacity,
                    backgroundColor: colorTokens.primary,
                    transform: [{ scaleX }],
                  },
                ]}
              />
            );
          })}
        </View>
      ) : null}
    </View>
  );
}

type AvatarStackProps = {
  avatars: string[];
  borderColor: string;
};

function AvatarStack({ avatars, borderColor }: AvatarStackProps) {
  return (
    <View style={styles.avatarRow}>
      {avatars
        .filter(Boolean)
        .map((avatar, index) => (
          <Image
            key={`${avatar}-${index}`}
            source={{ uri: avatar }}
            style={[
              styles.avatar,
              { borderColor },
              index === 0 ? null : styles.avatarOffset,
            ]}
          />
        ))}
    </View>
  );
}

const styles = StyleSheet.create({
  screen: {
    flex: 1,
  },
  safeArea: {
    flex: 1,
  },
  scrollContent: {
    paddingHorizontal: 20,
    paddingBottom: 120,
  },
  headerRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginTop: 8,
    marginBottom: 26,
  },
  title: {
    fontSize: 24,
    fontWeight: '700',
    letterSpacing: 1,
    fontFamily: 'AliBold'
  },
  subtitle: {
    marginTop: 6,
    fontSize: 12,
    fontWeight: '500',
    opacity: 0.8,
    fontFamily: 'AliRegular'
  },
  headerActions: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  joinButtonGlass: {
    paddingHorizontal: 14,
    paddingVertical: 8,
    borderRadius: 16,
    minWidth: 70,
    alignItems: 'center',
    justifyContent: 'center',
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: 'rgba(255,255,255,0.45)',
  },
  joinButtonLabel: {
    fontSize: 12,
    fontWeight: '700',
    color: '#0f1528',
    letterSpacing: 0.5,
    fontFamily: 'AliBold'
  },
  joinButtonFallback: {
    backgroundColor: 'rgba(255,255,255,0.7)',
  },
  createButton: {
    width: 36,
    height: 36,
    borderRadius: 20,
    alignItems: 'center',
    justifyContent: 'center',
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: 'rgba(255,255,255,0.6)',
    backgroundColor: 'rgba(255,255,255,0.85)',
  },
  createButtonFallback: {
    backgroundColor: 'rgba(255,255,255,0.75)',
  },
  cardsContainer: {
    gap: 18,
  },
  cardGroups: {
    gap: 20,
  },
  sectionHeaderRow: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    marginBottom: 8,
  },
  sectionHeaderText: {
    fontSize: 16,
    fontWeight: '800',
  },
  customEmpty: {
    borderRadius: 18,
    backgroundColor: 'rgba(255,255,255,0.08)',
  },
  primaryGhostButton: {
    marginTop: 12,
    paddingHorizontal: 16,
    paddingVertical: 8,
    borderWidth: StyleSheet.hairlineWidth,
    borderRadius: 14,
  },
  carouselContainer: {
    marginBottom: 24,
  },
  carouselCard: {
    width: '100%',
  },
  carouselTouchable: {
    flex: 1,
  },
  carouselProgressCard: {
    width: '100%',
  },
  carouselIndicators: {
    marginTop: 18,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
  },
  carouselDot: {
    width: DOT_BASE_SIZE,
    height: DOT_BASE_SIZE,
    borderRadius: DOT_BASE_SIZE / 2,
    marginHorizontal: 4,
    backgroundColor: 'transparent',
  },
  stateContainer: {
    alignItems: 'center',
    justifyContent: 'center',
    paddingVertical: 40,
    paddingHorizontal: 20,
  },
  stateText: {
    marginTop: 12,
    fontSize: 14,
    textAlign: 'center',
    lineHeight: 20,
  },
  retryButton: {
    marginTop: 16,
    paddingHorizontal: 18,
    paddingVertical: 8,
    borderRadius: 18,
    borderWidth: StyleSheet.hairlineWidth,
  },
  retryText: {
    fontSize: 13,
    fontWeight: '600',
  },
  card: {
    borderRadius: 28,
    padding: 18,
    shadowOffset: { width: 0, height: 16 },
    shadowOpacity: 0.18,
    shadowRadius: 24,
    elevation: 6,
    position: 'relative',
    overflow: 'hidden',
  },
  cardInner: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  cardImage: {
    width: CARD_IMAGE_WIDTH,
    height: CARD_IMAGE_HEIGHT,
    borderRadius: 22,
  },
  cardMedia: {
    borderRadius: 22,
    overflow: 'hidden',
    position: 'relative',
  },
  cardContent: {
    flex: 1,
    marginLeft: 16,
  },
  cardTitle: {
    fontSize: 18,
    fontWeight: '700',
    marginBottom: 4,
    fontFamily: 'AliBold',
  },

  cardDate: {
    fontSize: 13,
    fontWeight: '500',
    marginBottom: 4,
    fontFamily: 'AliRegular',
  },
  cardParticipants: {
    fontSize: 13,
    fontWeight: '500',
    fontFamily: 'AliRegular'
  },
  cardExpired: {
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: 'rgba(148, 163, 184, 0.22)',
  },
  cardExpiredText: {
    opacity: 0.7,
  },
  cardDimOverlay: {
    ...StyleSheet.absoluteFillObject,
    borderRadius: 28,
  },
  cardImageOverlay: {
    ...StyleSheet.absoluteFillObject,
  },
  expiredBadge: {
    position: 'absolute',
    left: 12,
    bottom: 12,
    paddingHorizontal: 10,
    paddingVertical: 4,
    borderRadius: 12,
    backgroundColor: 'rgba(12, 16, 28, 0.45)',
  },
  expiredBadgeText: {
    fontSize: 12,
    fontWeight: '600',
    color: '#f7f9ff',
    letterSpacing: 0.3,
    fontFamily: 'AliRegular',
  },
  cardProgress: {
    marginTop: 8,
    fontSize: 13,
    fontWeight: '600',
  },
  avatarRow: {
    flexDirection: 'row',
    marginTop: 16,
    alignItems: 'center',
  },
  avatar: {
    width: AVATAR_SIZE,
    height: AVATAR_SIZE,
    borderRadius: AVATAR_SIZE / 2,
    borderWidth: 2,
  },
  avatarOffset: {
    marginLeft: -12,
  },
  modalInputWrapper: {
    borderRadius: 14,
    borderWidth: 1,
    borderColor: '#e5e7eb',
    backgroundColor: '#f8fafc',
    paddingHorizontal: 12,
    paddingVertical: 10,
    gap: 6,
  },
  modalInput: {
    paddingVertical: 12,
    fontSize: 16,
    fontWeight: '700',
    letterSpacing: 1.5,
    color: '#0f1528',
  },
  modalError: {
    marginTop: 10,
    fontSize: 12,
    color: '#ef4444',
  },
});
