@cogenta/theme-portfolio 1.1.3 → 1.3.4

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 (128) hide show
  1. package/dist/src/index.d.ts +9 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +10 -1
  4. package/dist/src/index.js.map +1 -1
  5. package/dist/src/render/blocks/accordion.d.ts.map +1 -1
  6. package/dist/src/render/blocks/accordion.js +10 -18
  7. package/dist/src/render/blocks/accordion.js.map +1 -1
  8. package/dist/src/render/blocks/collection-list.d.ts +0 -20
  9. package/dist/src/render/blocks/collection-list.d.ts.map +1 -1
  10. package/dist/src/render/blocks/collection-list.js +59 -66
  11. package/dist/src/render/blocks/collection-list.js.map +1 -1
  12. package/dist/src/render/blocks/cta.d.ts +4 -4
  13. package/dist/src/render/blocks/cta.d.ts.map +1 -1
  14. package/dist/src/render/blocks/cta.js +15 -10
  15. package/dist/src/render/blocks/cta.js.map +1 -1
  16. package/dist/src/render/blocks/embed.d.ts.map +1 -1
  17. package/dist/src/render/blocks/embed.js +16 -31
  18. package/dist/src/render/blocks/embed.js.map +1 -1
  19. package/dist/src/render/blocks/faq.d.ts.map +1 -1
  20. package/dist/src/render/blocks/faq.js +12 -17
  21. package/dist/src/render/blocks/faq.js.map +1 -1
  22. package/dist/src/render/blocks/feature-grid.d.ts.map +1 -1
  23. package/dist/src/render/blocks/feature-grid.js +26 -23
  24. package/dist/src/render/blocks/feature-grid.js.map +1 -1
  25. package/dist/src/render/blocks/gallery.d.ts +0 -14
  26. package/dist/src/render/blocks/gallery.d.ts.map +1 -1
  27. package/dist/src/render/blocks/gallery.js +29 -21
  28. package/dist/src/render/blocks/gallery.js.map +1 -1
  29. package/dist/src/render/blocks/hero.d.ts +8 -8
  30. package/dist/src/render/blocks/hero.d.ts.map +1 -1
  31. package/dist/src/render/blocks/hero.js +17 -18
  32. package/dist/src/render/blocks/hero.js.map +1 -1
  33. package/dist/src/render/blocks/logo-strip.d.ts.map +1 -1
  34. package/dist/src/render/blocks/logo-strip.js +9 -14
  35. package/dist/src/render/blocks/logo-strip.js.map +1 -1
  36. package/dist/src/render/blocks/logos.d.ts.map +1 -1
  37. package/dist/src/render/blocks/logos.js +14 -19
  38. package/dist/src/render/blocks/logos.js.map +1 -1
  39. package/dist/src/render/blocks/media-figure.d.ts +8 -12
  40. package/dist/src/render/blocks/media-figure.d.ts.map +1 -1
  41. package/dist/src/render/blocks/media-figure.js +20 -20
  42. package/dist/src/render/blocks/media-figure.js.map +1 -1
  43. package/dist/src/render/blocks/pricing-table.d.ts.map +1 -1
  44. package/dist/src/render/blocks/pricing-table.js +17 -20
  45. package/dist/src/render/blocks/pricing-table.js.map +1 -1
  46. package/dist/src/render/blocks/prose.d.ts +10 -9
  47. package/dist/src/render/blocks/prose.d.ts.map +1 -1
  48. package/dist/src/render/blocks/prose.js +29 -10
  49. package/dist/src/render/blocks/prose.js.map +1 -1
  50. package/dist/src/render/blocks/quote.d.ts +5 -12
  51. package/dist/src/render/blocks/quote.d.ts.map +1 -1
  52. package/dist/src/render/blocks/quote.js +9 -15
  53. package/dist/src/render/blocks/quote.js.map +1 -1
  54. package/dist/src/render/blocks/stat-counter.d.ts.map +1 -1
  55. package/dist/src/render/blocks/stat-counter.js +10 -12
  56. package/dist/src/render/blocks/stat-counter.js.map +1 -1
  57. package/dist/src/render/blocks/stats.d.ts.map +1 -1
  58. package/dist/src/render/blocks/stats.js +7 -15
  59. package/dist/src/render/blocks/stats.js.map +1 -1
  60. package/dist/src/render/blocks/testimonial.d.ts +4 -14
  61. package/dist/src/render/blocks/testimonial.d.ts.map +1 -1
  62. package/dist/src/render/blocks/testimonial.js +9 -18
  63. package/dist/src/render/blocks/testimonial.js.map +1 -1
  64. package/dist/src/render/chrome.d.ts.map +1 -1
  65. package/dist/src/render/chrome.js +93 -90
  66. package/dist/src/render/chrome.js.map +1 -1
  67. package/dist/src/render/layout.d.ts +61 -0
  68. package/dist/src/render/layout.d.ts.map +1 -0
  69. package/dist/src/render/layout.js +134 -0
  70. package/dist/src/render/layout.js.map +1 -0
  71. package/dist/src/render/project.d.ts +27 -0
  72. package/dist/src/render/project.d.ts.map +1 -0
  73. package/dist/src/render/project.js +82 -0
  74. package/dist/src/render/project.js.map +1 -0
  75. package/dist/src/render/render-block.d.ts +17 -7
  76. package/dist/src/render/render-block.d.ts.map +1 -1
  77. package/dist/src/render/render-block.js +47 -34
  78. package/dist/src/render/render-block.js.map +1 -1
  79. package/dist/src/render/term-archive.d.ts +0 -11
  80. package/dist/src/render/term-archive.d.ts.map +1 -1
  81. package/dist/src/render/term-archive.js +36 -24
  82. package/dist/src/render/term-archive.js.map +1 -1
  83. package/dist/src/render/widget-areas.d.ts +14 -0
  84. package/dist/src/render/widget-areas.d.ts.map +1 -0
  85. package/dist/src/render/widget-areas.js +21 -0
  86. package/dist/src/render/widget-areas.js.map +1 -0
  87. package/dist/src/render/work.d.ts +37 -0
  88. package/dist/src/render/work.d.ts.map +1 -0
  89. package/dist/src/render/work.js +49 -0
  90. package/dist/src/render/work.js.map +1 -0
  91. package/dist/theme.config.d.ts +4 -7
  92. package/dist/theme.config.d.ts.map +1 -1
  93. package/dist/theme.config.js +6 -9
  94. package/dist/theme.config.js.map +1 -1
  95. package/package.json +4 -4
  96. package/src/index.ts +10 -1
  97. package/src/render/blocks/accordion.ts +22 -42
  98. package/src/render/blocks/collection-list.ts +83 -137
  99. package/src/render/blocks/cta.ts +24 -12
  100. package/src/render/blocks/embed.ts +39 -47
  101. package/src/render/blocks/faq.ts +24 -33
  102. package/src/render/blocks/feature-grid.ts +38 -41
  103. package/src/render/blocks/gallery.ts +34 -28
  104. package/src/render/blocks/hero.ts +31 -28
  105. package/src/render/blocks/logo-strip.ts +18 -20
  106. package/src/render/blocks/logos.ts +22 -43
  107. package/src/render/blocks/media-figure.ts +28 -20
  108. package/src/render/blocks/pricing-table.ts +31 -32
  109. package/src/render/blocks/prose.ts +38 -13
  110. package/src/render/blocks/quote.ts +18 -18
  111. package/src/render/blocks/stat-counter.ts +19 -37
  112. package/src/render/blocks/stats.ts +18 -33
  113. package/src/render/blocks/testimonial.ts +16 -22
  114. package/src/render/chrome.ts +99 -97
  115. package/src/render/layout.ts +177 -0
  116. package/src/render/project.ts +140 -0
  117. package/src/render/render-block.ts +49 -45
  118. package/src/render/term-archive.ts +92 -70
  119. package/src/render/widget-areas.ts +25 -0
  120. package/src/render/work.ts +124 -0
  121. package/src/styles/archive.css +61 -21
  122. package/src/styles/base.css +763 -648
  123. package/src/styles/blocks.css +697 -1093
  124. package/src/styles/theme.css +22 -10
  125. package/src/styles/tokens.css +174 -252
  126. package/src/styles/widgets.css +948 -0
  127. package/src/styles/work.css +405 -0
  128. package/tokens.json +19 -19
@@ -1,20 +1,32 @@
1
1
  /*
2
- * The portfolio theme's stylesheet — the entry point, and nothing else.
2
+ * `@cogenta/theme-portfolio`'s stylesheet: the entry point, and nothing else.
3
3
  *
4
- * Three layers, in the only order that works:
4
+ * tokens.css the design system, derived from the skin's `--cogenta-*`
5
+ * custom properties (contract D)
6
+ * base.css document, accessibility floor, grid, section labels,
7
+ * actions, header, footer, search, forms and comments
8
+ * work.css the work grid, the index, the strip, the project page
9
+ * blocks.css the other vocabulary blocks
10
+ * archive.css the taxonomy-term archive, set as the studio's index
11
+ * widgets.css the widget areas: the column beside an index, the bands
12
+ * before and after the work, the footer columns
5
13
  *
6
- * tokens.css the design system, derived entirely from the skin's
7
- * `--cogenta-*` custom properties (contract D)
8
- * base.css document, accessibility floor, page frame, chrome, actions
9
- * blocks.css the seventeen vocabulary blocks
14
+ * Not one colour is written literally in any of them: every value comes from
15
+ * a skin token or from a `--cg-*` property composed from those.
10
16
  *
11
- * Not one colour, font, radius, duration or shadow is written literally in any
12
- * of the three: every value comes from a `--cogenta-<group>-<name>` property
13
- * produced from the skin's tokens, or from a `--cg-*` property composed from
14
- * those.
17
+ * The one thing this file adds on its own is the Google Fonts request for
18
+ * Archivo with both of its axes: width (62 to 125, the display sizes are set
19
+ * wide) and weight. A skin only names a family; it never fetches one. The
20
+ * family falls back to a real system stack if Google Fonts is unreachable,
21
+ * and `display=swap` keeps text visible while it loads. `cogenta serve`
22
+ * hoists this `@import` above the skin's rules.
15
23
  */
16
24
 
25
+ @import url("https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&display=swap");
26
+
17
27
  @import "./tokens.css";
18
28
  @import "./base.css";
29
+ @import "./work.css";
19
30
  @import "./blocks.css";
20
31
  @import "./archive.css";
32
+ @import "./widgets.css";
@@ -1,35 +1,25 @@
1
1
  /*
2
- * The portfolio theme's design system.
2
+ * `@cogenta/theme-portfolio`'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, `clamp`). A skin swap rewrites the
9
- * generated `--cogenta-*` sheet and this whole system follows, with no build
10
- * step.
4
+ * The register is an independent design studio: black type on white paper,
5
+ * work shown large and square-cornered, one signal colour kept for a couple of
6
+ * details, and structure drawn with space and hairlines, never with boxes or
7
+ * shadows. One family, Archivo, does everything: its width axis sets the
8
+ * display sizes wide and calm, and the text sits at its regular width.
11
9
  *
12
- * Two rules hold everywhere in this file and the two that import it:
10
+ * Contract D fixes a closed skin token set, so nothing here adds a token:
11
+ * every value is derived from a `--cogenta-*` property (`calc`, `color-mix`,
12
+ * relative colour syntax).
13
13
  *
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.
16
- * 2. **No second colour or type scale.** The type steps come from
17
- * `--cogenta-font-size-*` and the spacing multiplier from
18
- * `--cogenta-space-scale`. The display headline sizes below (`--cg-text-
19
- * hero`, `--cg-text-jumbo`, …) are `clamp()` *lengths*, not colours — the
20
- * isolation rule is about colour, and a viewport-responsive headline scale
21
- * is exactly the "risk-taking" this theme's brief asks for, tied to the
22
- * same weight/tracking/leading tokens as the rest of the system.
14
+ * Two rules hold in every stylesheet of this theme:
15
+ *
16
+ * 1. No colour literal. Every colour is a skin token or a function of one.
17
+ * 2. No second scale. Type steps come from `--cogenta-font-size-*`; the
18
+ * display steps above `3xl` continue the same ratio, and fluid sizes only
19
+ * interpolate between steps of that one ladder.
23
20
  */
24
21
 
25
- /* Google Fonts — a real fallback stack accompanies every one, so the theme
26
- degrades to a system stack rather than to invisible text when the network
27
- is unavailable (`font-display: swap` is the default for this endpoint). */
28
- @import url("https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,200..800&family=Fraunces:ital,opsz,wght@0,9..144,300..700;1,9..144,300..700&family=JetBrains+Mono:wght@400;500;600&display=swap");
29
-
30
22
  :where(:root) {
31
- /* Lets the browser paint native controls, scrollbars and form widgets in the
32
- right scheme, and is what makes `light-dark()` below resolve at all. */
33
23
  color-scheme: light dark;
34
24
  }
35
25
 
@@ -42,7 +32,7 @@
42
32
  }
43
33
 
44
34
  /* --------------------------------------------------------------------------
45
- Space
35
+ Space: one unit, one section rhythm, one twelve-column grid.
46
36
  -------------------------------------------------------------------------- */
47
37
 
48
38
  :where(:root) {
@@ -63,156 +53,138 @@
63
53
  --cg-s24: calc(var(--cg-unit) * 24);
64
54
  --cg-s32: calc(var(--cg-unit) * 32);
65
55
 
66
- --cg-gutter: var(--cg-s5);
67
- --cg-gap-tight: var(--cg-s2);
68
- --cg-gap: var(--cg-s4);
69
- --cg-gap-loose: var(--cg-s10);
70
- --cg-section-y: var(--cg-s24);
56
+ /* The only vertical rhythm between blocks. Every block is padded by half of
57
+ it above and below, so any two blocks sit one full step apart, whatever
58
+ their order. A studio page breathes: the step is long. */
59
+ --cg-section: clamp(var(--cg-s16), 9vw, var(--cg-s32));
60
+
61
+ /* Twelve columns with constant gutters, on a wide page: the work is shown
62
+ large. */
63
+ --cg-columns: 12;
64
+ --cg-gutter: clamp(var(--cg-s5), 3vw, var(--cg-s12));
65
+ --cg-col-gap: clamp(var(--cg-s4), 1.7vw, var(--cg-s8));
66
+ --cg-row-gap: clamp(var(--cg-s12), 6vw, var(--cg-s24));
67
+ --cg-page: 96rem;
68
+
69
+ --cg-measure: 64ch;
70
+ --cg-measure-short: 44ch;
71
+ --cg-header-height: 4.5rem;
72
+ }
73
+
74
+ :where([data-density="compact"]) {
75
+ --cg-density: 0.75;
76
+ }
77
+
78
+ :where([data-density="comfortable"]) {
79
+ --cg-density: 1;
80
+ }
71
81
 
72
- --cg-measure: 66ch;
73
- --cg-measure-narrow: 44ch;
74
- --cg-page: 84rem;
75
- --cg-page-narrow: 52rem;
82
+ :where([data-density="spacious"]) {
83
+ --cg-density: 1.25;
76
84
  }
77
85
 
78
86
  /* --------------------------------------------------------------------------
79
- Type — the skin's scale, named, plus the display tier a portfolio's
80
- headlines need. `renderSkin` only ever emits seven steps up to `3xl`; the
81
- display tier is composed on top of `3xl` with `calc`, so a skin with a
82
- flatter scale still produces a *bigger* display size than its own body
83
- text, in proportion — never a fixed number disconnected from the skin.
87
+ Type: one family, two widths.
84
88
  -------------------------------------------------------------------------- */
85
89
 
86
90
  :where(:root) {
87
- --cg-text-xs: var(--cogenta-font-size-xs, 0.64rem);
88
- --cg-text-sm: var(--cogenta-font-size-sm, 0.8rem);
89
- --cg-text-md: var(--cogenta-font-size-md, var(--cogenta-font-base-size, 1rem));
90
- --cg-text-lg: var(--cogenta-font-size-lg, 1.25rem);
91
- --cg-text-xl: var(--cogenta-font-size-xl, 1.5625rem);
92
- --cg-text-2xl: var(--cogenta-font-size-2xl, 1.9531rem);
93
- --cg-text-3xl: var(--cogenta-font-size-3xl, 2.4414rem);
94
-
95
- /* Fluid display tiers — clamped between a floor that still reads as
96
- "headline" on a phone and a ceiling this theme's brief asks for outright
97
- (8-12rem worth of visual weight once line-height and tracking are
98
- applied). Each is anchored to `--cg-text-3xl` so a skin with a smaller
99
- base type still gets a proportionally smaller, never a fixed, display
100
- size. */
101
- --cg-text-jumbo: clamp(calc(var(--cg-text-3xl) * 1.6), 11vw, calc(var(--cg-text-3xl) * 4.1));
102
- --cg-text-hero: clamp(
103
- calc(var(--cg-text-3xl) * 1.35),
104
- 7vw +
105
- 1rem,
106
- calc(var(--cg-text-3xl) * 2.85)
91
+ --cg-font: var(--cogenta-font-sans);
92
+ --cg-font-code: var(--cogenta-font-mono);
93
+
94
+ /* Archivo's width axis runs from 62 to 125. The display sizes are set wide,
95
+ which calms a large line and gives it the proportions of a studio's
96
+ lettering; text and interface stay at the width the face was drawn for. */
97
+ --cg-width-text: 100%;
98
+ --cg-width-display: 112%;
99
+ --cg-width-wide: 125%;
100
+
101
+ --cg-text-xs: var(--cogenta-font-size-xs, 0.68rem);
102
+ --cg-text-sm: var(--cogenta-font-size-sm, 0.85rem);
103
+ --cg-text-md: var(--cogenta-font-size-md, var(--cogenta-font-base-size, 1.0625rem));
104
+ --cg-text-lg: var(--cogenta-font-size-lg, 1.33rem);
105
+ --cg-text-xl: var(--cogenta-font-size-xl, 1.66rem);
106
+ --cg-text-2xl: var(--cogenta-font-size-2xl, 2.08rem);
107
+ --cg-text-3xl: var(--cogenta-font-size-3xl, 2.59rem);
108
+ /* The same ladder, continued: each step is the previous one times the
109
+ skin's own ratio. */
110
+ --cg-text-4xl: calc(var(--cg-text-3xl) * var(--cogenta-font-scale, 1.25));
111
+ --cg-text-5xl: calc(var(--cg-text-4xl) * var(--cogenta-font-scale, 1.25));
112
+ --cg-text-6xl: calc(var(--cg-text-5xl) * var(--cogenta-font-scale, 1.25));
113
+ --cg-text-7xl: calc(var(--cg-text-6xl) * var(--cogenta-font-scale, 1.25));
114
+
115
+ /* Captions and labels sit between `sm` and `md`. */
116
+ --cg-text-caption: calc((var(--cg-text-sm) + var(--cg-text-md)) / 2);
117
+ /* The reading size: `md` on a phone, a little above it on a desk. */
118
+ --cg-text-reading: clamp(
119
+ var(--cg-text-md),
120
+ calc(0.95rem + 0.22vw),
121
+ calc((var(--cg-text-md) * 3 + var(--cg-text-lg)) / 4)
107
122
  );
108
- --cg-text-cta: clamp(
109
- calc(var(--cg-text-3xl) * 1.1),
110
- 5vw +
111
- 0.5rem,
112
- calc(var(--cg-text-3xl) * 1.95)
113
- );
114
- --cg-text-quote: clamp(
115
- calc(var(--cg-text-3xl) * 0.85),
116
- 3vw +
117
- 0.75rem,
118
- calc(var(--cg-text-3xl) * 1.35)
119
- );
120
- --cg-text-stat: clamp(
121
- calc(var(--cg-text-3xl) * 0.95),
122
- 3.5vw +
123
- 0.5rem,
124
- calc(var(--cg-text-3xl) * 1.7)
125
- );
126
-
127
- --cg-leading-tight: 1.02;
128
- --cg-leading-snug: 1.15;
129
- --cg-leading-normal: 1.5;
130
- --cg-leading-relaxed: 1.68;
131
123
 
132
- --cg-tracking-tighter: -0.035em;
133
- --cg-tracking-tight: -0.02em;
134
- --cg-tracking-snug: -0.01em;
135
- --cg-tracking-normal: 0em;
136
- --cg-tracking-wide: 0.09em;
137
- --cg-tracking-wider: 0.16em;
124
+ --cg-size-statement: clamp(var(--cg-text-2xl), calc(0.75rem + 4.9vw), var(--cg-text-7xl));
125
+ --cg-size-title: clamp(var(--cg-text-3xl), calc(0.9rem + 4.6vw), var(--cg-text-7xl));
126
+ --cg-size-contact: clamp(var(--cg-text-xl), calc(0.6rem + 4.1vw), var(--cg-text-6xl));
127
+ --cg-size-lead: clamp(var(--cg-text-lg), calc(0.85rem + 1.05vw), var(--cg-text-2xl));
128
+ --cg-size-heading: clamp(var(--cg-text-lg), calc(0.9rem + 0.9vw), var(--cg-text-2xl));
129
+ --cg-size-figure: clamp(var(--cg-text-3xl), calc(1rem + 3.6vw), var(--cg-text-6xl));
130
+ --cg-size-work: clamp(var(--cg-text-md), calc(0.85rem + 0.45vw), var(--cg-text-lg));
131
+ --cg-size-nav: clamp(var(--cg-text-2xl), calc(1rem + 6vw), var(--cg-text-4xl));
132
+
133
+ --cg-leading-display: 1;
134
+ --cg-leading-title: 1.04;
135
+ --cg-leading-heading: 1.12;
136
+ --cg-leading-lead: 1.28;
137
+ --cg-leading-text: 1.58;
138
+ --cg-leading-ui: 1.4;
139
+
140
+ --cg-tracking-display: -0.024em;
141
+ --cg-tracking-heading: -0.012em;
142
+ --cg-tracking-caption: 0.005em;
138
143
 
139
144
  --cg-weight-regular: 400;
140
145
  --cg-weight-medium: 500;
141
146
  --cg-weight-semibold: 600;
142
- --cg-weight-bold: 700;
143
- --cg-weight-black: 800;
144
147
  }
145
148
 
146
149
  /* --------------------------------------------------------------------------
147
- Radius — kept small and mostly square: a brutalist-editorial system draws
148
- its softness from generous space and huge type, not from rounded corners.
150
+ Shape and motion: square corners, motion is a colour or an underline.
149
151
  -------------------------------------------------------------------------- */
150
152
 
151
153
  :where(:root) {
152
- --cg-radius-xs: calc(var(--cogenta-radius-sm) / 2);
153
- --cg-radius-sm: var(--cogenta-radius-sm);
154
- --cg-radius-md: var(--cogenta-radius-md);
155
- --cg-radius-lg: var(--cogenta-radius-lg);
156
- --cg-radius-pill: 999rem;
157
- }
154
+ --cg-radius: var(--cogenta-radius-sm);
155
+ --cg-radius-control: var(--cogenta-radius-sm);
158
156
 
159
- /* --------------------------------------------------------------------------
160
- Motion
161
- -------------------------------------------------------------------------- */
162
-
163
- :where(:root) {
164
- --cg-duration-fast: calc(var(--cogenta-motion-duration) * 0.55);
165
- --cg-duration: var(--cogenta-motion-duration);
166
- --cg-duration-slow: calc(var(--cogenta-motion-duration) * 3.2);
157
+ --cg-duration: min(var(--cogenta-motion-duration), 150ms);
167
158
  --cg-ease: var(--cogenta-motion-easing);
159
+
160
+ --cg-rule: 1px;
161
+ --cg-rule-strong: 2px;
162
+ --cg-rule-heavy: 3px;
168
163
  }
169
164
 
170
165
  /* --------------------------------------------------------------------------
171
- Colour — one palette per scheme, both derived from the same seven tokens.
166
+ Colour: black and white, and one signal.
172
167
  --------------------------------------------------------------------------
173
168
 
174
- The block below declares the **light** palette in plain terms; the scheme
175
- aware values live in the `@supports` block after it.
176
-
177
- **The dark palette is designed, not inverted — this theme's own five
178
- decisions, not a restatement of any other theme's:**
179
-
180
- 1. *Elevation changes colour, never shape (L25 D5, binding: no glow).* In
181
- light, this is a brutalist system: a raised surface carries a hard,
182
- unblurred offset shadow straight from the skin's own `shadow.sm`/
183
- `shadow.md` tokens — a shape that reads as "cut paper laid on paper".
184
- A near-black shadow is invisible on a dark ground, so dark elevation
185
- keeps the *exact same* hard, zero-blur offset geometry and only
186
- recolours it in `--cg-line-strong` — the same brighter-than-surface
187
- line this palette already uses for depth (decision 5, below). An
188
- earlier version of this system read that shadow as a soft accent glow
189
- instead; that is precisely the generic "AI-generated" register the
190
- product owner ruled out, so elevation now stays flat in both schemes.
191
- 2. *The accent is pushed toward neon, not merely lifted.* Dark ink makes a
192
- mid-saturation accent read as merely "lighter"; this palette both lifts
193
- *and* re-saturates it (`calc(c * 1.05)` against light mode's own
194
- chroma), because a portfolio in dark mode is exactly the context an
195
- "electric" accent is chosen for in the first place.
196
- 3. *The accent foreground follows, ink-dark and warmed by the same hue*, so
197
- a button never reads as a light chip pasted onto a light accent.
198
- 4. *Text carries the accent's own warmth, not a neutral grey.* Ink in dark
199
- mode is not merely "off white" — its hue is drawn from the accent, so
200
- the whole dark page reads as one lit surface rather than white text
201
- dropped onto an unrelated background.
202
- 5. *Borders in dark mode are drawn brighter than the surface they outline*,
203
- because this system replaces shadow-as-depth with line-as-depth in dark
204
- mode (decision 1) — the border is doing elevation's job, so it has to be
205
- visible on its own, not merely "a shade darker than the panel".
206
-
207
- Every ratio below is computed for real, from this file, by
208
- `test/design-system.test.ts` — in both schemes, against the AA body
209
- threshold.
210
-
211
- Known limit, matching the same one `theme-canonical` records: the
212
- derivation assumes a light-first skin (`bg` lighter than `fg`), which is
213
- contract D's default and every current blueprint. A skin that is already
214
- dark would need a second colour group in the contract — a `theme@2.0`
215
- bump, not a change this theme can make on its own.
169
+ The first block declares the light palette plainly; the scheme-aware
170
+ values follow behind a feature query, so a browser that cannot parse
171
+ `light-dark()` still gets a complete light palette.
172
+
173
+ The signal (the skin's accent) is for details only: the underline of the
174
+ contact line, the focus ring, a selection. It is never a text colour at the
175
+ text size, which is why no pair below sets small text in it.
176
+
177
+ The dark palette is designed, not inverted:
178
+
179
+ 1. The ground is true black, the way a studio shows work on a screen, and
180
+ the few raised surfaces step up in lightness from it.
181
+ 2. Type is white lowered a step, so a long case study stays calm.
182
+ 3. The signal is kept exactly: it was chosen to hold on black and white.
183
+ 4. Hairlines are a step up in lightness from black.
184
+ 5. A mark drawn for paper keeps a light plate, so no logo disappears.
185
+
186
+ Every ratio is computed from this file by `test/design-system.test.ts`,
187
+ in both schemes.
216
188
  -------------------------------------------------------------------------- */
217
189
 
218
190
  :where(:root) {
@@ -220,144 +192,94 @@
220
192
  --cg-surface: var(--cogenta-color-bg);
221
193
  --cg-surface-raised: var(--cogenta-color-bg);
222
194
  --cg-surface-sunken: var(--cogenta-color-muted);
223
- --cg-surface-tinted: color-mix(in oklab, var(--cogenta-color-accent) 9%, var(--cogenta-color-bg));
224
- --cg-surface-inverted: var(--cogenta-color-fg);
225
- --cg-surface-inverted-fg: var(--cogenta-color-bg);
195
+ --cg-plate: var(--cogenta-color-muted);
226
196
 
227
197
  --cg-ink: var(--cogenta-color-fg);
228
198
  --cg-ink-muted: var(--cogenta-color-muted-fg);
229
- --cg-ink-subtle: color-mix(in oklab, var(--cogenta-color-muted-fg) 86%, var(--cogenta-color-bg));
230
-
231
- --cg-accent: var(--cogenta-color-accent);
232
- --cg-accent-fg: var(--cogenta-color-accent-fg);
233
- --cg-accent-hover: color-mix(in oklab, var(--cogenta-color-accent) 88%, var(--cogenta-color-fg));
234
- --cg-accent-soft: color-mix(in oklab, var(--cogenta-color-accent) 11%, var(--cogenta-color-bg));
235
- --cg-accent-soft-fg: color-mix(
236
- in oklab,
237
- var(--cogenta-color-accent) 70%,
238
- var(--cogenta-color-fg)
239
- );
199
+ --cg-ink-subtle: color-mix(in oklab, var(--cogenta-color-muted-fg) 88%, var(--cogenta-color-bg));
200
+ --cg-plate-ink: var(--cogenta-color-fg);
201
+
202
+ --cg-signal: var(--cogenta-color-accent);
203
+ --cg-signal-fg: var(--cogenta-color-accent-fg);
240
204
 
241
205
  --cg-line: var(--cogenta-color-border);
242
- --cg-line-soft: color-mix(in oklab, var(--cogenta-color-border) 55%, var(--cogenta-color-bg));
243
- --cg-line-strong: color-mix(in oklab, var(--cogenta-color-border) 60%, var(--cogenta-color-fg));
206
+ --cg-line-strong: color-mix(in oklab, var(--cogenta-color-border) 45%, var(--cogenta-color-fg));
207
+ --cg-line-ink: var(--cogenta-color-fg);
208
+
209
+ --cg-action: var(--cogenta-color-fg);
210
+ --cg-action-fg: var(--cogenta-color-bg);
211
+ --cg-action-hover: color-mix(in oklab, var(--cogenta-color-fg) 78%, var(--cogenta-color-bg));
212
+ --cg-action-hover-fg: var(--cogenta-color-bg);
244
213
 
245
- --cg-scrim: color-mix(in oklab, var(--cogenta-color-fg) 64%, transparent);
214
+ --cg-image-brightness: 1;
246
215
  }
247
216
 
248
217
  @supports (color: light-dark(currentColor, currentColor)) and
249
218
  (color: oklch(from currentColor l c h)) {
250
219
  :where(:root) {
251
- --cg-canvas: light-dark(
252
- var(--cogenta-color-bg),
253
- oklch(from var(--cogenta-color-fg) 0.155 calc(c * 0.65) h)
254
- );
255
- --cg-surface: light-dark(
256
- var(--cogenta-color-bg),
257
- oklch(from var(--cogenta-color-fg) 0.195 calc(c * 0.6) h)
258
- );
220
+ --cg-canvas: light-dark(var(--cogenta-color-bg), oklch(from var(--cogenta-color-fg) 0 0 h));
221
+ --cg-surface: light-dark(var(--cogenta-color-bg), oklch(from var(--cogenta-color-fg) 0 0 h));
259
222
  --cg-surface-raised: light-dark(
260
223
  var(--cogenta-color-bg),
261
- oklch(from var(--cogenta-color-fg) 0.24 calc(c * 0.52) h)
224
+ oklch(from var(--cogenta-color-fg) 0.19 c h)
262
225
  );
263
226
  --cg-surface-sunken: light-dark(
264
227
  var(--cogenta-color-muted),
265
- oklch(from var(--cogenta-color-fg) 0.12 calc(c * 0.75) h)
266
- );
267
- --cg-surface-tinted: light-dark(
268
- color-mix(in oklab, var(--cogenta-color-accent) 9%, var(--cogenta-color-bg)),
269
- oklch(from var(--cogenta-color-accent) 0.24 calc(c * 0.48) h)
270
- );
271
- --cg-surface-inverted: light-dark(
272
- var(--cogenta-color-fg),
273
- oklch(from var(--cogenta-color-bg) 0.94 calc(c * 0.4) h)
228
+ oklch(from var(--cogenta-color-fg) 0.16 c h)
274
229
  );
275
- --cg-surface-inverted-fg: light-dark(
276
- var(--cogenta-color-bg),
277
- oklch(from var(--cogenta-color-fg) 0.14 calc(c * 0.5) h)
230
+ --cg-plate: light-dark(
231
+ var(--cogenta-color-muted),
232
+ oklch(from var(--cogenta-color-muted) 0.94 c h)
278
233
  );
279
234
 
280
- --cg-ink: light-dark(
281
- var(--cogenta-color-fg),
282
- oklch(from var(--cogenta-color-accent) 0.93 0.018 h)
283
- );
235
+ --cg-ink: light-dark(var(--cogenta-color-fg), oklch(from var(--cogenta-color-bg) 0.96 c h));
284
236
  --cg-ink-muted: light-dark(
285
237
  var(--cogenta-color-muted-fg),
286
- oklch(from var(--cogenta-color-accent) 0.76 0.024 h)
238
+ oklch(from var(--cogenta-color-muted) 0.78 c h)
287
239
  );
288
240
  --cg-ink-subtle: light-dark(
289
- color-mix(in oklab, var(--cogenta-color-muted-fg) 86%, var(--cogenta-color-bg)),
290
- oklch(from var(--cogenta-color-accent) 0.65 0.02 h)
291
- );
292
-
293
- --cg-accent: light-dark(
294
- var(--cogenta-color-accent),
295
- oklch(from var(--cogenta-color-accent) 0.78 calc(c * 1.05) h)
296
- );
297
- --cg-accent-fg: light-dark(
298
- var(--cogenta-color-accent-fg),
299
- oklch(from var(--cogenta-color-accent) 0.16 calc(c * 0.6) h)
241
+ color-mix(in oklab, var(--cogenta-color-muted-fg) 88%, var(--cogenta-color-bg)),
242
+ oklch(from var(--cogenta-color-muted) 0.7 c h)
300
243
  );
301
- --cg-accent-hover: light-dark(
302
- color-mix(in oklab, var(--cogenta-color-accent) 88%, var(--cogenta-color-fg)),
303
- oklch(from var(--cogenta-color-accent) 0.87 calc(c * 0.95) h)
304
- );
305
- --cg-accent-soft: light-dark(
306
- color-mix(in oklab, var(--cogenta-color-accent) 11%, var(--cogenta-color-bg)),
307
- oklch(from var(--cogenta-color-accent) 0.32 calc(c * 0.55) h)
244
+ --cg-plate-ink: light-dark(
245
+ var(--cogenta-color-fg),
246
+ oklch(from var(--cogenta-color-fg) 0.18 c h)
308
247
  );
309
- --cg-accent-soft-fg: light-dark(
310
- color-mix(in oklab, var(--cogenta-color-accent) 70%, var(--cogenta-color-fg)),
311
- oklch(from var(--cogenta-color-accent) 0.92 calc(c * 0.5) h)
248
+
249
+ --cg-signal: light-dark(var(--cogenta-color-accent), var(--cogenta-color-accent));
250
+ --cg-signal-fg: light-dark(var(--cogenta-color-accent-fg), var(--cogenta-color-accent-fg));
251
+
252
+ --cg-line: light-dark(var(--cogenta-color-border), oklch(from var(--cogenta-color-fg) 0.3 c h));
253
+ --cg-line-strong: light-dark(
254
+ color-mix(in oklab, var(--cogenta-color-border) 45%, var(--cogenta-color-fg)),
255
+ oklch(from var(--cogenta-color-fg) 0.52 c h)
312
256
  );
313
- --cg-line: light-dark(
314
- var(--cogenta-color-border),
315
- oklch(from var(--cogenta-color-accent) 0.4 calc(c * 0.24) h)
257
+ --cg-line-ink: light-dark(
258
+ var(--cogenta-color-fg),
259
+ oklch(from var(--cogenta-color-bg) 0.96 c h)
316
260
  );
317
- --cg-line-soft: light-dark(
318
- color-mix(in oklab, var(--cogenta-color-border) 55%, var(--cogenta-color-bg)),
319
- oklch(from var(--cogenta-color-accent) 0.3 calc(c * 0.22) h)
261
+
262
+ --cg-action: light-dark(var(--cogenta-color-fg), oklch(from var(--cogenta-color-bg) 0.96 c h));
263
+ --cg-action-fg: light-dark(var(--cogenta-color-bg), oklch(from var(--cogenta-color-fg) 0 0 h));
264
+ --cg-action-hover: light-dark(
265
+ color-mix(in oklab, var(--cogenta-color-fg) 78%, var(--cogenta-color-bg)),
266
+ oklch(from var(--cogenta-color-bg) 0.82 c h)
320
267
  );
321
- --cg-line-strong: light-dark(
322
- color-mix(in oklab, var(--cogenta-color-border) 60%, var(--cogenta-color-fg)),
323
- oklch(from var(--cogenta-color-accent) 0.62 calc(c * 0.28) h)
268
+ --cg-action-hover-fg: light-dark(
269
+ var(--cogenta-color-bg),
270
+ oklch(from var(--cogenta-color-fg) 0 0 h)
324
271
  );
325
272
  }
326
273
  }
327
274
 
328
- /* --------------------------------------------------------------------------
329
- Elevation — a hard, zero-blur offset shadow in both schemes (L25 D5,
330
- binding: "never glows"). Light reads it in the skin's own near-black
331
- `--cogenta-shadow-sm`/`-md`; dark cannot reuse those (a near-black shadow
332
- is invisible on a near-black surface), so it draws the *same* offset
333
- geometry in `--cg-line-strong` instead — the brighter-than-surface line
334
- colour this file already uses to do elevation's job in dark mode (see the
335
- colour system's own decision 5, above). Two literal card corners stacking
336
- behind one another, never a halo: this replaces what used to be an
337
- accent-tinted `blur()` glow, which is exactly the "100% AI" look the
338
- product owner ruled out.
339
- -------------------------------------------------------------------------- */
340
-
341
- :where(:root) {
342
- --cg-ring: inset 0 0 0 1px var(--cg-line);
343
- --cg-ring-accent: inset 0 0 0 1px var(--cg-accent);
344
-
345
- --cg-elevation-0: none;
346
- --cg-elevation-1: var(--cogenta-shadow-sm);
347
- --cg-elevation-2: var(--cogenta-shadow-md);
348
- --cg-elevation-3: var(--cogenta-shadow-md), var(--cg-ring);
349
- }
350
-
275
+ /* Work on black is dimmed a very little, so a white page in a picture does not
276
+ glare in a dark room. A brightness step, not a blur. */
351
277
  @media (prefers-color-scheme: dark) {
352
278
  :where(:root:not([data-theme="light"])) {
353
- --cg-elevation-1: var(--cg-ring), 0.125rem 0.125rem 0 var(--cg-line-strong);
354
- --cg-elevation-2: var(--cg-ring), 0.25rem 0.25rem 0 var(--cg-line-strong);
355
- --cg-elevation-3: var(--cg-ring), 0.4rem 0.4rem 0 var(--cg-line-strong);
279
+ --cg-image-brightness: 0.92;
356
280
  }
357
281
  }
358
282
 
359
283
  :where(:root[data-theme="dark"]) {
360
- --cg-elevation-1: var(--cg-ring), 0.125rem 0.125rem 0 var(--cg-line-strong);
361
- --cg-elevation-2: var(--cg-ring), 0.25rem 0.25rem 0 var(--cg-line-strong);
362
- --cg-elevation-3: var(--cg-ring), 0.4rem 0.4rem 0 var(--cg-line-strong);
284
+ --cg-image-brightness: 0.92;
363
285
  }