clairity.css 0.1.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,7 @@
2
2
  BASE - these are the base styles for *all* elements and certain core pseudo-
3
3
  elments / -classes. for simple sites this stylesheet plus variables.css
4
4
  (where :root vars & color-scheme: light dark; are set) should suffice.
5
-
5
+
6
6
  Note that simple & full :is() support (without multiple declarations)
7
7
  only landed broadly in ~Jan 2020. With it came :where() support, and
8
8
  both now have forgiving selector lists. Since we're already implcitly
@@ -11,13 +11,17 @@
11
11
 
12
12
  specificity is a 4-element designation:
13
13
  [inline, #id, .class/[attr]/:pseudo-class, element/::pseudo-element]
14
-
14
+
15
15
  we'll generally shoot for [0001] specificity in this base.css file,
16
16
  with a few notable exceptions, like button-type input elements and
17
17
  [multiple] selects, and relegate higher specificity niceties to the
18
18
  states.css stylesheet. exceptions have [0010] or [0011] specificity.
19
-
20
- Quickly search for elements using hashtag syntax, e.g., #a for anchors.
19
+
20
+ Quickly search for elements using hashtag syntax, e.g., #a for anchors,
21
+ reducing unwanted matches and better narrowing in on what you searched.
22
+
23
+ NOTE that a <meta charset="utf-8"> declaration is needed to get certain
24
+ non-Latin glyphs (like open-quote in blockquotes) to render correctly.
21
25
 
22
26
  A few key styles from normalize.css are repeated here, and marked as
23
27
  such via comments, in case normalize.css is not being used.
@@ -115,7 +119,7 @@ noscript { }
115
119
  /* container queries - default names/types for common container elements -
116
120
  EXPERIMENTAL - only safari 16+ & chrome 93+ behind a flag for now
117
121
  // .......................................................................... */
118
- main, aside, article, nav, section, header, footer {
122
+ main, aside, article, nav, section, form, header, footer {
119
123
  container-type: inline-size;
120
124
  /*font-size: clamp(1rem, 1rem + 1cqi, 2rem);*/
121
125
  }
@@ -124,6 +128,7 @@ aside { container-name: aside; }
124
128
  article { container-name: article; }
125
129
  nav { container-name: nav; }
126
130
  section { container-name: section; }
131
+ form { container-name: form; }
127
132
  header { container-name: header; }
128
133
  footer { container-name: footer; }
129
134
 
@@ -404,7 +409,9 @@ button, [type="button"],[type="submit"],[type="reset"], ::file-selector-button {
404
409
  padding: 0 var(--m);
405
410
  border: var(--solid) var(--transparent);
406
411
  border-radius: var(--radius);
412
+
407
413
  /*vertical-align: bottom;*/
414
+ grid-column: elements;
408
415
  }
409
416
  /* #reset */
410
417
  [type="reset"] { /* [0010] specificity */
@@ -413,6 +420,10 @@ button, [type="button"],[type="submit"],[type="reset"], ::file-selector-button {
413
420
  border-color: var(--foreground);
414
421
  }
415
422
 
423
+ ::file-selector-button {
424
+ min-height: calc(var(--height) - var(--xs));
425
+ }
426
+
416
427
 
417
428
  /* -----------------------------------------------------------------------------
418
429
  // #selections - dropdown/selection form controls
@@ -521,6 +532,8 @@ select, optgroup, option {
521
532
  border: none;
522
533
  }
523
534
 
535
+ [type="file"] { padding-inline-start: 0; }
536
+
524
537
  /* #::-webkit-calendar-picker-indicator -a webkit picker pseudo-element-[0001]*/
525
538
  ::-webkit-calendar-picker-indicator {
526
539
  display: none;
@@ -901,7 +914,7 @@ hr, hr:hover {
901
914
  margin: var(--l) auto;
902
915
  max-width: var(--width);
903
916
  width: 50%;
904
- grid-column: 1 / -1; /* span full width of a enclosing grid */
917
+ grid-column: 1 / -1; /* span full width of an enclosing grid */
905
918
  }
906
919
 
907
920
  /* #disabled - needs to be last to "beat" the other [0010] specificity rules
@@ -20,12 +20,6 @@ CLASSES - Here is where we first deviate from the classless CSS directive. We'll
20
20
  // #containers -
21
21
  // -------------------------------------------------------------------------- */
22
22
 
23
- /* this doesn't work because some items aren't full width, like asides
24
- body > *:not(.fluid) {
25
- margin-inline: var(--m);
26
- }
27
- */
28
-
29
23
  /* for constraining width to a reasonable line length - keep in sync
30
24
  with sectioning children of the body element in components.css */
31
25
  .readable {
@@ -38,52 +32,43 @@ body > *:not(.fluid) {
38
32
  ._100vw, [class~="100vw"] {
39
33
  width: 100vw;
40
34
  max-width: 100vw; /* still has horizontal scrollbar issues */
41
- margin-inline: calc(50% - 50vw - var(--xs));/*neg. margin if needed*/
35
+ margin-inline: calc(50% - 50vw); /* neg. margin where necessary */
42
36
  }
43
37
 
44
- /* #100dvi - dynamic full width of the viewport */
38
+ /* #100dvi - full dynamic viewport width - unfortunately doesn't account for
39
+ scrollbars, so its utility for full-bleed breakouts is severely limited
40
+ ...........................................................................*/
45
41
  ._100dvi, [class~="100dvi"] {
46
42
  width: 100dvi;
47
43
  max-width: 100dvi; /* still has horizontal scrollbar issues */
48
- margin-inline: calc(50% - 50dvi - var(--xs));/*neg margin if needed*/
44
+ margin-inline: calc(50% - 50dvi); /* neg. margin where necessary */
49
45
  }
50
46
 
51
47
 
52
48
  /* -----------------------------------------------------------------------------
53
- // #grid helpters -
49
+ // #grid - subgrid is ff 71+ & safari 16+ only, chrome/edge in dev - 20230423
54
50
  // -------------------------------------------------------------------------- */
55
51
 
56
- /* .subgrid extends grid into descendents - firefox 71+ & safari 16+ only, no
57
- chrome/edge yet - EXPERIMENTAL
52
+ /* .subgrid extends grid into descendents - EXPERIMENTAL
58
53
  ...........................................................................*/
59
54
  .subgrid {
60
- grid-column: padded; /* place subgrid on the parent grid */
61
- display: inherit; /* inherits grid, otherwise no subgrid */
62
- grid-template-columns: subgrid; /* only subgrid columns */
63
- gap: inherit; /* inherit parent grid gap */
64
- max-width: unset; /* let parent grid dictate width */
55
+ grid-column: padded; /* place subgrid on the parent grid */
56
+ display: inherit; /* inherits grid, otherwise no subgrid */
57
+ grid-template-columns: subgrid; /* only subgrid columns */
58
+ gap: inherit; /* inherit parent grid gap */
59
+ max-width: unset; /* let parent grid dictate width */
65
60
  }
66
61
 
67
- /* HACK: chrome & edge do not yet support subgrid as of 20221001 */
68
- @supports not (grid-template-columns: subgrid) {
69
- .subgrid { display: contents; }
70
- .subgrid :first-child { /* TODO: this breaks some layouts, like banner images */
71
- /*grid-column-start: 2;*/ /* TODO: fix right side guttering too */
72
- }}
73
-
74
62
  /* span the full width of the grid
75
63
  .......................................................................... */
76
64
  .full {
77
- /*grid-column: full;*/
78
- grid-column: 1 / -1;
79
- max-width: none; /* remove other width restrictions */
65
+ grid-column: 1 / -1; /* more foolproof than `full` grid area */
66
+ /*max-width: none;*/ /* interferes with .full in .subgrid */
80
67
  }
81
68
 
82
69
  /* span all but the 1st & last grid columns
83
70
  .......................................................................... */
84
- .padded {
85
- grid-column: 2 / -2;
86
- }
71
+ .padded { grid-column: 2 / -2; } /* 1st/last columns are typically padding */
87
72
 
88
73
 
89
74
  /* -----------------------------------------------------------------------------
@@ -132,27 +117,14 @@ body > *:not(.fluid) {
132
117
 
133
118
 
134
119
  /* -----------------------------------------------------------------------------
135
- // #colors - provide a set of utility color classes where the --color variable
136
- // is employed - EXPERIMENTAL
120
+ // #colors - semantic classes for setting the --color variable - EXPERIMENTAL
137
121
  // -------------------------------------------------------------------------- */
138
122
 
139
- /* semantic colors for states */
123
+ /* semantic colors for icon states */
140
124
  .valid { --color: var(--valid); }
141
125
  .invalid { --color: var(--invalid); }
142
126
  .unknown { --color: var(--unknown); }
143
127
 
144
- .red { --color: var(--error); }
145
- .orange { --color: var(--error); }
146
- .yellow { --color: var(--warning); }
147
- .lime { --color: var(--error); }
148
- .green { --color: var(--success); }
149
- .aqua { --color: var(--error); }
150
- .blue { --color: var(--info); }
151
- .indigo { --color: var(--error); }
152
- .purple { --color: var(--error); }
153
- .violet { --color: var(--error); }
154
- .magenta { --color: var(--error); }
155
-
156
128
 
157
129
  /* -----------------------------------------------------------------------------
158
130
  // #backgrounds -
@@ -160,79 +132,27 @@ body > *:not(.fluid) {
160
132
 
161
133
  /* https://css-tricks.com/background-patterns-simplified-by-conic-gradients/ */
162
134
  .checkerboard {
163
- background: repeating-conic-gradient(var(--neutral) 0% 25%,
164
- transparent 0% 50%) 50% / 20px 20px;
135
+ background: repeating-conic-gradient(var(--neutral) 0% 25%,
136
+ transparent 0% 50%) 50% / 20px 20px;
165
137
  }
166
138
 
167
- /* -----------------------------------------------------------------------------
168
- // #spacing -
169
- // -------------------------------------------------------------------------- */
170
-
171
- /* for inserting an icon using the background-blend-mode technique */
172
- .icon {
173
- display: inline-block;
174
- padding-right: var(--inline-padding);
175
- background-size: var(--text-icon);
176
- background-position: var(--center-right);
177
- background-blend-mode: lighten, normal;
178
- }
179
-
180
- /* leading space for inline ::before elements, typically icons */
181
- .leading {
182
- padding-left: var(--inline-padding);
183
- }
184
-
185
- /* trailing space for inline ::after elements, typically icons */
186
- .trailing {
187
- padding-right: var(--inline-padding);
188
- }
189
139
 
190
140
  /* -----------------------------------------------------------------------------
191
141
  // #layout -
192
142
  // -------------------------------------------------------------------------- */
193
143
 
194
- /* a grid with columns of width var(--column)
195
- // .......................................................................... */
196
- .grid {
197
- display: grid;
198
- grid-template-columns: [full-start] repeat(auto-fit,
199
- minmax(var(--column), 1fr)) [full-end];
200
- column-gap: var(--m);
201
- container-type: none; /* containment clashes with grid on safari */
202
- }
203
-
204
144
  /* main content placement in the holy grail 3-column grid
145
+ // firefox is not forgiving with :has() rules, so this must be separated out
205
146
  // .......................................................................... */
206
- /* firefox is not forgiving with :has() rules, so this must be separated out */
207
147
  .dual-aside { grid-column: 2 / -2; }
208
148
 
209
149
 
210
- /* a basic flex container
211
- ............................................................................ */
212
- .flex {
213
- --flex-break: 100rem; /* TODO/TEMP - a bit of a magical number */
214
- display: flex;
215
- flex-wrap: wrap;
216
- gap: var(--m);
217
- }
218
-
219
- /* flex all the children of .flex to single column below --flex-break */
220
- :where(.flex) > * { /* [0000] specificity */
221
- flex-grow: 1;
222
- flex-basis: calc((var(--flex-break) - 100%) * 999);
223
- }
224
-
225
- .flex > :where(.column, .main) {
226
- /*flex: 1 1 auto;*/
227
- }
228
-
229
-
230
150
  /* -----------------------------------------------------------------------------
231
151
  // #breaks - #br #wbr #hr - line breaks and the horizontal rule
232
152
  // -------------------------------------------------------------------------- */
233
153
 
234
- /* #hr #section - the sectioning horizontal rule - [0011] specificity */
235
- hr.section {
154
+ /* #sectioning - a significant break between sections */
155
+ .sectioning {
236
156
  height: 3rem;
237
157
  margin: auto;
238
158
  width: unset;
@@ -247,9 +167,26 @@ hr.section {
247
167
 
248
168
 
249
169
  /* -----------------------------------------------------------------------------
250
- // #icons - convenience classes for icons defined in icons.css - EXPERIMENTAL
170
+ // #icons - helper classes for icons - EXPERIMENTAL
251
171
  // -------------------------------------------------------------------------- */
252
172
 
173
+ /* for inserting an icon using the background-blend-mode technique */
174
+ .icon {
175
+ display: inline-block;
176
+ padding-right: var(--inline-padding);
177
+ background-size: var(--text-icon);
178
+ background-position: var(--center-right);
179
+ background-blend-mode: lighten, normal;
180
+ }
181
+
182
+ /* leading/trailing space for inline ::before elements, typically icons
183
+ // TODO: investigate using :has() for this on the parent of .icon
184
+ // ........................................................................... */
185
+ .leading { padding-left: var(--inline-padding); }
186
+ .trailing {padding-right: var(--inline-padding); }
187
+
188
+ /* convenience classes for icons defined in icons.css
189
+ // ........................................................................... */
253
190
  .i-burger { --icon: var(--i-burger); }
254
191
  .i-check { --icon: var(--i-check); }
255
192
  .i-chevron { --icon: var(--i-chevron); }
@@ -261,11 +198,13 @@ hr.section {
261
198
  .i-mail-x { --icon: var(--i-mail-x); }
262
199
  .i-send { --icon: var(--i-send); }
263
200
  .i-server-cog { --icon: var(--i-server-cog); }
201
+ .i-settings { --icon: var(--i-settings); }
264
202
  .i-trash { --icon: var(--i-trash); }
265
203
  .i-user-circle { --icon: var(--i-user-circle); }
266
204
  .i-user-off { --icon: var(--i-user-off); }
267
205
 
268
- /* #unadorned removes a ::before or ::after icon - [0011] specificity */
206
+ /* removes a ::before or ::after icon - [0011] specificity
207
+ // ........................................................................... */
269
208
  .unadorned::before, .unadorned::after {
270
209
  content: unset;
271
210
  }
@@ -9,22 +9,22 @@
9
9
  // -------------------------------------------------------------------------- */
10
10
 
11
11
  /* #body - auto-grid by default - overrides base.css default body definition.
12
- set --columns to the number of columns desired */
12
+ set --columns to the number of columns desired
13
+ // .......................................................................... */
13
14
  body {
14
15
  display: grid;
15
16
  grid-template-columns: [full-start] var(--padding, var(--m))
16
17
  [padded-start] repeat(var(--columns, auto-fit),
17
18
  minmax(var(--grid), 1fr)) [padded-end]
18
19
  var(--padding, var(--m)) [full-end];
19
- column-gap: var(--gap); /* flexible between 400 - 800px */
20
+ column-gap: var(--gap); /* --gap is fluid between 400 - 800px */
20
21
  max-width: unset;
21
22
  }
22
23
 
23
24
  /* some containers should span full or padded width by default if in the grid */
24
- :where(:not(.grid)) > main { grid-column: padded; }
25
- nav, header, footer {
26
- grid-column: full;
27
- }
25
+ :where(:not(.grid)) > main { grid-column: padded; }
26
+ nav, header, footer { grid-column: full; }
27
+
28
28
 
29
29
  /* the top header typically should sit flush to the top of the page and use
30
30
  padding; TODO: this seems to be over-specified */
@@ -39,11 +39,39 @@ footer {
39
39
  grid-auto-rows: min-content; /* don't unnecessarily expand rows */
40
40
  column-gap: var(--m);
41
41
  container-type: unset; /* safari doesn't like contain with grid */
42
- padding-inline: var(--padding, var(--m)); /* flexible padding */
42
+ /*padding-inline: var(--padding, var(--m));*/ /* flexible padding */
43
43
  }
44
44
 
45
45
  footer > p { grid-column: 1 / -1; } /* take up a whole row in the grid */
46
46
 
47
+ /* HACK: because .100dvi uses a negative margin hack to break out of the parent
48
+ container and extra negative margin to compensate for the vertical scrollbar,
49
+ the content needs more padding on narrower screens to stay visible */
50
+ body > footer:last-of-type:is(._100dvi, [class~="100dvi"]) {
51
+ margin-inline: calc(50% - 50dvi - var(--s));
52
+ padding-inline: var(--m) var(--s); /* asymmetric due to neg. margin;
53
+ centers because --m is twice --s & --s used above */
54
+ }
55
+
56
+ /* a basic flex container
57
+ // .......................................................................... */
58
+ .flex {
59
+ --flex-break: 100rem; /* TODO/TEMP - a bit of a magical number */
60
+ display: flex;
61
+ flex-wrap: wrap;
62
+ gap: var(--m);
63
+ }
64
+
65
+ /* flex all the children of .flex to single column below --flex-break */
66
+ :where(.flex) > * { /* [0000] specificity */
67
+ flex-grow: 1;
68
+ flex-basis: calc((var(--flex-break) - 100%) * 999);
69
+ }
70
+
71
+ .flex > :where(.column, .main) {
72
+ /*flex: 1 1 auto;*/
73
+ }
74
+
47
75
 
48
76
  /* -----------------------------------------------------------------------------
49
77
  // #headings -
@@ -53,13 +81,14 @@ header:not(.banner) {
53
81
  display: flex;
54
82
  flex-wrap: wrap;
55
83
  justify-content: space-between;
84
+ align-items: baseline; /* make sure flexed text lines up visually*/
56
85
  }
57
86
 
58
- header :where(h1,h2,h3,h4,h5,h6) {
59
- }
87
+ /*header :where(h1,h2,h3,h4,h5,h6) { ??? }*/
60
88
 
61
- header :where(p) {
62
- flex: 1 0 100%;
89
+ /* use <span>, not <p>, for text that sits alongside a heading within a header*/
90
+ header :where(p, .subtitle) {
91
+ flex: 1 0 100%; /* flex to a full row, forcing a line wrap*/
63
92
  }
64
93
 
65
94
 
@@ -91,7 +120,8 @@ header :where(p) {
91
120
  grid-column: unset;
92
121
  flex-direction: column;
93
122
  flex-grow: 1; /* take up the whole role if orphaned */
94
- flex-basis: calc((40vw - 100%) * 999);
123
+ /* flex-basis unnecessary? seems to wrap weirdly at larger viewport widths */
124
+ /*flex-basis: calc((40vw - 100%) * 999);*/
95
125
  align-items: start; /* some items will float otherwise */
96
126
  row-gap: var(--s); /* add some vertical spacing */
97
127
  justify-content: start;
@@ -139,7 +169,7 @@ header :where(p) {
139
169
 
140
170
 
141
171
  /* -----------------------------------------------------------------------------
142
- // #icons - svg icons
172
+ // #i #icons - standalone svg icons
143
173
  // -------------------------------------------------------------------------- */
144
174
 
145
175
  i[class^='i-'] {
@@ -165,6 +195,7 @@ i[class^='i-'] {
165
195
  grid-template-areas: "banner";
166
196
  place-items: center;
167
197
  align-self: flex-start;
198
+ max-width: unset; /* override header max-width in cosmetic.css */
168
199
  height: var(--banner-height);
169
200
  /*max-height: var(--banner-max-height);*/
170
201
  /*background-color: var(--primary-transparent);*/ /* bg color was meant
@@ -179,21 +210,28 @@ i[class^='i-'] {
179
210
  /* banner #content - constrain content width with a css variable set on parent*/
180
211
  .banner .content {
181
212
  width: var(--content-width);
213
+ max-width: 100dvi; /* don't let content overflow viewport */
182
214
  z-index: 0; /* safari uses source order otherwise */
183
215
  }
184
216
 
185
217
  /* banner grid */
186
218
  .banner > * { grid-area: banner; }
187
219
  .banner > nav {
188
- place-self: start center;
220
+ place-self: flex-start center;
189
221
  width: var(--line-length);
222
+ max-width: 100dvi; /* make sure nav doesn't go off-screen */
190
223
  }
191
224
  .banner nav menu { /*flex: auto;*/ }
192
225
 
226
+ /* TODO: use fluid padding on non-hero children rather than container query? */
227
+ @container (width <= 50rem) {
228
+ .banner > :not(img, .hero) { padding-inline: var(--s); }
229
+ }
230
+
193
231
  .banner > img, .hero {
194
232
  height: min(var(--banner-height), var(--banner-max-height));
195
233
  width: 100%;
196
- max-width: none;
234
+ max-width: none; /* TODO: should this be broken out separately?*/
197
235
  z-index: -1;
198
236
  }
199
237
 
@@ -220,8 +258,9 @@ i[class^='i-'] {
220
258
  // #alert - the alert flash message box for providing timely info to the user
221
259
  // -------------------------------------------------------------------------- */
222
260
 
261
+ /* TODO: rather than an .alert class, use [role="alert"] by default */
223
262
  /* #alert - the default alert box is an info box */
224
- .alert {
263
+ [role="alert"] {
225
264
  color: var(--info);
226
265
  background-color: var(--bg-info);
227
266
  border: var(--solid) var(--info-low);
@@ -232,7 +271,7 @@ i[class^='i-'] {
232
271
  }
233
272
 
234
273
  /* #headers - a single header style since alerts only need 1 header typically */
235
- .alert :where(h1,h2,h3,h4,h5,h6) {
274
+ [role="alert"] :where(h1,h2,h3,h4,h5,h6) {
236
275
  color: var(--info-low);
237
276
  font-size: var(--large);
238
277
  font-weight: var(--bold);
@@ -240,24 +279,24 @@ i[class^='i-'] {
240
279
  }
241
280
 
242
281
  /* #success #warning #error #alert - other alert types get their own colors */
243
- .success.alert {
282
+ [role="alert"].success {
244
283
  color: var(--success);
245
284
  background-color: var(--bg-success);
246
285
  border: var(--solid) var(--success-low);
247
286
  }
248
- .warning.alert {
287
+ [role="alert"].warning {
249
288
  color: var(--warning);
250
289
  background-color: var(--bg-warning);
251
290
  border: var(--solid) var(--warning-low);
252
291
  }
253
- .error.alert {
292
+ [role="alert"].error {
254
293
  color: var(--error);
255
294
  background-color: var(--bg-error);
256
295
  border: var(--solid) var(--error-low);
257
296
  }
258
- .success.alert :where(h1,h2,h3,h4,h5,h6) { color: var(--success-low); }
259
- .warning.alert :where(h1,h2,h3,h4,h5,h6) { color: var(--warning-low); }
260
- .error.alert :where(h1,h2,h3,h4,h5,h6) { color: var(--error-low); }
297
+ [role="alert"].success :where(h1,h2,h3,h4,h5,h6) { color: var(--success-low); }
298
+ [role="alert"].warning :where(h1,h2,h3,h4,h5,h6) { color: var(--warning-low); }
299
+ [role="alert"].error :where(h1,h2,h3,h4,h5,h6) { color: var(--error-low); }
261
300
 
262
301
 
263
302
  /* -----------------------------------------------------------------------------
@@ -316,6 +355,7 @@ body > nav a, body > header > nav a {
316
355
  outline: none;
317
356
  border: none;
318
357
  width: var(--height); /* form icons are square */
358
+ max-width: 100cqi;
319
359
  min-width: 0;
320
360
  padding: 0;
321
361
  cursor: pointer; /* unconventional usage for 'clickable' */
@@ -457,26 +497,26 @@ menu > li > button, menu > li > button:hover {
457
497
  /* #secondary #button - less emphasized than the standard button
458
498
  // .......................................................................... */
459
499
 
460
- button.secondary, .secondary.button { /* [0011] / [0020] specificity */
500
+ button.secondary, .secondary.button, .secondary::file-selector-button { /* [0011] / [0020] specificity */
461
501
  color: var(--foreground); /* invert foreground/background */
462
502
  background-color: var(--background); /* invert foreground/background */
463
503
  border-color: var(--foreground);
464
504
  }
465
505
 
466
- :where(button, .button).secondary:hover { /* [0020] specificity */
506
+ :where(button, .button).secondary:hover, .secondary::file-selector-button:hover { /* [0020] specificity */
467
507
  background-color: var(--contrast); /* TODO: make grey in dark mode */
468
508
  }
469
509
 
470
510
  /* #tertiary #button - a link-like button
471
511
  // .......................................................................... */
472
512
 
473
- button.tertiary, .tertiary.button { /* [0011] / [0020] specificity */
513
+ button.tertiary, .tertiary.button, .tertiary::file-selector-button { /* [0011] / [0020] specificity */
474
514
  color: var(--foreground); /* invert foreground/background */
475
515
  background-color: unset; /* border is transparent */
476
516
  padding-inline: var(--xxs);
477
517
  }
478
518
 
479
- :where(button, .button).tertiary:hover { /* [0020] specificity */
519
+ :where(button, .button).tertiary:hover, .tertiary::file-selector-button:hover { /* [0020] specificity */
480
520
  text-decoration: underline; /* TODO: make grey in dark mode */
481
521
  border-color: var(--transparent);
482
522
  }
@@ -563,7 +603,7 @@ button.tertiary, .tertiary.button { /* [0011] / [0020] specificity */
563
603
  // .......................................................................... */
564
604
 
565
605
  /* TODO: the main form grid should inline elements rather than forcing it here
566
- .bottons inlines/wraps multiple buttons where necessary - [0010] specificity*/
606
+ .buttons inlines/wraps multiple buttons where necessary - [0010] specificity*/
567
607
  .buttons {
568
608
  list-style: none;
569
609
  display: flex; /* overwrite display: grid; */
@@ -584,11 +624,12 @@ form .buttons { max-width: var(--field-max) }
584
624
  .roomy.buttons { gap: var(--ml); }
585
625
 
586
626
  /* fix buttons floating and getting squished at smaller screen widths */
587
- @container (max-width: 28rem) {
627
+ @container (width <= 28rem) {
588
628
  form { max-width: unset; }
589
629
  form .buttons {
590
- max-width: unset;
591
- grid-column: -1/1;
630
+ max-width: unset; /* don't constrain width in narrow confines */
631
+ grid-column: -1/1; /* span the entire grid for more room */
632
+ justify-content: flex-end; /* end-align looks more natural than start*/
592
633
  }
593
634
  label { font-size: var(--small); }
594
635
  }
@@ -658,6 +699,18 @@ nav:has(.toggle[aria-expanded=false]) > menu {
658
699
  [rel~="external"].button:hover::after { background-color: var(--foreground); }
659
700
 
660
701
 
702
+ /* #button_to - a rails class set on forms that look like buttons - minimize the
703
+ // form width while maximizing the button within to that form width
704
+ // .......................................................................... */
705
+ .button_to {
706
+ width: min-content;
707
+ /*HACK: an inline-size container-type make forms zero-width, so make it normal*/
708
+ container-type: normal;
709
+ }
710
+ .button_to > [type="submit"] {
711
+ width: max-content;
712
+ }
713
+
661
714
 
662
715
  /* -----------------------------------------------------------------------------
663
716
  // #selectmenu - Open UI replacement to the standard select element -
@@ -732,7 +785,7 @@ selectmenu::part(listbox) {
732
785
  margin-top: auto; /* make sure buttons are at the bottom */
733
786
  }
734
787
 
735
- @container (min-width: 35rem) {
788
+ @container (width >= 35rem) {
736
789
  /*.card { flex-direction: row; }*/ /* interferes with single-card section */
737
790
  .card > img, .cards > article > img {
738
791
  max-height: var(--width);
@@ -745,19 +798,6 @@ selectmenu::part(listbox) {
745
798
  }
746
799
  }
747
800
 
748
- /* TEMP: use media queries for browsers that don't support container queries */
749
- @supports not (container-type: inline-size) {
750
- @media (min-width: 47rem) {
751
- /*.card { flex-direction: row; }*/ /* interferes with single-card section */
752
- .card > img, .cards > article > img {
753
- max-height: var(--width);
754
- max-width: var(--width);
755
- }
756
- .cards :last-child:nth-child(3n - 2) {
757
- grid-column-end: span 3;
758
- flex-direction: row;
759
- }
760
- }}
761
801
 
762
802
  /* -----------------------------------------------------------------------------
763
803
  // #tags - an inline list of metatags; can be text, links, icons, or other
@@ -771,7 +811,8 @@ selectmenu::part(listbox) {
771
811
  padding: 0;
772
812
  }
773
813
 
774
- .tags > li {
814
+ /* TODO: .tag should be in classes.css and kept in sync with this rule? */
815
+ .tags > li, .tag {
775
816
  display: inline-block;
776
817
  color: var(--secondary);
777
818
  font-size: var(--small);
@@ -793,12 +834,6 @@ selectmenu::part(listbox) {
793
834
  margin-bottom: var(--m);
794
835
  }
795
836
 
796
- /* TEMP: add margin-top to buttons for browsers that don't support :has() */
797
- @supports not (:has(a)) {
798
- .tags + .buttons {
799
- margin-top: var(--m);
800
- }}
801
-
802
837
 
803
838
  /* -----------------------------------------------------------------------------
804
839
  // #grid - multi-column grid adjustments
@@ -814,12 +849,6 @@ selectmenu::part(listbox) {
814
849
  container-type: none; /* containment clashes with grid on safari */
815
850
  }
816
851
 
817
- /* for layouts with left & right asides, put main in the middle grid columns */
818
- /* grrr, firefox is not forgiving with :has() rules, so this must be separated*/
819
- .dual-aside {
820
- grid-column: 2 / -2;
821
- }
822
-
823
852
  /*full is a grid area for a row that spans all columns - [0000] specificity */
824
853
  :where(.grid) > :where(header,hgroup,h1,h2,h3,h4,h5,h6,nav:not(.column),footer){
825
854
  grid-column: full;
@@ -911,7 +940,7 @@ selectmenu::part(listbox) {
911
940
  // #progressbar - a circular progress bar component - from almond.css
912
941
  // -------------------------------------------------------------------------- */
913
942
 
914
- [role="progressbar"] {
943
+ [role="progressbar"] {
915
944
  --value: 50;
916
945
  --thick: 50%;
917
946
  --medium: 58%;