@gemboss/website-ui 0.9.0 → 0.10.0
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/CHANGELOG.md +50 -0
- package/README.md +2 -2
- package/css/footer.css +74 -58
- package/css/header.css +12 -0
- package/css/tokens.css +2 -2
- package/demo/footer.html +1 -1
- package/docs/components.md +14 -9
- package/docs/markup-contract.md +9 -4
- package/js/website.js +3 -3
- package/js/website.mjs +6 -6
- package/package.json +1 -1
- package/system.json +3 -3
- package/templates/footer.html +11 -9
- package/website.css +89 -61
- package/website.min.css +1 -1
package/templates/footer.html
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Footer: one per site, the same on every page, built from this template (AGENTS.md: brands fill its rows, they never
|
|
3
3
|
invent a footer part). It is the footer of gemboss.ai (0.7.0). In order:
|
|
4
4
|
1. the brand block: logo, one sentence; OPTIONAL the Ask AI row; OPTIONAL the newsletter form (0.6.0)
|
|
5
|
-
2. three to six link columns, each a <details class="gw-footer__fold">: folded rows on phones (
|
|
6
|
-
columns from
|
|
5
|
+
2. three to six link columns, each a <details class="gw-footer__fold">: folded rows on phones (up to 620px), open
|
|
6
|
+
columns from 621px. Headings one or two words in sentence case, four to seven links each.
|
|
7
7
|
3. OPTIONAL product-family rows: a label and two to eight products, name and one line each; repeat the <nav> for a
|
|
8
8
|
second family
|
|
9
9
|
4. the bottom row: copyright, legal links, OPTIONAL theme toggle, social links. Nothing else.
|
|
@@ -11,14 +11,15 @@
|
|
|
11
11
|
Replace every [bracketed] placeholder and delete the optional parts you do not use. website.js wires the folds and
|
|
12
12
|
the toggle; without it the footer still works (the browser folds the <details> by itself).
|
|
13
13
|
|
|
14
|
-
Links that leave the site carry <span class="gw-footer__ext" aria-hidden="true"
|
|
14
|
+
Links that leave the site carry <span class="gw-footer__ext" aria-hidden="true">↗</span> (the glyph, set muted, as
|
|
15
|
+
gemboss.ai writes it; an empty span draws it instead). A link with
|
|
15
16
|
target="_blank" also carries <span class="gw-visually-hidden"> (opens in a new tab)</span>; a link without it does not.
|
|
16
17
|
-->
|
|
17
18
|
<footer class="gw-footer">
|
|
18
19
|
<div class="gw-wrap">
|
|
19
20
|
<div class="gw-footer__grid">
|
|
20
21
|
<div class="gw-footer__brand">
|
|
21
|
-
<a class="gw-brand" href="/"><img class="gw-brand__mark" src="[/logo.svg]" alt="" width="
|
|
22
|
+
<a class="gw-brand" href="/"><img class="gw-brand__mark" src="[/logo.svg]" alt="" width="34" height="34"><span class="gw-brand__name">[Brand]</span></a>
|
|
22
23
|
<p>[One sentence on what the brand does for the reader.]</p>
|
|
23
24
|
<!-- OPTIONAL Ask AI: each link opens an assistant with the same neutral question already typed, URL-encoded after
|
|
24
25
|
?q= (spaces as %20). Ask what the brand is and what it does for the reader, never a leading question. Words,
|
|
@@ -89,7 +90,7 @@
|
|
|
89
90
|
<li><a href="[/blog]">[Blog]</a></li>
|
|
90
91
|
<li><a href="[/docs]">[Docs]</a></li>
|
|
91
92
|
<li><a href="[/page]">[Page title]</a></li>
|
|
92
|
-
<li><a href="[https://another site of the brand]" rel="noopener">[Changelog]<span class="gw-footer__ext" aria-hidden="true"
|
|
93
|
+
<li><a href="[https://another site of the brand]" rel="noopener">[Changelog] <span class="gw-footer__ext" aria-hidden="true">↗</span></a></li>
|
|
93
94
|
</ul>
|
|
94
95
|
</details>
|
|
95
96
|
</nav>
|
|
@@ -114,8 +115,8 @@
|
|
|
114
115
|
<ul>
|
|
115
116
|
<li><a href="[/product]"><b>[Product]</b> <i>[One line on what it is]</i></a></li>
|
|
116
117
|
<li><a href="[/product]"><b>[Product]</b> <i>[One line on what it is]</i></a></li>
|
|
117
|
-
<li><a href="[https://another site of the brand]" rel="noopener"><b>[Product]<span class="gw-footer__ext" aria-hidden="true"
|
|
118
|
-
<li><a href="[https://a sibling brand's site]" target="_blank" rel="noopener"><b>[Product]<span class="gw-footer__ext" aria-hidden="true"
|
|
118
|
+
<li><a href="[https://another site of the brand]" rel="noopener"><b>[Product] <span class="gw-footer__ext" aria-hidden="true">↗</span></b> <i>[One line on what it is]</i></a></li>
|
|
119
|
+
<li><a href="[https://a sibling brand's site]" target="_blank" rel="noopener"><b>[Product] <span class="gw-footer__ext" aria-hidden="true">↗</span></b> <i>[One line on what it is]</i><span class="gw-visually-hidden"> (opens in a new tab)</span></a></li>
|
|
119
120
|
</ul>
|
|
120
121
|
</details>
|
|
121
122
|
</nav>
|
|
@@ -126,7 +127,7 @@
|
|
|
126
127
|
<li><a href="[/terms]">Terms</a></li>
|
|
127
128
|
</ul>
|
|
128
129
|
<!-- OPTIONAL theme toggle: the header's toggle, here instead of (or as well as) in the header -->
|
|
129
|
-
<button class="gw-theme-toggle gw-footer__toggle" type="button" data-gw-theme-toggle aria-label="Switch to dark theme"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><circle cx="12" cy="12" r="
|
|
130
|
+
<button class="gw-theme-toggle gw-footer__toggle" type="button" data-gw-theme-toggle aria-label="Switch to dark theme"><svg class="gw-theme-toggle__moon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M21 12.8A8 8 0 1111.2 3a6 6 0 009.8 9.8z"/></svg><svg class="gw-theme-toggle__sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2M5 5l1.5 1.5M17.5 17.5L19 19M19 5l-1.5 1.5M6.5 17.5L5 19"/></svg></button>
|
|
130
131
|
<ul aria-label="Social">
|
|
131
132
|
<li><a href="[https://social profile]" rel="noopener">[Network]</a></li>
|
|
132
133
|
<li><a href="[https://social profile]" rel="noopener">[Network]</a></li>
|
|
@@ -134,7 +135,8 @@
|
|
|
134
135
|
</div>
|
|
135
136
|
<!-- OPTIONAL wordmark: decoration (aria-hidden="true", the name is already in the brand block). The mark is an
|
|
136
137
|
inline SVG drawn in currentColor, so it takes the faint colour; an <img> cannot, so leave the mark out and keep
|
|
137
|
-
the name. Not shown
|
|
138
|
+
the name. Not shown up to 620px. The mark is 7vw wide; give the <svg> width and height attributes for its
|
|
139
|
+
shape (gemboss.ai's gem: width="86" height="100"). -->
|
|
138
140
|
<div class="gw-footer__wordmark" aria-hidden="true">
|
|
139
141
|
<svg viewBox="[0 0 width height]">[the brand's mark, every fill and stroke "currentColor"]</svg>
|
|
140
142
|
<span>[Brand]</span>
|
package/website.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @gemboss/website-ui 0.
|
|
1
|
+
/*! @gemboss/website-ui 0.10.0 | generated by scripts/build.mjs from the files in css/. Edit those and not this file */
|
|
2
2
|
/* @gemboss/website-ui tokens. GENERATED from system.json by scripts/build.mjs: do not edit by hand. */
|
|
3
3
|
:root {
|
|
4
4
|
color-scheme: light;
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
--gw-surface: #ffffff;
|
|
96
96
|
--gw-ink: #1b1c1e;
|
|
97
97
|
--gw-ink-2: #3b3d42;
|
|
98
|
-
--gw-muted: #
|
|
98
|
+
--gw-muted: #6a6d73;
|
|
99
99
|
--gw-line: #e5e7ea;
|
|
100
100
|
--gw-line-strong: #d5d8dd;
|
|
101
101
|
--gw-line-control: #85888e;
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
--gw-surface: #ffffff;
|
|
188
188
|
--gw-ink: #1b1c1e;
|
|
189
189
|
--gw-ink-2: #3b3d42;
|
|
190
|
-
--gw-muted: #
|
|
190
|
+
--gw-muted: #6a6d73;
|
|
191
191
|
--gw-line: #e5e7ea;
|
|
192
192
|
--gw-line-strong: #d5d8dd;
|
|
193
193
|
--gw-line-control: #85888e;
|
|
@@ -1222,22 +1222,38 @@ html.is-menu-open .gw-header:has(> .gw-mobile-menu.is-drill) { position: sticky;
|
|
|
1222
1222
|
.gw-header__actions > .gw-lang { display: block; }
|
|
1223
1223
|
}
|
|
1224
1224
|
|
|
1225
|
+
/* ---- 0.10.0: the theme toggle's two icons ---------------------------------------------------------------------------
|
|
1226
|
+
A toggle may hold two icons: .gw-theme-toggle__moon, shown in light, and .gw-theme-toggle__sun, shown in dark, as
|
|
1227
|
+
gemboss.ai draws them. The theme in force picks one: data-theme on <html>, else the system's. A toggle with one plain
|
|
1228
|
+
<svg> stays as it is. */
|
|
1229
|
+
.gw-theme-toggle__sun { display: none; }
|
|
1230
|
+
:root[data-theme="dark"] .gw-theme-toggle__sun { display: block; }
|
|
1231
|
+
:root[data-theme="dark"] .gw-theme-toggle__moon { display: none; }
|
|
1232
|
+
@media (prefers-color-scheme: dark) {
|
|
1233
|
+
:root:not([data-theme="light"]) .gw-theme-toggle__sun { display: block; }
|
|
1234
|
+
:root:not([data-theme="light"]) .gw-theme-toggle__moon { display: none; }
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1225
1237
|
/* footer: brand block, link columns, bottom row. One hairline on top, white like the page. */
|
|
1226
1238
|
.gw-footer {
|
|
1227
|
-
padding-block: 64px
|
|
1239
|
+
padding-block: 64px 32px;
|
|
1228
1240
|
border-top: 1px solid var(--gw-line);
|
|
1229
|
-
background:
|
|
1241
|
+
background: transparent;
|
|
1230
1242
|
color: var(--gw-ink);
|
|
1231
1243
|
font-size: 14px;
|
|
1232
1244
|
}
|
|
1233
1245
|
.gw-footer__grid {
|
|
1234
1246
|
display: grid;
|
|
1235
1247
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
1236
|
-
gap: 32px
|
|
1237
|
-
}
|
|
1238
|
-
.gw-footer__brand {
|
|
1239
|
-
.gw-footer__brand
|
|
1240
|
-
.gw-
|
|
1248
|
+
gap: 32px;
|
|
1249
|
+
}
|
|
1250
|
+
.gw-footer__brand p { max-width: 30ch; margin-top: 16px; color: var(--gw-muted); line-height: 22px; }
|
|
1251
|
+
.gw-footer__brand .gw-brand { display: flex; min-height: 34px; font-family: var(--gw-font); line-height: 1.6; }
|
|
1252
|
+
.gw-footer__brand .gw-brand__mark { width: 34px; height: 34px; border-radius: var(--gw-radius-8); }
|
|
1253
|
+
/* the brand's name, the column headings and the wordmark are set in the kit's face (--gw-font), whatever the page
|
|
1254
|
+
does to its body or its h2 (a page in Chinese puts PingFang first; gemboss.ai keeps Inter for these three); a
|
|
1255
|
+
heading is balanced, like gemboss.ai's main pages */
|
|
1256
|
+
.gw-footer__heading { margin: 0 0 12px; color: var(--gw-ink); font-family: var(--gw-font); font-size: 13px; font-weight: 600; letter-spacing: 0; line-height: 1.6; text-wrap: balance; }
|
|
1241
1257
|
/* an optional newsletter form in the brand block (0.6.0): label, the inline row (field and button), a note on what the
|
|
1242
1258
|
reader agrees to; only when the form is wired to a list that keeps the address */
|
|
1243
1259
|
.gw-footer__newsletter { margin-top: 24px; }
|
|
@@ -1250,33 +1266,35 @@ html.is-menu-open .gw-header:has(> .gw-mobile-menu.is-drill) { position: sticky;
|
|
|
1250
1266
|
flex-wrap: wrap;
|
|
1251
1267
|
align-items: center;
|
|
1252
1268
|
justify-content: space-between;
|
|
1253
|
-
gap:
|
|
1254
|
-
margin-top:
|
|
1269
|
+
gap: 12px 24px;
|
|
1270
|
+
margin-top: 32px;
|
|
1255
1271
|
padding-top: 24px;
|
|
1256
1272
|
border-top: 1px solid var(--gw-line);
|
|
1257
1273
|
color: var(--gw-muted);
|
|
1258
1274
|
font-size: 13px;
|
|
1259
1275
|
}
|
|
1260
1276
|
.gw-footer__bottom:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
|
|
1261
|
-
.gw-footer__bottom ul { display: flex; flex-wrap: wrap; gap:
|
|
1277
|
+
.gw-footer__bottom ul { display: flex; flex-wrap: wrap; gap: 16px; margin: 0; padding: 0; list-style: none; }
|
|
1262
1278
|
.gw-footer__bottom a {
|
|
1263
1279
|
display: inline-flex;
|
|
1264
1280
|
align-items: center;
|
|
1265
1281
|
justify-content: center;
|
|
1266
|
-
min-width: 24px;
|
|
1267
|
-
min-height: 24px;
|
|
1268
1282
|
color: var(--gw-muted);
|
|
1269
1283
|
}
|
|
1270
1284
|
.gw-footer__bottom a:hover { color: var(--gw-ink); }
|
|
1271
|
-
@media (
|
|
1272
|
-
.gw-footer__grid {
|
|
1285
|
+
@media (max-width: 620px) {
|
|
1286
|
+
.gw-footer__grid { gap: 24px 20px; }
|
|
1287
|
+
.gw-footer__brand { grid-column: 1 / -1; }
|
|
1273
1288
|
}
|
|
1274
|
-
@media (min-width:
|
|
1275
|
-
.gw-footer__grid { grid-auto-flow: column; grid-template-columns: minmax(0, 1.6fr); grid-auto-columns: minmax(0, 1fr); }
|
|
1276
|
-
.gw-footer__brand { grid-column: auto; }
|
|
1289
|
+
@media (min-width: 1081px) {
|
|
1290
|
+
.gw-footer__grid { grid-auto-flow: column; grid-template-columns: minmax(0, 1.6fr); grid-auto-columns: minmax(0, 1fr); gap: 32px 24px; }
|
|
1277
1291
|
}
|
|
1278
1292
|
@media (max-width: 768px), (pointer: coarse) {
|
|
1293
|
+
.gw-footer__brand .gw-brand { min-height: var(--gw-tap-min); }
|
|
1294
|
+
.gw-footer__col a { display: flex; align-items: center; min-height: var(--gw-tap-min); padding-block: 0; }
|
|
1279
1295
|
.gw-footer__bottom a { min-height: var(--gw-tap-min); }
|
|
1296
|
+
.gw-footer__bottom ul:last-child a { min-width: var(--gw-tap-min); }
|
|
1297
|
+
.gw-footer__bottom ul:not(:last-child) { gap: 8px 16px; }
|
|
1280
1298
|
}
|
|
1281
1299
|
|
|
1282
1300
|
/* ---- 0.7.0: the footer as gemboss.ai has it (issue #71) ---------------------------------------------------------------
|
|
@@ -1290,16 +1308,14 @@ html.is-menu-open .gw-header:has(> .gw-mobile-menu.is-drill) { position: sticky;
|
|
|
1290
1308
|
touch. */
|
|
1291
1309
|
.gw-footer__ask { margin-top: 24px; }
|
|
1292
1310
|
/* the row may run wider than the brand's sentence (four names on one line at 390px) */
|
|
1293
|
-
.gw-
|
|
1294
|
-
.gw-footer__brand:has(> .gw-footer__ask) > :not(.gw-footer__ask) { max-width: 320px; }
|
|
1295
|
-
.gw-footer__ask > .gw-footer__ask-label { margin: 0; color: var(--gw-muted); font-size: 13px; }
|
|
1311
|
+
.gw-footer__ask > .gw-footer__ask-label { margin: 0; color: var(--gw-muted); font-size: 13px; line-height: 22px; }
|
|
1296
1312
|
.gw-footer__ask > ul { display: flex; flex-wrap: wrap; gap: 0 16px; margin: 4px 0 0; padding: 0; list-style: none; }
|
|
1297
1313
|
.gw-footer__ask a { display: block; padding-block: 4px; color: var(--gw-ink); line-height: 20px; }
|
|
1298
|
-
.gw-footer__ask a:hover { text-decoration: underline;
|
|
1314
|
+
.gw-footer__ask a:hover { text-decoration: underline; }
|
|
1299
1315
|
|
|
1300
1316
|
/* the mark after a link that leaves the site (↗, drawn), aria-hidden; the words "(opens in a new tab)" are a separate
|
|
1301
1317
|
.gw-visually-hidden span, only when the link has target="_blank" */
|
|
1302
|
-
.gw-footer__ext {
|
|
1318
|
+
.gw-footer__ext:empty {
|
|
1303
1319
|
display: inline-block;
|
|
1304
1320
|
width: 12px;
|
|
1305
1321
|
height: 12px;
|
|
@@ -1309,6 +1325,7 @@ html.is-menu-open .gw-header:has(> .gw-mobile-menu.is-drill) { position: sticky;
|
|
|
1309
1325
|
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3.5 8.5l5-5M4.5 3.5h4v4' fill='none' stroke='%23000' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 12px no-repeat;
|
|
1310
1326
|
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3.5 8.5l5-5M4.5 3.5h4v4' fill='none' stroke='%23000' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 12px no-repeat;
|
|
1311
1327
|
}
|
|
1328
|
+
.gw-footer__ext:not(:empty) { color: var(--gw-muted); font-weight: 400; }
|
|
1312
1329
|
|
|
1313
1330
|
/* Folds: <details class="gw-footer__fold"> inside a .gw-footer__col (or a .gw-footer__family), its <summary> holding the
|
|
1314
1331
|
.gw-footer__heading, then the <ul>. Below 768px each is a 52px row with a chevron, folded unless the markup says
|
|
@@ -1317,48 +1334,52 @@ html.is-menu-open .gw-header:has(> .gw-mobile-menu.is-drill) { position: sticky;
|
|
|
1317
1334
|
(::details-content; website.js also sets `open` there, for browsers without it). */
|
|
1318
1335
|
.gw-footer__fold > summary { list-style: none; }
|
|
1319
1336
|
.gw-footer__fold > summary::-webkit-details-marker { display: none; }
|
|
1320
|
-
.gw-footer__fold .gw-footer__heading { margin: 0;
|
|
1337
|
+
.gw-footer__fold .gw-footer__heading { margin: 0; }
|
|
1321
1338
|
.gw-footer__fold > ul { margin: 0; padding: 0; list-style: none; }
|
|
1322
1339
|
.gw-footer__col > .gw-footer__fold a { line-height: 20px; }
|
|
1323
|
-
@media (min-width:
|
|
1340
|
+
@media (min-width: 621px) {
|
|
1324
1341
|
.gw-footer__fold > summary { display: contents; }
|
|
1325
1342
|
.gw-footer__col > .gw-footer__fold .gw-footer__heading { margin-bottom: 12px; }
|
|
1326
1343
|
}
|
|
1327
|
-
@media (min-width:
|
|
1344
|
+
@media (min-width: 621px) {
|
|
1328
1345
|
.gw-footer__fold::details-content { content-visibility: visible; }
|
|
1329
1346
|
}
|
|
1330
|
-
@media (max-width:
|
|
1347
|
+
@media (max-width: 620px) {
|
|
1331
1348
|
.gw-footer__grid:has(> .gw-footer__col > .gw-footer__fold) { grid-template-columns: minmax(0, 1fr); row-gap: 0; }
|
|
1332
1349
|
.gw-footer__grid:has(> .gw-footer__col > .gw-footer__fold) > .gw-footer__brand { padding-bottom: 24px; }
|
|
1333
|
-
.
|
|
1350
|
+
/* a column's hairline on top, the last column's below too, a family row's below (gemboss.ai's order: a focused
|
|
1351
|
+
row's ring passes under the next row's line) */
|
|
1352
|
+
.gw-footer__col:has(> .gw-footer__fold) { border-top: 1px solid var(--gw-line); }
|
|
1353
|
+
.gw-footer__col:has(> .gw-footer__fold):last-child,
|
|
1334
1354
|
.gw-footer__family { border-bottom: 1px solid var(--gw-line); }
|
|
1335
|
-
.gw-footer__brand + .gw-footer__col:has(> .gw-footer__fold) { border-top: 1px solid var(--gw-line); }
|
|
1336
1355
|
.gw-footer__fold > summary {
|
|
1337
1356
|
display: flex;
|
|
1338
1357
|
align-items: center;
|
|
1339
1358
|
justify-content: space-between;
|
|
1340
1359
|
gap: 16px;
|
|
1341
|
-
min-height:
|
|
1342
|
-
padding
|
|
1360
|
+
min-height: 52px;
|
|
1361
|
+
padding: 0;
|
|
1343
1362
|
cursor: pointer;
|
|
1344
1363
|
}
|
|
1345
1364
|
.gw-footer__fold > summary::after {
|
|
1346
1365
|
content: "";
|
|
1347
1366
|
flex: none;
|
|
1348
|
-
width:
|
|
1349
|
-
height:
|
|
1350
|
-
|
|
1351
|
-
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1367
|
+
width: 8px;
|
|
1368
|
+
height: 8px;
|
|
1369
|
+
margin-right: 4px;
|
|
1370
|
+
border-right: 2px solid var(--gw-muted);
|
|
1371
|
+
border-bottom: 2px solid var(--gw-muted);
|
|
1372
|
+
rotate: 45deg;
|
|
1373
|
+
translate: 0 -2px;
|
|
1354
1374
|
}
|
|
1355
|
-
.gw-footer__fold[open] > summary::after {
|
|
1375
|
+
.gw-footer__fold[open] > summary::after { rotate: 225deg; translate: 0 2px; }
|
|
1376
|
+
.gw-footer__fold > summary:focus-visible { outline: 2px solid var(--gw-accent); outline-offset: 2px; border-radius: var(--gw-radius-6); }
|
|
1356
1377
|
.gw-footer__fold > ul { padding-bottom: 12px; }
|
|
1357
1378
|
.gw-footer__col > .gw-footer__fold a { display: flex; align-items: center; min-height: var(--gw-tap-min); }
|
|
1358
1379
|
}
|
|
1359
1380
|
/* desktop: the brand's track is as wide as gemboss.ai draws it beside five columns (1.2 parts of 6.2, after five 24px
|
|
1360
1381
|
gaps), whatever the number of columns, so a family row can line up with it; the columns share the rest */
|
|
1361
|
-
@media (min-width:
|
|
1382
|
+
@media (min-width: 1081px) {
|
|
1362
1383
|
.gw-footer__grid:has(> .gw-footer__col > .gw-footer__fold) { grid-template-columns: minmax(0, calc((100% - 120px) * 6 / 31)); }
|
|
1363
1384
|
}
|
|
1364
1385
|
|
|
@@ -1368,6 +1389,8 @@ html.is-menu-open .gw-header:has(> .gw-mobile-menu.is-drill) { position: sticky;
|
|
|
1368
1389
|
the items start where the first column starts. */
|
|
1369
1390
|
.gw-footer__family .gw-footer__heading { color: var(--gw-muted); font-weight: 500; }
|
|
1370
1391
|
.gw-footer__family .gw-footer__fold > ul { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
|
|
1392
|
+
.gw-footer__family .gw-footer__fold > ul > li { display: flex; }
|
|
1393
|
+
.gw-footer__family .gw-footer__fold > ul > li > a { flex: 1 1 auto; }
|
|
1371
1394
|
.gw-footer__family a {
|
|
1372
1395
|
display: flex;
|
|
1373
1396
|
flex-direction: column;
|
|
@@ -1381,14 +1404,18 @@ html.is-menu-open .gw-header:has(> .gw-mobile-menu.is-drill) { position: sticky;
|
|
|
1381
1404
|
.gw-footer__family a:hover { background: var(--gw-bg-soft); }
|
|
1382
1405
|
.gw-footer__family b { font-size: 14px; font-weight: 600; line-height: 20px; }
|
|
1383
1406
|
.gw-footer__family i { color: var(--gw-muted); font-size: 13px; font-style: normal; line-height: 18px; }
|
|
1384
|
-
@media (min-width:
|
|
1407
|
+
@media (min-width: 621px) {
|
|
1385
1408
|
.gw-footer__family { margin-top: 48px; padding-top: 32px; border-top: 1px solid var(--gw-line); }
|
|
1386
1409
|
.gw-footer__family .gw-footer__heading { margin-bottom: 12px; }
|
|
1387
|
-
.gw-footer__family .gw-footer__fold > ul { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px 16px;
|
|
1410
|
+
.gw-footer__family .gw-footer__fold > ul { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px 16px; }
|
|
1388
1411
|
.gw-footer__family a { min-height: 0; padding: 8px 12px; }
|
|
1389
1412
|
.gw-footer__family + .gw-footer__bottom { margin-top: 32px; }
|
|
1390
1413
|
}
|
|
1391
|
-
@media (min-width:
|
|
1414
|
+
@media (min-width: 621px) and (max-width: 768px) {
|
|
1415
|
+
.gw-footer__family a { min-height: var(--gw-tap-min); }
|
|
1416
|
+
}
|
|
1417
|
+
@media (min-width: 1081px) {
|
|
1418
|
+
.gw-footer__family .gw-footer__fold > ul { margin-left: -12px; }
|
|
1392
1419
|
.gw-footer__family { display: flow-root; }
|
|
1393
1420
|
.gw-footer__family .gw-footer__heading { float: left; width: calc((100% - 120px) * 6 / 31); margin: 8px 0 0; }
|
|
1394
1421
|
.gw-footer__family .gw-footer__fold > ul { margin-left: calc((100% - 120px) * 6 / 31 + 12px); }
|
|
@@ -1396,7 +1423,7 @@ html.is-menu-open .gw-header:has(> .gw-mobile-menu.is-drill) { position: sticky;
|
|
|
1396
1423
|
|
|
1397
1424
|
/* The theme toggle in the bottom row (.gw-theme-toggle with data-gw-theme-toggle, wired like the header's): a 32px
|
|
1398
1425
|
square with one hairline, its hit area 40px, 44px on touch. It pushes itself and the social links to the right.
|
|
1399
|
-
|
|
1426
|
+
Up to 620px the copyright and the toggle share the first line, legal and social links the second. */
|
|
1400
1427
|
.gw-footer__toggle {
|
|
1401
1428
|
position: relative;
|
|
1402
1429
|
width: 32px;
|
|
@@ -1407,12 +1434,15 @@ html.is-menu-open .gw-header:has(> .gw-mobile-menu.is-drill) { position: sticky;
|
|
|
1407
1434
|
}
|
|
1408
1435
|
.gw-footer__toggle::after { content: ""; position: absolute; inset: -5px; }
|
|
1409
1436
|
.gw-footer__toggle svg { width: 18px; height: 18px; }
|
|
1437
|
+
/* on hover the hairline turns ink and the icon the accent, the ground stays (gemboss.ai's); colour only, 0.15s */
|
|
1438
|
+
.gw-footer__toggle { transition: border-color 0.15s, color 0.15s; }
|
|
1439
|
+
.gw-footer__toggle:hover { border-color: var(--gw-ink); background: var(--gw-surface); color: var(--gw-accent); }
|
|
1410
1440
|
@media (max-width: 768px), (pointer: coarse) {
|
|
1411
1441
|
.gw-footer__toggle { width: var(--gw-tap-min); height: var(--gw-tap-min); }
|
|
1412
1442
|
}
|
|
1413
|
-
@media (max-width:
|
|
1414
|
-
.gw-footer__bottom:has(> .gw-footer__toggle) {
|
|
1415
|
-
.gw-footer__bottom:has(> .gw-footer__toggle) > :first-child { flex: 1 1 calc(100% -
|
|
1443
|
+
@media (max-width: 620px) {
|
|
1444
|
+
.gw-footer__bottom:has(> .gw-footer__toggle) { gap: 8px 16px; }
|
|
1445
|
+
.gw-footer__bottom:has(> .gw-footer__toggle) > :first-child { flex: 1 1 calc(100% - 64px); }
|
|
1416
1446
|
.gw-footer__bottom > .gw-footer__toggle { order: 1; margin: 0; }
|
|
1417
1447
|
.gw-footer__bottom:has(> .gw-footer__toggle) > ul { order: 2; }
|
|
1418
1448
|
.gw-footer__family + .gw-footer__bottom,
|
|
@@ -1422,39 +1452,37 @@ html.is-menu-open .gw-header:has(> .gw-mobile-menu.is-drill) { position: sticky;
|
|
|
1422
1452
|
/* The wordmark: the brand's mark and name, large and faint, the footer's last line. Decoration (aria-hidden="true"):
|
|
1423
1453
|
the name is already in the brand block. Its size follows the viewport (--gw-display-wordmark) and it never makes the
|
|
1424
1454
|
page scroll sideways: a name too long for the line is cut. The mark is drawn in currentColor (an inline SVG); an
|
|
1425
|
-
<img> mark keeps its own colours, so leave it out and keep the name.
|
|
1426
|
-
|
|
1427
|
-
|
|
1455
|
+
<img> mark keeps its own colours, so leave it out and keep the name. Values are gemboss.ai's, 1:1 (Chris 26/10/2026):
|
|
1456
|
+
weight 800, 48px above, nothing below but the footer's own 32px, the mark 7vw wide (40–96px), hidden up to 620px.
|
|
1457
|
+
The footer is not painted (transparent on the page), so the breathing gate reads it as part of the page. */
|
|
1428
1458
|
.gw-footer__wordmark {
|
|
1429
1459
|
display: flex;
|
|
1430
1460
|
align-items: center;
|
|
1431
1461
|
justify-content: center;
|
|
1432
1462
|
gap: 24px;
|
|
1433
|
-
padding-block: 48px
|
|
1463
|
+
padding-block: 48px 0;
|
|
1434
1464
|
color: color-mix(in srgb, var(--gw-ink) 10%, transparent);
|
|
1465
|
+
font-family: var(--gw-font);
|
|
1435
1466
|
font-size: var(--gw-display-wordmark);
|
|
1436
|
-
font-weight:
|
|
1467
|
+
font-weight: 800;
|
|
1437
1468
|
letter-spacing: var(--gw-display-tracking);
|
|
1438
1469
|
line-height: 1;
|
|
1439
1470
|
white-space: nowrap;
|
|
1440
1471
|
user-select: none;
|
|
1441
1472
|
}
|
|
1442
1473
|
.gw-footer__wordmark > svg,
|
|
1443
|
-
.gw-footer__wordmark > img { flex: none; width:
|
|
1474
|
+
.gw-footer__wordmark > img { flex: none; width: clamp(40px, 7vw, 96px); height: auto; }
|
|
1444
1475
|
.gw-footer__wordmark > span { min-width: 0; overflow-x: clip; }
|
|
1445
|
-
@media (max-width:
|
|
1446
|
-
@media (max-width:
|
|
1476
|
+
@media (max-width: 640px) { .gw-footer__wordmark { gap: 16px; } }
|
|
1477
|
+
@media (max-width: 620px) { .gw-footer__wordmark { display: none; } }
|
|
1447
1478
|
|
|
1448
1479
|
@media (max-width: 768px), (pointer: coarse) {
|
|
1449
1480
|
.gw-footer__ask a { display: flex; align-items: center; min-height: var(--gw-tap-min); padding-block: 0; }
|
|
1450
1481
|
}
|
|
1451
|
-
@media (prefers-reduced-motion: reduce) {
|
|
1452
|
-
.gw-footer__fold > summary::after { transition: none; }
|
|
1453
|
-
}
|
|
1454
1482
|
/* a forced-colours screen drops backgrounds: draw the chevron and the ↗ in its text colour */
|
|
1455
1483
|
@media (forced-colors: active) {
|
|
1456
|
-
.gw-footer__ext
|
|
1457
|
-
.gw-footer__fold > summary::after {
|
|
1484
|
+
.gw-footer__ext:empty { forced-color-adjust: none; background: CanvasText; }
|
|
1485
|
+
.gw-footer__fold > summary::after { border-color: CanvasText; }
|
|
1458
1486
|
}
|
|
1459
1487
|
|
|
1460
1488
|
/* sections: hero, logos, stats, features, split, showcase, steps, quote, pricing, CTA. */
|