+ {/* Top row: zone indicator + tariff info */}
+
+
+ {/* Animated zone dot */}
+
+
+
+
+
+ {isUnlimited ? t('dashboard.unlimited') : t(zone.labelKey)}
+
+
+
+
+ {subscription.is_trial
+ ? t('subscription.trialStatus')
+ : subscription.is_active
+ ? t('subscription.active')
+ : t('subscription.expired')}
+
+
+
+ {/* Tariff info line */}
+
+ {subscription.tariff_name && (
+ <>
+ {subscription.tariff_name}
+ ·
+ >
+ )}
+ {t('dashboard.validUntil', { date: formattedDate })}
+ ·
+
+ {subscription.device_limit} {t('subscription.devices')}
+
+
+
+ {/* Big percentage or infinity */}
+
+ {isUnlimited ? (
+ ∞
+ ) : (
+
+ {animatedPercent.toFixed(1)}
+ %
+
+ )}
+
+
+ {/* Traffic used line with refresh */}
+
+
+ {isUnlimited
+ ? `${usedGb.toFixed(1)} ${t('common.units.gb')}`
+ : `${usedGb.toFixed(1)} / ${subscription.traffic_limit_gb} ${t('common.units.gb')}`}
+
+
+
+
+ {/* Progress bar */}
+
0}
+ showThresholds={!isUnlimited}
+ />
+
+ {/* Connect device button */}
+ {subscription.subscription_url && (
+
+ navigate('/connection')}
+ containerClassName="w-full"
+ className="flex w-full items-center justify-center gap-3 py-3"
+ data-onboarding="connect-devices"
+ >
+
+ {t('dashboard.connectDevice')}
+
+
+ )}
+
+ {/* Bottom link */}
+
+
+ {t('dashboard.viewSubscription')} →
+
+
+
+ );
+}
diff --git a/src/components/dashboard/SubscriptionCardExpired.tsx b/src/components/dashboard/SubscriptionCardExpired.tsx
new file mode 100644
index 0000000..c5cdad7
--- /dev/null
+++ b/src/components/dashboard/SubscriptionCardExpired.tsx
@@ -0,0 +1,88 @@
+import { useTranslation } from 'react-i18next';
+import { Link } from 'react-router';
+import type { Subscription } from '../../types';
+
+interface SubscriptionCardExpiredProps {
+ subscription: Subscription;
+}
+
+const ClockIcon = () => (
+
+ {/* Header */}
+
+
+
+
+
+
+ {subscription.is_trial
+ ? t('dashboard.expired.trialTitle')
+ : t('dashboard.expired.title')}
+
+
+
{t('subscription.expired')}
+
+
+ {/* 3-column info */}
+
+
+
0
+
+ {t('dashboard.expired.traffic')}
+
+
+
+
0
+
+ {t('dashboard.expired.devices')}
+
+
+
+
{formattedDate}
+
+ {t('dashboard.expired.expiredDate')}
+
+
+
+
+ {/* Action buttons */}
+
+
+ {t('dashboard.expired.renew')}
+
+
+ {t('dashboard.expired.tariffs')}
+
+
+
+ );
+}
diff --git a/src/components/dashboard/TrialOfferCard.tsx b/src/components/dashboard/TrialOfferCard.tsx
new file mode 100644
index 0000000..519fc63
--- /dev/null
+++ b/src/components/dashboard/TrialOfferCard.tsx
@@ -0,0 +1,170 @@
+import { useTranslation } from 'react-i18next';
+import { Link } from 'react-router';
+import { UseMutationResult } from '@tanstack/react-query';
+import { HoverBorderGradient } from '../ui/hover-border-gradient';
+import type { TrialInfo } from '../../types';
+import { useCurrency } from '../../hooks/useCurrency';
+
+interface TrialOfferCardProps {
+ trialInfo: TrialInfo;
+ balanceKopeks: number;
+ balanceRubles: number;
+ activateTrialMutation: UseMutationResult