@roottale/cms-renderer-next 0.22.0 → 0.25.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.
@@ -36,9 +36,9 @@
36
36
  align-items: center;
37
37
  padding: 0.4375rem 0.875rem;
38
38
  border-radius: 999px;
39
- border: 1px solid color-mix(in srgb, var(--rt-color-border, #e5e7eb) 82%, transparent);
40
- background: color-mix(in srgb, var(--rt-color-muted, #f8fafc) 60%, white);
41
- color: color-mix(in srgb, var(--rt-color-foreground, #111827) 76%, transparent);
39
+ border: 1px solid color-mix(in srgb, var(--rt-color-border, #dceef3) 82%, transparent);
40
+ background: color-mix(in srgb, var(--rt-color-muted, #f7f8f7) 60%, white);
41
+ color: color-mix(in srgb, var(--rt-color-foreground, #06162f) 76%, transparent);
42
42
  font-family: var(--rt-font-body, system-ui, sans-serif);
43
43
  font-size: 0.8125rem;
44
44
  font-weight: 700;
@@ -52,13 +52,13 @@
52
52
 
53
53
  [data-roottale-cms] :where(.rt-cms-filter-chip:hover),
54
54
  [data-roottale-cms] :where(.rt-cms-filter-chip:focus-visible) {
55
- border-color: color-mix(in srgb, var(--rt-color-primary, #4f46e5) 40%, var(--rt-color-border, #e5e7eb));
56
- color: var(--rt-color-foreground, #111827);
55
+ border-color: color-mix(in srgb, var(--rt-color-primary, #06162f) 40%, var(--rt-color-border, #dceef3));
56
+ color: var(--rt-color-foreground, #06162f);
57
57
  }
58
58
 
59
59
  [data-roottale-cms] :where(.rt-cms-filter-chip[data-active]) {
60
60
  border-color: transparent;
61
- background: var(--rt-color-primary, #4f46e5);
61
+ background: var(--rt-color-primary, #06162f);
62
62
  color: var(--rt-color-primary-foreground, #ffffff);
63
63
  }
64
64
 
@@ -80,10 +80,10 @@
80
80
  justify-content: space-between;
81
81
  gap: var(--rt-spacing-3, 0.75rem);
82
82
  padding: 0.875rem 1rem;
83
- border: 1px solid color-mix(in srgb, var(--rt-color-border, #e5e7eb) 82%, transparent);
83
+ border: 1px solid color-mix(in srgb, var(--rt-color-border, #dceef3) 82%, transparent);
84
84
  border-radius: var(--rt-radius-md, 0.5rem);
85
- background: color-mix(in srgb, var(--rt-color-muted, #f8fafc) 58%, white);
86
- color: var(--rt-color-foreground, #111827);
85
+ background: color-mix(in srgb, var(--rt-color-muted, #f7f8f7) 58%, white);
86
+ color: var(--rt-color-foreground, #06162f);
87
87
  font-family: var(--rt-font-body, system-ui, sans-serif);
88
88
  text-decoration: none;
89
89
  transition:
@@ -93,7 +93,7 @@
93
93
 
94
94
  [data-roottale-cms] :where(.rt-cms-category-link:hover),
95
95
  [data-roottale-cms] :where(.rt-cms-category-link:focus-visible) {
96
- border-color: color-mix(in srgb, var(--rt-color-primary, #4f46e5) 40%, var(--rt-color-border, #e5e7eb));
96
+ border-color: color-mix(in srgb, var(--rt-color-primary, #06162f) 40%, var(--rt-color-border, #dceef3));
97
97
  background: #fff;
98
98
  }
99
99
 
@@ -110,7 +110,7 @@
110
110
  min-inline-size: 1.75rem;
111
111
  padding: 0.1875rem 0.5rem;
112
112
  border-radius: 999px;
113
- background: var(--rt-color-primary, #4f46e5);
113
+ background: var(--rt-color-primary, #06162f);
114
114
  color: var(--rt-color-primary-foreground, #ffffff);
115
115
  font-size: 0.75rem;
116
116
  font-weight: 800;
@@ -130,17 +130,17 @@
130
130
  display: grid;
131
131
  align-content: start;
132
132
  min-block-size: 100%;
133
- border: 1px solid color-mix(in srgb, var(--rt-color-border, #e5e7eb) 78%, transparent);
133
+ border: 1px solid color-mix(in srgb, var(--rt-color-border, #dceef3) 78%, transparent);
134
134
  border-radius: var(--rt-radius-md, 0.5rem);
135
135
  background:
136
136
  linear-gradient(
137
137
  180deg,
138
138
  rgb(255 255 255 / 0.94),
139
- color-mix(in srgb, var(--rt-color-muted, #f8fafc) 70%, white)
139
+ color-mix(in srgb, var(--rt-color-muted, #f7f8f7) 70%, white)
140
140
  ),
141
141
  radial-gradient(
142
142
  circle at top right,
143
- color-mix(in srgb, var(--rt-color-primary, #4f46e5) 8%, transparent),
143
+ color-mix(in srgb, var(--rt-color-primary, #06162f) 8%, transparent),
144
144
  transparent 46%
145
145
  );
146
146
  box-shadow:
@@ -163,7 +163,7 @@
163
163
  var(--rt-spacing-4, 1rem);
164
164
  aspect-ratio: 16 / 9;
165
165
  object-fit: cover;
166
- background: color-mix(in srgb, var(--rt-color-muted, #f8fafc) 70%, white);
166
+ background: color-mix(in srgb, var(--rt-color-muted, #f7f8f7) 70%, white);
167
167
  }
168
168
 
169
169
  /* Category badge. */
@@ -174,8 +174,8 @@
174
174
  margin-block-end: var(--rt-spacing-3, 0.75rem);
175
175
  padding: 0.25rem 0.625rem;
176
176
  border-radius: 999px;
177
- background: color-mix(in srgb, var(--rt-color-primary, #4f46e5) 10%, transparent);
178
- color: color-mix(in srgb, var(--rt-color-primary, #4f46e5) 92%, var(--rt-color-foreground, #111827));
177
+ background: color-mix(in srgb, var(--rt-color-primary, #06162f) 10%, transparent);
178
+ color: color-mix(in srgb, var(--rt-color-primary, #06162f) 92%, var(--rt-color-foreground, #06162f));
179
179
  font-family: var(--rt-font-body, system-ui, sans-serif);
180
180
  font-size: 0.75rem;
181
181
  font-weight: 800;
@@ -191,14 +191,14 @@
191
191
  background: linear-gradient(
192
192
  90deg,
193
193
  transparent,
194
- color-mix(in srgb, var(--rt-color-primary, #4f46e5) 30%, transparent),
194
+ color-mix(in srgb, var(--rt-color-primary, #06162f) 30%, transparent),
195
195
  transparent
196
196
  );
197
197
  }
198
198
 
199
199
  [data-roottale-cms] :where(.rt-cms-card-link:hover),
200
200
  [data-roottale-cms] :where(.rt-cms-card-link:focus-visible) {
201
- border-color: color-mix(in srgb, var(--rt-color-primary, #4f46e5) 32%, var(--rt-color-border, #e5e7eb));
201
+ border-color: color-mix(in srgb, var(--rt-color-primary, #06162f) 32%, var(--rt-color-border, #dceef3));
202
202
  box-shadow:
203
203
  0 20px 46px rgb(17 24 39 / 0.07),
204
204
  inset 0 1px 0 rgb(255 255 255 / 0.82);
@@ -227,7 +227,7 @@
227
227
  gap: 0.375rem;
228
228
  justify-self: start;
229
229
  margin-block-start: var(--rt-spacing-5, 1.25rem);
230
- color: color-mix(in srgb, var(--rt-color-foreground, #111827) 62%, transparent);
230
+ color: color-mix(in srgb, var(--rt-color-foreground, #06162f) 62%, transparent);
231
231
  font-family: var(--rt-font-body, system-ui, sans-serif);
232
232
  font-size: 0.8125rem;
233
233
  font-weight: 800;
@@ -238,7 +238,7 @@
238
238
  content: "";
239
239
  inline-size: 1.75rem;
240
240
  block-size: 1px;
241
- background: color-mix(in srgb, var(--rt-color-primary, #4f46e5) 46%, transparent);
241
+ background: color-mix(in srgb, var(--rt-color-primary, #06162f) 46%, transparent);
242
242
  transition: inline-size 180ms ease;
243
243
  }
244
244
 
@@ -251,7 +251,7 @@
251
251
  font-family: var(--rt-font-display, system-ui, sans-serif);
252
252
  font-size: var(--rt-font-size-2xl, 1.5rem);
253
253
  font-weight: var(--rt-font-weight-bold, 700);
254
- color: var(--rt-color-foreground, #111827);
254
+ color: var(--rt-color-foreground, #06162f);
255
255
  letter-spacing: 0;
256
256
  line-height: 1.25;
257
257
  margin: 0 0 var(--rt-spacing-2, 0.5rem);
@@ -260,7 +260,7 @@
260
260
  [data-roottale-cms] :where(.rt-cms-excerpt) {
261
261
  font-family: var(--rt-font-body, system-ui, sans-serif);
262
262
  font-size: var(--rt-font-size-base, 1.0625rem);
263
- color: color-mix(in srgb, var(--rt-color-foreground, #111827) 68%, transparent);
263
+ color: color-mix(in srgb, var(--rt-color-foreground, #06162f) 68%, transparent);
264
264
  margin: 0;
265
265
  line-height: 1.75;
266
266
  max-inline-size: 42rem;
@@ -274,7 +274,7 @@
274
274
  gap: 0.375rem 0.75rem;
275
275
  font-size: var(--rt-font-size-sm, 0.8125rem);
276
276
  font-weight: 600;
277
- color: color-mix(in srgb, var(--rt-color-foreground, #111827) 56%, transparent);
277
+ color: color-mix(in srgb, var(--rt-color-foreground, #06162f) 56%, transparent);
278
278
  margin: 0 0 var(--rt-spacing-3, 0.75rem);
279
279
  }
280
280
 
@@ -290,19 +290,19 @@
290
290
  inline-size: 0.25rem;
291
291
  block-size: 0.25rem;
292
292
  border-radius: 999px;
293
- background: color-mix(in srgb, var(--rt-color-primary, #4f46e5) 70%, white);
293
+ background: color-mix(in srgb, var(--rt-color-primary, #06162f) 70%, white);
294
294
  margin-inline-end: 0.75rem;
295
295
  }
296
296
 
297
297
  [data-roottale-cms] :where(.rt-cms-empty) {
298
298
  font-family: var(--rt-font-body, system-ui, sans-serif);
299
- color: var(--rt-color-muted-foreground, #64748b);
299
+ color: var(--rt-color-muted-foreground, #6e6e6e);
300
300
  font-style: italic;
301
301
  }
302
302
 
303
303
  [data-roottale-cms] :where(.rt-cms-article) {
304
304
  font-family: var(--rt-font-body, system-ui, sans-serif);
305
- color: var(--rt-color-foreground, #111827);
305
+ color: var(--rt-color-foreground, #06162f);
306
306
  }
307
307
 
308
308
  [data-roottale-cms] :where(.rt-cms-body) {
@@ -310,17 +310,17 @@
310
310
  font-family: var(--rt-font-body, system-ui, sans-serif);
311
311
  font-size: var(--rt-font-size-base, 1rem);
312
312
  line-height: 1.7;
313
- color: var(--rt-color-foreground, #111827);
313
+ color: var(--rt-color-foreground, #06162f);
314
314
  }
315
315
 
316
316
  [data-roottale-cms] :where(.rt-cms-post-header) {
317
317
  position: relative;
318
318
  overflow: hidden;
319
- border: 1px solid color-mix(in srgb, var(--rt-color-border, #e5e7eb) 78%, transparent);
319
+ border: 1px solid color-mix(in srgb, var(--rt-color-border, #dceef3) 78%, transparent);
320
320
  border-radius: calc(var(--rt-radius-md, 0.5rem) * 1.5);
321
321
  background:
322
- linear-gradient(135deg, rgb(255 255 255 / 0.92), color-mix(in srgb, var(--rt-color-muted, #f8fafc) 70%, white)),
323
- radial-gradient(circle at top right, color-mix(in srgb, var(--rt-color-primary, #4f46e5) 10%, transparent), transparent 42%);
322
+ linear-gradient(135deg, rgb(255 255 255 / 0.92), color-mix(in srgb, var(--rt-color-muted, #f7f8f7) 70%, white)),
323
+ radial-gradient(circle at top right, color-mix(in srgb, var(--rt-color-primary, #06162f) 10%, transparent), transparent 42%);
324
324
  box-shadow: 0 20px 55px rgb(17 24 39 / 0.05);
325
325
  padding: clamp(1.5rem, 3vw, 2.5rem);
326
326
  margin-block-end: var(--rt-spacing-6, 1.5rem);
@@ -342,7 +342,7 @@
342
342
  inline-size: 0.25rem;
343
343
  background: linear-gradient(
344
344
  180deg,
345
- color-mix(in srgb, var(--rt-color-primary, #4f46e5) 72%, white),
345
+ color-mix(in srgb, var(--rt-color-primary, #06162f) 72%, white),
346
346
  transparent
347
347
  );
348
348
  }
@@ -361,7 +361,7 @@
361
361
  [data-roottale-cms] :where(.rt-cms-article [data-roottale-cms="body"] h3),
362
362
  [data-roottale-cms] :where(.rt-cms-article [data-roottale-cms="body"] h4) {
363
363
  font-family: var(--rt-font-display, system-ui, sans-serif);
364
- color: var(--rt-color-foreground, #111827);
364
+ color: var(--rt-color-foreground, #06162f);
365
365
  letter-spacing: 0;
366
366
  line-height: 1.4;
367
367
  }
@@ -409,14 +409,14 @@
409
409
  }
410
410
 
411
411
  [data-roottale-cms] :where(.rt-cms-article [data-roottale-cms="body"] blockquote) {
412
- border-inline-start: 3px solid var(--rt-color-border, #e5e7eb);
412
+ border-inline-start: 3px solid var(--rt-color-border, #dceef3);
413
413
  padding-inline-start: var(--rt-spacing-3, 0.75rem);
414
- color: var(--rt-color-muted-foreground, #64748b);
414
+ color: var(--rt-color-muted-foreground, #6e6e6e);
415
415
  font-style: italic;
416
416
  }
417
417
 
418
418
  [data-roottale-cms] :where(.rt-cms-article [data-roottale-cms="body"] a) {
419
- color: var(--rt-color-primary, #0070f3);
419
+ color: var(--rt-color-primary, #06162f);
420
420
  text-decoration: underline;
421
421
  text-underline-offset: 0.15em;
422
422
  }
@@ -441,7 +441,7 @@
441
441
 
442
442
  [data-roottale-cms] :where(.rt-cms-article [data-roottale-cms="body"] code) {
443
443
  border-radius: var(--rt-radius-sm, 0.25rem);
444
- background: var(--rt-color-muted, #f8fafc);
444
+ background: var(--rt-color-muted, #f7f8f7);
445
445
  padding-inline: 0.25em;
446
446
  font-family: var(--rt-font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
447
447
  font-size: 0.9em;
@@ -450,7 +450,7 @@
450
450
  [data-roottale-cms] :where(.rt-cms-article [data-roottale-cms="body"] pre) {
451
451
  overflow-x: auto;
452
452
  border-radius: var(--rt-radius-md, 0.5rem);
453
- background: var(--rt-color-muted, #f8fafc);
453
+ background: var(--rt-color-muted, #f7f8f7);
454
454
  padding: var(--rt-spacing-3, 0.75rem);
455
455
  font-family: var(--rt-font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
456
456
  font-size: 0.9em;
@@ -470,7 +470,7 @@
470
470
 
471
471
  [data-roottale-cms] :where(.rt-cms-article [data-roottale-cms="body"] hr) {
472
472
  border: 0;
473
- border-block-start: 1px solid var(--rt-color-border, #e5e7eb);
473
+ border-block-start: 1px solid var(--rt-color-border, #dceef3);
474
474
  margin-block: var(--rt-spacing-4, 1rem);
475
475
  }
476
476
 
@@ -482,8 +482,8 @@
482
482
  /* RootTaleTableOfContents */
483
483
  [data-roottale-cms] :where(.rt-cms-toc) {
484
484
  position: relative;
485
- background: color-mix(in srgb, var(--rt-color-muted, #f8fafc) 34%, white);
486
- border: 1px solid color-mix(in srgb, var(--rt-color-border, #e5e7eb) 86%, transparent);
485
+ background: color-mix(in srgb, var(--rt-color-muted, #f7f8f7) 34%, white);
486
+ border: 1px solid color-mix(in srgb, var(--rt-color-border, #dceef3) 86%, transparent);
487
487
  border-radius: min(var(--rt-radius-md, 0.5rem), 0.5rem);
488
488
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.76);
489
489
  padding: 0.875rem 1rem;
@@ -497,7 +497,7 @@
497
497
  inset-inline-start: 0;
498
498
  inline-size: 3px;
499
499
  border-radius: 999px;
500
- background: color-mix(in srgb, var(--rt-color-primary, #4f46e5) 58%, var(--rt-color-border, #e5e7eb));
500
+ background: color-mix(in srgb, var(--rt-color-primary, #06162f) 58%, var(--rt-color-border, #dceef3));
501
501
  }
502
502
 
503
503
  [data-roottale-cms] :where(.rt-cms-toc-details) {
@@ -526,7 +526,7 @@
526
526
  font-weight: var(--rt-font-weight-bold, 800);
527
527
  letter-spacing: 0;
528
528
  margin: 0;
529
- color: color-mix(in srgb, var(--rt-color-foreground, #111827) 72%, transparent);
529
+ color: color-mix(in srgb, var(--rt-color-foreground, #06162f) 72%, transparent);
530
530
  }
531
531
 
532
532
  [data-roottale-cms] :where(.rt-cms-toc-title)::after {
@@ -538,7 +538,7 @@
538
538
  flex: 0 0 auto;
539
539
  inline-size: 1.625rem;
540
540
  block-size: 1.625rem;
541
- border: 1px solid color-mix(in srgb, var(--rt-color-border, #e5e7eb) 90%, transparent);
541
+ border: 1px solid color-mix(in srgb, var(--rt-color-border, #dceef3) 90%, transparent);
542
542
  border-radius: 999px;
543
543
  background: var(--rt-color-background, #ffffff);
544
544
  }
@@ -551,7 +551,7 @@
551
551
  inset-inline-start: 50%;
552
552
  inline-size: 0.625rem;
553
553
  block-size: 1px;
554
- background: color-mix(in srgb, var(--rt-color-foreground, #111827) 66%, transparent);
554
+ background: color-mix(in srgb, var(--rt-color-foreground, #06162f) 66%, transparent);
555
555
  transform: translate(-50%, -50%);
556
556
  }
557
557
 
@@ -592,7 +592,7 @@
592
592
  inset-block-start: 0.5rem;
593
593
  inset-inline-start: 0.625rem;
594
594
  inline-size: 1.375rem;
595
- color: color-mix(in srgb, var(--rt-color-foreground, #111827) 36%, transparent);
595
+ color: color-mix(in srgb, var(--rt-color-foreground, #06162f) 36%, transparent);
596
596
  font-size: 0.6875rem;
597
597
  font-variant-numeric: tabular-nums;
598
598
  font-weight: 700;
@@ -608,7 +608,7 @@
608
608
 
609
609
  [data-roottale-cms] :where(.rt-cms-toc-item a) {
610
610
  display: block;
611
- color: color-mix(in srgb, var(--rt-color-foreground, #111827) 76%, transparent);
611
+ color: color-mix(in srgb, var(--rt-color-foreground, #06162f) 76%, transparent);
612
612
  text-decoration: none;
613
613
  border-radius: min(calc(var(--rt-radius-md, 0.5rem) * 0.75), 0.375rem);
614
614
  padding: 0.375rem 0.5rem 0.375rem 2.375rem;
@@ -620,8 +620,8 @@
620
620
 
621
621
  [data-roottale-cms] :where(.rt-cms-toc-item a:hover),
622
622
  [data-roottale-cms] :where(.rt-cms-toc-item a:focus-visible) {
623
- color: var(--rt-color-foreground, #111827);
624
- background: color-mix(in srgb, var(--rt-color-primary, #4f46e5) 7%, var(--rt-color-background, #ffffff));
623
+ color: var(--rt-color-foreground, #06162f);
624
+ background: color-mix(in srgb, var(--rt-color-primary, #06162f) 7%, var(--rt-color-background, #ffffff));
625
625
  text-decoration: none;
626
626
  transform: translateX(0.125rem);
627
627
  }
@@ -631,11 +631,11 @@
631
631
  align-items: center;
632
632
  gap: var(--rt-spacing-4, 1rem);
633
633
  margin-block-start: var(--rt-spacing-8, 3rem);
634
- border: 1px solid color-mix(in srgb, var(--rt-color-border, #e5e7eb) 82%, transparent);
634
+ border: 1px solid color-mix(in srgb, var(--rt-color-border, #dceef3) 82%, transparent);
635
635
  border-radius: calc(var(--rt-radius-md, 0.5rem) * 1.25);
636
636
  background:
637
- linear-gradient(135deg, rgb(255 255 255 / 0.92), color-mix(in srgb, var(--rt-color-muted, #f8fafc) 82%, white)),
638
- radial-gradient(circle at bottom left, color-mix(in srgb, var(--rt-color-primary, #4f46e5) 9%, transparent), transparent 48%);
637
+ linear-gradient(135deg, rgb(255 255 255 / 0.92), color-mix(in srgb, var(--rt-color-muted, #f7f8f7) 82%, white)),
638
+ radial-gradient(circle at bottom left, color-mix(in srgb, var(--rt-color-primary, #06162f) 9%, transparent), transparent 48%);
639
639
  box-shadow: 0 18px 44px rgb(17 24 39 / 0.055);
640
640
  padding: var(--rt-spacing-5, 1.25rem);
641
641
  }
@@ -652,13 +652,13 @@
652
652
  display: grid;
653
653
  place-items: center;
654
654
  background:
655
- linear-gradient(135deg, var(--rt-color-primary, #4f46e5), color-mix(in srgb, var(--rt-color-primary, #4f46e5) 42%, #111827));
655
+ linear-gradient(135deg, var(--rt-color-primary, #06162f), color-mix(in srgb, var(--rt-color-primary, #06162f) 42%, #06162f));
656
656
  color: var(--rt-color-primary-foreground, #ffffff);
657
657
  font-family: var(--rt-font-display, system-ui, sans-serif);
658
658
  font-size: 0.9375rem;
659
659
  font-weight: 800;
660
660
  letter-spacing: 0;
661
- box-shadow: 0 12px 30px color-mix(in srgb, var(--rt-color-primary, #4f46e5) 18%, transparent);
661
+ box-shadow: 0 12px 30px color-mix(in srgb, var(--rt-color-primary, #06162f) 18%, transparent);
662
662
  }
663
663
 
664
664
  [data-roottale-cms] :where(.rt-cms-author-card__image) {
@@ -673,7 +673,7 @@
673
673
 
674
674
  [data-roottale-cms] :where(.rt-cms-author-card__eyebrow) {
675
675
  margin: 0 0 0.125rem;
676
- color: color-mix(in srgb, var(--rt-color-foreground, #111827) 46%, transparent);
676
+ color: color-mix(in srgb, var(--rt-color-foreground, #06162f) 46%, transparent);
677
677
  font-size: 0.75rem;
678
678
  font-weight: 700;
679
679
  line-height: 1.2;
@@ -681,7 +681,7 @@
681
681
 
682
682
  [data-roottale-cms] :where(.rt-cms-author-card__name) {
683
683
  margin: 0;
684
- color: var(--rt-color-foreground, #111827);
684
+ color: var(--rt-color-foreground, #06162f);
685
685
  font-family: var(--rt-font-display, system-ui, sans-serif);
686
686
  font-size: 1.0625rem;
687
687
  font-weight: 800;
@@ -690,7 +690,7 @@
690
690
 
691
691
  [data-roottale-cms] :where(.rt-cms-author-card__description) {
692
692
  margin: 0.375rem 0 0;
693
- color: color-mix(in srgb, var(--rt-color-foreground, #111827) 62%, transparent);
693
+ color: color-mix(in srgb, var(--rt-color-foreground, #06162f) 62%, transparent);
694
694
  font-size: 0.9375rem;
695
695
  line-height: 1.55;
696
696
  max-inline-size: 42rem;
@@ -751,7 +751,7 @@
751
751
  align-items: center;
752
752
  gap: var(--rt-spacing-2, 0.5rem);
753
753
  padding: var(--rt-spacing-3, 0.75rem) var(--rt-spacing-4, 1rem);
754
- background: var(--rt-color-primary, #0070f3);
754
+ background: var(--rt-color-primary, #06162f);
755
755
  color: var(--rt-color-primary-foreground, #ffffff);
756
756
  border-radius: var(--rt-radius-full, 9999px);
757
757
  text-decoration: none;
@@ -777,7 +777,7 @@
777
777
  gap: var(--rt-spacing-4, 1rem);
778
778
  max-inline-size: 32rem;
779
779
  font-family: var(--rt-font-body, system-ui, sans-serif);
780
- color: var(--rt-color-foreground, #0f172a);
780
+ color: var(--rt-color-foreground, #06162f);
781
781
  }
782
782
 
783
783
  [data-roottale-cms="lead-form"] :where(.rt-cms-lead-heading) {
@@ -789,7 +789,7 @@
789
789
 
790
790
  [data-roottale-cms="lead-form"] :where(.rt-cms-lead-description) {
791
791
  margin: 0;
792
- color: var(--rt-color-muted-foreground, #64748b);
792
+ color: var(--rt-color-muted-foreground, #6e6e6e);
793
793
  font-size: var(--rt-font-size-base, 1rem);
794
794
  line-height: 1.5;
795
795
  }
@@ -797,7 +797,7 @@
797
797
  [data-roottale-cms="lead-form"] :where(.rt-cms-lead-vertical-label) {
798
798
  margin: 0;
799
799
  padding: var(--rt-spacing-3, 0.75rem);
800
- background: var(--rt-color-muted, #f8fafc);
800
+ background: var(--rt-color-muted, #f7f8f7);
801
801
  border-radius: var(--rt-radius-md, 0.5rem);
802
802
  font-size: var(--rt-font-size-sm, 0.875rem);
803
803
  }
@@ -810,7 +810,7 @@
810
810
  [data-roottale-cms="lead-form"] :where(.rt-cms-field-label) {
811
811
  font-size: var(--rt-font-size-sm, 0.875rem);
812
812
  font-weight: var(--rt-font-weight-medium, 500);
813
- color: var(--rt-color-foreground, #0f172a);
813
+ color: var(--rt-color-foreground, #06162f);
814
814
  }
815
815
 
816
816
  [data-roottale-cms="lead-form"] :where(.rt-cms-field-input) {
@@ -818,21 +818,21 @@
818
818
  inline-size: 100%;
819
819
  min-block-size: 2.75rem; /* WCAG 2.2 AA 48px touch */
820
820
  padding: var(--rt-spacing-2, 0.5rem) var(--rt-spacing-3, 0.75rem);
821
- border: 1px solid var(--rt-color-border, #e5e7eb);
821
+ border: 1px solid var(--rt-color-border, #dceef3);
822
822
  border-radius: var(--rt-radius-md, 0.5rem);
823
823
  background: var(--rt-color-background, #fff);
824
- color: var(--rt-color-foreground, #0f172a);
824
+ color: var(--rt-color-foreground, #06162f);
825
825
  font: inherit;
826
826
  }
827
827
 
828
828
  [data-roottale-cms="lead-form"] :where(.rt-cms-field-input:focus-visible) {
829
- outline: 2px solid var(--rt-color-primary, #0070f3);
829
+ outline: 2px solid var(--rt-color-primary, #06162f);
830
830
  outline-offset: 2px;
831
831
  }
832
832
 
833
833
  [data-roottale-cms="lead-form"] :where(.rt-cms-field-hint) {
834
834
  font-size: var(--rt-font-size-xs, 0.75rem);
835
- color: var(--rt-color-muted-foreground, #64748b);
835
+ color: var(--rt-color-muted-foreground, #6e6e6e);
836
836
  }
837
837
 
838
838
  [data-roottale-cms="lead-form"] :where(.rt-cms-lead-consent) {
@@ -861,7 +861,7 @@
861
861
  justify-content: center;
862
862
  min-block-size: 2.75rem;
863
863
  padding: var(--rt-spacing-3, 0.75rem) var(--rt-spacing-5, 1.25rem);
864
- background: var(--rt-color-primary, #0070f3);
864
+ background: var(--rt-color-primary, #06162f);
865
865
  color: var(--rt-color-primary-foreground, #fff);
866
866
  border: 0;
867
867
  border-radius: var(--rt-radius-md, 0.5rem);
@@ -875,6 +875,6 @@
875
875
  }
876
876
 
877
877
  [data-roottale-cms="lead-form"] :where(.rt-cms-lead-submit:focus-visible) {
878
- outline: 2px solid var(--rt-color-primary, #0070f3);
878
+ outline: 2px solid var(--rt-color-primary, #06162f);
879
879
  outline-offset: 2px;
880
880
  }
package/dist/routes.d.ts CHANGED
@@ -64,6 +64,43 @@ interface SitemapEntry {
64
64
  * ```
65
65
  */
66
66
  declare function createSitemap(config: RootTaleSiteConfig, staticRoutes?: SitemapEntry[]): () => Promise<SitemapEntry[]>;
67
+ /** llms.txt 정적 섹션의 링크 1개. */
68
+ interface LlmsTxtLink {
69
+ title: string;
70
+ url: string;
71
+ /** 링크 뒤 ": {note}" 로 붙는 한 줄 설명 (선택). */
72
+ note?: string;
73
+ }
74
+ /** llms.txt 의 정적 페이지 링크 그룹 — 블로그 목록 앞에 출력. */
75
+ interface LlmsTxtSection {
76
+ title: string;
77
+ links: LlmsTxtLink[];
78
+ }
79
+ type LlmsTxtRouteConfig = RootTaleSiteConfig & {
80
+ /** (선택) 서비스 소개 등 정적 페이지 링크 그룹. */
81
+ sections?: LlmsTxtSection[];
82
+ };
83
+ /**
84
+ * `app/llms.txt/route.ts` 용 GET 핸들러 — AEO/GEO(AI 검색·생성엔진 최적화).
85
+ *
86
+ * AI 크롤러(ChatGPT/Claude/Perplexity 등)가 사이트 구조·콘텐츠를 빠르게
87
+ * 파악하도록 llms.txt 스펙(https://llmstxt.org)의 마크다운 인덱스를 제공한다.
88
+ * 발행 글 최대 100개를 "## 블로그" 섹션으로 자동 포함 — feed/sitemap 처럼
89
+ * fetch 실패도 swallow 하여 *항상 200* (헤더 부분만 출력).
90
+ *
91
+ * ```ts
92
+ * import { createLlmsTxtRoute } from "@roottale/cms-renderer-next/routes";
93
+ * export const dynamic = "force-dynamic";
94
+ * export const GET = createLlmsTxtRoute({
95
+ * apiKey: process.env.ROOTTALE_API_KEY!,
96
+ * siteUrl: "https://example.com",
97
+ * title: "Example",
98
+ * description: "...",
99
+ * sections: [{ title: "주요 페이지", links: [{ title: "서비스", url: "https://example.com/services" }] }],
100
+ * });
101
+ * ```
102
+ */
103
+ declare function createLlmsTxtRoute(config: LlmsTxtRouteConfig): () => Promise<Response>;
67
104
  interface RevalidateRouteConfig {
68
105
  /** `rtlk_cust_*` — 블로그 조회/webhook 검증 공통 키. */
69
106
  apiKey: string;
@@ -75,7 +112,8 @@ interface RevalidateRouteConfig {
75
112
  /**
76
113
  * 모든 글/분류/미디어 변경에 대해 *항상 함께* revalidate 할 파생 경로.
77
114
  * 피드·사이트맵·블로그 인덱스처럼 "글 목록"에 의존하는 경로 — admin 변경이
78
- * 자동 반영되려면 필수. 기본: ["/feed.xml", "/sitemap.xml", blogBase].
115
+ * 자동 반영되려면 필수.
116
+ * 기본: ["/feed.xml", "/sitemap.xml", "/llms.txt", blogBase, `${blogBase}/categories`].
79
117
  */
80
118
  alsoRevalidate?: string[];
81
119
  /** (옵션) jti replay 방지 hook (cms-client verify 로 전달). */
@@ -97,6 +135,29 @@ interface RevalidateRouteConfig {
97
135
  * ```
98
136
  */
99
137
  declare function createRevalidateRoute(config: RevalidateRouteConfig): (req: Request) => Promise<Response>;
138
+ /**
139
+ * 옛 slug → 현재 slug 301 redirect 판단 (순수 함수, `next` 비의존).
140
+ *
141
+ * Public API 는 slug 변경 후에도 옛 slug 로 글을 찾아 *현재* slug 를 응답한다
142
+ * (post_slug_history fallback). 요청 slug 와 응답 slug 가 다르면 새 경로를
143
+ * 반환 — 페이지에서 `permanentRedirect()` 로 301 처리한다:
144
+ *
145
+ * ```ts
146
+ * import { permanentRedirect, notFound } from "next/navigation";
147
+ * import { postRedirectPath } from "@roottale/cms-renderer-next/routes";
148
+ *
149
+ * const post = await getPost(slug);
150
+ * if (!post) notFound();
151
+ * const redirect = postRedirectPath(post, slug);
152
+ * if (redirect) permanentRedirect(redirect);
153
+ * ```
154
+ *
155
+ * Next App Router 의 `params` 는 percent-encoding 된 채 들어올 수 있어
156
+ * (한글 slug) 디코딩 후 비교한다. redirect 가 불필요하면 null.
157
+ */
158
+ declare function postRedirectPath(post: {
159
+ slug: string;
160
+ }, requestedSlug: string, blogBasePath?: string): string | null;
100
161
  interface FleetInfoRouteConfig {
101
162
  /** 사이트 식별 라벨 (선택 — 기본 Vercel project URL 또는 null). */
102
163
  site?: string;
@@ -116,5 +177,65 @@ interface FleetInfoRouteConfig {
116
177
  * ```
117
178
  */
118
179
  declare function createFleetInfoRoute(config?: FleetInfoRouteConfig): () => Promise<Response>;
180
+ /** Next `opengraph-image` export 컨벤션과 호환되는 크기 상수. */
181
+ declare const OG_IMAGE_SIZE: {
182
+ readonly width: 1200;
183
+ readonly height: 630;
184
+ };
185
+ declare const OG_IMAGE_CONTENT_TYPE = "image/png";
186
+ interface OgImageRouteConfig extends RootTaleSiteConfig {
187
+ /** 배경색. 기본 진네이비 그라데이션 베이스. */
188
+ backgroundColor?: string;
189
+ /** 본문 텍스트 색. 기본 흰색. */
190
+ foregroundColor?: string;
191
+ /** 상단 액센트 바 + 브랜드 라벨 색. 기본 하늘색. */
192
+ accentColor?: string;
193
+ /** 하단 브랜드 라벨. 기본 = `title`. */
194
+ brandLabel?: string;
195
+ }
196
+ /** `next/og` 의 ImageResponse 와 구조 호환(직접 의존 회피 — revalidate 콜백 주입과 동일 원칙). */
197
+ interface ImageResponseLike {
198
+ new (element: unknown, options?: {
199
+ width?: number;
200
+ height?: number;
201
+ fonts?: {
202
+ name: string;
203
+ data: ArrayBuffer;
204
+ weight?: number;
205
+ style?: "normal";
206
+ }[];
207
+ }): Response;
208
+ }
209
+ /**
210
+ * `app/blog/[slug]/opengraph-image.tsx` 용 동적 OG 이미지 (1200×630).
211
+ *
212
+ * `next/og` 의 ImageResponse 를 주입받는다 — 본 패키지는 `next` 에 직접
213
+ * 의존하지 않는다. 글이 없거나 fetch 실패면 사이트 제목만으로 fail-soft 렌더
214
+ * (소셜 크롤러에 빈 카드 대신 브랜드 카드).
215
+ *
216
+ * ```tsx
217
+ * // app/blog/[slug]/opengraph-image.tsx
218
+ * import { ImageResponse } from "next/og";
219
+ * import {
220
+ * createPostOgImage,
221
+ * OG_IMAGE_SIZE,
222
+ * OG_IMAGE_CONTENT_TYPE,
223
+ * } from "@roottale/cms-renderer-next/routes";
224
+ * import { roottale } from "@/lib/roottale"; // RootTaleSiteConfig
225
+ *
226
+ * export const size = OG_IMAGE_SIZE;
227
+ * export const contentType = OG_IMAGE_CONTENT_TYPE;
228
+ * export default createPostOgImage(roottale, { ImageResponse });
229
+ * ```
230
+ */
231
+ declare function createPostOgImage(config: OgImageRouteConfig, deps: {
232
+ ImageResponse: ImageResponseLike;
233
+ }): (props: {
234
+ params: Promise<{
235
+ slug: string;
236
+ }> | {
237
+ slug: string;
238
+ };
239
+ }) => Promise<Response>;
119
240
 
120
- export { type FleetInfoRouteConfig, type RevalidateRouteConfig, type RootTaleSiteConfig, type SitemapEntry, createFeedRoute, createFleetInfoRoute, createRevalidateRoute, createSitemap };
241
+ export { type FleetInfoRouteConfig, type ImageResponseLike, type LlmsTxtLink, type LlmsTxtRouteConfig, type LlmsTxtSection, OG_IMAGE_CONTENT_TYPE, OG_IMAGE_SIZE, type OgImageRouteConfig, type RevalidateRouteConfig, type RootTaleSiteConfig, type SitemapEntry, createFeedRoute, createFleetInfoRoute, createLlmsTxtRoute, createPostOgImage, createRevalidateRoute, createSitemap, postRedirectPath };