@rathnasgala/theme 0.0.17 → 0.0.19
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.
- package/package.json +1 -1
- package/payload/.gala/managed-files.json +10 -6
- package/payload/lib/site-config.js +23 -3
- package/payload/src/_includes/layouts/base.njk +3 -7
- package/payload/src/assets/favicon.svg +1 -0
- package/payload/src/assets/theme-mode.js +14 -2
- package/payload/src/assets/theme.css +393 -56
- package/payload/src/settings.njk +0 -19
package/package.json
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"themePackage": {
|
|
4
4
|
"name": "@rathnasgala/theme",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.19",
|
|
6
6
|
"availableDesignThemes": [
|
|
7
7
|
"editorial"
|
|
8
8
|
],
|
|
9
9
|
"securityAdvisories": []
|
|
10
10
|
},
|
|
11
|
+
"requiredBudgets": {
|
|
12
|
+
"managedJavaScriptBytes": 65536,
|
|
13
|
+
"managedCssBytes": 32768
|
|
14
|
+
},
|
|
11
15
|
"files": {
|
|
12
16
|
".gala/publish.yml.template": "73080241d89bd09964b797a8bcc8e18471412e11bc873efad76305b60f497d08",
|
|
13
17
|
".gitignore": "b5fa24e10155097a0d372926fd2e59e6072e7cc2cb6399bbfb4beb8b33ea315b",
|
|
@@ -21,7 +25,7 @@
|
|
|
21
25
|
"lib/render-markdown.js": "40e6d6743b76de6c16d138475f188a4263967530c370d8b26a363f4df58c2caf",
|
|
22
26
|
"lib/seo.js": "107de8804931945b8e73894877fc394d6b535a9d0d969a4ba5b68f2e136e0a17",
|
|
23
27
|
"lib/share-targets.js": "458aff86fab2b62a364442cd8c612565c6e0b53eef2f20cb6237cc562b1e0731",
|
|
24
|
-
"lib/site-config.js": "
|
|
28
|
+
"lib/site-config.js": "da7d2dffab62c7346c9930494b85fc6ea735d4f50565bbd0454a04393f8cad96",
|
|
25
29
|
"package-lock.json": "c97a6a2f794aef083a39a8d2628eccc4a3c484e1c6225899b77ec1fb7c466d9e",
|
|
26
30
|
"package.json": "4c60bea06f39aec755ac68caf8d8841c1d59d0f6121fad7f4396231ce14712dc",
|
|
27
31
|
"src/404.njk": "be0d44370ac5402156aaf3d32ea581057bc61ec94c1a5f92bb809733af7a8a20",
|
|
@@ -31,7 +35,7 @@
|
|
|
31
35
|
"src/_data/languages.js": "1358748f7fa2f74406d3295a030827d6229a53e94da72cf712e719d7a356aeac",
|
|
32
36
|
"src/_data/site.js": "d9c001f4cc12a34027dd92303530b11b5402d47613459bb997e22c4bcbea326d",
|
|
33
37
|
"src/_includes/components/ui.njk": "23eb647d8658868449ec6bb809e965a85302124a97639f94d5d28af72df56e4c",
|
|
34
|
-
"src/_includes/layouts/base.njk": "
|
|
38
|
+
"src/_includes/layouts/base.njk": "e73be30738535902599e1c060c11afbd128c86332913114f643dc56dea99fcba",
|
|
35
39
|
"src/_includes/layouts/post.njk": "1accd2832064ad19ee7bf18daf5fa1e60569f32c9b7a547934a6361f747d7eb7",
|
|
36
40
|
"src/assets/embed-codepen.svg": "e9def697f38c466fb2b6652535c4c814e8cbbbefc6e052a69f335aeb27e8356b",
|
|
37
41
|
"src/assets/embed-gist.svg": "fcd9bc2bf29a5c118492b853c0a01390b7539c38ddb985da3c2a6e2f246a39f7",
|
|
@@ -39,11 +43,12 @@
|
|
|
39
43
|
"src/assets/embed-youtube.svg": "10d192f2b14b67664fea88c8cf246321d20190def51d59fad5762e552219b067",
|
|
40
44
|
"src/assets/engagement-comments.js": "b20d9268c9d908b4453a42188eaca25349f25534fb04a9293c9e688a982cd8f8",
|
|
41
45
|
"src/assets/engagement-transport.js": "4f9ca0cd669bf8abc25f2909104e3e4b231657ef97d36a17d06e53454d711786",
|
|
46
|
+
"src/assets/favicon.svg": "8615e3d96fe37ae9ed14afb1886e7c0e690eef5b10be66ca91cccfd085a74bb6",
|
|
42
47
|
"src/assets/interactions.js": "dd4e343505e528d89596ca67db679b52c989e022f93399193e4377db01fc8a08",
|
|
43
48
|
"src/assets/preferences.js": "789127bee013ed6a1bbf8cefd7b9109291c16220e7a6e09314e3c93c54731d1d",
|
|
44
49
|
"src/assets/search.js": "df425f0239277792ad39f2138bc89cb66cc4ecda5ed59042d46abc2f05372088",
|
|
45
|
-
"src/assets/theme-mode.js": "
|
|
46
|
-
"src/assets/theme.css": "
|
|
50
|
+
"src/assets/theme-mode.js": "944b29db11a577961a60ddcfa52f07ef2411f3f3631bea85bd79be16428c08be",
|
|
51
|
+
"src/assets/theme.css": "cdd41ddb670fb8c823b3490efa2a887d11dd6a1931afa0264deee53283b684d3",
|
|
47
52
|
"src/assets/vendor/hooks.js": "ae6ec58592683ca64fa4d65b20d40b103df62a673bcc4712515cf165950b07f3",
|
|
48
53
|
"src/assets/vendor/htm.js": "e4dac9bc40a6f2ec590413d787ae30bbcfdfcde4f28971ee65d9578271b7aad4",
|
|
49
54
|
"src/assets/vendor/preact.js": "712517dd2a42c3c22b5ab0264ad7e9a2b1e8be6cf97fa00dbedd98203617e616",
|
|
@@ -58,7 +63,6 @@
|
|
|
58
63
|
"src/redirects.11ty.js": "3c163246a59f5364861db6a6f05ae88afc938a5379d86cf42776d8d49b0031f3",
|
|
59
64
|
"src/search-index.11ty.js": "700dc2a2be0ef20de3a828a4612fcf7a082691eade29c6e1d75f09c24b6c6024",
|
|
60
65
|
"src/search.njk": "63f2e8aeebb63c90da2e375eece639ce096cad1eff7f28628cafc46faf7ceee6",
|
|
61
|
-
"src/settings.njk": "9e6babf4d2774687558618c4fbd109ddfc0f479f52ec2e5d00c373c44ad16676",
|
|
62
66
|
"src/sitemap.11ty.js": "4f233e94fb4a913ad5659116518432ed264984a7b622eba3558c77b4ec6435dc",
|
|
63
67
|
"static/robots.txt": "16ceb5ee3e0dc13aa9adf31a3ebbe45a1d965b8c2b9f72eaf84e5911e140ed95"
|
|
64
68
|
},
|
|
@@ -7,19 +7,39 @@ const BUDGET_KEYS = Object.freeze([
|
|
|
7
7
|
'managedCssBytes',
|
|
8
8
|
'ordinaryHtmlBytes'
|
|
9
9
|
]);
|
|
10
|
+
/*
|
|
11
|
+
* Only what the theme actually implements. A value here is a promise that choosing it changes how
|
|
12
|
+
* a publication looks; anything the CSS does not answer to has no business being offered.
|
|
13
|
+
*/
|
|
10
14
|
const DESIGN_VALUES = Object.freeze({
|
|
11
15
|
layout: Object.freeze(['article-first', 'portfolio']),
|
|
12
|
-
palette: Object.freeze(['default', 'ocean'])
|
|
16
|
+
palette: Object.freeze(['default', 'ocean']),
|
|
17
|
+
typography: Object.freeze(['system', 'editorial', 'humanist', 'mono']),
|
|
18
|
+
density: Object.freeze(['compact', 'comfortable', 'spacious']),
|
|
19
|
+
spacing: Object.freeze(['compact', 'comfortable', 'spacious']),
|
|
20
|
+
radius: Object.freeze(['sharp', 'soft', 'round']),
|
|
21
|
+
motion: Object.freeze(['none', 'subtle', 'expressive']),
|
|
22
|
+
componentStyle: Object.freeze(['quiet', 'outlined', 'raised'])
|
|
13
23
|
});
|
|
14
24
|
const CONTACT_KEYS = Object.freeze([
|
|
15
25
|
'enabled', 'websiteEnabled', 'phoneEnabled'
|
|
16
26
|
]);
|
|
17
27
|
|
|
28
|
+
/*
|
|
29
|
+
* `layout` and `palette` have always been required. The rest were added later and are optional:
|
|
30
|
+
* a publication written before they existed is still a valid publication, and the theme falls
|
|
31
|
+
* back to its own defaults for anything absent. Present-but-unknown is still an error, because
|
|
32
|
+
* that is a writer expecting something the CSS will not do.
|
|
33
|
+
*/
|
|
34
|
+
const REQUIRED_DESIGN = Object.freeze(['layout', 'palette']);
|
|
35
|
+
|
|
18
36
|
function validateImplementedDesign(config) {
|
|
19
37
|
if (config?.design == null) return;
|
|
20
38
|
for (const [field, allowed] of Object.entries(DESIGN_VALUES)) {
|
|
21
|
-
|
|
22
|
-
|
|
39
|
+
const value = config.design[field];
|
|
40
|
+
if (value === undefined && !REQUIRED_DESIGN.includes(field)) continue;
|
|
41
|
+
if (!allowed.includes(value)) {
|
|
42
|
+
throw new TypeError(`Unsupported design.${field}: ${value}`);
|
|
23
43
|
}
|
|
24
44
|
}
|
|
25
45
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
|
-
<html lang="{{ post.language or site.site.defaultLanguage }}" data-theme="{{ site.design.theme }}" data-layout="{{ site.design.layout }}" data-palette="{{ site.design.palette }}" data-mode="system">
|
|
2
|
+
<html lang="{{ post.language or site.site.defaultLanguage }}" data-theme="{{ site.design.theme }}" data-layout="{{ site.design.layout }}" data-palette="{{ site.design.palette }}" data-typography="{{ site.design.typography }}" data-density="{{ site.design.density }}" data-spacing="{{ site.design.spacing }}" data-radius="{{ site.design.radius }}" data-motion="{{ site.design.motion }}" data-component-style="{{ site.design.componentStyle }}" data-mode="{{ site.design.colorMode | default('system') }}">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
<link rel="stylesheet" href="{{ '/custom.css' | url }}">
|
|
27
27
|
<script src="{{ '/assets/theme-mode.js' | url }}" defer></script>
|
|
28
28
|
<script src="{{ '/assets/preferences.js' | url }}" defer></script>
|
|
29
|
+
<link rel="icon" href="{{ '/assets/favicon.svg' | url }}" type="image/svg+xml">
|
|
29
30
|
<script src="{{ '/assets/interactions.js' | url }}" defer></script>
|
|
30
31
|
<script type="module" src="{{ '/assets/engagement-comments.js' | url }}"></script>
|
|
31
32
|
<script src="{{ '/assets/search.js' | url }}" defer></script>
|
|
@@ -69,17 +70,12 @@
|
|
|
69
70
|
<dialog id="gala-settings-dialog" class="gala-dialog" aria-labelledby="gala-settings-title">
|
|
70
71
|
<form method="dialog" class="gala-dialog__close"><button type="submit" aria-label="Close settings">Close</button></form>
|
|
71
72
|
<h2 id="gala-settings-title">Reader settings</h2>
|
|
72
|
-
<section aria-labelledby="gala-dialog-theme-setting">
|
|
73
|
-
<h3 id="gala-dialog-theme-setting">Appearance</h3>
|
|
74
|
-
<button type="button" data-theme-mode-toggle aria-label="Color mode: system. Activate for light."><span data-theme-mode-label>Theme: system</span></button>
|
|
75
|
-
</section>
|
|
76
73
|
<section aria-labelledby="gala-dialog-language-setting">
|
|
77
74
|
<h3 id="gala-dialog-language-setting">Language preference</h3>
|
|
78
75
|
<label>Preferred language
|
|
79
76
|
<select data-language-preference>{% for language in languages %}<option value="{{ language | escape }}">{{ language }}</option>{% endfor %}</select>
|
|
80
77
|
</label>
|
|
81
78
|
</section>
|
|
82
|
-
<p><a href="{{ '/settings/' | url }}">Open settings page</a></p>
|
|
83
79
|
</dialog>
|
|
84
80
|
<dialog id="gala-search-dialog" class="gala-dialog" aria-labelledby="gala-search-title">
|
|
85
81
|
<form method="dialog" class="gala-dialog__close"><button type="submit" aria-label="Close search">Close</button></form>
|
|
@@ -98,7 +94,7 @@
|
|
|
98
94
|
{% if site.site.id and site.site.id != "unavailable" %}
|
|
99
95
|
<dialog id="gala-account-dialog" class="gala-dialog gala-account-dialog" aria-labelledby="gala-account-title">
|
|
100
96
|
<form method="dialog" class="gala-dialog__close"><button type="submit" aria-label="Close account">Close</button></form>
|
|
101
|
-
<h2 id="gala-account-title">Gala account</h2>
|
|
97
|
+
<h2 id="gala-account-title" class="gala-visually-hidden">Gala account</h2>
|
|
102
98
|
<iframe data-gala-session-frame title="Gala account and sign in" allow="identity-credentials-get" src="{{ site.platform.apiBaseUrl or 'https://api.gala67.com' }}/v1/widget/session?siteId={{ site.site.id | escape }}"></iframe>
|
|
103
99
|
</dialog>
|
|
104
100
|
{% endif %}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="32" height="32" rx="7" fill="#8a4b2a"/><path d="M22 11.5c-1.1-1.3-2.8-2-4.6-2-3.6 0-6.4 2.9-6.4 6.5s2.8 6.5 6.4 6.5c3.2 0 5.6-2 6-5h-5.6" fill="none" stroke="#fdfcfb" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
const MODES = ['system', 'light', 'dark'];
|
|
2
2
|
const STORAGE_KEY = 'gala-color-mode';
|
|
3
3
|
|
|
4
|
+
/*
|
|
5
|
+
* The reader's own choice always wins. Absent one, the publication's `design.colorMode` decides
|
|
6
|
+
* what they see first — it is already on the element, server-rendered. This used to fall back to
|
|
7
|
+
* `system` unconditionally, which meant a writer could set a colour mode and no reader ever saw
|
|
8
|
+
* it: the setting existed everywhere except in the page.
|
|
9
|
+
*/
|
|
10
|
+
function publicationDefault() {
|
|
11
|
+
const declared = document.documentElement.dataset.mode;
|
|
12
|
+
return MODES.includes(declared) ? declared : 'system';
|
|
13
|
+
}
|
|
14
|
+
|
|
4
15
|
function storedMode() {
|
|
5
16
|
try {
|
|
6
17
|
const mode = localStorage.getItem(STORAGE_KEY);
|
|
7
|
-
|
|
18
|
+
if (MODES.includes(mode)) return mode;
|
|
8
19
|
} catch {
|
|
9
|
-
return
|
|
20
|
+
return publicationDefault();
|
|
10
21
|
}
|
|
22
|
+
return publicationDefault();
|
|
11
23
|
}
|
|
12
24
|
|
|
13
25
|
function applyMode(mode) {
|
|
@@ -1,57 +1,181 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* A publication should read like a well-set page, not like a product.
|
|
3
|
+
*
|
|
4
|
+
* The chrome is quiet, the type carries the hierarchy, and depth comes from surface and space
|
|
5
|
+
* rather than from an outline around everything. Every value here is a token so that the ten
|
|
6
|
+
* `design:` choices in site.config.yml can move the whole page by moving a handful of variables,
|
|
7
|
+
* instead of each component inventing its own spacing and its own grey.
|
|
8
|
+
*/
|
|
1
9
|
:root {
|
|
2
10
|
color-scheme: light dark;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
--gala-
|
|
6
|
-
--gala-
|
|
7
|
-
--gala-color-
|
|
8
|
-
--gala-color-
|
|
9
|
-
--gala-color-
|
|
10
|
-
--gala-
|
|
11
|
-
--gala-
|
|
11
|
+
|
|
12
|
+
/* Neutrals carry a slight warmth. A pure grey reads as unconsidered; these were picked. */
|
|
13
|
+
--gala-color-background: light-dark(#fdfcfb, #131211);
|
|
14
|
+
--gala-color-surface: light-dark(#f6f4f1, #1c1a18);
|
|
15
|
+
--gala-color-raised: light-dark(#fffffe, #24211f);
|
|
16
|
+
--gala-color-text: light-dark(#1a1817, #f2efec);
|
|
17
|
+
--gala-color-muted: light-dark(#6b645e, #a8a099);
|
|
18
|
+
--gala-color-border: light-dark(#968e86, #6b645e);
|
|
19
|
+
--gala-color-hairline: light-dark(#e8e3dd, #2a2724);
|
|
20
|
+
--gala-color-border-strong: light-dark(#c9c2ba, #46413d);
|
|
21
|
+
--gala-color-accent: light-dark(#8a4b2a, #e8a87c);
|
|
22
|
+
|
|
23
|
+
/* Type. One scale, used everywhere, fluid between a phone and a desk. */
|
|
24
|
+
--gala-font-body: ui-sans-serif, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
|
|
25
|
+
--gala-font-display: var(--gala-font-body);
|
|
26
|
+
--gala-font-mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace;
|
|
27
|
+
--gala-text-xs: 0.78rem;
|
|
28
|
+
--gala-text-sm: 0.875rem;
|
|
29
|
+
--gala-text-base: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
|
|
30
|
+
--gala-text-lg: clamp(1.15rem, 1.09rem + 0.3vw, 1.3rem);
|
|
31
|
+
--gala-text-xl: clamp(1.4rem, 1.28rem + 0.6vw, 1.75rem);
|
|
32
|
+
--gala-text-2xl: clamp(1.75rem, 1.5rem + 1.2vw, 2.4rem);
|
|
33
|
+
--gala-text-3xl: clamp(2.2rem, 1.7rem + 2.4vw, 3.4rem);
|
|
34
|
+
--gala-leading-tight: 1.15;
|
|
35
|
+
--gala-leading-body: 1.65;
|
|
36
|
+
--gala-tracking-tight: -0.018em;
|
|
37
|
+
--gala-tracking-wide: 0.08em;
|
|
38
|
+
--gala-weight-display: 640;
|
|
39
|
+
|
|
40
|
+
/* Space, radius, depth, motion. */
|
|
41
|
+
--gala-step: 1rem;
|
|
42
|
+
--gala-space-2xs: calc(var(--gala-step) * 0.25);
|
|
43
|
+
--gala-space-xs: calc(var(--gala-step) * 0.5);
|
|
44
|
+
--gala-space-sm: calc(var(--gala-step) * 0.75);
|
|
45
|
+
--gala-space-md: var(--gala-step);
|
|
46
|
+
--gala-space-lg: calc(var(--gala-step) * 1.75);
|
|
47
|
+
--gala-space-xl: calc(var(--gala-step) * 3);
|
|
48
|
+
--gala-space-page: clamp(1.25rem, 5vw, 4.5rem);
|
|
49
|
+
--gala-radius-control: 0.625rem;
|
|
50
|
+
--gala-radius-surface: 1rem;
|
|
51
|
+
--gala-shadow-low: 0 1px 2px light-dark(rgb(26 24 23 / 6%), rgb(0 0 0 / 40%));
|
|
52
|
+
--gala-shadow-high:
|
|
53
|
+
0 1px 2px light-dark(rgb(26 24 23 / 5%), rgb(0 0 0 / 35%)),
|
|
54
|
+
0 12px 28px -12px light-dark(rgb(26 24 23 / 18%), rgb(0 0 0 / 60%));
|
|
55
|
+
--gala-motion-fast: 120ms;
|
|
56
|
+
--gala-motion-base: 220ms;
|
|
57
|
+
--gala-ease: cubic-bezier(0.2, 0, 0, 1);
|
|
58
|
+
|
|
59
|
+
--gala-content-width: 72rem;
|
|
60
|
+
--gala-measure: 68ch;
|
|
12
61
|
--gala-widget-min-block-size: 8rem;
|
|
13
62
|
}
|
|
14
63
|
|
|
64
|
+
/* An explicit choice must beat the operating system in both directions, so every colour is
|
|
65
|
+
restated rather than left to `light-dark()`. */
|
|
15
66
|
:root[data-mode='light'] {
|
|
16
67
|
color-scheme: light;
|
|
17
|
-
--gala-color-background: #
|
|
18
|
-
--gala-color-
|
|
19
|
-
--gala-color-
|
|
20
|
-
--gala-color-
|
|
21
|
-
--gala-color-
|
|
68
|
+
--gala-color-background: #fdfcfb;
|
|
69
|
+
--gala-color-surface: #f6f4f1;
|
|
70
|
+
--gala-color-raised: #fffffe;
|
|
71
|
+
--gala-color-text: #1a1817;
|
|
72
|
+
--gala-color-muted: #6b645e;
|
|
73
|
+
--gala-color-border: #968e86;
|
|
74
|
+
--gala-color-hairline: #e8e3dd;
|
|
75
|
+
--gala-color-border-strong: #c9c2ba;
|
|
76
|
+
--gala-color-accent: #8a4b2a;
|
|
22
77
|
}
|
|
23
|
-
|
|
24
78
|
:root[data-mode='dark'] {
|
|
25
79
|
color-scheme: dark;
|
|
26
|
-
--gala-color-background: #
|
|
27
|
-
--gala-color-
|
|
28
|
-
--gala-color-
|
|
29
|
-
--gala-color-
|
|
30
|
-
--gala-color-
|
|
80
|
+
--gala-color-background: #131211;
|
|
81
|
+
--gala-color-surface: #1c1a18;
|
|
82
|
+
--gala-color-raised: #24211f;
|
|
83
|
+
--gala-color-text: #f2efec;
|
|
84
|
+
--gala-color-muted: #a8a099;
|
|
85
|
+
--gala-color-border: #6b645e;
|
|
86
|
+
--gala-color-hairline: #2a2724;
|
|
87
|
+
--gala-color-border-strong: #46413d;
|
|
88
|
+
--gala-color-accent: #e8a87c;
|
|
31
89
|
}
|
|
32
90
|
|
|
91
|
+
/* ---------------------------------------------------------------- palettes */
|
|
33
92
|
:root[data-palette='ocean'] {
|
|
34
|
-
--gala-color-background: light-dark(#
|
|
35
|
-
--gala-color-
|
|
36
|
-
--gala-color-
|
|
37
|
-
--gala-color-
|
|
38
|
-
--gala-color-
|
|
93
|
+
--gala-color-background: light-dark(#f8fbfd, #0b1a24);
|
|
94
|
+
--gala-color-surface: light-dark(#eef4f9, #12252f);
|
|
95
|
+
--gala-color-raised: light-dark(#ffffff, #172d39);
|
|
96
|
+
--gala-color-text: light-dark(#12242f, #eaf3f8);
|
|
97
|
+
--gala-color-muted: light-dark(#5a6f7d, #98aebb);
|
|
98
|
+
--gala-color-border: light-dark(#7d8d99, #5f7d8c);
|
|
99
|
+
--gala-color-hairline: light-dark(#dde7ee, #1d3644);
|
|
100
|
+
--gala-color-border-strong: light-dark(#bdccd7, #33505f);
|
|
101
|
+
--gala-color-accent: light-dark(#0f5f7a, #7fd0e8);
|
|
39
102
|
}
|
|
40
|
-
|
|
41
103
|
:root[data-palette='ocean'][data-mode='light'] {
|
|
42
|
-
|
|
43
|
-
--gala-color-
|
|
44
|
-
--gala-color-surface: #
|
|
45
|
-
--gala-color-
|
|
46
|
-
--gala-color-
|
|
104
|
+
color-scheme: light;
|
|
105
|
+
--gala-color-background: #f8fbfd;
|
|
106
|
+
--gala-color-surface: #eef4f9;
|
|
107
|
+
--gala-color-raised: #ffffff;
|
|
108
|
+
--gala-color-text: #12242f;
|
|
109
|
+
--gala-color-muted: #5a6f7d;
|
|
110
|
+
--gala-color-border: #7d8d99;
|
|
111
|
+
--gala-color-hairline: #dde7ee;
|
|
112
|
+
--gala-color-border-strong: #bdccd7;
|
|
113
|
+
--gala-color-accent: #0f5f7a;
|
|
47
114
|
}
|
|
48
|
-
|
|
49
115
|
:root[data-palette='ocean'][data-mode='dark'] {
|
|
50
|
-
|
|
51
|
-
--gala-color-
|
|
52
|
-
--gala-color-surface: #
|
|
53
|
-
--gala-color-
|
|
54
|
-
--gala-color-
|
|
116
|
+
color-scheme: dark;
|
|
117
|
+
--gala-color-background: #0b1a24;
|
|
118
|
+
--gala-color-surface: #12252f;
|
|
119
|
+
--gala-color-raised: #172d39;
|
|
120
|
+
--gala-color-text: #eaf3f8;
|
|
121
|
+
--gala-color-muted: #98aebb;
|
|
122
|
+
--gala-color-border: #5f7d8c;
|
|
123
|
+
--gala-color-hairline: #1d3644;
|
|
124
|
+
--gala-color-border-strong: #33505f;
|
|
125
|
+
--gala-color-accent: #7fd0e8;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* ---------------------------------------------------------------- typography
|
|
129
|
+
System stacks rather than a downloaded face: a publication must build and render with no call
|
|
130
|
+
to anyone, and a webfont is bytes on every reader's first paint. These are the good faces the
|
|
131
|
+
reader's machine already has. */
|
|
132
|
+
:root[data-typography='editorial'] {
|
|
133
|
+
--gala-font-body: ui-serif, "Iowan Old Style", Charter, "Source Serif 4", Georgia, serif;
|
|
134
|
+
--gala-font-display: var(--gala-font-body);
|
|
135
|
+
--gala-weight-display: 600;
|
|
136
|
+
}
|
|
137
|
+
:root[data-typography='humanist'] {
|
|
138
|
+
--gala-font-body: Optima, Candara, "Gill Sans", "Trebuchet MS", sans-serif;
|
|
139
|
+
--gala-font-display: var(--gala-font-body);
|
|
140
|
+
}
|
|
141
|
+
:root[data-typography='mono'] {
|
|
142
|
+
--gala-font-display: var(--gala-font-mono);
|
|
143
|
+
--gala-weight-display: 560;
|
|
144
|
+
--gala-tracking-tight: -0.005em;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* ---------------------------------------------------------------- density */
|
|
148
|
+
:root[data-density='compact'], :root[data-spacing='compact'] {
|
|
149
|
+
--gala-step: 0.8rem;
|
|
150
|
+
--gala-leading-body: 1.5;
|
|
151
|
+
}
|
|
152
|
+
:root[data-density='spacious'], :root[data-spacing='spacious'] {
|
|
153
|
+
--gala-step: 1.25rem;
|
|
154
|
+
--gala-leading-body: 1.75;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/* ---------------------------------------------------------------- radius */
|
|
158
|
+
:root[data-radius='sharp'] { --gala-radius-control: 0; --gala-radius-surface: 0; }
|
|
159
|
+
:root[data-radius='round'] { --gala-radius-control: 999px; --gala-radius-surface: 1.5rem; }
|
|
160
|
+
|
|
161
|
+
/* ---------------------------------------------------------------- motion
|
|
162
|
+
`none` is honoured for everyone; a reader who asks the operating system for less motion is
|
|
163
|
+
honoured regardless of what the publication chose. */
|
|
164
|
+
:root[data-motion='none'] { --gala-motion-fast: 0ms; --gala-motion-base: 0ms; }
|
|
165
|
+
:root[data-motion='expressive'] { --gala-motion-base: 340ms; }
|
|
166
|
+
@media (prefers-reduced-motion: reduce) {
|
|
167
|
+
:root { --gala-motion-fast: 0ms; --gala-motion-base: 0ms; }
|
|
168
|
+
*, *::before, *::after { animation-duration: 1ms !important; transition-duration: 1ms !important; }
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* ---------------------------------------------------------------- surfaces
|
|
172
|
+
`quiet` sits on the page, `outlined` draws its edge, `raised` lifts. One variable decides,
|
|
173
|
+
so every card, dialog and chip agrees. */
|
|
174
|
+
:root { --gala-surface-border: var(--gala-color-hairline); --gala-surface-shadow: var(--gala-shadow-low); }
|
|
175
|
+
:root[data-component-style='outlined'] { --gala-surface-border: var(--gala-color-border-strong); }
|
|
176
|
+
:root[data-component-style='raised'] {
|
|
177
|
+
--gala-surface-border: transparent;
|
|
178
|
+
--gala-surface-shadow: var(--gala-shadow-high);
|
|
55
179
|
}
|
|
56
180
|
|
|
57
181
|
:root[data-layout='portfolio'] { --gala-content-width: 82rem; }
|
|
@@ -62,15 +186,78 @@ body {
|
|
|
62
186
|
color: var(--gala-color-text);
|
|
63
187
|
background: var(--gala-color-background);
|
|
64
188
|
font-family: var(--gala-font-body);
|
|
189
|
+
font-size: var(--gala-text-base);
|
|
190
|
+
line-height: var(--gala-leading-body);
|
|
191
|
+
-webkit-font-smoothing: antialiased;
|
|
192
|
+
text-rendering: optimizeLegibility;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* Headings carry the hierarchy, so they get the display face, a tighter measure and tighter
|
|
196
|
+
tracking — large type set at body tracking is the single clearest sign of an unconsidered page. */
|
|
197
|
+
:where(h1, h2, h3, h4) {
|
|
198
|
+
font-family: var(--gala-font-display);
|
|
199
|
+
font-weight: var(--gala-weight-display);
|
|
200
|
+
line-height: var(--gala-leading-tight);
|
|
201
|
+
letter-spacing: var(--gala-tracking-tight);
|
|
202
|
+
text-wrap: balance;
|
|
203
|
+
margin-block: 0 var(--gala-space-sm);
|
|
204
|
+
}
|
|
205
|
+
:where(h1) { font-size: var(--gala-text-3xl); }
|
|
206
|
+
:where(h2) { font-size: var(--gala-text-2xl); }
|
|
207
|
+
:where(h3) { font-size: var(--gala-text-xl); }
|
|
208
|
+
:where(h4) { font-size: var(--gala-text-lg); }
|
|
209
|
+
:where(p, ul, ol, blockquote) { margin-block: 0 var(--gala-space-md); }
|
|
210
|
+
:where(p) { text-wrap: pretty; }
|
|
211
|
+
|
|
212
|
+
blockquote {
|
|
213
|
+
margin-inline: 0;
|
|
214
|
+
padding-inline-start: var(--gala-space-md);
|
|
215
|
+
border-inline-start: 2px solid var(--gala-color-accent);
|
|
216
|
+
color: var(--gala-color-muted);
|
|
65
217
|
}
|
|
66
218
|
|
|
219
|
+
:where(code, kbd, samp) { font-family: var(--gala-font-mono); font-size: 0.9em; }
|
|
220
|
+
:where(pre) {
|
|
221
|
+
padding: var(--gala-space-md);
|
|
222
|
+
overflow-x: auto;
|
|
223
|
+
background: var(--gala-color-surface);
|
|
224
|
+
border-radius: var(--gala-radius-control);
|
|
225
|
+
}
|
|
226
|
+
:where(hr) { border: 0; border-block-start: 1px solid var(--gala-color-hairline); margin-block: var(--gala-space-xl); }
|
|
227
|
+
:where(table) { border-collapse: collapse; inline-size: 100%; }
|
|
228
|
+
:where(th, td) { padding: var(--gala-space-xs) var(--gala-space-sm); border-block-end: 1px solid var(--gala-color-hairline); text-align: start; }
|
|
229
|
+
|
|
230
|
+
/* An uppercase label needs air between the letters or it sets as a solid block. */
|
|
231
|
+
.gala-eyebrow, .gala-comment__meta time, .gala-comment__edited {
|
|
232
|
+
font-size: var(--gala-text-xs);
|
|
233
|
+
letter-spacing: var(--gala-tracking-wide);
|
|
234
|
+
text-transform: uppercase;
|
|
235
|
+
color: var(--gala-color-muted);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/*
|
|
239
|
+
* Stays with the reader. It used to scroll away, so on a long post the only way back to the site
|
|
240
|
+
* — or to sign in — was to scroll to the top. The negative inline margin lets the bar's background
|
|
241
|
+
* reach the edge of the viewport while its contents stay on the page's own measure.
|
|
242
|
+
*/
|
|
67
243
|
.gala-site-header {
|
|
244
|
+
position: sticky;
|
|
245
|
+
inset-block-start: 0;
|
|
246
|
+
z-index: 10;
|
|
68
247
|
display: flex;
|
|
69
248
|
align-items: center;
|
|
70
249
|
justify-content: space-between;
|
|
250
|
+
gap: var(--gala-space-md);
|
|
71
251
|
max-inline-size: var(--gala-content-width);
|
|
72
252
|
margin-inline: auto;
|
|
73
|
-
margin-block-end:
|
|
253
|
+
margin-block-end: var(--gala-space-xl);
|
|
254
|
+
padding-block: var(--gala-space-xs);
|
|
255
|
+
background: color-mix(in srgb, var(--gala-color-background) 88%, transparent);
|
|
256
|
+
backdrop-filter: blur(8px);
|
|
257
|
+
border-block-end: 1px solid var(--gala-color-hairline);
|
|
258
|
+
}
|
|
259
|
+
@supports not (backdrop-filter: blur(8px)) {
|
|
260
|
+
.gala-site-header { background: var(--gala-color-background); }
|
|
74
261
|
}
|
|
75
262
|
|
|
76
263
|
.gala-site-header__actions { display: flex; gap: 0.5rem; }
|
|
@@ -85,7 +272,12 @@ body {
|
|
|
85
272
|
border: 0.125rem solid transparent;
|
|
86
273
|
border-radius: 50%;
|
|
87
274
|
}
|
|
88
|
-
.gala-icon-control
|
|
275
|
+
.gala-icon-control {
|
|
276
|
+
transition: background var(--gala-motion-fast) var(--gala-ease),
|
|
277
|
+
color var(--gala-motion-fast) var(--gala-ease);
|
|
278
|
+
color: var(--gala-color-muted);
|
|
279
|
+
}
|
|
280
|
+
.gala-icon-control:hover { background: var(--gala-color-surface); color: var(--gala-color-text); }
|
|
89
281
|
.gala-icon-control:focus-visible { outline: 0.1875rem solid currentcolor; outline-offset: 0.1875rem; }
|
|
90
282
|
/* Stroked, not filled: the icons are drawn on one 24px grid at a single weight, so they read as
|
|
91
283
|
a set rather than as six unrelated silhouettes. */
|
|
@@ -98,12 +290,21 @@ body {
|
|
|
98
290
|
padding: 1.5rem;
|
|
99
291
|
color: var(--gala-color-text);
|
|
100
292
|
background: var(--gala-color-background);
|
|
101
|
-
border:
|
|
102
|
-
border-radius: var(--gala-radius-
|
|
293
|
+
border: 1px solid var(--gala-surface-border);
|
|
294
|
+
border-radius: var(--gala-radius-surface);
|
|
295
|
+
box-shadow: var(--gala-shadow-high);
|
|
103
296
|
}
|
|
104
297
|
.gala-dialog::backdrop { background: rgb(0 0 0 / 65%); }
|
|
105
|
-
.
|
|
106
|
-
.gala-account-dialog
|
|
298
|
+
/* Sized to what it holds. 22rem was a box for a name and one button, and it showed. */
|
|
299
|
+
.gala-account-dialog { inline-size: min(26rem, calc(100% - 2rem)); }
|
|
300
|
+
.gala-account-dialog iframe {
|
|
301
|
+
display: block;
|
|
302
|
+
inline-size: 100%;
|
|
303
|
+
min-block-size: 7rem;
|
|
304
|
+
border: 0;
|
|
305
|
+
}
|
|
306
|
+
/* The close control belongs on the same line as the title, not floated above it. */
|
|
307
|
+
.gala-dialog__close { float: inline-end; margin-inline-start: var(--gala-space-md); }
|
|
107
308
|
|
|
108
309
|
main,
|
|
109
310
|
.gala-page-footer {
|
|
@@ -115,14 +316,19 @@ a { color: var(--gala-color-accent); }
|
|
|
115
316
|
|
|
116
317
|
button {
|
|
117
318
|
min-block-size: 2.75rem;
|
|
118
|
-
padding-inline:
|
|
319
|
+
padding-inline: var(--gala-space-md);
|
|
119
320
|
color: inherit;
|
|
120
|
-
background:
|
|
121
|
-
border:
|
|
321
|
+
background: var(--gala-color-surface);
|
|
322
|
+
border: 1px solid var(--gala-color-border);
|
|
122
323
|
border-radius: var(--gala-radius-control);
|
|
123
324
|
font: inherit;
|
|
325
|
+
font-size: var(--gala-text-sm);
|
|
124
326
|
cursor: pointer;
|
|
327
|
+
transition: background var(--gala-motion-fast) var(--gala-ease),
|
|
328
|
+
border-color var(--gala-motion-fast) var(--gala-ease);
|
|
125
329
|
}
|
|
330
|
+
button:hover { border-color: var(--gala-color-border-strong); background: var(--gala-color-raised); }
|
|
331
|
+
button[disabled] { opacity: 0.55; cursor: not-allowed; }
|
|
126
332
|
|
|
127
333
|
button:focus-visible {
|
|
128
334
|
outline: 0.1875rem solid currentcolor;
|
|
@@ -135,8 +341,9 @@ button:focus-visible {
|
|
|
135
341
|
display: inline-flex;
|
|
136
342
|
align-items: center;
|
|
137
343
|
min-block-size: 2.75rem;
|
|
138
|
-
border:
|
|
344
|
+
border: 1px solid var(--gala-color-border);
|
|
139
345
|
border-radius: var(--gala-radius-control);
|
|
346
|
+
font-size: var(--gala-text-sm);
|
|
140
347
|
}
|
|
141
348
|
|
|
142
349
|
.gala-badge,
|
|
@@ -146,7 +353,7 @@ button:focus-visible {
|
|
|
146
353
|
.gala-section-heading > :where(h2, p) { margin-block: 0 0.5rem; }
|
|
147
354
|
.gala-hero { display: grid; gap: 1.5rem; align-items: center; }
|
|
148
355
|
.gala-hero__image { inline-size: 100%; block-size: auto; border-radius: var(--gala-radius-control); }
|
|
149
|
-
.gala-page-content { max-inline-size:
|
|
356
|
+
.gala-page-content { max-inline-size: var(--gala-measure); }
|
|
150
357
|
.gala-page-content :where(img, video) { max-inline-size: 100%; block-size: auto; }
|
|
151
358
|
.gala-author-profile { display: flex; gap: 1rem; padding: 1rem; background: var(--gala-color-surface); border-radius: var(--gala-radius-control); }
|
|
152
359
|
.gala-author-profile img { border-radius: 50%; object-fit: cover; }
|
|
@@ -156,7 +363,25 @@ button:focus-visible {
|
|
|
156
363
|
.gala-card-index { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); gap: 1rem; padding: 0; list-style: none; }
|
|
157
364
|
[data-layout='portfolio'] .gala-card-index { grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); gap: 1.5rem; }
|
|
158
365
|
[data-layout='portfolio'] .gala-card { padding: clamp(1.25rem, 3vw, 2rem); }
|
|
159
|
-
|
|
366
|
+
/* The surfaces are where `componentStyle` becomes visible: quiet sits on the page, outlined draws
|
|
367
|
+
its edge, raised lifts. One variable decides, so cards and dialogs cannot drift apart. */
|
|
368
|
+
.gala-card {
|
|
369
|
+
block-size: 100%;
|
|
370
|
+
box-sizing: border-box;
|
|
371
|
+
padding: var(--gala-space-lg);
|
|
372
|
+
background: var(--gala-color-surface);
|
|
373
|
+
border: 1px solid var(--gala-surface-border);
|
|
374
|
+
border-radius: var(--gala-radius-surface);
|
|
375
|
+
box-shadow: var(--gala-surface-shadow);
|
|
376
|
+
}
|
|
377
|
+
[data-component-style='raised'] .gala-card { background: var(--gala-color-raised); }
|
|
378
|
+
/* The one place the page moves of its own accord, and so the one place `motion` is legible:
|
|
379
|
+
`subtle` is a short settle, `expressive` a longer one, `none` no movement at all. */
|
|
380
|
+
.gala-card { transition: transform var(--gala-motion-base) var(--gala-ease),
|
|
381
|
+
box-shadow var(--gala-motion-base) var(--gala-ease); }
|
|
382
|
+
.gala-card-index li:hover .gala-card { transform: translateY(-2px); box-shadow: var(--gala-shadow-high); }
|
|
383
|
+
[data-motion='none'] .gala-card { transition: none; }
|
|
384
|
+
[data-motion='none'] .gala-card-index li:hover .gala-card { transform: none; }
|
|
160
385
|
.gala-stats-graph { min-block-size: var(--gala-widget-min-block-size); margin-inline: 0; }
|
|
161
386
|
.gala-stats-graph svg { inline-size: 100%; block-size: 8rem; }
|
|
162
387
|
.gala-stats-graph polyline { fill: none; stroke: var(--gala-color-accent); stroke-width: 2; }
|
|
@@ -171,12 +396,7 @@ button:focus-visible {
|
|
|
171
396
|
.gala-search-results h2 { margin-block-start: 0; }
|
|
172
397
|
.gala-toc { padding: 1rem; background: var(--gala-color-surface); }
|
|
173
398
|
.gala-share__fallback { inline-size: min(100%, 36rem); }
|
|
174
|
-
.gala-engagement { min-block-size: var(--gala-widget-min-block-size); }
|
|
175
|
-
.gala-engagement dl { display: flex; flex-wrap: wrap; gap: 1rem 2rem; }
|
|
176
|
-
.gala-engagement dl > div { display: grid; gap: 0.25rem; }
|
|
177
|
-
.gala-engagement dd { margin: 0; font-size: 1.25rem; font-weight: 700; }
|
|
178
399
|
.gala-engagement__placeholder { display: grid; min-block-size: var(--gala-widget-min-block-size); align-content: center; margin: 0; }
|
|
179
|
-
.gala-engagement-profile { margin-block: 1.5rem; padding: 1rem; background: var(--gala-color-surface); border-radius: var(--gala-radius-control); }
|
|
180
400
|
.gala-engagement-profile > * { margin-block: 0 0.5rem; }
|
|
181
401
|
.gala-comments { display: grid; gap: 1rem; padding-inline-start: 1.5rem; }
|
|
182
402
|
.gala-comments li { padding: 1rem; background: var(--gala-color-surface); border-radius: var(--gala-radius-control); }
|
|
@@ -186,8 +406,6 @@ button:focus-visible {
|
|
|
186
406
|
reassures rather than sells. Hidden for anyone who opened the account dialog deliberately. */
|
|
187
407
|
.gala-account-dialog__invite { margin-block: 0 1rem; max-inline-size: 34rem; }
|
|
188
408
|
.gala-account-dialog__invite[hidden] { display: none; }
|
|
189
|
-
.gala-reaction-actions,
|
|
190
|
-
.gala-comment-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
|
|
191
409
|
.gala-engagement-actions form,
|
|
192
410
|
[data-comment-editor] { display: grid; gap: 0.5rem; max-inline-size: 42rem; }
|
|
193
411
|
.gala-engagement-actions label { display: grid; gap: 0.5rem; }
|
|
@@ -249,3 +467,122 @@ button:focus-visible {
|
|
|
249
467
|
@media (prefers-reduced-motion: no-preference) {
|
|
250
468
|
@view-transition { navigation: auto; }
|
|
251
469
|
}
|
|
470
|
+
|
|
471
|
+
/* ---------------------------------------------------------------- the conversation
|
|
472
|
+
A thread is a hierarchy, and the indent is the only thing that says so. It is drawn with a
|
|
473
|
+
rule rather than padding alone, so five levels deep still reads as five levels and not as an
|
|
474
|
+
accident of margin. */
|
|
475
|
+
.gala-comments-island { margin-block-start: var(--gala-space-xl); }
|
|
476
|
+
.gala-comments__heading {
|
|
477
|
+
font-size: var(--gala-text-lg);
|
|
478
|
+
margin-block-end: var(--gala-space-md);
|
|
479
|
+
}
|
|
480
|
+
.gala-comments, .gala-comment-replies { list-style: none; margin: 0; padding: 0; }
|
|
481
|
+
.gala-comment-replies {
|
|
482
|
+
margin-block-start: var(--gala-space-sm);
|
|
483
|
+
margin-inline-start: var(--gala-space-xs);
|
|
484
|
+
padding-inline-start: var(--gala-space-md);
|
|
485
|
+
border-inline-start: 1px solid var(--gala-color-hairline);
|
|
486
|
+
}
|
|
487
|
+
.gala-comment { padding-block: var(--gala-space-sm); }
|
|
488
|
+
.gala-comment + .gala-comment { border-block-start: 1px solid var(--gala-color-hairline); }
|
|
489
|
+
.gala-comment-replies .gala-comment + .gala-comment { border-block-start: 0; }
|
|
490
|
+
.gala-comment__meta {
|
|
491
|
+
display: flex;
|
|
492
|
+
align-items: baseline;
|
|
493
|
+
gap: var(--gala-space-xs);
|
|
494
|
+
margin-block-end: var(--gala-space-2xs);
|
|
495
|
+
font-size: var(--gala-text-sm);
|
|
496
|
+
}
|
|
497
|
+
.gala-comment__meta strong { font-weight: 600; }
|
|
498
|
+
.gala-comment__pending { font-size: var(--gala-text-xs); color: var(--gala-color-muted); }
|
|
499
|
+
.gala-comment__body { margin-block: 0; overflow-wrap: anywhere; }
|
|
500
|
+
|
|
501
|
+
/* The controls stay out of the way until the comment is worth acting on. */
|
|
502
|
+
.gala-comment-actions {
|
|
503
|
+
display: flex;
|
|
504
|
+
gap: var(--gala-space-2xs);
|
|
505
|
+
margin-block-start: var(--gala-space-2xs);
|
|
506
|
+
opacity: 0.72;
|
|
507
|
+
transition: opacity var(--gala-motion-fast) var(--gala-ease);
|
|
508
|
+
}
|
|
509
|
+
.gala-comment:hover > .gala-comment-actions,
|
|
510
|
+
.gala-comment:focus-within > .gala-comment-actions { opacity: 1; }
|
|
511
|
+
.gala-comment-actions button {
|
|
512
|
+
min-block-size: 2rem;
|
|
513
|
+
padding-inline: var(--gala-space-xs);
|
|
514
|
+
font-size: var(--gala-text-xs);
|
|
515
|
+
background: transparent;
|
|
516
|
+
border-color: transparent;
|
|
517
|
+
color: var(--gala-color-muted);
|
|
518
|
+
}
|
|
519
|
+
.gala-comment-actions button:hover { color: var(--gala-color-text); background: var(--gala-color-surface); }
|
|
520
|
+
|
|
521
|
+
.gala-comment__form { display: grid; gap: var(--gala-space-xs); margin-block: var(--gala-space-sm); }
|
|
522
|
+
.gala-comment__form textarea {
|
|
523
|
+
inline-size: 100%;
|
|
524
|
+
box-sizing: border-box;
|
|
525
|
+
padding: var(--gala-space-sm);
|
|
526
|
+
color: inherit;
|
|
527
|
+
background: var(--gala-color-raised);
|
|
528
|
+
border: 1px solid var(--gala-color-border);
|
|
529
|
+
border-radius: var(--gala-radius-control);
|
|
530
|
+
font: inherit;
|
|
531
|
+
font-size: var(--gala-text-sm);
|
|
532
|
+
line-height: var(--gala-leading-body);
|
|
533
|
+
resize: vertical;
|
|
534
|
+
}
|
|
535
|
+
.gala-comment__form textarea:focus-visible { outline: 2px solid var(--gala-color-accent); outline-offset: 1px; }
|
|
536
|
+
.gala-comment__controls { display: flex; gap: var(--gala-space-xs); }
|
|
537
|
+
.gala-comments__status, .gala-comments__empty, .gala-comments__prompt {
|
|
538
|
+
color: var(--gala-color-muted);
|
|
539
|
+
font-size: var(--gala-text-sm);
|
|
540
|
+
}
|
|
541
|
+
.gala-comments__more { margin-block-start: var(--gala-space-md); }
|
|
542
|
+
|
|
543
|
+
/* ---------------------------------------------------------------- where the article ends
|
|
544
|
+
The writing and the conversation about it are different things, and the page has to say so.
|
|
545
|
+
A footnote used to run straight into the author card with nothing between them. */
|
|
546
|
+
.gala-engagement {
|
|
547
|
+
/* Space is reserved before the counts arrive, so the page does not jump under the reader. */
|
|
548
|
+
min-block-size: var(--gala-widget-min-block-size);
|
|
549
|
+
max-inline-size: var(--gala-content-width);
|
|
550
|
+
margin-block-start: var(--gala-space-xl);
|
|
551
|
+
padding-block-start: var(--gala-space-lg);
|
|
552
|
+
border-block-start: 1px solid var(--gala-color-border);
|
|
553
|
+
}
|
|
554
|
+
.gala-engagement-profile {
|
|
555
|
+
display: flex;
|
|
556
|
+
align-items: baseline;
|
|
557
|
+
gap: var(--gala-space-sm);
|
|
558
|
+
padding: 0;
|
|
559
|
+
background: none;
|
|
560
|
+
}
|
|
561
|
+
.gala-engagement-profile h2 { font-size: var(--gala-text-lg); margin: 0; }
|
|
562
|
+
.gala-engagement-profile p { margin: 0; color: var(--gala-color-muted); font-size: var(--gala-text-sm); }
|
|
563
|
+
|
|
564
|
+
/* Counts read as data, not as three stacked paragraphs. */
|
|
565
|
+
.gala-engagement dl {
|
|
566
|
+
display: flex;
|
|
567
|
+
flex-wrap: wrap;
|
|
568
|
+
gap: var(--gala-space-lg);
|
|
569
|
+
margin-block: var(--gala-space-md);
|
|
570
|
+
}
|
|
571
|
+
.gala-engagement dl > div { display: flex; flex-direction: column-reverse; gap: 0.1rem; }
|
|
572
|
+
.gala-engagement dt {
|
|
573
|
+
font-size: var(--gala-text-xs);
|
|
574
|
+
letter-spacing: var(--gala-tracking-wide);
|
|
575
|
+
text-transform: uppercase;
|
|
576
|
+
color: var(--gala-color-muted);
|
|
577
|
+
}
|
|
578
|
+
.gala-engagement dd {
|
|
579
|
+
margin: 0;
|
|
580
|
+
font-size: var(--gala-text-lg);
|
|
581
|
+
font-variant-numeric: tabular-nums;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
.gala-reaction-actions { display: flex; flex-wrap: wrap; gap: var(--gala-space-2xs); }
|
|
585
|
+
.gala-comment-actions { display: flex; flex-wrap: wrap; gap: var(--gala-space-2xs); }
|
|
586
|
+
.gala-engagement-actions { display: grid; gap: var(--gala-space-sm); justify-items: start; }
|
|
587
|
+
.gala-engagement-actions > [data-follow-article] { inline-size: auto; }
|
|
588
|
+
.gala-share { margin-block-start: var(--gala-space-lg); }
|
package/payload/src/settings.njk
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: layouts/base.njk
|
|
3
|
-
title: Settings
|
|
4
|
-
permalink: /settings/index.html
|
|
5
|
-
---
|
|
6
|
-
<h1>Reader settings</h1>
|
|
7
|
-
<section aria-labelledby="theme-setting">
|
|
8
|
-
<h2 id="theme-setting">Theme</h2>
|
|
9
|
-
<button type="button" data-theme-mode-toggle aria-label="Color mode: system. Activate for light.">Theme: system</button>
|
|
10
|
-
</section>
|
|
11
|
-
<section aria-labelledby="language-setting">
|
|
12
|
-
<h2 id="language-setting">Language preference</h2>
|
|
13
|
-
<p>Your preference highlights matching choices. The language in the page URL always controls the content.</p>
|
|
14
|
-
<label>Preferred language
|
|
15
|
-
<select data-language-preference>
|
|
16
|
-
{% for language in languages %}<option value="{{ language | escape }}">{{ language }}</option>{% endfor %}
|
|
17
|
-
</select>
|
|
18
|
-
</label>
|
|
19
|
-
</section>
|