@treeseed/core 0.8.8 → 0.8.10

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 (90) hide show
  1. package/dist/components/SiteTitle.astro +2 -2
  2. package/dist/components/content/ContentStatusLegend.astro +4 -4
  3. package/dist/components/docs/BookFontControls.astro +9 -9
  4. package/dist/components/docs/DesktopSidebarToggle.astro +8 -8
  5. package/dist/components/docs/Footer.astro +7 -91
  6. package/dist/components/docs/Header.astro +9 -2
  7. package/dist/components/docs/PageTitle.astro +1 -1
  8. package/dist/components/docs/ThemeSelect.astro +3 -1
  9. package/dist/components/forms/ContactForm.astro +21 -21
  10. package/dist/components/forms/FooterSubscribeForm.astro +9 -9
  11. package/dist/components/site/BookList.astro +7 -7
  12. package/dist/components/site/CTASection.astro +4 -4
  13. package/dist/components/site/ChronicleList.astro +6 -6
  14. package/dist/components/site/Hero.astro +3 -3
  15. package/dist/components/site/PathCard.astro +5 -5
  16. package/dist/components/site/ProfileList.astro +5 -5
  17. package/dist/components/site/RouteNotFound.astro +6 -6
  18. package/dist/components/site/SectionIntro.astro +3 -3
  19. package/dist/components/site/StageBanner.astro +2 -2
  20. package/dist/components/site/TrustCallout.astro +3 -3
  21. package/dist/components/ui/data/ActionList.astro +51 -0
  22. package/dist/components/ui/data/Badge.astro +19 -0
  23. package/dist/components/ui/data/DataTable.astro +51 -0
  24. package/dist/components/ui/data/KeyValueList.astro +28 -0
  25. package/dist/components/ui/data/MetricCard.astro +25 -0
  26. package/dist/components/ui/data/MetricGrid.astro +27 -0
  27. package/dist/components/ui/data/StatusPill.astro +20 -0
  28. package/dist/components/ui/forms/Button.astro +52 -0
  29. package/dist/components/ui/forms/Field.astro +39 -0
  30. package/dist/components/ui/forms/FormActions.astro +12 -0
  31. package/dist/components/ui/forms/PasswordMeter.astro +80 -0
  32. package/dist/components/ui/forms/RadioGroup.astro +55 -0
  33. package/dist/components/ui/forms/Select.astro +44 -0
  34. package/dist/components/ui/forms/TextInput.astro +58 -0
  35. package/dist/components/ui/forms/Textarea.astro +45 -0
  36. package/dist/components/ui/layout/PageHeader.astro +45 -0
  37. package/dist/components/ui/shell/AppShell.astro +112 -0
  38. package/dist/components/ui/shell/BottomNav.astro +35 -0
  39. package/dist/components/ui/shell/ProjectHeader.astro +66 -0
  40. package/dist/components/ui/shell/PublicFooter.astro +39 -0
  41. package/dist/components/ui/shell/PublicShell.astro +179 -0
  42. package/dist/components/ui/shell/RailNav.astro +35 -0
  43. package/dist/components/ui/shell/TopBar.astro +52 -0
  44. package/dist/components/ui/surface/Card.astro +46 -0
  45. package/dist/components/ui/surface/EmptyState.astro +45 -0
  46. package/dist/components/ui/surface/Panel.astro +54 -0
  47. package/dist/components/ui/theme/ThemeMenu.astro +32 -0
  48. package/dist/components/ui/theme/ThemePreviewSwatch.astro +18 -0
  49. package/dist/components/ui/theme/ThemeScript.astro +111 -0
  50. package/dist/components/ui/theme/ThemeSelector.astro +202 -0
  51. package/dist/components/ui/types.js +0 -0
  52. package/dist/dev-watch.d.ts +6 -2
  53. package/dist/dev-watch.js +12 -3
  54. package/dist/dev.d.ts +10 -2
  55. package/dist/dev.js +352 -68
  56. package/dist/layouts/AuthoredEntryLayout.astro +27 -27
  57. package/dist/layouts/BookLayout.astro +10 -10
  58. package/dist/layouts/ContentLayout.astro +4 -4
  59. package/dist/layouts/MainLayout.astro +66 -193
  60. package/dist/layouts/NoteLayout.astro +6 -6
  61. package/dist/layouts/ProfileLayout.astro +17 -17
  62. package/dist/middleware/starlightRouteData.js +20 -14
  63. package/dist/pages/404.astro +8 -8
  64. package/dist/pages/[slug].astro +1 -1
  65. package/dist/pages/books/[slug].astro +5 -5
  66. package/dist/pages/contact.astro +4 -4
  67. package/dist/pages/docs-runtime/[...slug].astro +12 -12
  68. package/dist/pages/docs-runtime/index.astro +13 -13
  69. package/dist/pages/index.astro +28 -28
  70. package/dist/pages/ui/index.astro +216 -0
  71. package/dist/scripts/dev-platform.js +7 -1
  72. package/dist/site.js +53 -5
  73. package/dist/styles/app-shell.css +597 -0
  74. package/dist/styles/forms.css +258 -0
  75. package/dist/styles/global.css +125 -120
  76. package/dist/styles/prose.css +11 -11
  77. package/dist/styles/theme.css +177 -0
  78. package/dist/styles/tokens.css +62 -22
  79. package/dist/styles/ui.css +551 -0
  80. package/dist/utils/color-schemes/cedar.js +53 -0
  81. package/dist/utils/color-schemes/fern.js +53 -0
  82. package/dist/utils/color-schemes/index.js +13 -0
  83. package/dist/utils/color-schemes/lichen.js +53 -0
  84. package/dist/utils/color-schemes/shared.js +33 -0
  85. package/dist/utils/color-schemes/tidepool.js +53 -0
  86. package/dist/utils/content-status.js +5 -5
  87. package/dist/utils/site-config.js +2 -2
  88. package/dist/utils/starlight-nav.js +13 -7
  89. package/dist/utils/theme.js +133 -41
  90. package/package.json +36 -2
@@ -23,8 +23,8 @@ const { siteTitleHref } = Astro.locals.starlightRoute;
23
23
  }
24
24
 
25
25
  .site-header-logo {
26
- width: 2.5rem;
27
- height: 2.5rem;
26
+ width: 3.75rem;
27
+ height: 3.75rem;
28
28
  object-fit: contain;
29
29
  flex: 0 0 auto;
30
30
  }
@@ -2,15 +2,15 @@
2
2
  import { CONTENT_STATUSES, CONTENT_STATUS_META } from '../../utils/content-status';
3
3
  ---
4
4
 
5
- <section class="border-t border-[color:var(--site-border-strong)] pt-8">
6
- <p class="text-sm font-semibold uppercase tracking-[0.18em] text-[color:var(--site-accent-strong)]">Content status legend</p>
5
+ <section class="border-t border-[color:var(--ts-color-border-strong)] pt-8">
6
+ <p class="text-sm font-semibold uppercase tracking-[0.18em] text-[color:var(--ts-color-accent-strong)]">Content status legend</p>
7
7
  <div class="mt-5 grid gap-3 md:grid-cols-2 xl:grid-cols-5">
8
8
  {CONTENT_STATUSES.map((status) => {
9
9
  const meta = CONTENT_STATUS_META[status];
10
10
  return (
11
- <div class:list={['border-l-4 bg-[color:var(--site-bg-soft)] px-4 py-4', meta.tone]}>
11
+ <div class:list={['border-l-4 bg-[color:var(--ts-color-canvas-subtle)] px-4 py-4', meta.tone]}>
12
12
  <p class="font-semibold">{meta.label}</p>
13
- <p class="mt-2 text-sm leading-7 text-[color:var(--site-text-muted)]">{meta.description}</p>
13
+ <p class="mt-2 text-sm leading-7 text-[color:var(--ts-color-text-muted)]">{meta.description}</p>
14
14
  </div>
15
15
  );
16
16
  })}
@@ -113,9 +113,9 @@ const isBookPage = Boolean(getBookForPath(Astro.url.pathname));
113
113
  .book-font-controls__buttons {
114
114
  display: inline-flex;
115
115
  align-items: center;
116
- border: 1px solid var(--site-border-strong);
116
+ border: 1px solid var(--ts-color-border-strong);
117
117
  border-radius: 999px;
118
- background: color-mix(in srgb, var(--site-bg-elevated) 78%, white 22%);
118
+ background: color-mix(in srgb, var(--ts-color-canvas-subtle) 78%, white 22%);
119
119
  }
120
120
 
121
121
  .book-font-controls__button {
@@ -126,7 +126,7 @@ const isBookPage = Boolean(getBookForPath(Astro.url.pathname));
126
126
  height: 2rem;
127
127
  border: 0;
128
128
  background: transparent;
129
- color: var(--site-text);
129
+ color: var(--ts-color-text);
130
130
  font-size: 1rem;
131
131
  font-weight: 700;
132
132
  line-height: 1;
@@ -135,13 +135,13 @@ const isBookPage = Boolean(getBookForPath(Astro.url.pathname));
135
135
  }
136
136
 
137
137
  .book-font-controls__button + .book-font-controls__button {
138
- border-inline-start: 1px solid var(--site-border-strong);
138
+ border-inline-start: 1px solid var(--ts-color-border-strong);
139
139
  }
140
140
 
141
141
  .book-font-controls__button:hover,
142
142
  .book-font-controls__button:focus-visible {
143
- background: color-mix(in srgb, var(--site-blue-soft) 66%, white 34%);
144
- color: var(--site-blue-strong);
143
+ background: color-mix(in srgb, var(--ts-color-info-soft) 66%, white 34%);
144
+ color: var(--ts-color-info-text);
145
145
  }
146
146
 
147
147
  .book-font-controls__button::after {
@@ -151,10 +151,10 @@ const isBookPage = Boolean(getBookForPath(Astro.url.pathname));
151
151
  inset-block-start: calc(100% + 0.45rem);
152
152
  transform: translateX(-50%) translateY(-0.2rem);
153
153
  padding: 0.3rem 0.5rem;
154
- border: 1px solid var(--site-border-strong);
154
+ border: 1px solid var(--ts-color-border-strong);
155
155
  border-radius: 0.45rem;
156
- background: color-mix(in srgb, var(--site-bg-elevated) 88%, white 12%);
157
- color: var(--site-text);
156
+ background: color-mix(in srgb, var(--ts-color-canvas-subtle) 88%, white 12%);
157
+ color: var(--ts-color-text);
158
158
  font-size: 0.76rem;
159
159
  font-weight: 700;
160
160
  letter-spacing: 0.04em;
@@ -43,8 +43,8 @@ const iconPath =
43
43
  border: 1px solid var(--sl-color-hairline);
44
44
  border-radius: 999px;
45
45
  padding: 0.45rem 0.8rem;
46
- background: color-mix(in srgb, var(--site-bg-soft) 84%, white 16%);
47
- color: var(--site-text-muted);
46
+ background: color-mix(in srgb, var(--ts-color-canvas-subtle) 84%, white 16%);
47
+ color: var(--ts-color-text-muted);
48
48
  font-size: 0.85rem;
49
49
  line-height: 1;
50
50
  transition:
@@ -55,15 +55,15 @@ const iconPath =
55
55
 
56
56
  .desktop-sidebar-toggle:hover,
57
57
  .desktop-sidebar-toggle:focus-visible {
58
- background: color-mix(in srgb, var(--site-blue-soft) 52%, white 48%);
59
- border-color: var(--site-blue);
60
- color: var(--site-text);
58
+ background: color-mix(in srgb, var(--ts-color-info-soft) 52%, white 48%);
59
+ border-color: var(--ts-color-info);
60
+ color: var(--ts-color-text);
61
61
  }
62
62
 
63
63
  .desktop-sidebar-toggle[aria-expanded='true'] {
64
- background: color-mix(in srgb, var(--site-blue-soft) 68%, white 32%);
65
- border-color: var(--site-blue);
66
- color: var(--site-text);
64
+ background: color-mix(in srgb, var(--ts-color-info-soft) 68%, white 32%);
65
+ border-color: var(--ts-color-info);
66
+ color: var(--ts-color-text);
67
67
  }
68
68
 
69
69
  .desktop-sidebar-toggle__icon {
@@ -3,11 +3,8 @@ import EditLink from '../../vendor/starlight/components/EditLink.astro';
3
3
  import LastUpdated from '../../vendor/starlight/components/LastUpdated.astro';
4
4
  import Pagination from '../../vendor/starlight/components/Pagination.astro';
5
5
  import config from 'virtual:starlight/user-config';
6
- import FooterSubscribeForm from '../forms/FooterSubscribeForm.astro';
6
+ import PublicFooter from '../ui/shell/PublicFooter.astro';
7
7
  import DevWatchReload from '../DevWatchReload.astro';
8
- import { PROJECT_STAGE } from '../../utils/content-status';
9
- import { SITE } from '../../utils/seo';
10
- import { SITE_FOOTER_MENU } from '../../utils/site-config';
11
8
  ---
12
9
 
13
10
  <div class="docs-footer-shell">
@@ -28,32 +25,7 @@ import { SITE_FOOTER_MENU } from '../../utils/site-config';
28
25
  </div>
29
26
  </div>
30
27
 
31
- <footer class="docs-site-footer">
32
- <div class="docs-site-footer-inner">
33
- <div class="docs-footer-grid">
34
- <div class="docs-footer-column">
35
- <p class="docs-footer-title">{SITE.name}</p>
36
- <p class="docs-footer-copy">{SITE.summary}</p>
37
- </div>
38
- <div class="docs-footer-column">
39
- <p class="docs-footer-heading">Project stage</p>
40
- <p class="docs-footer-column-title">{PROJECT_STAGE.label}</p>
41
- <p class="docs-footer-copy">{PROJECT_STAGE.description}</p>
42
- </div>
43
- {SITE_FOOTER_MENU.map((group) => (
44
- <div class="docs-footer-column">
45
- <p class="docs-footer-heading">{group.label}</p>
46
- <div class="docs-footer-links">
47
- {group.items.map((item) => (
48
- <a href={item.href}>{item.label}</a>
49
- ))}
50
- </div>
51
- </div>
52
- ))}
53
- </div>
54
- <FooterSubscribeForm currentPath={Astro.url.pathname} />
55
- </div>
56
- </footer>
28
+ <PublicFooter currentPath={Astro.url.pathname} />
57
29
  <DevWatchReload />
58
30
  </div>
59
31
 
@@ -65,8 +37,8 @@ import { SITE_FOOTER_MENU } from '../../utils/site-config';
65
37
  }
66
38
 
67
39
  .docs-footer-page-inner,
68
- .docs-site-footer-inner {
69
- width: min(100%, var(--site-max));
40
+ .docs-footer-shell :global(.ts-public-footer__inner) {
41
+ width: min(100%, var(--ts-content-width));
70
42
  margin-inline: auto;
71
43
  padding-inline: 1rem;
72
44
  }
@@ -119,76 +91,20 @@ import { SITE_FOOTER_MENU } from '../../utils/site-config';
119
91
  color: var(--sl-color-white);
120
92
  }
121
93
 
122
- .docs-site-footer {
94
+ .docs-footer-shell :global(.ts-public-footer) {
123
95
  margin-top: 0;
124
- border-top: 2px solid var(--site-border-strong);
125
- padding-top: 2rem;
126
- }
127
-
128
- .docs-site-footer-inner {
129
- padding-bottom: 3.75rem;
130
- }
131
-
132
- .docs-footer-grid {
133
- display: flex;
134
- flex-wrap: wrap;
135
- justify-content: center;
136
- gap: 2rem;
137
- padding-bottom: 2rem;
138
- }
139
-
140
- .docs-footer-column {
141
- width: 16rem;
142
- }
143
-
144
- .docs-footer-heading {
145
- font-size: var(--sl-text-sm);
146
- font-weight: 600;
147
- letter-spacing: 0.16em;
148
- text-transform: uppercase;
149
- color: var(--site-blue-strong);
150
- }
151
-
152
- .docs-footer-title,
153
- .docs-footer-column-title {
154
- font-size: 1.25rem;
155
- font-weight: 700;
156
- color: var(--site-text);
157
- }
158
-
159
- .docs-footer-copy,
160
- .docs-footer-links {
161
- margin-top: 0.75rem;
162
- font-size: 1rem;
163
- line-height: 2;
164
- color: var(--site-text-muted);
165
- }
166
-
167
- .docs-footer-links {
168
- display: flex;
169
- flex-direction: column;
170
- gap: 0.5rem;
171
- }
172
-
173
- .docs-footer-links a {
174
- text-decoration: none;
175
- }
176
-
177
- .docs-footer-links a:hover,
178
- .docs-footer-links a:focus-visible {
179
- color: var(--site-text);
180
96
  }
181
97
 
182
98
  @media (min-width: 40rem) {
183
99
  .docs-footer-page-inner,
184
- .docs-site-footer-inner {
100
+ .docs-footer-shell :global(.ts-public-footer__inner) {
185
101
  padding-inline: 1.5rem;
186
102
  }
187
103
  }
188
104
 
189
105
  @media (min-width: 64rem) {
190
106
  .docs-footer-page-inner,
191
- .docs-site-footer-inner {
107
+ .docs-footer-shell :global(.ts-public-footer__inner) {
192
108
  padding-inline: 2rem;
193
109
  }
194
110
  }
@@ -3,7 +3,6 @@ import config from 'virtual:starlight/user-config';
3
3
 
4
4
  import LanguageSelect from '../../vendor/starlight/components/LanguageSelect.astro';
5
5
  import Search from '../../vendor/starlight/components/Search.astro';
6
- import SiteTitle from '../../vendor/starlight/components/SiteTitle.astro';
7
6
  import SocialIcons from '../../vendor/starlight/components/SocialIcons.astro';
8
7
  import DesktopSidebarToggle from './DesktopSidebarToggle.astro';
9
8
  import BookFontControls from './BookFontControls.astro';
@@ -18,7 +17,15 @@ const hasToc = Boolean(toc);
18
17
 
19
18
  <div class="header">
20
19
  <div class="title-wrapper sl-flex">
21
- <SiteTitle />
20
+ <a class="ts-shell-brand" href="/">
21
+ <span class="ts-shell-brand__mark">
22
+ <img src={SITE.logo.src} alt={SITE.logo.alt} width="60" height="60" loading="eager" />
23
+ </span>
24
+ <span class="ts-shell-brand__text">
25
+ <span class="ts-shell-brand__name">{SITE.name}</span>
26
+ <span class="ts-shell-brand__tag">{SITE.statement}</span>
27
+ </span>
28
+ </a>
22
29
  </div>
23
30
  <div class="sl-hidden md:sl-flex print:hidden right-group">
24
31
  <div class="desktop-sidebar-toggles" aria-label="Reading controls">
@@ -24,7 +24,7 @@ const PAGE_TITLE_ID = '_top';
24
24
  font-size: clamp(1rem, 1.1vw, 1.4rem);
25
25
  line-height: 1.18;
26
26
  font-weight: 800;
27
- color: var(--site-accent-strong);
27
+ color: var(--ts-color-accent-strong);
28
28
  text-wrap: pretty;
29
29
  }
30
30
 
@@ -1,3 +1,5 @@
1
1
  ---
2
- // Intentionally empty to remove Starlight's theme/color selector from the docs UI.
2
+ import ThemeScript from '../ui/theme/ThemeScript.astro';
3
3
  ---
4
+
5
+ <ThemeScript includeCss={false} />
@@ -33,8 +33,8 @@ const formsApiBaseUrl = SITE_FORMS?.apiBaseUrl ?? '/api/form/submit';
33
33
  <div class:list={[
34
34
  'rounded-lg border px-4 py-3 text-sm font-medium',
35
35
  status === 'success'
36
- ? 'border-[color:var(--site-blue)] bg-[color:var(--site-blue-soft)] text-[color:var(--site-text)]'
37
- : 'border-[color:var(--site-warm)] bg-[color:rgba(194,139,91,0.14)] text-[color:var(--site-text)]',
36
+ ? 'border-[color:var(--ts-color-info)] bg-[color:var(--ts-color-info-soft)] text-[color:var(--ts-color-text)]'
37
+ : 'border-[color:var(--ts-color-warning)] bg-[color:var(--ts-color-warning-soft)] text-[color:var(--ts-color-text)]',
38
38
  ]}>
39
39
  {statusMessage}
40
40
  </div>
@@ -47,8 +47,8 @@ const formsApiBaseUrl = SITE_FORMS?.apiBaseUrl ?? '/api/form/submit';
47
47
  data-form-type="contact"
48
48
  data-turnstile-action="contact_submit"
49
49
  >
50
- <p class="text-sm text-[color:var(--site-text-soft)]">
51
- Fields marked <span class="font-semibold text-[color:var(--site-warm)]">*</span> are required.
50
+ <p class="text-sm text-[color:var(--ts-color-text-subtle)]">
51
+ Fields marked <span class="font-semibold text-[color:var(--ts-color-warning)]">*</span> are required.
52
52
  </p>
53
53
  <input type="hidden" name="formType" value="contact" />
54
54
  <input type="hidden" name="formToken" value="" />
@@ -63,9 +63,9 @@ const formsApiBaseUrl = SITE_FORMS?.apiBaseUrl ?? '/api/form/submit';
63
63
 
64
64
  <div class="grid gap-5 md:grid-cols-2">
65
65
  <label class="grid gap-2">
66
- <span class="text-sm font-semibold text-[color:var(--site-text)]">Name <span aria-hidden="true" class="text-[color:var(--site-warm)]">*</span></span>
66
+ <span class="text-sm font-semibold text-[color:var(--ts-color-text)]">Name <span aria-hidden="true" class="text-[color:var(--ts-color-warning)]">*</span></span>
67
67
  <input
68
- class="min-h-12 rounded-md border border-[color:var(--site-border-strong)] bg-white/70 px-4 py-3"
68
+ class="min-h-12 rounded-md border border-[color:var(--ts-color-border-strong)] bg-white/70 px-4 py-3"
69
69
  type="text"
70
70
  name="name"
71
71
  autocomplete="name"
@@ -74,9 +74,9 @@ const formsApiBaseUrl = SITE_FORMS?.apiBaseUrl ?? '/api/form/submit';
74
74
  />
75
75
  </label>
76
76
  <label class="grid gap-2">
77
- <span class="text-sm font-semibold text-[color:var(--site-text)]">Email <span aria-hidden="true" class="text-[color:var(--site-warm)]">*</span></span>
77
+ <span class="text-sm font-semibold text-[color:var(--ts-color-text)]">Email <span aria-hidden="true" class="text-[color:var(--ts-color-warning)]">*</span></span>
78
78
  <input
79
- class="min-h-12 rounded-md border border-[color:var(--site-border-strong)] bg-white/70 px-4 py-3"
79
+ class="min-h-12 rounded-md border border-[color:var(--ts-color-border-strong)] bg-white/70 px-4 py-3"
80
80
  type="email"
81
81
  name="email"
82
82
  autocomplete="email"
@@ -88,18 +88,18 @@ const formsApiBaseUrl = SITE_FORMS?.apiBaseUrl ?? '/api/form/submit';
88
88
 
89
89
  <div class="grid gap-5 md:grid-cols-[minmax(0,1fr)_minmax(0,1fr)]">
90
90
  <label class="grid gap-2">
91
- <span class="text-sm font-semibold text-[color:var(--site-text)]">Organization</span>
91
+ <span class="text-sm font-semibold text-[color:var(--ts-color-text)]">Organization</span>
92
92
  <input
93
- class="min-h-12 rounded-md border border-[color:var(--site-border-strong)] bg-white/70 px-4 py-3"
93
+ class="min-h-12 rounded-md border border-[color:var(--ts-color-border-strong)] bg-white/70 px-4 py-3"
94
94
  type="text"
95
95
  name="organization"
96
96
  autocomplete="organization"
97
97
  />
98
98
  </label>
99
99
  <label class="grid gap-2">
100
- <span class="text-sm font-semibold text-[color:var(--site-text)]">Topic <span aria-hidden="true" class="text-[color:var(--site-warm)]">*</span></span>
100
+ <span class="text-sm font-semibold text-[color:var(--ts-color-text)]">Topic <span aria-hidden="true" class="text-[color:var(--ts-color-warning)]">*</span></span>
101
101
  <select
102
- class="min-h-12 rounded-md border border-[color:var(--site-border-strong)] bg-white/70 px-4 py-3"
102
+ class="min-h-12 rounded-md border border-[color:var(--ts-color-border-strong)] bg-white/70 px-4 py-3"
103
103
  name="contactType"
104
104
  required
105
105
  aria-required="true"
@@ -112,9 +112,9 @@ const formsApiBaseUrl = SITE_FORMS?.apiBaseUrl ?? '/api/form/submit';
112
112
  </div>
113
113
 
114
114
  <label class="grid gap-2">
115
- <span class="text-sm font-semibold text-[color:var(--site-text)]">Subject <span aria-hidden="true" class="text-[color:var(--site-warm)]">*</span></span>
115
+ <span class="text-sm font-semibold text-[color:var(--ts-color-text)]">Subject <span aria-hidden="true" class="text-[color:var(--ts-color-warning)]">*</span></span>
116
116
  <input
117
- class="min-h-12 rounded-md border border-[color:var(--site-border-strong)] bg-white/70 px-4 py-3"
117
+ class="min-h-12 rounded-md border border-[color:var(--ts-color-border-strong)] bg-white/70 px-4 py-3"
118
118
  type="text"
119
119
  name="subject"
120
120
  required
@@ -123,9 +123,9 @@ const formsApiBaseUrl = SITE_FORMS?.apiBaseUrl ?? '/api/form/submit';
123
123
  </label>
124
124
 
125
125
  <label class="grid gap-2">
126
- <span class="text-sm font-semibold text-[color:var(--site-text)]">Message <span aria-hidden="true" class="text-[color:var(--site-warm)]">*</span></span>
126
+ <span class="text-sm font-semibold text-[color:var(--ts-color-text)]">Message <span aria-hidden="true" class="text-[color:var(--ts-color-warning)]">*</span></span>
127
127
  <textarea
128
- class="min-h-48 rounded-md border border-[color:var(--site-border-strong)] bg-white/70 px-4 py-3"
128
+ class="min-h-48 rounded-md border border-[color:var(--ts-color-border-strong)] bg-white/70 px-4 py-3"
129
129
  name="message"
130
130
  required
131
131
  aria-required="true"
@@ -133,24 +133,24 @@ const formsApiBaseUrl = SITE_FORMS?.apiBaseUrl ?? '/api/form/submit';
133
133
  </label>
134
134
 
135
135
  {TREESEED_PUBLIC_TURNSTILE_SITE_KEY && !shouldBypassTurnstile ? (
136
- <div class="js-turnstile rounded-md border border-dashed border-[color:var(--site-border-strong)] p-3"></div>
136
+ <div class="js-turnstile rounded-md border border-dashed border-[color:var(--ts-color-border-strong)] p-3"></div>
137
137
  ) : shouldBypassTurnstile ? (
138
- <p class="rounded-md border border-[color:var(--site-blue)] bg-[color:var(--site-blue-soft)] px-4 py-3 text-sm text-[color:var(--site-text)]">
138
+ <p class="rounded-md border border-[color:var(--ts-color-info)] bg-[color:var(--ts-color-info-soft)] px-4 py-3 text-sm text-[color:var(--ts-color-text)]">
139
139
  Local development mode is bypassing Turnstile so you can test the form workflow without Cloudflare captcha.
140
140
  </p>
141
141
  ) : (
142
- <p class="rounded-md border border-[color:var(--site-warm)] bg-[color:rgba(194,139,91,0.14)] px-4 py-3 text-sm text-[color:var(--site-text)]">
142
+ <p class="rounded-md border border-[color:var(--ts-color-warning)] bg-[color:var(--ts-color-warning-soft)] px-4 py-3 text-sm text-[color:var(--ts-color-text)]">
143
143
  Turnstile is not configured yet. Add `TREESEED_PUBLIC_TURNSTILE_SITE_KEY` before deploying forms.
144
144
  </p>
145
145
  )}
146
146
 
147
147
  <div class="flex flex-wrap items-center justify-between gap-4">
148
- <p class="text-sm leading-7 text-[color:var(--site-text-soft)]">
148
+ <p class="text-sm leading-7 text-[color:var(--ts-color-text-subtle)]">
149
149
  By sending this message, you agree that we may reply by email about this inquiry.
150
150
  </p>
151
151
  <button
152
152
  type="submit"
153
- class="js-submit inline-flex min-h-12 items-center justify-center border border-[color:var(--site-accent)] bg-[color:var(--site-accent)] px-6 py-3 text-base font-semibold text-[color:var(--site-text)] transition hover:border-[color:var(--site-blue)] hover:bg-[color:var(--site-blue-soft)] disabled:cursor-not-allowed disabled:opacity-60"
153
+ class="js-submit inline-flex min-h-12 items-center justify-center border border-[color:var(--ts-color-accent)] bg-[color:var(--ts-color-accent)] px-6 py-3 text-base font-semibold text-[color:var(--ts-color-text)] transition hover:border-[color:var(--ts-color-info)] hover:bg-[color:var(--ts-color-info-soft)] disabled:cursor-not-allowed disabled:opacity-60"
154
154
  disabled
155
155
  >
156
156
  Send message
@@ -11,11 +11,11 @@ const shouldBypassTurnstile = import.meta.env.DEV;
11
11
  const formsApiBaseUrl = SITE_FORMS?.apiBaseUrl ?? '/api/form/submit';
12
12
  ---
13
13
 
14
- <section id={SUBSCRIBE_ANCHOR_ID} class="mt-6 border-t border-[color:var(--site-border)] pt-4">
14
+ <section id={SUBSCRIBE_ANCHOR_ID} class="mt-6 border-t border-[color:var(--ts-color-border)] pt-4">
15
15
  <div class="flex flex-col items-center gap-3 text-center">
16
16
  <div class="flex flex-col gap-1">
17
- <p class="text-sm font-semibold uppercase tracking-[0.16em] text-[color:var(--site-blue-strong)]">Subscribe for updates</p>
18
- <p class="text-sm text-[color:var(--site-text-muted)]">
17
+ <p class="text-sm font-semibold uppercase tracking-[0.16em] text-[color:var(--ts-color-info-text)]">Subscribe for updates</p>
18
+ <p class="text-sm text-[color:var(--ts-color-text-muted)]">
19
19
  Get occasional notes when new writing or project updates are published.
20
20
  </p>
21
21
  </div>
@@ -40,7 +40,7 @@ const formsApiBaseUrl = SITE_FORMS?.apiBaseUrl ?? '/api/form/submit';
40
40
  <input type="hidden" name="name" value="" />
41
41
  <div class="flex w-full flex-col items-center justify-center gap-3 md:flex-row md:flex-wrap">
42
42
  <input
43
- class="min-h-11 w-full rounded-md border border-[color:var(--site-border-strong)] bg-white/80 px-4 py-2 md:w-auto md:min-w-[16rem] md:max-w-[18rem]"
43
+ class="min-h-11 w-full rounded-md border border-[color:var(--ts-color-border-strong)] bg-white/80 px-4 py-2 md:w-auto md:min-w-[16rem] md:max-w-[18rem]"
44
44
  type="email"
45
45
  name="email"
46
46
  placeholder="Email address"
@@ -50,13 +50,13 @@ const formsApiBaseUrl = SITE_FORMS?.apiBaseUrl ?? '/api/form/submit';
50
50
  {TREESEED_PUBLIC_TURNSTILE_SITE_KEY && !shouldBypassTurnstile ? (
51
51
  <div class="js-turnstile min-h-0"></div>
52
52
  ) : shouldBypassTurnstile ? (
53
- <p class="text-xs text-[color:var(--site-text-soft)]">Captcha bypassed locally.</p>
53
+ <p class="text-xs text-[color:var(--ts-color-text-subtle)]">Captcha bypassed locally.</p>
54
54
  ) : (
55
- <p class="text-xs text-[color:var(--site-text-soft)]">Turnstile not configured.</p>
55
+ <p class="text-xs text-[color:var(--ts-color-text-subtle)]">Turnstile not configured.</p>
56
56
  )}
57
57
  <button
58
58
  type="submit"
59
- class="js-submit inline-flex min-h-11 items-center justify-center whitespace-nowrap border border-[color:var(--site-accent)] bg-[color:var(--site-accent)] px-4 py-2 text-sm font-semibold text-[color:var(--site-text)] transition hover:border-[color:var(--site-blue)] hover:bg-[color:var(--site-blue-soft)] disabled:cursor-not-allowed disabled:opacity-60"
59
+ class="js-submit inline-flex min-h-11 items-center justify-center whitespace-nowrap border border-[color:var(--ts-color-accent)] bg-[color:var(--ts-color-accent)] px-4 py-2 text-sm font-semibold text-[color:var(--ts-color-text)] transition hover:border-[color:var(--ts-color-info)] hover:bg-[color:var(--ts-color-info-soft)] disabled:cursor-not-allowed disabled:opacity-60"
60
60
  disabled
61
61
  >
62
62
  Subscribe
@@ -106,9 +106,9 @@ const formsApiBaseUrl = SITE_FORMS?.apiBaseUrl ?? '/api/form/submit';
106
106
  statusNode.textContent = subscribeMessages[code] ?? (status === 'success' ? 'Subscription complete.' : 'We could not complete the signup.');
107
107
  statusNode.classList.remove('hidden');
108
108
  if (status === 'success') {
109
- statusNode.className = 'js-subscribe-status rounded-md border border-[color:var(--site-blue)] bg-[color:var(--site-blue-soft)] px-4 py-2 text-sm font-medium text-[color:var(--site-text)]';
109
+ statusNode.className = 'js-subscribe-status rounded-md border border-[color:var(--ts-color-info)] bg-[color:var(--ts-color-info-soft)] px-4 py-2 text-sm font-medium text-[color:var(--ts-color-text)]';
110
110
  } else {
111
- statusNode.className = 'js-subscribe-status rounded-md border border-[color:var(--site-warm)] bg-[color:rgba(194,139,91,0.14)] px-4 py-2 text-sm font-medium text-[color:var(--site-text)]';
111
+ statusNode.className = 'js-subscribe-status rounded-md border border-[color:var(--ts-color-warning)] bg-[color:var(--ts-color-warning-soft)] px-4 py-2 text-sm font-medium text-[color:var(--ts-color-text)]';
112
112
  }
113
113
  };
114
114
 
@@ -13,14 +13,14 @@ const { items } = Astro.props as { items: BookItem[] };
13
13
 
14
14
  <div class="grid gap-6 md:grid-cols-2">
15
15
  {items.map((item) => (
16
- <div class="border border-[color:var(--site-border)] bg-[color:var(--site-surface)] p-6">
17
- <p class="text-sm font-semibold uppercase tracking-[0.14em] text-[color:var(--site-blue-strong)]">{item.meta}</p>
18
- <h3 class="mt-4 text-2xl font-bold text-[color:var(--site-text)]">{item.title}</h3>
19
- <p class="mt-3 text-base leading-8 text-[color:var(--site-text-muted)]">{item.summary}</p>
16
+ <div class="border border-[color:var(--ts-color-border)] bg-[color:var(--ts-color-surface)] p-6">
17
+ <p class="text-sm font-semibold uppercase tracking-[0.14em] text-[color:var(--ts-color-info-text)]">{item.meta}</p>
18
+ <h3 class="mt-4 text-2xl font-bold text-[color:var(--ts-color-text)]">{item.title}</h3>
19
+ <p class="mt-3 text-base leading-8 text-[color:var(--ts-color-text-muted)]">{item.summary}</p>
20
20
  <div class="mt-5 flex flex-wrap gap-3">
21
- <a href={item.href} class="border border-[color:var(--site-border-strong)] px-4 py-2 text-sm font-semibold text-[color:var(--site-text)] transition hover:border-[color:var(--site-blue)] hover:bg-[color:var(--site-blue-soft)]">Book page</a>
22
- <a href={item.landingPath} class="border border-[color:var(--site-border-strong)] px-4 py-2 text-sm font-semibold text-[color:var(--site-text)] transition hover:border-[color:var(--site-blue)] hover:bg-[color:var(--site-blue-soft)]">Open knowledge</a>
23
- <a href={item.downloadHref} class="border border-[color:var(--site-accent)] bg-[color:var(--site-accent)] px-4 py-2 text-sm font-semibold text-[color:var(--site-text)] transition hover:border-[color:var(--site-blue)] hover:bg-[color:var(--site-blue-soft)]">Download</a>
21
+ <a href={item.href} class="border border-[color:var(--ts-color-border-strong)] px-4 py-2 text-sm font-semibold text-[color:var(--ts-color-text)] transition hover:border-[color:var(--ts-color-info)] hover:bg-[color:var(--ts-color-info-soft)]">Book page</a>
22
+ <a href={item.landingPath} class="border border-[color:var(--ts-color-border-strong)] px-4 py-2 text-sm font-semibold text-[color:var(--ts-color-text)] transition hover:border-[color:var(--ts-color-info)] hover:bg-[color:var(--ts-color-info-soft)]">Open knowledge</a>
23
+ <a href={item.downloadHref} class="border border-[color:var(--ts-color-accent)] bg-[color:var(--ts-color-accent)] px-4 py-2 text-sm font-semibold text-[color:var(--ts-color-text)] transition hover:border-[color:var(--ts-color-info)] hover:bg-[color:var(--ts-color-info-soft)]">Download</a>
24
24
  </div>
25
25
  </div>
26
26
  ))}
@@ -2,19 +2,19 @@
2
2
  const { title, body, primaryHref, primaryLabel, secondaryHref, secondaryLabel } = Astro.props;
3
3
  ---
4
4
 
5
- <section class="site-footer-cta px-0 py-0 text-[color:var(--site-text)]">
5
+ <section class="site-footer-cta px-0 py-0 text-[color:var(--ts-color-text)]">
6
6
  <div class="site-footer-cta__inner">
7
7
  <div class="mx-auto flex max-w-4xl flex-col items-center gap-6">
8
8
  <div class="max-w-3xl">
9
9
  <h2 class="font-serif text-3xl font-bold md:text-4xl">{title}</h2>
10
- <p class="mt-4 text-lg leading-9 text-[color:var(--site-text-muted)]">{body}</p>
10
+ <p class="mt-4 text-lg leading-9 text-[color:var(--ts-color-text-muted)]">{body}</p>
11
11
  </div>
12
12
  <div class="flex flex-wrap justify-center gap-3">
13
- <a href={primaryHref} class="border border-[color:var(--site-accent)] bg-[color:var(--site-accent)] px-5 py-3 text-base font-semibold text-[color:var(--site-text)] transition hover:border-[color:var(--site-blue)] hover:bg-[color:var(--site-blue-soft)]">{
13
+ <a href={primaryHref} class="border border-[color:var(--ts-color-accent)] bg-[color:var(--ts-color-accent)] px-5 py-3 text-base font-semibold text-[color:var(--ts-color-text)] transition hover:border-[color:var(--ts-color-info)] hover:bg-[color:var(--ts-color-info-soft)]">{
14
14
  primaryLabel
15
15
  }</a>
16
16
  {secondaryHref && secondaryLabel && (
17
- <a href={secondaryHref} class="border border-[color:var(--site-border-strong)] bg-[color:rgba(248,243,233,0.72)] px-5 py-3 text-base font-semibold text-[color:var(--site-text)] transition hover:border-[color:var(--site-blue)] hover:bg-[color:var(--site-blue-soft)]">
17
+ <a href={secondaryHref} class="border border-[color:var(--ts-color-border-strong)] bg-[color:var(--ts-color-surface-muted)] px-5 py-3 text-base font-semibold text-[color:var(--ts-color-text)] transition hover:border-[color:var(--ts-color-info)] hover:bg-[color:var(--ts-color-info-soft)]">
18
18
  {secondaryLabel}
19
19
  </a>
20
20
  )}
@@ -17,16 +17,16 @@ const { items } = Astro.props as { items: ChronicleItem[] };
17
17
 
18
18
  <div class="grid gap-1">
19
19
  {items.map((item) => (
20
- <a href={item.href} class="block border-t border-[color:var(--site-border)] py-7 transition hover:border-[color:var(--site-border-strong)]">
20
+ <a href={item.href} class="block border-t border-[color:var(--ts-color-border)] py-7 transition hover:border-[color:var(--ts-color-border-strong)]">
21
21
  <div class="flex flex-wrap items-center gap-4">
22
22
  <StatusBadge status={item.status} />
23
- <p class="text-sm font-medium text-[color:var(--site-text-soft)]">{item.date.toISOString().slice(0, 10)}</p>
24
- {item.meta && <p class="text-sm text-[color:var(--site-text-soft)]">{item.meta}</p>}
23
+ <p class="text-sm font-medium text-[color:var(--ts-color-text-subtle)]">{item.date.toISOString().slice(0, 10)}</p>
24
+ {item.meta && <p class="text-sm text-[color:var(--ts-color-text-subtle)]">{item.meta}</p>}
25
25
  </div>
26
- <h3 class="mt-4 max-w-3xl text-2xl font-bold text-[color:var(--site-text)] md:text-3xl">{item.title}</h3>
27
- <p class="mt-3 max-w-3xl text-lg leading-9 text-[color:var(--site-text-muted)]">{item.summary}</p>
26
+ <h3 class="mt-4 max-w-3xl text-2xl font-bold text-[color:var(--ts-color-text)] md:text-3xl">{item.title}</h3>
27
+ <p class="mt-3 max-w-3xl text-lg leading-9 text-[color:var(--ts-color-text-muted)]">{item.summary}</p>
28
28
  {item.tags && item.tags.length > 0 && (
29
- <p class="mt-4 text-sm uppercase tracking-[0.14em] text-[color:var(--site-accent-strong)]">{item.tags.join(' / ')}</p>
29
+ <p class="mt-4 text-sm uppercase tracking-[0.14em] text-[color:var(--ts-color-accent-strong)]">{item.tags.join(' / ')}</p>
30
30
  )}
31
31
  </a>
32
32
  ))}
@@ -1,5 +1,5 @@
1
- <section class="relative overflow-hidden border-y border-[color:var(--site-border-strong)] py-12 md:py-18">
2
- <div class="absolute inset-y-0 left-[68%] hidden w-px bg-[linear-gradient(180deg,transparent,var(--site-border-strong),transparent)] lg:block"></div>
1
+ <section class="relative overflow-hidden border-y border-[color:var(--ts-color-border-strong)] py-12 md:py-18">
2
+ <div class="absolute inset-y-0 left-[68%] hidden w-px bg-[linear-gradient(180deg,transparent,var(--ts-color-border-strong),transparent)] lg:block"></div>
3
3
  <div class="grid gap-10 lg:grid-cols-[1.45fr_0.7fr] lg:items-start">
4
4
  <div class="space-y-7 pr-0 lg:pr-10">
5
5
  <slot name="eyebrow" />
@@ -11,7 +11,7 @@
11
11
  <slot name="actions" />
12
12
  </div>
13
13
  </div>
14
- <div class="border-l border-[color:var(--site-border)] pl-0 lg:pl-8">
14
+ <div class="border-l border-[color:var(--ts-color-border)] pl-0 lg:pl-8">
15
15
  <slot name="aside" />
16
16
  </div>
17
17
  </div>
@@ -2,15 +2,15 @@
2
2
  const { href, title, description, meta } = Astro.props;
3
3
  ---
4
4
 
5
- <a href={href} class="group block border-t border-[color:var(--site-border)] py-6 transition hover:border-[color:var(--site-border-strong)]">
5
+ <a href={href} class="group block border-t border-[color:var(--ts-color-border)] py-6 transition hover:border-[color:var(--ts-color-border-strong)]">
6
6
  <div class="grid gap-3 md:grid-cols-[0.42fr_1fr_auto] md:items-start md:gap-6">
7
7
  <div>
8
- {meta && <p class="text-sm font-semibold uppercase tracking-[0.14em] text-[color:var(--site-accent-strong)]">{meta}</p>}
8
+ {meta && <p class="text-sm font-semibold uppercase tracking-[0.14em] text-[color:var(--ts-color-accent-strong)]">{meta}</p>}
9
9
  </div>
10
10
  <div>
11
- <h3 class="text-2xl font-bold text-[color:var(--site-text)]">{title}</h3>
12
- <p class="mt-3 max-w-2xl text-base leading-8 text-[color:var(--site-text-muted)]">{description}</p>
11
+ <h3 class="text-2xl font-bold text-[color:var(--ts-color-text)]">{title}</h3>
12
+ <p class="mt-3 max-w-2xl text-base leading-8 text-[color:var(--ts-color-text-muted)]">{description}</p>
13
13
  </div>
14
- <p class="text-sm font-semibold uppercase tracking-[0.14em] text-[color:var(--site-blue-strong)] group-hover:text-[color:var(--site-accent-strong)]">Open path</p>
14
+ <p class="text-sm font-semibold uppercase tracking-[0.14em] text-[color:var(--ts-color-info-text)] group-hover:text-[color:var(--ts-color-accent-strong)]">Open path</p>
15
15
  </div>
16
16
  </a>
@@ -15,15 +15,15 @@ const { items } = Astro.props as { items: ProfileItem[] };
15
15
 
16
16
  <div class="grid gap-6 md:grid-cols-2">
17
17
  {items.map((item) => (
18
- <a href={item.href} class="border border-[color:var(--site-border)] bg-[color:var(--site-surface)] p-6 transition hover:border-[color:var(--site-border-strong)]">
18
+ <a href={item.href} class="border border-[color:var(--ts-color-border)] bg-[color:var(--ts-color-surface)] p-6 transition hover:border-[color:var(--ts-color-border-strong)]">
19
19
  <div class="flex flex-wrap items-center gap-3">
20
20
  {item.status && <StatusBadge status={item.status} />}
21
- <p class="text-sm font-semibold uppercase tracking-[0.14em] text-[color:var(--site-blue-strong)]">{item.meta}</p>
21
+ <p class="text-sm font-semibold uppercase tracking-[0.14em] text-[color:var(--ts-color-info-text)]">{item.meta}</p>
22
22
  </div>
23
- <h3 class="mt-4 text-2xl font-bold text-[color:var(--site-text)]">{item.name}</h3>
24
- <p class="mt-3 text-base leading-8 text-[color:var(--site-text-muted)]">{item.summary}</p>
23
+ <h3 class="mt-4 text-2xl font-bold text-[color:var(--ts-color-text)]">{item.name}</h3>
24
+ <p class="mt-3 text-base leading-8 text-[color:var(--ts-color-text-muted)]">{item.summary}</p>
25
25
  {item.tags && item.tags.length > 0 && (
26
- <p class="mt-4 text-sm uppercase tracking-[0.14em] text-[color:var(--site-accent-strong)]">{item.tags.join(' / ')}</p>
26
+ <p class="mt-4 text-sm uppercase tracking-[0.14em] text-[color:var(--ts-color-accent-strong)]">{item.tags.join(' / ')}</p>
27
27
  )}
28
28
  </a>
29
29
  ))}