@gerege-systems/eid-mongolia-sdk 0.15.0 → 0.15.2
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 +83 -14
- package/dist/button.cjs +55 -45
- package/dist/button.js +55 -45
- package/dist/chunk-52O3T7DZ.js +1043 -0
- package/dist/index.cjs +885 -79
- package/dist/index.d.cts +135 -4
- package/dist/index.d.ts +135 -4
- package/dist/index.js +312 -39
- package/dist/pades.cjs +16 -3
- package/dist/pades.d.cts +5 -0
- package/dist/pades.d.ts +5 -0
- package/dist/pades.js +61 -1028
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,8 +72,10 @@ export const eidLogin = createEidLogin({
|
|
|
72
72
|
};
|
|
73
73
|
},
|
|
74
74
|
// store: redisStore, // олон instance / serverless бол (анхдагч — процессын санах ой)
|
|
75
|
-
// rateLimit: (key) => redisLimiter.allow(key), //
|
|
75
|
+
// rateLimit: { start: (key) => redisLimiter.allow(key) }, // анхдагчтай нэгтгэгдэнэ (push 3/мин хэвээр) — доор «Хязгаарлалт»
|
|
76
76
|
trustProxy: 1, // handle(Request)-д клиент IP: nginx/LB нэг hop бол 1 (доор «Клиент IP»)
|
|
77
|
+
onEvent: ({ kind, sessionId, meta }) => audit.record(`auth.eid_${kind}`, sessionId, meta), // таны аудит
|
|
78
|
+
// auditKey: process.env.EID_AUDIT_KEY, // pushKey-ийг instance/restart хооронд тогтвортой болгох
|
|
77
79
|
});
|
|
78
80
|
```
|
|
79
81
|
|
|
@@ -95,8 +97,27 @@ export const POST = (req: Request) => eidLogin.handle(req);
|
|
|
95
97
|
Vercel `req.headers.get("x-real-ip")`). `trustProxy`-оос давуу.
|
|
96
98
|
|
|
97
99
|
Аль нь ч үгүй бол IP-ээр хязгаарлахгүй (эхний хүсэлтэд `onError`-оор нэг удаа анхааруулна). `handleRequest`-д `req.ip`
|
|
98
|
-
(Express `req.ip`, `app.set("trust proxy", …)`-тэй) шууд хэрэглэгдэнэ.
|
|
99
|
-
|
|
100
|
+
(Express `req.ip`, `app.set("trust proxy", …)`-тэй) шууд хэрэглэгдэнэ. Go: `eidlogin.Config.ClientIP` (`eidlogin.ForwardedClientIP(n)`) — ижил дүрэм.
|
|
101
|
+
|
|
102
|
+
**Хязгаарлалт** (`rateLimit`). Түлхүүр: `start:<ip>` (IP мэдэгдэж байвал), `push:<idCode>`; татгалзвал 429 + `Retry-After: 60`.
|
|
103
|
+
Анхдагч `defaultRateLimit` = `{ push: { limit: 3, windowMs: 60_000 } }` — нэг дугаарт минутад 3 мэдэгдэл (MFA fatigue);
|
|
104
|
+
`start`-ийг анхдагчаар хязгаарладаггүй.
|
|
105
|
+
|
|
106
|
+
- **Объект** `{ start?, push? }` — анхдагчтай **нэгтгэгдэнэ**: өгсөн төрөл анхдагчийг дарна, өгөөгүй нь анхдагчаараа үлдэнэ.
|
|
107
|
+
Утга: `{ limit, windowMs }` (процессын санах ойн гулсах цонх), `(key) => boolean | Promise<boolean>` (Redis г.м.),
|
|
108
|
+
эсвэл `false` (тухайн төрлийг хязгаарлахгүй). Өөр түлхүүр → `createEidLogin` throw.
|
|
109
|
+
- **Функц** `(key) => …` — бүх түлхүүрт дуудагдана, анхдагч хязгаар **дээр нэмэгдэнэ** (хоёулаа зөвшөөрөх ёстой).
|
|
110
|
+
Анхдагчийг сулруулах/солих бол объектоор тухайн төрлийг өг (`{ push: … }`).
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { defaultRateLimit } from "@gerege-systems/eid-mongolia-sdk";
|
|
114
|
+
rateLimit: { start: { limit: 20, windowMs: 60_000 } }, // push 3/мин хэвээр
|
|
115
|
+
rateLimit: { ...defaultRateLimit, start: (k) => redis.allow(k) }, // ижил — анхдагчийг илэрхий бичсэн
|
|
116
|
+
rateLimit: { push: (k) => redis.allow(k, 3, 60) }, // олон instance: push-ийг Redis-ээр солино
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Go: `eidlogin.Config.RateLimits` (`map[string]eidlogin.RateRule{"start": {Max: 20, Window: time.Minute}}`,
|
|
120
|
+
`eidlogin.DefaultRateLimit()`) — ижил нэгтгэл; `Config.RateLimit` функц мөн анхдагч дээр нэмэгдэнэ.
|
|
100
121
|
|
|
101
122
|
Express:
|
|
102
123
|
|
|
@@ -128,21 +149,39 @@ app.use("/auth/eid", express.json(), async (req, res) => {
|
|
|
128
149
|
**Дизайн, theme.** Дизайн нь eID нэвтрэх хуудсынх (лого, өнгө). Фонт нь хуудаснаас өвлөгдөнө (товч, цонх, input бүгд).
|
|
129
150
|
`theme="auto"` үед дараалал: хуудасны `html[data-theme="dark|light"]` → `html.dark` / `html.light` → OS
|
|
130
151
|
(`prefers-color-scheme`); хуудас theme солиход (MutationObserver) шууд дагана. `theme="light|dark"` нь хуудсыг давна.
|
|
131
|
-
Өнгө, радиусыг CSS хувьсагчаар
|
|
152
|
+
Өнгө, радиусыг CSS хувьсагчаар дарна. `--eid-*` нь зөвхөн **оролт** (shadow дотор тодорхойлогддоггүй) тул хуудасны
|
|
153
|
+
аль ч түвшинд (`:root`, эцэг элемент, `eid-login-button`) өгсөн утга өвлөгдөж **light ба dark хоёуланд** үйлчилнэ;
|
|
154
|
+
`--eid-<нэр>-dark` нь зөвхөн dark-д, `--eid-<нэр>`-ээс давуу. Аль нь ч үгүй бол eID-ийн анхдагч (доорх хүснэгт) — fallback л.
|
|
155
|
+
Dark-ийн дараалал: `--eid-<нэр>-dark` → `--eid-<нэр>` → dark анхдагч.
|
|
132
156
|
|
|
133
157
|
```css
|
|
134
|
-
eid-login-button {
|
|
135
|
-
--eid-accent:
|
|
136
|
-
--eid-
|
|
137
|
-
--eid-fg: …; --eid-fg-muted: …; --eid-fg-subtle: …; /* текст */
|
|
138
|
-
--eid-border: …; --eid-border-strong: …; --eid-ring: …; /* хүрээ, focus */
|
|
139
|
-
--eid-warning-bg: …; --eid-warning-border: …; --eid-warning-fg: …; --eid-danger-fg: …;
|
|
158
|
+
:root { /* эсвэл eid-login-button { … } */
|
|
159
|
+
--eid-accent: var(--brand); /* хоёр theme-д */
|
|
160
|
+
--eid-accent-dark: var(--brand-400); /* зөвхөн dark-д (өгөхгүй бол --eid-accent) */
|
|
140
161
|
--eid-radius: 6px; --eid-radius-lg: 8px;
|
|
141
162
|
}
|
|
142
|
-
|
|
143
|
-
eid-login-button::part(button) { width: 100%; } /* part: button, backdrop, dialog */
|
|
163
|
+
eid-login-button::part(button) { width: 100%; } /* part: button, backdrop, dialog */
|
|
144
164
|
```
|
|
145
165
|
|
|
166
|
+
| Хувьсагч (`-dark` хувилбартай) | Юунд | Light анхдагч | Dark анхдагч |
|
|
167
|
+
|---|---|---|---|
|
|
168
|
+
| `--eid-accent` | үндсэн товч | `oklch(0.534 0.2 259)` | `oklch(0.64 0.15 259)` |
|
|
169
|
+
| `--eid-accent-fg` | үндсэн товчны текст | `#fff` | `hsl(229 50% 6%)` |
|
|
170
|
+
| `--eid-accent-subtle` | алхмын дугаарын дэвсгэр | `oklch(0.97 0.03 259)` | `oklch(0.24 0.06 259)` |
|
|
171
|
+
| `--eid-accent-subtle-fg` | алхмын дугаар | `oklch(0.474 0.19 259)` | `oklch(0.82 0.1 259)` |
|
|
172
|
+
| `--eid-ring` | focus | `oklch(0.604 0.2 259)` | `oklch(0.68 0.15 259)` |
|
|
173
|
+
| `--eid-bg` | цонх, outline товч, input | `hsl(0 0% 100%)` | `hsl(229 50% 6%)` |
|
|
174
|
+
| `--eid-bg-subtle` | — (нөөц) | `hsl(210 40% 98%)` | `hsl(222 47% 9%)` |
|
|
175
|
+
| `--eid-bg-muted` | hover | `hsl(210 40% 96%)` | `hsl(217 33% 13%)` |
|
|
176
|
+
| `--eid-fg` | текст | `hsl(222 47% 11%)` | `hsl(210 40% 98%)` |
|
|
177
|
+
| `--eid-fg-muted` | хоёрдогч текст | `hsl(215 19% 35%)` | `hsl(213 27% 84%)` |
|
|
178
|
+
| `--eid-fg-subtle` | тайлбар, placeholder | `hsl(215 16% 45%)` | `hsl(215 20% 65%)` |
|
|
179
|
+
| `--eid-border` | цонх, QR, тусгаарлагч | `hsl(214 32% 91%)` | `hsl(217 33% 17%)` |
|
|
180
|
+
| `--eid-border-strong` | outline товч, input | `hsl(213 27% 84%)` | `hsl(215 25% 27%)` |
|
|
181
|
+
| `--eid-warning-bg` / `-border` / `-fg` | сүлжээний анхааруулга | `hsl(48 100% 96%)` / `hsl(45 95% 78%)` / `hsl(23 75% 33%)` | `hsl(20 60% 10%)` / `hsl(22 70% 26%)` / `hsl(40 92% 65%)` |
|
|
182
|
+
| `--eid-danger-fg` | алдаа | `hsl(0 74% 42%)` | `hsl(0 91% 71%)` |
|
|
183
|
+
| `--eid-radius` / `--eid-radius-lg` (theme-гүй) | булан | `6px` / `8px` | — |
|
|
184
|
+
|
|
146
185
|
**eID аппын доод хувилбар.** `flowType` бэхлэлт (device link v3) ба Web2App-ийн `userChallengeVerifier` нь
|
|
147
186
|
**iOS 2.2.3 (build 59)**, **Android 2.2.3 (versionCode 60)**-аас эхэлсэн. eID сервер 2026-10-07-оос legacy холбоосыг
|
|
148
187
|
бүрэн хассан (v3-гүй session-д утас `DEVICE_LINK_REQUIRED`) бөгөөд доод хувилбарыг `/mobile/app-config`-оор албадан
|
|
@@ -160,7 +199,31 @@ RP талд нэмэлт шалгалт хэрэггүй. Эх сурвалж: e
|
|
|
160
199
|
- `OK` нь зөвхөн `validateAuth` амжилттай үед: QR → `flowType=QR`, push → `Notification`, утас → `Web2App` + callback-ийн
|
|
161
200
|
`userChallengeVerifier`. Web2App session-ийг poll дуусгахгүй (`WAIT_CALLBACK`). `onSuccess` нэг session-д нэг л удаа
|
|
162
201
|
(store-ийн `delete` атомар байх ёстой — Redis `DEL`).
|
|
163
|
-
- `onSuccess`-ийн `data` хөтөчид очно — нууц бүү оруул.
|
|
202
|
+
- `onSuccess`-ийн `data` хөтөчид очно — нууц бүү оруул.
|
|
203
|
+
- **Регистрийн oracle хаалт (decoy + доод хугацаа, анхдагчаар асаалттай).** eID push-ийг дугаарын шалтгаанаар татгалзвал
|
|
204
|
+
(eID-ийн өөрийн JSON 4xx — танихгүй / ашиглах боломжгүй дугаар) бодит push-тэй **ижил** хариу: `{mode, vc (санамсаргүй
|
|
205
|
+
5 оронтой — eID-тэй ижил хэлбэр), expiresIn}`, ижил cookie; `status` нь eID-ээс асуулгүй `pollMs`-ийн хугацаанд барьж
|
|
206
|
+
`PENDING`, TTL-ийн дараа `EXPIRED` — утсаа аваагүй иргэнтэй ялгаагүй (бодит push-ийн CA `TIMEOUT` ч `EXPIRED` болно). Push start-ийн хариу бүр (бодит, decoy, 502)
|
|
207
|
+
`pushFloorMs`-оос (анхдагч 1000) хурдан гарахгүй — decoy-г цагаар ялгахгүйн тулд (`handle(Request)`-д хүсэлт тасарвал
|
|
208
|
+
хүлээхгүй; `handleRequest`-д `signal` өг). Хязгаар (`push:<idCode>`, `start:<ip>`) decoy-д ч үйлчилнэ; 429 ба 400
|
|
209
|
+
(`invalid_id` — хэлбэрийн алдаа, бүртгэлээс хамааралгүй) нь floor-гүй. eID-ийн 5xx, холболтын алдаа, JSON бус 4xx (eID-ийн
|
|
210
|
+
өмнөх proxy, ж: mTLS татгалзал), 401/403 (RP-ийн нууц/эрх) ба 429 нь **decoy биш** — `502 eid_unavailable` / `429` (eID
|
|
211
|
+
порталын зан: тасалдлыг decoy-оор нуувал иргэн дуусахгүй spinner харна; эдгээр нь дугаараас хамаардаггүй тул oracle
|
|
212
|
+
биш). Унтраах: `decoy: false`, `pushFloorMs: 0` — **⚠️** тэгвэл `/start` нь «энэ регистр eID-д бүртгэлтэй эсэх»-ийг
|
|
213
|
+
нэвтрээгүй хэнд ч хэлнэ; зөвхөн дотоод/тестийн орчинд.
|
|
214
|
+
- **Гэрчилгээний цуцлалт (OCSP, анхдагчаар асаалттай).** `validateAuth`-ийн дараа, `onSuccess`-ийн өмнө иргэний гэрчилгээг
|
|
215
|
+
түүний AIA-д бичигдсэн OCSP responder-оос асууна (`revocation`, анхдагч `ocspRevocationChecker()`; хариу олгогч эсвэл
|
|
216
|
+
түүний OCSPSigning responder-ийн гарын үсэгтэй, энэ serial-ийн, thisUpdate ≤ 48 цаг, good-ийг 5 мин кэшлэнэ). `revoked`,
|
|
217
|
+
мөн `unknown` (олгогч энэ гэрчилгээг олгоогүй) → `FAILED` / `VALIDATION` (500 биш), `onSuccess` дуудагдахгүй. Хариугүй
|
|
218
|
+
(timeout 2 с, 5xx, AIA алга, шалгалт унасан хариу): `revocationMode` анхдагч `"soft-fail"` — зөвшөөрч `onError`-оор
|
|
219
|
+
анхааруулна, `identity.revocation = "unchecked"` (eID порталын `EID_OCSP=soft`: CA-ийн responder унавал бүх иргэн
|
|
220
|
+
түгжигдэхгүй; утас session-ийг батлахад CA секундын өмнө хүрэх боломжтой байсан); `"hard-fail"` → `FAILED` /
|
|
221
|
+
`VALIDATION`. `revocation: false` — **⚠️** цуцалсан (хулгайлагдсан утасны) гэрчилгээгээр нэвтэрнэ.
|
|
222
|
+
- **Аудит — `onEvent({ kind, sessionId, meta })`** (await хийгдэнэ, алдаа нь `onError` руу): `push_sent` (meta `decoy` —
|
|
223
|
+
зөвхөн таны аудитад, хөтөч рүү хэзээ ч), `push_limited`, `refused` (иргэн татгалзсан), `expired` (TIMEOUT / eID-д
|
|
224
|
+
олдохгүй), `unverified` (`reason`: `validation` | `revoked` | `revocation_unavailable`), `flow_refused` (Web2App callback
|
|
225
|
+
өөр хөтчид), `success` (`flow`, `revocation`), `failed` (бусад `endResult`). meta-д `mode`; токен/нууц, регистрийн дугаар
|
|
226
|
+
орохгүй — push-д `pushKey` = HMAC-SHA256(`auditKey`, дугаар)-ын 32 hex (`auditKey` алга бол процесс бүрт санамсаргүй).
|
|
164
227
|
- Олон instance / serverless (Vercel г.м.) дээр анхдагч санах ойн store ажиллахгүй — `EidLoginStore` (`get`/`set`/`delete`)-ийг Redis-ээр.
|
|
165
228
|
- `onSuccess` дуудагдахаас ӨМНӨ tx store-оос атомар устгагдана (нэг удаагийн баталгаа) — `onSuccess` дотор store-оос бүү
|
|
166
229
|
унш; хэрэгтэй бүхэн `identity`-д (`sessionId`, `documentNumber`, `certificateDerB64`, …).
|
|
@@ -445,6 +508,11 @@ const reg = await eid.registerSignature(registrationFromCompleted(req.body, {
|
|
|
445
508
|
reply({ verifyUrl: reg.verifyUrl });
|
|
446
509
|
```
|
|
447
510
|
|
|
511
|
+
- `reg.created` — `true` 201 (шинэ), `false` 200 (ижил биеийн давталт). Өмнөх гарын үсэг CA-ийн угсарсан (горим A) бол
|
|
512
|
+
`complete().priorRevisionSha256`-ийг (`sha256(doc[0 : ByteRange[2]+ByteRange[3]])`) `registrationFromCompleted`
|
|
513
|
+
`priorSignatures` болгож дамжуулна; `registerSignature` 409 `PRIOR_MISMATCH`-ийн дараа өөрөө revision-оор тааруулна
|
|
514
|
+
(`priorRevisionSha256`-г гараар өгвөл оролдохгүй). Хөтчөөс JSON-оор дамжуулахдаа `priorRevisionSha256`-ийг ч явуул.
|
|
515
|
+
|
|
448
516
|
### Зөвхөн Node (backend бүгдийг хийнэ)
|
|
449
517
|
|
|
450
518
|
```ts
|
|
@@ -589,7 +657,8 @@ OK ирж болзошгүй. Иймд `ResponseValidator`:
|
|
|
589
657
|
хүссэн session-д `ecdsa-with-SHA256` хариу ирвэл хуурамч гэж татгалзана.
|
|
590
658
|
|
|
591
659
|
5. Цуцлалт — `trust.revocation` (OCSP/CRL hook) → `checkRevocation`, эсвэл `checkRevocationStatus` (`"good"` /
|
|
592
|
-
`"unchecked"` (soft-fail) / `"skipped"` (hook алга)).
|
|
660
|
+
`"unchecked"` (soft-fail) / `"skipped"` (hook алга)). Бэлэн hook: `ocspRevocationChecker()` — гэрчилгээний AIA OCSP
|
|
661
|
+
(revoked/unknown → `"revoked"`; хариугүй → `"unknown"`, горим шийднэ). Өөр checker/горимоор нэг удаа: `checkRevocationWith`.
|
|
593
662
|
6. Нэмэлт (сонголттой): `allowedIssuerSkis: [CITIZEN_ISSUING_CA_SKI]` — зөвхөн иргэний Issuing CA (04)-ийн гэрчилгээ;
|
|
594
663
|
`checkKeyUsage: true` — auth → clientAuth, sign → nonRepudiation (CA-ийн профайл); `schemeName` — CA-ийн
|
|
595
664
|
`acsp_scheme_name` (анхдагч `smart-id`).
|
package/dist/button.cjs
CHANGED
|
@@ -465,87 +465,97 @@ var T = {
|
|
|
465
465
|
minute: "1 minute left"
|
|
466
466
|
}
|
|
467
467
|
};
|
|
468
|
+
var EID_COLOR_TOKENS = [
|
|
469
|
+
["bg", "hsl(0 0% 100%)", "hsl(229 50% 6%)"],
|
|
470
|
+
["bg-subtle", "hsl(210 40% 98%)", "hsl(222 47% 9%)"],
|
|
471
|
+
["bg-muted", "hsl(210 40% 96%)", "hsl(217 33% 13%)"],
|
|
472
|
+
["fg", "hsl(222 47% 11%)", "hsl(210 40% 98%)"],
|
|
473
|
+
["fg-muted", "hsl(215 19% 35%)", "hsl(213 27% 84%)"],
|
|
474
|
+
["fg-subtle", "hsl(215 16% 45%)", "hsl(215 20% 65%)"],
|
|
475
|
+
["border", "hsl(214 32% 91%)", "hsl(217 33% 17%)"],
|
|
476
|
+
["border-strong", "hsl(213 27% 84%)", "hsl(215 25% 27%)"],
|
|
477
|
+
["accent", "oklch(0.534 0.2 259)", "oklch(0.64 0.15 259)"],
|
|
478
|
+
["accent-fg", "#fff", "hsl(229 50% 6%)"],
|
|
479
|
+
["accent-subtle", "oklch(0.97 0.03 259)", "oklch(0.24 0.06 259)"],
|
|
480
|
+
["accent-subtle-fg", "oklch(0.474 0.19 259)", "oklch(0.82 0.1 259)"],
|
|
481
|
+
["ring", "oklch(0.604 0.2 259)", "oklch(0.68 0.15 259)"],
|
|
482
|
+
["warning-bg", "hsl(48 100% 96%)", "hsl(20 60% 10%)"],
|
|
483
|
+
["warning-border", "hsl(45 95% 78%)", "hsl(22 70% 26%)"],
|
|
484
|
+
["warning-fg", "hsl(23 75% 33%)", "hsl(40 92% 65%)"],
|
|
485
|
+
["danger-fg", "hsl(0 74% 42%)", "hsl(0 91% 71%)"]
|
|
486
|
+
];
|
|
487
|
+
var lightVars = EID_COLOR_TOKENS.map(([n, l]) => `--_eid-${n}: var(--eid-${n}, ${l});`).join("\n ");
|
|
488
|
+
var darkVars = EID_COLOR_TOKENS.map(([n, , d]) => `--_eid-${n}: var(--eid-${n}-dark, var(--eid-${n}, ${d}));`).join("\n ");
|
|
468
489
|
var CSS_BASE = `
|
|
469
|
-
:host { display: inline-block;
|
|
470
|
-
|
|
471
|
-
--
|
|
472
|
-
--eid-border: hsl(214 32% 91%); --eid-border-strong: hsl(213 27% 84%);
|
|
473
|
-
--eid-accent: oklch(0.534 0.2 259); --eid-accent-fg: #fff; --eid-accent-subtle: oklch(0.97 0.03 259);
|
|
474
|
-
--eid-accent-subtle-fg: oklch(0.474 0.19 259); --eid-ring: oklch(0.604 0.2 259);
|
|
475
|
-
--eid-warning-bg: hsl(48 100% 96%); --eid-warning-border: hsl(45 95% 78%); --eid-warning-fg: hsl(23 75% 33%);
|
|
476
|
-
--eid-danger-fg: hsl(0 74% 42%); --eid-radius: 6px; --eid-radius-lg: 8px; font-family: inherit; color-scheme: light; }
|
|
490
|
+
:host { display: inline-block; font-family: inherit; color-scheme: light;
|
|
491
|
+
${lightVars}
|
|
492
|
+
--_eid-radius: var(--eid-radius, 6px); --_eid-radius-lg: var(--eid-radius-lg, 8px); }
|
|
477
493
|
button, input { font-family: inherit; }
|
|
478
494
|
`;
|
|
479
495
|
var DARK_CSS = `:host { color-scheme: dark;
|
|
480
|
-
|
|
481
|
-
--eid-fg: hsl(210 40% 98%); --eid-fg-muted: hsl(213 27% 84%); --eid-fg-subtle: hsl(215 20% 65%);
|
|
482
|
-
--eid-border: hsl(217 33% 17%); --eid-border-strong: hsl(215 25% 27%);
|
|
483
|
-
--eid-accent: oklch(0.64 0.15 259); --eid-accent-fg: hsl(229 50% 6%); --eid-accent-subtle: oklch(0.24 0.06 259);
|
|
484
|
-
--eid-accent-subtle-fg: oklch(0.82 0.1 259); --eid-ring: oklch(0.68 0.15 259);
|
|
485
|
-
--eid-warning-bg: hsl(20 60% 10%); --eid-warning-border: hsl(22 70% 26%); --eid-warning-fg: hsl(40 92% 65%);
|
|
486
|
-
--eid-danger-fg: hsl(0 91% 71%); }
|
|
496
|
+
${darkVars} }
|
|
487
497
|
`;
|
|
488
498
|
var CSS_REST = `
|
|
489
499
|
*, *::before, *::after { box-sizing: border-box; }
|
|
490
500
|
[hidden] { display: none !important; }
|
|
491
501
|
h2, p, ol { margin: 0; }
|
|
492
|
-
:focus-visible { outline: 2px solid var(--
|
|
502
|
+
:focus-visible { outline: 2px solid var(--_eid-ring); outline-offset: 2px; }
|
|
493
503
|
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
|
494
504
|
.btn { display: inline-flex; width: 100%; align-items: center; justify-content: center; gap: 8px; min-height: 44px; padding: 0 20px;
|
|
495
|
-
border-radius: var(--
|
|
505
|
+
border-radius: var(--_eid-radius); font-family: inherit; font-weight: 500; font-size: 1rem; line-height: 1.25; text-decoration: none; border: 1px solid transparent; cursor: pointer;
|
|
496
506
|
transition: background-color 160ms cubic-bezier(0,0,0.2,1); }
|
|
497
507
|
.btn:disabled { opacity: 0.6; cursor: progress; }
|
|
498
|
-
.btn-primary { background: var(--
|
|
499
|
-
.btn-primary:hover { background: color-mix(in oklab, var(--
|
|
500
|
-
.btn-outline { background: var(--
|
|
501
|
-
.btn-outline:hover { background: var(--
|
|
508
|
+
.btn-primary { background: var(--_eid-accent); color: var(--_eid-accent-fg); }
|
|
509
|
+
.btn-primary:hover { background: color-mix(in oklab, var(--_eid-accent) 88%, black); }
|
|
510
|
+
.btn-outline { background: var(--_eid-bg); color: var(--_eid-fg); border-color: var(--_eid-border-strong); }
|
|
511
|
+
.btn-outline:hover { background: var(--_eid-bg-muted); }
|
|
502
512
|
.btn-sm { width: auto; min-height: 36px; padding: 0 14px; font-size: 0.8125rem; }
|
|
503
513
|
.trigger { width: auto; }
|
|
504
514
|
.trigger img { width: 20px; height: 20px; border-radius: 4px; }
|
|
505
515
|
.backdrop { position: fixed; inset: 0; z-index: 2147483000; background: hsl(222 47% 11% / 0.5); display: flex; align-items: center;
|
|
506
516
|
justify-content: center; padding: 16px; overflow-y: auto; }
|
|
507
|
-
.dialog { position: relative; width: 100%; max-width: 26rem; max-height: calc(100dvh - 32px); overflow-y: auto; background: var(--
|
|
508
|
-
color: var(--
|
|
517
|
+
.dialog { position: relative; width: 100%; max-width: 26rem; max-height: calc(100dvh - 32px); overflow-y: auto; background: var(--_eid-bg);
|
|
518
|
+
color: var(--_eid-fg); border: 1px solid var(--_eid-border); border-radius: var(--_eid-radius-lg); padding: 24px; font-size: 0.875rem; line-height: 1.5rem; }
|
|
509
519
|
@media (max-width: 639px) { .dialog { padding: 16px; } }
|
|
510
520
|
.head { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; }
|
|
511
|
-
.head img { width: 28px; height: 28px; border-radius: var(--
|
|
521
|
+
.head img { width: 28px; height: 28px; border-radius: var(--_eid-radius); }
|
|
512
522
|
.head h2 { flex: 1; font-size: 1.125rem; line-height: 1.75rem; font-weight: 600; }
|
|
513
|
-
.x { width: 36px; height: 36px; border: 0; border-radius: var(--
|
|
514
|
-
.x:hover { background: var(--
|
|
515
|
-
.qr { position: relative; width: 256px; max-width: 100%; aspect-ratio: 1; margin: 0 auto; border: 1px solid var(--
|
|
516
|
-
border-radius: var(--
|
|
523
|
+
.x { width: 36px; height: 36px; border: 0; border-radius: var(--_eid-radius); background: transparent; color: var(--_eid-fg-muted); cursor: pointer; font-size: 1.25rem; line-height: 1; }
|
|
524
|
+
.x:hover { background: var(--_eid-bg-muted); color: var(--_eid-fg); }
|
|
525
|
+
.qr { position: relative; width: 256px; max-width: 100%; aspect-ratio: 1; margin: 0 auto; border: 1px solid var(--_eid-border);
|
|
526
|
+
border-radius: var(--_eid-radius-lg); background: #fff; overflow: hidden; }
|
|
517
527
|
.qr svg { display: block; width: 100%; height: 100%; }
|
|
518
528
|
.qr.stale svg { opacity: 0.12; }
|
|
519
529
|
.qr-stale { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
|
|
520
530
|
color: hsl(222 47% 11%); font-weight: 500; }
|
|
521
|
-
.qr-vc { margin-top: 8px; text-align: center; font-size: 0.8125rem; color: var(--
|
|
522
|
-
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-variant-numeric: tabular-nums; letter-spacing: 0.08em; color: var(--
|
|
531
|
+
.qr-vc { margin-top: 8px; text-align: center; font-size: 0.8125rem; color: var(--_eid-fg-subtle); }
|
|
532
|
+
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-variant-numeric: tabular-nums; letter-spacing: 0.08em; color: var(--_eid-fg-muted); }
|
|
523
533
|
.steps { margin-top: 16px; padding: 0; list-style: none; counter-reset: st; display: grid; gap: 8px; }
|
|
524
534
|
.steps li { counter-increment: st; display: flex; align-items: center; gap: 12px; }
|
|
525
|
-
.steps li::before { content: counter(st); flex: none; width: 24px; height: 24px; border-radius: 9999px; background: var(--
|
|
526
|
-
color: var(--
|
|
527
|
-
.or { display: flex; align-items: center; gap: 12px; margin: 24px 0; color: var(--
|
|
528
|
-
.or::before, .or::after { content: ""; flex: 1; height: 1px; background: var(--
|
|
535
|
+
.steps li::before { content: counter(st); flex: none; width: 24px; height: 24px; border-radius: 9999px; background: var(--_eid-accent-subtle);
|
|
536
|
+
color: var(--_eid-accent-subtle-fg); display: flex; align-items: center; justify-content: center; font-size: 0.75rem; font-weight: 600; }
|
|
537
|
+
.or { display: flex; align-items: center; gap: 12px; margin: 24px 0; color: var(--_eid-fg-subtle); font-size: 0.8125rem; }
|
|
538
|
+
.or::before, .or::after { content: ""; flex: 1; height: 1px; background: var(--_eid-border); }
|
|
529
539
|
.field { display: grid; gap: 8px; }
|
|
530
540
|
.field label { font-weight: 500; }
|
|
531
|
-
.field input { width: 100%; height: 44px; padding: 0 12px; border: 1px solid var(--
|
|
532
|
-
background: var(--
|
|
533
|
-
.field input::placeholder { color: var(--
|
|
534
|
-
.field input[aria-invalid="true"] { border-color: var(--
|
|
535
|
-
.hint { font-size: 0.8125rem; color: var(--
|
|
536
|
-
.err { font-size: 0.8125rem; color: var(--
|
|
541
|
+
.field input { width: 100%; height: 44px; padding: 0 12px; border: 1px solid var(--_eid-border-strong); border-radius: var(--_eid-radius);
|
|
542
|
+
background: var(--_eid-bg); color: var(--_eid-fg); font-family: inherit; font-size: 1rem; line-height: 1.5rem; letter-spacing: 0.02em; text-transform: uppercase; }
|
|
543
|
+
.field input::placeholder { color: var(--_eid-fg-subtle); text-transform: none; }
|
|
544
|
+
.field input[aria-invalid="true"] { border-color: var(--_eid-danger-fg); }
|
|
545
|
+
.hint { font-size: 0.8125rem; color: var(--_eid-fg-subtle); }
|
|
546
|
+
.err { font-size: 0.8125rem; color: var(--_eid-danger-fg); font-weight: 500; }
|
|
537
547
|
.push { margin-top: 16px; }
|
|
538
548
|
.center { text-align: center; }
|
|
539
549
|
.vc { font: 600 2.25rem/2.5rem ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 0.16em; padding-left: 0.16em; }
|
|
540
550
|
.vc:focus, h2:focus { outline: none; }
|
|
541
|
-
.text { margin-top: 12px; color: var(--
|
|
542
|
-
.pending { margin-top: 16px; display: inline-flex; align-items: center; gap: 8px; color: var(--
|
|
551
|
+
.text { margin-top: 12px; color: var(--_eid-fg-muted); }
|
|
552
|
+
.pending { margin-top: 16px; display: inline-flex; align-items: center; gap: 8px; color: var(--_eid-fg-muted); }
|
|
543
553
|
.end .btn, .center .btn { margin-top: 24px; }
|
|
544
554
|
.spinner { width: 16px; height: 16px; flex: none; border: 2px solid currentColor; border-right-color: transparent; border-radius: 9999px; animation: spin 0.8s linear infinite; }
|
|
545
555
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
546
|
-
.netwarn { margin-top: 16px; padding: 8px 12px; border: 1px solid var(--
|
|
547
|
-
color: var(--
|
|
548
|
-
.meta { margin-top: 16px; font-size: 0.8125rem; color: var(--
|
|
556
|
+
.netwarn { margin-top: 16px; padding: 8px 12px; border: 1px solid var(--_eid-warning-border); border-radius: var(--_eid-radius); background: var(--_eid-warning-bg);
|
|
557
|
+
color: var(--_eid-warning-fg); font-size: 0.8125rem; }
|
|
558
|
+
.meta { margin-top: 16px; font-size: 0.8125rem; color: var(--_eid-fg-subtle); }
|
|
549
559
|
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; }
|
|
550
560
|
.spinner { animation: none; border-right-color: currentColor; opacity: 0.6; } }
|
|
551
561
|
`;
|
package/dist/button.js
CHANGED
|
@@ -436,87 +436,97 @@ var T = {
|
|
|
436
436
|
minute: "1 minute left"
|
|
437
437
|
}
|
|
438
438
|
};
|
|
439
|
+
var EID_COLOR_TOKENS = [
|
|
440
|
+
["bg", "hsl(0 0% 100%)", "hsl(229 50% 6%)"],
|
|
441
|
+
["bg-subtle", "hsl(210 40% 98%)", "hsl(222 47% 9%)"],
|
|
442
|
+
["bg-muted", "hsl(210 40% 96%)", "hsl(217 33% 13%)"],
|
|
443
|
+
["fg", "hsl(222 47% 11%)", "hsl(210 40% 98%)"],
|
|
444
|
+
["fg-muted", "hsl(215 19% 35%)", "hsl(213 27% 84%)"],
|
|
445
|
+
["fg-subtle", "hsl(215 16% 45%)", "hsl(215 20% 65%)"],
|
|
446
|
+
["border", "hsl(214 32% 91%)", "hsl(217 33% 17%)"],
|
|
447
|
+
["border-strong", "hsl(213 27% 84%)", "hsl(215 25% 27%)"],
|
|
448
|
+
["accent", "oklch(0.534 0.2 259)", "oklch(0.64 0.15 259)"],
|
|
449
|
+
["accent-fg", "#fff", "hsl(229 50% 6%)"],
|
|
450
|
+
["accent-subtle", "oklch(0.97 0.03 259)", "oklch(0.24 0.06 259)"],
|
|
451
|
+
["accent-subtle-fg", "oklch(0.474 0.19 259)", "oklch(0.82 0.1 259)"],
|
|
452
|
+
["ring", "oklch(0.604 0.2 259)", "oklch(0.68 0.15 259)"],
|
|
453
|
+
["warning-bg", "hsl(48 100% 96%)", "hsl(20 60% 10%)"],
|
|
454
|
+
["warning-border", "hsl(45 95% 78%)", "hsl(22 70% 26%)"],
|
|
455
|
+
["warning-fg", "hsl(23 75% 33%)", "hsl(40 92% 65%)"],
|
|
456
|
+
["danger-fg", "hsl(0 74% 42%)", "hsl(0 91% 71%)"]
|
|
457
|
+
];
|
|
458
|
+
var lightVars = EID_COLOR_TOKENS.map(([n, l]) => `--_eid-${n}: var(--eid-${n}, ${l});`).join("\n ");
|
|
459
|
+
var darkVars = EID_COLOR_TOKENS.map(([n, , d]) => `--_eid-${n}: var(--eid-${n}-dark, var(--eid-${n}, ${d}));`).join("\n ");
|
|
439
460
|
var CSS_BASE = `
|
|
440
|
-
:host { display: inline-block;
|
|
441
|
-
|
|
442
|
-
--
|
|
443
|
-
--eid-border: hsl(214 32% 91%); --eid-border-strong: hsl(213 27% 84%);
|
|
444
|
-
--eid-accent: oklch(0.534 0.2 259); --eid-accent-fg: #fff; --eid-accent-subtle: oklch(0.97 0.03 259);
|
|
445
|
-
--eid-accent-subtle-fg: oklch(0.474 0.19 259); --eid-ring: oklch(0.604 0.2 259);
|
|
446
|
-
--eid-warning-bg: hsl(48 100% 96%); --eid-warning-border: hsl(45 95% 78%); --eid-warning-fg: hsl(23 75% 33%);
|
|
447
|
-
--eid-danger-fg: hsl(0 74% 42%); --eid-radius: 6px; --eid-radius-lg: 8px; font-family: inherit; color-scheme: light; }
|
|
461
|
+
:host { display: inline-block; font-family: inherit; color-scheme: light;
|
|
462
|
+
${lightVars}
|
|
463
|
+
--_eid-radius: var(--eid-radius, 6px); --_eid-radius-lg: var(--eid-radius-lg, 8px); }
|
|
448
464
|
button, input { font-family: inherit; }
|
|
449
465
|
`;
|
|
450
466
|
var DARK_CSS = `:host { color-scheme: dark;
|
|
451
|
-
|
|
452
|
-
--eid-fg: hsl(210 40% 98%); --eid-fg-muted: hsl(213 27% 84%); --eid-fg-subtle: hsl(215 20% 65%);
|
|
453
|
-
--eid-border: hsl(217 33% 17%); --eid-border-strong: hsl(215 25% 27%);
|
|
454
|
-
--eid-accent: oklch(0.64 0.15 259); --eid-accent-fg: hsl(229 50% 6%); --eid-accent-subtle: oklch(0.24 0.06 259);
|
|
455
|
-
--eid-accent-subtle-fg: oklch(0.82 0.1 259); --eid-ring: oklch(0.68 0.15 259);
|
|
456
|
-
--eid-warning-bg: hsl(20 60% 10%); --eid-warning-border: hsl(22 70% 26%); --eid-warning-fg: hsl(40 92% 65%);
|
|
457
|
-
--eid-danger-fg: hsl(0 91% 71%); }
|
|
467
|
+
${darkVars} }
|
|
458
468
|
`;
|
|
459
469
|
var CSS_REST = `
|
|
460
470
|
*, *::before, *::after { box-sizing: border-box; }
|
|
461
471
|
[hidden] { display: none !important; }
|
|
462
472
|
h2, p, ol { margin: 0; }
|
|
463
|
-
:focus-visible { outline: 2px solid var(--
|
|
473
|
+
:focus-visible { outline: 2px solid var(--_eid-ring); outline-offset: 2px; }
|
|
464
474
|
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
|
465
475
|
.btn { display: inline-flex; width: 100%; align-items: center; justify-content: center; gap: 8px; min-height: 44px; padding: 0 20px;
|
|
466
|
-
border-radius: var(--
|
|
476
|
+
border-radius: var(--_eid-radius); font-family: inherit; font-weight: 500; font-size: 1rem; line-height: 1.25; text-decoration: none; border: 1px solid transparent; cursor: pointer;
|
|
467
477
|
transition: background-color 160ms cubic-bezier(0,0,0.2,1); }
|
|
468
478
|
.btn:disabled { opacity: 0.6; cursor: progress; }
|
|
469
|
-
.btn-primary { background: var(--
|
|
470
|
-
.btn-primary:hover { background: color-mix(in oklab, var(--
|
|
471
|
-
.btn-outline { background: var(--
|
|
472
|
-
.btn-outline:hover { background: var(--
|
|
479
|
+
.btn-primary { background: var(--_eid-accent); color: var(--_eid-accent-fg); }
|
|
480
|
+
.btn-primary:hover { background: color-mix(in oklab, var(--_eid-accent) 88%, black); }
|
|
481
|
+
.btn-outline { background: var(--_eid-bg); color: var(--_eid-fg); border-color: var(--_eid-border-strong); }
|
|
482
|
+
.btn-outline:hover { background: var(--_eid-bg-muted); }
|
|
473
483
|
.btn-sm { width: auto; min-height: 36px; padding: 0 14px; font-size: 0.8125rem; }
|
|
474
484
|
.trigger { width: auto; }
|
|
475
485
|
.trigger img { width: 20px; height: 20px; border-radius: 4px; }
|
|
476
486
|
.backdrop { position: fixed; inset: 0; z-index: 2147483000; background: hsl(222 47% 11% / 0.5); display: flex; align-items: center;
|
|
477
487
|
justify-content: center; padding: 16px; overflow-y: auto; }
|
|
478
|
-
.dialog { position: relative; width: 100%; max-width: 26rem; max-height: calc(100dvh - 32px); overflow-y: auto; background: var(--
|
|
479
|
-
color: var(--
|
|
488
|
+
.dialog { position: relative; width: 100%; max-width: 26rem; max-height: calc(100dvh - 32px); overflow-y: auto; background: var(--_eid-bg);
|
|
489
|
+
color: var(--_eid-fg); border: 1px solid var(--_eid-border); border-radius: var(--_eid-radius-lg); padding: 24px; font-size: 0.875rem; line-height: 1.5rem; }
|
|
480
490
|
@media (max-width: 639px) { .dialog { padding: 16px; } }
|
|
481
491
|
.head { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; }
|
|
482
|
-
.head img { width: 28px; height: 28px; border-radius: var(--
|
|
492
|
+
.head img { width: 28px; height: 28px; border-radius: var(--_eid-radius); }
|
|
483
493
|
.head h2 { flex: 1; font-size: 1.125rem; line-height: 1.75rem; font-weight: 600; }
|
|
484
|
-
.x { width: 36px; height: 36px; border: 0; border-radius: var(--
|
|
485
|
-
.x:hover { background: var(--
|
|
486
|
-
.qr { position: relative; width: 256px; max-width: 100%; aspect-ratio: 1; margin: 0 auto; border: 1px solid var(--
|
|
487
|
-
border-radius: var(--
|
|
494
|
+
.x { width: 36px; height: 36px; border: 0; border-radius: var(--_eid-radius); background: transparent; color: var(--_eid-fg-muted); cursor: pointer; font-size: 1.25rem; line-height: 1; }
|
|
495
|
+
.x:hover { background: var(--_eid-bg-muted); color: var(--_eid-fg); }
|
|
496
|
+
.qr { position: relative; width: 256px; max-width: 100%; aspect-ratio: 1; margin: 0 auto; border: 1px solid var(--_eid-border);
|
|
497
|
+
border-radius: var(--_eid-radius-lg); background: #fff; overflow: hidden; }
|
|
488
498
|
.qr svg { display: block; width: 100%; height: 100%; }
|
|
489
499
|
.qr.stale svg { opacity: 0.12; }
|
|
490
500
|
.qr-stale { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
|
|
491
501
|
color: hsl(222 47% 11%); font-weight: 500; }
|
|
492
|
-
.qr-vc { margin-top: 8px; text-align: center; font-size: 0.8125rem; color: var(--
|
|
493
|
-
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-variant-numeric: tabular-nums; letter-spacing: 0.08em; color: var(--
|
|
502
|
+
.qr-vc { margin-top: 8px; text-align: center; font-size: 0.8125rem; color: var(--_eid-fg-subtle); }
|
|
503
|
+
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-variant-numeric: tabular-nums; letter-spacing: 0.08em; color: var(--_eid-fg-muted); }
|
|
494
504
|
.steps { margin-top: 16px; padding: 0; list-style: none; counter-reset: st; display: grid; gap: 8px; }
|
|
495
505
|
.steps li { counter-increment: st; display: flex; align-items: center; gap: 12px; }
|
|
496
|
-
.steps li::before { content: counter(st); flex: none; width: 24px; height: 24px; border-radius: 9999px; background: var(--
|
|
497
|
-
color: var(--
|
|
498
|
-
.or { display: flex; align-items: center; gap: 12px; margin: 24px 0; color: var(--
|
|
499
|
-
.or::before, .or::after { content: ""; flex: 1; height: 1px; background: var(--
|
|
506
|
+
.steps li::before { content: counter(st); flex: none; width: 24px; height: 24px; border-radius: 9999px; background: var(--_eid-accent-subtle);
|
|
507
|
+
color: var(--_eid-accent-subtle-fg); display: flex; align-items: center; justify-content: center; font-size: 0.75rem; font-weight: 600; }
|
|
508
|
+
.or { display: flex; align-items: center; gap: 12px; margin: 24px 0; color: var(--_eid-fg-subtle); font-size: 0.8125rem; }
|
|
509
|
+
.or::before, .or::after { content: ""; flex: 1; height: 1px; background: var(--_eid-border); }
|
|
500
510
|
.field { display: grid; gap: 8px; }
|
|
501
511
|
.field label { font-weight: 500; }
|
|
502
|
-
.field input { width: 100%; height: 44px; padding: 0 12px; border: 1px solid var(--
|
|
503
|
-
background: var(--
|
|
504
|
-
.field input::placeholder { color: var(--
|
|
505
|
-
.field input[aria-invalid="true"] { border-color: var(--
|
|
506
|
-
.hint { font-size: 0.8125rem; color: var(--
|
|
507
|
-
.err { font-size: 0.8125rem; color: var(--
|
|
512
|
+
.field input { width: 100%; height: 44px; padding: 0 12px; border: 1px solid var(--_eid-border-strong); border-radius: var(--_eid-radius);
|
|
513
|
+
background: var(--_eid-bg); color: var(--_eid-fg); font-family: inherit; font-size: 1rem; line-height: 1.5rem; letter-spacing: 0.02em; text-transform: uppercase; }
|
|
514
|
+
.field input::placeholder { color: var(--_eid-fg-subtle); text-transform: none; }
|
|
515
|
+
.field input[aria-invalid="true"] { border-color: var(--_eid-danger-fg); }
|
|
516
|
+
.hint { font-size: 0.8125rem; color: var(--_eid-fg-subtle); }
|
|
517
|
+
.err { font-size: 0.8125rem; color: var(--_eid-danger-fg); font-weight: 500; }
|
|
508
518
|
.push { margin-top: 16px; }
|
|
509
519
|
.center { text-align: center; }
|
|
510
520
|
.vc { font: 600 2.25rem/2.5rem ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 0.16em; padding-left: 0.16em; }
|
|
511
521
|
.vc:focus, h2:focus { outline: none; }
|
|
512
|
-
.text { margin-top: 12px; color: var(--
|
|
513
|
-
.pending { margin-top: 16px; display: inline-flex; align-items: center; gap: 8px; color: var(--
|
|
522
|
+
.text { margin-top: 12px; color: var(--_eid-fg-muted); }
|
|
523
|
+
.pending { margin-top: 16px; display: inline-flex; align-items: center; gap: 8px; color: var(--_eid-fg-muted); }
|
|
514
524
|
.end .btn, .center .btn { margin-top: 24px; }
|
|
515
525
|
.spinner { width: 16px; height: 16px; flex: none; border: 2px solid currentColor; border-right-color: transparent; border-radius: 9999px; animation: spin 0.8s linear infinite; }
|
|
516
526
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
517
|
-
.netwarn { margin-top: 16px; padding: 8px 12px; border: 1px solid var(--
|
|
518
|
-
color: var(--
|
|
519
|
-
.meta { margin-top: 16px; font-size: 0.8125rem; color: var(--
|
|
527
|
+
.netwarn { margin-top: 16px; padding: 8px 12px; border: 1px solid var(--_eid-warning-border); border-radius: var(--_eid-radius); background: var(--_eid-warning-bg);
|
|
528
|
+
color: var(--_eid-warning-fg); font-size: 0.8125rem; }
|
|
529
|
+
.meta { margin-top: 16px; font-size: 0.8125rem; color: var(--_eid-fg-subtle); }
|
|
520
530
|
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; }
|
|
521
531
|
.spinner { animation: none; border-right-color: currentColor; opacity: 0.6; } }
|
|
522
532
|
`;
|