@ttt-productions/theme-core 0.1.19 → 0.1.20

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.
@@ -1,7 +1,41 @@
1
1
  @layer components {
2
- /* ===================
3
- LAYOUT / CARDS
4
- =================== */
2
+ /* =========================================================
3
+ FOUNDATIONS (icon + layout bundles) — replaces inline utils
4
+ ========================================================= */
5
+
6
+ /* Icons */
7
+ .icon-xxs { @apply h-3 w-3; }
8
+ .icon-xs { @apply h-4 w-4; }
9
+ .icon-sm { @apply h-5 w-5; }
10
+ .icon-md { @apply h-6 w-6; }
11
+ .icon-lg { @apply h-8 w-8; }
12
+ .icon-xl { @apply h-10 w-10; }
13
+ .icon-2xl { @apply h-12 w-12; }
14
+
15
+ /* Spinners */
16
+ .spinner-xs { @apply icon-xs animate-spin; color: hsl(var(--primary)); }
17
+ .spinner-sm { @apply icon-sm animate-spin; color: hsl(var(--primary)); }
18
+ .spinner-md { @apply icon-md animate-spin; color: hsl(var(--primary)); }
19
+ .spinner-lg { @apply icon-lg animate-spin; color: hsl(var(--primary)); }
20
+ .spinner-xl { @apply icon-xl animate-spin; color: hsl(var(--primary)); }
21
+ .spinner-with-gap { @apply mr-2; }
22
+
23
+ /* Common centering */
24
+ .center-row { @apply flex items-center justify-center; }
25
+ .center-col { @apply flex flex-col items-center justify-center; }
26
+ .loading-block { @apply center-row py-8; }
27
+ .loading-block-padded { @apply center-row p-8; }
28
+ .loading-screen { @apply flex flex-col h-screen-mobile w-screen items-center justify-center bg-background space-y-4; }
29
+
30
+ /* Stacks */
31
+ .stack-1 { @apply space-y-1; }
32
+ .stack-2 { @apply space-y-2; }
33
+ .stack-4 { @apply space-y-4; }
34
+ .stack-6 { @apply space-y-6; }
35
+
36
+ /* =========================================================
37
+ PAGE LAYOUT
38
+ ========================================================= */
5
39
  .page-container {
6
40
  @apply flex-1 w-full mx-auto py-4;
7
41
  }
@@ -11,7 +45,11 @@
11
45
  }
12
46
 
13
47
  .page-card-header {
14
- @apply text-center p-4 sm:p-6;
48
+ @apply text-center p-4 sm:p-6 items-center;
49
+ }
50
+
51
+ .page-card-header-left {
52
+ @apply p-4 sm:p-6 text-left;
15
53
  }
16
54
 
17
55
  .page-card-title {
@@ -26,25 +64,21 @@
26
64
  @apply px-4 py-2;
27
65
  }
28
66
 
29
- /* ===================
30
- TEXT UTILITIES
31
- =================== */
32
- .card-title {
67
+ /* =========================================================
68
+ TYPOGRAPHY (high-level)
69
+ ========================================================= */
70
+ .text-body {
71
+ @apply text-sm font-medium;
33
72
  color: hsl(var(--foreground));
34
73
  }
35
74
 
36
- .card-description {
37
- @apply text-sm font-bold;
38
- color: hsl(var(--muted-foreground));
39
- }
40
-
41
- .input-description {
42
- @apply text-xs;
75
+ .text-muted {
76
+ @apply text-sm font-medium;
43
77
  color: hsl(var(--muted-foreground));
44
78
  }
45
79
 
46
- .disclaimer-text {
47
- @apply text-sm font-bold text-center;
80
+ .text-caption {
81
+ @apply text-xs font-medium;
48
82
  color: hsl(var(--muted-foreground));
49
83
  }
50
84
 
@@ -73,261 +107,527 @@
73
107
  color: hsl(var(--muted-foreground));
74
108
  }
75
109
 
76
- /* ===================
110
+ .card-description {
111
+ @apply text-sm font-bold;
112
+ color: hsl(var(--muted-foreground));
113
+ }
114
+
115
+ .input-description {
116
+ @apply text-xs;
117
+ color: hsl(var(--muted-foreground));
118
+ }
119
+
120
+ .disclaimer-text {
121
+ @apply text-sm font-bold text-center;
122
+ color: hsl(var(--muted-foreground));
123
+ }
124
+
125
+ /* Error blocks / inline */
126
+ .text-error {
127
+ @apply text-sm font-bold;
128
+ color: hsl(var(--destructive));
129
+ }
130
+
131
+ .text-error-block {
132
+ @apply text-center p-4 font-bold rounded-md border;
133
+ color: hsl(var(--destructive));
134
+ border-color: hsl(var(--destructive) / 0.5);
135
+ background-color: hsl(var(--destructive) / 0.10);
136
+ }
137
+
138
+ /* =========================================================
77
139
  LINKS
78
- =================== */
140
+ ========================================================= */
79
141
  .auth-link {
80
142
  @apply text-sm underline font-semibold;
81
143
  color: hsl(var(--primary));
82
144
  }
83
145
 
84
- /* ===================
85
- POPOVERS
86
- =================== */
87
- .app-popover {
88
- @apply w-80 p-2 border-2;
89
- background-color: hsl(var(--card));
90
- border-color: hsl(var(--border));
91
- color: hsl(var(--card-foreground));
146
+ /* =========================================================
147
+ CHAT
148
+ ========================================================= */
149
+ .chat-date-separator {
150
+ @apply text-xs font-bold bg-muted px-3 py-1 rounded-full;
151
+ color: hsl(var(--foreground));
92
152
  }
93
153
 
94
- /* ===================
95
- ALERT DIALOGS
96
- =================== */
97
- .alert-dialog-overlay {
98
- background-color: rgba(0, 0, 0, 0.8);
154
+ /* Status pills (replaces bg-blue-100/text-blue-700 etc.) */
155
+ .status-pill {
156
+ @apply text-xs-bold px-2 py-0.5 rounded-full inline-flex items-center;
99
157
  }
100
158
 
101
- .alert-dialog-content {
102
- background-color: hsl(var(--card)) !important;
103
- border-color: hsl(var(--border)) !important;
104
- color: hsl(var(--card-foreground)) !important;
105
- @apply border-2;
159
+ .status-pill--info {
160
+ background-color: hsl(var(--info) / 0.15);
161
+ color: hsl(var(--info));
106
162
  }
107
163
 
108
- .alert-dialog-title {
109
- color: hsl(var(--foreground)) !important;
164
+ .status-pill--success {
165
+ background-color: hsl(var(--success) / 0.15);
166
+ color: hsl(var(--success));
110
167
  }
111
168
 
112
- .alert-dialog-description {
113
- color: hsl(var(--muted-foreground)) !important;
114
- @apply font-bold;
169
+ .status-pill--warning {
170
+ background-color: hsl(var(--warning) / 0.15);
171
+ color: hsl(var(--warning));
115
172
  }
116
173
 
117
- /* ===================
118
- SELECTS (GENERIC)
119
- =================== */
120
- .form-select-trigger {
121
- @apply font-semibold rounded-xl h-11 px-4 shadow-sm border-2;
174
+ .status-pill--muted {
175
+ background-color: hsl(var(--muted));
176
+ color: hsl(var(--muted-foreground));
177
+ }
178
+
179
+ /* High contrast pills: pure B/W */
180
+ .high-contrast .status-pill--info,
181
+ .high-contrast .status-pill--success,
182
+ .high-contrast .status-pill--warning,
183
+ .high-contrast .status-pill--muted {
122
184
  background-color: hsl(var(--background));
123
- border-color: hsl(var(--border)) !important;
124
185
  color: hsl(var(--foreground));
186
+ border: 2px solid hsl(var(--border));
125
187
  }
126
188
 
127
189
  /* ===================
128
- FILTER & SORT (GENERIC)
129
- =================== */
130
- .filter-select-trigger,
131
- .sort-select-trigger {
132
- @apply w-full sm:w-auto rounded-xl h-11 px-4 font-bold shadow-sm border-2;
190
+ SCREEN ADAPTIVE VIEW
191
+ =================== */
192
+ .screen-adaptive-root {
193
+ @apply flex flex-1 flex-col w-full;
194
+ }
195
+
196
+ .screen-adaptive-inner {
197
+ @apply mx-auto w-full;
198
+ }
199
+
200
+ /* Max width variants */
201
+ .screen-max-w-none { max-width: none; }
202
+ .screen-max-w-full { max-width: 100%; }
203
+
204
+ .screen-max-w-sm { max-width: 24rem; } /* 384px */
205
+ .screen-max-w-md { max-width: 28rem; } /* 448px */
206
+ .screen-max-w-lg { max-width: 32rem; } /* 512px */
207
+ .screen-max-w-xl { max-width: 36rem; } /* 576px */
208
+
209
+ .screen-max-w-2xl { max-width: 42rem; } /* 672px */
210
+ .screen-max-w-3xl { max-width: 48rem; } /* 768px */
211
+ .screen-max-w-4xl { max-width: 56rem; } /* 896px */
212
+ .screen-max-w-5xl { max-width: 64rem; } /* 1024px */
213
+ .screen-max-w-6xl { max-width: 72rem; } /* 1152px */
214
+ .screen-max-w-7xl { max-width: 80rem; } /* 1280px */
215
+
216
+ /* =========================================================
217
+ RULE CARDS
218
+ ========================================================= */
219
+ .rule-card {
220
+ @apply p-4 rounded-lg border-2 border-border bg-card;
221
+ }
222
+
223
+ .rule-card-title {
224
+ @apply font-bold mb-2;
225
+ color: hsl(var(--foreground));
226
+ }
227
+
228
+ .rule-card-description {
229
+ @apply text-sm leading-relaxed font-bold;
230
+ color: hsl(var(--muted-foreground));
231
+ }
232
+
233
+ /* =========================================================
234
+ ACCORDION
235
+ ========================================================= */
236
+ .accordion-trigger {
237
+ @apply p-6 hover:no-underline rounded-t-lg;
238
+ }
239
+
240
+ .accordion-icon-container {
241
+ @apply p-2 rounded-lg;
242
+ background-color: hsl(var(--primary) / 0.10);
243
+ color: hsl(var(--primary));
244
+ }
245
+
246
+ .accordion-title {
247
+ @apply text-lg font-semibold;
248
+ color: hsl(var(--foreground));
249
+ }
250
+
251
+ .accordion-content-container {
252
+ @apply px-6 py-4 rounded-b-lg space-y-4 bg-card;
253
+ }
254
+
255
+ /* =========================================================
256
+ DETAILS (nested accordions)
257
+ ========================================================= */
258
+ .details-summary {
259
+ @apply flex items-center justify-between cursor-pointer list-none p-4 rounded-lg border-2 border-border bg-card transition-all;
260
+ }
261
+
262
+ .details-summary:hover {
263
+ border-color: hsl(var(--primary));
264
+ background-color: hsl(var(--primary) / 0.05);
265
+ }
266
+
267
+ .details-icon-container {
268
+ @apply p-2 rounded-lg transition-colors;
269
+ background-color: hsl(var(--primary) / 0.10);
270
+ color: hsl(var(--primary));
271
+ }
272
+
273
+ .group\/details:hover .details-icon-container {
133
274
  background-color: hsl(var(--primary));
134
- border-color: hsl(var(--border));
135
275
  color: hsl(var(--primary-foreground));
136
276
  }
137
277
 
138
- .filter-select-content,
139
- .sort-select-content {
140
- background-color: hsl(var(--popover));
278
+ .details-title {
279
+ @apply font-semibold text-base;
280
+ color: hsl(var(--foreground));
281
+ }
282
+
283
+ .details-chevron {
284
+ color: hsl(var(--primary));
285
+ }
286
+
287
+ /* =========================================================
288
+ AGREEMENT LIST ITEMS
289
+ ========================================================= */
290
+ .agreement-list-item {
291
+ @apply flex gap-2 text-sm font-bold;
292
+ color: hsl(var(--muted-foreground));
293
+ }
294
+
295
+ /* =========================================================
296
+ FUTURE PLANS / MEDIA
297
+ ========================================================= */
298
+ .future-plan-description {
299
+ @apply text-base whitespace-pre-wrap leading-relaxed max-w-prose font-bold;
300
+ color: hsl(var(--muted-foreground));
301
+ }
302
+
303
+ .future-plan-media {
304
+ @apply w-full aspect-video rounded-lg overflow-hidden border;
141
305
  border-color: hsl(var(--border));
142
- color: hsl(var(--popover-foreground));
306
+ background-color: hsl(var(--muted));
143
307
  }
144
308
 
145
- .filter-select-item,
146
- .sort-select-item {
147
- @apply font-bold;
148
- color: hsl(var(--foreground));
309
+ /* Media helpers (replaces repeated w/full/max-w/aspect) */
310
+ .media-image-sm-centered {
311
+ @apply w-full h-auto max-w-sm mx-auto;
149
312
  }
150
313
 
151
- .filter-select-item:hover,
152
- .sort-select-item:hover {
153
- background-color: hsl(var(--accent));
154
- color: hsl(var(--accent-foreground));
314
+ .media-square-centered {
315
+ @apply w-full max-w-[400px] mx-auto aspect-square rounded-md overflow-hidden;
316
+ background-color: hsl(var(--muted));
155
317
  }
156
318
 
157
- /* High contrast behavior */
158
- .high-contrast .filter-select-trigger,
159
- .high-contrast .sort-select-trigger {
160
- background-color: hsl(var(--background));
319
+ .media-wide {
320
+ @apply w-full aspect-video rounded-lg overflow-hidden border;
161
321
  border-color: hsl(var(--border));
322
+ background-color: hsl(var(--muted));
323
+ }
324
+
325
+ /* =========================================================
326
+ INFO SECTIONS
327
+ ========================================================= */
328
+ .info-section {
329
+ @apply flex items-start gap-4;
330
+ }
331
+
332
+ .info-section-icon {
333
+ @apply mt-1;
334
+ color: hsl(var(--primary));
335
+ }
336
+
337
+ .info-section-title {
338
+ @apply font-semibold;
162
339
  color: hsl(var(--foreground));
163
340
  }
164
341
 
165
- .high-contrast .filter-select-content,
166
- .high-contrast .sort-select-content {
167
- background-color: hsl(var(--background));
168
- border-color: hsl(var(--border));
342
+ .info-section-description {
343
+ @apply text-sm font-bold;
344
+ color: hsl(var(--muted-foreground));
345
+ }
346
+
347
+ .info-section-divider {
348
+ @apply w-full h-px;
349
+ background-color: hsl(var(--border));
350
+ }
351
+
352
+ .info-section-header {
353
+ @apply text-lg font-semibold text-center pt-4;
169
354
  color: hsl(var(--foreground));
170
355
  }
171
356
 
172
- .high-contrast .filter-select-item:hover,
173
- .high-contrast .sort-select-item:hover {
174
- background-color: hsl(var(--foreground));
175
- color: hsl(var(--background));
357
+ /* =========================================================
358
+ ATTRIBUTION SECTIONS
359
+ ========================================================= */
360
+ .attribution-item {
361
+ @apply flex items-start gap-4;
176
362
  }
177
363
 
178
- /* ===================
179
- VIEW TOGGLE (GENERIC)
180
- =================== */
181
- .view-toggle-container {
182
- @apply flex items-center p-1 rounded-xl border-2 shadow-sm;
183
- background-color: hsl(var(--muted));
364
+ .attribution-icon {
365
+ @apply mt-1;
366
+ color: hsl(var(--primary));
367
+ }
368
+
369
+ .attribution-title {
370
+ @apply font-semibold;
371
+ color: hsl(var(--foreground));
372
+ }
373
+
374
+ .attribution-cost {
375
+ @apply text-sm font-semibold;
376
+ color: hsl(var(--primary));
377
+ }
378
+
379
+ .attribution-description {
380
+ @apply text-sm mt-1 font-bold;
381
+ color: hsl(var(--muted-foreground));
382
+ }
383
+
384
+ /* =========================================================
385
+ DEDICATION SECTIONS
386
+ ========================================================= */
387
+ .dedication-section {
388
+ @apply text-center space-y-2;
389
+ }
390
+
391
+ .dedication-header {
392
+ @apply inline-flex items-center gap-2;
393
+ }
394
+
395
+ .dedication-title {
396
+ @apply font-semibold text-lg;
397
+ color: hsl(var(--foreground));
398
+ }
399
+
400
+ .dedication-content {
401
+ @apply font-bold;
402
+ color: hsl(var(--muted-foreground));
403
+ }
404
+
405
+ /* =========================================================
406
+ DMCA INFO
407
+ ========================================================= */
408
+ .dmca-section-title {
409
+ @apply text-lg font-semibold;
410
+ color: hsl(var(--foreground));
411
+ }
412
+
413
+ .dmca-info-container {
414
+ @apply space-y-2 pl-4 border-l-2;
184
415
  border-color: hsl(var(--border));
185
416
  }
186
417
 
187
- .view-toggle-button {
188
- @apply rounded-lg h-8 w-8;
418
+ .dmca-info-row {
419
+ @apply flex flex-col sm:flex-row sm:items-center;
420
+ }
421
+
422
+ .dmca-label {
423
+ @apply w-full sm:w-40 font-semibold shrink-0;
189
424
  color: hsl(var(--foreground));
190
425
  }
191
426
 
192
- /* ===================
193
- DATE PICKER (GENERIC)
194
- =================== */
195
- .date-picker-popover {
196
- background-color: hsl(var(--card)) !important;
427
+ .dmca-value {
428
+ @apply break-all font-bold;
429
+ color: hsl(var(--muted-foreground));
430
+ }
431
+
432
+ /* =========================================================
433
+ BUTTONS
434
+ ========================================================= */
435
+ .primary-action-button {
436
+ @apply w-full text-lg py-6;
437
+ }
438
+
439
+ .secondary-action-grid {
440
+ @apply grid grid-cols-2 md:grid-cols-3 gap-4 mt-6;
441
+ }
442
+
443
+ .secondary-action-button {
444
+ @apply justify-center;
445
+ }
446
+
447
+ /* =========================================================
448
+ FOOTER
449
+ ========================================================= */
450
+ .app-footer {
451
+ @apply w-full h-12 flex-shrink-0 bg-secondary pt-4;
452
+ }
453
+
454
+ /* =========================================================
455
+ CUSTOM FORM ELEMENTS
456
+ ========================================================= */
457
+ .form-select-trigger {
458
+ @apply font-semibold rounded-xl h-11 px-4 shadow-sm border-2;
459
+ background-color: hsl(var(--background));
197
460
  border-color: hsl(var(--border)) !important;
198
- color: hsl(var(--card-foreground)) !important;
199
- @apply border-2;
461
+ color: hsl(var(--foreground));
200
462
  }
201
463
 
202
- .date-picker-caption {
203
- color: hsl(var(--foreground)) !important;
464
+ /* =========================================================
465
+ SAFE AREA UTILITIES
466
+ ========================================================= */
467
+ .fixed-header {
468
+ padding-top: max(1rem, var(--sat));
204
469
  }
205
470
 
206
- .date-picker-day-label {
207
- color: hsl(var(--muted-foreground)) !important;
208
- @apply font-bold text-center;
471
+ .fixed-footer {
472
+ padding-bottom: max(1rem, var(--sab));
209
473
  }
210
474
 
211
- .date-picker-day {
212
- color: hsl(var(--foreground)) !important;
213
- @apply font-semibold;
475
+ /* =========================================================
476
+ LANDING PAGE
477
+ ========================================================= */
478
+ .landing-tabs-list {
479
+ @apply grid w-full grid-cols-2 bg-transparent p-0 gap-2 mb-4;
214
480
  }
215
481
 
216
- .date-picker-day-today {
217
- background-color: hsl(var(--accent)) !important;
218
- color: hsl(var(--accent-foreground)) !important;
219
- @apply font-bold;
482
+ .landing-tab-trigger {
483
+ @apply flex-1;
220
484
  }
221
485
 
222
- .date-picker-day-selected {
223
- background-color: hsl(var(--primary)) !important;
224
- color: hsl(var(--primary-foreground)) !important;
225
- @apply font-bold;
486
+ .landing-section-title {
487
+ @apply text-xl font-semibold text-center;
488
+ color: hsl(var(--foreground));
226
489
  }
227
490
 
228
- .date-picker-day:hover {
229
- background-color: hsl(var(--primary) / 0.12) !important;
230
- color: hsl(var(--foreground)) !important;
491
+ .landing-section-description {
492
+ @apply text-center font-bold;
493
+ color: hsl(var(--muted-foreground));
231
494
  }
232
495
 
233
- .date-picker-day-disabled {
234
- opacity: 0.3;
235
- cursor: not-allowed;
496
+ .landing-video-container {
497
+ @apply aspect-video w-full rounded-lg overflow-hidden border;
498
+ border-color: hsl(var(--border));
499
+ background-color: hsl(var(--muted));
236
500
  }
237
501
 
238
- .date-picker-nav-button {
239
- background-color: hsl(var(--primary)) !important;
240
- color: hsl(var(--primary-foreground)) !important;
241
- border: none !important;
502
+ /* =========================================================
503
+ APP HEADER
504
+ ========================================================= */
505
+ .app-header {
506
+ @apply flex items-center h-[60px] shadow-md;
507
+ background-color: hsl(var(--secondary));
508
+ border-bottom: 2px solid hsl(var(--border));
242
509
  }
243
510
 
244
- .high-contrast .date-picker-nav-button {
245
- border: 2px solid hsl(var(--border)) !important;
511
+ .app-header-container {
512
+ @apply flex items-center justify-between w-full px-0.5;
246
513
  }
247
514
 
248
- /* ===================
249
- TOAST (Radix/shadcn-friendly)
250
- =================== */
251
- .toast-viewport {
252
- @apply fixed bottom-0 right-0 z-50 flex max-h-screen w-full flex-col p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px];
515
+ .app-header-actions {
516
+ @apply flex items-center space-x-3;
517
+ }
518
+
519
+ .app-header-menu-button {
520
+ @apply flex items-center space-x-2 h-10 px-3 rounded-full;
253
521
  }
254
522
 
255
- .toast-root {
256
- @apply relative overflow-hidden rounded-lg border-2 p-4 shadow-lg;
523
+ .app-dropdown-menu {
524
+ @apply w-56 border-2;
257
525
  background-color: hsl(var(--card));
258
526
  border-color: hsl(var(--border));
259
- color: hsl(var(--card-foreground));
260
527
  }
261
528
 
262
- .toast-root[data-variant="success"] {
263
- border-color: hsl(var(--success));
529
+ .app-dropdown-item {
530
+ @apply flex items-center cursor-pointer font-bold;
531
+ color: hsl(var(--foreground)) !important;
264
532
  }
265
533
 
266
- .toast-root[data-variant="warning"] {
267
- border-color: hsl(var(--warning));
534
+ .app-dropdown-item:hover,
535
+ .app-dropdown-item:focus {
536
+ background-color: hsl(var(--accent));
537
+ color: hsl(var(--accent-foreground)) !important;
268
538
  }
269
539
 
270
- .toast-root[data-variant="error"],
271
- .toast-root[data-variant="destructive"] {
272
- border-color: hsl(var(--destructive));
540
+ /* =========================================================
541
+ POPOVERS
542
+ ========================================================= */
543
+ .app-popover {
544
+ @apply w-80 p-2 border-2;
545
+ background-color: hsl(var(--card));
546
+ border-color: hsl(var(--border));
547
+ color: hsl(var(--card-foreground));
273
548
  }
274
549
 
275
- .toast-dismiss {
276
- @apply absolute right-2 top-2 inline-flex h-8 w-8 items-center justify-center rounded-md text-sm font-bold;
277
- background-color: transparent;
278
- color: hsl(var(--muted-foreground));
550
+ /* =========================================================
551
+ HELP DIALOG
552
+ ========================================================= */
553
+ .help-dialog-title {
554
+ @apply font-semibold;
555
+ color: hsl(var(--foreground)) !important;
279
556
  }
280
557
 
281
- .toast-dismiss:hover,
282
- .toast-dismiss:focus-visible {
283
- background-color: hsl(var(--accent));
284
- color: hsl(var(--accent-foreground));
558
+ .help-dialog-body {
559
+ font-weight: 700 !important;
560
+ color: hsl(var(--muted-foreground)) !important;
285
561
  }
286
562
 
287
- /* countdown bar (uses --toast-duration; can be overridden per-toast) */
288
- .toast-progress {
289
- @apply absolute bottom-0 left-0 h-1 w-full;
290
- background-color: hsl(var(--foreground));
291
- transform-origin: left center;
292
- animation: toast-life var(--toast-duration) linear forwards;
293
- opacity: 0.35;
563
+ @media (prefers-contrast: more) {
564
+ .help-dialog-body {
565
+ color: #ffffff !important;
566
+ }
294
567
  }
295
568
 
296
- .high-contrast .toast-progress {
297
- opacity: 1;
569
+ /* =========================================================
570
+ FILTER & SORT (GENERIC)
571
+ ========================================================= */
572
+ .filter-select-trigger,
573
+ .sort-select-trigger {
574
+ @apply w-full sm:w-auto rounded-xl h-11 px-4 font-bold shadow-sm border-2;
575
+ background-color: hsl(var(--primary));
576
+ border-color: hsl(var(--border));
577
+ color: hsl(var(--primary-foreground));
298
578
  }
299
- }
300
579
 
301
- /* Radix swipe support (works if toast root is Radix Toast.Root) */
302
- [data-swipe="move"] {
303
- transform: translateX(var(--radix-toast-swipe-move-x));
304
- }
580
+ .filter-select-content,
581
+ .sort-select-content {
582
+ background-color: hsl(var(--popover));
583
+ border-color: hsl(var(--border));
584
+ color: hsl(var(--popover-foreground));
585
+ }
305
586
 
306
- [data-swipe="cancel"] {
307
- transform: translateX(0);
308
- transition: transform 200ms ease-out;
309
- }
587
+ .filter-select-item,
588
+ .sort-select-item {
589
+ @apply font-bold;
590
+ color: hsl(var(--foreground));
591
+ }
310
592
 
311
- [data-swipe="end"] {
312
- animation: toast-swipe-out 120ms ease-out forwards;
313
- }
593
+ .filter-select-item:hover,
594
+ .sort-select-item:hover {
595
+ background-color: hsl(var(--accent));
596
+ color: hsl(var(--accent-foreground));
597
+ }
314
598
 
315
- @keyframes toast-life {
316
- from {
317
- transform: scaleX(1);
599
+ /* High contrast behavior */
600
+ .high-contrast .filter-select-trigger,
601
+ .high-contrast .sort-select-trigger {
602
+ background-color: hsl(var(--background));
603
+ border-color: hsl(var(--border));
604
+ color: hsl(var(--foreground));
605
+ }
606
+
607
+ .high-contrast .filter-select-content,
608
+ .high-contrast .sort-select-content {
609
+ background-color: hsl(var(--background));
610
+ border-color: hsl(var(--border));
611
+ color: hsl(var(--foreground));
318
612
  }
319
- to {
320
- transform: scaleX(0);
613
+
614
+ .high-contrast .filter-select-item:hover,
615
+ .high-contrast .sort-select-item:hover {
616
+ background-color: hsl(var(--foreground));
617
+ color: hsl(var(--background));
321
618
  }
322
- }
323
619
 
324
- @keyframes toast-swipe-out {
325
- from {
326
- transform: translateX(var(--radix-toast-swipe-end-x));
327
- opacity: 1;
620
+ /* =========================================================
621
+ VIEW TOGGLE (GENERIC)
622
+ ========================================================= */
623
+ .view-toggle-container {
624
+ @apply flex items-center p-1 rounded-xl border-2 shadow-sm;
625
+ background-color: hsl(var(--muted));
626
+ border-color: hsl(var(--border));
328
627
  }
329
- to {
330
- transform: translateX(calc(var(--radix-toast-swipe-end-x) * 1.2));
331
- opacity: 0;
628
+
629
+ .view-toggle-button {
630
+ @apply rounded-lg h-8 w-8;
631
+ color: hsl(var(--foreground));
332
632
  }
333
633
  }
@@ -1,37 +1,30 @@
1
1
  @layer base {
2
2
  :root {
3
- /* Loud fallbacks: if you see this color, the app did not define required brand contract */
3
+ /* Loud fallbacks: if you see this, app did NOT define required brand tokens */
4
4
  --brand-primary: 999 100% 50%;
5
5
  --brand-secondary: 999 100% 50%;
6
6
  --brand-accent: 999 100% 50%;
7
7
 
8
- /* Always-available neutrals (theme-core owned) */
8
+ /* Status tokens: OPTIONAL (sane defaults) */
9
+ --status-success: 140 70% 45%;
10
+ --status-warning: 45 90% 50%;
11
+ --status-error: 0 84% 60%;
12
+ --status-info: 221 83% 53%;
13
+
14
+ /* Neutrals */
9
15
  --neutral-white: 0 0% 100%;
10
16
  --neutral-black: 0 0% 0%;
11
-
12
- /* OPTIONAL status colors (apps can override) */
13
- --color-for-success: 142 71% 45%;
14
- --color-for-warning: 38 92% 50%;
15
- --color-for-error: 0 84% 60%;
16
-
17
- /* Mapped status tokens used by theme-core */
18
- --status-success: var(--color-for-success);
19
- --status-warning: var(--color-for-warning);
20
- --status-error: var(--color-for-error);
21
17
  }
22
18
 
23
- /* High contrast must be pure B/W (prevents bleed from any app colors) */
19
+ /* High contrast must be pure B/W: override brand + status tokens too (prevents bleed) */
24
20
  .high-contrast {
25
21
  --brand-primary: 0 0% 0%;
26
22
  --brand-secondary: 0 0% 0%;
27
23
  --brand-accent: 0 0% 100%;
28
24
 
29
- --color-for-success: 0 0% 0%;
30
- --color-for-warning: 0 0% 0%;
31
- --color-for-error: 0 0% 0%;
32
-
33
25
  --status-success: 0 0% 0%;
34
26
  --status-warning: 0 0% 0%;
35
27
  --status-error: 0 0% 0%;
28
+ --status-info: 0 0% 0%;
36
29
  }
37
30
  }
@@ -0,0 +1,94 @@
1
+
2
+ @layer components {
3
+ /* ===================
4
+ BUTTONS
5
+ =================== */
6
+ .btn-destructive {
7
+ @apply bg-destructive text-destructive-foreground hover:bg-destructive/90;
8
+ }
9
+
10
+ /* ===================
11
+ MESSAGE BUBBLES
12
+ =================== */
13
+ .msg-bubble {
14
+ @apply p-3 rounded-lg;
15
+ }
16
+
17
+ .msg-bubble--mine {
18
+ background-color: hsl(var(--primary) / 0.10);
19
+ }
20
+
21
+ .msg-bubble--theirs {
22
+ @apply bg-muted;
23
+ }
24
+
25
+ /* ===================
26
+ STATUS PILLS
27
+ =================== */
28
+ .status-pill {
29
+ @apply text-xs-bold px-2 py-0.5 rounded-full;
30
+ }
31
+
32
+ /* map to semantic tokens (no blue/yellow/green hardcodes) */
33
+ .status-pill--open-user {
34
+ background-color: hsl(var(--info) / 0.15);
35
+ color: hsl(var(--info-foreground));
36
+ }
37
+
38
+ .status-pill--admin-reply {
39
+ background-color: hsl(var(--warning) / 0.20);
40
+ color: hsl(var(--warning-foreground));
41
+ }
42
+
43
+ .status-pill--user-reply {
44
+ background-color: hsl(var(--success) / 0.18);
45
+ color: hsl(var(--success-foreground));
46
+ }
47
+
48
+ .status-pill--closed {
49
+ @apply bg-muted text-muted-foreground;
50
+ }
51
+
52
+ .status-pill--default {
53
+ @apply bg-muted text-muted-foreground;
54
+ }
55
+
56
+ /* ===================
57
+ STATUS ICONS
58
+ =================== */
59
+ .status-icon {
60
+ @apply h-5 w-5;
61
+ }
62
+
63
+ .status-icon--success { color: hsl(var(--success)); }
64
+ .status-icon--warning { color: hsl(var(--warning)); }
65
+ .status-icon--info { color: hsl(var(--info)); }
66
+ .status-icon--error { color: hsl(var(--destructive)); }
67
+
68
+ /* ===================
69
+ NOTIFICATIONS
70
+ =================== */
71
+ .notify-dot {
72
+ @apply absolute top-1 right-1 h-2 w-2 rounded-full;
73
+ background-color: hsl(var(--destructive));
74
+ }
75
+
76
+ .notify-empty-icon {
77
+ color: hsl(var(--success));
78
+ }
79
+
80
+ /* ===================
81
+ MEDIA PREVIEW
82
+ =================== */
83
+ .media-preview {
84
+ @apply relative w-full h-full;
85
+ }
86
+
87
+ .media-preview--frame {
88
+ @apply w-full h-auto max-w-sm mx-auto;
89
+ }
90
+
91
+ .media-preview--fullwidth {
92
+ @apply w-full h-auto;
93
+ }
94
+ }
@@ -1,4 +1,5 @@
1
1
  @import "./contract.css";
2
2
  @import "./tokens.css";
3
3
  @import "./base.css";
4
+ @import "./hooks.css";
4
5
  /* components.css is a separate entrypoint: @ttt-productions/theme-core/components.css */
@@ -11,7 +11,7 @@
11
11
  --popover-foreground: var(--neutral-black);
12
12
 
13
13
  --muted: 0 0% 95%;
14
- --muted-foreground: var(--neutral-black);
14
+ --muted-foreground: 0 0% 25%;
15
15
 
16
16
  --accent: var(--brand-accent);
17
17
  --accent-foreground: var(--neutral-black);
@@ -22,31 +22,27 @@
22
22
  --secondary: var(--brand-secondary);
23
23
  --secondary-foreground: var(--neutral-white);
24
24
 
25
- /* canonical shadcn name */
26
25
  --destructive: var(--status-error);
27
26
  --destructive-foreground: var(--neutral-white);
28
27
 
29
- /* extra semantic status tokens */
28
+ /* Extra semantic status colors (used by pills/toasts/etc.) */
30
29
  --success: var(--status-success);
31
30
  --success-foreground: var(--neutral-white);
32
31
 
33
32
  --warning: var(--status-warning);
34
33
  --warning-foreground: var(--neutral-black);
35
34
 
36
- --error: var(--status-error);
37
- --error-foreground: var(--neutral-white);
35
+ --info: var(--status-info);
36
+ --info-foreground: var(--neutral-white);
38
37
 
39
38
  --border: var(--brand-primary);
40
39
  --ring: var(--brand-primary);
41
40
 
42
41
  --radius: 1rem;
43
-
44
- /* toast defaults (overridable per-toast via inline CSS var) */
45
- --toast-duration: 5000ms;
46
42
  }
47
43
 
48
44
  .dark {
49
- /* Keep semantic token mapping; apps can override brand tokens per-mode if they want */
45
+ /* Dark base (brand tokens are still app-controlled) */
50
46
  --background: 240 6% 10%;
51
47
  --foreground: 0 0% 100%;
52
48
 
@@ -57,16 +53,15 @@
57
53
  --popover-foreground: 0 0% 100%;
58
54
 
59
55
  --muted: 240 4% 20%;
60
- --muted-foreground: 0 0% 100%;
56
+ --muted-foreground: 0 0% 85%;
61
57
 
62
58
  --border: 0 0% 100%;
63
59
  --ring: 0 0% 100%;
64
60
 
65
- /* status foregrounds in dark */
66
- --destructive-foreground: 0 0% 100%;
67
- --success-foreground: 0 0% 100%;
61
+ /* status foregrounds still reasonable in dark */
62
+ --success-foreground: 0 0% 0%;
68
63
  --warning-foreground: 0 0% 0%;
69
- --error-foreground: 0 0% 100%;
64
+ --info-foreground: 0 0% 0%;
70
65
  }
71
66
 
72
67
  .high-contrast {
@@ -101,8 +96,8 @@
101
96
  --warning: 0 0% 100%;
102
97
  --warning-foreground: 0 0% 0%;
103
98
 
104
- --error: 0 0% 100%;
105
- --error-foreground: 0 0% 0%;
99
+ --info: 0 0% 100%;
100
+ --info-foreground: 0 0% 0%;
106
101
 
107
102
  --border: 0 0% 100%;
108
103
  --ring: 0 0% 100%;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttt-productions/theme-core",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "Theme provider + CSS token contract for TTT Productions apps",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",