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.
@@ -11,14 +11,18 @@
11
11
  // -------------------------------------------------------------------------- */
12
12
 
13
13
  /* TODO: moved from components.css; make sure no unintended consequences appear;
14
- sectioning children of body should be .readable by default - keep in sync
15
- with classes.css - [0001] specificity */
14
+ sectioning children of body should be .readable by default so keep in sync
15
+ with .readable in classes.css - [0001] specificity
16
+ // .......................................................................... */
16
17
  body > :where(header, nav, main, section, div, figure, footer) {
17
18
  width: 100%;
18
19
  max-width: var(--line-length); /* for horizontal centering */
19
20
  margin-inline: auto; /* centers if width is set */
20
21
  }
21
22
 
23
+ /* make bare divs in body grid padded by default; should probably go in shims */
24
+ body > :is(section, div) { grid-column: 2/-2; }
25
+
22
26
  /* bare pages should not have grid applied */
23
27
  body:not(:has(main)):has(h1, p) { /* [0003] specificity */
24
28
  display: block;
@@ -52,6 +56,30 @@ nav > menu > li { display: inline; } /* only direct children, as menu
52
56
  text-decoration-style: dotted;
53
57
  }
54
58
 
59
+ body > footer:last-of-type { margin-top: var(--l); }
60
+
61
+
62
+ /* TEMP: moved from states.css ++++++++++++++++++++++++++++++++++++++++++++++ */
63
+ /* -----------------------------------------------------------------------------
64
+ // #links - for linking to other documents
65
+ // -------------------------------------------------------------------------- */
66
+
67
+ /* #mailto #tel #sms #file #external #bookmark #download - special link icons -
68
+ this uses the svg mask technique to place & color icons on hover; as such, it
69
+ must be in a separate pseudo-element so masking doesn't bleed out to text */
70
+ /* #icons - set --icon to an svg from icons.css, set color with --icon-color */
71
+ [href^="tel:"] { --icon: var(--i-phone); }
72
+ [href^="sms:"] { --icon: var(--i-message-2); }
73
+ [href^="file:"] { --icon: var(--i-file); }
74
+ [download] { --icon: var(--i-file-download); }
75
+ [href^="mailto:"] { --icon: var(--i-mail); }
76
+ [rel~="external"] { --icon: var(--i-external-link); }
77
+ [rel~="bookmark"] { --icon: var(--i-bookmark); }
78
+
79
+ /* give followed fragment links some room at the top - [0010] specificity */
80
+ [id] { scroll-margin-top: var(--l); }
81
+ /* END: moved from states.css +++++++++++++++++++++++++++++++++++++++++++++++ */
82
+
55
83
 
56
84
  /* -----------------------------------------------------------------------------
57
85
  // #lists - ordered and unordered lists of items
@@ -72,6 +100,50 @@ ul:where(:has(li [type="checkbox"], li [type="radio"])) {
72
100
  list-style: none;
73
101
  }
74
102
 
103
+ /* TEMP: moved from states.css ++++++++++++++++++++++++++++++++++++++++++++++ */
104
+ /* #ul #ol - removes vertical gaps for lists within lists - uses :where() to get
105
+ [0001] specificity rather than [0002] */
106
+ :where(ul, ol) :is(ul, ol) { margin: 0; }
107
+
108
+
109
+ /* -----------------------------------------------------------------------------
110
+ // #tables - for tabular data
111
+ // -------------------------------------------------------------------------- */
112
+
113
+ /* makes the first column sticky - [0012] specificity */
114
+ :not(tfoot) > tr th:first-of-type {
115
+ position: sticky; /* works best w/ <table> display ≅ block */
116
+ left: 0;
117
+ background-color: var(--background); /* is transparent otherwise */
118
+ }
119
+ /* makes the table header row sticky - [0002] specificity */
120
+ thead th {
121
+ position: sticky;
122
+ top: 0;
123
+ z-index: 1; /* puts header row on top of tbody rows, including
124
+ header column */
125
+ background-color: var(--background); /* is transparent otherwise */
126
+ }
127
+ /* sticks top left box on top of both header columns/rows - [0012] specificity*/
128
+ thead th:first-child { z-index: 2; }
129
+
130
+ /* zebra-striping of table rows - [0013] specificity */
131
+ tbody tr:nth-child(even), tbody tr:nth-child(even) th {
132
+ background-color: var(--bg-contrast);
133
+ }
134
+ /* this is more robust because it excludes hidden rows, but only safari and
135
+ chrome support this syntax - [0023] specificity */
136
+ @supports selector(:nth-child(even of :not([hidden]))) {
137
+ tbody tr:where(:nth-child( even of :not([hidden]) )),
138
+ tbody tr:where(:nth-child( even of :not([hidden]) )) th {
139
+ background-color: var(--bg-contrast);
140
+ }}
141
+
142
+ /* adds sticky borders below thead and above tfoot */
143
+ thead tr:last-of-type th {box-shadow: inset 0 -2px var(--secondary, --neutral);}
144
+ tfoot :where(td, th) {box-shadow: inset 0 2px var(--secondary, --neutral);}
145
+ /* END: moved from states.css +++++++++++++++++++++++++++++++++++++++++++++++ */
146
+
75
147
 
76
148
  /* -----------------------------------------------------------------------------
77
149
  // #forms - for submitting data to the server
@@ -79,15 +151,148 @@ ul:where(:has(li [type="checkbox"], li [type="radio"])) {
79
151
 
80
152
  /* #form #section #p #div - would prefer subgrid to have containers layout
81
153
  contents on the grid, but its not yet supported by chrome/edge. use
82
- display: contents; to pierce the grid instead - [0002] specificity
154
+ display: contents; to pierce the grid instead - [0002] specificity
83
155
  // .......................................................................... */
84
- form section, form p, form div {
156
+ form section, form p, form div { /* TODO: should be a shim eventually */
85
157
  display: contents; /* make contents align to form grid */
86
158
  margin: 0; /* let contents, not container, set spacing */
159
+ container-type: unset; /*let contents adjust to outer form container*/
87
160
  }
88
161
  /* #h2 - make form headers/paragraphs span the full width - [0002] specificity*/
89
162
  form h2, form p { grid-column: full; }
90
163
 
164
+ /* #fieldset grid should span full form grid in narrower form containers
165
+ // .......................................................................... */
166
+ @container form (width <= 35rem) {
167
+ fieldset {
168
+ grid-column: full;
169
+ border-inline: none;
170
+ border-color: var(--deemphasized);
171
+ }
172
+ /* #legend should be visually de-emphasized as a separator as well */
173
+ legend {
174
+ border: none;
175
+ margin-bottom: var(--m);
176
+ font-weight: var(--bold);
177
+ }
178
+ }
179
+
180
+ /* #label becomes inline-grid to take full row --height - EXPERIMENTAL
181
+ // TODO: fix label-to-textarea baseline alignment, and radio/checkbox height
182
+ // .......................................................................... */
183
+ label {
184
+ display: inline-grid;
185
+ grid-auto-flow: column;
186
+ height: var(--height);
187
+ align-content: center;
188
+ }
189
+
190
+ /* TEMP: moved from states.css ++++++++++++++++++++++++++++++++++++++++++++++ */
191
+ /* #form #ul - since lists in forms typically list out form controls, remove
192
+ the bullet styling from them - [0002] specificity */
193
+ form ul { list-style: none; }
194
+
195
+ /* #form #section #p #div - extend the subgrid into common, but strictly
196
+ // non-semantic, container elements used within forms - subgrid is firefox 71+ &
197
+ // safari 16+ only 20221001
198
+ // .......................................................................... */
199
+ @supports (grid-template-columns: subgrid) {
200
+ /* :where() can be used here, since @supports is also a recent addition */
201
+ form :where(section, p, div) { /* [0001] specificity */
202
+ grid-column: full;
203
+ display: grid;
204
+ grid-template-columns: subgrid;
205
+ gap: inherit;
206
+ }
207
+
208
+ /* TEMP: swap the grid placement of radio/checkboxes & their labels */
209
+ :where(form) :where(section, p, div) :is([type='checkbox'], [type='radio']) {
210
+ grid-column: labels;
211
+ justify-self: right;
212
+ }
213
+ :where(form) :is(:where(section, p, div)
214
+ :is([type='checkbox'], [type='radio'])+label) {
215
+ grid-column: elements;
216
+ justify-self: left;
217
+ }
218
+ }
219
+ /*form section :where(h1,h2,h3,h4,h5,h6) + p { display: block; }*/
220
+
221
+ /* chrome/edge doesn't support subgrid yet but does support :has() & :where() */
222
+ @supports selector(:has(*)) {
223
+ /* set up a form grid on fieldsets that include form elements */
224
+ fieldset:where(:has(label, input, button, textarea, select, fieldset)) {
225
+ margin: 0;
226
+ display: grid;
227
+ grid-template-columns:[labels full-start] 3fr [elements] 7fr [full-end];
228
+ gap: var(--m);
229
+ }
230
+ /* for fieldsets containing <p> tags that encompass checkboxes/radios, but no
231
+ other form inputs, remove extraneous gap between label and element */
232
+ fieldset:where(:has(p :is([type='checkbox'], [type='radio'])):not(:has(select,
233
+ textarea, [type="text"], [type="date"], [type="email"], [type="password"],
234
+ [type="datetime-local"], [type="search"]))) {
235
+ row-gap: 0;
236
+ }
237
+ /* since grid properties fall through p tags, assign margin-top to first child
238
+ elements to get a gap between paragraphs of different input types */
239
+ fieldset p:has([type='checkbox'], [type='radio']) + p:has([type='radio'],
240
+ [type='checkbox']) :is([type='radio'], [type='checkbox'],
241
+ label):first-of-type {
242
+ margin-top: var(--m);
243
+ }
244
+ /* chrome/edge doesn't support subgrid, so pierce the grid barrier instead */
245
+ fieldset :where(p:has(label, input, button, textarea, select, fieldset)) {
246
+ display: contents;
247
+ }
248
+ /* labels go on the labels gridline */
249
+ :where(fieldset :is(p, div)) label {
250
+ grid-column: labels;
251
+ }
252
+ /* lists that contain radios/checkboxes go on the elements gridline */
253
+ form:has(fieldset :where(select, textarea, [type="text"], [type="date"],
254
+ [type="email"], [type="password"], [type="datetime-local"],
255
+ [type="search"])) fieldset ul:has(li label :where([type='radio'],
256
+ [type='checkbox'])) {
257
+ grid-column: elements;
258
+ }
259
+
260
+ /* inputs on the elements gridline; pad right side away from fieldset line */
261
+ :where(fieldset) :where(p):has(input, button, textarea, select, fieldset)
262
+ :where(input:not(:is([type='checkbox'],[type='radio']), button,
263
+ textarea, select, fieldset)) {
264
+ grid-column: elements;
265
+ margin-right: var(--m);
266
+ }
267
+ /* for radios & checks, invert the placement of the input and label */
268
+ /* NOTE: align-self & justify-self are not properly supported for grid by IE
269
+ anyway, so just use the combined property `place-self` here */
270
+ :where(fieldset) :where(p):has(label) :where([type='checkbox'],
271
+ [type='radio']):has(+ label) {
272
+ grid-column: labels;
273
+ place-self: center end;
274
+ }
275
+ :where(fieldset p:has(label) :is([type='checkbox'],
276
+ [type='radio']):has(+ label)) + label {
277
+ grid-column: elements;
278
+ justify-self: start;
279
+ }
280
+ /* for paragraph tags that aren't form element containers, span the grid */
281
+ :where(fieldset) :where(p, div, h2, h3, h4, h5, h6):not(:has(label, input,
282
+ button, textarea, select, fieldset)) {
283
+ display: block;
284
+ grid-column: full;
285
+ }
286
+ }
287
+ /*form :where(fieldset, input, select, button, input[type="button"]) {
288
+ grid-column: elements;
289
+ }*/
290
+
291
+ fieldset > :last-child {
292
+ margin-bottom: 0;
293
+ }
294
+ /* END: moved from states.css +++++++++++++++++++++++++++++++++++++++++++++++ */
295
+
91
296
 
92
297
  /* -----------------------------------------------------------------------------
93
298
  // #selections - dropdown/selection form controls
@@ -99,6 +304,16 @@ select { background-image: var(--i-chevron); }
99
304
  /* only pad options inside optgroups - [0002] specificity */
100
305
  optgroup option { padding: 0 0 0 var(--m); }
101
306
 
307
+ /* TEMP: moved from states.css ++++++++++++++++++++++++++++++++++++++++++++++ */
308
+ /* #label for taller #multiple #textarea should align top - firefox 106 still
309
+ doesn't properly support :has() with combinator selectors */
310
+ @supports selector(:has(*)) {
311
+ label:where(:has(+ [multiple],+ textarea,+ select[size])){/*[0001] specificity*/
312
+ vertical-align: top;
313
+ align-self: start;
314
+ }}
315
+ /* END: moved from states.css +++++++++++++++++++++++++++++++++++++++++++++++ */
316
+
102
317
 
103
318
  /* -----------------------------------------------------------------------------
104
319
  // #inputs - core form elements
@@ -107,7 +322,7 @@ optgroup option { padding: 0 0 0 var(--m); }
107
322
  /* #label #checkbox - checkboxes inside labels is a common layout - firefox
108
323
  only understands simple :has() selectors, so can't use the direct descendent
109
324
  selector > here until it understands it - [0011] specificity
110
- // ...........................................................................*/
325
+ // .......................................................................... */
111
326
  label:has([type="checkbox"]) {
112
327
  grid-column: elements;
113
328
  justify-self: left;
@@ -119,6 +334,56 @@ label + [type="image"] {
119
334
  vertical-align: middle;
120
335
  }
121
336
 
337
+ /* TEMP: moved from states.css ++++++++++++++++++++++++++++++++++++++++++++++ */
338
+ /* if [size] is set on an input, respect that choice - [0011] specificity */
339
+ input[size] {
340
+ width: fit-content;
341
+ min-width: unset;
342
+ max-width: unset;
343
+ }
344
+
345
+ /* -----------------------------------------------------------------------------
346
+ // specialized inputs - #date #time #datetime-local #month #week #datetime
347
+ // #email #password #search #file #image #url #tel #color
348
+ // #range #number #hidden
349
+ // -------------------------------------------------------------------------- */
350
+
351
+ /* input images */
352
+ [type="date"], [type="time"], [type="datetime"], [type="datetime-local"],
353
+ [type="month"], [type="week"], [type="url"], [type="email"],
354
+ [type="number"], [type="tel"], [type="password"], [type="search"] {
355
+ padding-left: var(--height);
356
+ background-blend-mode: var(--icon-blend-mode);
357
+ }
358
+ [type="date"], [type="month"], [type="week"] {
359
+ background-image: var(--colorize-icon), var(--i-calendar); }
360
+ [type="datetime"], [type="datetime-local"], [type="time"] {
361
+ background-image: var(--colorize-icon), var(--i-calendar-time); }
362
+ [type="url"] { background-image: var(--colorize-icon), var(--i-browser); }
363
+ [type="email"] { background-image: var(--colorize-icon), var(--i-mail); }
364
+ [type="number"] { background-image: var(--colorize-icon), var(--i-numbers); }
365
+ [type="tel"] { background-image: var(--colorize-icon), var(--i-phone); }
366
+ [type="password"]{ background-image: var(--colorize-icon), var(--i-lock); }
367
+ [type="search"] { background-image: var(--colorize-icon), var(--i-search); }
368
+
369
+ /* hide nav search's placeholder text if the background icon is present; opacity
370
+ is used here because other methods are disallowed on ::placeholder - [0001]*/
371
+ :where(nav) :where([type="search"])::placeholder { opacity: 0; }
372
+
373
+ /* if radios/checkboxes are inline, insert a gap between them for readability */
374
+ :where([type="radio"] + label, [type="checkbox"] + label) +
375
+ :is([type="radio"], [type="checkbox"]) { /* [0010] specificity */
376
+ margin-left: var(--m);
377
+ }
378
+
379
+ /* search decorations - [0011] specificity */
380
+ [type="search"]::-webkit-search-cancel-button,
381
+ [type="search"]::-webkit-search-decoration {
382
+ appearance: none; /* needed? */
383
+ }
384
+ /* END: moved from states.css +++++++++++++++++++++++++++++++++++++++++++++++ */
385
+
386
+
122
387
  /* -----------------------------------------------------------------------------
123
388
  // #blocks - elements that contain text blocks
124
389
  // -------------------------------------------------------------------------- */
@@ -129,6 +394,27 @@ pre > code, xmp {
129
394
  border-radius: 0 var(--radius) var(--radius) 0;
130
395
  }
131
396
 
397
+ /* #blockquote
398
+ // ...........................................................................*/
399
+ blockquote::before { /* [0002] specificity is the least possible here */
400
+ content: open-quote;
401
+ color: var(--pale);
402
+ font-size: 5rem;
403
+ font-family: var(--serif);
404
+ left: var(--xs);
405
+ line-height: 1;
406
+ position: absolute;
407
+ top: 0;
408
+ z-index: -1;
409
+ }
410
+ blockquote > :first-child { /* [0011] specificity */
411
+ margin-top: 0;
412
+ text-indent: var(--m);
413
+ }
414
+ blockquote > :last-child { /* [0011] specificity */
415
+ margin-bottom: 0;
416
+ }
417
+
132
418
 
133
419
  /* -----------------------------------------------------------------------------
134
420
  // #inline elements - elements that occur principally within text blocks.
@@ -149,6 +435,43 @@ pre > code {
149
435
  }
150
436
 
151
437
 
438
+
439
+ /* TEMP: moved from states.css ++++++++++++++++++++++++++++++++++++++++++++++ */
440
+ /* #q - inline quotations - note that the closing smart quote is added manually
441
+ here as <q>'s automatic quotes are otherwise added via pseudo elements
442
+ // ...........................................................................*/
443
+ q[cite]::after { content: "” (cf. " attr(cite) ") "; }
444
+
445
+
446
+ /* -----------------------------------------------------------------------------
447
+ // #media / #embedded - elements that add multimedia to a page
448
+ // -------------------------------------------------------------------------- */
449
+
450
+ /* #figure #headings - #h1 #h2 #h3 #h4 #h5 #h6 ~*/
451
+ figure > :where(h1,h2,h3,h4,h5,h6):first-child { margin-top: 0; }
452
+
453
+ /* #blockquote inside #figure - safari only for now - :where is older than :has
454
+ so it can be used here to reduce specificity - [0001] specificity */
455
+ figure:where(:has(blockquote)) {
456
+ background-color: revert;
457
+ }
458
+ /* fix doubled margin of a blockquote in a figure - [0002] specificity */
459
+ figure > blockquote {
460
+ text-align: start;
461
+ margin: var(--ms);
462
+ padding: var(--ms);
463
+ max-width: calc(var(--line-length) - (var(--ms) * 2));
464
+ }
465
+
466
+ /* #svg - [0001] specificity */
467
+ svg:not(:where(:root)) {
468
+ width: var(--m);
469
+ /*max-width: 100%;*/
470
+ overflow: hidden;
471
+ }
472
+ /* END: moved from states.css +++++++++++++++++++++++++++++++++++++++++++++++ */
473
+
474
+
152
475
  /* -----------------------------------------------------------------------------
153
476
  // #interactive - built-in interactive components
154
477
  // -------------------------------------------------------------------------- */
@@ -156,3 +479,44 @@ pre > code {
156
479
  /* a method="dialog" #form with a plain <button> closes the dialog without js!*/
157
480
  /* makes form/close button not be full-width - [0010] specificity */
158
481
  [method="dialog"] { width: min-content; }
482
+
483
+ /* TEMP: moved from states.css ++++++++++++++++++++++++++++++++++++++++++++++ */
484
+ /* #dialog - built-in modal overlay - comes with 'Esc' support with no js! */
485
+ /* wrap long dialogs in a container to scroll the body content sans button */
486
+ dialog > :where(div, section, article) {
487
+ overflow-y: auto; /* scrolls as necessary w/ height set */
488
+ max-height: calc(80vh * 0.8); /* container queries needed! */
489
+ }
490
+
491
+ dialog button {
492
+ margin-top: var(--ms);
493
+ }
494
+
495
+ dialog :where(h1, h2, h3, h4, h5, h6) {
496
+ border-bottom: var(--solid) var(--border);
497
+ border-radius: var(--radius) var(--radius) 0 0;
498
+ color: var(--distinct); /* differentiate dialog headings */
499
+ font-size: var(--large); /* dialogs typically only need 1 heading
500
+ level, so make it all the same size */
501
+ margin: 0 0 0 calc(-1 * var(--m)); /* negative left margin
502
+ lines up heading with paragraph text */
503
+ padding: 0 var(--m) var(--m); /* top padding provided by dialog
504
+ padding so remove it here */
505
+ }
506
+
507
+ /* #details - an accordion-like widget for question & answer style layouts */
508
+ details + details {
509
+ border-top: 0;
510
+ border-radius: 0;
511
+ }
512
+
513
+ details:first-of-type {
514
+ border-top-left-radius: var(--radius);
515
+ border-top-right-radius: var(--radius);
516
+ }
517
+
518
+ details:last-of-type {
519
+ border-bottom-left-radius: var(--radius);
520
+ border-bottom-right-radius: var(--radius);
521
+ }
522
+ /* END: moved from states.css +++++++++++++++++++++++++++++++++++++++++++++++ */
@@ -38,6 +38,7 @@
38
38
  --i-phone: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path stroke='none' d='M0 0h24v24H0z' fill='none'/><path d='M5 4h4l2 5l-2.5 1.5a11 11 0 0 0 5 5l1.5 -2.5l5 2v4a2 2 0 0 1 -2 2a16 16 0 0 1 -15 -15a2 2 0 0 1 2 -2' /></svg>");
39
39
  --i-send: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><title>send</title><path stroke='none' d='M0 0h24v24H0z' fill='none'/><line x1='10' y1='14' x2='21' y2='3' /><path d='M21 3l-6.5 18a0.55 .55 0 0 1 -1 0l-3.5 -7l-7 -3.5a0.55 .55 0 0 1 0 -1l18 -6.5' /></svg>");
40
40
  --i-server-cog: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><title>server cog</title><path stroke='none' d='M0 0h24v24H0z' fill='none'/><rect x='3' y='4' width='18' height='8' rx='3' /><path d='M12 20h-6a3 3 0 0 1 -3 -3v-2a3 3 0 0 1 3 -3h10.5' /><circle cx='18.001' cy='18' r='2' /><path d='M18.001 14.5v1.5' /><path d='M18.001 20v1.5' /><path d='M21.032 16.25l-1.299 .75' /><path d='M16.27 19l-1.3 .75' /><path d='M14.97 16.25l1.3 .75' /><path d='M19.733 19l1.3 .75' /><path d='M7 8v.01' /><path d='M7 16v.01' /></svg>");
41
+ --i-settings: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><title>settings</title><path stroke='none' d='M0 0h24v24H0z' fill='none'/><path d='M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z' /><path d='M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0' /></svg>");
41
42
  --i-trash: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><title>delete</title><path stroke='none' d='M0 0h24v24H0z' fill='none'/><line x1='4' y1='7' x2='20' y2='7' /><line x1='10' y1='11' x2='10' y2='17' /><line x1='14' y1='11' x2='14' y2='17' /><path d='M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12' /><path d='M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3' /></svg>");
42
43
  --i-user-circle: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path stroke='none' d='M0 0h24v24H0z' fill='none'/><circle cx='12' cy='12' r='9' /><circle cx='12' cy='10' r='3' /><path d='M6.168 18.849a4 4 0 0 1 3.832 -2.849h4a4 4 0 0 1 3.834 2.855' /></svg>");
43
44
  --i-user-off: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><title>disable</title><path stroke='none' d='M0 0h24v24H0z' fill='none'/><path d='M14.274 10.291a4 4 0 1 0 -5.554 -5.58m-.548 3.453a4.01 4.01 0 0 0 2.62 2.65' /><path d='M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 1.147 .167m2.685 2.681a4 4 0 0 1 .168 1.152v2' /><line x1='3' y1='3' x2='21' y2='21' /></svg>");
@@ -0,0 +1,65 @@
1
+ /******************************************************************************\
2
+ LEGACY - Graceful degradation for "legacy" browsers, which we define as those
3
+ that don't support modern css, not just IE11.
4
+
5
+ We'll generally aim for [0010] specificity here, as that's the default
6
+ specificity of a single class, which can be overridden in later styles
7
+ using just a single class. Exceptions will be marked with their
8
+ specificity, as usual.
9
+
10
+ \******************************************************************************/
11
+
12
+
13
+ /* -----------------------------------------------------------------------------
14
+ // #containers -
15
+ // -------------------------------------------------------------------------- */
16
+
17
+ /* this doesn't work because some items aren't full width, like asides
18
+ body > *:not(.fluid) {
19
+ margin-inline: var(--m);
20
+ }
21
+ */
22
+
23
+
24
+ /* -----------------------------------------------------------------------------
25
+ // #grid -
26
+ // -------------------------------------------------------------------------- */
27
+
28
+
29
+ /* chrome & edge don't support subgrid yet, though in development - 20230423 */
30
+ @supports not (grid-template-columns: subgrid) {
31
+ .subgrid { display: contents; }
32
+ .subgrid :first-child { /* TODO: this breaks some layouts, like banner images */
33
+ /*grid-column-start: 2;*/ /* TODO: fix right side guttering too */
34
+ }}
35
+
36
+
37
+ /* -----------------------------------------------------------------------------
38
+ // #card -
39
+ // -------------------------------------------------------------------------- */
40
+
41
+ /* TEMP: use media queries for browsers that don't support container queries */
42
+ @supports not (container-type: inline-size) {
43
+ @media (min-width: 47rem) {
44
+ /*.card { flex-direction: row; }*/ /* interferes with single-card section */
45
+ .card > img, .cards > article > img {
46
+ max-height: var(--width);
47
+ max-width: var(--width);
48
+ }
49
+ .cards :last-child:nth-child(3n - 2) {
50
+ grid-column-end: span 3;
51
+ flex-direction: row;
52
+ }
53
+ }}
54
+
55
+
56
+ /* -----------------------------------------------------------------------------
57
+ // #tags -
58
+ // -------------------------------------------------------------------------- */
59
+
60
+ /* TEMP: add margin-top to buttons for browsers that don't support :has() */
61
+ @supports not (:has(a)) {
62
+ .tags + .buttons {
63
+ margin-top: var(--m);
64
+ }}
65
+