@geenius/i18n 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/.changeset/config.json +11 -0
  2. package/.github/CODEOWNERS +1 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +16 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +11 -0
  5. package/.github/PULL_REQUEST_TEMPLATE.md +10 -0
  6. package/.github/dependabot.yml +11 -0
  7. package/.github/workflows/ci.yml +23 -0
  8. package/.github/workflows/release.yml +29 -0
  9. package/.nvmrc +1 -0
  10. package/.project/ACCOUNT.yaml +4 -0
  11. package/.project/IDEAS.yaml +7 -0
  12. package/.project/PROJECT.yaml +11 -0
  13. package/.project/ROADMAP.yaml +15 -0
  14. package/CHANGELOG.md +8 -0
  15. package/CODE_OF_CONDUCT.md +16 -0
  16. package/CONTRIBUTING.md +26 -0
  17. package/LICENSE +2 -0
  18. package/README.md +1 -0
  19. package/SECURITY.md +15 -0
  20. package/SUPPORT.md +8 -0
  21. package/package.json +75 -0
  22. package/packages/convex/package.json +42 -0
  23. package/packages/convex/src/index.ts +3 -0
  24. package/packages/convex/src/mutations.ts +65 -0
  25. package/packages/convex/src/queries.ts +54 -0
  26. package/packages/convex/src/schema.ts +26 -0
  27. package/packages/convex/tsconfig.json +18 -0
  28. package/packages/convex/tsup.config.ts +17 -0
  29. package/packages/react/README.md +1 -0
  30. package/packages/react/package.json +51 -0
  31. package/packages/react/src/components/index.tsx +87 -0
  32. package/packages/react/src/hooks/index.ts +4 -0
  33. package/packages/react/src/hooks/useI18n.tsx +50 -0
  34. package/packages/react/src/hooks/useI18nAdmin.ts +12 -0
  35. package/packages/react/src/hooks/useLocaleDetect.ts +10 -0
  36. package/packages/react/src/hooks/useTranslations.ts +11 -0
  37. package/packages/react/src/index.tsx +8 -0
  38. package/packages/react/src/pages/I18nAdminPage.tsx +42 -0
  39. package/packages/react/src/pages/LocalePreviewPage.tsx +54 -0
  40. package/packages/react/src/pages/index.ts +2 -0
  41. package/packages/react/tsconfig.json +19 -0
  42. package/packages/react/tsup.config.ts +12 -0
  43. package/packages/react-css/README.md +1 -0
  44. package/packages/react-css/package.json +36 -0
  45. package/packages/react-css/src/components/index.tsx +66 -0
  46. package/packages/react-css/src/hooks/index.ts +4 -0
  47. package/packages/react-css/src/index.tsx +4 -0
  48. package/packages/react-css/src/pages/LocaleSettingsPage.tsx +74 -0
  49. package/packages/react-css/src/pages/TranslationsPage.tsx +98 -0
  50. package/packages/react-css/src/styles.css +210 -0
  51. package/packages/react-css/tsconfig.json +19 -0
  52. package/packages/react-css/tsup.config.ts +10 -0
  53. package/packages/shared/README.md +1 -0
  54. package/packages/shared/package.json +44 -0
  55. package/packages/shared/src/__tests__/i18n.test.ts +78 -0
  56. package/packages/shared/src/config.ts +344 -0
  57. package/packages/shared/src/index.ts +106 -0
  58. package/packages/shared/src/types.ts +51 -0
  59. package/packages/shared/tsconfig.json +18 -0
  60. package/packages/shared/tsup.config.ts +11 -0
  61. package/packages/shared/vitest.config.ts +4 -0
  62. package/packages/solidjs/README.md +1 -0
  63. package/packages/solidjs/package.json +47 -0
  64. package/packages/solidjs/src/components/LocaleCard.tsx +44 -0
  65. package/packages/solidjs/src/components/LocaleStatsCard.tsx +35 -0
  66. package/packages/solidjs/src/components/LocaleSwitcher.tsx +65 -0
  67. package/packages/solidjs/src/components/MissingKeyAlert.tsx +21 -0
  68. package/packages/solidjs/src/components/RTLWrapper.tsx +13 -0
  69. package/packages/solidjs/src/components/TranslationKeyRow.tsx +41 -0
  70. package/packages/solidjs/src/components/index.ts +6 -0
  71. package/packages/solidjs/src/index.tsx +8 -0
  72. package/packages/solidjs/src/pages/I18nAdminPage.tsx +188 -0
  73. package/packages/solidjs/src/pages/LocalePreviewPage.tsx +99 -0
  74. package/packages/solidjs/src/pages/index.ts +2 -0
  75. package/packages/solidjs/src/primitives/I18nProvider.tsx +56 -0
  76. package/packages/solidjs/src/primitives/createI18nAdmin.ts +7 -0
  77. package/packages/solidjs/src/primitives/createLocaleDetect.ts +8 -0
  78. package/packages/solidjs/src/primitives/createTranslations.ts +22 -0
  79. package/packages/solidjs/src/primitives/index.ts +4 -0
  80. package/packages/solidjs/tsconfig.json +20 -0
  81. package/packages/solidjs/tsup.config.ts +12 -0
  82. package/packages/solidjs-css/README.md +1 -0
  83. package/packages/solidjs-css/package.json +33 -0
  84. package/packages/solidjs-css/src/components/LocaleCard.tsx +45 -0
  85. package/packages/solidjs-css/src/components/LocaleStatsCard.tsx +43 -0
  86. package/packages/solidjs-css/src/components/LocaleSwitcher.tsx +51 -0
  87. package/packages/solidjs-css/src/components/MissingKeyAlert.tsx +24 -0
  88. package/packages/solidjs-css/src/components/RTLWrapper.tsx +16 -0
  89. package/packages/solidjs-css/src/components/TranslationKeyRow.tsx +47 -0
  90. package/packages/solidjs-css/src/components/index.ts +6 -0
  91. package/packages/solidjs-css/src/i18n.css +1322 -0
  92. package/packages/solidjs-css/src/index.tsx +3 -0
  93. package/packages/solidjs-css/src/pages/I18nAdminPage.tsx +134 -0
  94. package/packages/solidjs-css/src/pages/LocalePreviewPage.tsx +116 -0
  95. package/packages/solidjs-css/src/pages/index.ts +2 -0
  96. package/packages/solidjs-css/src/primitives/index.ts +1 -0
  97. package/packages/solidjs-css/tsconfig.json +20 -0
  98. package/packages/solidjs-css/tsup.config.bundled_dcjc4sct21j.mjs +18 -0
  99. package/packages/solidjs-css/tsup.config.ts +14 -0
  100. package/pnpm-workspace.yaml +2 -0
  101. package/tsconfig.json +23 -0
@@ -0,0 +1,1322 @@
1
+ /* ═══════════════════════════════════════════════════════════════
2
+ @geenius-i18n/solidjs-css — BEM Design System
3
+ OKLCH Design Tokens + Comprehensive Component Styles
4
+ ═══════════════════════════════════════════════════════════════ */
5
+
6
+ /* ─── Design Tokens ──────────────────────────────────────────── */
7
+ :root {
8
+ --i18n-bg: oklch(0.10 0.01 250);
9
+ --i18n-bg-card: oklch(0.13 0.01 250);
10
+ --i18n-bg-card-hover: oklch(0.15 0.01 250);
11
+ --i18n-bg-input: oklch(0.16 0.01 250);
12
+ --i18n-border: oklch(0.22 0.01 250);
13
+ --i18n-border-focus: oklch(0.65 0.20 265);
14
+ --i18n-text: oklch(0.95 0.01 250);
15
+ --i18n-text-muted: oklch(0.65 0.01 250);
16
+ --i18n-text-faint: oklch(0.45 0.01 250);
17
+ --i18n-accent: oklch(0.65 0.20 265);
18
+ --i18n-accent-hover: oklch(0.70 0.22 265);
19
+ --i18n-accent-subtle: oklch(0.65 0.20 265 / 0.12);
20
+ --i18n-success: oklch(0.72 0.20 145);
21
+ --i18n-success-subtle: oklch(0.72 0.20 145 / 0.12);
22
+ --i18n-warning: oklch(0.78 0.18 75);
23
+ --i18n-warning-subtle: oklch(0.78 0.18 75 / 0.12);
24
+ --i18n-error: oklch(0.60 0.25 25);
25
+ --i18n-error-subtle: oklch(0.60 0.25 25 / 0.08);
26
+ --i18n-error-border: oklch(0.60 0.25 25 / 0.20);
27
+ --i18n-radius: 0.75rem;
28
+ --i18n-radius-sm: 0.375rem;
29
+ --i18n-radius-lg: 1rem;
30
+ --i18n-radius-full: 9999px;
31
+ --i18n-shadow: 0 4px 24px oklch(0 0 0 / 0.4);
32
+ --i18n-shadow-lg: 0 8px 40px oklch(0 0 0 / 0.5);
33
+ --i18n-shadow-dropdown: 0 12px 48px oklch(0 0 0 / 0.6);
34
+ --i18n-transition: 200ms ease;
35
+ --i18n-transition-fast: 120ms ease;
36
+ --i18n-transition-slow: 300ms ease;
37
+ --i18n-font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;
38
+ --i18n-font-sans: 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
39
+ }
40
+
41
+
42
+ /* ═══════════════════════════════════════════════════════════════
43
+ LOCALE SWITCHER
44
+ ═══════════════════════════════════════════════════════════════ */
45
+
46
+ .i18n__locale-switcher {
47
+ position: relative;
48
+ display: inline-block;
49
+ }
50
+
51
+ .i18n__locale-switcher-trigger {
52
+ display: flex;
53
+ align-items: center;
54
+ gap: 0.5rem;
55
+ padding: 0.5rem 0.75rem;
56
+ border-radius: var(--i18n-radius);
57
+ border: 1px solid var(--i18n-border);
58
+ background: oklch(1 0 0 / 0.05);
59
+ font-size: 0.875rem;
60
+ font-family: var(--i18n-font-sans);
61
+ color: var(--i18n-text);
62
+ cursor: pointer;
63
+ transition: all var(--i18n-transition);
64
+ white-space: nowrap;
65
+ }
66
+
67
+ .i18n__locale-switcher-trigger:hover {
68
+ background: oklch(1 0 0 / 0.10);
69
+ border-color: oklch(1 0 0 / 0.18);
70
+ }
71
+
72
+ .i18n__locale-switcher-trigger:focus-visible {
73
+ outline: 2px solid var(--i18n-accent);
74
+ outline-offset: 2px;
75
+ }
76
+
77
+ .i18n__locale-switcher-flag {
78
+ font-size: 1.125rem;
79
+ line-height: 1;
80
+ }
81
+
82
+ .i18n__locale-switcher-label {
83
+ font-weight: 500;
84
+ letter-spacing: -0.01em;
85
+ }
86
+
87
+ .i18n__locale-switcher-arrow {
88
+ font-size: 0.75rem;
89
+ color: var(--i18n-text-faint);
90
+ margin-left: 0.125rem;
91
+ transition: transform var(--i18n-transition);
92
+ }
93
+
94
+ .i18n__locale-switcher-dropdown {
95
+ position: absolute;
96
+ top: calc(100% + 0.375rem);
97
+ right: 0;
98
+ z-index: 50;
99
+ min-width: 14rem;
100
+ max-height: 20rem;
101
+ overflow-y: auto;
102
+ border-radius: var(--i18n-radius);
103
+ border: 1px solid var(--i18n-border);
104
+ background: oklch(0.09 0.01 250);
105
+ padding: 0.25rem;
106
+ box-shadow: var(--i18n-shadow-dropdown);
107
+ animation: i18n-dropdown-in 150ms ease-out;
108
+ }
109
+
110
+ .i18n__locale-switcher-dropdown::-webkit-scrollbar {
111
+ width: 4px;
112
+ }
113
+
114
+ .i18n__locale-switcher-dropdown::-webkit-scrollbar-track {
115
+ background: transparent;
116
+ }
117
+
118
+ .i18n__locale-switcher-dropdown::-webkit-scrollbar-thumb {
119
+ background: oklch(1 0 0 / 0.1);
120
+ border-radius: var(--i18n-radius-full);
121
+ }
122
+
123
+ .i18n__locale-switcher-option {
124
+ display: flex;
125
+ align-items: center;
126
+ gap: 0.75rem;
127
+ width: 100%;
128
+ padding: 0.625rem 0.75rem;
129
+ border: none;
130
+ border-radius: calc(var(--i18n-radius) - 0.125rem);
131
+ font-size: 0.875rem;
132
+ font-family: var(--i18n-font-sans);
133
+ color: oklch(1 0 0 / 0.7);
134
+ cursor: pointer;
135
+ background: transparent;
136
+ transition: all var(--i18n-transition-fast);
137
+ text-align: left;
138
+ }
139
+
140
+ .i18n__locale-switcher-option:hover {
141
+ background: oklch(1 0 0 / 0.06);
142
+ color: var(--i18n-text);
143
+ }
144
+
145
+ .i18n__locale-switcher-option--active {
146
+ background: var(--i18n-accent-subtle);
147
+ color: var(--i18n-accent);
148
+ }
149
+
150
+ .i18n__locale-switcher-option--active:hover {
151
+ background: oklch(0.65 0.20 265 / 0.18);
152
+ }
153
+
154
+ .i18n__locale-switcher-option-flag {
155
+ font-size: 1.125rem;
156
+ line-height: 1;
157
+ }
158
+
159
+ .i18n__locale-switcher-option-name {
160
+ flex: 1;
161
+ font-weight: 450;
162
+ }
163
+
164
+ .i18n__locale-switcher-option-rtl {
165
+ font-size: 0.5625rem;
166
+ font-weight: 600;
167
+ letter-spacing: 0.05em;
168
+ text-transform: uppercase;
169
+ padding: 0.125rem 0.375rem;
170
+ border-radius: var(--i18n-radius-sm);
171
+ background: var(--i18n-warning-subtle);
172
+ color: var(--i18n-warning);
173
+ }
174
+
175
+
176
+ /* ═══════════════════════════════════════════════════════════════
177
+ RTL WRAPPER
178
+ ═══════════════════════════════════════════════════════════════ */
179
+
180
+ .i18n__rtl-wrapper {
181
+ transition: all var(--i18n-transition-slow);
182
+ }
183
+
184
+ .i18n__rtl-wrapper--ltr {
185
+ direction: ltr;
186
+ text-align: left;
187
+ }
188
+
189
+ .i18n__rtl-wrapper--rtl {
190
+ direction: rtl;
191
+ text-align: right;
192
+ }
193
+
194
+
195
+ /* ═══════════════════════════════════════════════════════════════
196
+ LOCALE STATS CARD
197
+ ═══════════════════════════════════════════════════════════════ */
198
+
199
+ .i18n__stats-card {
200
+ padding: 1rem;
201
+ border: 1px solid var(--i18n-border);
202
+ border-radius: var(--i18n-radius);
203
+ background: var(--i18n-bg-card);
204
+ transition: all var(--i18n-transition);
205
+ }
206
+
207
+ .i18n__stats-card:hover {
208
+ background: var(--i18n-bg-card-hover);
209
+ border-color: oklch(1 0 0 / 0.14);
210
+ box-shadow: var(--i18n-shadow);
211
+ }
212
+
213
+ .i18n__stats-card-header {
214
+ display: flex;
215
+ align-items: center;
216
+ gap: 0.5rem;
217
+ margin-bottom: 0.625rem;
218
+ }
219
+
220
+ .i18n__stats-card-flag {
221
+ font-size: 1.25rem;
222
+ line-height: 1;
223
+ }
224
+
225
+ .i18n__stats-card-locale {
226
+ font-size: 0.8125rem;
227
+ font-weight: 600;
228
+ color: var(--i18n-text);
229
+ letter-spacing: -0.01em;
230
+ }
231
+
232
+ .i18n__stats-card-coverage {
233
+ display: flex;
234
+ justify-content: space-between;
235
+ align-items: baseline;
236
+ font-size: 0.6875rem;
237
+ color: var(--i18n-text-faint);
238
+ margin-bottom: 0.375rem;
239
+ }
240
+
241
+ .i18n__stats-card-keys {
242
+ color: var(--i18n-text-muted);
243
+ }
244
+
245
+ .i18n__stats-card-percent {
246
+ font-weight: 700;
247
+ font-variant-numeric: tabular-nums;
248
+ color: var(--i18n-text-muted);
249
+ }
250
+
251
+ .i18n__stats-card-bar {
252
+ height: 0.375rem;
253
+ border-radius: var(--i18n-radius-full);
254
+ background: oklch(1 0 0 / 0.06);
255
+ overflow: hidden;
256
+ }
257
+
258
+ .i18n__stats-card-bar-fill {
259
+ height: 100%;
260
+ border-radius: var(--i18n-radius-full);
261
+ transition: width var(--i18n-transition-slow);
262
+ }
263
+
264
+ .i18n__stats-card-bar-fill--complete {
265
+ background: var(--i18n-success);
266
+ }
267
+
268
+ .i18n__stats-card-bar-fill--partial {
269
+ background: var(--i18n-warning);
270
+ }
271
+
272
+ .i18n__stats-card-bar-fill--low {
273
+ background: var(--i18n-error);
274
+ }
275
+
276
+ .i18n__stats-card-counts {
277
+ margin-top: 0.375rem;
278
+ font-size: 0.625rem;
279
+ }
280
+
281
+ .i18n__stats-card-missing {
282
+ color: var(--i18n-error);
283
+ font-weight: 500;
284
+ }
285
+
286
+ .i18n__stats-card-complete {
287
+ color: var(--i18n-success);
288
+ font-weight: 500;
289
+ }
290
+
291
+
292
+ /* ═══════════════════════════════════════════════════════════════
293
+ MISSING KEY ALERT
294
+ ═══════════════════════════════════════════════════════════════ */
295
+
296
+ .i18n__missing-alert {
297
+ display: flex;
298
+ align-items: center;
299
+ gap: 0.75rem;
300
+ padding: 0.75rem 1rem;
301
+ border-radius: var(--i18n-radius);
302
+ border: 1px solid var(--i18n-error-border);
303
+ background: var(--i18n-error-subtle);
304
+ margin-bottom: 1.5rem;
305
+ animation: i18n-alert-in 250ms ease-out;
306
+ }
307
+
308
+ .i18n__missing-alert-icon {
309
+ font-size: 1rem;
310
+ line-height: 1;
311
+ flex-shrink: 0;
312
+ }
313
+
314
+ .i18n__missing-alert-text {
315
+ font-size: 0.8125rem;
316
+ color: oklch(0.75 0.18 25);
317
+ line-height: 1.4;
318
+ }
319
+
320
+ .i18n__missing-alert-text strong {
321
+ font-weight: 600;
322
+ color: oklch(0.80 0.20 25);
323
+ }
324
+
325
+ .i18n__missing-alert-count {
326
+ font-weight: 700;
327
+ font-variant-numeric: tabular-nums;
328
+ color: var(--i18n-error);
329
+ }
330
+
331
+
332
+ /* ═══════════════════════════════════════════════════════════════
333
+ TRANSLATION KEY ROW
334
+ ═══════════════════════════════════════════════════════════════ */
335
+
336
+ .i18n__key-row {
337
+ display: grid;
338
+ grid-template-columns: 1fr 2fr auto auto;
339
+ align-items: center;
340
+ gap: 1rem;
341
+ padding: 0.75rem 1rem;
342
+ border-bottom: 1px solid oklch(1 0 0 / 0.05);
343
+ transition: background var(--i18n-transition-fast);
344
+ }
345
+
346
+ .i18n__key-row:hover {
347
+ background: oklch(1 0 0 / 0.03);
348
+ }
349
+
350
+ .i18n__key-row:last-child {
351
+ border-bottom: none;
352
+ }
353
+
354
+ .i18n__key-row-key {
355
+ font-family: var(--i18n-font-mono);
356
+ font-size: 0.75rem;
357
+ font-weight: 500;
358
+ color: var(--i18n-accent);
359
+ letter-spacing: -0.01em;
360
+ overflow: hidden;
361
+ text-overflow: ellipsis;
362
+ white-space: nowrap;
363
+ }
364
+
365
+ .i18n__key-row-value {
366
+ font-size: 0.8125rem;
367
+ color: oklch(1 0 0 / 0.75);
368
+ overflow: hidden;
369
+ text-overflow: ellipsis;
370
+ white-space: nowrap;
371
+ max-width: 20rem;
372
+ }
373
+
374
+ .i18n__key-row-locale {
375
+ display: flex;
376
+ align-items: center;
377
+ gap: 0.375rem;
378
+ }
379
+
380
+ .i18n__key-row-locale-badge {
381
+ display: inline-flex;
382
+ align-items: center;
383
+ padding: 0.125rem 0.375rem;
384
+ border-radius: var(--i18n-radius-sm);
385
+ background: oklch(1 0 0 / 0.06);
386
+ font-size: 0.625rem;
387
+ font-weight: 600;
388
+ letter-spacing: 0.05em;
389
+ color: var(--i18n-text-faint);
390
+ }
391
+
392
+ .i18n__key-row-namespace {
393
+ display: inline-flex;
394
+ align-items: center;
395
+ padding: 0.125rem 0.375rem;
396
+ border-radius: var(--i18n-radius-sm);
397
+ background: var(--i18n-accent-subtle);
398
+ font-size: 0.5625rem;
399
+ font-weight: 500;
400
+ color: var(--i18n-accent);
401
+ }
402
+
403
+ .i18n__key-row-actions {
404
+ display: flex;
405
+ align-items: center;
406
+ gap: 0.375rem;
407
+ opacity: 0;
408
+ transition: opacity var(--i18n-transition);
409
+ }
410
+
411
+ .i18n__key-row:hover .i18n__key-row-actions {
412
+ opacity: 1;
413
+ }
414
+
415
+ .i18n__key-row-btn {
416
+ padding: 0.25rem 0.5rem;
417
+ border: none;
418
+ border-radius: var(--i18n-radius-sm);
419
+ font-size: 0.6875rem;
420
+ font-weight: 500;
421
+ font-family: var(--i18n-font-sans);
422
+ cursor: pointer;
423
+ transition: all var(--i18n-transition-fast);
424
+ background: transparent;
425
+ }
426
+
427
+ .i18n__key-row-btn--edit {
428
+ color: var(--i18n-text-muted);
429
+ }
430
+
431
+ .i18n__key-row-btn--edit:hover {
432
+ color: var(--i18n-accent);
433
+ background: var(--i18n-accent-subtle);
434
+ }
435
+
436
+ .i18n__key-row-btn--delete {
437
+ color: oklch(1 0 0 / 0.25);
438
+ }
439
+
440
+ .i18n__key-row-btn--delete:hover {
441
+ color: var(--i18n-error);
442
+ background: var(--i18n-error-subtle);
443
+ }
444
+
445
+
446
+ /* ═══════════════════════════════════════════════════════════════
447
+ LOCALE CARD
448
+ ═══════════════════════════════════════════════════════════════ */
449
+
450
+ .i18n__locale-card {
451
+ display: flex;
452
+ flex-direction: column;
453
+ gap: 0.625rem;
454
+ padding: 1rem;
455
+ border: 1px solid var(--i18n-border);
456
+ border-radius: var(--i18n-radius);
457
+ background: var(--i18n-bg-card);
458
+ cursor: pointer;
459
+ transition: all var(--i18n-transition);
460
+ text-align: left;
461
+ font-family: var(--i18n-font-sans);
462
+ width: 100%;
463
+ }
464
+
465
+ .i18n__locale-card:hover {
466
+ background: var(--i18n-bg-card-hover);
467
+ border-color: oklch(1 0 0 / 0.16);
468
+ box-shadow: var(--i18n-shadow);
469
+ transform: translateY(-1px);
470
+ }
471
+
472
+ .i18n__locale-card--selected {
473
+ border-color: var(--i18n-accent);
474
+ background: var(--i18n-accent-subtle);
475
+ box-shadow: 0 0 0 1px var(--i18n-accent), var(--i18n-shadow);
476
+ }
477
+
478
+ .i18n__locale-card--selected:hover {
479
+ background: oklch(0.65 0.20 265 / 0.16);
480
+ border-color: var(--i18n-accent-hover);
481
+ }
482
+
483
+ .i18n__locale-card-header {
484
+ display: flex;
485
+ align-items: center;
486
+ gap: 0.75rem;
487
+ }
488
+
489
+ .i18n__locale-card-flag {
490
+ font-size: 1.5rem;
491
+ line-height: 1;
492
+ }
493
+
494
+ .i18n__locale-card-info {
495
+ display: flex;
496
+ flex-direction: column;
497
+ gap: 0.125rem;
498
+ flex: 1;
499
+ min-width: 0;
500
+ }
501
+
502
+ .i18n__locale-card-name {
503
+ font-size: 0.875rem;
504
+ font-weight: 600;
505
+ color: var(--i18n-text);
506
+ letter-spacing: -0.01em;
507
+ }
508
+
509
+ .i18n__locale-card-code {
510
+ font-size: 0.6875rem;
511
+ color: var(--i18n-text-faint);
512
+ }
513
+
514
+ .i18n__locale-card-rtl {
515
+ font-size: 0.5625rem;
516
+ font-weight: 600;
517
+ letter-spacing: 0.05em;
518
+ text-transform: uppercase;
519
+ padding: 0.125rem 0.375rem;
520
+ border-radius: var(--i18n-radius-sm);
521
+ background: var(--i18n-warning-subtle);
522
+ color: var(--i18n-warning);
523
+ margin-left: auto;
524
+ flex-shrink: 0;
525
+ }
526
+
527
+ .i18n__locale-card-bar {
528
+ height: 0.375rem;
529
+ border-radius: var(--i18n-radius-full);
530
+ background: oklch(1 0 0 / 0.06);
531
+ overflow: hidden;
532
+ }
533
+
534
+ .i18n__locale-card-bar-fill {
535
+ height: 100%;
536
+ border-radius: var(--i18n-radius-full);
537
+ transition: width var(--i18n-transition-slow);
538
+ }
539
+
540
+ .i18n__locale-card-bar-fill--complete {
541
+ background: var(--i18n-success);
542
+ }
543
+
544
+ .i18n__locale-card-bar-fill--partial {
545
+ background: var(--i18n-warning);
546
+ }
547
+
548
+ .i18n__locale-card-bar-fill--low {
549
+ background: var(--i18n-error);
550
+ }
551
+
552
+ .i18n__locale-card-coverage {
553
+ font-size: 0.6875rem;
554
+ font-weight: 600;
555
+ font-variant-numeric: tabular-nums;
556
+ color: var(--i18n-text-faint);
557
+ text-align: right;
558
+ }
559
+
560
+
561
+ /* ═══════════════════════════════════════════════════════════════
562
+ ADMIN PAGE LAYOUT
563
+ ═══════════════════════════════════════════════════════════════ */
564
+
565
+ .i18n__admin-page {
566
+ min-height: 100vh;
567
+ background: var(--i18n-bg);
568
+ color: var(--i18n-text);
569
+ font-family: var(--i18n-font-sans);
570
+ }
571
+
572
+ .i18n__admin-container {
573
+ max-width: 72rem;
574
+ margin: 0 auto;
575
+ padding: 3rem 1.5rem;
576
+ }
577
+
578
+ .i18n__page-header {
579
+ margin-bottom: 2.5rem;
580
+ }
581
+
582
+ .i18n__page-title {
583
+ font-size: 1.75rem;
584
+ font-weight: 700;
585
+ letter-spacing: -0.03em;
586
+ color: var(--i18n-text);
587
+ margin: 0 0 0.375rem;
588
+ line-height: 1.2;
589
+ }
590
+
591
+ .i18n__page-subtitle {
592
+ font-size: 0.875rem;
593
+ color: var(--i18n-text-muted);
594
+ margin: 0;
595
+ }
596
+
597
+ .i18n__admin-body {
598
+ display: flex;
599
+ flex-direction: column;
600
+ gap: 2rem;
601
+ }
602
+
603
+ .i18n__admin-section {
604
+ display: flex;
605
+ flex-direction: column;
606
+ gap: 1rem;
607
+ }
608
+
609
+ .i18n__admin-section-header {
610
+ display: flex;
611
+ align-items: center;
612
+ justify-content: space-between;
613
+ gap: 1rem;
614
+ flex-wrap: wrap;
615
+ }
616
+
617
+ .i18n__admin-section-title {
618
+ font-size: 0.75rem;
619
+ font-weight: 600;
620
+ color: var(--i18n-text-muted);
621
+ text-transform: uppercase;
622
+ letter-spacing: 0.06em;
623
+ margin: 0;
624
+ }
625
+
626
+ .i18n__stats-grid {
627
+ display: grid;
628
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
629
+ gap: 0.75rem;
630
+ }
631
+
632
+ .i18n__locale-grid {
633
+ display: grid;
634
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
635
+ gap: 0.75rem;
636
+ }
637
+
638
+ .i18n__search-input {
639
+ width: 100%;
640
+ max-width: 16rem;
641
+ padding: 0.5rem 0.75rem;
642
+ border: 1px solid var(--i18n-border);
643
+ border-radius: var(--i18n-radius);
644
+ background: var(--i18n-bg-input);
645
+ font-size: 0.875rem;
646
+ font-family: var(--i18n-font-sans);
647
+ color: var(--i18n-text);
648
+ outline: none;
649
+ transition: all var(--i18n-transition);
650
+ }
651
+
652
+ .i18n__search-input::placeholder {
653
+ color: var(--i18n-text-faint);
654
+ }
655
+
656
+ .i18n__search-input:focus {
657
+ border-color: var(--i18n-border-focus);
658
+ box-shadow: 0 0 0 3px oklch(0.65 0.20 265 / 0.12);
659
+ }
660
+
661
+ .i18n__translation-list {
662
+ border: 1px solid var(--i18n-border);
663
+ border-radius: var(--i18n-radius);
664
+ background: var(--i18n-bg-card);
665
+ overflow: hidden;
666
+ }
667
+
668
+ .i18n__empty-state {
669
+ display: flex;
670
+ flex-direction: column;
671
+ align-items: center;
672
+ justify-content: center;
673
+ padding: 4rem 1.5rem;
674
+ text-align: center;
675
+ }
676
+
677
+ .i18n__empty-state-icon {
678
+ font-size: 3rem;
679
+ opacity: 0.15;
680
+ margin-bottom: 1rem;
681
+ }
682
+
683
+ .i18n__empty-state-text {
684
+ font-size: 0.875rem;
685
+ color: var(--i18n-text-faint);
686
+ margin: 0;
687
+ }
688
+
689
+
690
+ /* ═══════════════════════════════════════════════════════════════
691
+ PREVIEW PAGE LAYOUT
692
+ ═══════════════════════════════════════════════════════════════ */
693
+
694
+ .i18n__preview-page {
695
+ min-height: 100vh;
696
+ background: var(--i18n-bg);
697
+ color: var(--i18n-text);
698
+ font-family: var(--i18n-font-sans);
699
+ }
700
+
701
+ .i18n__preview-container {
702
+ max-width: 52rem;
703
+ margin: 0 auto;
704
+ padding: 3rem 1.5rem;
705
+ }
706
+
707
+ .i18n__preview-header {
708
+ display: flex;
709
+ align-items: center;
710
+ justify-content: space-between;
711
+ gap: 1rem;
712
+ margin-bottom: 2rem;
713
+ flex-wrap: wrap;
714
+ }
715
+
716
+ .i18n__preview-header-text {
717
+ display: flex;
718
+ flex-direction: column;
719
+ gap: 0.25rem;
720
+ }
721
+
722
+ .i18n__preview-title {
723
+ font-size: 1.5rem;
724
+ font-weight: 700;
725
+ letter-spacing: -0.02em;
726
+ margin: 0;
727
+ line-height: 1.2;
728
+ }
729
+
730
+ .i18n__preview-subtitle {
731
+ font-size: 0.875rem;
732
+ color: var(--i18n-text-muted);
733
+ margin: 0;
734
+ }
735
+
736
+ .i18n__preview-info-grid {
737
+ display: grid;
738
+ grid-template-columns: repeat(4, 1fr);
739
+ gap: 0.75rem;
740
+ margin-bottom: 2rem;
741
+ }
742
+
743
+ .i18n__preview-info-card {
744
+ padding: 1rem;
745
+ border: 1px solid var(--i18n-border);
746
+ border-radius: var(--i18n-radius);
747
+ background: var(--i18n-bg-card);
748
+ display: flex;
749
+ flex-direction: column;
750
+ gap: 0.25rem;
751
+ transition: all var(--i18n-transition);
752
+ }
753
+
754
+ .i18n__preview-info-card:hover {
755
+ background: var(--i18n-bg-card-hover);
756
+ box-shadow: var(--i18n-shadow);
757
+ }
758
+
759
+ .i18n__preview-info-label {
760
+ font-size: 0.625rem;
761
+ font-weight: 500;
762
+ color: var(--i18n-text-faint);
763
+ text-transform: uppercase;
764
+ letter-spacing: 0.06em;
765
+ }
766
+
767
+ .i18n__preview-info-value {
768
+ font-size: 1.125rem;
769
+ font-weight: 700;
770
+ color: var(--i18n-text);
771
+ }
772
+
773
+ .i18n__preview-info-value--highlight {
774
+ color: var(--i18n-warning);
775
+ }
776
+
777
+ .i18n__preview-content {
778
+ display: flex;
779
+ flex-direction: column;
780
+ gap: 1.5rem;
781
+ }
782
+
783
+ .i18n__preview-section {
784
+ padding: 1.25rem;
785
+ border: 1px solid var(--i18n-border);
786
+ border-radius: var(--i18n-radius);
787
+ background: var(--i18n-bg-card);
788
+ }
789
+
790
+ .i18n__preview-section-title {
791
+ font-size: 0.875rem;
792
+ font-weight: 600;
793
+ color: oklch(1 0 0 / 0.85);
794
+ margin: 0 0 1rem;
795
+ }
796
+
797
+ .i18n__preview-examples {
798
+ display: flex;
799
+ flex-direction: column;
800
+ gap: 0.625rem;
801
+ }
802
+
803
+ .i18n__preview-example {
804
+ display: flex;
805
+ justify-content: space-between;
806
+ align-items: baseline;
807
+ padding: 0.5rem 0;
808
+ border-bottom: 1px solid oklch(1 0 0 / 0.04);
809
+ }
810
+
811
+ .i18n__preview-example:last-child {
812
+ border-bottom: none;
813
+ padding-bottom: 0;
814
+ }
815
+
816
+ .i18n__preview-label {
817
+ font-size: 0.875rem;
818
+ color: var(--i18n-text-faint);
819
+ }
820
+
821
+ .i18n__preview-value {
822
+ font-family: var(--i18n-font-mono);
823
+ font-size: 0.8125rem;
824
+ color: oklch(1 0 0 / 0.85);
825
+ font-variant-numeric: tabular-nums;
826
+ }
827
+
828
+ .i18n__preview-rtl-notice {
829
+ padding: 0.875rem 1.125rem;
830
+ border-radius: var(--i18n-radius);
831
+ border: 1px solid oklch(0.78 0.18 75 / 0.20);
832
+ background: oklch(0.78 0.18 75 / 0.06);
833
+ font-size: 0.875rem;
834
+ font-weight: 500;
835
+ color: var(--i18n-warning);
836
+ }
837
+
838
+ .i18n__preview-sample-text {
839
+ font-size: 0.875rem;
840
+ color: oklch(1 0 0 / 0.6);
841
+ line-height: 1.7;
842
+ margin: 0;
843
+ }
844
+
845
+
846
+ /* ═══════════════════════════════════════════════════════════════
847
+ ANIMATIONS
848
+ ═══════════════════════════════════════════════════════════════ */
849
+
850
+ @keyframes i18n-dropdown-in {
851
+ from {
852
+ opacity: 0;
853
+ transform: translateY(-4px) scale(0.97);
854
+ }
855
+ to {
856
+ opacity: 1;
857
+ transform: translateY(0) scale(1);
858
+ }
859
+ }
860
+
861
+ @keyframes i18n-alert-in {
862
+ from {
863
+ opacity: 0;
864
+ transform: translateY(-6px);
865
+ }
866
+ to {
867
+ opacity: 1;
868
+ transform: translateY(0);
869
+ }
870
+ }
871
+
872
+ @keyframes i18n-pulse {
873
+ 0%, 100% {
874
+ opacity: 1;
875
+ }
876
+ 50% {
877
+ opacity: 0.4;
878
+ }
879
+ }
880
+
881
+ @keyframes i18n-fade-in {
882
+ from {
883
+ opacity: 0;
884
+ }
885
+ to {
886
+ opacity: 1;
887
+ }
888
+ }
889
+
890
+ @keyframes i18n-slide-up {
891
+ from {
892
+ opacity: 0;
893
+ transform: translateY(8px);
894
+ }
895
+ to {
896
+ opacity: 1;
897
+ transform: translateY(0);
898
+ }
899
+ }
900
+
901
+
902
+ /* ═══════════════════════════════════════════════════════════════
903
+ SKELETON / LOADING
904
+ ═══════════════════════════════════════════════════════════════ */
905
+
906
+ .i18n__skeleton {
907
+ background: oklch(1 0 0 / 0.05);
908
+ border-radius: var(--i18n-radius);
909
+ animation: i18n-pulse 1.5s ease-in-out infinite;
910
+ }
911
+
912
+ .i18n__skeleton--sm {
913
+ height: 1rem;
914
+ border-radius: var(--i18n-radius-sm);
915
+ }
916
+
917
+ .i18n__skeleton--md {
918
+ height: 2.5rem;
919
+ }
920
+
921
+ .i18n__skeleton--lg {
922
+ height: 5rem;
923
+ }
924
+
925
+ .i18n__skeleton--xl {
926
+ height: 12rem;
927
+ }
928
+
929
+ .i18n__skeleton--card {
930
+ height: 6rem;
931
+ border-radius: var(--i18n-radius);
932
+ }
933
+
934
+
935
+ /* ═══════════════════════════════════════════════════════════════
936
+ RESPONSIVE
937
+ ═══════════════════════════════════════════════════════════════ */
938
+
939
+ @media (max-width: 768px) {
940
+ .i18n__admin-container {
941
+ padding: 1.5rem 1rem;
942
+ }
943
+
944
+ .i18n__preview-container {
945
+ padding: 1.5rem 1rem;
946
+ }
947
+
948
+ .i18n__page-title {
949
+ font-size: 1.375rem;
950
+ }
951
+
952
+ .i18n__preview-title {
953
+ font-size: 1.25rem;
954
+ }
955
+
956
+ .i18n__stats-grid {
957
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
958
+ }
959
+
960
+ .i18n__locale-grid {
961
+ grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
962
+ }
963
+
964
+ .i18n__preview-info-grid {
965
+ grid-template-columns: repeat(2, 1fr);
966
+ }
967
+
968
+ .i18n__key-row {
969
+ grid-template-columns: 1fr 1.5fr auto;
970
+ gap: 0.5rem;
971
+ padding: 0.625rem 0.75rem;
972
+ }
973
+
974
+ .i18n__key-row-locale {
975
+ display: none;
976
+ }
977
+
978
+ .i18n__search-input {
979
+ max-width: 100%;
980
+ }
981
+
982
+ .i18n__admin-section-header {
983
+ flex-direction: column;
984
+ align-items: flex-start;
985
+ }
986
+
987
+ .i18n__preview-header {
988
+ flex-direction: column;
989
+ align-items: flex-start;
990
+ }
991
+ }
992
+
993
+ @media (max-width: 480px) {
994
+ .i18n__stats-grid {
995
+ grid-template-columns: 1fr 1fr;
996
+ }
997
+
998
+ .i18n__locale-grid {
999
+ grid-template-columns: 1fr;
1000
+ }
1001
+
1002
+ .i18n__preview-info-grid {
1003
+ grid-template-columns: 1fr 1fr;
1004
+ gap: 0.5rem;
1005
+ }
1006
+
1007
+ .i18n__key-row {
1008
+ grid-template-columns: 1fr auto;
1009
+ }
1010
+
1011
+ .i18n__key-row-value {
1012
+ display: none;
1013
+ }
1014
+
1015
+ .i18n__locale-switcher-label {
1016
+ display: none;
1017
+ }
1018
+ }
1019
+
1020
+
1021
+ /* ═══════════════════════════════════════════════════════════════
1022
+ FOCUS & ACCESSIBILITY
1023
+ ═══════════════════════════════════════════════════════════════ */
1024
+
1025
+ .i18n__locale-card:focus-visible {
1026
+ outline: 2px solid var(--i18n-accent);
1027
+ outline-offset: 2px;
1028
+ }
1029
+
1030
+ .i18n__locale-switcher-option:focus-visible {
1031
+ outline: 2px solid var(--i18n-accent);
1032
+ outline-offset: -2px;
1033
+ }
1034
+
1035
+ .i18n__key-row-btn:focus-visible {
1036
+ outline: 2px solid var(--i18n-accent);
1037
+ outline-offset: 2px;
1038
+ }
1039
+
1040
+ .i18n__search-input:focus-visible {
1041
+ outline: none;
1042
+ border-color: var(--i18n-border-focus);
1043
+ box-shadow: 0 0 0 3px oklch(0.65 0.20 265 / 0.12);
1044
+ }
1045
+
1046
+
1047
+ /* ═══════════════════════════════════════════════════════════════
1048
+ UTILITY CLASSES
1049
+ ═══════════════════════════════════════════════════════════════ */
1050
+
1051
+ .i18n__divider {
1052
+ height: 1px;
1053
+ background: var(--i18n-border);
1054
+ border: none;
1055
+ margin: 1.5rem 0;
1056
+ }
1057
+
1058
+ .i18n__badge {
1059
+ display: inline-flex;
1060
+ align-items: center;
1061
+ padding: 0.125rem 0.5rem;
1062
+ border-radius: var(--i18n-radius-full);
1063
+ font-size: 0.625rem;
1064
+ font-weight: 600;
1065
+ letter-spacing: 0.03em;
1066
+ }
1067
+
1068
+ .i18n__badge--accent {
1069
+ background: var(--i18n-accent-subtle);
1070
+ color: var(--i18n-accent);
1071
+ }
1072
+
1073
+ .i18n__badge--success {
1074
+ background: var(--i18n-success-subtle);
1075
+ color: var(--i18n-success);
1076
+ }
1077
+
1078
+ .i18n__badge--warning {
1079
+ background: var(--i18n-warning-subtle);
1080
+ color: var(--i18n-warning);
1081
+ }
1082
+
1083
+ .i18n__badge--error {
1084
+ background: var(--i18n-error-subtle);
1085
+ color: var(--i18n-error);
1086
+ }
1087
+
1088
+ .i18n__text-mono {
1089
+ font-family: var(--i18n-font-mono);
1090
+ }
1091
+
1092
+ .i18n__text-muted {
1093
+ color: var(--i18n-text-muted);
1094
+ }
1095
+
1096
+ .i18n__text-faint {
1097
+ color: var(--i18n-text-faint);
1098
+ }
1099
+
1100
+
1101
+ /* ═══════════════════════════════════════════════════════════════
1102
+ EDITOR FORM
1103
+ ═══════════════════════════════════════════════════════════════ */
1104
+
1105
+ .i18n__editor {
1106
+ display: flex;
1107
+ flex-direction: column;
1108
+ gap: 0.75rem;
1109
+ padding: 1.25rem;
1110
+ border: 1px solid var(--i18n-border);
1111
+ border-radius: var(--i18n-radius);
1112
+ background: var(--i18n-bg-card);
1113
+ }
1114
+
1115
+ .i18n__editor-title {
1116
+ font-size: 0.75rem;
1117
+ font-weight: 600;
1118
+ color: var(--i18n-text-muted);
1119
+ text-transform: uppercase;
1120
+ letter-spacing: 0.06em;
1121
+ margin: 0;
1122
+ }
1123
+
1124
+ .i18n__editor-input {
1125
+ width: 100%;
1126
+ padding: 0.625rem 1rem;
1127
+ border: 1px solid var(--i18n-border);
1128
+ border-radius: var(--i18n-radius);
1129
+ background: var(--i18n-bg-input);
1130
+ font-size: 0.875rem;
1131
+ font-family: var(--i18n-font-sans);
1132
+ color: var(--i18n-text);
1133
+ outline: none;
1134
+ transition: all var(--i18n-transition);
1135
+ }
1136
+
1137
+ .i18n__editor-input::placeholder {
1138
+ color: var(--i18n-text-faint);
1139
+ }
1140
+
1141
+ .i18n__editor-input:focus {
1142
+ border-color: var(--i18n-border-focus);
1143
+ box-shadow: 0 0 0 3px oklch(0.65 0.20 265 / 0.12);
1144
+ }
1145
+
1146
+ .i18n__editor-textarea {
1147
+ width: 100%;
1148
+ padding: 0.625rem 1rem;
1149
+ border: 1px solid var(--i18n-border);
1150
+ border-radius: var(--i18n-radius);
1151
+ background: var(--i18n-bg-input);
1152
+ font-size: 0.875rem;
1153
+ font-family: var(--i18n-font-sans);
1154
+ color: var(--i18n-text);
1155
+ outline: none;
1156
+ resize: vertical;
1157
+ min-height: 4rem;
1158
+ transition: all var(--i18n-transition);
1159
+ }
1160
+
1161
+ .i18n__editor-textarea::placeholder {
1162
+ color: var(--i18n-text-faint);
1163
+ }
1164
+
1165
+ .i18n__editor-textarea:focus {
1166
+ border-color: var(--i18n-border-focus);
1167
+ box-shadow: 0 0 0 3px oklch(0.65 0.20 265 / 0.12);
1168
+ }
1169
+
1170
+ .i18n__editor-actions {
1171
+ display: flex;
1172
+ justify-content: flex-end;
1173
+ gap: 0.5rem;
1174
+ }
1175
+
1176
+
1177
+ /* ═══════════════════════════════════════════════════════════════
1178
+ BUTTONS
1179
+ ═══════════════════════════════════════════════════════════════ */
1180
+
1181
+ .i18n__btn {
1182
+ display: inline-flex;
1183
+ align-items: center;
1184
+ justify-content: center;
1185
+ gap: 0.375rem;
1186
+ padding: 0.5rem 1rem;
1187
+ border-radius: var(--i18n-radius);
1188
+ font-size: 0.8125rem;
1189
+ font-weight: 500;
1190
+ font-family: var(--i18n-font-sans);
1191
+ cursor: pointer;
1192
+ border: none;
1193
+ transition: all var(--i18n-transition);
1194
+ }
1195
+
1196
+ .i18n__btn--primary {
1197
+ background: var(--i18n-accent);
1198
+ color: white;
1199
+ }
1200
+
1201
+ .i18n__btn--primary:hover {
1202
+ background: var(--i18n-accent-hover);
1203
+ box-shadow: 0 2px 8px oklch(0.65 0.20 265 / 0.3);
1204
+ }
1205
+
1206
+ .i18n__btn--primary:disabled {
1207
+ opacity: 0.4;
1208
+ cursor: not-allowed;
1209
+ box-shadow: none;
1210
+ }
1211
+
1212
+ .i18n__btn--ghost {
1213
+ background: transparent;
1214
+ color: var(--i18n-text-muted);
1215
+ border: 1px solid var(--i18n-border);
1216
+ }
1217
+
1218
+ .i18n__btn--ghost:hover {
1219
+ background: oklch(1 0 0 / 0.05);
1220
+ color: var(--i18n-text);
1221
+ }
1222
+
1223
+ .i18n__btn--danger {
1224
+ background: var(--i18n-error-subtle);
1225
+ color: var(--i18n-error);
1226
+ border: 1px solid var(--i18n-error-border);
1227
+ }
1228
+
1229
+ .i18n__btn--danger:hover {
1230
+ background: oklch(0.60 0.25 25 / 0.15);
1231
+ }
1232
+
1233
+
1234
+ /* ═══════════════════════════════════════════════════════════════
1235
+ TOOLTIP
1236
+ ═══════════════════════════════════════════════════════════════ */
1237
+
1238
+ .i18n__tooltip {
1239
+ position: relative;
1240
+ }
1241
+
1242
+ .i18n__tooltip-content {
1243
+ position: absolute;
1244
+ bottom: calc(100% + 0.5rem);
1245
+ left: 50%;
1246
+ transform: translateX(-50%);
1247
+ padding: 0.375rem 0.625rem;
1248
+ border-radius: var(--i18n-radius-sm);
1249
+ background: oklch(0.20 0.01 250);
1250
+ color: var(--i18n-text);
1251
+ font-size: 0.6875rem;
1252
+ white-space: nowrap;
1253
+ pointer-events: none;
1254
+ box-shadow: var(--i18n-shadow);
1255
+ animation: i18n-fade-in 150ms ease-out;
1256
+ }
1257
+
1258
+
1259
+ /* ═══════════════════════════════════════════════════════════════
1260
+ SCROLLBAR (global for i18n containers)
1261
+ ═══════════════════════════════════════════════════════════════ */
1262
+
1263
+ .i18n__admin-page::-webkit-scrollbar {
1264
+ width: 6px;
1265
+ }
1266
+
1267
+ .i18n__admin-page::-webkit-scrollbar-track {
1268
+ background: transparent;
1269
+ }
1270
+
1271
+ .i18n__admin-page::-webkit-scrollbar-thumb {
1272
+ background: oklch(1 0 0 / 0.08);
1273
+ border-radius: var(--i18n-radius-full);
1274
+ }
1275
+
1276
+ .i18n__admin-page::-webkit-scrollbar-thumb:hover {
1277
+ background: oklch(1 0 0 / 0.14);
1278
+ }
1279
+
1280
+ .i18n__translation-list::-webkit-scrollbar {
1281
+ width: 4px;
1282
+ }
1283
+
1284
+ .i18n__translation-list::-webkit-scrollbar-track {
1285
+ background: transparent;
1286
+ }
1287
+
1288
+ .i18n__translation-list::-webkit-scrollbar-thumb {
1289
+ background: oklch(1 0 0 / 0.08);
1290
+ border-radius: var(--i18n-radius-full);
1291
+ }
1292
+
1293
+
1294
+ /* ═══════════════════════════════════════════════════════════════
1295
+ COVERAGE INDICATOR MODIFIERS
1296
+ ═══════════════════════════════════════════════════════════════ */
1297
+
1298
+ .i18n__locale-card--coverage-high .i18n__locale-card-coverage {
1299
+ color: var(--i18n-success);
1300
+ }
1301
+
1302
+ .i18n__locale-card--coverage-mid .i18n__locale-card-coverage {
1303
+ color: var(--i18n-warning);
1304
+ }
1305
+
1306
+ .i18n__locale-card--coverage-low .i18n__locale-card-coverage {
1307
+ color: var(--i18n-error);
1308
+ }
1309
+
1310
+ .i18n__stats-card--highlighted {
1311
+ border-color: var(--i18n-accent);
1312
+ box-shadow: 0 0 0 1px var(--i18n-accent);
1313
+ }
1314
+
1315
+ .i18n__key-row--missing {
1316
+ background: var(--i18n-error-subtle);
1317
+ border-left: 3px solid var(--i18n-error);
1318
+ }
1319
+
1320
+ .i18n__key-row--missing .i18n__key-row-key {
1321
+ color: var(--i18n-error);
1322
+ }