andy-note-nuxt 0.2.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.
@@ -0,0 +1,609 @@
1
+ /* =================================================================
2
+ * andy-note-nuxt — brutalist terminal theme
3
+ * Tailwind v3 base + custom @layer additions for prose / list rows.
4
+ * Tokens defined in tailwind.config.js; CSS vars below are kept only
5
+ * for inline-style usage in stacked-column layout (--column-width etc.)
6
+ * ================================================================= */
7
+
8
+ /* Fonts — @import MUST precede @tailwind directives per CSS spec.
9
+ Local @fontsource packages = self-host (no FOUT, no third-party request). */
10
+ @import "@fontsource/space-grotesk/300.css";
11
+ @import "@fontsource/space-grotesk/400.css";
12
+ @import "@fontsource/space-grotesk/500.css";
13
+ @import "@fontsource/space-grotesk/600.css";
14
+ @import "@fontsource/space-grotesk/700.css";
15
+ @import "@fontsource/literata/400.css";
16
+ @import "@fontsource/literata/400-italic.css";
17
+ @import "@fontsource/literata/600.css";
18
+ @import "@fontsource/literata/700.css";
19
+
20
+ @tailwind base;
21
+ @tailwind components;
22
+ @tailwind utilities;
23
+
24
+ @layer base {
25
+ /* Layout/spacing tokens that components reference via inline style. */
26
+ :root {
27
+ --column-width: 670px;
28
+ --column-min-width: 540px;
29
+ --content-width: 720px;
30
+ --content-width-wide: 960px;
31
+
32
+ /* Width of the peek strip when an earlier column is sticky-stacked at
33
+ the left edge (Andy Matuschak / Stripe-docs pattern). 48px = visible
34
+ border + a few characters of section header, and ≥ minimum tap target
35
+ (44px) so peek strips are clickable on touch devices. */
36
+ --stack-peek: 48px;
37
+
38
+ --space-1: 0.25rem;
39
+ --space-2: 0.5rem;
40
+ --space-3: 0.75rem;
41
+ --space-4: 1rem;
42
+ --space-5: 1.5rem;
43
+ --space-6: 2rem;
44
+ --space-7: 2.5rem;
45
+ --space-8: 3rem;
46
+ }
47
+
48
+ *, *::before, *::after { box-sizing: border-box; }
49
+ * { margin: 0; padding: 0; }
50
+
51
+ html {
52
+ -webkit-text-size-adjust: 100%;
53
+ scroll-behavior: smooth;
54
+ }
55
+
56
+ body {
57
+ @apply bg-terminal-bg text-terminal-text font-display;
58
+ -webkit-font-smoothing: antialiased;
59
+ -moz-osx-font-smoothing: grayscale;
60
+ text-rendering: optimizeLegibility;
61
+ min-height: 100vh;
62
+ }
63
+
64
+ h1, h2, h3, h4, h5, h6 {
65
+ @apply font-display font-bold uppercase tracking-tight;
66
+ }
67
+
68
+ ::selection { @apply bg-primary text-terminal-bg; }
69
+ ::-moz-selection { @apply bg-primary text-terminal-bg; }
70
+
71
+ /* Thin scrollbars with coral hover — matches the terminal accent. */
72
+ * {
73
+ scrollbar-width: thin;
74
+ scrollbar-color: theme('colors.terminal.border') transparent;
75
+ }
76
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
77
+ ::-webkit-scrollbar-track { @apply bg-transparent; }
78
+ ::-webkit-scrollbar-thumb { @apply bg-terminal-border; }
79
+ ::-webkit-scrollbar-thumb:hover { @apply bg-primary; }
80
+ ::-webkit-scrollbar-corner { @apply bg-transparent; }
81
+
82
+ img, svg, video { max-width: 100%; height: auto; display: block; }
83
+ button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
84
+ input, select, textarea { font: inherit; color: inherit; }
85
+
86
+ /* Tabular numerals for stat tables, prices, comparison columns. */
87
+ table, time, code, .tabular-nums {
88
+ font-variant-numeric: tabular-nums;
89
+ }
90
+ }
91
+
92
+ @layer components {
93
+ /* ---------- Brutalist primitives ---------- */
94
+
95
+ /* Section header pinned above the column's scroll body via flex layout.
96
+ Lives outside the overflow container, so the scrollbar never overlaps it. */
97
+ .section-card-header {
98
+ @apply px-4 py-3 border-b-[3px] border-terminal-border bg-terminal-bg;
99
+ }
100
+
101
+ /* Copy + AI-deep-link split button — true button-group pattern. The
102
+ outer `.copy-actions` wrapper owns the border, background, and focus
103
+ stamp-shadow; child `.copy-btn` halves are border-less segments
104
+ separated only by an internal vertical divider. This eliminates the
105
+ double-border seam that earlier `margin: -1px` hacks couldn't fully
106
+ hide. Primary half carries the "Copy" / "Copied" / "Failed" text
107
+ label; `.copy-btn--menu` is the attached caret half opening
108
+ `.copy-menu`. `data-state` flips the primary half to a filled
109
+ coral affordance during the brief success window. */
110
+ .copy-actions {
111
+ @apply relative inline-flex items-stretch shrink-0 border border-terminal-border bg-terminal-bg transition-colors;
112
+ }
113
+ /* Group-level focus ring — single stamp shadow on the wrapper instead
114
+ of per-button shadows, so the focused half doesn't "lift" away from
115
+ its sibling and break the fused appearance. */
116
+ .copy-actions:focus-within {
117
+ @apply border-primary;
118
+ box-shadow: 2px 2px 0 0 theme('colors.primary');
119
+ }
120
+ /* Borderless segment. Width is fixed at the widest label ("Copied" /
121
+ "Failed", 6 chars in mono bold 10px) so "Copy" doesn't reflow when
122
+ state flips and the pair stays balanced with the icon-narrow caret. */
123
+ .copy-btn {
124
+ @apply inline-flex items-center justify-center text-terminal-text-secondary cursor-pointer transition-colors;
125
+ background: transparent;
126
+ border: 0;
127
+ height: 22px;
128
+ width: 48px;
129
+ padding: 0;
130
+ }
131
+ /* Internal divider — paints on the trailing edge of every segment
132
+ except the last, so it shows once between Copy and the caret half
133
+ and never leaks outside the group. */
134
+ .copy-btn:not(:last-child) {
135
+ border-right: 1px solid theme('colors.terminal.border');
136
+ }
137
+ .copy-btn--menu {
138
+ width: 22px;
139
+ }
140
+ .copy-btn__label {
141
+ @apply font-mono font-bold uppercase tracking-tight;
142
+ font-size: 10px;
143
+ line-height: 1;
144
+ }
145
+ .copy-btn__caret {
146
+ width: 10px;
147
+ height: 7px;
148
+ display: block;
149
+ transition: transform 140ms ease;
150
+ }
151
+ .copy-btn__caret--open {
152
+ transform: rotate(180deg);
153
+ }
154
+ .copy-btn:hover,
155
+ .copy-btn[aria-expanded='true'] {
156
+ @apply text-primary;
157
+ }
158
+ .copy-btn:focus-visible {
159
+ @apply outline-none text-primary;
160
+ }
161
+ .copy-btn[data-state='copied'] {
162
+ @apply bg-primary text-terminal-bg;
163
+ }
164
+ .copy-btn[data-state='error'] {
165
+ @apply text-terminal-text-muted;
166
+ }
167
+
168
+ /* Dropdown menu — sharp-edged, stamp-shadow, mono. Teleported to <body>
169
+ so it escapes any column overflow clip; positioning comes from inline
170
+ styles written by Floating-UI's `useFloating`. We only own the visual
171
+ surface (border, shadow, palette, sizing) — never the coords. z-index
172
+ sits above stacked-column borders, which top out near 20–30 in practice. */
173
+ .copy-menu {
174
+ @apply bg-terminal-bg border-2 border-terminal-border;
175
+ position: absolute;
176
+ min-width: 168px;
177
+ box-shadow: 4px 4px 0 0 theme('colors.primary');
178
+ z-index: 100;
179
+ }
180
+ .copy-menu__item {
181
+ @apply flex items-center gap-2 px-3 py-2 font-mono text-[11px] font-bold uppercase tracking-widest text-terminal-text transition-colors no-underline;
182
+ }
183
+ .copy-menu__item + .copy-menu__item {
184
+ @apply border-t border-terminal-border;
185
+ }
186
+ .copy-menu__item:hover {
187
+ @apply bg-primary text-terminal-bg;
188
+ }
189
+ .copy-menu__arrow {
190
+ @apply text-terminal-text-faint;
191
+ }
192
+ .copy-menu__item:hover .copy-menu__arrow {
193
+ @apply text-terminal-bg;
194
+ }
195
+
196
+ /* Dotted leader (between list-row title and counter). 2px dashes,
197
+ positioned slightly above baseline so it visually aligns with letter midline. */
198
+ .dotted-leader {
199
+ flex-grow: 1;
200
+ border-bottom: 2px dotted theme('colors.terminal.border');
201
+ margin: 0 0.75rem;
202
+ position: relative;
203
+ top: -4px;
204
+ }
205
+
206
+ /* Hover-stamp effect on list items — outline + offset shadow on hover. */
207
+ .terminal-item:hover .title-text {
208
+ outline: 2px solid theme('colors.primary');
209
+ box-shadow: 4px 4px 0px 0px theme('colors.primary');
210
+ background: transparent;
211
+ }
212
+
213
+ /* Stacked-column trail highlight — when a list row's target path is open
214
+ as a deeper column in the stack, mark it with persistent filled bg so
215
+ the user can see which row led to which column (Miller-column UX). */
216
+ .terminal-item--active .title-text {
217
+ @apply bg-primary text-terminal-bg;
218
+ }
219
+ .terminal-item--active .dotted-leader {
220
+ border-bottom-color: theme('colors.primary');
221
+ }
222
+ .terminal-item--active:hover .title-text {
223
+ /* Hover on already-active item: keep filled bg + inverted text, add offset
224
+ shadow as click-affordance hint. Must re-declare bg/color because the
225
+ generic `.terminal-item:hover .title-text` rule has equal specificity
226
+ and resets `background: transparent` — without these, text becomes
227
+ terminal-bg on transparent (= invisible against the dark page). */
228
+ @apply bg-primary text-terminal-bg;
229
+ outline: 2px solid theme('colors.primary');
230
+ box-shadow: 4px 4px 0px 0px theme('colors.primary');
231
+ }
232
+
233
+ /* List row used in section listings (sections + articles). */
234
+ .list-row {
235
+ @apply flex flex-col gap-1 py-3 px-4 border-b border-terminal-border transition-colors;
236
+ }
237
+ .list-row:hover {
238
+ @apply bg-terminal-surface-0;
239
+ }
240
+ .list-row__title {
241
+ @apply text-base font-bold uppercase tracking-tight text-terminal-text transition-colors;
242
+ }
243
+ .list-row:hover .list-row__title {
244
+ @apply text-primary;
245
+ }
246
+ .list-row__description {
247
+ @apply text-sm text-terminal-text-muted normal-case;
248
+ font-family: 'Literata', Georgia, serif;
249
+ text-transform: none;
250
+ letter-spacing: 0;
251
+ }
252
+ .list-row__meta {
253
+ @apply text-[10px] text-terminal-text-faint uppercase tracking-widest font-mono mt-1 flex flex-wrap gap-x-3;
254
+ }
255
+
256
+ /* Tag badge — bracketed, mono, hover coral. */
257
+ .tag-badge {
258
+ @apply inline-block text-[10px] font-bold font-mono uppercase tracking-widest px-2 py-1 border-2 border-terminal-border text-terminal-text-secondary transition-colors;
259
+ }
260
+ .tag-badge::before {
261
+ content: '#';
262
+ @apply text-terminal-text-faint mr-0.5;
263
+ }
264
+ .tag-badge:hover {
265
+ @apply border-primary text-primary;
266
+ }
267
+ .tag-badge--active {
268
+ @apply bg-primary text-terminal-bg border-primary;
269
+ }
270
+ .tag-badge--active::before {
271
+ @apply text-terminal-bg;
272
+ }
273
+
274
+ /* Section heading inside list-view (e.g. "Sections" / "Articles"). The
275
+ leading icon (clock / folder / document) is inlined as SVG in the
276
+ template so each section gets a semantic glyph instead of a generic
277
+ coral square. */
278
+ .section-heading {
279
+ @apply text-xs font-bold uppercase tracking-widest-lg text-terminal-text-muted mt-8 mb-3 pb-2 border-b border-terminal-border flex items-center gap-2;
280
+ }
281
+ .section-heading__icon {
282
+ @apply text-primary shrink-0;
283
+ width: 14px;
284
+ height: 14px;
285
+ display: block;
286
+ }
287
+
288
+ /* Meta row (author · date · tags) — separated by middle dot. */
289
+ .meta {
290
+ @apply flex flex-wrap gap-x-4 gap-y-1 text-xs text-terminal-text-muted font-mono uppercase tracking-wider;
291
+ }
292
+ .meta > * + *::before {
293
+ content: '·';
294
+ @apply text-terminal-text-faint mr-2;
295
+ }
296
+ .meta > * + * {
297
+ margin-inline-start: -1rem;
298
+ padding-inline-start: 1rem;
299
+ }
300
+
301
+ /* ---------- Long-form prose (.content rendered markdown) ---------- */
302
+ /* Applied to <ContentRenderer> output — h2/h3/p/ul/ol/code/pre/table generated
303
+ from markdown. Literata serif body for readability, brutalist treatment for
304
+ code/tables/lists. */
305
+ .content {
306
+ @apply text-terminal-text;
307
+ font-family: 'Literata', Georgia, serif;
308
+ font-size: 1.0625rem;
309
+ line-height: 1.65;
310
+ letter-spacing: 0.008em;
311
+ }
312
+
313
+ .content > * + * { margin-top: 1.5rem; }
314
+
315
+ .content h1 {
316
+ @apply font-display font-bold uppercase tracking-tight text-2xl md:text-3xl mt-10 mb-4;
317
+ }
318
+ .content h2 {
319
+ @apply font-display font-bold uppercase tracking-tight text-xl md:text-2xl mt-10 mb-4;
320
+ font-family: 'Space Grotesk', sans-serif;
321
+ }
322
+ .content h3 {
323
+ @apply font-display font-bold uppercase tracking-tight text-base md:text-lg mt-8 mb-3;
324
+ font-family: 'Space Grotesk', sans-serif;
325
+ }
326
+ .content h4, .content h5, .content h6 {
327
+ @apply font-display font-bold uppercase tracking-widest text-xs text-terminal-text-muted mt-6 mb-2;
328
+ }
329
+
330
+ .content p { @apply my-4; }
331
+
332
+ .content a {
333
+ @apply text-primary transition-colors;
334
+ text-decoration: none;
335
+ }
336
+ .content a:hover {
337
+ @apply text-terminal-accent-hover;
338
+ text-decoration: underline;
339
+ text-decoration-style: wavy;
340
+ text-decoration-thickness: 1px;
341
+ text-underline-offset: 3px;
342
+ }
343
+
344
+ .content strong {
345
+ @apply text-terminal-text font-semibold;
346
+ /* Explicit text-decoration to ensure wavy underline inherits correctly
347
+ when <a> wraps <strong> */
348
+ text-decoration: inherit;
349
+ text-decoration-color: inherit;
350
+ text-decoration-style: inherit;
351
+ text-underline-offset: inherit;
352
+ }
353
+ /* Ensure strong inside links explicitly inherits the underline */
354
+ .content a strong {
355
+ text-decoration: underline;
356
+ text-decoration-style: wavy;
357
+ text-decoration-color: currentColor;
358
+ text-underline-offset: 3px;
359
+ }
360
+ .content em { font-style: italic; }
361
+
362
+ /* Lists — top level uses heavy brutalist markers (coral square, decimal-leading-zero
363
+ counter). Nested levels strip the box/shadow/zero-pad chrome and tighten padding,
364
+ because in stacked columns 540-640px wide, every depth was eating ~2-2.5rem of
365
+ padding plus a repeating stamp — three levels deep left almost nothing for prose. */
366
+ .content ul, .content ol {
367
+ @apply my-4 space-y-2 list-none pl-0;
368
+ }
369
+ .content li {
370
+ @apply pl-7 relative;
371
+ line-height: 1.6;
372
+ }
373
+ .content ul li::before {
374
+ content: '';
375
+ @apply absolute left-0 top-2 w-3 h-3 bg-primary border-2 border-terminal-border;
376
+ box-shadow: 2px 2px 0px theme('colors.terminal.border');
377
+ }
378
+ .content ol {
379
+ counter-reset: terminal-counter;
380
+ }
381
+ .content ol li {
382
+ counter-increment: terminal-counter;
383
+ @apply pl-10;
384
+ }
385
+ .content ol li::before {
386
+ content: counter(terminal-counter, decimal-leading-zero);
387
+ @apply absolute left-0 top-1 inline-flex items-center justify-center bg-terminal-surface-0 text-primary border-2 border-terminal-border text-xs font-bold font-display;
388
+ width: 1.6rem;
389
+ height: 1.3rem;
390
+ box-shadow: 2px 2px 0px theme('colors.terminal.border');
391
+ font-family: 'Space Grotesk', sans-serif;
392
+ }
393
+
394
+ /* Nested lists (depth ≥ 2): drop the box stamp, switch to flat text markers,
395
+ trim padding and vertical rhythm. Selectors `.content li ul/ol li` only match
396
+ items inside an outer <li>, so the top-level rules above stay untouched. */
397
+ .content li ul, .content li ol {
398
+ @apply my-1 space-y-1 pl-0;
399
+ }
400
+ .content li ul li,
401
+ .content li ol li {
402
+ padding-left: 1.25rem;
403
+ line-height: 1.55;
404
+ }
405
+ .content li ul li::before {
406
+ content: '›';
407
+ background: transparent;
408
+ border: 0;
409
+ box-shadow: none;
410
+ width: auto;
411
+ height: auto;
412
+ color: theme('colors.terminal.text-muted');
413
+ font-family: 'SF Mono', Monaco, Consolas, monospace;
414
+ font-weight: 700;
415
+ font-size: 1em;
416
+ top: 0;
417
+ left: 0.25rem;
418
+ line-height: inherit;
419
+ display: inline;
420
+ }
421
+ .content li ol li {
422
+ padding-left: 1.6rem;
423
+ }
424
+ .content li ol li::before {
425
+ content: counter(terminal-counter) '.';
426
+ background: transparent;
427
+ border: 0;
428
+ box-shadow: none;
429
+ width: auto;
430
+ height: auto;
431
+ padding: 0;
432
+ color: theme('colors.terminal.text-muted');
433
+ font-family: 'SF Mono', Monaco, Consolas, monospace;
434
+ font-weight: 700;
435
+ font-size: 0.85em;
436
+ top: 0.15rem;
437
+ left: 0;
438
+ display: inline;
439
+ line-height: inherit;
440
+ }
441
+
442
+ /* Blockquote — bg + italic carry the visual cue; no border/shadow chrome. */
443
+ .content blockquote {
444
+ @apply bg-terminal-surface-0 p-4 my-6 italic text-terminal-text-secondary;
445
+ }
446
+ .content blockquote p { @apply mb-0; }
447
+ .content blockquote p:first-child { @apply mt-0; }
448
+
449
+ /* Code — brutalist terminal aesthetic
450
+ Inline: "inverted tag" look with stamp shadow, muted text (no coral)
451
+ Blocks: coral rail accent + muted text for readability */
452
+ .content code:not(pre code) {
453
+ @apply bg-terminal-surface-0 text-terminal-text-secondary px-1.5 py-0.5 text-[0.85em] border border-terminal-border-strong;
454
+ font-family: 'SF Mono', Monaco, Consolas, monospace;
455
+ border-radius: 0;
456
+ white-space: nowrap;
457
+ box-shadow: 2px 2px 0px 0px theme('colors.terminal.border');
458
+ transition: all 0.08s ease-out;
459
+ }
460
+ .content code:not(pre code):hover {
461
+ @apply border-primary text-terminal-text;
462
+ box-shadow: 2px 2px 0px 0px theme('colors.primary');
463
+ }
464
+ .content pre {
465
+ @apply bg-terminal-surface-0 overflow-x-auto my-6 text-sm relative border border-terminal-border;
466
+ font-family: 'SF Mono', Monaco, Consolas, monospace;
467
+ line-height: 1.6;
468
+ border-radius: 0;
469
+ padding: 1rem 1.25rem;
470
+ box-shadow: 4px 4px 0px 0px theme('colors.terminal.border');
471
+ }
472
+ /* Lime accent rail on the left edge — terminal-cursor vibe. */
473
+ .content pre::before {
474
+ content: '';
475
+ @apply absolute left-0 top-0 bottom-0 w-1 bg-primary;
476
+ }
477
+ .content pre code {
478
+ @apply bg-transparent p-0 border-0 text-terminal-text-secondary;
479
+ font-size: inherit;
480
+ white-space: pre;
481
+ }
482
+
483
+ /* Tables — internal grid with cell padding. Edge cells flush horizontally
484
+ (leftmost: no pl, rightmost: no pr) and at the bottom (last tbody row: no
485
+ pb), but th keeps balanced vertical padding because the bg highlight needs
486
+ breathing room above the label. Saves horizontal space inside narrow
487
+ stacked columns while keeping internal cells legible. */
488
+ .content table {
489
+ @apply w-full border-collapse my-6 text-sm;
490
+ }
491
+ .content thead {
492
+ @apply border-b border-terminal-border;
493
+ }
494
+ .content th {
495
+ @apply bg-terminal-surface-0 font-bold font-display uppercase tracking-wider text-[11px] text-terminal-text-secondary;
496
+ @apply text-left align-bottom px-3 py-2 border-r border-terminal-border;
497
+ }
498
+ .content th:first-child { padding-left: 0; }
499
+ .content th:last-child { padding-right: 0; border-right: 0; }
500
+ .content td {
501
+ @apply text-left align-top px-3 py-2 border-r border-b border-terminal-border;
502
+ }
503
+ .content td:first-child { padding-left: 0; }
504
+ .content td:last-child { padding-right: 0; border-right: 0; }
505
+ .content tbody tr:last-child td { padding-bottom: 0; border-bottom: 0; }
506
+ .content tbody tr:hover td { @apply bg-terminal-surface-0; }
507
+
508
+ .content hr {
509
+ @apply border-0 my-10 h-0.5;
510
+ background: linear-gradient(
511
+ to right,
512
+ transparent,
513
+ theme('colors.terminal.border'),
514
+ transparent
515
+ );
516
+ }
517
+
518
+ .content img {
519
+ @apply w-full h-auto my-6 border-2 border-terminal-border;
520
+ box-shadow: 4px 4px 0px 0px theme('colors.terminal.border');
521
+ }
522
+
523
+ .content kbd {
524
+ @apply bg-terminal-surface-0 border border-terminal-border-strong text-terminal-text px-1.5 py-0.5 text-xs;
525
+ font-family: 'SF Mono', Monaco, Consolas, monospace;
526
+ border-bottom-width: 2px;
527
+ }
528
+ }
529
+
530
+ @layer utilities {
531
+ .border-3 { border-width: 3px; }
532
+ }
533
+
534
+ /* Focus ring — accent outline + offset stamp. */
535
+ :focus-visible {
536
+ outline: 2px solid theme('colors.primary');
537
+ outline-offset: 2px;
538
+ }
539
+
540
+ /* Reduced motion */
541
+ @media (prefers-reduced-motion: reduce) {
542
+ *, *::before, *::after {
543
+ animation-duration: 0.01ms !important;
544
+ animation-iteration-count: 1 !important;
545
+ transition-duration: 0.01ms !important;
546
+ }
547
+ }
548
+
549
+ @media (max-width: 640px) {
550
+ .content { font-size: 1rem; line-height: 1.6; }
551
+ .terminal-item:hover .title-text {
552
+ outline: none;
553
+ box-shadow: none;
554
+ }
555
+ }
556
+
557
+ /* ---------- Brutalist toaster (vue-sonner) ----------
558
+ vue-sonner ships its own CSS via `vue-sonner/style.css` (loaded by the
559
+ nuxt module). We override the exposed CSS variables + a few structural
560
+ props so toasts look like the rest of the surface: sharp corners, stamp
561
+ offset shadow, monospace, terminal palette. Selectors target the
562
+ `data-sonner-*` attribute tree so they win over the package defaults
563
+ without `!important`. */
564
+ [data-sonner-toaster] {
565
+ --border-radius: 0;
566
+ --normal-bg: theme('colors.terminal.surface.0');
567
+ --normal-border: theme('colors.terminal.border');
568
+ --normal-text: theme('colors.terminal.text');
569
+ --success-bg: theme('colors.terminal.surface.0');
570
+ --success-border: theme('colors.primary');
571
+ --success-text: theme('colors.terminal.text');
572
+ --error-bg: theme('colors.terminal.surface.0');
573
+ --error-border: theme('colors.terminal.text-muted');
574
+ --error-text: theme('colors.terminal.text');
575
+ font-family: theme('fontFamily.display');
576
+ }
577
+ [data-sonner-toaster] [data-sonner-toast][data-styled='true'] {
578
+ border-radius: 0;
579
+ border-width: 2px;
580
+ box-shadow: 4px 4px 0 0 theme('colors.terminal.border');
581
+ padding: 14px 16px;
582
+ }
583
+ [data-sonner-toaster] [data-sonner-toast][data-styled='true'][data-type='success'] {
584
+ box-shadow: 4px 4px 0 0 theme('colors.primary');
585
+ }
586
+ [data-sonner-toaster] [data-sonner-toast][data-styled='true'][data-type='error'] {
587
+ box-shadow: 4px 4px 0 0 theme('colors.terminal.text-muted');
588
+ }
589
+ [data-sonner-toaster] [data-sonner-toast] [data-title] {
590
+ font-weight: 700;
591
+ text-transform: uppercase;
592
+ letter-spacing: 0.02em;
593
+ font-size: 12px;
594
+ }
595
+ [data-sonner-toaster] [data-sonner-toast] [data-description] {
596
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
597
+ font-size: 11px;
598
+ color: theme('colors.terminal.text-muted') !important;
599
+ margin-top: 2px;
600
+ letter-spacing: 0.01em;
601
+ }
602
+ /* Icon column — recolor the built-in success/error SVG so it tracks our palette
603
+ instead of the package's saturated greens/reds. */
604
+ [data-sonner-toaster] [data-sonner-toast][data-type='success'] [data-icon] {
605
+ color: theme('colors.primary');
606
+ }
607
+ [data-sonner-toaster] [data-sonner-toast][data-type='error'] [data-icon] {
608
+ color: theme('colors.terminal.text-muted');
609
+ }