@cogenta/theme-entreprise 1.1.2

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 (117) hide show
  1. package/LICENSE +373 -0
  2. package/dist/src/index.d.ts +16 -0
  3. package/dist/src/index.d.ts.map +1 -0
  4. package/dist/src/index.js +16 -0
  5. package/dist/src/index.js.map +1 -0
  6. package/dist/src/render/blocks/accordion.d.ts +4 -0
  7. package/dist/src/render/blocks/accordion.d.ts.map +1 -0
  8. package/dist/src/render/blocks/accordion.js +24 -0
  9. package/dist/src/render/blocks/accordion.js.map +1 -0
  10. package/dist/src/render/blocks/collection-list.d.ts +14 -0
  11. package/dist/src/render/blocks/collection-list.d.ts.map +1 -0
  12. package/dist/src/render/blocks/collection-list.js +55 -0
  13. package/dist/src/render/blocks/collection-list.js.map +1 -0
  14. package/dist/src/render/blocks/cta.d.ts +12 -0
  15. package/dist/src/render/blocks/cta.d.ts.map +1 -0
  16. package/dist/src/render/blocks/cta.js +19 -0
  17. package/dist/src/render/blocks/cta.js.map +1 -0
  18. package/dist/src/render/blocks/embed.d.ts +4 -0
  19. package/dist/src/render/blocks/embed.d.ts.map +1 -0
  20. package/dist/src/render/blocks/embed.js +92 -0
  21. package/dist/src/render/blocks/embed.js.map +1 -0
  22. package/dist/src/render/blocks/faq.d.ts +4 -0
  23. package/dist/src/render/blocks/faq.d.ts.map +1 -0
  24. package/dist/src/render/blocks/faq.js +25 -0
  25. package/dist/src/render/blocks/faq.js.map +1 -0
  26. package/dist/src/render/blocks/feature-grid.d.ts +4 -0
  27. package/dist/src/render/blocks/feature-grid.d.ts.map +1 -0
  28. package/dist/src/render/blocks/feature-grid.js +33 -0
  29. package/dist/src/render/blocks/feature-grid.js.map +1 -0
  30. package/dist/src/render/blocks/gallery.d.ts +15 -0
  31. package/dist/src/render/blocks/gallery.d.ts.map +1 -0
  32. package/dist/src/render/blocks/gallery.js +28 -0
  33. package/dist/src/render/blocks/gallery.js.map +1 -0
  34. package/dist/src/render/blocks/hero.d.ts +15 -0
  35. package/dist/src/render/blocks/hero.d.ts.map +1 -0
  36. package/dist/src/render/blocks/hero.js +31 -0
  37. package/dist/src/render/blocks/hero.js.map +1 -0
  38. package/dist/src/render/blocks/logo-strip.d.ts +4 -0
  39. package/dist/src/render/blocks/logo-strip.d.ts.map +1 -0
  40. package/dist/src/render/blocks/logo-strip.js +21 -0
  41. package/dist/src/render/blocks/logo-strip.js.map +1 -0
  42. package/dist/src/render/blocks/logos.d.ts +4 -0
  43. package/dist/src/render/blocks/logos.d.ts.map +1 -0
  44. package/dist/src/render/blocks/logos.js +30 -0
  45. package/dist/src/render/blocks/logos.js.map +1 -0
  46. package/dist/src/render/blocks/media-figure.d.ts +13 -0
  47. package/dist/src/render/blocks/media-figure.d.ts.map +1 -0
  48. package/dist/src/render/blocks/media-figure.js +28 -0
  49. package/dist/src/render/blocks/media-figure.js.map +1 -0
  50. package/dist/src/render/blocks/pricing-table.d.ts +4 -0
  51. package/dist/src/render/blocks/pricing-table.d.ts.map +1 -0
  52. package/dist/src/render/blocks/pricing-table.js +33 -0
  53. package/dist/src/render/blocks/pricing-table.js.map +1 -0
  54. package/dist/src/render/blocks/prose.d.ts +9 -0
  55. package/dist/src/render/blocks/prose.d.ts.map +1 -0
  56. package/dist/src/render/blocks/prose.js +10 -0
  57. package/dist/src/render/blocks/prose.js.map +1 -0
  58. package/dist/src/render/blocks/quote.d.ts +18 -0
  59. package/dist/src/render/blocks/quote.d.ts.map +1 -0
  60. package/dist/src/render/blocks/quote.js +31 -0
  61. package/dist/src/render/blocks/quote.js.map +1 -0
  62. package/dist/src/render/blocks/stat-counter.d.ts +4 -0
  63. package/dist/src/render/blocks/stat-counter.d.ts.map +1 -0
  64. package/dist/src/render/blocks/stat-counter.js +23 -0
  65. package/dist/src/render/blocks/stat-counter.js.map +1 -0
  66. package/dist/src/render/blocks/stats.d.ts +4 -0
  67. package/dist/src/render/blocks/stats.d.ts.map +1 -0
  68. package/dist/src/render/blocks/stats.js +23 -0
  69. package/dist/src/render/blocks/stats.js.map +1 -0
  70. package/dist/src/render/blocks/testimonial.d.ts +16 -0
  71. package/dist/src/render/blocks/testimonial.d.ts.map +1 -0
  72. package/dist/src/render/blocks/testimonial.js +25 -0
  73. package/dist/src/render/blocks/testimonial.js.map +1 -0
  74. package/dist/src/render/chrome.d.ts +3 -0
  75. package/dist/src/render/chrome.d.ts.map +1 -0
  76. package/dist/src/render/chrome.js +101 -0
  77. package/dist/src/render/chrome.js.map +1 -0
  78. package/dist/src/render/render-block.d.ts +24 -0
  79. package/dist/src/render/render-block.d.ts.map +1 -0
  80. package/dist/src/render/render-block.js +108 -0
  81. package/dist/src/render/render-block.js.map +1 -0
  82. package/dist/src/render/term-archive.d.ts +12 -0
  83. package/dist/src/render/term-archive.d.ts.map +1 -0
  84. package/dist/src/render/term-archive.js +34 -0
  85. package/dist/src/render/term-archive.js.map +1 -0
  86. package/dist/theme.config.d.ts +16 -0
  87. package/dist/theme.config.d.ts.map +1 -0
  88. package/dist/theme.config.js +46 -0
  89. package/dist/theme.config.js.map +1 -0
  90. package/package.json +57 -0
  91. package/src/index.ts +15 -0
  92. package/src/render/blocks/accordion.ts +60 -0
  93. package/src/render/blocks/collection-list.ts +122 -0
  94. package/src/render/blocks/cta.ts +48 -0
  95. package/src/render/blocks/embed.ts +115 -0
  96. package/src/render/blocks/faq.ts +61 -0
  97. package/src/render/blocks/feature-grid.ts +73 -0
  98. package/src/render/blocks/gallery.ts +48 -0
  99. package/src/render/blocks/hero.ts +60 -0
  100. package/src/render/blocks/logo-strip.ts +36 -0
  101. package/src/render/blocks/logos.ts +60 -0
  102. package/src/render/blocks/media-figure.ts +43 -0
  103. package/src/render/blocks/pricing-table.ts +77 -0
  104. package/src/render/blocks/prose.ts +11 -0
  105. package/src/render/blocks/quote.ts +48 -0
  106. package/src/render/blocks/stat-counter.ts +45 -0
  107. package/src/render/blocks/stats.ts +50 -0
  108. package/src/render/blocks/testimonial.ts +41 -0
  109. package/src/render/chrome.ts +128 -0
  110. package/src/render/render-block.ts +144 -0
  111. package/src/render/term-archive.ts +80 -0
  112. package/src/styles/archive.css +68 -0
  113. package/src/styles/base.css +895 -0
  114. package/src/styles/blocks.css +1433 -0
  115. package/src/styles/theme.css +36 -0
  116. package/src/styles/tokens.css +326 -0
  117. package/tokens.json +36 -0
@@ -0,0 +1,895 @@
1
+ /*
2
+ * Document, accessibility floor, page frame, chrome (header/footer/nav) and
3
+ * the one control the theme ships (an action link). Everything here reads
4
+ * the design system from `tokens.css`; nothing here reads a `--cogenta-*`
5
+ * token directly.
6
+ */
7
+
8
+ /* --------------------------------------------------------------------------
9
+ Document
10
+ -------------------------------------------------------------------------- */
11
+
12
+ *,
13
+ *::before,
14
+ *::after {
15
+ box-sizing: border-box;
16
+ }
17
+
18
+ body {
19
+ margin: 0;
20
+ background: var(--cg-canvas);
21
+ color: var(--cg-ink);
22
+ font-family: var(--cogenta-font-sans);
23
+ font-size: var(--cg-text-md);
24
+ line-height: var(--cg-leading-normal);
25
+ font-kerning: normal;
26
+ font-variant-ligatures: common-ligatures;
27
+ text-underline-offset: 0.15em;
28
+ text-decoration-thickness: from-font;
29
+ -webkit-text-size-adjust: 100%;
30
+ }
31
+
32
+ ::selection {
33
+ background: var(--cg-accent-soft);
34
+ color: var(--cg-accent-soft-fg);
35
+ }
36
+
37
+ img,
38
+ video,
39
+ iframe {
40
+ max-width: 100%;
41
+ height: auto;
42
+ }
43
+
44
+ img {
45
+ display: block;
46
+ object-fit: cover;
47
+ }
48
+
49
+ :where(a) {
50
+ color: var(--cg-accent);
51
+ text-decoration-color: color-mix(in oklab, var(--cg-accent) 40%, transparent);
52
+ transition:
53
+ color var(--cg-duration-fast) var(--cg-ease),
54
+ text-decoration-color var(--cg-duration-fast) var(--cg-ease);
55
+ }
56
+
57
+ :where(a:hover) {
58
+ color: var(--cg-accent-hover);
59
+ text-decoration-color: currentColor;
60
+ }
61
+
62
+ :where(hr) {
63
+ block-size: 1px;
64
+ border: 0;
65
+ margin-block: var(--cg-s10);
66
+ background: var(--cg-line);
67
+ }
68
+
69
+ /* --------------------------------------------------------------------------
70
+ Focus, targets, motion
71
+ -------------------------------------------------------------------------- */
72
+
73
+ :where(a, button, summary, [tabindex]):focus-visible {
74
+ outline: 2px solid var(--cg-accent);
75
+ outline-offset: 3px;
76
+ border-radius: var(--cg-radius-xs);
77
+ }
78
+
79
+ :where(.cg-action, .cg-faq__question, .cg-clients__link, .cg-nav-toggle-label) {
80
+ min-block-size: 44px;
81
+ min-inline-size: 44px;
82
+ }
83
+
84
+ /* A restrained entrance: blocks settle upward a few pixels as they enter
85
+ the viewport, scroll-driven so it plays once per block rather than firing
86
+ for all of them on load. Wrapped in a feature query because the starting
87
+ state is `opacity: 0` — a browser without `animation-timeline` must never
88
+ be left holding an invisible page. */
89
+ @supports (animation-timeline: view()) {
90
+ @media (prefers-reduced-motion: no-preference) {
91
+ @keyframes cg-settle {
92
+ from {
93
+ opacity: 0;
94
+ transform: translateY(var(--cg-s3));
95
+ }
96
+
97
+ to {
98
+ opacity: 1;
99
+ transform: none;
100
+ }
101
+ }
102
+
103
+ .cg-block {
104
+ animation: cg-settle linear both;
105
+ animation-timeline: view();
106
+ animation-range: entry 0% cover 20%;
107
+ }
108
+ }
109
+ }
110
+
111
+ @media (prefers-reduced-motion: reduce) {
112
+ /* The `motion.reduced` token says the skin's motion may be removed.
113
+ Nothing here conveys meaning through movement, so removing all of it,
114
+ including the smooth scroll of a carousel, is safe. */
115
+ *,
116
+ *::before,
117
+ *::after {
118
+ animation-duration: 1ms !important;
119
+ animation-iteration-count: 1 !important;
120
+ transition-duration: 1ms !important;
121
+ scroll-behavior: auto !important;
122
+ }
123
+ }
124
+
125
+ .cg-skip-link {
126
+ position: absolute;
127
+ inset-inline-start: var(--cg-s3);
128
+ inset-block-start: calc(var(--cg-s3) * -8);
129
+ z-index: 10;
130
+ padding: var(--cg-s2) var(--cg-s4);
131
+ background: var(--cg-ink);
132
+ color: var(--cg-canvas);
133
+ border-radius: var(--cg-radius-sm);
134
+ font-weight: var(--cg-weight-semibold);
135
+ text-decoration: none;
136
+ transition: inset-block-start var(--cg-duration) var(--cg-ease);
137
+ }
138
+
139
+ .cg-skip-link:focus-visible {
140
+ inset-block-start: var(--cg-s3);
141
+ outline-color: var(--cg-canvas);
142
+ }
143
+
144
+ /* --------------------------------------------------------------------------
145
+ Page frame
146
+ -------------------------------------------------------------------------- */
147
+
148
+ .cg-main {
149
+ display: flow-root;
150
+ /* A hero's own decorative frame and any full-bleed band can end up a
151
+ fraction wider than the viewport on some zoom levels; `clip` — not
152
+ `hidden` — cuts that at the edge without turning `<main>` into a scroll
153
+ container, so a sticky header inside it keeps behaving normally. */
154
+ overflow-x: clip;
155
+ }
156
+
157
+ .cg-block {
158
+ max-inline-size: var(--cg-page);
159
+ margin-inline: auto;
160
+ margin-block: var(--cg-section-y);
161
+ padding-inline: var(--cg-gutter);
162
+ }
163
+
164
+ /* Every block is a page-width, gutter-padded section by default — `:where()`
165
+ keeps this at zero specificity so a block that sets its own narrower
166
+ measure (`.cg-quote`, `.cg-faq`, `.cg-prose`…) still wins, while a block
167
+ that never set one (`.cg-hero`, `.cg-services`) no longer sits flush
168
+ against the viewport edge on a wide screen. `data-variant-width="full"`
169
+ below opts a block back out. */
170
+ :where(.cg-main > [data-block]) {
171
+ max-inline-size: var(--cg-page);
172
+ margin-inline: auto;
173
+ padding-inline: var(--cg-gutter);
174
+ }
175
+
176
+ /* --- per-block visual variant (blocks@2.0, RFC 0002) ----------------------
177
+ `withBlockVariant` (`@cogenta/theme-kit`) stamps one `data-variant-<axis>`
178
+ attribute per axis an author actually set — never all four, never one this
179
+ theme does not resolve. Two attribute selectors give every rule here the
180
+ same specificity, (0,2,0), which is what lets it override `.cg-block`
181
+ above regardless of source order, without `!important` anywhere.
182
+
183
+ `background: 'image'` has no theme mechanism to attach an actual image to
184
+ a block instance (RFC 0002 adds only the semantic token, not a media
185
+ field) — resolved to the same tinted surface as the closest honest
186
+ approximation this theme has, rather than silently doing nothing with a
187
+ stated author intent.
188
+ ------------------------------------------------------------------------- */
189
+
190
+ [data-block][data-variant-background="muted"],
191
+ [data-block][data-variant-background="image"] {
192
+ padding-block: var(--cg-s10);
193
+ border-radius: var(--cg-radius-lg);
194
+ }
195
+
196
+ [data-block][data-variant-background="muted"] {
197
+ background: var(--cg-surface-sunken);
198
+ }
199
+
200
+ [data-block][data-variant-background="image"] {
201
+ background: var(--cg-surface-tinted);
202
+ }
203
+
204
+ [data-block][data-variant-spacing="compact"] {
205
+ margin-block: calc(var(--cg-section-y) / 2);
206
+ }
207
+
208
+ /* No rule for "comfortable": it names this theme's existing default, so an
209
+ author who picks it explicitly gets exactly what an absent `variant`
210
+ already gave them — the whole point of "theme default" being a real,
211
+ selectable option and not only the absence of a choice. */
212
+
213
+ [data-block][data-variant-spacing="spacious"] {
214
+ margin-block: calc(var(--cg-section-y) * 1.6);
215
+ }
216
+
217
+ [data-block][data-variant-align="start"] {
218
+ text-align: start;
219
+ }
220
+
221
+ [data-block][data-variant-align="center"] {
222
+ text-align: center;
223
+ }
224
+
225
+ [data-block][data-variant-align="end"] {
226
+ text-align: end;
227
+ }
228
+
229
+ [data-block][data-variant-width="full"] {
230
+ max-inline-size: none;
231
+ padding-inline: 0;
232
+ }
233
+
234
+ .cg-page__title {
235
+ max-inline-size: var(--cg-page);
236
+ margin-inline: auto;
237
+ margin-block: var(--cg-section-y) var(--cg-s6);
238
+ padding-inline: var(--cg-gutter);
239
+ font-size: var(--cg-text-3xl);
240
+ line-height: var(--cg-leading-tight);
241
+ letter-spacing: var(--cg-tracking-tight);
242
+ font-weight: var(--cg-weight-bold);
243
+ text-wrap: balance;
244
+ }
245
+
246
+ /* --------------------------------------------------------------------------
247
+ Chrome — header
248
+ -------------------------------------------------------------------------- */
249
+
250
+ .cg-site-header {
251
+ position: sticky;
252
+ inset-block-start: 0;
253
+ z-index: 5;
254
+ padding: var(--cg-s4) var(--cg-gutter);
255
+ /* Flat and fully opaque, not a frosted-glass blur: a plane above the
256
+ page, marked off by a hairline rather than a haze. */
257
+ background: var(--cg-canvas);
258
+ border-block-end: 1px solid var(--cg-line-soft);
259
+ }
260
+
261
+ .cg-site-header__inner {
262
+ display: flex;
263
+ flex-wrap: wrap;
264
+ align-items: center;
265
+ gap: var(--cg-gap);
266
+ max-inline-size: var(--cg-page);
267
+ margin-inline: auto;
268
+ }
269
+
270
+ .cg-site-header__home {
271
+ color: var(--cg-ink);
272
+ font-weight: var(--cg-weight-bold);
273
+ font-size: var(--cg-text-lg);
274
+ letter-spacing: var(--cg-tracking-tight);
275
+ text-decoration: none;
276
+ margin-inline-end: auto;
277
+ }
278
+
279
+ /* The uploaded corporate logo. Height-constrained so the header bar keeps a
280
+ constant height whatever aspect ratio the company's mark has. */
281
+ .cg-site-header__logo {
282
+ display: block;
283
+ block-size: 2rem;
284
+ inline-size: auto;
285
+ max-inline-size: 14rem;
286
+ object-fit: contain;
287
+ }
288
+
289
+ /* The mobile-menu checkbox: visually hidden the accessible way (still in
290
+ the tab order, still Space-operable) rather than `display: none` (which
291
+ would remove it from the tab order entirely) or `left: -9999px` (which
292
+ some assistive technology and "find in page" treat as content, not
293
+ chrome). */
294
+ .cg-nav-toggle-input {
295
+ position: absolute;
296
+ inline-size: 1px;
297
+ block-size: 1px;
298
+ overflow: hidden;
299
+ clip-path: inset(50%);
300
+ white-space: nowrap;
301
+ }
302
+
303
+ .cg-nav-toggle-label {
304
+ display: none;
305
+ flex-direction: column;
306
+ justify-content: center;
307
+ gap: 0.28rem;
308
+ inline-size: 2.5rem;
309
+ block-size: 2.5rem;
310
+ padding: 0.5rem;
311
+ margin-inline-start: auto;
312
+ border-radius: var(--cg-radius-sm);
313
+ cursor: pointer;
314
+ }
315
+
316
+ .cg-nav-toggle-input:focus-visible ~ .cg-nav-toggle-label {
317
+ outline: 2px solid var(--cg-accent);
318
+ outline-offset: 2px;
319
+ }
320
+
321
+ .cg-nav-toggle-bar {
322
+ display: block;
323
+ inline-size: 100%;
324
+ block-size: 2px;
325
+ background: var(--cg-ink);
326
+ transition: transform var(--cg-duration) var(--cg-ease);
327
+ }
328
+
329
+ .cg-site-header__nav {
330
+ display: flex;
331
+ align-items: center;
332
+ gap: var(--cg-s5);
333
+ }
334
+
335
+ .cg-nav__items {
336
+ display: flex;
337
+ flex-wrap: wrap;
338
+ align-items: center;
339
+ gap: var(--cg-s5);
340
+ margin: 0;
341
+ padding: 0;
342
+ list-style: none;
343
+ font-size: var(--cg-text-sm);
344
+ font-weight: var(--cg-weight-medium);
345
+ }
346
+
347
+ .cg-nav__items a,
348
+ .cg-nav__items span {
349
+ color: var(--cg-ink-muted);
350
+ text-decoration: none;
351
+ }
352
+
353
+ .cg-nav__items a:hover {
354
+ color: var(--cg-ink);
355
+ }
356
+
357
+ .cg-site-header__action {
358
+ flex: none;
359
+ }
360
+
361
+ /* The manual light/dark/system control (`renderThemeToggle`, `@cogenta/
362
+ theme-kit`, L26). Sits beside the mobile menu button in `renderChrome`,
363
+ outside the `<nav>` it does not control — a visitor must be able to flip
364
+ appearance without opening the collapsed mobile panel first. Sized and
365
+ squared off like `.cg-nav-toggle-label` right next to it (`--cg-radius-sm`,
366
+ this theme's structured register — never the pill canonical uses),
367
+ plain-bordered like `.cg-action[data-emphasis="secondary"]`'s own resting
368
+ state rather than filled, so it never competes with a real call to action. */
369
+ .cg-theme-toggle {
370
+ display: inline-flex;
371
+ align-items: center;
372
+ justify-content: center;
373
+ flex-shrink: 0;
374
+ inline-size: 2.5rem;
375
+ block-size: 2.5rem;
376
+ border: 1px solid var(--cg-line-soft);
377
+ border-radius: var(--cg-radius-sm);
378
+ background: transparent;
379
+ color: var(--cg-ink);
380
+ cursor: pointer;
381
+ transition: background-color var(--cg-duration) var(--cg-ease);
382
+ }
383
+
384
+ .cg-theme-toggle:hover {
385
+ background: var(--cg-surface-sunken);
386
+ }
387
+
388
+ .cg-theme-toggle:focus-visible {
389
+ outline: 2px solid var(--cg-accent);
390
+ outline-offset: 2px;
391
+ }
392
+
393
+ .cg-theme-toggle__icon {
394
+ inline-size: 1.1rem;
395
+ block-size: 1.1rem;
396
+ }
397
+
398
+ .cg-theme-toggle__icon--moon {
399
+ display: none;
400
+ }
401
+
402
+ /* Icon reflects the *current* effective appearance — sun while light, moon
403
+ while dark — from the same `[data-theme]`/`prefers-color-scheme` signals
404
+ `tokens.css` already keys the whole palette on. */
405
+ @media (prefers-color-scheme: dark) {
406
+ :where(:root:not([data-theme='light'])) .cg-theme-toggle__icon--sun {
407
+ display: none;
408
+ }
409
+ :where(:root:not([data-theme='light'])) .cg-theme-toggle__icon--moon {
410
+ display: block;
411
+ }
412
+ }
413
+
414
+ :where(:root[data-theme='dark']) .cg-theme-toggle__icon--sun {
415
+ display: none;
416
+ }
417
+
418
+ :where(:root[data-theme='dark']) .cg-theme-toggle__icon--moon {
419
+ display: block;
420
+ }
421
+
422
+ /* Below the breakpoint: the toggle button appears, and the nav becomes a
423
+ panel anchored under the header, shown only while the checkbox is
424
+ checked — the whole mechanism is this one selector, no JavaScript. */
425
+ @media (max-width: 56rem) {
426
+ .cg-site-header__inner {
427
+ position: relative;
428
+ }
429
+
430
+ .cg-nav-toggle-label {
431
+ display: flex;
432
+ }
433
+
434
+ .cg-site-header__nav {
435
+ display: none;
436
+ position: absolute;
437
+ inset-inline: 0;
438
+ inset-block-start: 100%;
439
+ flex-direction: column;
440
+ align-items: stretch;
441
+ gap: var(--cg-s5);
442
+ padding: var(--cg-s6) var(--cg-gutter);
443
+ background: var(--cg-canvas);
444
+ border-block-end: 1px solid var(--cg-line-soft);
445
+ box-shadow: var(--cogenta-shadow-md);
446
+ }
447
+
448
+ .cg-nav-toggle-input:checked ~ .cg-site-header__nav {
449
+ display: flex;
450
+ }
451
+
452
+ .cg-nav-toggle-input:checked ~ .cg-nav-toggle-label .cg-nav-toggle-bar:nth-child(1) {
453
+ transform: translateY(0.42rem) rotate(45deg);
454
+ }
455
+
456
+ .cg-nav-toggle-input:checked ~ .cg-nav-toggle-label .cg-nav-toggle-bar:nth-child(2) {
457
+ opacity: 0;
458
+ }
459
+
460
+ .cg-nav-toggle-input:checked ~ .cg-nav-toggle-label .cg-nav-toggle-bar:nth-child(3) {
461
+ transform: translateY(-0.42rem) rotate(-45deg);
462
+ }
463
+
464
+ .cg-site-header__nav .cg-nav__items {
465
+ flex-direction: column;
466
+ align-items: flex-start;
467
+ gap: var(--cg-s4);
468
+ }
469
+
470
+ .cg-site-header__action {
471
+ align-self: flex-start;
472
+ }
473
+ }
474
+
475
+ /* --------------------------------------------------------------------------
476
+ Chrome — footer, a real four-column layout
477
+ -------------------------------------------------------------------------- */
478
+
479
+ .cg-site-footer {
480
+ padding: var(--cg-s16) var(--cg-gutter) var(--cg-s8);
481
+ background: var(--cg-surface-sunken);
482
+ color: var(--cg-ink-muted);
483
+ border-block-start: 1px solid var(--cg-line-soft);
484
+ font-size: var(--cg-text-sm);
485
+ }
486
+
487
+ .cg-site-footer__grid {
488
+ display: grid;
489
+ gap: var(--cg-gap-loose);
490
+ grid-template-columns: 1fr;
491
+ max-inline-size: var(--cg-page);
492
+ margin-inline: auto;
493
+ padding-block-end: var(--cg-s10);
494
+ border-block-end: 1px solid var(--cg-line-soft);
495
+ }
496
+
497
+ @media (min-width: 56rem) {
498
+ .cg-site-footer__grid {
499
+ grid-template-columns: 1.3fr 1fr 0.8fr 1fr;
500
+ align-items: start;
501
+ }
502
+ }
503
+
504
+ .cg-site-footer__brand a {
505
+ color: var(--cg-ink);
506
+ font-weight: var(--cg-weight-bold);
507
+ font-size: var(--cg-text-lg);
508
+ letter-spacing: var(--cg-tracking-tight);
509
+ text-decoration: none;
510
+ }
511
+
512
+ .cg-site-footer__tagline {
513
+ margin: var(--cg-s3) 0 0;
514
+ max-inline-size: 24ch;
515
+ color: var(--cg-ink-muted);
516
+ line-height: var(--cg-leading-relaxed);
517
+ }
518
+
519
+ .cg-site-footer__nav .cg-nav__items {
520
+ flex-direction: column;
521
+ align-items: flex-start;
522
+ gap: var(--cg-s3);
523
+ }
524
+
525
+ .cg-site-footer__social {
526
+ display: flex;
527
+ gap: var(--cg-s3);
528
+ margin: 0;
529
+ padding: 0;
530
+ list-style: none;
531
+ }
532
+
533
+ .cg-site-footer__social-item a {
534
+ display: inline-flex;
535
+ align-items: center;
536
+ justify-content: center;
537
+ inline-size: 2.25rem;
538
+ block-size: 2.25rem;
539
+ border: 1px solid var(--cg-line);
540
+ border-radius: var(--cg-radius-sm);
541
+ color: var(--cg-ink-muted);
542
+ transition:
543
+ color var(--cg-duration) var(--cg-ease),
544
+ border-color var(--cg-duration) var(--cg-ease);
545
+ }
546
+
547
+ .cg-site-footer__social-item a:hover {
548
+ color: var(--cg-accent);
549
+ border-color: var(--cg-accent);
550
+ }
551
+
552
+ .cg-social__icon {
553
+ inline-size: 1.1rem;
554
+ block-size: 1.1rem;
555
+ }
556
+
557
+ .cg-site-footer__note {
558
+ margin: 0 0 var(--cg-s4);
559
+ color: var(--cg-ink-muted);
560
+ line-height: var(--cg-leading-normal);
561
+ }
562
+
563
+ .cg-site-footer__meta,
564
+ .cg-site-footer__branding {
565
+ display: flex;
566
+ flex-direction: column;
567
+ align-items: flex-start;
568
+ justify-content: flex-start;
569
+ }
570
+
571
+ @media (min-width: 56rem) {
572
+ .cg-site-footer__meta {
573
+ align-items: flex-end;
574
+ text-align: end;
575
+ }
576
+ }
577
+
578
+ .cg-site-footer__branding a {
579
+ display: flex;
580
+ align-items: center;
581
+ gap: 0.4em;
582
+ opacity: 0.75;
583
+ transition: opacity var(--cg-duration) var(--cg-ease);
584
+ }
585
+
586
+ .cg-site-footer__branding a:hover,
587
+ .cg-site-footer__branding a:focus-visible {
588
+ opacity: 1;
589
+ }
590
+
591
+ .cg-site-footer__brand-logo {
592
+ display: block;
593
+ /* Explicit pixels, not `em`: relative sizing cascaded from the footer's
594
+ own small font-size and made the credit mark unreadably tiny. */
595
+ block-size: 25px;
596
+ inline-size: auto;
597
+ }
598
+
599
+ .cg-site-footer__version {
600
+ font-variant-numeric: tabular-nums;
601
+ font-size: 0.9em;
602
+ }
603
+
604
+ .cg-site-footer__bottom {
605
+ max-inline-size: var(--cg-page);
606
+ margin-inline: auto;
607
+ padding-block-start: var(--cg-s6);
608
+ font-size: var(--cg-text-xs);
609
+ letter-spacing: var(--cg-tracking-wide);
610
+ text-transform: uppercase;
611
+ color: var(--cg-ink-subtle);
612
+ }
613
+
614
+ /* --------------------------------------------------------------------------
615
+ Actions — the theme's only control
616
+ -------------------------------------------------------------------------- */
617
+
618
+ .cg-actions {
619
+ display: flex;
620
+ flex-wrap: wrap;
621
+ gap: var(--cg-s3);
622
+ margin: var(--cg-s8) 0 0;
623
+ padding: 0;
624
+ list-style: none;
625
+ }
626
+
627
+ .cg-action {
628
+ display: inline-flex;
629
+ align-items: center;
630
+ justify-content: center;
631
+ gap: var(--cg-s2);
632
+ padding: var(--cg-s3) var(--cg-s6);
633
+ border: 0;
634
+ border-radius: var(--cg-radius-sm);
635
+ font-size: var(--cg-text-sm);
636
+ font-weight: var(--cg-weight-semibold);
637
+ letter-spacing: var(--cg-tracking-snug);
638
+ line-height: var(--cg-leading-snug);
639
+ text-decoration: none;
640
+ white-space: nowrap;
641
+ transition:
642
+ background-color var(--cg-duration) var(--cg-ease),
643
+ color var(--cg-duration) var(--cg-ease),
644
+ box-shadow var(--cg-duration) var(--cg-ease),
645
+ transform var(--cg-duration-fast) var(--cg-ease);
646
+ }
647
+
648
+ .cg-action[data-emphasis="primary"] {
649
+ background: var(--cg-accent);
650
+ color: var(--cg-accent-fg);
651
+ }
652
+
653
+ .cg-action[data-emphasis="primary"]:hover {
654
+ background: var(--cg-accent-hover);
655
+ box-shadow: var(--cogenta-shadow-sm);
656
+ transform: translateY(-1px);
657
+ }
658
+
659
+ .cg-action[data-emphasis="secondary"] {
660
+ background: transparent;
661
+ color: var(--cg-ink);
662
+ box-shadow: var(--cg-ring-strong);
663
+ }
664
+
665
+ .cg-action[data-emphasis="secondary"]:hover {
666
+ color: var(--cg-accent);
667
+ box-shadow: var(--cg-ring-accent);
668
+ }
669
+
670
+ .cg-action:active {
671
+ transform: translateY(0);
672
+ box-shadow: none;
673
+ }
674
+
675
+ /* --------------------------------------------------------------------------
676
+ Shared block furniture
677
+ -------------------------------------------------------------------------- */
678
+
679
+ .cg-services__title,
680
+ .cg-banner__title,
681
+ .cg-faq__title,
682
+ .cg-metrics__title,
683
+ .cg-clients__title,
684
+ .cg-list__title-heading {
685
+ margin: 0 0 var(--cg-s10);
686
+ font-size: var(--cg-text-xl);
687
+ line-height: var(--cg-leading-snug);
688
+ letter-spacing: var(--cg-tracking-tight);
689
+ font-weight: var(--cg-weight-bold);
690
+ text-wrap: balance;
691
+ }
692
+
693
+ .cg-services__items,
694
+ .cg-clients__items,
695
+ .cg-gallery__items,
696
+ .cg-list__items,
697
+ .cg-faq__items {
698
+ margin: 0;
699
+ padding: 0;
700
+ list-style: none;
701
+ }
702
+
703
+ .cg-gallery__viewport,
704
+ .cg-list__viewport {
705
+ overflow-x: auto;
706
+ scroll-snap-type: x mandatory;
707
+ scroll-behavior: smooth;
708
+ overscroll-behavior-inline: contain;
709
+ scrollbar-width: thin;
710
+ scrollbar-color: var(--cg-line-strong) transparent;
711
+ padding-block: var(--cg-s2);
712
+ margin-block: calc(var(--cg-s2) * -1);
713
+ }
714
+
715
+ /* --------------------------------------------------------------------------
716
+ Search, forms, comments — public utility pages and post-content furniture,
717
+ styled with the same restrained, structured language as the seventeen blocks.
718
+ -------------------------------------------------------------------------- */
719
+
720
+ .cg-search__form,
721
+ .cg-search__results,
722
+ .cg-search__empty,
723
+ .cg-search__error,
724
+ .cg-form,
725
+ .cg-form__confirmation,
726
+ .cg-comments {
727
+ max-inline-size: var(--cg-page);
728
+ margin-inline: auto;
729
+ padding-inline: var(--cg-gutter);
730
+ }
731
+
732
+ .cg-search__form {
733
+ display: flex;
734
+ flex-wrap: wrap;
735
+ align-items: end;
736
+ gap: var(--cg-s3);
737
+ margin-block-end: var(--cg-s8);
738
+ }
739
+
740
+ .cg-search__form label {
741
+ display: block;
742
+ font-size: var(--cg-text-sm);
743
+ font-weight: var(--cg-weight-semibold);
744
+ margin-block-end: var(--cg-s2);
745
+ }
746
+
747
+ .cg-search__form input[type="search"] {
748
+ flex: 1 1 16rem;
749
+ }
750
+
751
+ .cg-search__results {
752
+ margin: 0 auto;
753
+ padding-inline-start: var(--cg-gutter);
754
+ display: grid;
755
+ gap: var(--cg-s4);
756
+ font-size: var(--cg-text-lg);
757
+ }
758
+
759
+ .cg-search__empty,
760
+ .cg-comments__empty,
761
+ .cg-comments__closed {
762
+ color: var(--cg-ink-muted);
763
+ }
764
+
765
+ .cg-search__error,
766
+ .cg-form__error,
767
+ .cg-form__field-error {
768
+ color: var(--cg-ink);
769
+ font-weight: var(--cg-weight-bold);
770
+ }
771
+
772
+ .cg-search__form input,
773
+ .cg-form__field input,
774
+ .cg-form__field select,
775
+ .cg-form__field textarea,
776
+ .cg-comment__form input,
777
+ .cg-comment__form textarea {
778
+ inline-size: 100%;
779
+ padding: var(--cg-s3) var(--cg-s4);
780
+ border: 1px solid var(--cg-line);
781
+ border-radius: var(--cg-radius-sm);
782
+ background: var(--cg-surface);
783
+ color: var(--cg-ink);
784
+ font: inherit;
785
+ }
786
+
787
+ .cg-form__field input[aria-invalid="true"],
788
+ .cg-form__field select[aria-invalid="true"],
789
+ .cg-form__field textarea[aria-invalid="true"] {
790
+ border-width: 2px;
791
+ border-color: var(--cg-line-strong);
792
+ }
793
+
794
+ .cg-search__form button,
795
+ .cg-form button[type="submit"],
796
+ .cg-comment__form button[type="submit"] {
797
+ padding: var(--cg-s3) var(--cg-s6);
798
+ border: 0;
799
+ border-radius: var(--cg-radius-sm);
800
+ background: var(--cg-accent);
801
+ color: var(--cg-accent-fg);
802
+ font-weight: var(--cg-weight-semibold);
803
+ cursor: pointer;
804
+ transition: background-color var(--cg-duration) var(--cg-ease);
805
+ }
806
+
807
+ .cg-search__form button:hover,
808
+ .cg-form button[type="submit"]:hover,
809
+ .cg-comment__form button[type="submit"]:hover {
810
+ background: var(--cg-accent-hover);
811
+ }
812
+
813
+ .cg-form__field,
814
+ .cg-comment__form p {
815
+ display: block;
816
+ margin-block-end: var(--cg-s5);
817
+ }
818
+
819
+ .cg-form__field label,
820
+ .cg-comment__form label {
821
+ display: block;
822
+ font-size: var(--cg-text-sm);
823
+ font-weight: var(--cg-weight-semibold);
824
+ margin-block-end: var(--cg-s2);
825
+ }
826
+
827
+ .cg-form__help {
828
+ margin: var(--cg-s2) 0 0;
829
+ font-size: var(--cg-text-sm);
830
+ color: var(--cg-ink-muted);
831
+ }
832
+
833
+ .cg-form__choice {
834
+ display: inline-flex;
835
+ align-items: center;
836
+ gap: var(--cg-s2);
837
+ margin-inline-end: var(--cg-s4);
838
+ font-weight: normal;
839
+ }
840
+
841
+ .cg-form__honeypot,
842
+ .cg-comment__honeypot {
843
+ position: absolute;
844
+ inline-size: 1px;
845
+ block-size: 1px;
846
+ overflow: hidden;
847
+ inset-inline-start: -9999px;
848
+ }
849
+
850
+ .cg-comments {
851
+ margin-block-start: var(--cg-section-y);
852
+ padding-block-start: var(--cg-s8);
853
+ padding-block-end: var(--cg-section-y);
854
+ border-block-start: 1px solid var(--cg-line-soft);
855
+ }
856
+
857
+ .cg-comments__list,
858
+ .cg-comment__replies {
859
+ margin: 0;
860
+ padding: 0;
861
+ list-style: none;
862
+ }
863
+
864
+ .cg-comment {
865
+ padding-block: var(--cg-s5);
866
+ border-block-end: 1px solid var(--cg-line-soft);
867
+ }
868
+
869
+ .cg-comment__replies {
870
+ padding-block-start: var(--cg-s5);
871
+ }
872
+
873
+ .cg-comment__replies .cg-comment {
874
+ padding-inline-start: var(--cg-s6);
875
+ border-inline-start: 2px solid var(--cg-line-soft);
876
+ border-block-end: 0;
877
+ }
878
+
879
+ .cg-comment__meta {
880
+ display: flex;
881
+ gap: var(--cg-s3);
882
+ align-items: baseline;
883
+ font-size: var(--cg-text-sm);
884
+ color: var(--cg-ink-muted);
885
+ margin-block-end: var(--cg-s2);
886
+ }
887
+
888
+ .cg-comment__author {
889
+ font-weight: var(--cg-weight-semibold);
890
+ color: var(--cg-ink);
891
+ }
892
+
893
+ .cg-comment__body {
894
+ margin: 0;
895
+ }