@cogenta/theme-magazine 1.1.3 → 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 (126) hide show
  1. package/dist/src/index.d.ts +3 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +3 -0
  4. package/dist/src/index.js.map +1 -1
  5. package/dist/src/render/article.d.ts +32 -0
  6. package/dist/src/render/article.d.ts.map +1 -0
  7. package/dist/src/render/article.js +137 -0
  8. package/dist/src/render/article.js.map +1 -0
  9. package/dist/src/render/blocks/accordion.d.ts.map +1 -1
  10. package/dist/src/render/blocks/accordion.js +9 -13
  11. package/dist/src/render/blocks/accordion.js.map +1 -1
  12. package/dist/src/render/blocks/collection-list.d.ts.map +1 -1
  13. package/dist/src/render/blocks/collection-list.js +91 -118
  14. package/dist/src/render/blocks/collection-list.js.map +1 -1
  15. package/dist/src/render/blocks/cta.d.ts +4 -4
  16. package/dist/src/render/blocks/cta.d.ts.map +1 -1
  17. package/dist/src/render/blocks/cta.js +7 -9
  18. package/dist/src/render/blocks/cta.js.map +1 -1
  19. package/dist/src/render/blocks/embed.d.ts.map +1 -1
  20. package/dist/src/render/blocks/embed.js +17 -20
  21. package/dist/src/render/blocks/embed.js.map +1 -1
  22. package/dist/src/render/blocks/faq.d.ts.map +1 -1
  23. package/dist/src/render/blocks/faq.js +12 -11
  24. package/dist/src/render/blocks/faq.js.map +1 -1
  25. package/dist/src/render/blocks/feature-grid.d.ts.map +1 -1
  26. package/dist/src/render/blocks/feature-grid.js +13 -20
  27. package/dist/src/render/blocks/feature-grid.js.map +1 -1
  28. package/dist/src/render/blocks/gallery.d.ts +6 -6
  29. package/dist/src/render/blocks/gallery.d.ts.map +1 -1
  30. package/dist/src/render/blocks/gallery.js +15 -13
  31. package/dist/src/render/blocks/gallery.js.map +1 -1
  32. package/dist/src/render/blocks/hero.d.ts +6 -5
  33. package/dist/src/render/blocks/hero.d.ts.map +1 -1
  34. package/dist/src/render/blocks/hero.js +15 -14
  35. package/dist/src/render/blocks/hero.js.map +1 -1
  36. package/dist/src/render/blocks/logo-strip.d.ts.map +1 -1
  37. package/dist/src/render/blocks/logo-strip.js +8 -11
  38. package/dist/src/render/blocks/logo-strip.js.map +1 -1
  39. package/dist/src/render/blocks/logos.d.ts.map +1 -1
  40. package/dist/src/render/blocks/logos.js +16 -16
  41. package/dist/src/render/blocks/logos.js.map +1 -1
  42. package/dist/src/render/blocks/media-figure.d.ts +8 -8
  43. package/dist/src/render/blocks/media-figure.d.ts.map +1 -1
  44. package/dist/src/render/blocks/media-figure.js +23 -19
  45. package/dist/src/render/blocks/media-figure.js.map +1 -1
  46. package/dist/src/render/blocks/pricing-table.d.ts.map +1 -1
  47. package/dist/src/render/blocks/pricing-table.js +19 -22
  48. package/dist/src/render/blocks/pricing-table.js.map +1 -1
  49. package/dist/src/render/blocks/prose.d.ts +6 -10
  50. package/dist/src/render/blocks/prose.d.ts.map +1 -1
  51. package/dist/src/render/blocks/prose.js +8 -11
  52. package/dist/src/render/blocks/prose.js.map +1 -1
  53. package/dist/src/render/blocks/quote.d.ts +6 -9
  54. package/dist/src/render/blocks/quote.d.ts.map +1 -1
  55. package/dist/src/render/blocks/quote.js +11 -13
  56. package/dist/src/render/blocks/quote.js.map +1 -1
  57. package/dist/src/render/blocks/stat-counter.d.ts.map +1 -1
  58. package/dist/src/render/blocks/stat-counter.js +9 -10
  59. package/dist/src/render/blocks/stat-counter.js.map +1 -1
  60. package/dist/src/render/blocks/stats.d.ts.map +1 -1
  61. package/dist/src/render/blocks/stats.js +9 -12
  62. package/dist/src/render/blocks/stats.js.map +1 -1
  63. package/dist/src/render/blocks/testimonial.d.ts +4 -13
  64. package/dist/src/render/blocks/testimonial.d.ts.map +1 -1
  65. package/dist/src/render/blocks/testimonial.js +7 -15
  66. package/dist/src/render/blocks/testimonial.js.map +1 -1
  67. package/dist/src/render/chrome.d.ts.map +1 -1
  68. package/dist/src/render/chrome.js +109 -97
  69. package/dist/src/render/chrome.js.map +1 -1
  70. package/dist/src/render/layout.d.ts +28 -0
  71. package/dist/src/render/layout.d.ts.map +1 -0
  72. package/dist/src/render/layout.js +72 -0
  73. package/dist/src/render/layout.js.map +1 -0
  74. package/dist/src/render/render-block.d.ts +15 -13
  75. package/dist/src/render/render-block.d.ts.map +1 -1
  76. package/dist/src/render/render-block.js +53 -29
  77. package/dist/src/render/render-block.js.map +1 -1
  78. package/dist/src/render/story.d.ts +41 -0
  79. package/dist/src/render/story.d.ts.map +1 -0
  80. package/dist/src/render/story.js +65 -0
  81. package/dist/src/render/story.js.map +1 -0
  82. package/dist/src/render/term-archive.d.ts +0 -10
  83. package/dist/src/render/term-archive.d.ts.map +1 -1
  84. package/dist/src/render/term-archive.js +42 -19
  85. package/dist/src/render/term-archive.js.map +1 -1
  86. package/dist/src/render/widget-areas.d.ts +12 -0
  87. package/dist/src/render/widget-areas.d.ts.map +1 -0
  88. package/dist/src/render/widget-areas.js +19 -0
  89. package/dist/src/render/widget-areas.js.map +1 -0
  90. package/dist/theme.config.js +2 -2
  91. package/dist/theme.config.js.map +1 -1
  92. package/package.json +5 -5
  93. package/src/index.ts +3 -0
  94. package/src/render/article.ts +239 -0
  95. package/src/render/blocks/accordion.ts +23 -30
  96. package/src/render/blocks/collection-list.ts +161 -225
  97. package/src/render/blocks/cta.ts +19 -13
  98. package/src/render/blocks/embed.ts +40 -36
  99. package/src/render/blocks/faq.ts +31 -36
  100. package/src/render/blocks/feature-grid.ts +26 -36
  101. package/src/render/blocks/gallery.ts +24 -18
  102. package/src/render/blocks/hero.ts +32 -32
  103. package/src/render/blocks/logo-strip.ts +17 -17
  104. package/src/render/blocks/logos.ts +23 -31
  105. package/src/render/blocks/media-figure.ts +36 -20
  106. package/src/render/blocks/pricing-table.ts +29 -34
  107. package/src/render/blocks/prose.ts +13 -13
  108. package/src/render/blocks/quote.ts +24 -24
  109. package/src/render/blocks/stat-counter.ts +16 -24
  110. package/src/render/blocks/stats.ts +14 -24
  111. package/src/render/blocks/testimonial.ts +12 -17
  112. package/src/render/chrome.ts +123 -104
  113. package/src/render/layout.ts +105 -0
  114. package/src/render/render-block.ts +61 -33
  115. package/src/render/story.ts +139 -0
  116. package/src/render/term-archive.ts +111 -58
  117. package/src/render/widget-areas.ts +22 -0
  118. package/src/styles/archive.css +114 -17
  119. package/src/styles/article.css +237 -0
  120. package/src/styles/base.css +848 -591
  121. package/src/styles/blocks.css +903 -921
  122. package/src/styles/stories.css +593 -0
  123. package/src/styles/theme.css +28 -9
  124. package/src/styles/tokens.css +200 -185
  125. package/src/styles/widgets.css +614 -0
  126. package/tokens.json +18 -18
@@ -0,0 +1,139 @@
1
+ import {
2
+ type ContentEntry,
3
+ entryDate,
4
+ entryExcerpt,
5
+ entryHref,
6
+ entryImage,
7
+ entryTitle,
8
+ type HeadingTag,
9
+ type HtmlElement,
10
+ h,
11
+ heading,
12
+ type ImageSource,
13
+ type RenderContext,
14
+ renderImageSource,
15
+ type TermArchiveEntry,
16
+ } from '@cogenta/theme-kit'
17
+ import { entryKicker, shortDate } from './layout.js'
18
+
19
+ /**
20
+ * One story as a listing sets it: a kicker, a headline, a standfirst, a date
21
+ * and, where the slot allows, a photograph. The front page, the rails, the
22
+ * opinion strip, the ranked list and the section front all build their rows
23
+ * from this one unit, so a kicker or a headline reads the same wherever the
24
+ * reader meets it. Which parts show, and at what size, is the slot's choice
25
+ * (`StoryOptions`) and the stylesheet's.
26
+ *
27
+ * The headline is the one link. The photograph links to the same place but
28
+ * is taken out of the tab order and hidden from assistive technology, so a
29
+ * keyboard or screen-reader user meets each story once.
30
+ */
31
+
32
+ export interface Story {
33
+ readonly href: string | null
34
+ readonly title: string
35
+ readonly kicker?: string
36
+ readonly standfirst?: string
37
+ readonly date?: { readonly iso: string; readonly label: string }
38
+ readonly image?: ImageSource
39
+ }
40
+
41
+ export interface StoryOptions {
42
+ readonly tag: HeadingTag
43
+ /** A modifier, `cg-story--<variant>`: `lead`, `brief`, `secondary`, `rail`, `column`, `ranked`. */
44
+ readonly variant: string
45
+ readonly image?: boolean
46
+ readonly standfirst?: boolean
47
+ readonly date?: boolean
48
+ readonly sizes?: string
49
+ readonly loading?: 'eager' | 'lazy'
50
+ readonly numeral?: string
51
+ }
52
+
53
+ /** A `ContentEntry` as a story: every field read through the shared entry helpers, never assumed. */
54
+ export function storyFromEntry(entry: ContentEntry, ctx: RenderContext, imageWidth: number): Story {
55
+ const iso = entryDate(entry)
56
+ const label = iso === undefined ? null : shortDate(iso, ctx.locale)
57
+ const kicker = entryKicker(entry)
58
+ const standfirst = entryExcerpt(entry)
59
+ const image = entryImage(entry, ctx, {
60
+ width: imageWidth,
61
+ height: Math.round((imageWidth * 2) / 3),
62
+ fit: 'cover',
63
+ })
64
+ return {
65
+ href: entryHref(entry, ctx),
66
+ title: entryTitle(entry, ctx),
67
+ ...(kicker === undefined ? {} : { kicker }),
68
+ ...(standfirst === undefined ? {} : { standfirst }),
69
+ ...(iso === undefined || label === null ? {} : { date: { iso, label } }),
70
+ ...(image === undefined || image.kind !== 'image' ? {} : { image }),
71
+ }
72
+ }
73
+
74
+ /** A term archive row as a story. `TermArchiveEntry` carries no picture and no kicker, so neither is invented. */
75
+ export function storyFromArchive(entry: TermArchiveEntry, locale: string): Story {
76
+ const label = entry.publishedAt === null ? null : shortDate(entry.publishedAt, locale)
77
+ return {
78
+ href: entry.href,
79
+ title: entry.title,
80
+ ...(entry.summary === null ? {} : { standfirst: entry.summary }),
81
+ ...(entry.publishedAt === null || label === null
82
+ ? {}
83
+ : { date: { iso: entry.publishedAt, label } }),
84
+ }
85
+ }
86
+
87
+ export function renderStory(story: Story, options: StoryOptions): HtmlElement {
88
+ const imageOptions = {
89
+ className: 'cg-story__image',
90
+ ...(options.sizes === undefined ? {} : { sizes: options.sizes }),
91
+ ...(options.loading === undefined ? {} : { loading: options.loading }),
92
+ }
93
+ const showImage = options.image === true && story.image !== undefined
94
+ const titleNode =
95
+ story.href === null
96
+ ? story.title
97
+ : h('a', { class: 'cg-story__link', href: story.href }, story.title)
98
+
99
+ return h(
100
+ 'article',
101
+ {
102
+ class: `cg-story cg-story--${options.variant}`,
103
+ 'data-media': showImage ? 'image' : 'none',
104
+ },
105
+ showImage && story.image !== undefined
106
+ ? story.href === null
107
+ ? h('div', { class: 'cg-story__media' }, renderImageSource(story.image, imageOptions))
108
+ : h(
109
+ 'a',
110
+ {
111
+ class: 'cg-story__media',
112
+ href: story.href,
113
+ tabindex: '-1',
114
+ 'aria-hidden': 'true',
115
+ },
116
+ renderImageSource(story.image, imageOptions),
117
+ )
118
+ : null,
119
+ h(
120
+ 'div',
121
+ { class: 'cg-story__body' },
122
+ options.numeral === undefined
123
+ ? null
124
+ : h('span', { class: 'cg-story__numeral', 'aria-hidden': 'true' }, options.numeral),
125
+ story.kicker === undefined ? null : h('p', { class: 'cg-story__kicker' }, story.kicker),
126
+ heading(options.tag, { class: 'cg-story__title' }, titleNode),
127
+ options.standfirst === true && story.standfirst !== undefined
128
+ ? h('p', { class: 'cg-story__standfirst' }, story.standfirst)
129
+ : null,
130
+ options.date === true && story.date !== undefined
131
+ ? h(
132
+ 'p',
133
+ { class: 'cg-story__meta' },
134
+ h('time', { datetime: story.date.iso }, story.date.label),
135
+ )
136
+ : null,
137
+ ),
138
+ )
139
+ }
@@ -1,75 +1,120 @@
1
1
  import { type HtmlElement, h, type TermArchiveInput } from '@cogenta/theme-kit'
2
+ import { renderStory, storyFromArchive } from './story.js'
2
3
 
3
4
  /**
4
- * The taxonomy-term archive (contract D `theme@1.3`), as a section front.
5
+ * The taxonomy-term archive (contract D `theme@1.3`), set as a section front.
5
6
  *
6
- * A magazine's archive is a section page, so it is built from the same
7
- * `cg-issue__row` rows `collectionList` already sets here — a contents strip,
8
- * not a card grid — under a section head that names the taxonomy as a kicker
9
- * and the term as the section title. Reusing the block's classes is what
10
- * keeps the two looking like the same publication without a second
11
- * stylesheet.
7
+ * The term is the page's title, very large on a double rule, under the
8
+ * taxonomy's name as a kicker. Its stories follow the front page's own
9
+ * composition: the newest as the lead across eight columns, the next three
10
+ * as briefs behind a vertical rule, and the rest in a row of three divided by
11
+ * hairlines. `TermArchiveEntry` carries no picture and no kicker, so a
12
+ * section front is set entirely in type, which is how a newspaper's inside
13
+ * section pages read anyway.
14
+ *
15
+ * Every visible word that is not content comes from `input.labels`, already
16
+ * in the page's language.
12
17
  */
18
+ const BRIEFS = 3
19
+
13
20
  export function renderTermArchive(input: TermArchiveInput): HtmlElement {
14
- const rows = input.entries.map((entry, index) =>
21
+ const stories = input.entries.map((entry) => storyFromArchive(entry, input.locale))
22
+ const [lead, ...others] = stories
23
+ const briefs = others.slice(0, BRIEFS)
24
+ const more = others.slice(BRIEFS)
25
+
26
+ return h(
27
+ 'main',
28
+ { class: 'cg-main cg-archive', id: 'cg-main' },
15
29
  h(
16
- 'li',
17
- { class: 'cg-issue__row' },
30
+ 'header',
31
+ { class: 'cg-archive__head' },
18
32
  h(
19
- 'span',
20
- { class: 'cg-issue__row-number', 'aria-hidden': 'true' },
21
- String(index + 1).padStart(2, '0'),
33
+ 'div',
34
+ { class: 'cg-container cg-archive__head-inner' },
35
+ input.ancestors.length === 0
36
+ ? null
37
+ : h(
38
+ 'nav',
39
+ { class: 'cg-archive__breadcrumb', 'aria-label': input.labels.breadcrumb },
40
+ h(
41
+ 'ol',
42
+ {},
43
+ input.ancestors.map((link) => h('li', {}, h('a', { href: link.href }, link.label))),
44
+ ),
45
+ ),
46
+ h('p', { class: 'cg-archive__kicker' }, input.taxonomyName),
47
+ h('h1', { class: 'cg-archive__title' }, input.term.label),
48
+ input.children.length === 0
49
+ ? null
50
+ : h(
51
+ 'ul',
52
+ { class: 'cg-archive__children', 'aria-label': input.labels.subterms },
53
+ input.children.map((child) => h('li', {}, h('a', { href: child.href }, child.label))),
54
+ ),
22
55
  ),
56
+ ),
57
+ h(
58
+ 'section',
59
+ { class: 'cg-section cg-listing', 'data-form': 'archive' },
23
60
  h(
24
61
  'div',
25
- { class: 'cg-issue__row-body' },
26
- h(
27
- 'h2',
28
- { class: 'cg-issue__row-title' },
29
- entry.href === null
30
- ? entry.title
31
- : h('a', { class: 'cg-issue__link', href: entry.href }, entry.title),
32
- ),
33
- entry.publishedAt === null
34
- ? null
62
+ { class: 'cg-container cg-listing__inner' },
63
+ lead === undefined
64
+ ? h('p', { class: 'cg-empty' }, input.labels.empty)
35
65
  : h(
36
- 'time',
37
- { class: 'cg-issue__row-date', datetime: entry.publishedAt },
38
- entry.publishedAt.slice(0, 10),
66
+ 'div',
67
+ {
68
+ class: 'cg-front',
69
+ 'data-briefs': String(briefs.length),
70
+ 'data-more': String(more.length),
71
+ },
72
+ h(
73
+ 'div',
74
+ { class: 'cg-front__lead' },
75
+ renderStory(lead, { tag: 'h2', variant: 'lead', standfirst: true, date: true }),
76
+ ),
77
+ briefs.length === 0
78
+ ? null
79
+ : h(
80
+ 'ul',
81
+ { class: 'cg-front__briefs' },
82
+ briefs.map((story) =>
83
+ h(
84
+ 'li',
85
+ { class: 'cg-front__brief' },
86
+ renderStory(story, {
87
+ tag: 'h2',
88
+ variant: 'brief',
89
+ standfirst: true,
90
+ date: true,
91
+ }),
92
+ ),
93
+ ),
94
+ ),
95
+ more.length === 0
96
+ ? null
97
+ : h(
98
+ 'ul',
99
+ { class: 'cg-front__more' },
100
+ more.map((story) =>
101
+ h(
102
+ 'li',
103
+ { class: 'cg-front__item' },
104
+ renderStory(story, {
105
+ tag: 'h2',
106
+ variant: 'secondary',
107
+ standfirst: true,
108
+ date: true,
109
+ }),
110
+ ),
111
+ ),
112
+ ),
39
113
  ),
40
- entry.summary === null ? null : h('p', { class: 'cg-issue__lead-excerpt' }, entry.summary),
114
+ pager(input),
41
115
  ),
42
116
  ),
43
117
  )
44
-
45
- return h(
46
- 'main',
47
- { class: 'cg-main cg-archive', id: 'cg-main' },
48
- input.ancestors.length === 0
49
- ? null
50
- : h(
51
- 'nav',
52
- { class: 'cg-archive__breadcrumb', 'aria-label': input.labels.breadcrumb },
53
- h(
54
- 'ol',
55
- {},
56
- ...input.ancestors.map((l) => h('li', {}, h('a', { href: l.href }, l.label))),
57
- ),
58
- ),
59
- h('p', { class: 'cg-issue__kicker' }, input.taxonomyName),
60
- h('h1', { class: 'cg-page__title' }, input.term.label),
61
- input.children.length === 0
62
- ? null
63
- : h(
64
- 'ul',
65
- { class: 'cg-archive__children', 'aria-label': input.labels.subterms },
66
- ...input.children.map((c) => h('li', {}, h('a', { href: c.href }, c.label))),
67
- ),
68
- rows.length === 0
69
- ? h('p', { class: 'cg-issue__empty' }, input.labels.empty)
70
- : h('ul', { class: 'cg-issue__rest' }, ...rows),
71
- pager(input),
72
- )
73
118
  }
74
119
 
75
120
  function pager(input: TermArchiveInput): HtmlElement | null {
@@ -79,9 +124,17 @@ function pager(input: TermArchiveInput): HtmlElement | null {
79
124
  { class: 'cg-archive__pager', 'aria-label': input.labels.pagination },
80
125
  input.page.previousHref === null
81
126
  ? null
82
- : h('a', { rel: 'prev', href: input.page.previousHref }, input.labels.previous),
127
+ : h(
128
+ 'a',
129
+ { class: 'cg-archive__pager-link', rel: 'prev', href: input.page.previousHref },
130
+ input.labels.previous,
131
+ ),
83
132
  input.page.nextHref === null
84
133
  ? null
85
- : h('a', { rel: 'next', href: input.page.nextHref }, input.labels.next),
134
+ : h(
135
+ 'a',
136
+ { class: 'cg-archive__pager-link', rel: 'next', href: input.page.nextHref },
137
+ input.labels.next,
138
+ ),
86
139
  )
87
140
  }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The widget areas this theme names (contract D `theme@1.6`). Declaring them
3
+ * is what tells the host this theme draws the footer columns inside its own
4
+ * colophon; the page areas are placed by the host in the shared
5
+ * `cg-sidebar-layout` markup, which `styles/widgets.css` sets as a rail.
6
+ */
7
+ export const widgetAreas: readonly {
8
+ readonly id: string
9
+ readonly label: string
10
+ readonly description?: string
11
+ }[] = [
12
+ {
13
+ id: 'sidebar',
14
+ label: 'Rail',
15
+ description: 'Beside stories, section fronts and search results.',
16
+ },
17
+ {
18
+ id: 'content-after',
19
+ label: 'Under the story',
20
+ description: 'After an article or a page, before the comments.',
21
+ },
22
+ ]
@@ -1,40 +1,137 @@
1
1
  /*
2
- * The taxonomy-term archive (contract D `theme@1.3`).
3
- *
4
- * Only the three things an archive adds beyond what `collectionList` already
5
- * styles — a breadcrumb, a sub-term row, a prev/next pager. The entry list
6
- * itself reuses the `cg-entry`/`cg-collection__items` rules, on purpose: an
7
- * archive of articles must look like this theme's list of articles, and a
8
- * second set of card rules is exactly how those two drift apart.
2
+ * The taxonomy-term archive, set as a section front: the term very large on a
3
+ * double rule, then the front page's own composition in type alone
4
+ * (`stories.css`, `.cg-front`), with a row of three instead of four because
5
+ * no photograph holds the columns apart.
9
6
  */
10
7
 
11
- .cg-archive {
12
- max-inline-size: var(--cg-page);
13
- margin-inline: auto;
14
- padding: var(--cg-s10) var(--cg-gutter);
8
+ .cg-archive__head {
9
+ padding-block: calc(var(--cg-section) * 0.55) 0;
10
+ }
11
+
12
+ .cg-archive__head-inner {
13
+ position: relative;
14
+ row-gap: var(--cg-s2);
15
+ padding-block-end: var(--cg-s5);
16
+ }
17
+
18
+ /* The double rule under the section's name: a hairline over a heavy rule. */
19
+ .cg-archive__head-inner::after {
20
+ content: "";
21
+ position: absolute;
22
+ inset-inline: var(--cg-gutter);
23
+ inset-block-end: 0;
24
+ block-size: calc(var(--cg-rule-heavy) + var(--cg-rule-strong) + var(--cg-rule));
25
+ border-block-start: var(--cg-rule) solid var(--cg-line-ink);
26
+ border-block-end: var(--cg-rule-heavy) solid var(--cg-line-ink);
27
+ }
28
+
29
+ .cg-archive__kicker {
30
+ margin: 0;
31
+ color: var(--cg-accent);
32
+ font-family: var(--cg-font-ui);
33
+ font-size: var(--cg-text-label);
34
+ font-weight: var(--cg-weight-bold);
35
+ letter-spacing: var(--cg-tracking-caps);
36
+ text-transform: uppercase;
37
+ }
38
+
39
+ .cg-archive__title {
40
+ padding-block-end: var(--cg-s3);
41
+ font-size: var(--cg-size-nameplate);
42
+ font-weight: var(--cg-weight-bold);
43
+ line-height: 1;
44
+ letter-spacing: -0.018em;
15
45
  }
16
46
 
17
47
  .cg-archive__breadcrumb ol,
18
48
  .cg-archive__children {
19
49
  display: flex;
20
50
  flex-wrap: wrap;
21
- gap: var(--cg-s3);
22
- margin: 0 0 var(--cg-s4);
51
+ gap: var(--cg-s1) var(--cg-s5);
52
+ margin: 0;
23
53
  padding: 0;
24
54
  list-style: none;
55
+ font-family: var(--cg-font-ui);
25
56
  font-size: var(--cg-text-sm);
26
57
  }
27
58
 
59
+ .cg-archive__breadcrumb li + li::before {
60
+ content: "/";
61
+ margin-inline-end: var(--cg-s5);
62
+ color: var(--cg-ink-subtle);
63
+ }
64
+
65
+ .cg-archive__breadcrumb a,
66
+ .cg-archive__children a {
67
+ color: var(--cg-ink-muted);
68
+ text-decoration-color: transparent;
69
+ }
70
+
71
+ .cg-archive__breadcrumb a:hover,
72
+ .cg-archive__children a:hover {
73
+ color: var(--cg-ink);
74
+ text-decoration-color: currentColor;
75
+ }
76
+
28
77
  .cg-archive__children {
29
- margin-block: var(--cg-s4) var(--cg-s8);
78
+ padding-block-end: var(--cg-s3);
79
+ font-weight: var(--cg-weight-semibold);
80
+ }
81
+
82
+ /* A section front sets every story in type: the lead's headline takes the
83
+ size a photograph would otherwise have given it. */
84
+ .cg-archive .cg-story--lead .cg-story__title {
85
+ font-size: var(--cg-size-headline);
86
+ }
87
+
88
+ .cg-archive .cg-story--lead .cg-story__standfirst {
89
+ font-size: var(--cg-size-standfirst);
90
+ font-style: italic;
91
+ color: var(--cg-ink);
92
+ }
93
+
94
+ .cg-archive .cg-story--secondary .cg-story__title {
95
+ font-size: var(--cg-size-brief);
96
+ }
97
+
98
+ @media (min-width: 64rem) {
99
+ .cg-archive .cg-front__more {
100
+ grid-template-columns: repeat(3, minmax(0, 1fr));
101
+ }
102
+
103
+ .cg-archive .cg-front__item:nth-child(4n + 1)::before {
104
+ content: "";
105
+ }
106
+
107
+ .cg-archive .cg-front__item:nth-child(3n + 1)::before {
108
+ content: none;
109
+ }
30
110
  }
31
111
 
32
112
  .cg-archive__pager {
33
113
  display: flex;
34
114
  justify-content: space-between;
35
- gap: var(--cg-s4);
115
+ gap: var(--cg-s6);
36
116
  margin-block-start: var(--cg-s10);
37
- padding-block-start: var(--cg-s5);
38
- border-block-start: 1px solid var(--cg-rule-soft);
117
+ padding-block-start: var(--cg-s4);
118
+ border-block-start: var(--cg-rule) solid var(--cg-line-ink);
119
+ }
120
+
121
+ .cg-archive__pager-link {
122
+ color: var(--cg-ink);
123
+ font-family: var(--cg-font-ui);
124
+ font-size: var(--cg-text-ui);
39
125
  font-weight: var(--cg-weight-semibold);
126
+ text-decoration-color: var(--cg-line-strong);
127
+ text-underline-offset: 0.3em;
128
+ }
129
+
130
+ .cg-archive__pager-link[rel="next"] {
131
+ margin-inline-start: auto;
132
+ }
133
+
134
+ .cg-archive__pager-link:hover {
135
+ color: var(--cg-accent);
136
+ text-decoration-color: currentColor;
40
137
  }