@cogenta/theme-canonical 1.1.2 → 1.3.3

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 (71) hide show
  1. package/dist/src/index.d.ts +1 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +1 -0
  4. package/dist/src/index.js.map +1 -1
  5. package/dist/src/render/arrow-link.d.ts +11 -0
  6. package/dist/src/render/arrow-link.d.ts.map +1 -0
  7. package/dist/src/render/arrow-link.js +29 -0
  8. package/dist/src/render/arrow-link.js.map +1 -0
  9. package/dist/src/render/blocks/collection-list.d.ts +15 -5
  10. package/dist/src/render/blocks/collection-list.d.ts.map +1 -1
  11. package/dist/src/render/blocks/collection-list.js +36 -13
  12. package/dist/src/render/blocks/collection-list.js.map +1 -1
  13. package/dist/src/render/blocks/embed.d.ts.map +1 -1
  14. package/dist/src/render/blocks/embed.js +3 -2
  15. package/dist/src/render/blocks/embed.js.map +1 -1
  16. package/dist/src/render/blocks/gallery.d.ts.map +1 -1
  17. package/dist/src/render/blocks/gallery.js +4 -1
  18. package/dist/src/render/blocks/gallery.js.map +1 -1
  19. package/dist/src/render/blocks/hero.d.ts.map +1 -1
  20. package/dist/src/render/blocks/hero.js +9 -2
  21. package/dist/src/render/blocks/hero.js.map +1 -1
  22. package/dist/src/render/blocks/pricing-table.d.ts.map +1 -1
  23. package/dist/src/render/blocks/pricing-table.js +17 -4
  24. package/dist/src/render/blocks/pricing-table.js.map +1 -1
  25. package/dist/src/render/chrome.d.ts +40 -1
  26. package/dist/src/render/chrome.d.ts.map +1 -1
  27. package/dist/src/render/chrome.js +103 -71
  28. package/dist/src/render/chrome.js.map +1 -1
  29. package/dist/src/render/dates.d.ts +9 -0
  30. package/dist/src/render/dates.d.ts.map +1 -0
  31. package/dist/src/render/dates.js +16 -0
  32. package/dist/src/render/dates.js.map +1 -0
  33. package/dist/src/render/render-block.d.ts.map +1 -1
  34. package/dist/src/render/render-block.js +7 -1
  35. package/dist/src/render/render-block.js.map +1 -1
  36. package/dist/src/render/strings.d.ts +25 -0
  37. package/dist/src/render/strings.d.ts.map +1 -0
  38. package/dist/src/render/strings.js +26 -0
  39. package/dist/src/render/strings.js.map +1 -0
  40. package/dist/src/render/term-archive.d.ts +5 -5
  41. package/dist/src/render/term-archive.d.ts.map +1 -1
  42. package/dist/src/render/term-archive.js +14 -12
  43. package/dist/src/render/term-archive.js.map +1 -1
  44. package/dist/src/render/widget-areas.d.ts +20 -0
  45. package/dist/src/render/widget-areas.d.ts.map +1 -0
  46. package/dist/src/render/widget-areas.js +40 -0
  47. package/dist/src/render/widget-areas.js.map +1 -0
  48. package/package.json +5 -5
  49. package/src/index.ts +1 -0
  50. package/src/render/arrow-link.ts +27 -0
  51. package/src/render/blocks/collection-list.ts +53 -15
  52. package/src/render/blocks/embed.ts +3 -2
  53. package/src/render/blocks/gallery.ts +4 -1
  54. package/src/render/blocks/hero.ts +9 -2
  55. package/src/render/blocks/pricing-table.ts +22 -4
  56. package/src/render/chrome.ts +156 -70
  57. package/src/render/dates.ts +14 -0
  58. package/src/render/render-block.ts +6 -0
  59. package/src/render/strings.ts +30 -0
  60. package/src/render/term-archive.ts +54 -32
  61. package/src/render/widget-areas.ts +44 -0
  62. package/src/styles/archive.css +66 -20
  63. package/src/styles/base.css +266 -680
  64. package/src/styles/blocks.css +678 -811
  65. package/src/styles/chrome.css +469 -0
  66. package/src/styles/listings.css +183 -0
  67. package/src/styles/theme.css +28 -14
  68. package/src/styles/tokens.css +192 -205
  69. package/src/styles/utility.css +295 -0
  70. package/src/styles/widgets.css +1064 -0
  71. package/tokens.json +15 -15
@@ -1,34 +1,38 @@
1
1
  /*
2
2
  * The canonical theme's design system.
3
3
  *
4
- * Contract D fixes a *closed* skin token set — seven colours, five type tokens,
5
- * two spacing tokens, three radii, three motion tokens, two shadows — and
6
- * refuses any skin that adds one. So this layer adds nothing to the skin: every
7
- * value below is *derived* from `--cogenta-*` by composition (`calc`,
8
- * `color-mix`, relative colour syntax). A skin swap rewrites the generated
9
- * `--cogenta-*` sheet and this whole system follows, with no build step, which
10
- * is what contract D's hot swap means in practice.
4
+ * Contract D fixes a closed skin token set, and this layer adds nothing to
5
+ * it: every value below is derived from a `--cogenta-*` property by
6
+ * composition (`calc`, `min`, `color-mix`, relative colour syntax). A skin
7
+ * swap rewrites the generated `--cogenta-*` sheet and the whole system
8
+ * follows, with no build step.
11
9
  *
12
- * Two rules hold everywhere in this file and the two that import it:
10
+ * This is the default theme, so it has to look right under a skin it has
11
+ * never seen: the one it ships (Instrument Sans and Instrument Serif, pure
12
+ * neutrals, one deep blue), a skin an editor picked in the appearance screen,
13
+ * or one the theme workshop generated. That is why the theme owns proportions
14
+ * (the grid, the rhythm, the lightness targets of the dark palette) and the
15
+ * skin owns identity (families, hues, the base size and the ratio of the
16
+ * type scale).
13
17
  *
14
- * 1. **No colour literal.** Not one hex, `rgb()`, `hsl()` or bare `oklch()`.
15
- * Every colour is either a skin token or a function *of* a skin token, so
16
- * there is no colour on the page a skin cannot change. `theme.css`'s own
17
- * isolation test enforces this on the source.
18
- * 2. **No second scale.** The type steps come from `--cogenta-font-size-*` and
19
- * the spacing multiplier from `--cogenta-space-scale`, both emitted by
20
- * `renderSkin` from the same tokens the validator checked. Re-deriving them
21
- * here would let the theme's idea of "large" drift from the skin's.
18
+ * Two rules hold in every sheet of this theme:
19
+ *
20
+ * 1. **No colour literal.** Every colour is a skin token or a function of
21
+ * one, so there is no colour on the page a skin cannot change.
22
+ * 2. **No second scale.** Type sizes come from `--cogenta-font-size-*` and
23
+ * spacing from `--cogenta-space-unit`/`--cogenta-space-scale`, both emitted
24
+ * by `renderSkin`. A display size is a multiple of a skin step, never a
25
+ * number of its own.
22
26
  */
23
27
 
24
28
  :where(:root) {
25
- /* Lets the browser paint native controls, scrollbars and form widgets in the
26
- right scheme, and is what makes `light-dark()` below resolve at all. */
29
+ /* Lets native controls and scrollbars follow the palette, and is what makes
30
+ `light-dark()` below resolve at all. */
27
31
  color-scheme: light dark;
28
32
  }
29
33
 
30
- /* An explicit choice wins over the OS preference. No script ships with this
31
- theme to set it; the attribute is the hook a site (or the admin) can flip. */
34
+ /* An explicit choice (the header's light/dark control) wins over the OS
35
+ preference, in both directions. */
32
36
  :where(:root[data-theme="dark"]) {
33
37
  color-scheme: dark;
34
38
  }
@@ -38,12 +42,10 @@
38
42
  }
39
43
 
40
44
  /* --------------------------------------------------------------------------
41
- Space — one multiplier, one unit, a scale of multiples
45
+ Space — one unit, a scale of multiples, one section rhythm
42
46
  -------------------------------------------------------------------------- */
43
47
 
44
48
  :where(:root) {
45
- /* `renderSkin` turns the skin's `space.density` word into this number.
46
- The fallback keeps the theme usable against a hand-written sheet. */
47
49
  --cg-density: var(--cogenta-space-scale, 1);
48
50
  --cg-unit: calc(var(--cogenta-space-unit) * var(--cg-density));
49
51
 
@@ -60,22 +62,50 @@
60
62
  --cg-s20: calc(var(--cg-unit) * 20);
61
63
  --cg-s24: calc(var(--cg-unit) * 24);
62
64
 
63
- /* Named steps, so a block says what it means rather than picking a number. */
65
+ /* The grid. Twelve columns inside an explicit page width, the same gutter
66
+ on both sides at every width, and one column gap everywhere. */
67
+ --cg-columns: 12;
68
+ --cg-page: 72rem;
64
69
  --cg-gutter: var(--cg-s5);
65
- --cg-gap-tight: var(--cg-s2);
66
- --cg-gap: var(--cg-s4);
67
- --cg-gap-loose: var(--cg-s8);
68
- --cg-section-y: var(--cg-s16);
69
-
70
- --cg-measure: 68ch;
71
- --cg-measure-narrow: 46ch;
72
- --cg-page: 76rem;
73
- --cg-page-narrow: 52rem;
70
+ --cg-column-gap: var(--cg-s5);
71
+ /* The side padding that centres the page width in any box as wide as the
72
+ viewport. `100%` resolves where this is used, against that box. */
73
+ --cg-inset: max(var(--cg-gutter), calc((100% - var(--cg-page)) / 2));
74
+
75
+ /* The one vertical rhythm: every block is padded by half of it above and
76
+ below, so two neighbours are always one full section apart. */
77
+ --cg-section: var(--cg-s16);
78
+
79
+ /* The reading measure, in characters of the text face. */
80
+ --cg-measure: 66ch;
81
+ --cg-measure-narrow: 44ch;
82
+
83
+ /* The underline under a link set in ink: present, and quieter than the
84
+ words it underlines. */
85
+ --cg-underline: color-mix(in oklab, currentColor 40%, transparent);
86
+
87
+ /* Rules: a hairline between rows, a solid line in ink over a section. */
88
+ --cg-rule: 1px;
89
+ --cg-rule-strong: 2px;
74
90
  }
75
91
 
76
- /* `space.density` is a skin-wide word; these let one region override it — a
77
- compact sidebar inside a spacious page. CSS still cannot branch on the
78
- *value* of a custom property, so the attribute stays the mechanism. */
92
+ @media (min-width: 48rem) {
93
+ :where(:root) {
94
+ --cg-gutter: var(--cg-s8);
95
+ --cg-column-gap: var(--cg-s6);
96
+ --cg-section: var(--cg-s20);
97
+ }
98
+ }
99
+
100
+ @media (min-width: 64rem) {
101
+ :where(:root) {
102
+ --cg-gutter: var(--cg-s10);
103
+ --cg-column-gap: var(--cg-s8);
104
+ --cg-section: var(--cg-s24);
105
+ }
106
+ }
107
+
108
+ /* `space.density` is skin-wide; these let one region override it. */
79
109
  :where([data-density="compact"]) {
80
110
  --cg-density: 0.75;
81
111
  }
@@ -89,13 +119,19 @@
89
119
  }
90
120
 
91
121
  /* --------------------------------------------------------------------------
92
- Type — the skin's scale, named; plus the rhythm the scale does not carry
122
+ Type
93
123
  -------------------------------------------------------------------------- */
94
124
 
95
125
  :where(:root) {
96
- /* Seven steps, computed by `renderSkin` as `baseSize * scale^(n-2)`. The
97
- fallbacks matter: a sheet from an older skin renderer would otherwise
98
- leave every font size unset. */
126
+ /* The skin names the families. The sans sets everything a visitor reads and
127
+ every heading; the serif is kept for the one display line of a page (the
128
+ hero title, a page title) and for quotations. */
129
+ --cg-font-text: var(--cogenta-font-sans);
130
+ --cg-font-display: var(--cogenta-font-serif);
131
+ --cg-font-mono: var(--cogenta-font-mono);
132
+
133
+ /* Seven steps computed by `renderSkin` as `baseSize * scale^(n-2)`. The
134
+ fallbacks keep the theme usable against an older generated sheet. */
99
135
  --cg-text-xs: var(--cogenta-font-size-xs, 0.64rem);
100
136
  --cg-text-sm: var(--cogenta-font-size-sm, 0.8rem);
101
137
  --cg-text-md: var(--cogenta-font-size-md, var(--cogenta-font-base-size, 1rem));
@@ -104,130 +140,111 @@
104
140
  --cg-text-2xl: var(--cogenta-font-size-2xl, 1.9531rem);
105
141
  --cg-text-3xl: var(--cogenta-font-size-3xl, 2.4414rem);
106
142
 
107
- /* Unitless throughout: a line height inherited as a fixed pixel value is the
108
- classic cause of clipped text at 200% zoom (WCAG 1.4.4). */
109
- --cg-leading-tight: 1.06;
110
- --cg-leading-snug: 1.2;
111
- --cg-leading-normal: 1.5;
112
- --cg-leading-relaxed: 1.7;
143
+ /* The smallest text the theme sets: a skin with a steep ratio would push
144
+ `xs` below what anyone reads comfortably, so it is floored. */
145
+ --cg-text-label: max(var(--cg-text-xs), 0.8125rem);
146
+
147
+ /* Display sizes, as multiples of the top step, grown with the viewport
148
+ between a phone and a desktop. */
149
+ --cg-text-display: clamp(
150
+ calc(var(--cg-text-2xl) * 1.2),
151
+ calc(var(--cg-text-xl) + 4vw),
152
+ calc(var(--cg-text-3xl) * 1.75)
153
+ );
154
+ --cg-text-title: clamp(
155
+ var(--cg-text-2xl),
156
+ calc(var(--cg-text-lg) + 3vw),
157
+ calc(var(--cg-text-3xl) * 1.35)
158
+ );
159
+ --cg-text-heading: clamp(var(--cg-text-lg), calc(var(--cg-text-md) + 1vw), var(--cg-text-xl));
160
+ --cg-text-figure: clamp(var(--cg-text-2xl), calc(var(--cg-text-lg) + 2vw), var(--cg-text-3xl));
161
+
162
+ /* Unitless, so a line height never inherits as a fixed length (WCAG 1.4.4). */
163
+ --cg-leading-display: 1.04;
164
+ --cg-leading-heading: 1.2;
165
+ --cg-leading-snug: 1.35;
166
+ --cg-leading-body: 1.6;
113
167
 
114
- /* Display type needs negative tracking to stop looking loose; small caps
115
- labels need positive. Both are ems, so they follow the font size. */
116
- --cg-tracking-tight: -0.022em;
117
- --cg-tracking-snug: -0.012em;
118
- --cg-tracking-normal: 0em;
119
- --cg-tracking-wide: 0.08em;
168
+ /* Large type is tightened a little, never so much that letters touch. */
169
+ --cg-tracking-display: -0.012em;
170
+ --cg-tracking-heading: -0.014em;
120
171
 
121
172
  --cg-weight-regular: 400;
122
173
  --cg-weight-medium: 500;
123
174
  --cg-weight-semibold: 600;
124
- --cg-weight-bold: 700;
125
175
  }
126
176
 
127
177
  /* --------------------------------------------------------------------------
128
- Radius — the skin's three, plus the two ends they imply
178
+ Corners and motion
129
179
  -------------------------------------------------------------------------- */
130
180
 
131
181
  :where(:root) {
132
- --cg-radius-xs: calc(var(--cogenta-radius-sm) / 2);
133
- --cg-radius-sm: var(--cogenta-radius-sm);
134
- --cg-radius-md: var(--cogenta-radius-md);
135
- --cg-radius-lg: var(--cogenta-radius-lg);
136
- /* Panels and media want to round harder than a button does. Derived, so a
137
- square skin (`radius.lg: 0`) stays square all the way up. */
138
- --cg-radius-xl: calc(var(--cogenta-radius-lg) * 1.75);
139
- --cg-radius-pill: 999rem;
140
- }
141
-
142
- /* --------------------------------------------------------------------------
143
- Motion
144
- -------------------------------------------------------------------------- */
182
+ /* A control is softened by a hair, whatever the skin asks; a photograph,
183
+ a frame or a band keeps a square corner. */
184
+ --cg-radius-control: min(var(--cogenta-radius-sm), 0.25rem);
145
185
 
146
- :where(:root) {
147
- --cg-duration-fast: calc(var(--cogenta-motion-duration) * 0.6);
148
- --cg-duration: var(--cogenta-motion-duration);
149
- --cg-duration-slow: calc(var(--cogenta-motion-duration) * 2.6);
186
+ /* Colour and underline only, never longer than 150 ms. */
187
+ --cg-duration: min(var(--cogenta-motion-duration), 150ms);
150
188
  --cg-ease: var(--cogenta-motion-easing);
151
189
  }
152
190
 
191
+ @media (prefers-reduced-motion: reduce) {
192
+ :root {
193
+ --cg-duration: 0ms;
194
+ }
195
+ }
196
+
153
197
  /* --------------------------------------------------------------------------
154
- Colour — one palette per scheme, both derived from the same seven tokens
198
+ Colour
155
199
  --------------------------------------------------------------------------
156
200
 
157
- The block below declares the **light** palette in plain terms. The scheme
158
- aware values live in the `@supports` block after it, and only there.
159
-
160
- Why the split rather than one `light-dark()` per token: a custom property
161
- accepts any token sequence, so a browser that does not know `light-dark()`
162
- still stores the declaration and only fails when the value is *used* — at
163
- which point the property becomes `unset` and the page loses its colour. A
164
- feature query is the only construct that actually falls back here, and it is
165
- written with `currentColor` so it needs no colour literal of its own.
166
-
167
- **The dark palette is designed, not inverted.** Five decisions separate it
168
- from a mechanical swap of `bg` and `fg`, and each one is the opposite of what
169
- inversion produces:
170
-
171
- 1. *Elevation runs the other way.* In light, a raised surface is the same
172
- paper with a shadow under it. In dark, a shadow on a dark ground conveys
173
- nothing, so elevation is expressed as **lightness**: sunken < canvas <
174
- surface < raised, each a step up in L. Shadows give way to a hairline
175
- ring (`--cg-ring`).
176
- 2. *The accent is lifted, not kept.* A mid-dark accent that reads well on
177
- paper is muddy on ink, so the dark accent is pushed to L 0.74 — brighter
178
- than the skin's own accent, which inversion would never do.
179
- 3. *Therefore the accent's foreground flips to dark.* Light label text on a
180
- lifted accent fails contrast; the dark palette derives an ink-dark
181
- `accent-fg` from the accent's own hue. This is the clearest single
182
- difference from inversion, which would have kept the skin's `accentFg`.
183
- 4. *Text is never pure light.* Ink is L 0.945 with a trace of the accent's
184
- chroma — off-white reduces the halation pure white causes on dark.
185
- 5. *Borders become light overlays.* A darker line on a dark surface is
186
- invisible; the dark border is a step up in lightness, not down.
187
-
188
- The hue and chroma of every dark value come from a skin token, so a skin with
189
- an orange accent gets a warm dark palette without touching this file. The
190
- *lightness* targets are the theme's — which is exactly the split contract D
191
- draws: the skin owns the colours, the theme owns what it does with them.
192
-
193
- Every ratio these values produce is computed for real, from this file, by
194
- `test/design-system.test.ts` — in both schemes, against the AA body
195
- threshold. None of the numbers above is a comment to be trusted.
196
-
197
- Known limit, recorded in `BLOCKERS.md`: the derivation assumes a light-first
198
- skin (`bg` lighter than `fg`), which is what contract D's default and all
199
- nine blueprints use. A skin that is already dark would need a second colour
200
- group in the contract — a `theme@2.0` bump, not a change this theme can make.
201
+ The block below is the light palette in plain terms; the scheme-aware
202
+ values live in the `@supports` block after it, and only there. A browser
203
+ that cannot parse `light-dark()` would still store such a custom property
204
+ and fail only when it is used, leaving the page without colour; the feature
205
+ query is the construct that actually falls back.
206
+
207
+ Roles, not hues. Neutrals carry the page: canvas, a band a step off it,
208
+ ink, a muted ink, hairlines. The skin's accent is kept for what a reader
209
+ acts on in running text (a link, the focus ring, a selection). A primary
210
+ action is set in ink on the canvas, so an accent a skin picks, however
211
+ light or loud, never decides whether a button is legible.
212
+
213
+ **The dark palette is designed, not inverted.**
214
+
215
+ 1. The ground is a near-black taken from the skin's own ink, so a warm skin
216
+ gets a warm dark page and a neutral one stays neutral.
217
+ 2. Depth runs by lightness: the footer below the ground, a band above it.
218
+ 3. Type is the skin's own paper, lowered a step below white, which avoids
219
+ the halation of pure white on black.
220
+ 4. The accent is lifted to a light tint of its own hue: a deep blue that
221
+ reads on paper is mud on black.
222
+ 5. Hairlines become a step up in lightness, never down.
201
223
  -------------------------------------------------------------------------- */
202
224
 
203
225
  :where(:root) {
204
226
  --cg-canvas: var(--cogenta-color-bg);
205
- --cg-surface: var(--cogenta-color-bg);
206
- --cg-surface-raised: var(--cogenta-color-bg);
207
- --cg-surface-sunken: var(--cogenta-color-muted);
208
- --cg-surface-tinted: color-mix(in oklab, var(--cogenta-color-accent) 8%, var(--cogenta-color-bg));
227
+ --cg-band: var(--cogenta-color-muted);
228
+ --cg-footer: var(--cogenta-color-muted);
209
229
 
210
230
  --cg-ink: var(--cogenta-color-fg);
211
231
  --cg-ink-muted: var(--cogenta-color-muted-fg);
212
- /* Tertiary: timestamps, credits, the second line of a card. */
213
- --cg-ink-subtle: color-mix(in oklab, var(--cogenta-color-muted-fg) 88%, var(--cogenta-color-bg));
232
+
233
+ --cg-line: var(--cogenta-color-border);
234
+ --cg-line-strong: color-mix(in oklab, var(--cogenta-color-border) 45%, var(--cogenta-color-fg));
214
235
 
215
236
  --cg-accent: var(--cogenta-color-accent);
216
- --cg-accent-fg: var(--cogenta-color-accent-fg);
217
- --cg-accent-hover: color-mix(in oklab, var(--cogenta-color-accent) 86%, var(--cogenta-color-fg));
218
- --cg-accent-soft: color-mix(in oklab, var(--cogenta-color-accent) 10%, var(--cogenta-color-bg));
219
- --cg-accent-soft-fg: color-mix(
220
- in oklab,
221
- var(--cogenta-color-accent) 68%,
222
- var(--cogenta-color-fg)
223
- );
237
+ --cg-accent-hover: color-mix(in oklab, var(--cogenta-color-accent) 70%, var(--cogenta-color-fg));
238
+ --cg-selection: color-mix(in oklab, var(--cogenta-color-accent) 18%, var(--cogenta-color-bg));
224
239
 
225
- --cg-line: var(--cogenta-color-border);
226
- --cg-line-soft: color-mix(in oklab, var(--cogenta-color-border) 55%, var(--cogenta-color-bg));
227
- --cg-line-strong: color-mix(in oklab, var(--cogenta-color-border) 55%, var(--cogenta-color-fg));
240
+ --cg-action: var(--cogenta-color-fg);
241
+ --cg-action-fg: var(--cogenta-color-bg);
242
+ --cg-action-hover: color-mix(in oklab, var(--cogenta-color-fg) 78%, var(--cogenta-color-bg));
228
243
 
229
- /* Overlay ground, for a scrim over media. */
230
- --cg-scrim: color-mix(in oklab, var(--cogenta-color-fg) 62%, transparent);
244
+ /* Photographs are dimmed a step in the dark; a wordmark drawn in ink is
245
+ turned light. Numbers, so the filter itself is written once. */
246
+ --cg-image-brightness: 1;
247
+ --cg-mark-invert: 0;
231
248
  }
232
249
 
233
250
  @supports (color: light-dark(currentColor, currentColor)) and
@@ -235,105 +252,75 @@
235
252
  :where(:root) {
236
253
  --cg-canvas: light-dark(
237
254
  var(--cogenta-color-bg),
238
- oklch(from var(--cogenta-color-fg) 0.17 calc(c * 0.7) h)
255
+ oklch(from var(--cogenta-color-fg) 0.17 calc(c * 0.6) h)
239
256
  );
240
- --cg-surface: light-dark(
241
- var(--cogenta-color-bg),
242
- oklch(from var(--cogenta-color-fg) 0.215 calc(c * 0.62) h)
243
- );
244
- --cg-surface-raised: light-dark(
245
- var(--cogenta-color-bg),
246
- oklch(from var(--cogenta-color-fg) 0.26 calc(c * 0.55) h)
247
- );
248
- --cg-surface-sunken: light-dark(
257
+ --cg-band: light-dark(
249
258
  var(--cogenta-color-muted),
250
- oklch(from var(--cogenta-color-fg) 0.13 calc(c * 0.8) h)
259
+ oklch(from var(--cogenta-color-fg) 0.215 calc(c * 0.6) h)
251
260
  );
252
- --cg-surface-tinted: light-dark(
253
- color-mix(in oklab, var(--cogenta-color-accent) 8%, var(--cogenta-color-bg)),
254
- oklch(from var(--cogenta-color-accent) 0.255 calc(c * 0.5) h)
261
+ --cg-footer: light-dark(
262
+ var(--cogenta-color-muted),
263
+ oklch(from var(--cogenta-color-fg) 0.135 calc(c * 0.6) h)
255
264
  );
256
265
 
257
266
  --cg-ink: light-dark(
258
267
  var(--cogenta-color-fg),
259
- oklch(from var(--cogenta-color-accent) 0.945 0.012 h)
268
+ oklch(from var(--cogenta-color-bg) 0.93 calc(c * 0.8) h)
260
269
  );
261
270
  --cg-ink-muted: light-dark(
262
271
  var(--cogenta-color-muted-fg),
263
- oklch(from var(--cogenta-color-accent) 0.78 0.018 h)
272
+ oklch(from var(--cogenta-color-bg) 0.76 calc(c * 0.8) h)
264
273
  );
265
- --cg-ink-subtle: light-dark(
266
- color-mix(in oklab, var(--cogenta-color-muted-fg) 88%, var(--cogenta-color-bg)),
267
- oklch(from var(--cogenta-color-accent) 0.68 0.016 h)
274
+
275
+ --cg-line: light-dark(
276
+ var(--cogenta-color-border),
277
+ oklch(from var(--cogenta-color-fg) 0.33 calc(c * 0.6) h)
278
+ );
279
+ --cg-line-strong: light-dark(
280
+ color-mix(in oklab, var(--cogenta-color-border) 45%, var(--cogenta-color-fg)),
281
+ oklch(from var(--cogenta-color-fg) 0.56 calc(c * 0.6) h)
268
282
  );
269
283
 
284
+ /* On a light page the accent keeps its hue and chroma but never gets
285
+ lighter than L 0.5: the default deep blue passes through unchanged, and
286
+ an orange or a yellow a skin picks becomes a darker tone of itself that
287
+ still reads as link text. */
270
288
  --cg-accent: light-dark(
271
- var(--cogenta-color-accent),
272
- oklch(from var(--cogenta-color-accent) 0.74 calc(c * 0.85) h)
273
- );
274
- --cg-accent-fg: light-dark(
275
- var(--cogenta-color-accent-fg),
276
- oklch(from var(--cogenta-color-accent) 0.18 calc(c * 0.55) h)
289
+ oklch(from var(--cogenta-color-accent) min(l, 0.5) c h),
290
+ oklch(from var(--cogenta-color-accent) 0.78 calc(c * 0.7) h)
277
291
  );
278
292
  --cg-accent-hover: light-dark(
279
- color-mix(in oklab, var(--cogenta-color-accent) 86%, var(--cogenta-color-fg)),
280
- oklch(from var(--cogenta-color-accent) 0.82 calc(c * 0.8) h)
281
- );
282
- --cg-accent-soft: light-dark(
283
- color-mix(in oklab, var(--cogenta-color-accent) 10%, var(--cogenta-color-bg)),
284
- oklch(from var(--cogenta-color-accent) 0.3 calc(c * 0.5) h)
293
+ oklch(from var(--cogenta-color-accent) min(l, 0.36) c h),
294
+ oklch(from var(--cogenta-color-accent) 0.87 calc(c * 0.5) h)
285
295
  );
286
- --cg-accent-soft-fg: light-dark(
287
- color-mix(in oklab, var(--cogenta-color-accent) 68%, var(--cogenta-color-fg)),
288
- oklch(from var(--cogenta-color-accent) 0.9 calc(c * 0.45) h)
296
+ --cg-selection: light-dark(
297
+ color-mix(in oklab, var(--cogenta-color-accent) 18%, var(--cogenta-color-bg)),
298
+ oklch(from var(--cogenta-color-accent) 0.36 calc(c * 0.6) h)
289
299
  );
290
300
 
291
- --cg-line: light-dark(
292
- var(--cogenta-color-border),
293
- oklch(from var(--cogenta-color-accent) 0.33 calc(c * 0.22) h)
301
+ --cg-action: light-dark(
302
+ var(--cogenta-color-fg),
303
+ oklch(from var(--cogenta-color-bg) 0.93 calc(c * 0.8) h)
294
304
  );
295
- --cg-line-soft: light-dark(
296
- color-mix(in oklab, var(--cogenta-color-border) 55%, var(--cogenta-color-bg)),
297
- oklch(from var(--cogenta-color-accent) 0.26 calc(c * 0.2) h)
305
+ --cg-action-fg: light-dark(
306
+ var(--cogenta-color-bg),
307
+ oklch(from var(--cogenta-color-fg) 0.17 calc(c * 0.6) h)
298
308
  );
299
- --cg-line-strong: light-dark(
300
- color-mix(in oklab, var(--cogenta-color-border) 55%, var(--cogenta-color-fg)),
301
- oklch(from var(--cogenta-color-accent) 0.58 calc(c * 0.25) h)
309
+ --cg-action-hover: light-dark(
310
+ color-mix(in oklab, var(--cogenta-color-fg) 78%, var(--cogenta-color-bg)),
311
+ oklch(from var(--cogenta-color-bg) 0.82 calc(c * 0.8) h)
302
312
  );
303
313
  }
304
314
  }
305
315
 
306
- /* --------------------------------------------------------------------------
307
- Elevation — a shadow in light, a lighter surface and a ring in dark
308
- --------------------------------------------------------------------------
309
-
310
- `light-dark()` takes colours only, so these three cannot use it: a shadow is
311
- not a colour. They are the one place in this file where the dark values are
312
- written under a media query and repeated for the explicit toggle.
313
- -------------------------------------------------------------------------- */
314
-
315
- :where(:root) {
316
- /* Inset, so it never adds to the box's size and can sit in the same
317
- `box-shadow` list as a real drop shadow. */
318
- --cg-ring: inset 0 0 0 1px var(--cg-line);
319
- --cg-ring-accent: inset 0 0 0 1px var(--cg-accent);
320
-
321
- --cg-elevation-0: none;
322
- --cg-elevation-1: var(--cogenta-shadow-sm);
323
- --cg-elevation-2: var(--cogenta-shadow-md);
324
- --cg-elevation-3: var(--cogenta-shadow-md), var(--cogenta-shadow-sm);
325
- }
326
-
327
316
  @media (prefers-color-scheme: dark) {
328
317
  :where(:root:not([data-theme="light"])) {
329
- --cg-elevation-1: var(--cg-ring);
330
- --cg-elevation-2: var(--cg-ring);
331
- --cg-elevation-3: var(--cg-ring), var(--cogenta-shadow-md);
318
+ --cg-image-brightness: 0.9;
319
+ --cg-mark-invert: 1;
332
320
  }
333
321
  }
334
322
 
335
323
  :where(:root[data-theme="dark"]) {
336
- --cg-elevation-1: var(--cg-ring);
337
- --cg-elevation-2: var(--cg-ring);
338
- --cg-elevation-3: var(--cg-ring), var(--cogenta-shadow-md);
324
+ --cg-image-brightness: 0.9;
325
+ --cg-mark-invert: 1;
339
326
  }