clairity.css 0.1.2 → 0.3.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.
@@ -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%;