fix(theme): readable text on any operator palette + admin consistency pass

Контраст-аудит (WCAG-обход всех текстовых узлов, 4 палитры × юзер+админ
страницы) показал системные провалы читаемости: вторичный текст 1.5-2.5
на светлой/кастомных темах, статусные цвета 1.3-1.6, белый текст на
светлых акцентах 1.9.

Корневые фиксы:
- useThemeColors: контраст-кламп производных серых токенов — dark-400/
  champagne-600 (вторичный текст) держат >=5.0 к поверхности, dark-500/
  champagne-500 (подсказки) >=3.8; палитры с достаточным контрастом
  рендерятся байт-в-байт как раньше
- --color-on-accent/-success/-warning/-error: чёрный или белый текст
  по фактической яркости цвета оператора; text-white на accent-заливках
  заменён на text-on-accent (135 мест + variant примитива Button +
  .btn-primary)
- .light: статусные текстовые оттенки *-300/400 ремапятся на тёмные
  *-700 (жёлтая «Админка» 1.26 -> 3.8+, зелёные суммы 1.4 -> 3.4+,
  бейджи состояний)

Замер после: операторская тёмная палитра — 0 нарушений (всё >=4.5),
худшие точки остальных подняты с 1.26-1.6 до 3.2+.

Консистентность:
- заголовки админ-страниц приведены к text-xl font-bold text-dark-100
  (были 18/20/24/30px и 600/700 вперемешку)
- «Создать FAQ»: warning-500/80+белый -> warning-500+text-on-warning
- formatTraffic: единицы из i18n (убран микс «GB»/«ГБ» на одном экране)
- categoryCanvas -> categoryCANVAS в локалях (битый ключ на настройках)
- «Управление сквадами» -> «Управление локациями» (юзерский экран)
- мин-макс сумм на выборе метода: dark-600 -> dark-400
- неактивные пункты нижнего нава: dark-500 -> dark-400
This commit is contained in:
c0mrade
2026-06-11 15:49:17 +03:00
parent 47119c4c1f
commit 7f68e2cd5e
91 changed files with 287 additions and 176 deletions

View File

@@ -545,7 +545,7 @@ export default function AdminAuditLog() {
handleExport();
}}
disabled={exporting}
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600 disabled:opacity-50"
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600 disabled:opacity-50"
>
<DownloadIcon />
<span className="hidden sm:inline">
@@ -614,7 +614,7 @@ export default function AdminAuditLog() {
<span
className={`flex h-4 w-4 items-center justify-center rounded border text-xs ${
isSelected
? 'border-accent-500 bg-accent-500 text-white'
? 'border-accent-500 bg-accent-500 text-on-accent'
: 'border-dark-500 bg-dark-800'
}`}
>
@@ -734,7 +734,7 @@ export default function AdminAuditLog() {
<div className="mt-4 flex items-center gap-3">
<button
onClick={handleApplyFilters}
className="rounded-lg bg-accent-500 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-accent-600"
className="rounded-lg bg-accent-500 px-4 py-2 text-sm font-medium text-on-accent transition-colors hover:bg-accent-600"
>
{t('admin.auditLog.filters.apply')}
</button>

View File

@@ -702,7 +702,7 @@ export default function AdminBroadcastCreate() {
onClick={() => toggleButton(button.key)}
className={`rounded-lg px-3 py-2 text-sm transition-colors ${
selectedButtons.includes(button.key)
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'border border-dark-700 bg-dark-800 text-dark-300 hover:bg-dark-700'
}`}
>
@@ -770,7 +770,7 @@ export default function AdminBroadcastCreate() {
onClick={() => setNewButtonActionType('callback')}
className={`flex-1 rounded-lg px-3 py-2 text-sm transition-colors ${
newButtonActionType === 'callback'
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'border border-dark-700 bg-dark-800 text-dark-300 hover:bg-dark-700'
}`}
>
@@ -781,7 +781,7 @@ export default function AdminBroadcastCreate() {
onClick={() => setNewButtonActionType('url')}
className={`flex-1 rounded-lg px-3 py-2 text-sm transition-colors ${
newButtonActionType === 'url'
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'border border-dark-700 bg-dark-800 text-dark-300 hover:bg-dark-700'
}`}
>

View File

@@ -155,7 +155,7 @@ export default function AdminBroadcastDetail() {
<p className="text-dark-400">{t('admin.broadcasts.notFound')}</p>
<button
onClick={() => navigate('/admin/broadcasts')}
className="rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
{t('common.back')}
</button>

View File

@@ -117,7 +117,7 @@ export default function AdminBroadcasts() {
</button>
<button
onClick={() => navigate('/admin/broadcasts/create')}
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
<PlusIcon />
<span className="hidden sm:inline">{t('admin.broadcasts.create')}</span>

View File

@@ -79,7 +79,9 @@ function ServerSelector({
>
<div
className={`flex h-5 w-5 items-center justify-center rounded ${
selected.includes(server.squad_uuid) ? 'bg-accent-500 text-white' : 'bg-dark-600'
selected.includes(server.squad_uuid)
? 'bg-accent-500 text-on-accent'
: 'bg-dark-600'
}`}
>
{selected.includes(server.squad_uuid) && <CheckIcon />}

View File

@@ -79,7 +79,9 @@ function ServerSelector({
>
<div
className={`flex h-5 w-5 items-center justify-center rounded ${
selected.includes(server.squad_uuid) ? 'bg-accent-500 text-white' : 'bg-dark-600'
selected.includes(server.squad_uuid)
? 'bg-accent-500 text-on-accent'
: 'bg-dark-600'
}`}
>
{selected.includes(server.squad_uuid) && <CheckIcon />}

View File

@@ -136,7 +136,7 @@ export default function AdminCampaigns() {
</div>
<button
onClick={() => navigate('/admin/campaigns/create')}
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
<PlusIcon />
{t('admin.campaigns.createButton')}

View File

@@ -424,7 +424,7 @@ function AddChannelForm({
<button
onClick={handleSubmit}
disabled={!channelId.trim() || isLoading}
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-sm text-white transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-sm text-on-accent transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
>
<CheckIcon />
{t('admin.channelSubscriptions.form.submit')}
@@ -499,7 +499,7 @@ function EditChannelForm({
<button
onClick={handleSubmit}
disabled={isLoading}
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-sm text-white transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-sm text-on-accent transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
>
<CheckIcon />
{t('admin.channelSubscriptions.form.save')}
@@ -641,7 +641,7 @@ export default function AdminChannelSubscriptions() {
<button
onClick={() => setShowAddForm(true)}
aria-label={t('admin.channelSubscriptions.addChannel')}
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
<PlusIcon />
<span className="hidden sm:inline">{t('admin.channelSubscriptions.addChannel')}</span>

View File

@@ -442,7 +442,7 @@ function TemplateEditor({
<button
onClick={() => saveMutation.mutate()}
disabled={!isDirty || saveMutation.isPending}
className="inline-flex items-center justify-center gap-1.5 rounded-lg bg-accent-500 px-3 py-2.5 text-sm font-medium text-white transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-40 sm:px-4 sm:py-2"
className="inline-flex items-center justify-center gap-1.5 rounded-lg bg-accent-500 px-3 py-2.5 text-sm font-medium text-on-accent transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-40 sm:px-4 sm:py-2"
>
<SaveIcon className="h-4 w-4" />
{saveMutation.isPending ? t('common.loading') : t('common.save')}

View File

@@ -1027,7 +1027,7 @@ export default function AdminInfoPageEditor() {
<button
onClick={handleSave}
disabled={saveMutation.isPending || !slug.trim()}
className="min-h-[44px] rounded-lg bg-accent-500 px-6 py-2.5 text-sm font-medium text-white transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
className="min-h-[44px] rounded-lg bg-accent-500 px-6 py-2.5 text-sm font-medium text-on-accent transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
>
{saveMutation.isPending ? t('admin.infoPages.saving') : t('admin.infoPages.save')}
</button>
@@ -1108,7 +1108,7 @@ export default function AdminInfoPageEditor() {
className={cn(
'min-h-[44px] rounded-lg px-4 py-2.5 text-sm font-medium transition-colors',
displayMode === mode
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'bg-dark-700 text-dark-300 hover:bg-dark-600 hover:text-dark-100',
)}
>
@@ -1136,7 +1136,7 @@ export default function AdminInfoPageEditor() {
pageType === pt
? pt === 'faq'
? 'bg-warning-500 text-white'
: 'bg-accent-500 text-white'
: 'bg-accent-500 text-on-accent'
: 'bg-dark-700 text-dark-300 hover:bg-dark-600 hover:text-dark-100',
)}
>
@@ -1194,7 +1194,7 @@ export default function AdminInfoPageEditor() {
className={cn(
'min-h-[44px] rounded-lg px-4 py-2.5 text-sm font-medium transition-colors',
activeLocale === loc
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'bg-dark-700 text-dark-300 hover:bg-dark-600 hover:text-dark-100',
)}
>
@@ -1415,7 +1415,7 @@ export default function AdminInfoPageEditor() {
<button
onClick={handleSave}
disabled={saveMutation.isPending || !slug.trim()}
className="min-h-[44px] w-full rounded-lg bg-accent-500 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
className="min-h-[44px] w-full rounded-lg bg-accent-500 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
>
{saveMutation.isPending ? t('admin.infoPages.saving') : t('admin.infoPages.save')}
</button>

View File

@@ -238,7 +238,7 @@ export default function AdminInfoPages() {
haptic.buttonPress();
navigate('/admin/info-pages/create?type=faq');
}}
className="flex min-h-[44px] items-center gap-2 rounded-lg bg-warning-500/80 px-4 py-2.5 text-white transition-colors hover:bg-warning-500"
className="flex min-h-[44px] items-center gap-2 rounded-lg bg-warning-500 px-4 py-2.5 text-on-warning transition-colors hover:bg-warning-400"
aria-label={t('admin.infoPages.createFaq')}
>
<PlusIcon />
@@ -249,7 +249,7 @@ export default function AdminInfoPages() {
haptic.buttonPress();
navigate('/admin/info-pages/create');
}}
className="flex min-h-[44px] items-center gap-2 rounded-lg bg-accent-500 px-4 py-2.5 text-white transition-colors hover:bg-accent-600"
className="flex min-h-[44px] items-center gap-2 rounded-lg bg-accent-500 px-4 py-2.5 text-on-accent transition-colors hover:bg-accent-600"
aria-label={t('admin.infoPages.create')}
>
<PlusIcon />
@@ -268,7 +268,7 @@ export default function AdminInfoPages() {
className={cn(
'min-h-[44px] rounded-lg px-4 py-2.5 text-sm font-medium transition-colors',
activeFilter === tab
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'bg-dark-700 text-dark-300 hover:bg-dark-600 hover:text-dark-100',
)}
>

View File

@@ -588,7 +588,7 @@ export default function AdminLandingEditor() {
<button
onClick={handleSubmit}
disabled={isPending || !slug || !Object.values(title).some((v) => v.trim())}
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-sm text-white transition-colors hover:bg-accent-600 disabled:opacity-50"
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-sm text-on-accent transition-colors hover:bg-accent-600 disabled:opacity-50"
>
{isPending && (
<div className="h-4 w-4 animate-spin rounded-full border-2 border-white/30 border-t-white" />

View File

@@ -423,7 +423,7 @@ export default function AdminLandings() {
)}
<button
onClick={() => navigate('/admin/landings/create')}
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
<PlusIcon />
{t('admin.landings.create')}

View File

@@ -49,7 +49,7 @@ function DisplayModeSelector({
className={cn(
'min-h-[44px] rounded-lg px-4 py-2.5 text-sm font-medium transition-colors',
value === mode
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'bg-dark-700 text-dark-300 hover:bg-dark-600 hover:text-dark-100',
disabled && 'cursor-not-allowed opacity-50',
)}
@@ -87,7 +87,7 @@ function LanguageTabs({
className={cn(
'min-h-[44px] rounded-lg px-4 py-2.5 text-sm font-medium uppercase transition-colors',
active === lang
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'bg-dark-700 text-dark-300 hover:bg-dark-600 hover:text-dark-100',
)}
>
@@ -221,7 +221,7 @@ function DocumentEditor({
<button
onClick={() => saveMutation.mutate()}
disabled={saveMutation.isPending}
className="min-h-[44px] rounded-lg bg-accent-500 px-6 py-2.5 text-sm font-medium text-white transition-colors hover:bg-accent-600 disabled:opacity-50"
className="min-h-[44px] rounded-lg bg-accent-500 px-6 py-2.5 text-sm font-medium text-on-accent transition-colors hover:bg-accent-600 disabled:opacity-50"
>
{saveMutation.isPending ? t('admin.legalPages.saving') : t('admin.legalPages.save')}
</button>
@@ -321,7 +321,7 @@ function RulesEditor({ onDirtyChange }: { onDirtyChange: (dirty: boolean) => voi
<button
onClick={() => saveMutation.mutate()}
disabled={saveMutation.isPending}
className="min-h-[44px] rounded-lg bg-accent-500 px-6 py-2.5 text-sm font-medium text-white transition-colors hover:bg-accent-600 disabled:opacity-50"
className="min-h-[44px] rounded-lg bg-accent-500 px-6 py-2.5 text-sm font-medium text-on-accent transition-colors hover:bg-accent-600 disabled:opacity-50"
>
{saveMutation.isPending ? t('admin.legalPages.saving') : t('admin.legalPages.save')}
</button>
@@ -604,7 +604,7 @@ function FaqEditor({ onDirtyChange }: { onDirtyChange: (dirty: boolean) => void
<button
onClick={() => createMutation.mutate()}
disabled={createMutation.isPending}
className="flex min-h-[44px] items-center gap-2 rounded-lg bg-accent-500 px-4 py-2.5 text-sm font-medium text-white transition-colors hover:bg-accent-600 disabled:opacity-50"
className="flex min-h-[44px] items-center gap-2 rounded-lg bg-accent-500 px-4 py-2.5 text-sm font-medium text-on-accent transition-colors hover:bg-accent-600 disabled:opacity-50"
>
<PlusIcon />
<span className="hidden sm:inline">{t('admin.legalPages.addQuestion')}</span>
@@ -669,7 +669,7 @@ export default function AdminLegalPages() {
className={cn(
'min-h-[44px] rounded-lg px-4 py-2.5 text-sm font-medium transition-colors',
activeTab === tab
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'bg-dark-700 text-dark-300 hover:bg-dark-600 hover:text-dark-100',
)}
>

View File

@@ -273,7 +273,7 @@ export default function AdminNews() {
haptic.buttonPress();
navigate('/admin/news/create');
}}
className="flex min-h-[44px] items-center gap-2 rounded-lg bg-accent-500 px-4 py-2.5 text-white transition-colors hover:bg-accent-600"
className="flex min-h-[44px] items-center gap-2 rounded-lg bg-accent-500 px-4 py-2.5 text-on-accent transition-colors hover:bg-accent-600"
aria-label={t('news.admin.create')}
>
<PlusIcon />

View File

@@ -558,7 +558,7 @@ export default function AdminNewsCreate() {
<button
onClick={handleSave}
disabled={saveMutation.isPending || !title.trim() || !slug.trim() || !selectedCategory}
className="min-h-[44px] rounded-lg bg-accent-500 px-6 py-2.5 text-sm font-medium text-white transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
className="min-h-[44px] rounded-lg bg-accent-500 px-6 py-2.5 text-sm font-medium text-on-accent transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
>
{saveMutation.isPending ? t('news.admin.saving') : t('news.admin.save')}
</button>
@@ -912,7 +912,7 @@ export default function AdminNewsCreate() {
<button
onClick={handleSave}
disabled={saveMutation.isPending || !title.trim() || !slug.trim() || !selectedCategory}
className="min-h-[44px] w-full rounded-lg bg-accent-500 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
className="min-h-[44px] w-full rounded-lg bg-accent-500 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
>
{saveMutation.isPending ? t('news.admin.saving') : t('news.admin.save')}
</button>

View File

@@ -68,7 +68,7 @@ export default function AdminPartnerCampaignAssign() {
</div>
<button
onClick={() => navigate(`/admin/campaigns/create?partnerId=${userId}`)}
className="mt-2 w-full rounded-lg bg-accent-500 px-4 py-3 font-medium text-white transition-colors hover:bg-accent-600"
className="mt-2 w-full rounded-lg bg-accent-500 px-4 py-3 font-medium text-on-accent transition-colors hover:bg-accent-600"
>
{t('admin.partnerDetail.campaigns.createNew')}
</button>

View File

@@ -90,7 +90,7 @@ export default function AdminPartnerCommission() {
Number(commissionValue) < 1 ||
Number(commissionValue) > 100
}
className="flex-1 rounded-lg bg-accent-500 px-4 py-3 font-medium text-white transition-colors hover:bg-accent-600 disabled:opacity-50"
className="flex-1 rounded-lg bg-accent-500 px-4 py-3 font-medium text-on-accent transition-colors hover:bg-accent-600 disabled:opacity-50"
>
{updateMutation.isPending ? t('common.saving') : t('common.save')}
</button>

View File

@@ -301,7 +301,9 @@ export default function AdminPaymentMethodEdit() {
<span className="text-sm">{opt.name}</span>
<div
className={`flex h-5 w-5 items-center justify-center rounded ${
enabled ? 'bg-accent-500 text-white' : 'border border-dark-600 bg-dark-700'
enabled
? 'bg-accent-500 text-on-accent'
: 'border border-dark-600 bg-dark-700'
}`}
>
{enabled && <CheckIcon />}
@@ -493,7 +495,7 @@ export default function AdminPaymentMethodEdit() {
<span>{group.name}</span>
<div
className={`flex h-4 w-4 items-center justify-center rounded ${
selected ? 'bg-accent-500 text-white' : 'border border-dark-600'
selected ? 'bg-accent-500 text-on-accent' : 'border border-dark-600'
}`}
>
{selected && <CheckIcon />}

View File

@@ -218,7 +218,7 @@ export default function AdminPaymentMethods() {
</button>
)}
<div>
<h1 className="text-2xl font-bold text-dark-50">{t('admin.paymentMethods.title')}</h1>
<h1 className="text-xl font-bold text-dark-100">{t('admin.paymentMethods.title')}</h1>
<p className="text-sm text-dark-400">{t('admin.paymentMethods.description')}</p>
</div>
</div>

View File

@@ -184,7 +184,7 @@ export default function AdminPayments() {
</button>
)}
<div>
<h1 className="text-xl font-semibold text-dark-100">{t('admin.payments.title')}</h1>
<h1 className="text-xl font-bold text-dark-100">{t('admin.payments.title')}</h1>
<p className="text-sm text-dark-400">{t('admin.payments.description')}</p>
</div>
</div>
@@ -239,7 +239,7 @@ export default function AdminPayments() {
onClick={() => setStatusFilter(option.value)}
className={`rounded-lg px-3 py-1.5 text-sm transition-all ${
statusFilter === option.value
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'bg-dark-800 text-dark-300 hover:bg-dark-700'
}`}
>
@@ -256,7 +256,7 @@ export default function AdminPayments() {
onClick={() => handlePeriodChange(option.value)}
className={`rounded-lg px-3 py-1.5 text-sm transition-all ${
periodFilter === option.value
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'bg-dark-800 text-dark-300 hover:bg-dark-700'
}`}
>
@@ -267,7 +267,7 @@ export default function AdminPayments() {
onClick={() => handlePeriodChange('custom')}
className={`flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm transition-all ${
periodFilter === 'custom'
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'bg-dark-800 text-dark-300 hover:bg-dark-700'
}`}
>

View File

@@ -269,7 +269,7 @@ export default function AdminPinnedMessages() {
</button>
<button
onClick={() => navigate('/admin/pinned-messages/create')}
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="flex items-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
<PlusIcon />
<span className="hidden sm:inline">{t('admin.pinnedMessages.create')}</span>

View File

@@ -228,7 +228,7 @@ export default function AdminPolicies() {
<PermissionGate permission="roles:create">
<button
onClick={() => navigate('/admin/policies/create')}
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
<PlusIcon />
{t('admin.policies.createPolicy')}

View File

@@ -757,7 +757,7 @@ export default function AdminPolicyEdit() {
<button
type="submit"
disabled={isSaving}
className="rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600 disabled:opacity-50"
className="rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600 disabled:opacity-50"
>
{isSaving ? t('admin.policies.form.saving') : t('admin.policies.form.save')}
</button>

View File

@@ -65,7 +65,7 @@ export default function AdminPromoGroups() {
</div>
<button
onClick={() => navigate('/admin/promo-groups/create')}
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
<PlusIcon />
{t('admin.promoGroups.addGroup')}

View File

@@ -199,7 +199,7 @@ export default function AdminPromoOfferSend() {
<div className="flex justify-center gap-3">
<button
onClick={() => navigate('/admin/promo-offers')}
className="rounded-lg bg-accent-500 px-6 py-2 text-white transition-colors hover:bg-accent-600"
className="rounded-lg bg-accent-500 px-6 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
{t('admin.promoOffers.backToList')}
</button>
@@ -441,7 +441,7 @@ export default function AdminPromoOfferSend() {
{selectedTemplate.message_text}
</div>
<div className="mt-4">
<span className="inline-block rounded-lg bg-accent-500 px-4 py-2 text-sm text-white">
<span className="inline-block rounded-lg bg-accent-500 px-4 py-2 text-sm text-on-accent">
{selectedTemplate.button_text}
</span>
</div>

View File

@@ -93,7 +93,7 @@ export default function AdminPromoOffers() {
</div>
<button
onClick={() => navigate('/admin/promo-offers/send')}
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
<SendIcon />
{t('admin.promoOffers.sendButton')}

View File

@@ -124,7 +124,7 @@ export default function AdminPromocodeStats() {
</div>
<button
onClick={() => navigate(`/admin/promocodes/${id}/edit`)}
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
<EditIcon />
{t('admin.promocodes.modal.edit')}

View File

@@ -102,13 +102,13 @@ export default function AdminPromocodes() {
</button>
)}
<div>
<h1 className="text-xl font-semibold text-dark-100">{t('admin.promocodes.title')}</h1>
<h1 className="text-xl font-bold text-dark-100">{t('admin.promocodes.title')}</h1>
<p className="text-sm text-dark-400">{t('admin.promocodes.subtitle')}</p>
</div>
</div>
<button
onClick={() => navigate('/admin/promocodes/create')}
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
<PlusIcon />
{t('admin.promocodes.addPromocode')}

View File

@@ -432,7 +432,7 @@ export default function AdminRoleAssign() {
<button
type="submit"
disabled={assignMutation.isPending || !selectedUser || !selectedRoleId}
className="flex items-center gap-2 rounded-lg bg-accent-500 px-5 py-2 text-white transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
className="flex items-center gap-2 rounded-lg bg-accent-500 px-5 py-2 text-on-accent transition-colors hover:bg-accent-600 disabled:cursor-not-allowed disabled:opacity-50"
>
{assignMutation.isPending
? t('admin.roleAssign.assigning')

View File

@@ -514,7 +514,7 @@ export default function AdminRoleEdit() {
<button
type="submit"
disabled={isSaving}
className="rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600 disabled:opacity-50"
className="rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600 disabled:opacity-50"
>
{isSaving ? t('admin.roles.form.saving') : t('admin.roles.form.save')}
</button>

View File

@@ -81,7 +81,7 @@ export default function AdminRoles() {
<PermissionGate permission="roles:create">
<button
onClick={() => navigate('/admin/roles/create')}
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
<PlusIcon />
{t('admin.roles.createRole')}

View File

@@ -76,7 +76,7 @@ export default function AdminServers() {
<button
onClick={() => syncMutation.mutate()}
disabled={syncMutation.isPending}
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600 disabled:opacity-50"
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600 disabled:opacity-50"
>
<SyncIcon />
{syncMutation.isPending ? t('admin.servers.syncing') : t('admin.servers.sync')}

View File

@@ -248,7 +248,7 @@ export default function AdminSettings() {
<BackIcon />
</button>
)}
<h1 className="text-lg font-bold text-dark-100">{t('admin.settings.title')}</h1>
<h1 className="text-xl font-bold text-dark-100">{t('admin.settings.title')}</h1>
</div>
</div>
<SettingsTreeSidebar

View File

@@ -661,7 +661,7 @@ export default function AdminTariffCreate() {
!selectedExternalSquad
? isDaily
? 'bg-warning-500 text-white'
: 'bg-accent-500 text-white'
: 'bg-accent-500 text-on-accent'
: 'bg-dark-600'
}`}
>
@@ -691,7 +691,7 @@ export default function AdminTariffCreate() {
isSelected
? isDaily
? 'bg-warning-500 text-white'
: 'bg-accent-500 text-white'
: 'bg-accent-500 text-on-accent'
: 'bg-dark-600'
}`}
>
@@ -740,7 +740,7 @@ export default function AdminTariffCreate() {
isSelected
? isDaily
? 'bg-warning-500 text-white'
: 'bg-accent-500 text-white'
: 'bg-accent-500 text-on-accent'
: 'bg-dark-600'
}`}
>
@@ -1055,7 +1055,7 @@ export default function AdminTariffCreate() {
isSelected
? isDaily
? 'bg-warning-500 text-white'
: 'bg-accent-500 text-white'
: 'bg-accent-500 text-on-accent'
: 'bg-dark-600'
}`}
>

View File

@@ -307,7 +307,7 @@ export default function AdminTariffs() {
</button>
)}
<div>
<h1 className="text-xl font-semibold text-dark-100">{t('admin.tariffs.title')}</h1>
<h1 className="text-xl font-bold text-dark-100">{t('admin.tariffs.title')}</h1>
<p className="text-sm text-dark-400">{t('admin.tariffs.subtitle')}</p>
</div>
</div>
@@ -328,7 +328,7 @@ export default function AdminTariffs() {
)}
<button
onClick={() => navigate('/admin/tariffs/create')}
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="flex items-center justify-center gap-2 rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
<PlusIcon />
{t('admin.tariffs.create')}

View File

@@ -272,9 +272,7 @@ export default function AdminTickets() {
<BackIcon />
</button>
)}
<h1 className="text-2xl font-bold text-dark-50 sm:text-3xl">
{t('admin.tickets.title')}
</h1>
<h1 className="text-xl font-bold text-dark-100">{t('admin.tickets.title')}</h1>
</div>
<button
onClick={() => navigate('/admin/tickets/settings')}

View File

@@ -740,7 +740,7 @@ export default function AdminUserDetail() {
<p className="text-dark-400">{t('admin.users.notFound')}</p>
<button
onClick={() => navigate('/admin/users')}
className="rounded-lg bg-accent-500 px-4 py-2 text-white transition-colors hover:bg-accent-600"
className="rounded-lg bg-accent-500 px-4 py-2 text-on-accent transition-colors hover:bg-accent-600"
>
{t('common.back')}
</button>

View File

@@ -364,7 +364,7 @@ export default function AdminWithdrawalDetail() {
<button
onClick={() => completeMutation.mutate()}
disabled={completeMutation.isPending}
className="w-full rounded-lg bg-accent-500 px-4 py-3 font-medium text-white transition-colors hover:bg-accent-600 disabled:opacity-50"
className="w-full rounded-lg bg-accent-500 px-4 py-3 font-medium text-on-accent transition-colors hover:bg-accent-600 disabled:opacity-50"
>
{completeMutation.isPending
? t('admin.withdrawals.detail.completing')

View File

@@ -81,7 +81,7 @@ export default function AdminWithdrawals() {
onClick={() => setStatusFilter(filter)}
className={`whitespace-nowrap rounded-lg px-4 py-2 text-sm font-medium transition-colors ${
statusFilter === filter
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'bg-dark-800/40 text-dark-400 hover:bg-dark-700/50 hover:text-dark-200'
}`}
>

View File

@@ -58,7 +58,7 @@ export default function AutoLogin() {
<button
type="button"
onClick={() => navigate('/login', { replace: true })}
className="rounded-xl bg-accent-500 px-6 py-2.5 text-sm font-medium text-white transition-colors hover:bg-accent-400"
className="rounded-xl bg-accent-500 px-6 py-2.5 text-sm font-medium text-on-accent transition-colors hover:bg-accent-400"
>
{t('auth.login', 'Login')}
</button>

View File

@@ -340,7 +340,7 @@ export default function Balance() {
{translatedDesc || method.description}
</div>
)}
<div className="mt-3 text-xs text-dark-600">
<div className="mt-3 text-xs text-dark-400">
{formatAmount(method.min_amount_kopeks / 100, 0)} {t('common.rangeTo', 'to')}{' '}
{formatAmount(method.max_amount_kopeks / 100, 0)} {currencySymbol}
</div>

View File

@@ -318,7 +318,7 @@ export default function Dashboard() {
) : (
<Link
to="/subscription/purchase"
className="flex w-full items-center justify-center gap-2 rounded-2xl bg-accent-500 p-3.5 text-sm font-semibold text-white transition-colors hover:bg-accent-600"
className="flex w-full items-center justify-center gap-2 rounded-2xl bg-accent-500 p-3.5 text-sm font-semibold text-on-accent transition-colors hover:bg-accent-600"
>
<span className="text-base">+</span>{' '}
{t('subscriptions.browsePlans', 'Посмотреть тарифы и купить подписку')}
@@ -381,7 +381,7 @@ export default function Dashboard() {
)}
<Link
to="/subscription/purchase"
className="flex w-full items-center justify-center gap-2 rounded-2xl bg-accent-500 p-3.5 text-sm font-semibold text-white transition-colors hover:bg-accent-600"
className="flex w-full items-center justify-center gap-2 rounded-2xl bg-accent-500 p-3.5 text-sm font-semibold text-on-accent transition-colors hover:bg-accent-600"
>
<span className="text-base">+</span>{' '}
{t('subscriptions.browsePlans', 'Посмотреть тарифы и купить подписку')}

View File

@@ -189,7 +189,7 @@ export default function GiftClaim() {
'flex w-full items-center justify-center gap-2 rounded-xl px-4 py-3 text-sm font-bold transition-all active:scale-[0.98]',
copied
? 'bg-success-500/20 text-success-400'
: 'bg-accent-500 text-white hover:bg-accent-400',
: 'bg-accent-500 text-on-accent hover:bg-accent-400',
)}
>
{copied ? <CheckIcon className="h-4 w-4" /> : <CopyIcon className="h-4 w-4" />}
@@ -264,7 +264,7 @@ export default function GiftClaim() {
{gift.bot_claim_link && (
<a
href={gift.bot_claim_link}
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-6 py-3.5 text-sm font-bold text-white shadow-lg shadow-accent-500/25 transition-all hover:bg-accent-400 active:scale-[0.98]"
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-6 py-3.5 text-sm font-bold text-on-accent shadow-lg shadow-accent-500/25 transition-all hover:bg-accent-400 active:scale-[0.98]"
>
{t('landing.giftClaim.activateTelegram', 'Activate in Telegram')}
</a>
@@ -303,7 +303,7 @@ export default function GiftClaim() {
className={cn(
'flex w-full items-center justify-center gap-2 rounded-xl px-6 py-3.5 text-sm font-bold transition-all',
isValidEmail(email) && !claimMutation.isPending
? 'bg-accent-500 text-white hover:bg-accent-400 active:scale-[0.98]'
? 'bg-accent-500 text-on-accent hover:bg-accent-400 active:scale-[0.98]'
: 'cursor-not-allowed bg-dark-800 text-dark-500',
)}
>

View File

@@ -156,7 +156,7 @@ function CodeOnlySuccessState({
'flex w-full items-center justify-center gap-2 rounded-xl px-4 py-3.5 text-sm font-bold transition-all duration-200 active:scale-[0.98]',
copied
? 'bg-success-500/20 text-success-400'
: 'bg-accent-500 text-white shadow-lg shadow-accent-500/25 hover:bg-accent-400',
: 'bg-accent-500 text-on-accent shadow-lg shadow-accent-500/25 hover:bg-accent-400',
)}
>
{copied ? (
@@ -236,7 +236,7 @@ function DeliveredState({
<button
type="button"
onClick={() => navigate('/')}
className="flex w-full items-center justify-center rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-400"
className="flex w-full items-center justify-center rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-400"
>
{t('gift.backToDashboard', 'Back to dashboard')}
</button>
@@ -303,7 +303,7 @@ function PendingActivationState({
<button
type="button"
onClick={() => navigate('/')}
className="flex w-full items-center justify-center rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-400"
className="flex w-full items-center justify-center rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-400"
>
{t('gift.backToDashboard', 'Back to dashboard')}
</button>
@@ -335,7 +335,7 @@ function FailedState() {
<button
type="button"
onClick={() => navigate('/gift')}
className="flex w-full items-center justify-center rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-400"
className="flex w-full items-center justify-center rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-400"
>
{t('gift.tryAgain', 'Try again')}
</button>
@@ -372,7 +372,7 @@ function PollErrorState() {
<button
type="button"
onClick={() => navigate('/')}
className="flex w-full items-center justify-center rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-400"
className="flex w-full items-center justify-center rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-400"
>
{t('gift.backToDashboard', 'Back to dashboard')}
</button>
@@ -406,7 +406,7 @@ function PollTimedOutState({ onRetry }: { onRetry: () => void }) {
<button
type="button"
onClick={onRetry}
className="rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-400"
className="rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-400"
>
{t('gift.retry', 'Retry')}
</button>
@@ -436,7 +436,7 @@ function NoTokenState() {
<button
type="button"
onClick={() => navigate('/gift')}
className="rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-400"
className="rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-400"
>
{t('gift.backToGift', 'Go back')}
</button>

View File

@@ -231,7 +231,7 @@ function PeriodCard({
<span
className={cn(
'rounded-md px-2 py-0.5 text-xs font-bold',
isSelected ? 'bg-white/20 text-white' : 'bg-accent-500/20 text-accent-400',
isSelected ? 'bg-white/20 text-on-accent' : 'bg-accent-500/20 text-accent-400',
)}
>
-{period.discount_percent}%
@@ -366,7 +366,7 @@ function PaymentMethodCard({
className={cn(
'rounded-xl px-4 py-2 text-sm font-medium transition-all duration-200',
selectedSubOption === opt.id
? 'bg-accent-500 text-white shadow-sm shadow-accent-500/25'
? 'bg-accent-500 text-on-accent shadow-sm shadow-accent-500/25'
: 'bg-dark-800/50 text-dark-300 hover:bg-dark-700/50',
)}
>
@@ -716,7 +716,7 @@ function BuyTabContent({
className={cn(
'flex w-full items-center justify-center gap-2 rounded-2xl px-6 py-4 text-base font-semibold transition-all duration-200',
canSubmit && !purchaseMutation.isPending
? 'bg-accent-500 text-white shadow-lg shadow-accent-500/25 hover:bg-accent-400 hover:shadow-accent-500/40 active:scale-[0.98]'
? 'bg-accent-500 text-on-accent shadow-lg shadow-accent-500/25 hover:bg-accent-400 hover:shadow-accent-500/40 active:scale-[0.98]'
: 'cursor-not-allowed bg-dark-800 text-dark-500',
)}
>
@@ -833,7 +833,7 @@ function ActivateTabContent({ initialCode }: { initialCode?: string | null }) {
className={cn(
'w-full max-w-sm rounded-2xl px-6 py-4 text-base font-semibold transition-all duration-200',
code.trim() && !activateMutation.isPending
? 'bg-accent-500 text-white shadow-lg shadow-accent-500/25 hover:bg-accent-400 active:scale-[0.98]'
? 'bg-accent-500 text-on-accent shadow-lg shadow-accent-500/25 hover:bg-accent-400 active:scale-[0.98]'
: 'cursor-not-allowed bg-dark-800 text-dark-500',
)}
>
@@ -962,7 +962,7 @@ function SentGiftCard({ gift }: { gift: SentGift }) {
<button
type="button"
onClick={handleShare}
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-4 py-3 text-sm font-bold uppercase tracking-wider text-white transition-colors hover:bg-accent-400 active:scale-[0.98]"
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-4 py-3 text-sm font-bold uppercase tracking-wider text-on-accent transition-colors hover:bg-accent-400 active:scale-[0.98]"
>
<ExportIcon className="h-4 w-4" />
{t('gift.shareGift')}
@@ -1243,7 +1243,7 @@ export default function GiftSubscription() {
className={cn(
'flex-1 rounded-xl px-3 py-2.5 text-sm font-medium transition-all duration-200',
activeTab === tab.id
? 'bg-accent-500 text-white shadow-sm'
? 'bg-accent-500 text-on-accent shadow-sm'
: 'text-dark-400 hover:text-dark-200',
)}
>

View File

@@ -838,7 +838,7 @@ export default function Info() {
onClick={() => setActiveTab(tab.id)}
className={`flex min-h-[44px] shrink-0 items-center gap-2 rounded-lg px-4 py-2.5 text-sm font-medium transition-colors ${
activeTab === tab.id
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'bg-dark-800 text-dark-300 hover:bg-dark-700'
}`}
>

View File

@@ -583,7 +583,7 @@ export default function Login() {
type="button"
className={`flex-1 rounded-md py-2 text-sm font-medium transition-all ${
authMode === 'login'
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'text-dark-400 hover:text-dark-200'
}`}
onClick={() => setAuthMode('login')}
@@ -594,7 +594,7 @@ export default function Login() {
type="button"
className={`flex-1 rounded-md py-2 text-sm font-medium transition-all ${
authMode === 'register'
? 'bg-accent-500 text-white'
? 'bg-accent-500 text-on-accent'
: 'text-dark-400 hover:text-dark-200'
}`}
onClick={() => setAuthMode('register')}

View File

@@ -268,7 +268,7 @@ function SuccessState({
href={botLink}
target="_blank"
rel="noopener noreferrer"
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-400"
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-400"
>
{t('landing.openBot')}
</a>
@@ -492,7 +492,7 @@ function GiftPendingActivationState({
href={botLink}
target="_blank"
rel="noopener noreferrer"
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-400"
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-400"
>
{t('landing.openBot')}
</a>
@@ -545,7 +545,7 @@ function PollTimedOutState({ onRetry }: { onRetry: () => void }) {
<button
type="button"
onClick={onRetry}
className="rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-400"
className="rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-400"
>
{t('common.retry', 'Retry')}
</button>
@@ -641,7 +641,7 @@ function GiftLinkShareState({
'flex w-full items-center justify-center gap-2 rounded-xl px-4 py-3.5 text-sm font-bold transition-all duration-200 active:scale-[0.98]',
copied
? 'bg-success-500/20 text-success-400'
: 'bg-accent-500 text-white shadow-lg shadow-accent-500/25 hover:bg-accent-400',
: 'bg-accent-500 text-on-accent shadow-lg shadow-accent-500/25 hover:bg-accent-400',
)}
>
{copied ? (

View File

@@ -122,7 +122,7 @@ function PeriodTabs({
className={cn(
'whitespace-nowrap rounded-full px-4 py-2 text-sm font-medium transition-all duration-200',
selectedDays === period.days
? 'bg-accent-500 text-white shadow-lg shadow-accent-500/25'
? 'bg-accent-500 text-on-accent shadow-lg shadow-accent-500/25'
: 'bg-dark-800/50 text-dark-300 hover:bg-dark-700/50 hover:text-dark-100',
)}
>
@@ -409,7 +409,7 @@ function PaymentMethodCard({
className={cn(
'rounded-xl px-4 py-2 text-sm font-medium transition-all duration-200',
selectedSubOption === opt.id
? 'bg-accent-500 text-white shadow-sm shadow-accent-500/25'
? 'bg-accent-500 text-on-accent shadow-sm shadow-accent-500/25'
: 'bg-dark-800/50 text-dark-300 hover:bg-dark-700/50 hover:text-dark-100',
)}
>
@@ -583,7 +583,7 @@ function SummaryCard({
className={cn(
'flex w-full items-center justify-center gap-2 rounded-2xl px-6 py-4 text-base font-semibold transition-all duration-200',
canSubmit && !isSubmitting
? 'bg-accent-500 text-white shadow-lg shadow-accent-500/25 hover:bg-accent-400 hover:shadow-accent-500/40 active:scale-[0.98]'
? 'bg-accent-500 text-on-accent shadow-lg shadow-accent-500/25 hover:bg-accent-400 hover:shadow-accent-500/40 active:scale-[0.98]'
: 'cursor-not-allowed bg-dark-800 text-dark-500',
)}
>
@@ -629,7 +629,7 @@ function SummaryCard({
className={cn(
'flex w-full items-center justify-center gap-2 rounded-2xl px-6 py-4 text-base font-semibold transition-all duration-200',
canSubmit && !isSubmitting
? 'bg-accent-500 text-white shadow-lg shadow-accent-500/25 hover:bg-accent-400 hover:shadow-accent-500/40 active:scale-[0.98]'
? 'bg-accent-500 text-on-accent shadow-lg shadow-accent-500/25 hover:bg-accent-400 hover:shadow-accent-500/40 active:scale-[0.98]'
: 'cursor-not-allowed bg-dark-800 text-dark-500',
)}
>
@@ -734,7 +734,7 @@ function DiscountBanner({
<div className="flex flex-col items-center gap-4 px-5 py-5 sm:flex-row sm:justify-between">
{/* Left: badge + text */}
<div className="flex items-center gap-3">
<span className="shrink-0 rounded-full bg-accent-500 px-3 py-1 text-sm font-bold text-white shadow-lg shadow-accent-500/25">
<span className="shrink-0 rounded-full bg-accent-500 px-3 py-1 text-sm font-bold text-on-accent shadow-lg shadow-accent-500/25">
-{discount.percent}%
</span>
{discount.badge_text && (

View File

@@ -226,7 +226,7 @@ export default function RenewSubscription() {
<button
onClick={() => handleRenew(selectedPeriod)}
disabled={renewMutation.isPending}
className="w-full rounded-2xl bg-accent-500 py-3.5 text-base font-semibold text-white transition-colors hover:bg-accent-600 disabled:opacity-50"
className="w-full rounded-2xl bg-accent-500 py-3.5 text-base font-semibold text-on-accent transition-colors hover:bg-accent-600 disabled:opacity-50"
>
{renewMutation.isPending
? t('common.processing', 'Обработка...')

View File

@@ -515,7 +515,7 @@ export default function Subscription() {
</p>
<button
onClick={() => navigate('/subscriptions')}
className="rounded-xl bg-accent-500 px-6 py-2.5 text-sm font-medium text-white"
className="rounded-xl bg-accent-500 px-6 py-2.5 text-sm font-medium text-on-accent"
>
{t('subscription.backToList', 'Мои подписки')}
</button>

View File

@@ -121,7 +121,7 @@ export default function SubscriptionPurchase() {
</p>
<button
onClick={() => refetchOptions()}
className="rounded-xl bg-accent-500 px-6 py-2 text-sm font-medium text-white transition-colors hover:bg-accent-600"
className="rounded-xl bg-accent-500 px-6 py-2 text-sm font-medium text-on-accent transition-colors hover:bg-accent-600"
>
{t('common.retry')}
</button>
@@ -322,7 +322,7 @@ export default function SubscriptionPurchase() {
</p>
<button
onClick={() => refetchOptions()}
className="rounded-xl bg-accent-500 px-6 py-2 text-sm font-medium text-white transition-colors hover:bg-accent-600"
className="rounded-xl bg-accent-500 px-6 py-2 text-sm font-medium text-on-accent transition-colors hover:bg-accent-600"
>
{t('common.retry')}
</button>

View File

@@ -35,7 +35,7 @@ function EmptyState({ onBuy }: { onBuy: () => void }) {
</p>
<button
onClick={onBuy}
className="rounded-xl bg-accent-500 px-8 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-600"
className="rounded-xl bg-accent-500 px-8 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-600"
>
{t('subscriptions.buy', 'Купить подписку')}
</button>
@@ -135,7 +135,7 @@ export default function Subscriptions() {
{!isLoading && subscriptions.length > 0 && !hasActivePaid && (
<button
onClick={() => navigate('/subscription/purchase')}
className="flex w-full items-center justify-center gap-2 rounded-2xl bg-accent-500 p-3.5 text-sm font-semibold text-white transition-colors hover:bg-accent-600"
className="flex w-full items-center justify-center gap-2 rounded-2xl bg-accent-500 p-3.5 text-sm font-semibold text-on-accent transition-colors hover:bg-accent-600"
>
<PlusIcon className="h-5 w-5" />
{t('subscriptions.browsePlans', 'Посмотреть тарифы и купить подписку')}
@@ -171,7 +171,7 @@ export default function Subscriptions() {
(Telegram-баг #605056/#605063). */}
<button
onClick={() => navigate('/subscription/purchase')}
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-6 py-3 text-sm font-semibold text-white transition-colors hover:bg-accent-600"
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-6 py-3 text-sm font-semibold text-on-accent transition-colors hover:bg-accent-600"
>
<PlusIcon className="h-5 w-5" />
{t('subscriptions.browsePlans', 'Посмотреть тарифы и купить подписку')}

View File

@@ -507,7 +507,7 @@ export default function TopUpAmount() {
? 'cursor-not-allowed bg-dark-700 text-dark-500'
: isStarsMethod
? 'bg-gradient-to-r from-yellow-500 to-orange-500 text-white shadow-lg shadow-yellow-500/25 hover:from-yellow-400 hover:to-orange-400 active:from-yellow-600 active:to-orange-600'
: 'bg-accent-500 text-white shadow-lg shadow-accent-500/25 transition-colors hover:bg-accent-400 active:bg-accent-600'
: 'bg-accent-500 text-on-accent shadow-lg shadow-accent-500/25 transition-colors hover:bg-accent-400 active:bg-accent-600'
}`}
>
{isPending ? (

View File

@@ -82,7 +82,7 @@ export default function TopUpMethodSelect() {
{translatedDesc || method.description}
</div>
)}
<div className="mt-3 text-xs text-dark-600">
<div className="mt-3 text-xs text-dark-400">
{formatAmount(method.min_amount_kopeks / 100, 0)} {' '}
{formatAmount(method.max_amount_kopeks / 100, 0)} {currencySymbol}
</div>

View File

@@ -85,7 +85,7 @@ function SuccessState({ amountKopeks }: { amountKopeks: number | null }) {
<button
type="button"
onClick={handleGoToBalance}
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-400"
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-400"
>
{t('balance.topUpResult.goToBalance')}
</button>
@@ -162,7 +162,7 @@ function TimeoutState({ onRetry, onGoBack }: { onRetry: () => void; onGoBack: ()
<button
type="button"
onClick={onRetry}
className="w-full rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-400"
className="w-full rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-on-accent transition-colors hover:bg-accent-400"
>
{t('common.retry')}
</button>

View File

@@ -632,7 +632,7 @@ export default function Wheel() {
</button>
<button
onClick={handleDirectStarsPay}
className="rounded-lg bg-accent-500 px-4 py-2.5 text-sm font-medium text-white transition-colors hover:bg-accent-600"
className="rounded-lg bg-accent-500 px-4 py-2.5 text-sm font-medium text-on-accent transition-colors hover:bg-accent-600"
>
{t('wheel.payStars', { count: config.spin_cost_stars ?? 0 })}
</button>