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

@@ -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',
)}
>