aerolith 1.0.0 → 1.2.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/LICENSE +4 -0
- package/README.md +61 -108
- package/library/dist/aerolith.css +171 -16
- package/library/dist/aerolith.js +289 -36
- package/library/dist/fonts/OFL-Aerolith-Display.txt +100 -0
- package/library/dist/fonts/OFL-Aerolith-Text.txt +97 -0
- package/library/dist/fonts/OFL-Istok-Web.txt +94 -0
- package/library/dist/fonts/aerolith-display-aqua.bmp.woff2 +0 -0
- package/library/dist/fonts/aerolith-display-aqua.svg.woff2 +0 -0
- package/library/dist/fonts/aerolith-display-glass-dark.bmp.woff2 +0 -0
- package/library/dist/fonts/aerolith-display-glass-dark.svg.woff2 +0 -0
- package/library/dist/fonts/aerolith-display-glass.bmp.woff2 +0 -0
- package/library/dist/fonts/aerolith-display-glass.svg.woff2 +0 -0
- package/library/dist/fonts/aerolith-display-pearl.bmp.woff2 +0 -0
- package/library/dist/fonts/aerolith-display-pearl.svg.woff2 +0 -0
- package/library/dist/fonts/aerolith-text-bold.woff2 +0 -0
- package/library/dist/fonts/aerolith-text-light.woff2 +0 -0
- package/library/dist/fonts/aerolith-text-regular.woff2 +0 -0
- package/library/dist/fonts/aerolith-text-semibold.woff2 +0 -0
- package/library/dist/fonts/istok-web-bold-italic.woff2 +0 -0
- package/library/dist/fonts/istok-web-bold.woff2 +0 -0
- package/library/dist/fonts/istok-web-italic.woff2 +0 -0
- package/library/dist/fonts/istok-web-regular.woff2 +0 -0
- package/library/dist/sprites/lens.dark@1x.png +0 -0
- package/library/dist/sprites/lens.dark@2x.png +0 -0
- package/library/dist/sprites/lens.dark@3x.png +0 -0
- package/library/dist/sprites/lens@1x.png +0 -0
- package/library/dist/sprites/lens@2x.png +0 -0
- package/library/dist/sprites/lens@3x.png +0 -0
- package/library/dist/sprites/logo-aqua@1x.png +0 -0
- package/library/dist/sprites/logo-aqua@2x.png +0 -0
- package/library/dist/sprites/logo-aqua@3x.png +0 -0
- package/library/dist/sprites/logo-liquid@1x.png +0 -0
- package/library/dist/sprites/logo-liquid@2x.png +0 -0
- package/library/dist/sprites/logo-liquid@3x.png +0 -0
- package/library/dist/sprites.json +88 -0
- package/package.json +7 -5
package/LICENSE
CHANGED
|
@@ -21,5 +21,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
21
21
|
SOFTWARE.
|
|
22
22
|
|
|
23
23
|
The rendered sprite images in library/dist/ are covered by the same license.
|
|
24
|
+
The fonts in library/dist/fonts/ are not: they are under the SIL Open Font
|
|
25
|
+
License 1.1 (Istok Web, Aerolith Text, which is derived from Selawik, and
|
|
26
|
+
Aerolith Display, which is derived from Istok Web). Their license files are in
|
|
27
|
+
that folder.
|
|
24
28
|
Bryce is a trademark of its respective owner. This project is not affiliated
|
|
25
29
|
with or endorsed by it, and contains no part of the Bryce software.
|
package/README.md
CHANGED
|
@@ -1,32 +1,21 @@
|
|
|
1
1
|
# Aerolith
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Tactile UI for the web. Every button, field, pane, icon and title letter is a Bryce 2 render
|
|
4
|
+
(1996), laid over plain HTML elements.
|
|
5
5
|
|
|
6
6
|
**[Live showcase](https://immineal.github.io/aerolith/)** · [npm](https://www.npmjs.com/package/aerolith) · [Changelog](CHANGELOG.md)
|
|
7
7
|
|
|
8
|
-

|
|
14
9
|
|
|
15
10
|
## Use it
|
|
16
11
|
|
|
17
|
-
No build step
|
|
12
|
+
No build step:
|
|
18
13
|
|
|
19
14
|
```html
|
|
20
15
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aerolith@1/library/dist/aerolith.css">
|
|
21
16
|
<script src="https://cdn.jsdelivr.net/npm/aerolith@1/library/dist/aerolith.js" defer></script>
|
|
22
17
|
```
|
|
23
18
|
|
|
24
|
-
The same files are on GitHub through jsDelivr
|
|
25
|
-
(`https://cdn.jsdelivr.net/gh/immineal/aerolith@v1.0.0/library/dist/aerolith.css`) and in the
|
|
26
|
-
release zip. Keep `sprites/` next to `aerolith.css`; the CSS finds the images relative to itself.
|
|
27
|
-
|
|
28
|
-
Then use native elements with Aerolith classes:
|
|
29
|
-
|
|
30
19
|
```html
|
|
31
20
|
<button class="aer-button">Convert to PDF</button>
|
|
32
21
|
<button class="aer-button aer-secondary aer-l">Start</button>
|
|
@@ -41,39 +30,19 @@ Then use native elements with Aerolith classes:
|
|
|
41
30
|
</button>
|
|
42
31
|
```
|
|
43
32
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
### Package managers
|
|
33
|
+
`class="aer"` on `<body>` adds the focus ring and reduced-motion rules. The showcase source has an
|
|
34
|
+
example of every component. Self-hosting: keep `sprites/` and `fonts/` next to `aerolith.css`.
|
|
48
35
|
|
|
49
36
|
| Where | Install | Then |
|
|
50
37
|
|---|---|---|
|
|
51
|
-
| npm | `npm i aerolith` | `import "aerolith/aerolith.css"` (and `
|
|
52
|
-
| GitHub Packages | `npm i @immineal/aerolith --registry=https://npm.pkg.github.com` | same
|
|
38
|
+
| npm | `npm i aerolith` | `import "aerolith/aerolith.css"` (and `aerolith/aerolith.js`) |
|
|
39
|
+
| GitHub Packages | `npm i @immineal/aerolith --registry=https://npm.pkg.github.com` | same |
|
|
53
40
|
| Composer | `composer require immineal/aerolith` | serve `vendor/immineal/aerolith/library/dist/` |
|
|
54
41
|
| PyPI | `pip install aerolith` | `aerolith.static_dir()`; Django: add `"aerolith"` to `INSTALLED_APPS` |
|
|
55
|
-
| CDN |
|
|
56
|
-
|
|
57
|
-
### Frameworks
|
|
58
|
-
|
|
59
|
-
Aerolith is plain CSS classes on native elements, so it needs no wrapper components. Import the
|
|
60
|
-
stylesheet once:
|
|
61
|
-
|
|
62
|
-
```js
|
|
63
|
-
// React (Vite, Next.js), Vue, Svelte, Solid: in your entry file or root layout
|
|
64
|
-
import "aerolith/aerolith.css";
|
|
65
|
-
import "aerolith/aerolith.js"; // optional: slider fill, drop zone, theme switch, lens
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
```astro
|
|
69
|
-
---
|
|
70
|
-
// Astro: in a layout
|
|
71
|
-
import "aerolith/aerolith.css";
|
|
72
|
-
---
|
|
73
|
-
```
|
|
42
|
+
| CDN | jsDelivr, unpkg, esm.sh | or `cdn.jsdelivr.net/gh/immineal/aerolith@v1.2.0/library/dist/aerolith.css` |
|
|
74
43
|
|
|
75
|
-
|
|
76
|
-
|
|
44
|
+
React, Vue, Svelte, Astro: import the CSS once in your entry file and use the classes
|
|
45
|
+
(`className` in JSX). Content added after load needs `window.Aerolith.init(container)`.
|
|
77
46
|
|
|
78
47
|
## Components
|
|
79
48
|
|
|
@@ -86,7 +55,7 @@ routing), call `window.Aerolith.init(container)` to wire up the optional behavio
|
|
|
86
55
|
| `.aer-check`, `.aer-radio` | checkbox, radio | checked, mixed, disabled |
|
|
87
56
|
| `.aer-field` | `<input>`, `<textarea>`, `<select>` | focus, disabled |
|
|
88
57
|
| `.aer-select` | wrapper around `select.aer-field` | |
|
|
89
|
-
| `.aer-segmented` | radios in labels, or links with `aria-current` | hover, selected |
|
|
58
|
+
| `.aer-segmented` | radios in labels, or links with `aria-current` | hover, selected (slides with the JS) |
|
|
90
59
|
| `.aer-choice` | `<label>` with a radio or checkbox | hover, checked, focus |
|
|
91
60
|
| `.aer-drop` | `<label>` with `<input type="file">` | drag-over, focus |
|
|
92
61
|
| `.aer-progress` | `<progress>` | value |
|
|
@@ -98,95 +67,79 @@ routing), call `window.Aerolith.init(container)` to wire up the optional behavio
|
|
|
98
67
|
| `.aer-dialog`, `.aer-close` | `<dialog>`, `<button>` | open, backdrop |
|
|
99
68
|
| `.aer-popover`, `.aer-menu` | `[popover]` | item hover/focus |
|
|
100
69
|
| `.aer-bar` | `<header>`, `<nav>` | |
|
|
101
|
-
| `.aer-lens` | any block | rim refraction
|
|
70
|
+
| `.aer-lens` | any block | rim refraction; `data-aer-drag` makes it movable |
|
|
102
71
|
| `.aer-compare` | two `<img>` and an `<input type="range">` | |
|
|
72
|
+
| `.aer-display` (+ `.aer-aqua`, `.aer-glass`, `.aer-pearl`) | any heading | 116 characters |
|
|
103
73
|
|
|
104
|
-
|
|
105
|
-
or scope it with `.aer-dark`. The theme switch (`input[data-aer-theme]`) sets the attribute and
|
|
106
|
-
remembers the choice.
|
|
74
|
+
### Type
|
|
107
75
|
|
|
108
|
-
|
|
76
|
+
```html
|
|
77
|
+
<h1 class="aer-display">Welcome back</h1> <!-- aqua; glass on dark pages -->
|
|
78
|
+
<h2 class="aer-display aer-glass">Photos</h2> <!-- clear glass: needs colour behind it -->
|
|
79
|
+
<p class="aer-display aer-pearl">Ready</p> <!-- white, for coloured backgrounds -->
|
|
80
|
+
```
|
|
109
81
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
area, before the text halo is added: white on aqua 4.4:1, white on green 4.7:1, dark ink on
|
|
114
|
-
clear glass at least 4.6:1 in both themes. Hover and pressed states are lighter, so their
|
|
115
|
-
labels get a stronger halo.
|
|
116
|
-
- Controls are 44 px high by default. Small controls (checkbox, radio, close orb) get a 44 px hit
|
|
117
|
-
area through their label or a pseudo-element.
|
|
118
|
-
- `forced-colors` (Windows high contrast) drops the sprites and falls back to system colours.
|
|
119
|
-
Icons switch to `CanvasText`.
|
|
120
|
-
- `prefers-reduced-motion` stops the spinner and the toggle, toast and dialog animations.
|
|
121
|
-
- Where look and accessibility conflict, the look won, but only after the cheap fixes (ink
|
|
122
|
-
choice, halos, hit areas) were in. Without their halo, glossy hover states measure 3.3 to
|
|
123
|
-
3.6:1 and pressed states about 2.4:1, because the sunken face catches more light. Both are
|
|
124
|
-
momentary states. `python3 library/build/a11y.py` prints the numbers for every labelled sprite.
|
|
82
|
+
Aerolith Display is a colour font of rendered gel letters, so titles stay real, selectable text.
|
|
83
|
+
Use it from 32 px up. Each material is about 0.6 MB, loaded only where used. Browsers without
|
|
84
|
+
colour fonts show heavy Istok.
|
|
125
85
|
|
|
126
|
-
|
|
86
|
+
Body text is **Aerolith Text**, Selawik (an open Segoe UI stand-in) with a kern table, because Selawik
|
|
87
|
+
ships without kerning. `data-aer-type="istok"` switches to **Istok Web**. Dark mode follows the system; `data-theme="dark"` or `"light"` on `<html>` forces it,
|
|
88
|
+
and the sun/moon switch (`input[data-aer-theme]`) sets that for you.
|
|
127
89
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
Bryce 2.1 for Windows runs under Wine on a virtual X display, seven instances side by side. Python
|
|
131
|
-
writes each scene directly as a Bryce `.brc` file. The format was reverse-engineered for this:
|
|
132
|
-
see [docs/brc-format.md](docs/brc-format.md). Bryce then renders it to disk. Each sprite is
|
|
133
|
-
rendered three times:
|
|
90
|
+
## Accessibility
|
|
134
91
|
|
|
135
|
-
|
|
136
|
-
2. **W:** over mid grey, so the difference to K shows how much light the glass lets through.
|
|
137
|
-
3. **M:** flat colours, a mask that says which pixels are solid and which are glass.
|
|
92
|
+
Real form controls sit under every skin, so keyboards, screen readers and autofill work as usual.
|
|
138
93
|
|
|
139
|
-
|
|
140
|
-
|
|
94
|
+
- Label contrast, measured on the rendered pixels: white on aqua 4.4:1, white on green 4.7:1,
|
|
95
|
+
dark on glass 4.6:1 or better. Hover states measure 3.3 to 3.6:1 without their halo, pressed
|
|
96
|
+
about 2.4:1. There the look won. `python3 library/build/a11y.py` prints every number.
|
|
97
|
+
- Controls are 44 px high; small ones get a 44 px hit area.
|
|
98
|
+
- `forced-colors` swaps the sprites for system colours. `prefers-reduced-motion` stops the
|
|
99
|
+
animations.
|
|
141
100
|
|
|
142
|
-
|
|
143
|
-
their neighbours, which looks random once the sheet is cut up. The camera sits 4000 units away
|
|
144
|
-
with a long lens, so the projection is near-orthographic and one CSS pixel is exactly six render
|
|
145
|
-
pixels. That is downsampled to 3x, 2x and 1x files.
|
|
101
|
+
## How it's made
|
|
146
102
|
|
|
147
|
-

|
|
148
104
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
105
|
+
Bryce 2.1 runs under Wine on virtual displays, seven at once. Python writes each scene as a
|
|
106
|
+
`.brc` file; I reverse-engineered the format in [docs/brc-format.md](docs/brc-format.md). Each
|
|
107
|
+
sprite is rendered alone, three times: over black (colour and glints), over grey (how much light
|
|
108
|
+
the glass lets through) and as a flat mask. From those the build makes PNGs where gloss is solid
|
|
109
|
+
and glass is see-through.
|
|
152
110
|
|
|
153
|
-
|
|
154
|
-
an eased bevel, a blurred-mask bowl for pressed states, a recessed well for fields, and icons
|
|
155
|
-
embossed from vector drawings. The CSS draws every sprite with `border-image`, with slices
|
|
156
|
-
measured in raw image pixels per resolution. That behaves the same in Chromium, Firefox and
|
|
157
|
-
WebKit, where `image-set()` inside `border-image` does not.
|
|
111
|
+

|
|
158
112
|
|
|
159
|
-
|
|
113
|
+
Behind the camera is a sky and a meadow with two hills, so every button reflects blue on top and
|
|
114
|
+
green below. The shapes are height fields computed in NumPy. The CSS draws sprites with
|
|
115
|
+
`border-image`.
|
|
160
116
|
|
|
161
|
-
|
|
162
|
-
You need your own copy of Bryce 2 for Windows and Wine. Neither is included, and Bryce never will
|
|
163
|
-
be.
|
|
117
|
+
To render new sprites you need Wine and your own copy of Bryce 2 (not included):
|
|
164
118
|
|
|
165
119
|
```sh
|
|
166
120
|
cd library/build
|
|
167
|
-
python3 build.py # renders what changed
|
|
168
|
-
python3 build.py btn- # only sprites
|
|
121
|
+
python3 build.py # renders what changed, exports to dist/
|
|
122
|
+
python3 build.py btn- # only sprites starting with btn-
|
|
169
123
|
python3 build.py --export-only
|
|
170
|
-
python3 shots.py # screenshots in Chromium, Firefox, WebKit, light and dark
|
|
171
124
|
```
|
|
172
125
|
|
|
173
|
-
|
|
126
|
+
Setup: [harness/README.md](harness/README.md). Design rules:
|
|
174
127
|
[docs/ui-library/foundations.md](docs/ui-library/foundations.md).
|
|
175
128
|
|
|
176
129
|
## What it does not do
|
|
177
130
|
|
|
178
|
-
- **No
|
|
179
|
-
- **
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
own elements.
|
|
186
|
-
- **No icon font or SVG set.** The 35 icons are bitmaps at 16 and 24 px. They don't scale up
|
|
187
|
-
cleanly.
|
|
131
|
+
- **No colour picker.** Colours are baked into the renders.
|
|
132
|
+
- **Three heights.** 32, 44 or 56 px; buttons stretch sideways only.
|
|
133
|
+
- **The lens bends light in Chromium, and in Firefox with `data-aer-lens-backdrop="#el"`** (the
|
|
134
|
+
element behind it). Safari shows plain glass.
|
|
135
|
+
- **No framework components.** Put the classes on your own elements.
|
|
136
|
+
- **Bitmap icons and titles.** Icons are 16 and 24 px. Titles are sharp up to about 120 px and
|
|
137
|
+
cover Latin with German and French accents.
|
|
188
138
|
|
|
189
139
|
## License
|
|
190
140
|
|
|
191
|
-
MIT
|
|
192
|
-
|
|
141
|
+
MIT for code and sprites ([LICENSE](LICENSE)). Fonts in `library/dist/fonts/` are SIL OFL 1.1:
|
|
142
|
+
Istok Web (Andrey V. Panov) unmodified; Aerolith Text, derived from Selawik (Microsoft) with a kern
|
|
143
|
+
table added and renamed because the OFL reserves "Selawik"; Aerolith Display, derived from
|
|
144
|
+
Istok Web Bold. Bryce is a trademark of its owner; Aerolith is not affiliated and contains no
|
|
145
|
+
Bryce code.
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
--aer-target-gap: var(--aer-space-2);
|
|
22
22
|
|
|
23
23
|
/* type: modular scale 1.2 */
|
|
24
|
-
--aer-font-ui: "
|
|
24
|
+
--aer-font-ui: "Aerolith Text", "Selawik", "Segoe UI", "Istok Web", "Myriad Pro", Tahoma, system-ui, sans-serif; /* bundled: type.css */
|
|
25
25
|
--aer-font-text: var(--aer-font-ui);
|
|
26
26
|
--aer-font-mono: "Consolas", "Lucida Console", ui-monospace, monospace;
|
|
27
27
|
--aer-text-xs: 0.833rem;
|
|
@@ -68,6 +68,13 @@
|
|
|
68
68
|
/* 10-foot / distance media: scale everything so the visual angle stays comfortable at ~3 m */
|
|
69
69
|
.aer-distance { font-size: 150%; --aer-control: var(--aer-control-l); }
|
|
70
70
|
|
|
71
|
+
/* Chromium on Linux and Windows rounds every glyph advance to whole pixels unless asked for precise
|
|
72
|
+
geometry: a 16 px label came out 1.6 px wider with an open gap after the f in "verfügbar".
|
|
73
|
+
Scoped to our own controls; a host page keeps its own text-rendering. */
|
|
74
|
+
:is(.aer-button, .aer-field, .aer-select, .aer-badge, .aer-segmented, .aer-menu, .aer-label, .aer-option,
|
|
75
|
+
.aer-choice, .aer-check, .aer-radio, .aer-toggle, .aer-panel, .aer-card, .aer-callout, .aer-dialog,
|
|
76
|
+
.aer-popover, .aer-toast) { text-rendering: geometricPrecision; }
|
|
77
|
+
|
|
71
78
|
/* label text on glossy sprites: white + halo (WCAG measures text against its halo) */
|
|
72
79
|
.aer-on-gloss {
|
|
73
80
|
color: var(--aer-on-gloss);
|
|
@@ -89,7 +96,7 @@
|
|
|
89
96
|
@media (forced-colors: active) {
|
|
90
97
|
.aer [class*="aer-"] { border-color: ButtonText; }
|
|
91
98
|
.aer-button, .aer-field, .aer-panel { border: 1px solid ButtonText !important; }
|
|
92
|
-
.aer-button:focus-visible { outline: 2px solid Highlight; }
|
|
99
|
+
.aer-button:focus-visible, .aer .aer-field:focus-visible, .aer-field:focus-visible { outline: 2px solid Highlight; }
|
|
93
100
|
}
|
|
94
101
|
|
|
95
102
|
/* utilities */
|
|
@@ -98,6 +105,80 @@
|
|
|
98
105
|
clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
|
|
99
106
|
}
|
|
100
107
|
|
|
108
|
+
/* ---- type.css ---- */
|
|
109
|
+
/* Aerolith type.
|
|
110
|
+
Text: Aerolith Text (default; Selawik with a kern table, renamed because the OFL reserves "Selawik")
|
|
111
|
+
or Istok Web (data-aer-type="istok"), both bundled, both SIL OFL 1.1.
|
|
112
|
+
Titles: Aerolith Display, gel letters rendered in Bryce and packed into colour fonts. Each
|
|
113
|
+
material comes as OpenType-SVG (Firefox, Safari) and sbix (Chromium); tech() makes a browser
|
|
114
|
+
download only the file it can draw. The fonts keep outlines, so a browser without colour-font
|
|
115
|
+
support still shows the title, in plain heavy Istok. */
|
|
116
|
+
|
|
117
|
+
@font-face { font-family: "Istok Web"; src: url(fonts/istok-web-regular.woff2) format("woff2");
|
|
118
|
+
font-weight: 400; font-style: normal; font-display: swap; }
|
|
119
|
+
@font-face { font-family: "Istok Web"; src: url(fonts/istok-web-italic.woff2) format("woff2");
|
|
120
|
+
font-weight: 400; font-style: italic; font-display: swap; }
|
|
121
|
+
@font-face { font-family: "Istok Web"; src: url(fonts/istok-web-bold.woff2) format("woff2");
|
|
122
|
+
font-weight: 700; font-style: normal; font-display: swap; }
|
|
123
|
+
@font-face { font-family: "Istok Web"; src: url(fonts/istok-web-bold-italic.woff2) format("woff2");
|
|
124
|
+
font-weight: 700; font-style: italic; font-display: swap; }
|
|
125
|
+
|
|
126
|
+
@font-face { font-family: "Aerolith Text"; src: url(fonts/aerolith-text-light.woff2) format("woff2");
|
|
127
|
+
font-weight: 300; font-display: swap; }
|
|
128
|
+
@font-face { font-family: "Aerolith Text"; src: url(fonts/aerolith-text-regular.woff2) format("woff2");
|
|
129
|
+
font-weight: 400; font-display: swap; }
|
|
130
|
+
@font-face { font-family: "Aerolith Text"; src: url(fonts/aerolith-text-semibold.woff2) format("woff2");
|
|
131
|
+
font-weight: 600; font-display: swap; }
|
|
132
|
+
@font-face { font-family: "Aerolith Text"; src: url(fonts/aerolith-text-bold.woff2) format("woff2");
|
|
133
|
+
font-weight: 700; font-display: swap; }
|
|
134
|
+
|
|
135
|
+
@font-face { font-family: "Aerolith Display Aqua"; font-display: swap;
|
|
136
|
+
src: url(fonts/aerolith-display-aqua.svg.woff2) format("woff2") tech(color-SVG),
|
|
137
|
+
url(fonts/aerolith-display-aqua.bmp.woff2) format("woff2") tech(color-sbix); }
|
|
138
|
+
@font-face { font-family: "Aerolith Display Glass"; font-display: swap;
|
|
139
|
+
src: url(fonts/aerolith-display-glass.svg.woff2) format("woff2") tech(color-SVG),
|
|
140
|
+
url(fonts/aerolith-display-glass.bmp.woff2) format("woff2") tech(color-sbix); }
|
|
141
|
+
@font-face { font-family: "Aerolith Display Glass Dark"; font-display: swap;
|
|
142
|
+
src: url(fonts/aerolith-display-glass-dark.svg.woff2) format("woff2") tech(color-SVG),
|
|
143
|
+
url(fonts/aerolith-display-glass-dark.bmp.woff2) format("woff2") tech(color-sbix); }
|
|
144
|
+
@font-face { font-family: "Aerolith Display Pearl"; font-display: swap;
|
|
145
|
+
src: url(fonts/aerolith-display-pearl.svg.woff2) format("woff2") tech(color-SVG),
|
|
146
|
+
url(fonts/aerolith-display-pearl.bmp.woff2) format("woff2") tech(color-sbix); }
|
|
147
|
+
|
|
148
|
+
[data-aer-type="istok"], .aer-type-istok {
|
|
149
|
+
--aer-font-ui: "Istok Web", "Aerolith Text", "Segoe UI", Tahoma, system-ui, sans-serif;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Big titles only: the letters are rendered at about 80 px per em and read best from 32 px up.
|
|
153
|
+
Weight 700 picks the bold text face while the font loads; the colour face itself has one weight and is
|
|
154
|
+
never synthesised. */
|
|
155
|
+
.aer-display {
|
|
156
|
+
--_face: "Aerolith Display Aqua";
|
|
157
|
+
font-family: var(--_face), var(--aer-font-ui);
|
|
158
|
+
font-weight: 700; font-style: normal; font-synthesis: none;
|
|
159
|
+
line-height: 1.12; letter-spacing: 0; text-shadow: none;
|
|
160
|
+
color: var(--aer-ink);
|
|
161
|
+
}
|
|
162
|
+
/* Glass is clear: it needs colour or a picture behind it and all but vanishes on a pale page.
|
|
163
|
+
On dark pages the default face is Glass Dark, because Aqua's deep blue sinks into them
|
|
164
|
+
(APCA Lc about -22 against Glass Dark's -54). .aer-aqua keeps Aqua anyway, e.g. on a light
|
|
165
|
+
panel inside a dark page. */
|
|
166
|
+
.aer-display.aer-aqua { --_face: "Aerolith Display Aqua"; }
|
|
167
|
+
.aer-display.aer-glass { --_face: "Aerolith Display Glass"; }
|
|
168
|
+
.aer-display.aer-pearl { --_face: "Aerolith Display Pearl"; }
|
|
169
|
+
:root[data-theme="dark"] .aer-display:not(.aer-aqua, .aer-pearl),
|
|
170
|
+
.aer-dark .aer-display:not(.aer-aqua, .aer-pearl),
|
|
171
|
+
.aer-display.aer-dark:not(.aer-aqua, .aer-pearl) { --_face: "Aerolith Display Glass Dark"; }
|
|
172
|
+
@media (prefers-color-scheme: dark) {
|
|
173
|
+
:root:not([data-theme="light"]) .aer-display:not(.aer-aqua, .aer-pearl) { --_face: "Aerolith Display Glass Dark"; }
|
|
174
|
+
}
|
|
175
|
+
@media (forced-colors: active) {
|
|
176
|
+
.aer-display { font-family: var(--aer-font-ui); }
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* Vista-style glow: a soft halo of page colour behind dark text on glass or busy backgrounds */
|
|
180
|
+
.aer-glow { text-shadow: 0 0 1px var(--aer-page), 0 0 6px var(--aer-page), 0 0 12px var(--aer-page); }
|
|
181
|
+
|
|
101
182
|
/* ---- sprites.css ---- */
|
|
102
183
|
:root {
|
|
103
184
|
--aer-badge-error-w: 60px; --aer-badge-error-h: 22px;
|
|
@@ -256,6 +337,10 @@
|
|
|
256
337
|
--aer-lens-w: 160px; --aer-lens-h: 120px;
|
|
257
338
|
--aer-lens-border: 37px 37px 37px 37px;
|
|
258
339
|
--aer-lens-outset: 1px 1px 1px 1px;
|
|
340
|
+
--aer-logo-aqua-w: 36px; --aer-logo-aqua-h: 36px;
|
|
341
|
+
--aer-logo-aqua-outset: 0 0 0 0;
|
|
342
|
+
--aer-logo-liquid-w: 36px; --aer-logo-liquid-h: 36px;
|
|
343
|
+
--aer-logo-liquid-outset: 0 0 0 0;
|
|
259
344
|
--aer-orb-error-w: 16px; --aer-orb-error-h: 16px;
|
|
260
345
|
--aer-orb-error-outset: 1px 1px 1px 1px;
|
|
261
346
|
--aer-orb-info-w: 16px; --aer-orb-info-h: 16px;
|
|
@@ -420,6 +505,8 @@
|
|
|
420
505
|
--aer-iconbtn-primary-hover: url("sprites/iconbtn-primary-hover@1x.png");
|
|
421
506
|
--aer-lens: url("sprites/lens@1x.png");
|
|
422
507
|
--aer-lens-slice: 37 37 37 37 fill;
|
|
508
|
+
--aer-logo-aqua: url("sprites/logo-aqua@1x.png");
|
|
509
|
+
--aer-logo-liquid: url("sprites/logo-liquid@1x.png");
|
|
423
510
|
--aer-orb-error: url("sprites/orb-error@1x.png");
|
|
424
511
|
--aer-orb-info: url("sprites/orb-info@1x.png");
|
|
425
512
|
--aer-orb-ok: url("sprites/orb-ok@1x.png");
|
|
@@ -562,6 +649,8 @@
|
|
|
562
649
|
--aer-iconbtn-primary-hover: url("sprites/iconbtn-primary-hover@2x.png");
|
|
563
650
|
--aer-lens: url("sprites/lens@2x.png");
|
|
564
651
|
--aer-lens-slice: 74 74 74 74 fill;
|
|
652
|
+
--aer-logo-aqua: url("sprites/logo-aqua@2x.png");
|
|
653
|
+
--aer-logo-liquid: url("sprites/logo-liquid@2x.png");
|
|
565
654
|
--aer-orb-error: url("sprites/orb-error@2x.png");
|
|
566
655
|
--aer-orb-info: url("sprites/orb-info@2x.png");
|
|
567
656
|
--aer-orb-ok: url("sprites/orb-ok@2x.png");
|
|
@@ -705,6 +794,8 @@
|
|
|
705
794
|
--aer-iconbtn-primary-hover: url("sprites/iconbtn-primary-hover@3x.png");
|
|
706
795
|
--aer-lens: url("sprites/lens@3x.png");
|
|
707
796
|
--aer-lens-slice: 111 111 111 111 fill;
|
|
797
|
+
--aer-logo-aqua: url("sprites/logo-aqua@3x.png");
|
|
798
|
+
--aer-logo-liquid: url("sprites/logo-liquid@3x.png");
|
|
708
799
|
--aer-orb-error: url("sprites/orb-error@3x.png");
|
|
709
800
|
--aer-orb-info: url("sprites/orb-info@3x.png");
|
|
710
801
|
--aer-orb-ok: url("sprites/orb-ok@3x.png");
|
|
@@ -1119,31 +1210,31 @@
|
|
|
1119
1210
|
|
|
1120
1211
|
/* ---- skins.css ---- */
|
|
1121
1212
|
/* generated by build/build.py: component state -> sprite */
|
|
1122
|
-
.aer-button { --_img: var(--aer-btn-primary-m); --_slice: var(--aer-btn-primary-m-slice); --_bw: var(--aer-btn-primary-m-border); --_out: var(--aer-btn-primary-m-outset); }
|
|
1213
|
+
.aer-button { --_img: var(--aer-btn-primary-m); --_slice: var(--aer-btn-primary-m-slice); --_bw: var(--aer-btn-primary-m-border); --_out: var(--aer-btn-primary-m-outset); --_pre: var(--aer-btn-primary-m-hover), var(--aer-btn-primary-m-active); }
|
|
1123
1214
|
.aer-button:hover { --_img: var(--aer-btn-primary-m-hover); --_slice: var(--aer-btn-primary-m-hover-slice); --_bw: var(--aer-btn-primary-m-hover-border); --_out: var(--aer-btn-primary-m-hover-outset); }
|
|
1124
1215
|
.aer-button:active, .aer-button[aria-pressed="true"] { --_img: var(--aer-btn-primary-m-active); --_slice: var(--aer-btn-primary-m-active-slice); --_bw: var(--aer-btn-primary-m-active-border); --_out: var(--aer-btn-primary-m-active-outset); }
|
|
1125
|
-
.aer-button.aer-s { --_img: var(--aer-btn-primary-s); --_slice: var(--aer-btn-primary-s-slice); --_bw: var(--aer-btn-primary-s-border); --_out: var(--aer-btn-primary-s-outset); }
|
|
1216
|
+
.aer-button.aer-s { --_img: var(--aer-btn-primary-s); --_slice: var(--aer-btn-primary-s-slice); --_bw: var(--aer-btn-primary-s-border); --_out: var(--aer-btn-primary-s-outset); --_pre: var(--aer-btn-primary-s-hover), var(--aer-btn-primary-s-active); }
|
|
1126
1217
|
.aer-button.aer-s:hover { --_img: var(--aer-btn-primary-s-hover); --_slice: var(--aer-btn-primary-s-hover-slice); --_bw: var(--aer-btn-primary-s-hover-border); --_out: var(--aer-btn-primary-s-hover-outset); }
|
|
1127
1218
|
.aer-button.aer-s:active, .aer-button.aer-s[aria-pressed="true"] { --_img: var(--aer-btn-primary-s-active); --_slice: var(--aer-btn-primary-s-active-slice); --_bw: var(--aer-btn-primary-s-active-border); --_out: var(--aer-btn-primary-s-active-outset); }
|
|
1128
|
-
.aer-button.aer-l { --_img: var(--aer-btn-primary-l); --_slice: var(--aer-btn-primary-l-slice); --_bw: var(--aer-btn-primary-l-border); --_out: var(--aer-btn-primary-l-outset); }
|
|
1219
|
+
.aer-button.aer-l { --_img: var(--aer-btn-primary-l); --_slice: var(--aer-btn-primary-l-slice); --_bw: var(--aer-btn-primary-l-border); --_out: var(--aer-btn-primary-l-outset); --_pre: var(--aer-btn-primary-l-hover), var(--aer-btn-primary-l-active); }
|
|
1129
1220
|
.aer-button.aer-l:hover { --_img: var(--aer-btn-primary-l-hover); --_slice: var(--aer-btn-primary-l-hover-slice); --_bw: var(--aer-btn-primary-l-hover-border); --_out: var(--aer-btn-primary-l-hover-outset); }
|
|
1130
1221
|
.aer-button.aer-l:active, .aer-button.aer-l[aria-pressed="true"] { --_img: var(--aer-btn-primary-l-active); --_slice: var(--aer-btn-primary-l-active-slice); --_bw: var(--aer-btn-primary-l-active-border); --_out: var(--aer-btn-primary-l-active-outset); }
|
|
1131
|
-
.aer-button.aer-secondary { --_img: var(--aer-btn-secondary-m); --_slice: var(--aer-btn-secondary-m-slice); --_bw: var(--aer-btn-secondary-m-border); --_out: var(--aer-btn-secondary-m-outset); }
|
|
1222
|
+
.aer-button.aer-secondary { --_img: var(--aer-btn-secondary-m); --_slice: var(--aer-btn-secondary-m-slice); --_bw: var(--aer-btn-secondary-m-border); --_out: var(--aer-btn-secondary-m-outset); --_pre: var(--aer-btn-secondary-m-hover), var(--aer-btn-secondary-m-active); }
|
|
1132
1223
|
.aer-button.aer-secondary:hover { --_img: var(--aer-btn-secondary-m-hover); --_slice: var(--aer-btn-secondary-m-hover-slice); --_bw: var(--aer-btn-secondary-m-hover-border); --_out: var(--aer-btn-secondary-m-hover-outset); }
|
|
1133
1224
|
.aer-button.aer-secondary:active, .aer-button.aer-secondary[aria-pressed="true"] { --_img: var(--aer-btn-secondary-m-active); --_slice: var(--aer-btn-secondary-m-active-slice); --_bw: var(--aer-btn-secondary-m-active-border); --_out: var(--aer-btn-secondary-m-active-outset); }
|
|
1134
|
-
.aer-button.aer-secondary.aer-s { --_img: var(--aer-btn-secondary-s); --_slice: var(--aer-btn-secondary-s-slice); --_bw: var(--aer-btn-secondary-s-border); --_out: var(--aer-btn-secondary-s-outset); }
|
|
1225
|
+
.aer-button.aer-secondary.aer-s { --_img: var(--aer-btn-secondary-s); --_slice: var(--aer-btn-secondary-s-slice); --_bw: var(--aer-btn-secondary-s-border); --_out: var(--aer-btn-secondary-s-outset); --_pre: var(--aer-btn-secondary-s-hover), var(--aer-btn-secondary-s-active); }
|
|
1135
1226
|
.aer-button.aer-secondary.aer-s:hover { --_img: var(--aer-btn-secondary-s-hover); --_slice: var(--aer-btn-secondary-s-hover-slice); --_bw: var(--aer-btn-secondary-s-hover-border); --_out: var(--aer-btn-secondary-s-hover-outset); }
|
|
1136
1227
|
.aer-button.aer-secondary.aer-s:active, .aer-button.aer-secondary.aer-s[aria-pressed="true"] { --_img: var(--aer-btn-secondary-s-active); --_slice: var(--aer-btn-secondary-s-active-slice); --_bw: var(--aer-btn-secondary-s-active-border); --_out: var(--aer-btn-secondary-s-active-outset); }
|
|
1137
|
-
.aer-button.aer-secondary.aer-l { --_img: var(--aer-btn-secondary-l); --_slice: var(--aer-btn-secondary-l-slice); --_bw: var(--aer-btn-secondary-l-border); --_out: var(--aer-btn-secondary-l-outset); }
|
|
1228
|
+
.aer-button.aer-secondary.aer-l { --_img: var(--aer-btn-secondary-l); --_slice: var(--aer-btn-secondary-l-slice); --_bw: var(--aer-btn-secondary-l-border); --_out: var(--aer-btn-secondary-l-outset); --_pre: var(--aer-btn-secondary-l-hover), var(--aer-btn-secondary-l-active); }
|
|
1138
1229
|
.aer-button.aer-secondary.aer-l:hover { --_img: var(--aer-btn-secondary-l-hover); --_slice: var(--aer-btn-secondary-l-hover-slice); --_bw: var(--aer-btn-secondary-l-hover-border); --_out: var(--aer-btn-secondary-l-hover-outset); }
|
|
1139
1230
|
.aer-button.aer-secondary.aer-l:active, .aer-button.aer-secondary.aer-l[aria-pressed="true"] { --_img: var(--aer-btn-secondary-l-active); --_slice: var(--aer-btn-secondary-l-active-slice); --_bw: var(--aer-btn-secondary-l-active-border); --_out: var(--aer-btn-secondary-l-active-outset); }
|
|
1140
|
-
.aer-button.aer-quiet { --_img: var(--aer-btn-glass-m); --_slice: var(--aer-btn-glass-m-slice); --_bw: var(--aer-btn-glass-m-border); --_out: var(--aer-btn-glass-m-outset); }
|
|
1231
|
+
.aer-button.aer-quiet { --_img: var(--aer-btn-glass-m); --_slice: var(--aer-btn-glass-m-slice); --_bw: var(--aer-btn-glass-m-border); --_out: var(--aer-btn-glass-m-outset); --_pre: var(--aer-btn-glass-m-hover), var(--aer-btn-glass-m-active); }
|
|
1141
1232
|
.aer-button.aer-quiet:hover { --_img: var(--aer-btn-glass-m-hover); --_slice: var(--aer-btn-glass-m-hover-slice); --_bw: var(--aer-btn-glass-m-hover-border); --_out: var(--aer-btn-glass-m-hover-outset); }
|
|
1142
1233
|
.aer-button.aer-quiet:active, .aer-button.aer-quiet[aria-pressed="true"] { --_img: var(--aer-btn-glass-m-active); --_slice: var(--aer-btn-glass-m-active-slice); --_bw: var(--aer-btn-glass-m-active-border); --_out: var(--aer-btn-glass-m-active-outset); }
|
|
1143
|
-
.aer-button.aer-quiet.aer-s { --_img: var(--aer-btn-glass-s); --_slice: var(--aer-btn-glass-s-slice); --_bw: var(--aer-btn-glass-s-border); --_out: var(--aer-btn-glass-s-outset); }
|
|
1234
|
+
.aer-button.aer-quiet.aer-s { --_img: var(--aer-btn-glass-s); --_slice: var(--aer-btn-glass-s-slice); --_bw: var(--aer-btn-glass-s-border); --_out: var(--aer-btn-glass-s-outset); --_pre: var(--aer-btn-glass-s-hover), var(--aer-btn-glass-s-active); }
|
|
1144
1235
|
.aer-button.aer-quiet.aer-s:hover { --_img: var(--aer-btn-glass-s-hover); --_slice: var(--aer-btn-glass-s-hover-slice); --_bw: var(--aer-btn-glass-s-hover-border); --_out: var(--aer-btn-glass-s-hover-outset); }
|
|
1145
1236
|
.aer-button.aer-quiet.aer-s:active, .aer-button.aer-quiet.aer-s[aria-pressed="true"] { --_img: var(--aer-btn-glass-s-active); --_slice: var(--aer-btn-glass-s-active-slice); --_bw: var(--aer-btn-glass-s-active-border); --_out: var(--aer-btn-glass-s-active-outset); }
|
|
1146
|
-
.aer-button.aer-quiet.aer-l { --_img: var(--aer-btn-glass-l); --_slice: var(--aer-btn-glass-l-slice); --_bw: var(--aer-btn-glass-l-border); --_out: var(--aer-btn-glass-l-outset); }
|
|
1237
|
+
.aer-button.aer-quiet.aer-l { --_img: var(--aer-btn-glass-l); --_slice: var(--aer-btn-glass-l-slice); --_bw: var(--aer-btn-glass-l-border); --_out: var(--aer-btn-glass-l-outset); --_pre: var(--aer-btn-glass-l-hover), var(--aer-btn-glass-l-active); }
|
|
1147
1238
|
.aer-button.aer-quiet.aer-l:hover { --_img: var(--aer-btn-glass-l-hover); --_slice: var(--aer-btn-glass-l-hover-slice); --_bw: var(--aer-btn-glass-l-hover-border); --_out: var(--aer-btn-glass-l-hover-outset); }
|
|
1148
1239
|
.aer-button.aer-quiet.aer-l:active, .aer-button.aer-quiet.aer-l[aria-pressed="true"] { --_img: var(--aer-btn-glass-l-active); --_slice: var(--aer-btn-glass-l-active-slice); --_bw: var(--aer-btn-glass-l-active-border); --_out: var(--aer-btn-glass-l-active-outset); }
|
|
1149
1240
|
.aer-button:disabled, .aer-button[aria-disabled="true"] { --_img: var(--aer-btn-disabled-m); --_slice: var(--aer-btn-disabled-m-slice); --_bw: var(--aer-btn-disabled-m-border); --_out: var(--aer-btn-disabled-m-outset); }
|
|
@@ -1371,6 +1462,8 @@
|
|
|
1371
1462
|
.aer-field:focus {
|
|
1372
1463
|
border-image: var(--aer-field-focus) var(--aer-field-focus-slice) / var(--aer-field-focus-border) / var(--aer-field-focus-outset) stretch;
|
|
1373
1464
|
}
|
|
1465
|
+
/* the rendered aqua rim is the focus indicator: the square outline would cut across the rounded well */
|
|
1466
|
+
.aer .aer-field:focus-visible, .aer-field:focus-visible { outline: none; }
|
|
1374
1467
|
textarea.aer-field { block-size: auto; min-block-size: calc(var(--aer-control) * 2); padding-block: var(--aer-space-3); resize: vertical; line-height: var(--aer-leading); }
|
|
1375
1468
|
.aer-field:disabled, .aer-field[readonly] { color: var(--aer-ink-muted); }
|
|
1376
1469
|
.aer-label { display: grid; gap: var(--aer-space-1); font: 600 var(--aer-text-s) / 1.3 var(--aer-font-ui); color: var(--aer-ink); }
|
|
@@ -1546,6 +1639,20 @@ a.aer-card:hover, button.aer-card:hover, .aer-card[data-interactive]:hover {
|
|
|
1546
1639
|
}
|
|
1547
1640
|
.aer-segmented > :has(:focus-visible) { outline: 2px solid var(--aer-focus); outline-offset: 2px; }
|
|
1548
1641
|
.aer-segmented > :has(:disabled) { opacity: 0.5; cursor: not-allowed; }
|
|
1642
|
+
/* with aerolith.js: one pill carries the chip and slides; the items' own chips give way */
|
|
1643
|
+
.aer-segmented[data-aer-slide] { position: relative; isolation: isolate; }
|
|
1644
|
+
.aer-seg-pill {
|
|
1645
|
+
position: absolute; left: 0; top: 0; z-index: -1; box-sizing: border-box; pointer-events: none;
|
|
1646
|
+
border-style: solid; border-color: transparent; border-width: 0;
|
|
1647
|
+
border-image: var(--aer-seg-chip) var(--aer-seg-chip-slice) / var(--aer-seg-chip-border) / var(--aer-seg-chip-outset) stretch;
|
|
1648
|
+
}
|
|
1649
|
+
.aer-segmented[data-aer-ready] > .aer-seg-pill {
|
|
1650
|
+
transition: transform 300ms cubic-bezier(.3, 1.2, .5, 1), width 300ms cubic-bezier(.3, 1.2, .5, 1);
|
|
1651
|
+
}
|
|
1652
|
+
.aer-segmented[data-aer-slide] > :is(:has(:checked), [aria-current]:not([aria-current="false"]), [aria-selected="true"], [aria-pressed="true"]) {
|
|
1653
|
+
border-image: none;
|
|
1654
|
+
}
|
|
1655
|
+
.aer-segmented[data-aer-ready] > :not(.aer-seg-pill) { transition: color 200ms, text-shadow 200ms; }
|
|
1549
1656
|
|
|
1550
1657
|
/* ------------------------------------------------------------------ choice card: a whole tile is the radio/checkbox
|
|
1551
1658
|
<label class="aer-choice"><input type="radio" class="aer-radio" name="f"> <b>PDF</b> <small>…</small></label> */
|
|
@@ -1622,9 +1729,14 @@ a.aer-card:hover, button.aer-card:hover, .aer-card[data-interactive]:hover {
|
|
|
1622
1729
|
border-style: solid; border-color: transparent; border-width: 0;
|
|
1623
1730
|
border-image: var(--aer-card) var(--aer-card-slice) / var(--aer-card-border) / var(--aer-card-outset) stretch;
|
|
1624
1731
|
color: var(--aer-ink); font: var(--aer-text-m) / 1.4 var(--aer-font-text);
|
|
1732
|
+
border-radius: 14px; -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
|
|
1625
1733
|
animation: aer-toast-in 260ms cubic-bezier(.3, 1.4, .5, 1);
|
|
1626
1734
|
}
|
|
1627
1735
|
@keyframes aer-toast-in { from { opacity: 0; translate: 0 12px; } }
|
|
1736
|
+
@media (max-width: 600px) { /* phones: centred, clear of the screen edges */
|
|
1737
|
+
.aer-toaster { inset-inline: var(--aer-space-4); justify-items: center; }
|
|
1738
|
+
.aer-toast { max-inline-size: 100%; }
|
|
1739
|
+
}
|
|
1628
1740
|
|
|
1629
1741
|
/* ------------------------------------------------------------------ dialog: frosted window on native <dialog>
|
|
1630
1742
|
<dialog class="aer-dialog"><header>…<button class="aer-close" aria-label="Close">…</button></header>…</dialog> */
|
|
@@ -1635,7 +1747,8 @@ a.aer-card:hover, button.aer-card:hover, .aer-card[data-interactive]:hover {
|
|
|
1635
1747
|
background: none; color: var(--aer-ink); font: var(--aer-text-m) / var(--aer-leading) var(--aer-font-text);
|
|
1636
1748
|
overflow: visible;
|
|
1637
1749
|
}
|
|
1638
|
-
.aer-dialog::backdrop { background: rgba(8, 40, 80, 0.
|
|
1750
|
+
.aer-dialog::backdrop { background: rgba(8, 40, 80, 0.34);
|
|
1751
|
+
-webkit-backdrop-filter: blur(8px) saturate(1.2); backdrop-filter: blur(8px) saturate(1.2); }
|
|
1639
1752
|
.aer-dialog > header { display: flex; align-items: center; justify-content: space-between; gap: var(--aer-space-3);
|
|
1640
1753
|
margin: calc(-1 * var(--aer-space-2)) 0 var(--aer-space-3); font: 600 var(--aer-text-l) / 1.3 var(--aer-font-ui); }
|
|
1641
1754
|
.aer-dialog[open] { animation: aer-dialog-in 220ms cubic-bezier(.3, 1.3, .5, 1); }
|
|
@@ -1647,7 +1760,7 @@ a.aer-card:hover, button.aer-card:hover, .aer-card[data-interactive]:hover {
|
|
|
1647
1760
|
display: inline-grid; place-items: center; inline-size: 24px; block-size: 24px;
|
|
1648
1761
|
border-style: solid; border-color: transparent; border-width: 0;
|
|
1649
1762
|
border-image: var(--aer-close) 0 fill / 0 / var(--aer-close-outset) stretch;
|
|
1650
|
-
background: none; cursor: pointer;
|
|
1763
|
+
background: none; cursor: pointer; border-radius: 50%; /* the focus ring follows the gem */
|
|
1651
1764
|
}
|
|
1652
1765
|
.aer-close::after { content: ""; position: absolute; inset: -10px; }
|
|
1653
1766
|
.aer-close:hover { border-image: var(--aer-close-hover) 0 fill / 0 / var(--aer-close-hover-outset) stretch; }
|
|
@@ -1662,8 +1775,10 @@ a.aer-card:hover, button.aer-card:hover, .aer-card[data-interactive]:hover {
|
|
|
1662
1775
|
border-image: var(--aer-card) var(--aer-card-slice) / var(--aer-card-border) / var(--aer-card-outset) stretch;
|
|
1663
1776
|
background: none; color: var(--aer-ink); font: var(--aer-text-m) / 1.4 var(--aer-font-text);
|
|
1664
1777
|
overflow: visible;
|
|
1778
|
+
border-radius: 14px; -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
|
|
1665
1779
|
}
|
|
1666
1780
|
.aer-menu { display: grid; gap: 2px; }
|
|
1781
|
+
[data-aer-menu] { -webkit-touch-callout: none; } /* long-press opens our menu, not the system's */
|
|
1667
1782
|
.aer-menu > :is(a, button) {
|
|
1668
1783
|
display: flex; align-items: center; gap: var(--aer-space-2); box-sizing: border-box;
|
|
1669
1784
|
min-block-size: 36px; padding: 0 var(--aer-space-3); margin: 0;
|
|
@@ -1735,20 +1850,59 @@ a.aer-card:hover, button.aer-card:hover, .aer-card[data-interactive]:hover {
|
|
|
1735
1850
|
}
|
|
1736
1851
|
.aer-bar > .aer-spacer { flex: 1; }
|
|
1737
1852
|
|
|
1738
|
-
/* ------------------------------------------------------------------ lens: clear thick glass
|
|
1739
|
-
|
|
1853
|
+
/* ------------------------------------------------------------------ lens: clear thick glass. aerolith.js adds the
|
|
1854
|
+
refraction of its rim (an SVG displacement map computed from the same bevel profile): in Chromium, and in
|
|
1855
|
+
Firefox when data-aer-lens-backdrop names the element behind it. Safari shows plain glass. */
|
|
1740
1856
|
.aer-lens {
|
|
1741
1857
|
position: relative; box-sizing: border-box; padding: var(--aer-space-5);
|
|
1742
1858
|
border-style: solid; border-color: transparent; border-width: 0;
|
|
1743
1859
|
border-image: var(--aer-lens) var(--aer-lens-slice) / var(--aer-lens-border) / var(--aer-lens-outset) stretch;
|
|
1744
1860
|
color: var(--aer-ink);
|
|
1745
1861
|
}
|
|
1862
|
+
/* with a backdrop copy: copy at the bottom, glass sprite over it, content on top */
|
|
1863
|
+
.aer-lens[data-aer-lens-view] { isolation: isolate; border-image: none; }
|
|
1864
|
+
.aer-lens[data-aer-lens-view]::before {
|
|
1865
|
+
content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
|
|
1866
|
+
border-style: solid; border-color: transparent; border-width: 0;
|
|
1867
|
+
border-image: var(--aer-lens) var(--aer-lens-slice) / var(--aer-lens-border) / var(--aer-lens-outset) stretch;
|
|
1868
|
+
}
|
|
1869
|
+
.aer-lens-view { position: absolute; z-index: -2; overflow: hidden; pointer-events: none; } /* placed by aerolith.js */
|
|
1870
|
+
/* the focus ring follows the glass, not a square box */
|
|
1871
|
+
.aer-lens[data-aer-drag] { border-radius: 24px; }
|
|
1872
|
+
.aer-lens[data-aer-drag] { cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
|
|
1873
|
+
.aer-lens[data-aer-dragging] { cursor: grabbing; }
|
|
1746
1874
|
|
|
1747
1875
|
/* ------------------------------------------------------------------ preferences */
|
|
1876
|
+
/* ------------------------------------------------------------------ state sprites, fetched up front
|
|
1877
|
+
Each control lists its hover / pressed / checked sprites in --_pre; they hang off it as zero-size
|
|
1878
|
+
backgrounds, so the browser downloads them with the page (at the same resolution and theme the state
|
|
1879
|
+
will use) and a first tap never shows an empty control while its state sprite loads. */
|
|
1880
|
+
.aer-iconbtn { --_pre: var(--aer-iconbtn-primary-hover), var(--aer-iconbtn-primary-active); }
|
|
1881
|
+
.aer-iconbtn.aer-quiet { --_pre: var(--aer-iconbtn-glass-hover), var(--aer-iconbtn-glass-active); }
|
|
1882
|
+
.aer-toggle { --_pre: var(--aer-toggle-track-on), var(--aer-toggle-knob-on); }
|
|
1883
|
+
.aer-toggle.aer-theme { --_pre: var(--aer-toggle-knob-moon); }
|
|
1884
|
+
.aer-check { --_pre: var(--aer-check-on), var(--aer-check-mixed); }
|
|
1885
|
+
.aer-radio { --_pre: var(--aer-radio-on); }
|
|
1886
|
+
.aer-segmented, .aer-menu { --_pre: var(--aer-seg-chip-hover), var(--aer-seg-chip); }
|
|
1887
|
+
.aer-choice { --_pre: var(--aer-card-hover), var(--aer-choice-on); }
|
|
1888
|
+
a.aer-card, button.aer-card, .aer-card[data-interactive] { --_pre: var(--aer-card-hover); }
|
|
1889
|
+
.aer-close { --_pre: var(--aer-close-hover); }
|
|
1890
|
+
.aer-preload { /* added by aerolith.js when the page has dialogs, popovers or toasts */
|
|
1891
|
+
position: fixed; inset-inline-start: -1px; inset-block-start: -1px; inline-size: 1px; block-size: 1px;
|
|
1892
|
+
overflow: hidden; pointer-events: none;
|
|
1893
|
+
--_pre: var(--aer-dialog), var(--aer-close), var(--aer-close-hover), var(--aer-card), var(--aer-seg-chip-hover),
|
|
1894
|
+
var(--aer-orb-ok);
|
|
1895
|
+
}
|
|
1896
|
+
.aer-preload, .aer-button, .aer-iconbtn, .aer-toggle, .aer-check, .aer-radio, .aer-segmented, .aer-menu, .aer-choice,
|
|
1897
|
+
a.aer-card, button.aer-card, .aer-card[data-interactive], .aer-close {
|
|
1898
|
+
background-image: var(--_pre, none); background-size: 0 0; background-repeat: no-repeat;
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1748
1901
|
@media (prefers-reduced-motion: reduce) {
|
|
1749
1902
|
.aer-spinner::before { animation: none; }
|
|
1750
1903
|
.aer-toggle::before, .aer-progress::-webkit-progress-value { transition: none; }
|
|
1751
1904
|
.aer-toast, .aer-dialog[open] { animation: none; }
|
|
1905
|
+
.aer-segmented[data-aer-ready] > .aer-seg-pill, .aer-segmented[data-aer-ready] > :not(.aer-seg-pill) { transition: none; }
|
|
1752
1906
|
}
|
|
1753
1907
|
/* forced colours: sprites are dropped, native rendering and system colours take over */
|
|
1754
1908
|
@media (forced-colors: active) {
|
|
@@ -1761,6 +1915,7 @@ a.aer-card:hover, button.aer-card:hover, .aer-card[data-interactive]:hover {
|
|
|
1761
1915
|
background: Highlight; color: HighlightText; forced-color-adjust: none;
|
|
1762
1916
|
}
|
|
1763
1917
|
.aer-toggle, .aer-check, .aer-radio { appearance: auto; border-image: none; }
|
|
1764
|
-
.aer-toggle::before, .aer-spinner::before, .aer-callout::before
|
|
1918
|
+
.aer-toggle::before, .aer-spinner::before, .aer-callout::before, .aer-seg-pill,
|
|
1919
|
+
.aer-lens::before, .aer-lens-view { display: none; }
|
|
1765
1920
|
.aer-spinner { border: 3px dotted CanvasText; border-radius: 50%; }
|
|
1766
1921
|
}
|