@axiapps/axi-design 1.10.0 → 1.11.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/README.md +48 -10
- package/dist/axi.css +448 -27
- package/dist/themes/glass.css +11 -0
- package/docs/RULES.md +146 -17
- package/package.json +8 -4
- package/src/feedback.css +67 -0
- package/src/forms.css +89 -0
- package/src/primitives.css +53 -13
- package/src/prose.css +1 -1
- package/src/shells.css +209 -13
- package/src/tokens.css +25 -0
- package/docs/superpowers/plans/2026-09-23-axi-docs-site.md +0 -2376
- package/docs/superpowers/specs/2026-09-23-axi-docs-site-design.md +0 -333
package/src/shells.css
CHANGED
|
@@ -63,16 +63,17 @@
|
|
|
63
63
|
background: var(--axi-accent);
|
|
64
64
|
color: var(--axi-accent-ink);
|
|
65
65
|
border-color: var(--axi-ink-line);
|
|
66
|
-
box-shadow: var(--axi-
|
|
66
|
+
box-shadow: var(--axi-shadow-control);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
/* ---------- notice ---------- */
|
|
70
70
|
.axi-notice {
|
|
71
71
|
display: flex; gap: 14px; padding: 15px 18px;
|
|
72
72
|
background: var(--axi-surface);
|
|
73
|
+
backdrop-filter: var(--axi-surface-filter);
|
|
73
74
|
border: var(--axi-border-panel) solid var(--axi-ink-line);
|
|
74
75
|
border-radius: var(--axi-radius);
|
|
75
|
-
box-shadow: var(--axi-
|
|
76
|
+
box-shadow: var(--axi-shadow-panel);
|
|
76
77
|
}
|
|
77
78
|
.axi-notice__icon {
|
|
78
79
|
flex: none; width: 26px; height: 26px;
|
|
@@ -90,9 +91,10 @@
|
|
|
90
91
|
display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
|
|
91
92
|
padding: 14px;
|
|
92
93
|
background: var(--axi-surface);
|
|
94
|
+
backdrop-filter: var(--axi-surface-filter);
|
|
93
95
|
border: var(--axi-border-panel) solid var(--axi-ink-line);
|
|
94
96
|
border-radius: var(--axi-radius);
|
|
95
|
-
box-shadow: var(--axi-
|
|
97
|
+
box-shadow: var(--axi-shadow-panel);
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
/* ---------- menu popover ---------- */
|
|
@@ -107,9 +109,10 @@
|
|
|
107
109
|
width: var(--axi-menu-width, 310px);
|
|
108
110
|
max-height: 340px; overflow-y: auto; padding: 8px;
|
|
109
111
|
background: var(--axi-surface-raised);
|
|
112
|
+
backdrop-filter: var(--axi-surface-filter);
|
|
110
113
|
border: var(--axi-border-panel) solid var(--axi-ink-line);
|
|
111
114
|
border-radius: var(--axi-radius);
|
|
112
|
-
box-shadow: var(--axi-
|
|
115
|
+
box-shadow: var(--axi-shadow-panel);
|
|
113
116
|
}
|
|
114
117
|
.axi-menu__pop[hidden] { display: none; }
|
|
115
118
|
.axi-menu__pop label {
|
|
@@ -118,7 +121,7 @@
|
|
|
118
121
|
font-size: 13px; font-weight: 600; color: var(--axi-text-dim); cursor: pointer;
|
|
119
122
|
}
|
|
120
123
|
.axi-menu__pop label:hover { background: var(--axi-ground); color: var(--axi-text); }
|
|
121
|
-
.axi-menu__pop input { margin: 3px 0 0;
|
|
124
|
+
.axi-menu__pop input { margin: 3px 0 0; }
|
|
122
125
|
|
|
123
126
|
/* ---------- tooltip ---------- */
|
|
124
127
|
/* One line of ink on the darkest surface in the language, so it reads over
|
|
@@ -131,7 +134,11 @@
|
|
|
131
134
|
exists nowhere else, because a keyboard or touch user may never see it. */
|
|
132
135
|
.axi-tooltip {
|
|
133
136
|
position: fixed;
|
|
134
|
-
|
|
137
|
+
/* Layer 70: above the drawer and its scrim, above toasts, below a
|
|
138
|
+
showModal()-ed dialog's top layer - which it was below anyway, since the
|
|
139
|
+
top layer is above every z-index. 99999 was not a layer, it was an
|
|
140
|
+
argument with one. */
|
|
141
|
+
z-index: 70;
|
|
135
142
|
padding: 5px 8px;
|
|
136
143
|
background: var(--axi-ink-line);
|
|
137
144
|
color: var(--axi-text);
|
|
@@ -149,15 +156,16 @@
|
|
|
149
156
|
display: flex; flex-direction: column; gap: 11px;
|
|
150
157
|
padding: 22px 16px 14px;
|
|
151
158
|
background: var(--axi-surface);
|
|
159
|
+
backdrop-filter: var(--axi-surface-filter);
|
|
152
160
|
border: var(--axi-border-panel) solid var(--axi-ink-line);
|
|
153
161
|
border-radius: var(--axi-radius);
|
|
154
|
-
box-shadow: var(--axi-
|
|
162
|
+
box-shadow: var(--axi-shadow-panel);
|
|
155
163
|
font: inherit; color: inherit; text-decoration: none; cursor: pointer;
|
|
156
164
|
transition: transform .1s, box-shadow .1s;
|
|
157
165
|
}
|
|
158
166
|
.axi-card:hover {
|
|
159
167
|
transform: translate(-3px, -3px);
|
|
160
|
-
box-shadow: var(--axi-
|
|
168
|
+
box-shadow: var(--axi-shadow-panel-hover);
|
|
161
169
|
}
|
|
162
170
|
/* The top strip is drawn from the card itself so a renderer does not have to
|
|
163
171
|
emit an extra element for it. It is opt-in: a card only gets a strip when
|
|
@@ -205,12 +213,13 @@
|
|
|
205
213
|
.axi-card:hover .axi-card__go { color: var(--axi-text); }
|
|
206
214
|
|
|
207
215
|
/* ---------- drawer ---------- */
|
|
208
|
-
.axi-scrim { position: fixed; inset: 0; z-index: 50; background: var(--axi-scrim); border: 0; }
|
|
216
|
+
.axi-scrim { position: fixed; inset: 0; z-index: 50; background: var(--axi-scrim); backdrop-filter: var(--axi-surface-filter); border: 0; }
|
|
209
217
|
.axi-drawer {
|
|
210
218
|
position: fixed; top: 0; right: 0; bottom: 0; z-index: 51;
|
|
211
219
|
width: min(var(--axi-drawer-width, 560px), 100vw);
|
|
212
220
|
display: flex; flex-direction: column;
|
|
213
221
|
background: var(--axi-surface);
|
|
222
|
+
backdrop-filter: var(--axi-surface-filter);
|
|
214
223
|
border-left: var(--axi-border-panel) solid var(--axi-ink-line);
|
|
215
224
|
}
|
|
216
225
|
.axi-drawer[hidden], .axi-scrim[hidden] { display: none; }
|
|
@@ -236,7 +245,7 @@
|
|
|
236
245
|
}
|
|
237
246
|
.axi-drawer__close:hover {
|
|
238
247
|
background: var(--axi-accent); color: var(--axi-accent-ink);
|
|
239
|
-
box-shadow: var(--axi-
|
|
248
|
+
box-shadow: var(--axi-shadow-control);
|
|
240
249
|
transform: translate(-2px, -2px);
|
|
241
250
|
}
|
|
242
251
|
.axi-drawer__body { overflow-y: auto; padding: 18px 24px 30px; }
|
|
@@ -304,10 +313,70 @@
|
|
|
304
313
|
.axi-titlebar__btns button:hover { background: var(--axi-surface); color: var(--axi-text); }
|
|
305
314
|
/* Close is the one destructive control in the chrome, and the one place a
|
|
306
315
|
status ink belongs in a titlebar. */
|
|
307
|
-
.axi-titlebar__btns button:last-child:hover { background: var(--axi-danger); color: var(--axi-ink-
|
|
316
|
+
.axi-titlebar__btns button:last-child:hover { background: var(--axi-danger); color: var(--axi-ink-on-fill); }
|
|
308
317
|
/* The scrolling region under the chrome. */
|
|
309
318
|
.axi-window__body { flex: 1; overflow-y: auto; }
|
|
310
319
|
|
|
320
|
+
/* ---------- breadcrumbs ---------- */
|
|
321
|
+
/* A path, not a control strip. The separator is the family diamond (rule 7)
|
|
322
|
+
drawn in the rule ink, so it reads as punctuation rather than as a third
|
|
323
|
+
link the reader could click.
|
|
324
|
+
The current crumb is NOT filled. Rule 5 reserves a fill for a state
|
|
325
|
+
something is in - pressed, on, current-as-in-selected - and the last crumb
|
|
326
|
+
is a position, not a control that is on. It takes the full text ink and the
|
|
327
|
+
label weight instead. */
|
|
328
|
+
.axi-crumbs {
|
|
329
|
+
display: flex;
|
|
330
|
+
align-items: center;
|
|
331
|
+
gap: 10px;
|
|
332
|
+
flex-wrap: wrap;
|
|
333
|
+
font: var(--axi-t-small);
|
|
334
|
+
}
|
|
335
|
+
.axi-crumbs a { color: var(--axi-text-dim); text-decoration: none; }
|
|
336
|
+
.axi-crumbs a:hover { color: var(--axi-accent); }
|
|
337
|
+
/* 7px, matching the prose bullet (src/prose.css) exactly, with the same
|
|
338
|
+
--axi-border-hairline outline: rule 7 calls the motif "a 45deg-rotated
|
|
339
|
+
outlined square", and a bare fill with no border does not match it. The
|
|
340
|
+
hairline, not one of the two form steps, is the established weight for a
|
|
341
|
+
diamond this small - at 6px a 2px border on each side would leave only a
|
|
342
|
+
2px fill, too tight to read as a diamond at all. */
|
|
343
|
+
.axi-crumbs__sep {
|
|
344
|
+
width: 7px; height: 7px; flex: none;
|
|
345
|
+
background: var(--axi-rule);
|
|
346
|
+
border: var(--axi-border-hairline) solid var(--axi-ink-line);
|
|
347
|
+
transform: rotate(45deg);
|
|
348
|
+
}
|
|
349
|
+
.axi-crumbs [aria-current="page"] { color: var(--axi-text); font-weight: 800; }
|
|
350
|
+
|
|
351
|
+
/* ---------- pagination ---------- */
|
|
352
|
+
/* The same idea .axi-tabs already expresses, applied to a row of pages: the
|
|
353
|
+
current one is filled and blocked, because "this one is on" is what a fill
|
|
354
|
+
means here. Written as its own component rather than as a tabs modifier
|
|
355
|
+
because a pager sits under content and a tab strip sits in a titlebar, and
|
|
356
|
+
the two disagree about everything except that treatment. */
|
|
357
|
+
.axi-pages { display: flex; gap: 7px; align-items: center; flex-wrap: wrap; }
|
|
358
|
+
.axi-pages__n {
|
|
359
|
+
min-width: 36px;
|
|
360
|
+
padding: 8px 10px;
|
|
361
|
+
text-align: center;
|
|
362
|
+
font: var(--axi-t-label);
|
|
363
|
+
letter-spacing: var(--axi-ls-label);
|
|
364
|
+
color: var(--axi-text-dim);
|
|
365
|
+
text-decoration: none;
|
|
366
|
+
background: var(--axi-surface-raised);
|
|
367
|
+
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
368
|
+
border-radius: var(--axi-radius-sm);
|
|
369
|
+
}
|
|
370
|
+
.axi-pages__n:hover { color: var(--axi-text); }
|
|
371
|
+
.axi-pages__n[aria-current="page"] {
|
|
372
|
+
background: var(--axi-accent);
|
|
373
|
+
color: var(--axi-accent-ink);
|
|
374
|
+
box-shadow: var(--axi-shadow-control);
|
|
375
|
+
}
|
|
376
|
+
/* The elided run between two page numbers. Not a control and never focusable:
|
|
377
|
+
it is the only thing in the row a reader cannot go to. */
|
|
378
|
+
.axi-pages__gap { color: var(--axi-text-faint); padding: 0 2px; }
|
|
379
|
+
|
|
311
380
|
@media (max-width: 640px) {
|
|
312
381
|
.axi-mast__in { min-height: 0; padding: 10px 16px; gap: 12px; }
|
|
313
382
|
.axi-tabs { margin-left: 0; width: 100%; overflow-x: auto; }
|
|
@@ -317,9 +386,136 @@
|
|
|
317
386
|
to the panel hover block, so a card on a hover-emulating touch device
|
|
318
387
|
jumped further than it does on the desktop it was tuned for. */
|
|
319
388
|
.axi-notice, .axi-toolbar, .axi-card {
|
|
320
|
-
box-shadow: var(--axi-
|
|
389
|
+
box-shadow: var(--axi-shadow-control);
|
|
321
390
|
}
|
|
322
391
|
.axi-card:hover {
|
|
323
|
-
box-shadow: var(--axi-
|
|
392
|
+
box-shadow: var(--axi-shadow-control-hover);
|
|
324
393
|
}
|
|
325
394
|
}
|
|
395
|
+
|
|
396
|
+
/* ---------- modal ---------- */
|
|
397
|
+
/* A real <dialog>. Focus trapping, Esc-to-close, inertness for everything
|
|
398
|
+
behind it and promotion to the top layer all come from the browser, and
|
|
399
|
+
none of them can be had from CSS - so the alternative was a <div> plus a
|
|
400
|
+
focus trap this language has no script to write.
|
|
401
|
+
That choice has one visible cost, and it is named here rather than left to
|
|
402
|
+
be discovered: a <dialog> brings its own ::backdrop, so the modal styles
|
|
403
|
+
that instead of reusing .axi-scrim. The two look identical and are not the
|
|
404
|
+
same element. Reusing .axi-scrim would have meant giving up <dialog>.
|
|
405
|
+
Panel weight and panel block: it is the most raised thing on the page. */
|
|
406
|
+
.axi-modal {
|
|
407
|
+
padding: 0;
|
|
408
|
+
max-width: min(var(--axi-modal-width, 560px), calc(100vw - 32px));
|
|
409
|
+
background: var(--axi-surface);
|
|
410
|
+
backdrop-filter: var(--axi-surface-filter);
|
|
411
|
+
color: var(--axi-text);
|
|
412
|
+
border: var(--axi-border-panel) solid var(--axi-ink-line);
|
|
413
|
+
border-radius: var(--axi-radius);
|
|
414
|
+
box-shadow: var(--axi-shadow-panel);
|
|
415
|
+
}
|
|
416
|
+
.axi-modal::backdrop { background: var(--axi-scrim); backdrop-filter: var(--axi-surface-filter); }
|
|
417
|
+
/* The head and foot are divided from the body by rules, not by outlines: they
|
|
418
|
+
are parts of one raised thing, and rule 8's reading applies - a line inside
|
|
419
|
+
a raised surface separates its parts, it does not raise them. */
|
|
420
|
+
.axi-modal__head {
|
|
421
|
+
display: flex; align-items: center; gap: 12px;
|
|
422
|
+
padding: 15px 18px;
|
|
423
|
+
border-bottom: var(--axi-border-control) solid var(--axi-rule);
|
|
424
|
+
}
|
|
425
|
+
.axi-modal__head h2 { font: var(--axi-t-h3); letter-spacing: var(--axi-ls-h3); margin: 0; }
|
|
426
|
+
.axi-modal__body { padding: 18px; font: var(--axi-t-small); color: var(--axi-text-dim); }
|
|
427
|
+
.axi-modal__foot {
|
|
428
|
+
display: flex; justify-content: flex-end; gap: 9px;
|
|
429
|
+
padding: 15px 18px;
|
|
430
|
+
border-top: var(--axi-border-control) solid var(--axi-rule);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/* ---------- accordion ---------- */
|
|
434
|
+
/* <details>/<summary>, so it opens and closes with no script and is
|
|
435
|
+
announced as a disclosure. The native marker is removed and replaced with
|
|
436
|
+
the family diamond, which rotates a quarter turn on [open] - a transform,
|
|
437
|
+
so it is inside rule 4's rationing without needing rule 11. */
|
|
438
|
+
.axi-accordion {
|
|
439
|
+
background: var(--axi-surface);
|
|
440
|
+
backdrop-filter: var(--axi-surface-filter);
|
|
441
|
+
border: var(--axi-border-panel) solid var(--axi-ink-line);
|
|
442
|
+
border-radius: var(--axi-radius);
|
|
443
|
+
box-shadow: var(--axi-shadow-panel);
|
|
444
|
+
}
|
|
445
|
+
/* Stacked accordions need the gap the block occupies, or each one's block
|
|
446
|
+
lands on the next one's outline. */
|
|
447
|
+
.axi-accordion + .axi-accordion { margin-top: calc(var(--axi-offset-panel) + 8px); }
|
|
448
|
+
.axi-accordion__head {
|
|
449
|
+
display: flex; align-items: center; gap: 12px;
|
|
450
|
+
padding: 14px 18px;
|
|
451
|
+
cursor: pointer;
|
|
452
|
+
list-style: none;
|
|
453
|
+
font: var(--axi-t-label);
|
|
454
|
+
letter-spacing: var(--axi-ls-label);
|
|
455
|
+
color: var(--axi-text);
|
|
456
|
+
}
|
|
457
|
+
.axi-accordion__head::-webkit-details-marker { display: none; }
|
|
458
|
+
.axi-accordion__head::before {
|
|
459
|
+
content: "";
|
|
460
|
+
width: 8px; height: 8px; flex: none;
|
|
461
|
+
background: var(--axi-accent);
|
|
462
|
+
border: var(--axi-border-hairline) solid var(--axi-ink-line);
|
|
463
|
+
transform: rotate(45deg);
|
|
464
|
+
transition: transform .12s;
|
|
465
|
+
}
|
|
466
|
+
/* A 135deg turn, not the quarter turn "45deg to 180deg" might suggest by the
|
|
467
|
+
numbers alone: a literal quarter turn on a square lands back on the same
|
|
468
|
+
silhouette and would erase the open/closed cue. */
|
|
469
|
+
.axi-accordion[open] .axi-accordion__head::before { transform: rotate(180deg); }
|
|
470
|
+
.axi-accordion__body {
|
|
471
|
+
padding: 0 18px 16px 38px;
|
|
472
|
+
font: var(--axi-t-small);
|
|
473
|
+
color: var(--axi-text-dim);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/* ---------- toasts ---------- */
|
|
477
|
+
/* Layer 60, between the drawer and the tooltip.
|
|
478
|
+
The region is a layout box and nothing else, sized only by its content -
|
|
479
|
+
it sets no width or height of its own, so an empty one is zero-area and
|
|
480
|
+
pointer-events: none is not there to stop it covering the page. It is
|
|
481
|
+
there because the flex gaps between stacked toasts would otherwise eat
|
|
482
|
+
clicks aimed at the corner beneath them. The toasts themselves take their
|
|
483
|
+
events back.
|
|
484
|
+
This language ships no script, so appearing, stacking and leaving on a
|
|
485
|
+
timer are the consumer's: insert a .axi-toast into the region and remove it
|
|
486
|
+
when it is done. That is the same contract .axi-menu already publishes for
|
|
487
|
+
its open state, not a new kind of promise. */
|
|
488
|
+
.axi-toasts {
|
|
489
|
+
position: fixed;
|
|
490
|
+
right: var(--axi-gutter);
|
|
491
|
+
bottom: var(--axi-gutter);
|
|
492
|
+
z-index: 60;
|
|
493
|
+
display: flex;
|
|
494
|
+
flex-direction: column;
|
|
495
|
+
align-items: flex-end;
|
|
496
|
+
gap: calc(var(--axi-offset-control) + 9px);
|
|
497
|
+
pointer-events: none;
|
|
498
|
+
}
|
|
499
|
+
/* Control weight and control block, not panel: a stack of four panels over
|
|
500
|
+
the page is a wall. A toast is a chip-sized raised thing. */
|
|
501
|
+
.axi-toast {
|
|
502
|
+
pointer-events: auto;
|
|
503
|
+
display: flex; align-items: center; gap: 12px;
|
|
504
|
+
padding: 12px 15px;
|
|
505
|
+
background: var(--axi-surface-raised);
|
|
506
|
+
backdrop-filter: var(--axi-surface-filter);
|
|
507
|
+
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
508
|
+
border-radius: var(--axi-radius-sm);
|
|
509
|
+
box-shadow: var(--axi-shadow-control);
|
|
510
|
+
font: var(--axi-t-small);
|
|
511
|
+
color: var(--axi-text);
|
|
512
|
+
}
|
|
513
|
+
.axi-toast__dot {
|
|
514
|
+
width: 10px; height: 10px; flex: none;
|
|
515
|
+
background: var(--axi-accent);
|
|
516
|
+
border: var(--axi-border-hairline) solid var(--axi-ink-line);
|
|
517
|
+
transform: rotate(45deg);
|
|
518
|
+
}
|
|
519
|
+
.axi-toast--ok .axi-toast__dot { background: var(--axi-ok); }
|
|
520
|
+
.axi-toast--warn .axi-toast__dot { background: var(--axi-warn); }
|
|
521
|
+
.axi-toast--danger .axi-toast__dot { background: var(--axi-danger); }
|
package/src/tokens.css
CHANGED
|
@@ -20,6 +20,15 @@
|
|
|
20
20
|
--axi-text-dim: #a7b0be;
|
|
21
21
|
--axi-text-faint: #7c8695;
|
|
22
22
|
--axi-scrim: rgba(6, 7, 9, .72); /* behind a drawer */
|
|
23
|
+
/* What a surface does to whatever is behind it. `none` here, and `none` is
|
|
24
|
+
genuinely inert - it paints nothing and, unlike a transform, establishes
|
|
25
|
+
no containing block, so the fixed-descendant trap rule 4 documents stays
|
|
26
|
+
closed. It exists so a theme has somewhere to put the answer: a glass
|
|
27
|
+
theme makes the surfaces translucent and restates this token, and the
|
|
28
|
+
blur arrives on every surface at once without one component learning the
|
|
29
|
+
word. This is the toll the Themes section describes - a theme cannot
|
|
30
|
+
invent a capability, so the capability is declared here first, inert. */
|
|
31
|
+
--axi-surface-filter: none;
|
|
23
32
|
|
|
24
33
|
/* --- accent & status --- */
|
|
25
34
|
--axi-accent: #ffc53d;
|
|
@@ -27,6 +36,13 @@
|
|
|
27
36
|
enough to pass contrast on this ground; an app choosing a dark accent
|
|
28
37
|
overrides this to --axi-text rather than editing components. */
|
|
29
38
|
--axi-accent-ink: var(--axi-ink-line);
|
|
39
|
+
/* Text drawn on top of a STATUS fill (an ok/warn/danger chip, a close
|
|
40
|
+
button gone red). Identical to --axi-ink-line today, which is precisely
|
|
41
|
+
why it has to exist: components were spelling this "the outline colour"
|
|
42
|
+
and it happened to read correctly. A theme that makes the outline light
|
|
43
|
+
would otherwise put light text on a bright fill and lose the word. Same
|
|
44
|
+
idea as --axi-accent-ink above, for the fills that are not the accent. */
|
|
45
|
+
--axi-ink-on-fill: var(--axi-ink-line);
|
|
30
46
|
--axi-meta: #4ec3ff; /* the one cool ink: meta only, never a status */
|
|
31
47
|
--axi-ok: #2fd38a;
|
|
32
48
|
--axi-warn: #ff7a2f;
|
|
@@ -45,6 +61,15 @@
|
|
|
45
61
|
block instead of admitting bare literals. */
|
|
46
62
|
--axi-offset-panel-hover: 10px;
|
|
47
63
|
--axi-offset-control-hover: 6px;
|
|
64
|
+
/* The block itself, composed once. A component asks for "the panel block",
|
|
65
|
+
not for an offset it then has to assemble into a shadow correctly four
|
|
66
|
+
times per file - and a theme gets one place to restate what raising a
|
|
67
|
+
thing looks like. The shape is still rule 3's: two equal offsets, zero
|
|
68
|
+
blur, the outline ink. */
|
|
69
|
+
--axi-shadow-panel: var(--axi-offset-panel) var(--axi-offset-panel) 0 var(--axi-ink-line);
|
|
70
|
+
--axi-shadow-control: var(--axi-offset-control) var(--axi-offset-control) 0 var(--axi-ink-line);
|
|
71
|
+
--axi-shadow-panel-hover: var(--axi-offset-panel-hover) var(--axi-offset-panel-hover) 0 var(--axi-ink-line);
|
|
72
|
+
--axi-shadow-control-hover: var(--axi-offset-control-hover) var(--axi-offset-control-hover) 0 var(--axi-ink-line);
|
|
48
73
|
/* The form is sharp. A hard outline, a hard block and a rounded corner are
|
|
49
74
|
three decisions, and the rounded one softens the other two: the corner is
|
|
50
75
|
the first place a flat outlined shape can start looking like a button in
|