@takazudo/zudo-doc 4.3.0 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/bin/zudo-doc.mjs +54 -13
  3. package/dist/auto-logo/index.d.ts +18 -0
  4. package/dist/auto-logo/index.js +33 -0
  5. package/dist/auto-logo/shapes.d.ts +32 -0
  6. package/dist/auto-logo/shapes.js +183 -0
  7. package/dist/auto-logo/standalone.d.ts +7 -0
  8. package/dist/auto-logo/standalone.js +35 -0
  9. package/dist/config.d.ts +8 -0
  10. package/dist/config.js +1 -0
  11. package/dist/content.css +4 -3
  12. package/dist/doc-content-header/index.js +1 -1
  13. package/dist/doc-history/index.js +1 -1
  14. package/dist/doc-page-shell/index.js +1 -1
  15. package/dist/doc-pager/index.js +2 -2
  16. package/dist/eject-logo/config-parse.d.ts +25 -0
  17. package/dist/eject-logo/config-parse.js +68 -0
  18. package/dist/eject-logo/config-rewriter.d.ts +22 -0
  19. package/dist/eject-logo/config-rewriter.js +68 -0
  20. package/dist/eject-logo/eject.d.ts +18 -0
  21. package/dist/eject-logo/eject.js +66 -0
  22. package/dist/eject-logo/index.d.ts +4 -0
  23. package/dist/eject-logo/index.js +16 -0
  24. package/dist/eject-logo/site-name.d.ts +21 -0
  25. package/dist/eject-logo/site-name.js +31 -0
  26. package/dist/header/header.js +14 -6
  27. package/dist/header/nav-class-tokens.d.ts +12 -0
  28. package/dist/header/nav-class-tokens.js +80 -0
  29. package/dist/header/nav-overflow-script.js +33 -16
  30. package/dist/home-page/index.d.ts +34 -5
  31. package/dist/home-page/index.js +95 -38
  32. package/dist/home-page/prepare-home-data.d.ts +9 -0
  33. package/dist/home-page/prepare-home-data.js +10 -3
  34. package/dist/i18n-defaults/index.js +3 -0
  35. package/dist/metainfo/doc-metainfo.js +35 -22
  36. package/dist/routes/index.js +2 -1
  37. package/dist/routes/locale-index.js +2 -1
  38. package/dist/safelist.css +1 -1
  39. package/dist/settings.d.ts +7 -0
  40. package/dist/sidebar-tree-island/index.js +3 -3
  41. package/dist/theme-cli/config-scanner.js +47 -0
  42. package/dist/theme-packs/academia/fonts/CourierPrime-400-latin.woff2 +0 -0
  43. package/dist/theme-packs/academia/fonts/CourierPrime-700-latin.woff2 +0 -0
  44. package/dist/theme-packs/academia/fonts/OFL.txt +94 -0
  45. package/dist/theme-packs/academia/fonts/SourceSerif4-italic-latin.woff2 +0 -0
  46. package/dist/theme-packs/academia/fonts/SourceSerif4-latin.woff2 +0 -0
  47. package/dist/theme-packs/academia/meta.json +37 -0
  48. package/dist/theme-packs/academia/pack.css +505 -0
  49. package/dist/theme-packs/bauhaus/fonts/ArchivoBlack-latin.woff2 +0 -0
  50. package/dist/theme-packs/bauhaus/fonts/Jost-latin.woff2 +0 -0
  51. package/dist/theme-packs/bauhaus/fonts/OFL.txt +95 -0
  52. package/dist/theme-packs/bauhaus/fonts/SpaceMono-400-latin.woff2 +0 -0
  53. package/dist/theme-packs/bauhaus/fonts/SpaceMono-700-latin.woff2 +0 -0
  54. package/dist/theme-packs/bauhaus/meta.json +38 -0
  55. package/dist/theme-packs/bauhaus/pack.css +614 -0
  56. package/dist/theme-packs/blueprint/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
  57. package/dist/theme-packs/blueprint/fonts/IBMPlexMono-400-latin.woff2 +0 -0
  58. package/dist/theme-packs/blueprint/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
  59. package/dist/theme-packs/blueprint/fonts/IBMPlexMono-500-latin.woff2 +0 -0
  60. package/dist/theme-packs/blueprint/fonts/Inter-latin-ext.woff2 +0 -0
  61. package/dist/theme-packs/blueprint/fonts/Inter-latin.woff2 +0 -0
  62. package/dist/theme-packs/blueprint/fonts/JosefinSans-latin.woff2 +0 -0
  63. package/dist/theme-packs/blueprint/fonts/OFL.txt +95 -0
  64. package/dist/theme-packs/blueprint/meta.json +38 -0
  65. package/dist/theme-packs/blueprint/pack.css +577 -0
  66. package/dist/theme-packs/botanica/fonts/CormorantGaramond-latin.woff2 +0 -0
  67. package/dist/theme-packs/botanica/fonts/CourierPrime-400-latin-ext.woff2 +0 -0
  68. package/dist/theme-packs/botanica/fonts/CourierPrime-400-latin.woff2 +0 -0
  69. package/dist/theme-packs/botanica/fonts/CourierPrime-700-latin-ext.woff2 +0 -0
  70. package/dist/theme-packs/botanica/fonts/CourierPrime-700-latin.woff2 +0 -0
  71. package/dist/theme-packs/botanica/fonts/CrimsonPro-latin-italic.woff2 +0 -0
  72. package/dist/theme-packs/botanica/fonts/CrimsonPro-latin.woff2 +0 -0
  73. package/dist/theme-packs/botanica/fonts/OFL.txt +95 -0
  74. package/dist/theme-packs/botanica/meta.json +38 -0
  75. package/dist/theme-packs/botanica/pack.css +546 -0
  76. package/dist/theme-packs/brutalist/meta.json +1 -1
  77. package/dist/theme-packs/brutalist/pack.css +10 -9
  78. package/dist/theme-packs/eink/fonts/CourierPrime-400-latin-ext.woff2 +0 -0
  79. package/dist/theme-packs/eink/fonts/CourierPrime-400-latin.woff2 +0 -0
  80. package/dist/theme-packs/eink/fonts/CourierPrime-700-latin-ext.woff2 +0 -0
  81. package/dist/theme-packs/eink/fonts/CourierPrime-700-latin.woff2 +0 -0
  82. package/dist/theme-packs/eink/fonts/EBGaramond-latin-italic.woff2 +0 -0
  83. package/dist/theme-packs/eink/fonts/EBGaramond-latin.woff2 +0 -0
  84. package/dist/theme-packs/eink/fonts/OFL.txt +94 -0
  85. package/dist/theme-packs/eink/meta.json +37 -0
  86. package/dist/theme-packs/eink/pack.css +490 -0
  87. package/dist/theme-packs/foundry/meta.json +1 -1
  88. package/dist/theme-packs/foundry/pack.css +2 -2
  89. package/dist/theme-packs/hearth/meta.json +1 -1
  90. package/dist/theme-packs/hearth/pack.css +1 -1
  91. package/dist/theme-packs/nocturne/pack.css +4 -0
  92. package/dist/theme-packs/observatory/meta.json +1 -1
  93. package/dist/theme-packs/observatory/pack.css +4 -1
  94. package/dist/theme-packs/onyx/pack.css +6 -0
  95. package/dist/theme-packs/phosphor/pack.css +4 -0
  96. package/dist/theme-packs/riso/fonts/ArchivoBlack-latin.woff2 +0 -0
  97. package/dist/theme-packs/riso/fonts/OFL.txt +95 -0
  98. package/dist/theme-packs/riso/fonts/SpaceGrotesk-latin.woff2 +0 -0
  99. package/dist/theme-packs/riso/fonts/SpaceMono-400-italic-latin.woff2 +0 -0
  100. package/dist/theme-packs/riso/fonts/SpaceMono-400-latin.woff2 +0 -0
  101. package/dist/theme-packs/riso/fonts/SpaceMono-700-latin.woff2 +0 -0
  102. package/dist/theme-packs/riso/meta.json +38 -0
  103. package/dist/theme-packs/riso/pack.css +602 -0
  104. package/dist/theme-packs/sakura/fonts/MPlus1Code-400-latin.woff2 +0 -0
  105. package/dist/theme-packs/sakura/fonts/MPlus1Code-500-latin.woff2 +0 -0
  106. package/dist/theme-packs/sakura/fonts/Nunito-latin.woff2 +0 -0
  107. package/dist/theme-packs/sakura/fonts/OFL.txt +95 -0
  108. package/dist/theme-packs/sakura/fonts/ShipporiMincho-600-latin.woff2 +0 -0
  109. package/dist/theme-packs/sakura/fonts/ShipporiMincho-700-latin.woff2 +0 -0
  110. package/dist/theme-packs/sakura/meta.json +38 -0
  111. package/dist/theme-packs/sakura/pack.css +473 -0
  112. package/dist/theme-packs/scandi/fonts/Manrope-latin.woff2 +0 -0
  113. package/dist/theme-packs/scandi/fonts/OFL.txt +94 -0
  114. package/dist/theme-packs/scandi/fonts/SplineSansMono-latin.woff2 +0 -0
  115. package/dist/theme-packs/scandi/meta.json +37 -0
  116. package/dist/theme-packs/scandi/pack.css +370 -0
  117. package/dist/theme-packs/sumi/meta.json +1 -1
  118. package/dist/theme-packs/sumi/pack.css +4 -1
  119. package/dist/theme-packs/swissgrid/pack.css +4 -0
  120. package/dist/theme-packs/tidepool/fonts/JetBrainsMono-latin-ext.woff2 +0 -0
  121. package/dist/theme-packs/tidepool/fonts/JetBrainsMono-latin.woff2 +0 -0
  122. package/dist/theme-packs/tidepool/fonts/OFL.txt +94 -0
  123. package/dist/theme-packs/tidepool/fonts/SpaceGrotesk-latin.woff2 +0 -0
  124. package/dist/theme-packs/tidepool/meta.json +37 -0
  125. package/dist/theme-packs/tidepool/pack.css +425 -0
  126. package/dist/theme-packs/timberline/fonts/Fraunces-italic-latin.woff2 +0 -0
  127. package/dist/theme-packs/timberline/fonts/Fraunces-latin.woff2 +0 -0
  128. package/dist/theme-packs/timberline/fonts/JetBrainsMono-latin.woff2 +0 -0
  129. package/dist/theme-packs/timberline/fonts/OFL.txt +95 -0
  130. package/dist/theme-packs/timberline/fonts/SourceSans3-italic-latin.woff2 +0 -0
  131. package/dist/theme-packs/timberline/fonts/SourceSans3-latin.woff2 +0 -0
  132. package/dist/theme-packs/timberline/meta.json +38 -0
  133. package/dist/theme-packs/timberline/pack.css +509 -0
  134. package/dist/theme-packs/washi/meta.json +1 -1
  135. package/dist/theme-packs/washi/pack.css +6 -26
  136. package/eject/doc-history/index.tsx +1 -1
  137. package/eject/doc-pager/index.tsx +2 -2
  138. package/eject/header/header.tsx +16 -8
  139. package/eject/header/nav-class-tokens.ts +115 -0
  140. package/eject/header/nav-overflow-script.ts +49 -16
  141. package/eject/sidebar-tree-island/index.tsx +4 -4
  142. package/package.json +16 -8
  143. package/routes-src/index.tsx +2 -1
  144. package/routes-src/locale-index.tsx +2 -1
@@ -0,0 +1,509 @@
1
+ /* ============================================================
2
+ Timberline — zudo-doc theme pack (ADR docs/adr/theme-packs.md)
3
+
4
+ Forest cabin after dark: deep pine/umber plank surfaces, cream
5
+ prose, and a lantern-amber accent with a restrained MATTE glow —
6
+ warm wood, never gold luxury (that territory is nocturne/onyx).
7
+ The signature moves are wood-plank hairline SEAMS (a dark groove
8
+ hairline paired with a soft chamfer-highlight hairline — border
9
+ and box-shadow treatments only, no image textures), pine/umber
10
+ LAYERED surfaces (umber page, pine sidebar/footer panels, the
11
+ deepest umber for the code "window at night"), and ember-orange
12
+ warnings. Light mode is designed deliberately as the same lodge
13
+ at morning: warm cream paper, pine ink, and a deep lantern-amber
14
+ link ink that clears AA on every cream surface.
15
+
16
+ Fraunces carries the display layer (title, h2, lead, blockquote,
17
+ table heads, pager titles) over a Source Sans 3 reading face and
18
+ JetBrains Mono code. Shape language: sawn lumber with a chamfer —
19
+ square-ish 4px edges (between hearth's cozy 12px and nocturne's
20
+ hard 0).
21
+
22
+ Every rule below is scoped under html[data-theme-pack="timberline"]
23
+ — this is what makes the runtime pack swap atomic (Decision 3)
24
+ and lets the validator prove a pack can never leak styles while
25
+ inactive (Decision 6.7). The @font-face blocks are the sole
26
+ exception (at-rules can't be selector-scoped).
27
+
28
+ Authored directly against the stable hook table
29
+ (docs/theme-pack-authoring.md (b)) — no prototype selectors were
30
+ carried over. Notes where the real DOM shaped a decision:
31
+ - the active TOC entry is `nav[data-zd-toc] a[aria-current="true"]`
32
+ (toc/toc.tsx marks it with aria-current; there is no .toc-active)
33
+ - the header nav hover excludes `[aria-current="page"]` — that item
34
+ carries the base inverted `bg-fg text-bg` fill, so an accent
35
+ recolor would sit amber-on-fg below AA (the nocturne lesson)
36
+ - the mobile drawer (`aside[data-zd-mobile-sidebar]`) and mobile
37
+ TOC (`div[data-zd-mobile-toc]`) are separate hooks from their
38
+ desktop counterparts and are themed alongside them
39
+ - the plank-seam helper values (groove + chamfer highlight) are
40
+ not part of the token manifest, so their light-dark() pairs are
41
+ inlined at each use site:
42
+ groove light-dark(oklch(0.83 0.032 85), oklch(0.142 0.016 55))
43
+ highlight light-dark(oklch(0.988 0.008 95 / 0.85), oklch(0.87 0.07 80 / 0.13))
44
+ ============================================================ */
45
+
46
+ /* ---- Fraunces — display serif for the title layer: h1/h2, logo,
47
+ lead, blockquote, table heads, pager titles. Weight-only
48
+ variable files (400–700), both styles — the lead and
49
+ blockquote want a TRUE italic. Latin subsets only (all three
50
+ families): a stray latin-ext glyph falls back to the stack's
51
+ system face. ---- */
52
+
53
+ @font-face {
54
+ font-family: "Fraunces";
55
+ font-style: normal;
56
+ font-weight: 400 700;
57
+ font-display: swap;
58
+ src: url("./fonts/Fraunces-latin.woff2") format("woff2");
59
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
60
+ U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
61
+ U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
62
+ }
63
+
64
+ @font-face {
65
+ font-family: "Fraunces";
66
+ font-style: italic;
67
+ font-weight: 400 700;
68
+ font-display: swap;
69
+ src: url("./fonts/Fraunces-italic-latin.woff2") format("woff2");
70
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
71
+ U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
72
+ U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
73
+ }
74
+
75
+ /* ---- Source Sans 3 — the reading face. Variable 200–900, both
76
+ styles (true italic for prose emphasis). ---- */
77
+
78
+ @font-face {
79
+ font-family: "Source Sans 3";
80
+ font-style: normal;
81
+ font-weight: 200 900;
82
+ font-display: swap;
83
+ src: url("./fonts/SourceSans3-latin.woff2") format("woff2");
84
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
85
+ U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
86
+ U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
87
+ }
88
+
89
+ @font-face {
90
+ font-family: "Source Sans 3";
91
+ font-style: italic;
92
+ font-weight: 200 900;
93
+ font-display: swap;
94
+ src: url("./fonts/SourceSans3-italic-latin.woff2") format("woff2");
95
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
96
+ U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
97
+ U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
98
+ }
99
+
100
+ /* ---- JetBrains Mono — the workshop code face. Variable 400–700.
101
+ No italic file is shipped; the .hi-com italic renders
102
+ synthesized-oblique (the fjord/ledger/matcha precedent). ---- */
103
+
104
+ @font-face {
105
+ font-family: "JetBrains Mono";
106
+ font-style: normal;
107
+ font-weight: 400 700;
108
+ font-display: swap;
109
+ src: url("./fonts/JetBrainsMono-latin.woff2") format("woff2");
110
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
111
+ U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
112
+ U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
113
+ }
114
+
115
+ html[data-theme-pack="timberline"] {
116
+ /* Tier-2 semantic roles — morning lodge / cabin after dark.
117
+ Both modes always via light-dark(). */
118
+ --zd-bg: light-dark(oklch(0.962 0.016 90), oklch(0.207 0.02 60));
119
+ --zd-fg: light-dark(oklch(0.27 0.032 155), oklch(0.928 0.02 88));
120
+ --zd-selection-bg: light-dark(oklch(0.86 0.07 80), oklch(0.5 0.09 65));
121
+ --zd-selection-fg: light-dark(oklch(0.25 0.03 150), oklch(0.97 0.012 90));
122
+ --zd-surface: light-dark(oklch(0.934 0.02 88), oklch(0.243 0.023 58));
123
+ --zd-muted: light-dark(oklch(0.44 0.03 140), oklch(0.735 0.03 85));
124
+ --zd-accent: light-dark(oklch(0.465 0.11 62), oklch(0.78 0.125 72));
125
+ --zd-accent-hover: light-dark(oklch(0.4 0.1 55), oklch(0.84 0.115 78));
126
+ --zd-code-bg: light-dark(oklch(0.925 0.024 87), oklch(0.168 0.018 55));
127
+ --zd-code-fg: light-dark(oklch(0.27 0.032 155), oklch(0.915 0.022 88));
128
+ --zd-success: light-dark(oklch(0.44 0.1 145), oklch(0.76 0.11 140));
129
+ --zd-danger: light-dark(oklch(0.47 0.15 30), oklch(0.71 0.14 30));
130
+ --zd-warning: light-dark(oklch(0.45 0.11 60), oklch(0.75 0.13 55));
131
+ --zd-info: light-dark(oklch(0.42 0.08 230), oklch(0.76 0.08 220));
132
+
133
+ /* syntax — lantern-lit code, all 9 roles in both modes: amber
134
+ keywords, moss strings, ember numbers, moonlit-blue callables,
135
+ birch-gold types, mossy-ash comments. Every light value clears
136
+ WCAG AA (>=4.6:1 with headroom) on the toasted cream code panel;
137
+ inserted/deleted reuse the success/danger hues. */
138
+ --zd-syntax-comment: light-dark(oklch(0.49 0.035 140), oklch(0.66 0.035 110));
139
+ --zd-syntax-string: light-dark(oklch(0.46 0.09 145), oklch(0.79 0.1 135));
140
+ --zd-syntax-number: light-dark(oklch(0.49 0.12 50), oklch(0.77 0.125 55));
141
+ --zd-syntax-keyword: light-dark(oklch(0.475 0.11 70), oklch(0.8 0.125 80));
142
+ --zd-syntax-callable: light-dark(oklch(0.45 0.085 235), oklch(0.78 0.075 220));
143
+ --zd-syntax-type: light-dark(oklch(0.46 0.075 95), oklch(0.85 0.085 95));
144
+ --zd-syntax-name: light-dark(oklch(0.27 0.032 155), oklch(0.915 0.022 88));
145
+ --zd-syntax-inserted: light-dark(oklch(0.44 0.1 145), oklch(0.76 0.11 140));
146
+ --zd-syntax-deleted: light-dark(oklch(0.47 0.15 30), oklch(0.71 0.14 30));
147
+
148
+ /* fonts — Source Sans 3 reading face, JetBrains Mono code,
149
+ Fraunces display serif for the title layer. */
150
+ --font-sans: "Source Sans 3", system-ui, sans-serif;
151
+ --font-mono: "JetBrains Mono", ui-monospace, monospace;
152
+ --font-display: "Fraunces", Georgia, serif;
153
+
154
+ /* Tier-3 component seams — Fraunces titles (weights ride the
155
+ variable wght axis), chamfered 4px edges, and a plank-fill
156
+ active nav: deep pine board by morning, lantern amber by night
157
+ (ink comes from --zd-bg in the extras below — cream on pine,
158
+ dark-umber on amber). */
159
+ --zdc-doc-title-font: var(--font-display);
160
+ --zdc-doc-title-weight: 620;
161
+ --zdc-doc-title-tracking: -0.01em;
162
+ --zdc-doc-h2-font: var(--font-display);
163
+ --zdc-doc-h2-weight: 600;
164
+ --zdc-doc-h2-tracking: -0.005em;
165
+ --zdc-doc-h3-weight: 650;
166
+ --zdc-admonition-radius: 0 4px 4px 0;
167
+ --zdc-card-radius: 4px;
168
+ --zdc-nav-active-indicator-color: light-dark(oklch(0.34 0.05 155), oklch(0.78 0.125 72));
169
+ --zdc-nav-active-weight: 600;
170
+ }
171
+
172
+ /* ---- Timberline extras ---- */
173
+
174
+ /* cabin atmosphere: by night a lantern pool rises from the lower
175
+ right (matte, low alpha — a warm room, not a spotlight) under
176
+ cool pine depth up top; by morning, soft daylight from above and
177
+ the faintest hearth-warmth in the corner. Fixed, so the depth
178
+ holds while scrolling. */
179
+ html[data-theme-pack="timberline"] body {
180
+ background-image:
181
+ radial-gradient(
182
+ 72rem 46rem at 92% 104%,
183
+ light-dark(oklch(0.93 0.045 80 / 0.35), oklch(0.35 0.07 65 / 0.32)) 0%,
184
+ transparent 62%
185
+ ),
186
+ radial-gradient(
187
+ 100% 55% at 40% -8%,
188
+ light-dark(oklch(0.978 0.014 95 / 0.8), oklch(0.235 0.03 150 / 0.5)) 0%,
189
+ transparent 68%
190
+ );
191
+ background-attachment: fixed;
192
+ }
193
+
194
+ /* header: the lintel beam — umber board over a plank seam (dark
195
+ groove hairline + chamfer highlight catching on the board below) */
196
+ html[data-theme-pack="timberline"] header[data-header] {
197
+ background-image: linear-gradient(
198
+ 180deg,
199
+ light-dark(oklch(0.945 0.019 89), oklch(0.25 0.024 58)) 0%,
200
+ light-dark(oklch(0.93 0.02 88), oklch(0.232 0.022 58)) 100%
201
+ );
202
+ border-bottom-color: light-dark(oklch(0.83 0.032 85), oklch(0.142 0.016 55));
203
+ box-shadow: 0 1px 0 0 light-dark(oklch(0.988 0.008 95 / 0.85), oklch(0.87 0.07 80 / 0.13));
204
+ }
205
+ html[data-theme-pack="timberline"] [data-header-logo] {
206
+ font-family: var(--font-display);
207
+ font-weight: 620;
208
+ letter-spacing: -0.005em;
209
+ color: var(--zd-accent);
210
+ }
211
+ /* Exclude the current page: it carries the base `bg-fg text-bg`
212
+ inverted fill, so an accent recolor would sit amber-on-fg below AA. */
213
+ html[data-theme-pack="timberline"] [data-nav-item]:not([aria-current="page"]):hover {
214
+ color: var(--zd-accent);
215
+ text-decoration-color: color-mix(in oklch, var(--zd-accent) 55%, transparent);
216
+ text-underline-offset: 4px;
217
+ }
218
+
219
+ /* sidebar: the pine layer — a board of deep pine against the umber
220
+ page (the layered-surfaces signature), sealed by a vertical plank
221
+ seam on its right edge. The mobile drawer is the same board. */
222
+ html[data-theme-pack="timberline"] #desktop-sidebar {
223
+ background-color: light-dark(oklch(0.936 0.018 120), oklch(0.19 0.022 150));
224
+ border-right-color: light-dark(oklch(0.83 0.032 85), oklch(0.142 0.016 55));
225
+ box-shadow: 1px 0 0 0 light-dark(oklch(0.988 0.008 95 / 0.85), oklch(0.87 0.07 80 / 0.13));
226
+ }
227
+ html[data-theme-pack="timberline"] aside[data-zd-mobile-sidebar] {
228
+ background-color: light-dark(oklch(0.936 0.018 120), oklch(0.19 0.022 150));
229
+ border-right-color: light-dark(oklch(0.83 0.032 85), oklch(0.142 0.016 55));
230
+ }
231
+ html[data-theme-pack="timberline"] #desktop-sidebar a {
232
+ border-radius: 4px;
233
+ transition:
234
+ background-color 0.15s ease,
235
+ color 0.15s ease;
236
+ }
237
+ html[data-theme-pack="timberline"] #desktop-sidebar a:hover:not([data-nav-active]):not([aria-current="page"]) {
238
+ color: var(--zd-accent);
239
+ text-decoration: none;
240
+ background: color-mix(in srgb, var(--zd-accent) 10%, transparent);
241
+ }
242
+ /* active item: the lantern plank — amber board by night, deep pine
243
+ by morning (fill from --zdc-nav-active-indicator-color); ink via
244
+ the bg token reads dark-umber-on-amber / cream-on-pine. The glow
245
+ underneath stays matte: tight radius, low alpha. */
246
+ html[data-theme-pack="timberline"] a[data-nav-active] {
247
+ color: var(--zd-bg);
248
+ border-radius: 4px;
249
+ box-shadow: 0 2px 10px -4px light-dark(oklch(0.35 0.05 120 / 0.3), oklch(0.72 0.12 70 / 0.3));
250
+ }
251
+
252
+ /* breadcrumb: quiet trail markers */
253
+ html[data-theme-pack="timberline"] main nav[aria-label="Breadcrumb"] a:hover {
254
+ color: var(--zd-accent);
255
+ }
256
+
257
+ /* h1: hewn beam — the default fg rule is dropped for a short lantern
258
+ bar glowing along the beam's end */
259
+ html[data-theme-pack="timberline"] .zd-content h1 {
260
+ border-bottom: 0;
261
+ padding-bottom: 0;
262
+ }
263
+ html[data-theme-pack="timberline"] .zd-content h1::after {
264
+ content: "";
265
+ display: block;
266
+ width: 4.5rem;
267
+ height: 3px;
268
+ border-radius: 2px;
269
+ margin-top: 0.55rem;
270
+ background: linear-gradient(
271
+ to right,
272
+ var(--zd-accent),
273
+ color-mix(in oklch, var(--zd-accent) 40%, transparent) 70%,
274
+ transparent
275
+ );
276
+ }
277
+
278
+ /* the lead: a Fraunces italic whisper under the title */
279
+ html[data-theme-pack="timberline"] p[data-doc-description] {
280
+ font-family: var(--font-display);
281
+ font-style: italic;
282
+ font-size: 1.3rem;
283
+ line-height: 1.45;
284
+ color: color-mix(in oklch, var(--zd-fg) 70%, var(--zd-muted));
285
+ }
286
+
287
+ /* h2: lantern light along the top of each beam. The SSR-inlined
288
+ `style="border-image:linear-gradient(...)"` bar is defeated with
289
+ border-image none !important (Decision 6.6's sole allowlisted
290
+ carve-out) + a zeroed border-top; the fading amber rule is then
291
+ painted as a 2px top-anchored background gradient instead. */
292
+ html[data-theme-pack="timberline"] .zd-content h2 {
293
+ border-image: none !important;
294
+ border-top-width: 0;
295
+ background-image: linear-gradient(
296
+ to right,
297
+ var(--zd-accent),
298
+ color-mix(in oklch, var(--zd-accent) 35%, transparent) 55%,
299
+ transparent
300
+ );
301
+ background-size: 100% 2px;
302
+ background-repeat: no-repeat;
303
+ background-position: top left;
304
+ }
305
+
306
+ /* links: lantern-amber ink under a warm underline; the halo appears
307
+ only on hover, only after dark, and stays matte (small radius,
308
+ low alpha — never neon) */
309
+ html[data-theme-pack="timberline"] .zd-content a {
310
+ text-decoration-color: color-mix(in oklch, var(--zd-accent) 45%, transparent);
311
+ text-decoration-thickness: 1.5px;
312
+ text-underline-offset: 3px;
313
+ transition:
314
+ color 0.15s ease,
315
+ text-decoration-color 0.15s ease,
316
+ text-shadow 0.25s ease;
317
+ }
318
+ html[data-theme-pack="timberline"] .zd-content a:hover {
319
+ text-decoration-color: var(--zd-accent-hover);
320
+ text-shadow: 0 0 10px light-dark(oklch(0.78 0.125 72 / 0), oklch(0.8 0.13 75 / 0.28));
321
+ }
322
+
323
+ /* code block: the cabin window at night — the deepest umber pane,
324
+ set into a plank frame with a lantern-warmed sill along the top
325
+ edge; by morning, a toasted cream pane. */
326
+ html[data-theme-pack="timberline"] pre.hi-root {
327
+ border-radius: 4px;
328
+ border-color: light-dark(oklch(0.83 0.032 85), oklch(0.142 0.016 55));
329
+ border-top-color: light-dark(
330
+ oklch(0.79 0.06 78),
331
+ oklch(0.42 0.07 68)
332
+ );
333
+ background-image: linear-gradient(
334
+ 180deg,
335
+ light-dark(oklch(0.937 0.026 88), oklch(0.192 0.022 58)) 0%,
336
+ var(--zd-code-bg) 3.5rem
337
+ );
338
+ box-shadow:
339
+ inset 0 1px 0 light-dark(oklch(0.988 0.008 95 / 0.85), oklch(0.87 0.07 80 / 0.1)),
340
+ 0 10px 24px -18px light-dark(oklch(0.4 0.05 90 / 0.35), oklch(0.05 0.01 55 / 0.7));
341
+ padding: 1.05rem 1.2rem;
342
+ }
343
+ html[data-theme-pack="timberline"] .hi-com {
344
+ font-style: italic;
345
+ }
346
+
347
+ /* inline code: small chips sawn from the same board */
348
+ html[data-theme-pack="timberline"] .zd-content code:not(pre code) {
349
+ border-radius: 4px;
350
+ border: 1px solid light-dark(oklch(0.855 0.03 86), oklch(0.32 0.03 60));
351
+ padding: 1px 0.35rem;
352
+ }
353
+
354
+ /* blockquote: carved into the wall — Fraunces italic behind an
355
+ amber-tinged edge */
356
+ html[data-theme-pack="timberline"] .zd-content blockquote {
357
+ font-family: var(--font-display);
358
+ font-style: italic;
359
+ font-size: 1.15rem;
360
+ line-height: 1.55;
361
+ border-left: 3px solid color-mix(in oklch, var(--zd-accent) 55%, transparent);
362
+ border-radius: 0 4px 4px 0;
363
+ background: color-mix(in srgb, var(--zd-accent) 6%, transparent);
364
+ padding: 0.75rem 1.15rem 0.75rem 1.2rem;
365
+ color: color-mix(in oklch, var(--zd-fg) 80%, var(--zd-muted));
366
+ }
367
+
368
+ /* admonitions: trail markers on the cabin wall — matte umber shadow,
369
+ a distinct forest-cabin icon for every one of the 7 variants */
370
+ html[data-theme-pack="timberline"] [data-admonition] {
371
+ box-shadow: 0 6px 16px -14px light-dark(oklch(0.4 0.05 90 / 0.4), oklch(0.05 0.01 55 / 0.65));
372
+ }
373
+ html[data-theme-pack="timberline"] [data-admonition="note"] .admonition-title::before {
374
+ content: "🌲 ";
375
+ }
376
+ html[data-theme-pack="timberline"] [data-admonition="tip"] .admonition-title::before {
377
+ content: "🏮 ";
378
+ }
379
+ html[data-theme-pack="timberline"] [data-admonition="info"] .admonition-title::before {
380
+ content: "🧭 ";
381
+ }
382
+ html[data-theme-pack="timberline"] [data-admonition="warning"] .admonition-title::before {
383
+ content: "🔥 ";
384
+ }
385
+ html[data-theme-pack="timberline"] [data-admonition="important"] .admonition-title::before {
386
+ content: "📌 ";
387
+ }
388
+ html[data-theme-pack="timberline"] [data-admonition="danger"] .admonition-title::before {
389
+ content: "🐻 ";
390
+ }
391
+ html[data-theme-pack="timberline"] [data-admonition="caution"] .admonition-title::before {
392
+ content: "🪓 ";
393
+ }
394
+
395
+ /* table: Fraunces heads over a lantern-warmed sill, plank hairlines
396
+ between rows, a faint warm wash on row hover */
397
+ html[data-theme-pack="timberline"] .zd-content th {
398
+ font-family: var(--font-display);
399
+ font-weight: 600;
400
+ color: var(--zd-accent);
401
+ border-bottom-color: color-mix(in oklch, var(--zd-accent) 60%, transparent);
402
+ }
403
+ html[data-theme-pack="timberline"] .zd-content td {
404
+ border-bottom-color: light-dark(oklch(0.855 0.028 88), oklch(0.3 0.026 58));
405
+ }
406
+ html[data-theme-pack="timberline"] .zd-content tbody tr:hover {
407
+ background: color-mix(in srgb, var(--zd-accent) 7%, transparent);
408
+ }
409
+
410
+ /* hr: a literal plank seam — dark groove hairline over a chamfer
411
+ highlight hairline, edge to edge */
412
+ html[data-theme-pack="timberline"] .zd-content hr {
413
+ border: none;
414
+ height: 2px;
415
+ background: linear-gradient(
416
+ to bottom,
417
+ light-dark(oklch(0.83 0.032 85), oklch(0.142 0.016 55)) 0 1px,
418
+ light-dark(oklch(0.988 0.008 95 / 0.85), oklch(0.87 0.07 80 / 0.13)) 1px 2px
419
+ );
420
+ }
421
+
422
+ /* pager: cabin doors — umber boards in plank frames that warm under
423
+ the lantern when you reach for them (matte glow, restrained) */
424
+ html[data-theme-pack="timberline"] .zd-content > nav[data-doc-pager] a {
425
+ background: var(--zd-surface);
426
+ border-radius: 4px;
427
+ border-color: light-dark(oklch(0.83 0.032 85), oklch(0.142 0.016 55));
428
+ box-shadow: inset 0 1px 0 light-dark(oklch(0.988 0.008 95 / 0.85), oklch(0.87 0.07 80 / 0.08));
429
+ transition:
430
+ border-color 0.18s ease,
431
+ box-shadow 0.18s ease,
432
+ transform 0.18s ease;
433
+ }
434
+ html[data-theme-pack="timberline"] .zd-content > nav[data-doc-pager] a:hover {
435
+ /* the card's glow lives on its frame (box-shadow below) — suppress the
436
+ prose-link text halo this <a> would otherwise inherit from the
437
+ `.zd-content a:hover` rule above */
438
+ text-shadow: none;
439
+ border-color: color-mix(in oklch, var(--zd-accent) 55%, transparent);
440
+ box-shadow:
441
+ inset 0 1px 0 light-dark(oklch(0.988 0.008 95 / 0.85), oklch(0.87 0.07 80 / 0.08)),
442
+ 0 8px 22px -14px light-dark(oklch(0.45 0.06 70 / 0.35), oklch(0.72 0.12 70 / 0.3));
443
+ transform: translateY(-1px);
444
+ }
445
+ html[data-theme-pack="timberline"] .zd-content > nav[data-doc-pager] a p {
446
+ font-family: var(--font-display);
447
+ font-weight: 600;
448
+ }
449
+
450
+ /* TOC: the trail — plank-seam spine, lantern plank on the current
451
+ waypoint. The real DOM marks it with aria-current="true"
452
+ (toc/toc.tsx); the plank pulls left within the ul's padding and
453
+ its ink rides the bg token (dark-umber-on-amber by night,
454
+ cream-on-deep-amber by morning). */
455
+ html[data-theme-pack="timberline"] nav[data-zd-toc] ul {
456
+ border-left-color: light-dark(oklch(0.83 0.032 85), oklch(0.142 0.016 55));
457
+ }
458
+ html[data-theme-pack="timberline"] nav[data-zd-toc] a:hover {
459
+ color: var(--zd-accent);
460
+ }
461
+ html[data-theme-pack="timberline"] nav[data-zd-toc] a[aria-current="true"] {
462
+ background: var(--zd-accent);
463
+ color: var(--zd-bg);
464
+ font-weight: 600;
465
+ border-radius: 4px;
466
+ padding-left: 0.4rem;
467
+ margin-left: -0.4rem;
468
+ padding-right: 0.4rem;
469
+ box-shadow: 0 2px 10px -4px light-dark(oklch(0.45 0.06 70 / 0.3), oklch(0.72 0.12 70 / 0.3));
470
+ }
471
+
472
+ /* mobile TOC: the same board, plank frame and chamfered edge */
473
+ html[data-theme-pack="timberline"] div[data-zd-mobile-toc] {
474
+ background-color: var(--zd-surface);
475
+ border-color: light-dark(oklch(0.83 0.032 85), oklch(0.142 0.016 55));
476
+ border-radius: 4px;
477
+ }
478
+
479
+ /* footer: the pine floor — same layer as the sidebar, sealed by a
480
+ plank seam along its top edge */
481
+ html[data-theme-pack="timberline"] footer[data-footer] {
482
+ background-color: light-dark(oklch(0.936 0.018 120), oklch(0.19 0.022 150));
483
+ border-top-color: light-dark(oklch(0.83 0.032 85), oklch(0.142 0.016 55));
484
+ box-shadow: inset 0 1px 0 light-dark(oklch(0.988 0.008 95 / 0.85), oklch(0.87 0.07 80 / 0.13));
485
+ }
486
+
487
+ /* theme-pack flyout: lantern glass — a warm pane in a plank frame,
488
+ glowing softly (matte, restrained) with a Fraunces nameplate */
489
+ html[data-theme-pack="timberline"] div[data-switcher-card] {
490
+ border: 1px solid color-mix(in oklch, var(--zd-accent) 40%, transparent);
491
+ border-radius: 4px;
492
+ background:
493
+ radial-gradient(
494
+ 120% 90% at 82% 100%,
495
+ color-mix(in srgb, var(--zd-accent) 10%, transparent),
496
+ transparent 60%
497
+ ),
498
+ var(--zd-surface);
499
+ box-shadow:
500
+ inset 0 1px 0 light-dark(oklch(0.988 0.008 95 / 0.85), oklch(0.87 0.07 80 / 0.12)),
501
+ 0 14px 34px -14px light-dark(oklch(0.4 0.05 90 / 0.4), oklch(0.05 0.01 55 / 0.7)),
502
+ 0 0 18px -6px light-dark(oklch(0.78 0.125 72 / 0), oklch(0.72 0.12 70 / 0.25));
503
+ }
504
+ html[data-theme-pack="timberline"] div[data-switcher-card] p[aria-live="polite"] {
505
+ font-family: var(--font-display);
506
+ font-weight: 620;
507
+ font-size: 1.35rem;
508
+ letter-spacing: -0.005em;
509
+ }
@@ -4,7 +4,7 @@
4
4
  "name": "Washi",
5
5
  "description": "Warm washi paper, sumi ink, and ai-iro indigo seals — quiet Japanese stationery for calm documentation.",
6
6
  "mode": "light",
7
- "version": "1.0.1",
7
+ "version": "1.0.3",
8
8
  "fonts": {
9
9
  "sans": "Zen Kaku Gothic New",
10
10
  "mono": "M PLUS 1 Code",
@@ -4,8 +4,8 @@
4
4
  Warm washi paper, sumi ink, and ai-iro indigo seals — quiet
5
5
  Japanese stationery for calm documentation. Zen Kaku Gothic New
6
6
  prose over a CSS-only paper grain, Shippori Mincho headings, an
7
- indigo hanko (判子) stamp language: a tilted 藍 seal on the h1,
8
- kanji seal chips on admonitions, an asymmetric two-tone h2 rule.
7
+ indigo hanko (判子) stamp language: kanji seal chips on
8
+ admonitions, an asymmetric two-tone h2 rule.
9
9
  Everything is cut square (washi is cut straight — no rounding),
10
10
  with a generous 1.95 prose leading. Light = raw warm paper;
11
11
  dark = aizome night — the same sheet dyed indigo-charcoal, warm
@@ -20,9 +20,9 @@
20
20
  CJK font rule (Decision 5): packs do NOT ship CJK subsets. All
21
21
  three families load their latin subset only; every family stack
22
22
  ends in the correct bare generic (sans-serif / serif / monospace)
23
- so the platform's own Japanese fonts carry CJK glyphs. The 藍 and
24
- kanji chip glyphs below are decorative CSS content characters
25
- rendered by that platform CJK fallback — intentional.
23
+ so the platform's own Japanese fonts carry CJK glyphs. The kanji
24
+ chip glyphs below are decorative CSS content characters rendered
25
+ by that platform CJK fallback — intentional.
26
26
 
27
27
  Prototype-selector adaptations against the REAL DOM (tokens-dump
28
28
  §6 + component sources), noted inline where they matter:
@@ -177,7 +177,7 @@ html[data-theme-pack="washi"] {
177
177
  --zd-code-fg: light-dark(#2b2822, #ece5d5);
178
178
  --zd-success: light-dark(#3f6237, #a3c98e);
179
179
  --zd-danger: light-dark(#a03a2e, #e0968a);
180
- --zd-warning: light-dark(#875c12, #d9ac60);
180
+ --zd-warning: light-dark(#835809, #d9ac60);
181
181
  --zd-info: light-dark(#31608f, #8ab0dd);
182
182
 
183
183
  /* syntax — all 9 roles, both modes: sumi ink annotated with mineral
@@ -309,26 +309,6 @@ html[data-theme-pack="washi"] .zd-content > p[data-doc-description] {
309
309
  color: color-mix(in srgb, var(--zd-fg) 72%, var(--zd-bg));
310
310
  }
311
311
 
312
- /* signature move #2 — the h1 carries a small tilted 藍 seal, like a
313
- maker's hanko stamp on the sheet (platform CJK font renders the
314
- glyph — decorative content character, Decision 5 CJK rule) */
315
- html[data-theme-pack="washi"] .zd-content h1::after {
316
- content: "藍";
317
- display: inline-block;
318
- font-family: var(--font-display);
319
- font-size: 1rem;
320
- font-weight: 600;
321
- line-height: 1;
322
- color: light-dark(#f6f1e4, #161b24);
323
- background: var(--zd-accent);
324
- padding: 0.3em 0.32em 0.24em;
325
- margin-left: 0.8rem;
326
- vertical-align: 0.5em;
327
- border-radius: 2px;
328
- transform: rotate(-4deg);
329
- box-shadow: 0 1px 2px light-dark(rgb(43 40 34 / 0.25), rgb(0 0 0 / 0.5));
330
- }
331
-
332
312
  /* signature move #3 — quiet asymmetry: the h2 rule is two-tone, a
333
313
  short indigo stroke then a long faded one. Replaces the
334
314
  SSR-inlined `style="border-image:linear-gradient(...)"` — the
@@ -558,7 +558,7 @@ export function DocHistory({ slug, locale, basePath = "/" }: DocHistoryProps) {
558
558
  <button
559
559
  type="button"
560
560
  onClick={handleOpen}
561
- className="doc-history-trigger flex items-center gap-hsp-xs px-hsp-md py-vsp-xs rounded-lg bg-surface border border-muted text-muted hover:text-fg hover:border-fg transition-colors"
561
+ className="doc-history-trigger flex items-center gap-hsp-xs px-hsp-md py-vsp-xs rounded-lg bg-surface border border-muted text-muted hover:text-accent hover:border-accent focus-visible:text-accent focus-visible:border-accent transition-colors"
562
562
  aria-label="View document history"
563
563
  >
564
564
  <History className="h-icon-md w-icon-md" />
@@ -56,7 +56,7 @@ export function createDocPager<S extends Settings = Settings>(
56
56
  href={prev.href}
57
57
  class="group border border-muted rounded-lg p-hsp-lg hover:border-accent"
58
58
  >
59
- <div class="flex items-center gap-hsp-xs text-caption text-muted mb-vsp-2xs">
59
+ <div class="flex items-center gap-hsp-xs text-caption text-muted mb-vsp-2xs group-hover:text-accent group-focus-visible:text-accent">
60
60
  <ChevronLeft className="h-[1.125rem] w-[1.125rem]" />
61
61
  <span class="no-underline">{t("nav.previous", locale)}</span>
62
62
  </div>
@@ -72,7 +72,7 @@ export function createDocPager<S extends Settings = Settings>(
72
72
  href={next.href}
73
73
  class="group border border-muted rounded-lg p-hsp-lg hover:border-accent text-right"
74
74
  >
75
- <div class="flex items-center justify-end gap-hsp-xs text-caption text-muted mb-vsp-2xs">
75
+ <div class="flex items-center justify-end gap-hsp-xs text-caption text-muted mb-vsp-2xs group-hover:text-accent group-focus-visible:text-accent">
76
76
  <span class="no-underline">{t("nav.next", locale)}</span>
77
77
  <ChevronRight className="h-[1.125rem] w-[1.125rem]" />
78
78
  </div>
@@ -45,6 +45,14 @@ import {
45
45
  pathForMatch,
46
46
  } from "./nav-active.js";
47
47
  import { NAV_OVERFLOW_SCRIPT } from "./nav-overflow-script.js";
48
+ import {
49
+ NAV_CHEVRON_ACTIVE,
50
+ NAV_CHEVRON_INACTIVE,
51
+ NAV_CHILD_ACTIVE,
52
+ NAV_CHILD_INACTIVE,
53
+ NAV_TOP_ACTIVE,
54
+ NAV_TOP_INACTIVE,
55
+ } from "./nav-class-tokens.js";
48
56
  import { LANGUAGE_SWITCHER_INIT_SCRIPT } from "../i18n-version/language-switcher.js";
49
57
  import { VERSION_SWITCHER_REWIRE_SCRIPT } from "../i18n-version/version-switcher.js";
50
58
  import type {
@@ -349,7 +357,7 @@ export function Header(props: HeaderProps): JSX.Element {
349
357
  <div class="relative shrink-0" data-nav-more style="display:none">
350
358
  <button
351
359
  type="button"
352
- class="px-hsp-md py-vsp-2xs text-small font-medium text-muted hover:underline cursor-pointer"
360
+ class="px-hsp-md py-vsp-2xs text-small font-medium text-muted hover:text-accent hover:underline focus-visible:text-accent focus-visible:underline cursor-pointer"
353
361
  data-nav-more-toggle
354
362
  aria-expanded="false"
355
363
  >
@@ -454,15 +462,15 @@ function renderNavItem(
454
462
  class={[
455
463
  "flex items-center gap-x-hsp-xs px-hsp-md py-vsp-2xs text-small font-medium transition-colors",
456
464
  isActive
457
- ? "bg-fg text-bg"
458
- : "text-muted hover:underline focus:underline",
465
+ ? NAV_TOP_ACTIVE.join(" ")
466
+ : NAV_TOP_INACTIVE.join(" "),
459
467
  ].join(" ")}
460
468
  >
461
469
  {label}
462
470
  <svg
463
471
  class={[
464
472
  "h-[0.5rem] w-[0.5rem] shrink-0",
465
- isActive ? "text-bg" : "text-muted",
473
+ isActive ? NAV_CHEVRON_ACTIVE.join(" ") : NAV_CHEVRON_INACTIVE.join(" "),
466
474
  ].join(" ")}
467
475
  fill="none"
468
476
  viewBox="0 0 24 24"
@@ -492,8 +500,8 @@ function renderNavItem(
492
500
  href={childHref}
493
501
  data-active={childActive ? "" : undefined}
494
502
  class={[
495
- "block px-hsp-md py-vsp-2xs text-small hover:bg-accent/10 hover:underline",
496
- childActive ? "font-bold text-accent" : "text-fg",
503
+ "block px-hsp-md py-vsp-2xs text-small hover:bg-accent/10 hover:underline focus-visible:underline",
504
+ childActive ? NAV_CHILD_ACTIVE.join(" ") : NAV_CHILD_INACTIVE.join(" "),
497
505
  ].join(" ")}
498
506
  >
499
507
  {childLabel}
@@ -514,8 +522,8 @@ function renderNavItem(
514
522
  class={[
515
523
  "px-hsp-md py-vsp-2xs text-small font-medium transition-colors shrink-0",
516
524
  isActive
517
- ? "bg-fg text-bg"
518
- : "text-muted hover:underline focus:underline",
525
+ ? NAV_TOP_ACTIVE.join(" ")
526
+ : NAV_TOP_INACTIVE.join(" "),
519
527
  ].join(" ")}
520
528
  >
521
529
  {label}