paskia 0.9.0__py3-none-any.whl → 0.10.0__py3-none-any.whl

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.
Files changed (58) hide show
  1. paskia/_version.py +2 -2
  2. paskia/aaguid/__init__.py +5 -4
  3. paskia/authsession.py +4 -19
  4. paskia/db/__init__.py +2 -4
  5. paskia/db/background.py +3 -3
  6. paskia/db/jsonl.py +99 -111
  7. paskia/db/logging.py +318 -0
  8. paskia/db/migrations.py +19 -20
  9. paskia/db/operations.py +107 -196
  10. paskia/db/structs.py +236 -46
  11. paskia/fastapi/__main__.py +13 -6
  12. paskia/fastapi/admin.py +72 -195
  13. paskia/fastapi/api.py +56 -58
  14. paskia/fastapi/authz.py +3 -8
  15. paskia/fastapi/logging.py +261 -0
  16. paskia/fastapi/mainapp.py +14 -3
  17. paskia/fastapi/remote.py +11 -37
  18. paskia/fastapi/reset.py +0 -2
  19. paskia/fastapi/response.py +22 -0
  20. paskia/fastapi/user.py +7 -7
  21. paskia/fastapi/ws.py +14 -37
  22. paskia/fastapi/wschat.py +55 -2
  23. paskia/fastapi/wsutil.py +10 -2
  24. paskia/frontend-build/auth/admin/index.html +6 -6
  25. paskia/frontend-build/auth/assets/AccessDenied-C29NZI95.css +1 -0
  26. paskia/frontend-build/auth/assets/AccessDenied-DAdzg_MJ.js +12 -0
  27. paskia/frontend-build/auth/assets/{RestrictedAuth-CvR33_Z0.css → RestrictedAuth-BOdNrlQB.css} +1 -1
  28. paskia/frontend-build/auth/assets/{RestrictedAuth-DsJXicIw.js → RestrictedAuth-BSusdAfp.js} +1 -1
  29. paskia/frontend-build/auth/assets/_plugin-vue_export-helper-D2l53SUz.js +49 -0
  30. paskia/frontend-build/auth/assets/_plugin-vue_export-helper-DYJ24FZK.css +1 -0
  31. paskia/frontend-build/auth/assets/admin-BeFvGyD6.js +1 -0
  32. paskia/frontend-build/auth/assets/{admin-DzzjSg72.css → admin-CmNtuH3s.css} +1 -1
  33. paskia/frontend-build/auth/assets/{auth-C7k64Wad.css → auth-BKq4T2K2.css} +1 -1
  34. paskia/frontend-build/auth/assets/auth-DvHf8hgy.js +1 -0
  35. paskia/frontend-build/auth/assets/{forward-DmqVHZ7e.js → forward-C86Jm_Uq.js} +1 -1
  36. paskia/frontend-build/auth/assets/reset-B8PlNXuP.css +1 -0
  37. paskia/frontend-build/auth/assets/reset-D71FG0VL.js +1 -0
  38. paskia/frontend-build/auth/assets/{restricted-D3AJx3_6.js → restricted-CW0drE_k.js} +1 -1
  39. paskia/frontend-build/auth/index.html +6 -6
  40. paskia/frontend-build/auth/restricted/index.html +5 -5
  41. paskia/frontend-build/int/forward/index.html +5 -5
  42. paskia/frontend-build/int/reset/index.html +4 -4
  43. paskia/migrate/__init__.py +9 -9
  44. paskia/migrate/sql.py +26 -19
  45. paskia/remoteauth.py +6 -6
  46. {paskia-0.9.0.dist-info → paskia-0.10.0.dist-info}/METADATA +1 -1
  47. paskia-0.10.0.dist-info/RECORD +60 -0
  48. paskia/frontend-build/auth/assets/AccessDenied-DPkUS8LZ.css +0 -1
  49. paskia/frontend-build/auth/assets/AccessDenied-Fmeb6EtF.js +0 -8
  50. paskia/frontend-build/auth/assets/_plugin-vue_export-helper-BTzJAQlS.css +0 -1
  51. paskia/frontend-build/auth/assets/_plugin-vue_export-helper-nhjnO_bd.js +0 -2
  52. paskia/frontend-build/auth/assets/admin-CPE1pLMm.js +0 -1
  53. paskia/frontend-build/auth/assets/auth-YIZvPlW_.js +0 -1
  54. paskia/frontend-build/auth/assets/reset-Chtv69AT.css +0 -1
  55. paskia/frontend-build/auth/assets/reset-s20PATTN.js +0 -1
  56. paskia-0.9.0.dist-info/RECORD +0 -57
  57. {paskia-0.9.0.dist-info → paskia-0.10.0.dist-info}/WHEEL +0 -0
  58. {paskia-0.9.0.dist-info → paskia-0.10.0.dist-info}/entry_points.txt +0 -0
@@ -1 +1 @@
1
- import{r as p,c as h,o as m,y as l,d as f,J as w,K as k}from"./_plugin-vue_export-helper-nhjnO_bd.js";import{R as y}from"./RestrictedAuth-DsJXicIw.js";import"./pow-2N9bxgAo.js";const _={__name:"RestrictedApi",setup(g){const o=p(null);function c(){const e=window.location.pathname.match(/\/auth\/([^/]+)$/);if(e){const r=e[1],s=r.split(".");if(s.length===5&&s.every(d=>d.length>0))return r}return null}const i=h(()=>{const e=new URLSearchParams(window.location.hash.slice(1)).get("mode");return e==="reauth"?"reauth":e==="forbidden"?"forbidden":"login"});function n(t){window.parent&&window.parent!==window&&window.parent.postMessage(t,"*")}function u(t){n({type:"auth-success",authenticated:!0,sessionToken:t.session_token})}function a(){n({type:"auth-back"})}return m(()=>{o.value=c(),n({type:"auth-ready"}),window.addEventListener("keydown",t=>{t.key==="Escape"&&a()})}),(t,e)=>(f(),l(y,{mode:i.value,"remote-auth-token":o.value,onAuthenticated:u,onBack:a},null,8,["mode","remote-auth-token"]))}};w(_).mount("#app");k();
1
+ import{r as p,c as h,o as m,y as l,d as f,J as w,K as k}from"./_plugin-vue_export-helper-D2l53SUz.js";import{R as y}from"./RestrictedAuth-BSusdAfp.js";import"./pow-2N9bxgAo.js";const _={__name:"RestrictedApi",setup(g){const o=p(null);function c(){const e=window.location.pathname.match(/\/auth\/([^/]+)$/);if(e){const r=e[1],s=r.split(".");if(s.length===5&&s.every(d=>d.length>0))return r}return null}const i=h(()=>{const e=new URLSearchParams(window.location.hash.slice(1)).get("mode");return e==="reauth"?"reauth":e==="forbidden"?"forbidden":"login"});function n(t){window.parent&&window.parent!==window&&window.parent.postMessage(t,"*")}function u(t){n({type:"auth-success",authenticated:!0,sessionToken:t.session_token})}function a(){n({type:"auth-back"})}return m(()=>{o.value=c(),n({type:"auth-ready"}),window.addEventListener("keydown",t=>{t.key==="Escape"&&a()})}),(t,e)=>(f(),l(y,{mode:i.value,"remote-auth-token":o.value,onAuthenticated:u,onBack:a},null,8,["mode","remote-auth-token"]))}};w(_).mount("#app");k();
@@ -4,14 +4,14 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Auth Profile</title>
7
- <script type="module" crossorigin src="/auth/assets/auth-YIZvPlW_.js"></script>
8
- <link rel="modulepreload" crossorigin href="/auth/assets/_plugin-vue_export-helper-nhjnO_bd.js">
7
+ <script type="module" crossorigin src="/auth/assets/auth-DvHf8hgy.js"></script>
8
+ <link rel="modulepreload" crossorigin href="/auth/assets/_plugin-vue_export-helper-D2l53SUz.js">
9
9
  <link rel="modulepreload" crossorigin href="/auth/assets/helpers-DzjFIx78.js">
10
- <link rel="modulepreload" crossorigin href="/auth/assets/AccessDenied-Fmeb6EtF.js">
10
+ <link rel="modulepreload" crossorigin href="/auth/assets/AccessDenied-DAdzg_MJ.js">
11
11
  <link rel="modulepreload" crossorigin href="/auth/assets/pow-2N9bxgAo.js">
12
- <link rel="stylesheet" crossorigin href="/auth/assets/_plugin-vue_export-helper-BTzJAQlS.css">
13
- <link rel="stylesheet" crossorigin href="/auth/assets/AccessDenied-DPkUS8LZ.css">
14
- <link rel="stylesheet" crossorigin href="/auth/assets/auth-C7k64Wad.css">
12
+ <link rel="stylesheet" crossorigin href="/auth/assets/_plugin-vue_export-helper-DYJ24FZK.css">
13
+ <link rel="stylesheet" crossorigin href="/auth/assets/AccessDenied-C29NZI95.css">
14
+ <link rel="stylesheet" crossorigin href="/auth/assets/auth-BKq4T2K2.css">
15
15
  </head>
16
16
  <body>
17
17
  <div id="app"></div>
@@ -3,12 +3,12 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <script type="module" crossorigin src="/auth/assets/restricted-D3AJx3_6.js"></script>
7
- <link rel="modulepreload" crossorigin href="/auth/assets/_plugin-vue_export-helper-nhjnO_bd.js">
6
+ <script type="module" crossorigin src="/auth/assets/restricted-CW0drE_k.js"></script>
7
+ <link rel="modulepreload" crossorigin href="/auth/assets/_plugin-vue_export-helper-D2l53SUz.js">
8
8
  <link rel="modulepreload" crossorigin href="/auth/assets/pow-2N9bxgAo.js">
9
- <link rel="modulepreload" crossorigin href="/auth/assets/RestrictedAuth-DsJXicIw.js">
10
- <link rel="stylesheet" crossorigin href="/auth/assets/_plugin-vue_export-helper-BTzJAQlS.css">
11
- <link rel="stylesheet" crossorigin href="/auth/assets/RestrictedAuth-CvR33_Z0.css">
9
+ <link rel="modulepreload" crossorigin href="/auth/assets/RestrictedAuth-BSusdAfp.js">
10
+ <link rel="stylesheet" crossorigin href="/auth/assets/_plugin-vue_export-helper-DYJ24FZK.css">
11
+ <link rel="stylesheet" crossorigin href="/auth/assets/RestrictedAuth-BOdNrlQB.css">
12
12
  </head>
13
13
  <body>
14
14
  <div id="app"></div>
@@ -4,13 +4,13 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Access Restricted</title>
7
- <script type="module" crossorigin src="/auth/assets/forward-DmqVHZ7e.js"></script>
8
- <link rel="modulepreload" crossorigin href="/auth/assets/_plugin-vue_export-helper-nhjnO_bd.js">
7
+ <script type="module" crossorigin src="/auth/assets/forward-C86Jm_Uq.js"></script>
8
+ <link rel="modulepreload" crossorigin href="/auth/assets/_plugin-vue_export-helper-D2l53SUz.js">
9
9
  <link rel="modulepreload" crossorigin href="/auth/assets/pow-2N9bxgAo.js">
10
- <link rel="modulepreload" crossorigin href="/auth/assets/RestrictedAuth-DsJXicIw.js">
10
+ <link rel="modulepreload" crossorigin href="/auth/assets/RestrictedAuth-BSusdAfp.js">
11
11
  <link rel="modulepreload" crossorigin href="/auth/assets/helpers-DzjFIx78.js">
12
- <link rel="stylesheet" crossorigin href="/auth/assets/_plugin-vue_export-helper-BTzJAQlS.css">
13
- <link rel="stylesheet" crossorigin href="/auth/assets/RestrictedAuth-CvR33_Z0.css">
12
+ <link rel="stylesheet" crossorigin href="/auth/assets/_plugin-vue_export-helper-DYJ24FZK.css">
13
+ <link rel="stylesheet" crossorigin href="/auth/assets/RestrictedAuth-BOdNrlQB.css">
14
14
  </head>
15
15
  <body>
16
16
  <div id="app"></div>
@@ -4,10 +4,10 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Complete Passkey Setup</title>
7
- <script type="module" crossorigin src="/auth/assets/reset-s20PATTN.js"></script>
8
- <link rel="modulepreload" crossorigin href="/auth/assets/_plugin-vue_export-helper-nhjnO_bd.js">
9
- <link rel="stylesheet" crossorigin href="/auth/assets/_plugin-vue_export-helper-BTzJAQlS.css">
10
- <link rel="stylesheet" crossorigin href="/auth/assets/reset-Chtv69AT.css">
7
+ <script type="module" crossorigin src="/auth/assets/reset-D71FG0VL.js"></script>
8
+ <link rel="modulepreload" crossorigin href="/auth/assets/_plugin-vue_export-helper-D2l53SUz.js">
9
+ <link rel="stylesheet" crossorigin href="/auth/assets/_plugin-vue_export-helper-DYJ24FZK.css">
10
+ <link rel="stylesheet" crossorigin href="/auth/assets/reset-B8PlNXuP.css">
11
11
  </head>
12
12
  <body>
13
13
  <div id="app"></div>
@@ -14,7 +14,7 @@ Or via the CLI entry point (if installed):
14
14
  import argparse
15
15
  import asyncio
16
16
  import re
17
- from datetime import datetime, timezone
17
+ from datetime import UTC, datetime
18
18
  from uuid import UUID
19
19
 
20
20
  import base64url
@@ -154,7 +154,7 @@ async def migrate_from_sql(
154
154
  if perm_uuid:
155
155
  new_permissions[perm_uuid] = True
156
156
  new_role = Role(
157
- org=role.org_uuid,
157
+ org_uuid=role.org_uuid,
158
158
  display_name=role.display_name,
159
159
  permissions=new_permissions,
160
160
  )
@@ -172,8 +172,8 @@ async def migrate_from_sql(
172
172
  user_key: UUID = legacy_user.uuid
173
173
  new_user = User(
174
174
  display_name=legacy_user.display_name,
175
- role=legacy_user.role_uuid,
176
- created_at=legacy_user.created_at or datetime.now(timezone.utc),
175
+ role_uuid=legacy_user.role_uuid,
176
+ created_at=legacy_user.created_at or datetime.now(UTC),
177
177
  last_seen=legacy_user.last_seen,
178
178
  visits=legacy_user.visits,
179
179
  )
@@ -190,7 +190,7 @@ async def migrate_from_sql(
190
190
  cred_key: UUID = legacy_cred.uuid
191
191
  new_cred = Credential(
192
192
  credential_id=legacy_cred.credential_id,
193
- user=legacy_cred.user_uuid,
193
+ user_uuid=legacy_cred.user_uuid,
194
194
  aaguid=legacy_cred.aaguid,
195
195
  public_key=legacy_cred.public_key,
196
196
  sign_count=legacy_cred.sign_count,
@@ -217,8 +217,8 @@ async def migrate_from_sql(
217
217
  # Already in new format or unknown - try to use as-is
218
218
  session_key = base64url.enc(old_key[:12])
219
219
  db.sessions[session_key] = Session(
220
- user=sess.user_uuid,
221
- credential=sess.credential_uuid,
220
+ user_uuid=sess.user_uuid,
221
+ credential_uuid=sess.credential_uuid,
222
222
  host=sess.host,
223
223
  ip=sess.ip,
224
224
  user_agent=sess.user_agent,
@@ -241,14 +241,14 @@ async def migrate_from_sql(
241
241
  # Already in new format or unknown - truncate to 9 bytes
242
242
  token_key = old_key[:9]
243
243
  db.reset_tokens[token_key] = ResetToken(
244
- user=token.user_uuid,
244
+ user_uuid=token.user_uuid,
245
245
  expiry=token.expiry,
246
246
  token_type=token.token_type,
247
247
  )
248
248
  print(f" Migrated {len(token_models)} reset tokens")
249
249
 
250
250
  # Queue and flush all changes using the transaction mechanism
251
- with db.transaction("migrate"):
251
+ with db.transaction("migrate:sql"):
252
252
  pass # All data already added to _data, transaction commits on exit
253
253
 
254
254
  await store.flush()
paskia/migrate/sql.py CHANGED
@@ -9,7 +9,7 @@ DO NOT use this module for new code. Use paskia.db instead.
9
9
 
10
10
  from contextlib import asynccontextmanager
11
11
  from dataclasses import dataclass
12
- from datetime import datetime, timezone
12
+ from datetime import UTC, datetime
13
13
  from uuid import UUID
14
14
 
15
15
  from sqlalchemy import (
@@ -25,11 +25,6 @@ from sqlalchemy.dialects.sqlite import BLOB
25
25
  from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
26
26
  from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
27
27
 
28
- from paskia.db import (
29
- Org,
30
- Role,
31
- )
32
-
33
28
 
34
29
  # Legacy User class for SQL schema (uses 'role_uuid' not 'role')
35
30
  @dataclass
@@ -71,6 +66,17 @@ class _LegacyRole:
71
66
  permissions: list[str] | None = None
72
67
 
73
68
 
69
+ # Legacy Org class for SQL schema (has mutable permissions/roles lists)
70
+ @dataclass
71
+ class _LegacyOrg:
72
+ """Org as stored in the old SQL schema with mutable permissions/roles."""
73
+
74
+ uuid: UUID
75
+ display_name: str
76
+ permissions: list[str] | None = None
77
+ roles: list[_LegacyRole] | None = None
78
+
79
+
74
80
  # Legacy Session class for SQL schema (uses 'key' as field, 'user_uuid', 'credential_uuid')
75
81
  @dataclass
76
82
  class _LegacySession:
@@ -112,8 +118,8 @@ def _normalize_dt(value: datetime | None) -> datetime | None:
112
118
  if value is None:
113
119
  return None
114
120
  if value.tzinfo is None:
115
- return value.replace(tzinfo=timezone.utc)
116
- return value.astimezone(timezone.utc)
121
+ return value.replace(tzinfo=UTC)
122
+ return value.astimezone(UTC)
117
123
 
118
124
 
119
125
  class Base(DeclarativeBase):
@@ -128,12 +134,13 @@ class OrgModel(Base):
128
134
 
129
135
  def as_dataclass(self):
130
136
  # Base Org without permissions/roles (filled by data accessors)
131
- org = Org(display_name=self.display_name)
132
- org.uuid = UUID(bytes=self.uuid)
133
- return org
137
+ return _LegacyOrg(
138
+ uuid=UUID(bytes=self.uuid),
139
+ display_name=self.display_name,
140
+ )
134
141
 
135
142
  @staticmethod
136
- def from_dataclass(org: Org):
143
+ def from_dataclass(org: _LegacyOrg):
137
144
  return OrgModel(uuid=org.uuid.bytes, display_name=org.display_name)
138
145
 
139
146
 
@@ -172,7 +179,7 @@ class UserModel(Base):
172
179
  LargeBinary(16), ForeignKey("roles.uuid", ondelete="CASCADE"), nullable=False
173
180
  )
174
181
  created_at: Mapped[datetime] = mapped_column(
175
- DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
182
+ DateTime(timezone=True), default=lambda: datetime.now(UTC)
176
183
  )
177
184
  last_seen: Mapped[datetime | None] = mapped_column(
178
185
  DateTime(timezone=True), nullable=True
@@ -195,7 +202,7 @@ class UserModel(Base):
195
202
  uuid=user.uuid.bytes,
196
203
  display_name=user.display_name,
197
204
  role_uuid=user.role_uuid.bytes,
198
- created_at=user.created_at or datetime.now(timezone.utc),
205
+ created_at=user.created_at or datetime.now(UTC),
199
206
  last_seen=user.last_seen,
200
207
  visits=user.visits,
201
208
  )
@@ -215,7 +222,7 @@ class CredentialModel(Base):
215
222
  public_key: Mapped[bytes] = mapped_column(BLOB, nullable=False)
216
223
  sign_count: Mapped[int] = mapped_column(Integer, nullable=False)
217
224
  created_at: Mapped[datetime] = mapped_column(
218
- DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
225
+ DateTime(timezone=True), default=lambda: datetime.now(UTC)
219
226
  )
220
227
  last_used: Mapped[datetime | None] = mapped_column(
221
228
  DateTime(timezone=True), nullable=True
@@ -255,7 +262,7 @@ class SessionModel(Base):
255
262
  user_agent: Mapped[str] = mapped_column(String(512), nullable=False)
256
263
  renewed: Mapped[datetime] = mapped_column(
257
264
  DateTime(timezone=True),
258
- default=lambda: datetime.now(timezone.utc),
265
+ default=lambda: datetime.now(UTC),
259
266
  nullable=False,
260
267
  )
261
268
 
@@ -388,7 +395,7 @@ class DB:
388
395
  result = await session.execute(select(PermissionModel))
389
396
  return [p.as_dataclass() for p in result.scalars().all()]
390
397
 
391
- async def list_organizations(self) -> list[Org]:
398
+ async def list_organizations(self) -> list[_LegacyOrg]:
392
399
  async with self.session() as session:
393
400
  # Load all orgs
394
401
  orgs_result = await session.execute(select(OrgModel))
@@ -415,13 +422,13 @@ class DB:
415
422
  perms_by_role.setdefault(rp.role_uuid, []).append(rp.permission_id)
416
423
 
417
424
  # Build org dataclasses with roles and permission IDs
418
- roles_by_org: dict[bytes, list[Role]] = {}
425
+ roles_by_org: dict[bytes, list[_LegacyRole]] = {}
419
426
  for rm in role_models:
420
427
  r_dc = rm.as_dataclass()
421
428
  r_dc.permissions = perms_by_role.get(rm.uuid, [])
422
429
  roles_by_org.setdefault(rm.org_uuid, []).append(r_dc)
423
430
 
424
- orgs: list[Org] = []
431
+ orgs: list[_LegacyOrg] = []
425
432
  for om in org_models:
426
433
  o_dc = om.as_dataclass()
427
434
  o_dc.permissions = perms_by_org.get(om.uuid, [])
paskia/remoteauth.py CHANGED
@@ -19,9 +19,9 @@ The first 3 words of the token serve as the pairing code for manual entry.
19
19
 
20
20
  import asyncio
21
21
  import logging
22
+ from collections.abc import Callable
22
23
  from dataclasses import dataclass
23
- from datetime import datetime, timedelta, timezone
24
- from typing import Callable
24
+ from datetime import UTC, datetime, timedelta
25
25
  from uuid import UUID
26
26
 
27
27
  from paskia.util import passphrase, pow
@@ -94,7 +94,7 @@ class RemoteAuthManager:
94
94
 
95
95
  async def _cleanup_expired(self):
96
96
  """Remove expired requests and notify waiting clients."""
97
- now = datetime.now(timezone.utc)
97
+ now = datetime.now(UTC)
98
98
  expired_keys = []
99
99
  async with self._lock:
100
100
  for key, req in self._requests.items():
@@ -123,7 +123,7 @@ class RemoteAuthManager:
123
123
  Returns:
124
124
  (code, expiry) - The 3-word passphrase code and expiration time
125
125
  """
126
- now = datetime.now(timezone.utc)
126
+ now = datetime.now(UTC)
127
127
  expiry = now + REMOTE_AUTH_LIFETIME
128
128
 
129
129
  async with self._lock:
@@ -160,7 +160,7 @@ class RemoteAuthManager:
160
160
  req = self._requests.get(normalized)
161
161
  if req is None:
162
162
  return None
163
- now = datetime.now(timezone.utc)
163
+ now = datetime.now(UTC)
164
164
  if now > req.created_at + REMOTE_AUTH_LIFETIME:
165
165
  # Expired
166
166
  del self._requests[normalized]
@@ -331,7 +331,7 @@ class RemoteAuthManager:
331
331
  req = self._requests.get(token)
332
332
  if req is None:
333
333
  return None
334
- now = datetime.now(timezone.utc)
334
+ now = datetime.now(UTC)
335
335
  if now > req.created_at + REMOTE_AUTH_LIFETIME:
336
336
  del self._requests[token]
337
337
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: paskia
3
- Version: 0.9.0
3
+ Version: 0.10.0
4
4
  Summary: Passkey Auth made easy: all sites and APIs can be guarded even without any changes on the protected site.
5
5
  Project-URL: Homepage, https://git.zi.fi/LeoVasanko/paskia
6
6
  Project-URL: Repository, https://github.com/LeoVasanko/paskia
@@ -0,0 +1,60 @@
1
+ paskia/__init__.py,sha256=6eopO87IOFA2zfOuqt8Jj8Tdtp93HBMOgUBtTzMRweM,57
2
+ paskia/_version.py,sha256=XS8OMho0YiZyQ_qDeRsy__m_nWUzYVEJw-NLk1VtDQU,706
3
+ paskia/authsession.py,sha256=7TGZuJw4RLsRJ-pemii6zRXTR-wdLx3nFVItytKFz5s,1259
4
+ paskia/bootstrap.py,sha256=FShAMvLmLxQ4HfE9yz1ZB6EO9fC-lQroesU4dC58VO8,3875
5
+ paskia/config.py,sha256=BdGzQ3Ja1enSTHmkDkBDGQk_JluT3VaK3Y7AqB5xMlk,723
6
+ paskia/globals.py,sha256=ip03kLoS_27cNIgXTVcXNoeQDjTAC_IILuXaHKShTws,1712
7
+ paskia/remoteauth.py,sha256=IyC1Z9YTYjPi4h8B0UwwoWfxaheEgyfksbKraOrAcqA,12418
8
+ paskia/sansio.py,sha256=LQRdV1kW_aGwDWC8fhyEvqWPwKZVx_8qzQv65et6utg,9727
9
+ paskia/aaguid/__init__.py,sha256=I5HMkAwiyLKKlkZOb9z5s2xGApXIbhbBuuX3IhW2y8E,1047
10
+ paskia/aaguid/combined_aaguid.json,sha256=CaZ96AiwdAjBnyVZnJ1eolAHxUQMB2H6mDgZkorYg_A,4124722
11
+ paskia/db/__init__.py,sha256=BGiCFZFX4xMsFn6aKvuV7X7VL-NoA-URdl2493EfRXE,3220
12
+ paskia/db/background.py,sha256=hj3hXoEpneVWhrAHZvoL09DVVaqOTqe-n9RIJZbbEos,3546
13
+ paskia/db/jsonl.py,sha256=1uHBSTtLEc6CChoRJx2zYjFrMcPkGCZN_8MQpHCohFw,9959
14
+ paskia/db/logging.py,sha256=ENCHdrlUz27hjWPFLezpF9bpO-pnrkgO6bNnfCyHcJ4,11017
15
+ paskia/db/migrations.py,sha256=XHHC0LbxXBN6gldiKm4PhDVqEqroMN1E8tz0LEqGPbQ,957
16
+ paskia/db/operations.py,sha256=rCKDNwEfcQz-5DUtZHZECcE9syX50LOFIrmZw9iUink,26443
17
+ paskia/db/structs.py,sha256=G6udtoomKmB8wijO6x1AObX9Oas66gBmJ_YxIiDLO6E,14060
18
+ paskia/fastapi/__init__.py,sha256=NFsTX1qytoyZKiur7RDTa2fxiOWHrop5CAAx8rqK9E0,58
19
+ paskia/fastapi/__main__.py,sha256=DADaKS27BoDqTtfP_p1qbatUL1URjAy9wyJBgjhAQIA,8032
20
+ paskia/fastapi/admin.py,sha256=8raj__JkNTYuvjdZejnK4BhaZBl219qjobmUafQMRkI,30343
21
+ paskia/fastapi/api.py,sha256=RTRhhn6d44aE3MNrepgLBWIPgDPCNr6dHLKSEja_sgU,9240
22
+ paskia/fastapi/auth_host.py,sha256=Y5w9Mz6jyq0hj7SX8LfwebaesUOLGcWzGW9lsmw5WOo,3242
23
+ paskia/fastapi/authz.py,sha256=ui87Ii4hsy0V8f68wGSYft2D7OHAD2l2tsHqokAgBt8,3322
24
+ paskia/fastapi/logging.py,sha256=xP7dxwy8bfKRft3jZPBdsNQk8eQ3nIHB8BUyz7A7sI0,8840
25
+ paskia/fastapi/mainapp.py,sha256=bW7dVxgZfrPtmASri4X7mD5P4sHOmIq3AmoAj37-e8M,5057
26
+ paskia/fastapi/remote.py,sha256=0hsJj8qK89h1U7-5nJFCk9cTte2tvh02b510v-_TGxU,17789
27
+ paskia/fastapi/reset.py,sha256=MuZqhOF68P9kGq5zKPV19FjTIvhZQ423YowzHKcVjlc,3573
28
+ paskia/fastapi/response.py,sha256=gTPNJtS92HfQYey2DMMN8oM1YazNSj6tjBBuFJuuBhc,611
29
+ paskia/fastapi/session.py,sha256=BRnlgR8pTY7o0f7qFnkdyepS2fKEAgqwT9Hj951sZJM,1479
30
+ paskia/fastapi/user.py,sha256=1vi1usiH8IFqqmLkwq2CLoy-x46VTlUnsiNglndajV8,4599
31
+ paskia/fastapi/ws.py,sha256=iY8CVO0W117Vln0DW2xHxiCk__KI29oTMOB2BZEwv34,3581
32
+ paskia/fastapi/wschat.py,sha256=qbEY6AlDlvjeUoIGac3K3DH41MPxPCYuiaFOnz9gxMU,3699
33
+ paskia/fastapi/wsutil.py,sha256=JMPSSWDzMJr7cVobWTFM0HwJrSj_tfKmoO7JkfewuAE,2898
34
+ paskia/frontend-build/auth/index.html,sha256=FO5wXmc7WTTzOZXOKyvO9XrHsk0c931_j_Z3I2xYLes,936
35
+ paskia/frontend-build/auth/admin/index.html,sha256=XTbO2ag2Sojpx7K49vXjNylKmlj0VrqKbNiIhPt4rWc,862
36
+ paskia/frontend-build/auth/assets/AccessDenied-C29NZI95.css,sha256=lJ7TS_wxvrvF_5I8BIDZ23-A-4iusm6WKF4XseT_zuo,7945
37
+ paskia/frontend-build/auth/assets/AccessDenied-DAdzg_MJ.js,sha256=i0hIbfiTnRmRFFWEW7-vLj7v7IQ_cPcP3sIfZWlNcNQ,51889
38
+ paskia/frontend-build/auth/assets/RestrictedAuth-BOdNrlQB.css,sha256=6r_Kf-Q7sueSICtQt8-zufZc1U6qbs084JW-IxUdOoM,5401
39
+ paskia/frontend-build/auth/assets/RestrictedAuth-BSusdAfp.js,sha256=6d9HZzXsmO93ZSUaPd42jp1zJG5ZsZBc2kcvX9RY7bc,9761
40
+ paskia/frontend-build/auth/assets/_plugin-vue_export-helper-D2l53SUz.js,sha256=kuJt8utYB9pLXerrxDEXc0Ytx9jgoT98p4FcObciLSU,86296
41
+ paskia/frontend-build/auth/assets/_plugin-vue_export-helper-DYJ24FZK.css,sha256=5RqRAI3OVX7hxpNlUQvBqYzARmW2piqbcI2NU_PDW_s,12272
42
+ paskia/frontend-build/auth/assets/admin-BeFvGyD6.js,sha256=UJd2bEl4L0KNslnbM-EEX_6stf9MoZGP7sueZcnjKy4,41123
43
+ paskia/frontend-build/auth/assets/admin-CmNtuH3s.css,sha256=Jg_QeSPAOGf2dFCi7FDe71KQ0qma5Dbom70WEE-mNb0,7601
44
+ paskia/frontend-build/auth/assets/auth-BKq4T2K2.css,sha256=lfYJTjXr3iM8YDMHxtBN4jY6JrLE7yjR1nWEGbN_1uE,4333
45
+ paskia/frontend-build/auth/assets/auth-DvHf8hgy.js,sha256=uQHMfl0n3LbWgyy4ldBSfQnKIW26OdUgxDzb05WFVdI,25267
46
+ paskia/frontend-build/auth/assets/forward-C86Jm_Uq.js,sha256=GeqWr3Z7kDwdgiE5S1ojjjud71bS2TtEdhHoNRIZB2E,782
47
+ paskia/frontend-build/auth/assets/helpers-DzjFIx78.js,sha256=w_IsCBn3QwidsuwQhVRycd8Fa53lvbgRGGojTBXVlUc,940
48
+ paskia/frontend-build/auth/assets/pow-2N9bxgAo.js,sha256=7AfzW5lcTefPI6YGXrYao1b56L7v5Bon9Y9N40yHsaE,9447
49
+ paskia/frontend-build/auth/assets/reset-B8PlNXuP.css,sha256=19f4h_GGjADzWvaYag9lnwrmttNXvwVYYHcGGy5X61E,238
50
+ paskia/frontend-build/auth/assets/reset-D71FG0VL.js,sha256=ZccTsQHP5YMoQznz7JBfO-1sZ3UouiulnzhMaIzsnzs,3981
51
+ paskia/frontend-build/auth/assets/restricted-CW0drE_k.js,sha256=l8Qxc8N6RYlJdHTqOPX9zEdgBs0SR5ou5Y-My-IRCnA,1023
52
+ paskia/frontend-build/auth/restricted/index.html,sha256=N_1KkcLd52Un6pVCVpGeXnsacR5FVU6jjcO9CQ_4zkc,785
53
+ paskia/frontend-build/int/forward/index.html,sha256=ur0I53vLzasQM3KOvmhVEK0SC5stL56p7040Vmmdz5I,870
54
+ paskia/frontend-build/int/reset/index.html,sha256=Jx0m9XzYeEwhNddsJAUihL3JiW_rvRxBixNjfAzcg94,612
55
+ paskia/migrate/__init__.py,sha256=r2s99mbHfvlzQJ1V3xnxZOwIyMEMxEXDtFqFj7sJC2U,9916
56
+ paskia/migrate/sql.py,sha256=5HNEUnPP0kqis69URJ5keE4JNbwqWe8oYXwf-zKheLI,14333
57
+ paskia-0.10.0.dist-info/METADATA,sha256=TNP_cx3lJEFqNg6H-ZQMojA75zJlIa1YJuddqW4RTsY,4262
58
+ paskia-0.10.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
59
+ paskia-0.10.0.dist-info/entry_points.txt,sha256=vvx6RYetgd61I2ODqQPHqrKHgCfuo08w_T35yDlHenE,93
60
+ paskia-0.10.0.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- .breadcrumbs[data-v-6344dbb8]{margin:.25rem 0 .5rem;line-height:1.2;color:var(--color-text-muted)}.breadcrumbs ol[data-v-6344dbb8]{list-style:none;padding:0;margin:0;display:flex;flex-wrap:wrap;align-items:center;gap:.25rem}.breadcrumbs li[data-v-6344dbb8]{display:inline-flex;align-items:center;gap:.25rem;font-size:.9rem}.breadcrumbs a[data-v-6344dbb8]{text-decoration:none;color:var(--color-link);padding:0 .25rem;border-radius:4px;transition:color .2s ease,background .2s ease}.breadcrumbs .sep[data-v-6344dbb8]{color:var(--color-text-muted);margin:0}.btn-card-delete{display:none}.credential-item:focus .btn-card-delete{display:block}.user-info.has-extra[data-v-ce373d6c]{grid-template-columns:auto 1fr 2fr;grid-template-areas:"heading heading extra" "org org extra" "label1 value1 extra" "label2 value2 extra" "label3 value3 extra"}.user-info[data-v-ce373d6c]:not(.has-extra){grid-template-columns:auto 1fr;grid-template-areas:"heading heading" "org org" "label1 value1" "label2 value2" "label3 value3"}@media(max-width:720px){.user-info.has-extra[data-v-ce373d6c]{grid-template-columns:auto 1fr;grid-template-areas:"heading heading" "org org" "label1 value1" "label2 value2" "label3 value3" "extra extra"}}.user-name-heading[data-v-ce373d6c]{grid-area:heading;display:flex;align-items:center;flex-wrap:wrap;margin:0 0 .25rem}.org-role-sub[data-v-ce373d6c]{grid-area:org;display:flex;flex-direction:column;margin:-.15rem 0 .25rem}.org-line[data-v-ce373d6c]{font-size:.7rem;font-weight:600;line-height:1.1;color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.05em}.role-line[data-v-ce373d6c]{font-size:.65rem;color:var(--color-text-muted);line-height:1.1}.info-label[data-v-ce373d6c]:nth-of-type(1){grid-area:label1}.info-value[data-v-ce373d6c]:nth-of-type(2){grid-area:value1}.info-label[data-v-ce373d6c]:nth-of-type(3){grid-area:label2}.info-value[data-v-ce373d6c]:nth-of-type(4){grid-area:value2}.info-label[data-v-ce373d6c]:nth-of-type(5){grid-area:label3}.info-value[data-v-ce373d6c]:nth-of-type(6){grid-area:value3}.user-info-extra[data-v-ce373d6c]{grid-area:extra;padding-left:2rem;border-left:1px solid var(--color-border)}.user-name-row[data-v-ce373d6c]{display:inline-flex;align-items:center;gap:.35rem;max-width:100%}.user-name-row.editing[data-v-ce373d6c]{flex:1 1 auto}.display-name[data-v-ce373d6c]{font-weight:600;font-size:1.05em;line-height:1.2;max-width:14ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.name-input[data-v-ce373d6c]{width:auto;flex:1 1 140px;min-width:120px;padding:6px 8px;font-size:.9em;border:1px solid var(--color-border-strong);border-radius:6px;background:var(--color-surface);color:var(--color-text)}.user-name-heading .name-input[data-v-ce373d6c]{width:auto}.name-input[data-v-ce373d6c]:focus{outline:none;border-color:var(--color-accent);box-shadow:var(--focus-ring)}.mini-btn[data-v-ce373d6c]{width:auto;padding:4px 6px;margin:0;font-size:.75em;line-height:1;cursor:pointer}.mini-btn[data-v-ce373d6c]:hover:not(:disabled){background:var(--color-accent-soft);color:var(--color-accent)}.mini-btn[data-v-ce373d6c]:active:not(:disabled){transform:translateY(1px)}.mini-btn[data-v-ce373d6c]:disabled{opacity:.5;cursor:not-allowed}@media(max-width:720px){.user-info-extra[data-v-ce373d6c]{padding-left:0;padding-top:1rem;margin-top:1rem;border-left:none;border-top:1px solid var(--color-border)}}dialog[data-v-2ebcbb0a]{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:var(--shadow-xl);padding:calc(var(--space-lg) - var(--space-xs));max-width:500px;width:min(500px,90vw);max-height:90vh;overflow-y:auto;position:fixed;inset:0;margin:auto;height:fit-content}dialog[data-v-2ebcbb0a]::backdrop{background:transparent;backdrop-filter:blur(.1rem) brightness(.7);-webkit-backdrop-filter:blur(.1rem) brightness(.7)}dialog[data-v-2ebcbb0a] .modal-title,dialog[data-v-2ebcbb0a] h3{margin:0 0 var(--space-md);font-size:1.25rem;font-weight:600;color:var(--color-heading)}dialog[data-v-2ebcbb0a] form{display:flex;flex-direction:column;gap:var(--space-md)}dialog[data-v-2ebcbb0a] .modal-form{display:flex;flex-direction:column;gap:var(--space-md)}dialog[data-v-2ebcbb0a] .modal-form label{display:flex;flex-direction:column;gap:var(--space-xs);font-weight:500}dialog[data-v-2ebcbb0a] .modal-form input,dialog[data-v-2ebcbb0a] .modal-form textarea{padding:var(--space-md);border:1px solid var(--color-border);border-radius:var(--radius-sm);background:var(--color-bg);color:var(--color-text);font-size:1rem;line-height:1.4;min-height:2.5rem}dialog[data-v-2ebcbb0a] .modal-form input:focus,dialog[data-v-2ebcbb0a] .modal-form textarea:focus{outline:none;border-color:var(--color-accent);box-shadow:0 0 0 2px #c7d2fe}dialog[data-v-2ebcbb0a] .modal-actions{display:flex;justify-content:flex-end;gap:var(--space-sm);margin-top:var(--space-md);margin-bottom:var(--space-xs)}.name-edit-form[data-v-b73321cf]{display:flex;flex-direction:column;gap:var(--space-md)}.error[data-v-b73321cf]{color:var(--color-danger-text)}.small[data-v-b73321cf]{font-size:.9rem}.qr-display[data-v-727427c4]{display:flex;flex-direction:column;align-items:center;gap:.75rem}.qr-section[data-v-727427c4]{display:flex;flex-direction:column;align-items:center;gap:.5rem}.qr-link[data-v-727427c4]{display:flex;flex-direction:column;align-items:center;text-decoration:none;color:inherit;border-radius:var(--radius-sm, 6px);overflow:hidden}.qr-code[data-v-727427c4]{display:block;width:200px;height:200px;max-width:100%;object-fit:contain;border-radius:var(--radius-sm, 6px);background:#fff;cursor:pointer}.link-text[data-v-727427c4]{padding:.5rem;font-size:.75rem;color:var(--color-text-muted);font-family:monospace;word-break:break-all;line-height:1.2;transition:color .2s ease}.qr-link:hover .link-text[data-v-727427c4]{color:var(--color-text)}dialog[data-v-e04dd463]{border:none;background:transparent;padding:0;max-width:none;width:fit-content;height:fit-content;position:fixed;inset:0;margin:auto}dialog[data-v-e04dd463]::backdrop{-webkit-backdrop-filter:blur(.2rem) brightness(.5);backdrop-filter:blur(.2rem) brightness(.5)}.icon-btn[data-v-e04dd463]{background:none;border:none;cursor:pointer;font-size:1rem;opacity:.6}.icon-btn[data-v-e04dd463]:hover{opacity:1}.reg-header-row[data-v-e04dd463]{display:flex;justify-content:space-between;align-items:center;gap:.75rem;margin-bottom:.75rem}.reg-title[data-v-e04dd463]{margin:0;font-size:1.25rem;font-weight:600}.device-dialog[data-v-e04dd463]{background:var(--color-surface);padding:1.25rem 1.25rem 1rem;border-radius:var(--radius-md);max-width:480px;width:100%;box-shadow:0 6px 28px #00000040}.reg-help[data-v-e04dd463]{margin:.5rem 0 .75rem;font-size:.85rem;line-height:1.4;text-align:center;color:var(--color-text-muted)}.reg-actions[data-v-e04dd463]{display:flex;justify-content:flex-end;gap:.5rem;margin-top:1rem}.expiry-note[data-v-e04dd463]{font-size:.75rem;color:var(--color-text-muted);text-align:center;margin-top:.75rem}.loading-container[data-v-130f5abf]{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100vh;gap:1rem}.loading-spinner[data-v-130f5abf]{width:40px;height:40px;border:4px solid var(--color-border);border-top:4px solid var(--color-primary);border-radius:50%;animation:spin-130f5abf 1s linear infinite}@keyframes spin-130f5abf{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.loading-container p[data-v-130f5abf]{color:var(--color-text-muted);margin:0}.message-container[data-v-a7b258e7]{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100vh;padding:2rem}.message-content[data-v-a7b258e7]{text-align:center;max-width:480px}.message-content h2[data-v-a7b258e7]{margin:0 0 1rem;color:var(--color-heading)}.message-content .error-detail[data-v-a7b258e7]{margin:0 0 1.5rem;color:var(--color-text-muted)}.message-content .button-row[data-v-a7b258e7]{display:flex;gap:.75rem;justify-content:center}
@@ -1,8 +0,0 @@
1
- import{M as At,r as F,N as Rt,O as Yt,P as ue,Q as Tt,R as Qt,S as Gt,T as Wt,n as ze,U as Zt,c as x,w as He,V as Xt,W as en,H as Q,m as tn,X as nn,Y as on,b as R,f as L,z as U,d as T,e as v,t as D,g as se,_ as Y,F as oe,i as ce,B as z,D as Mt,l as de,Z as Nt,$ as Pt,a0 as Dt,a1 as Lt,o as qt,a2 as rn,a as Ft,C as sn,k as xe,h as an,a3 as ln,L as un,x as cn}from"./_plugin-vue_export-helper-nhjnO_bd.js";import{f as G,h as ae,g as We}from"./helpers-DzjFIx78.js";let Ut;const fe=e=>Ut=e,Kt=Symbol();function Oe(e){return e&&typeof e=="object"&&Object.prototype.toString.call(e)==="[object Object]"&&typeof e.toJSON!="function"}var re;(function(e){e.direct="direct",e.patchObject="patch object",e.patchFunction="patch function"})(re||(re={}));function vr(){const e=At(!0),s=e.run(()=>F({}));let r=[],t=[];const n=Rt({install(o){fe(n),n._a=o,o.provide(Kt,n),o.config.globalProperties.$pinia=n,t.forEach(i=>r.push(i)),t=[]},use(o){return this._a?r.push(o):t.push(o),this},_p:r,_a:null,_e:e,_s:new Map,state:s});return n}const Vt=()=>{};function Ze(e,s,r,t=Vt){e.add(s);const n=()=>{e.delete(s)&&t()};return!r&&Gt()&&Wt(n),n}function ee(e,...s){e.forEach(r=>{r(...s)})}const dn=e=>e(),Xe=Symbol(),pe=Symbol();function je(e,s){e instanceof Map&&s instanceof Map?s.forEach((r,t)=>e.set(t,r)):e instanceof Set&&s instanceof Set&&s.forEach(e.add,e);for(const r in s){if(!s.hasOwnProperty(r))continue;const t=s[r],n=e[r];Oe(n)&&Oe(t)&&e.hasOwnProperty(r)&&!ue(t)&&!Tt(t)?e[r]=je(n,t):e[r]=t}return e}const fn=Symbol();function hn(e){return!Oe(e)||!Object.prototype.hasOwnProperty.call(e,fn)}const{assign:J}=Object;function gn(e){return!!(ue(e)&&e.effect)}function mn(e,s,r,t){const{state:n,actions:o,getters:i}=s,a=r.state.value[e];let l;function u(){a||(r.state.value[e]=n?n():{});const f=Zt(r.state.value[e]);return J(f,o,Object.keys(i||{}).reduce((w,b)=>(w[b]=Rt(x(()=>{fe(r);const h=r._s.get(e);return i[b].call(h,h)})),w),{}))}return l=Ht(e,u,s,r,t,!0),l}function Ht(e,s,r={},t,n,o){let i;const a=J({actions:{}},r),l={deep:!0};let u,f,w=new Set,b=new Set,h;const d=t.state.value[e];!o&&!d&&(t.state.value[e]={}),F({});let g;function N(y){let m;u=f=!1,typeof y=="function"?(y(t.state.value[e]),m={type:re.patchFunction,storeId:e,events:h}):(je(t.state.value[e],y),m={type:re.patchObject,payload:y,storeId:e,events:h});const E=g=Symbol();ze().then(()=>{g===E&&(u=!0)}),f=!0,ee(w,m,t.state.value[e])}const A=o?function(){const{state:m}=r,E=m?m():{};this.$patch(_=>{J(_,E)})}:Vt;function P(){i.stop(),w.clear(),b.clear(),t._s.delete(e)}const c=(y,m="")=>{if(Xe in y)return y[pe]=m,y;const E=function(){fe(t);const _=Array.from(arguments),k=new Set,B=new Set;function M(q){k.add(q)}function V(q){B.add(q)}ee(b,{args:_,name:E[pe],store:I,after:M,onError:V});let K;try{K=y.apply(this&&this.$id===e?this:I,_)}catch(q){throw ee(B,q),q}return K instanceof Promise?K.then(q=>(ee(k,q),q)).catch(q=>(ee(B,q),Promise.reject(q))):(ee(k,K),K)};return E[Xe]=!0,E[pe]=m,E},S={_p:t,$id:e,$onAction:Ze.bind(null,b),$patch:N,$reset:A,$subscribe(y,m={}){const E=Ze(w,y,m.detached,()=>_()),_=i.run(()=>He(()=>t.state.value[e],k=>{(m.flush==="sync"?f:u)&&y({storeId:e,type:re.direct,events:h},k)},J({},l,m)));return E},$dispose:P},I=Yt(S);t._s.set(e,I);const p=(t._a&&t._a.runWithContext||dn)(()=>t._e.run(()=>(i=At()).run(()=>s({action:c}))));for(const y in p){const m=p[y];if(ue(m)&&!gn(m)||Tt(m))o||(d&&hn(m)&&(ue(m)?m.value=d[y]:je(m,d[y])),t.state.value[e][y]=m);else if(typeof m=="function"){const E=c(m,y);p[y]=E,a.actions[y]=m}}return J(I,p),J(Qt(I),p),Object.defineProperty(I,"$state",{get:()=>t.state.value[e],set:y=>{N(m=>{J(m,y)})}}),t._p.forEach(y=>{J(I,i.run(()=>y({store:I,app:t._a,pinia:t,options:a})))}),d&&o&&r.hydrate&&r.hydrate(I.$state,d),u=!0,f=!0,I}function yn(e,s,r){let t;const n=typeof s=="function";t=n?r:s;function o(i,a){const l=en();return i=i||(l?Xt(Kt,null):null),i&&fe(i),i=Ut,i._s.has(e)||(n?Ht(e,s,t,i):mn(e,t,i)),i._s.get(e)}return o.$id=e,o}const $e=yn("auth",{state:()=>({userInfo:null,isLoading:!1,settings:null,currentView:"login",status:{message:"",type:"info",show:!1}}),getters:{},actions:{setLoading(e){this.isLoading=!!e},showMessage(e,s="info",r=null){const t=r??(s==="error"?5e3:3e3);this.status={message:e,type:s,show:!0},t>0&&setTimeout(()=>{this.status.show=!1},t)},async setSessionCookie(e){if(!e?.session_token)throw console.error("setSessionCookie called with missing session_token:",e),new Error("Authentication response missing session_token");return await Q("/auth/api/set-session",{method:"POST",headers:{Authorization:`Bearer ${e.session_token}`}})},async register(){this.isLoading=!0;try{const e=await on();return await this.setSessionCookie(e),await this.loadUserInfo(),this.selectView(),e}finally{this.isLoading=!1}},async authenticate(){this.isLoading=!0;try{const e=await nn();return await this.setSessionCookie(e),await this.loadUserInfo(),this.selectView(),e}finally{this.isLoading=!1}},selectView(){this.userInfo?this.currentView="profile":this.currentView="login"},async loadSettings(){this.settings=await tn()},async loadUserInfo(){try{this.userInfo=await Q("/auth/api/user-info",{method:"POST"}),console.log("User info loaded:",this.userInfo)}catch(e){throw e.status===401||e.status===403?console.log("Authentication required:",e.message):this.showMessage(e.message||"Failed to load user info","error",5e3),e}},async deleteCredential(e){await Q(`/auth/api/user/credential/${e}`,{method:"DELETE"}),await this.loadUserInfo()},async terminateSession(e){try{if((await Q(`/auth/api/user/session/${e}`,{method:"DELETE"}))?.current_session_terminated){sessionStorage.clear(),location.reload();return}await this.loadUserInfo(),this.showMessage("Session terminated","success",2500)}catch(s){throw console.error("Terminate session error:",s),s}},async logout(){try{await Q("/auth/api/logout",{method:"POST"}),sessionStorage.clear(),location.reload()}catch(e){console.error("Logout error:",e),e.status!==401&&e.status!==403&&this.showMessage(e.message,"error")}},async logoutEverywhere(){try{await Q("/auth/api/user/logout-all",{method:"POST"}),sessionStorage.clear(),location.reload()}catch(e){console.error("Logout-all error:",e),e.status!==401&&e.status!==403&&this.showMessage(e.message,"error")}}}}),pn={key:0,class:"global-status",style:{display:"block"}},Cr={__name:"StatusMessage",setup(e){const s=$e();return(r,t)=>U(s).status.show?(T(),R("div",pn,[v("div",{class:se(["status",U(s).status.type])},D(U(s).status.message),3)])):L("",!0)}},wn=["href"],bn={key:0,class:"sep"},vn={__name:"Breadcrumbs",props:{entries:{type:Array,default:()=>[]},showHome:{type:Boolean,default:!0},homeHref:{type:String,default:"/"}},setup(e,{expose:s}){const r=e,t=F(null),n=x(()=>r.showHome&&r.entries.length>0&&r.entries[0].href===r.homeHref?[{label:"🏠 "+r.entries[0].label,href:r.homeHref},...r.entries.slice(1)]:[...r.showHome?[{label:"🏠",href:r.homeHref}]:[],...r.entries]),o=x(()=>{const u=window.location.hash||window.location.pathname;for(let f=n.value.length-1;f>=0;f--){const w=n.value[f].href;if(w===u||w&&u.startsWith(w))return f}return n.value.length-1});function i(u){if(u.target===t.value){const f=t.value.querySelectorAll("a"),w=Math.min(o.value,f.length-1);f[w]&&f[w].focus()}}function a(u){const f=z(u);f&&(f==="left"||f==="right")&&(u.preventDefault(),Mt(t.value,u.target,f,{itemSelector:"a"}))}function l(){const u=t.value?.querySelectorAll("a");if(u?.length){const f=Math.min(o.value,u.length-1);u[f]?.focus()}}return s({focusCurrent:l}),(u,f)=>n.value.length>1?(T(),R("nav",{key:0,ref_key:"navRef",ref:t,class:"breadcrumbs","aria-label":"Breadcrumb",tabindex:"0",onFocusin:i,onKeydown:a},[v("ol",null,[(T(!0),R(oe,null,ce(n.value,(w,b)=>(T(),R("li",{key:b},[v("a",{href:w.href,tabindex:"-1"},D(w.label),9,wn),b<n.value.length-1?(T(),R("span",bn," — ")):L("",!0)]))),128))])],544)):L("",!0)}},Sr=Y(vn,[["__scopeId","data-v-6344dbb8"]]),Cn={key:0},Sn={key:1},En=["onFocusin","onKeydown"],_n={class:"item-top"},kn={class:"item-icon"},Bn=["src","alt"],In={key:1,class:"auth-emoji"},An={class:"item-title"},Rn={class:"item-actions"},Tn={key:0,class:"badge badge-current"},Mn={key:1,class:"badge badge-current"},Nn={key:2,class:"badge badge-current"},Pn=["onClick","disabled","title"],Dn={class:"item-details"},Ln={class:"credential-dates"},qn={class:"date-value"},Fn={class:"date-value"},Un={class:"date-value"},Er={__name:"CredentialList",props:{credentials:{type:Array,default:()=>[]},aaguidInfo:{type:Object,default:()=>({})},loading:{type:Boolean,default:!1},allowDelete:{type:Boolean,default:!1},hoveredCredentialUuid:{type:String,default:null},hoveredSessionCredentialUuid:{type:String,default:null},navigationDisabled:{type:Boolean,default:!1}},emits:["delete","credentialHover","navigate-out"],setup(e,{emit:s}){const r=e,t=s,n=h=>{t("credentialHover",h)},o=h=>{h.currentTarget.contains(h.relatedTarget)||t("credentialHover",null)},i=h=>{h.currentTarget.matches(":focus")||(h.currentTarget.focus(),h.stopPropagation())},a=(h,d)=>{Pt(h,()=>{r.allowDelete&&!d.is_current_session&&t("delete",d)})},l=h=>{if(r.navigationDisabled)return;const d=h.currentTarget;if(h.target===d){const g=d.querySelector(".credential-item");g&&g.focus()}},u=h=>{r.navigationDisabled||Dt(h,d=>t("navigate-out",d))},f=(h,d)=>{if(a(h,d),h.defaultPrevented||r.navigationDisabled)return;const g=z(h);if(g){h.preventDefault();const N=h.currentTarget.closest(".credential-list");Nt(N,h.currentTarget,g,{itemSelector:".credential-item"})==="boundary"&&t("navigate-out",g)}},w=h=>{const d=r.aaguidInfo?.[h.aaguid];return d?d.name:"Unknown Authenticator"},b=h=>{const d=r.aaguidInfo?.[h.aaguid];if(!d)return null;const N=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"icon_dark":"icon_light";return d[N]||null};return(h,d)=>(T(),R("div",{class:"credential-list",tabindex:"0",onFocusin:l,onKeydown:u},[e.loading?(T(),R("div",Cn,[...d[2]||(d[2]=[v("p",null,"Loading credentials...",-1)])])):e.credentials?.length?(T(!0),R(oe,{key:2},ce(e.credentials,g=>(T(),R("div",{key:g.credential,class:se(["credential-item",{"current-session":g.is_current_session&&!e.hoveredCredentialUuid&&!e.hoveredSessionCredentialUuid,"is-hovered":e.hoveredCredentialUuid===g.credential,"is-linked-session":e.hoveredSessionCredentialUuid===g.credential}]),tabindex:"-1",onMousedown:d[0]||(d[0]=de(()=>{},["prevent"])),onClickCapture:i,onFocusin:N=>n(g.credential),onFocusout:d[1]||(d[1]=N=>o(N)),onKeydown:N=>f(N,g)},[v("div",_n,[v("div",kn,[b(g)?(T(),R("img",{key:0,src:b(g),alt:w(g),class:"auth-icon",width:"32",height:"32"},null,8,Bn)):(T(),R("span",In,"🔑"))]),v("h4",An,D(w(g)),1),v("div",Rn,[g.is_current_session&&!e.hoveredCredentialUuid&&!e.hoveredSessionCredentialUuid?(T(),R("span",Tn,"Current")):e.hoveredCredentialUuid===g.credential?(T(),R("span",Mn,"Selected")):e.hoveredSessionCredentialUuid===g.credential?(T(),R("span",Nn,"Linked")):L("",!0),e.allowDelete?(T(),R("button",{key:3,onClick:N=>h.$emit("delete",g),class:"btn-card-delete",disabled:g.is_current_session,title:g.is_current_session?"Cannot delete current session credential":"Delete passkey and terminate any linked sessions.",tabindex:"-1"},"❌",8,Pn)):L("",!0)])]),v("div",Dn,[v("div",Ln,[d[4]||(d[4]=v("span",{class:"date-label"},"Created:",-1)),v("span",qn,D(U(G)(g.created_at)),1),d[5]||(d[5]=v("span",{class:"date-label"},"Last used:",-1)),v("span",Fn,D(U(G)(g.last_used)),1),d[6]||(d[6]=v("span",{class:"date-label"},"Last verified:",-1)),v("span",Un,D(U(G)(g.last_verified)),1)])])],42,En))),128)):(T(),R("div",Sn,[...d[3]||(d[3]=[v("p",null,"No passkeys found.",-1)])]))],32))}},Kn={class:"user-name-heading"},Vn={class:"user-name-row"},Hn=["title"],On={key:0,class:"org-role-sub"},jn={key:0,class:"org-line"},zn={key:1,class:"role-line"},xn={class:"user-details"},$n={class:"date-value"},Jn={class:"date-value"},Yn={class:"date-value"},Qn={key:1,class:"user-info-extra"},Gn={__name:"UserBasicInfo",props:{name:{type:String,required:!0},visits:{type:[Number,String],default:0},createdAt:{type:[String,Number,Date],default:null},lastSeen:{type:[String,Number,Date],default:null},updateEndpoint:{type:String,default:null},canEdit:{type:Boolean,default:!0},loading:{type:Boolean,default:!1},orgDisplayName:{type:String,default:""},roleName:{type:String,default:""}},emits:["saved","editName"],setup(e,{emit:s}){const r=e,t=s;$e();const n=x(()=>!!r.name);return(o,i)=>n.value?(T(),R("div",{key:0,class:se(["user-info",{"has-extra":o.$slots.default}])},[v("h3",Kn,[i[1]||(i[1]=v("span",{class:"icon"},"👤",-1)),v("span",Vn,[v("span",{class:"display-name",title:e.name},D(e.name),9,Hn),e.canEdit&&e.updateEndpoint?(T(),R("button",{key:0,class:"mini-btn",onClick:i[0]||(i[0]=a=>t("editName")),title:"Edit name"},"✏️")):L("",!0)])]),e.orgDisplayName||e.roleName?(T(),R("div",On,[e.orgDisplayName?(T(),R("div",jn,D(e.orgDisplayName),1)):L("",!0),e.roleName?(T(),R("div",zn,D(e.roleName),1)):L("",!0)])):L("",!0),v("div",xn,[i[2]||(i[2]=v("span",{class:"date-label"},[v("strong",null,"Visits:")],-1)),v("span",$n,D(e.visits||0),1),i[3]||(i[3]=v("span",{class:"date-label"},[v("strong",null,"Registered:")],-1)),v("span",Jn,D(U(G)(e.createdAt)),1),i[4]||(i[4]=v("span",{class:"date-label"},[v("strong",null,"Last seen:")],-1)),v("span",Yn,D(U(G)(e.lastSeen)),1)]),o.$slots.default?(T(),R("div",Qn,[Lt(o.$slots,"default",{},void 0)])):L("",!0)],2)):L("",!0)}},_r=Y(Gn,[["__scopeId","data-v-ce373d6c"]]),Wn={__name:"Modal",props:{focusFallback:{type:[HTMLElement,Object],default:null},focusIndex:{type:Number,default:-1},focusSiblingSelector:{type:String,default:""}},emits:["close"],setup(e){const s=e,r=F(null),t=F(null),n=()=>{const i=t.value;if(!i)return;if(document.body.contains(i)&&!i.disabled){i.focus();return}if(s.focusSiblingSelector&&s.focusIndex>=0){const l=[s.focusFallback?.$el||s.focusFallback,i.closest("[data-nav-group]"),i.parentElement?.closest("section"),document.querySelector(".view-root")].filter(Boolean);for(const u of l){if(!u)continue;const f=u.querySelectorAll(s.focusSiblingSelector);if(f.length>0){const w=Math.min(s.focusIndex,f.length-1),b=f[w];if(b&&!b.disabled){b.focus();return}}}}const a=s.focusFallback?.$el||s.focusFallback;if(a&&document.body.contains(a)){const l=a.querySelector?.('button:not([disabled]), a, [tabindex="0"]')||a;if(l?.focus){l.focus();return}}},o=i=>{const a=z(i);if(!a)return;const l=i.target,u=l.closest(".modal-actions");if(u&&(a==="left"||a==="right"))i.preventDefault(),Mt(u,l,a,{itemSelector:"button"});else if(a==="up"&&u){i.preventDefault();const w=(u.closest("form")||u.closest(".modal-form"))?.querySelectorAll("input, textarea, select, button:not(.modal-actions button)");w&&w.length>0&&w[w.length-1].focus()}else if(a==="down"&&!u){const f=l.closest("form")||l.closest(".modal-form");if(f){i.preventDefault();const w=f.querySelector(".modal-actions");w&&sn(w,{primarySelector:".btn-primary",itemSelector:"button"})}}};return qt(()=>{t.value=document.activeElement,ze(()=>{if(r.value){r.value.showModal();const i=r.value.querySelector(".modal-actions .btn-primary");i&&i.setAttribute("data-nav-primary",""),rn(r.value)}})}),Ft(()=>{n()}),(i,a)=>(T(),R("dialog",{ref_key:"dialog",ref:r,onClose:a[0]||(a[0]=l=>i.$emit("close")),onKeydown:o},[Lt(i.$slots,"default",{},void 0)],544))}},kr=Y(Wn,[["__scopeId","data-v-2ebcbb0a"]]),Zn={class:"name-edit-form"},Xn=["for"],eo=["id","type","placeholder","disabled"],to={key:0,class:"error small"},no=["disabled"],oo=["disabled"],ro={__name:"NameEditForm",props:{modelValue:{type:String,default:""},label:{type:String,default:"Name"},placeholder:{type:String,default:""},submitText:{type:String,default:"Save"},cancelText:{type:String,default:"Cancel"},busy:{type:Boolean,default:!1},error:{type:String,default:""},autoFocus:{type:Boolean,default:!0},autoSelect:{type:Boolean,default:!0},inputId:{type:String,default:null},inputType:{type:String,default:"text"}},emits:["update:modelValue","cancel"],setup(e,{emit:s}){const r=e,t=s,n=F(null),o=`name-edit-${Math.random().toString(36).slice(2,10)}`,i=x({get:()=>r.modelValue,set:f=>t("update:modelValue",f)}),a=x(()=>r.inputId||o),l=f=>{if(z(f)==="up"){f.preventDefault(),n.value?.focus();return}};function u(){t("cancel")}return(f,w)=>(T(),R("div",Zn,[v("label",{for:a.value},[xe(D(e.label)+" ",1),an(v("input",{id:a.value,ref_key:"inputRef",ref:n,type:e.inputType,placeholder:e.placeholder,"onUpdate:modelValue":w[0]||(w[0]=b=>i.value=b),disabled:e.busy,required:""},null,8,eo),[[ln,i.value]])],8,Xn),e.error?(T(),R("div",to,D(e.error),1)):L("",!0),v("div",{class:"modal-actions",onKeydown:l},[v("button",{type:"button",class:"btn-secondary",onClick:u,disabled:e.busy},D(e.cancelText),9,no),v("button",{type:"submit",class:"btn-primary",disabled:e.busy,"data-nav-primary":""},D(e.submitText),9,oo)],32)]))}},Br=Y(ro,[["__scopeId","data-v-b73321cf"]]),so={class:"section-block","data-component":"session-list-section"},io={class:"section-header"},ao={class:"section-description"},lo={class:"section-body"},uo=["onKeydown"],co=["href"],fo={class:"session-list"},ho=["onFocusin","onKeydown"],go={class:"item-top"},mo={class:"item-title"},yo={class:"item-actions"},po={key:0,class:"badge badge-current"},wo={key:1,class:"badge badge-current"},bo={key:2,class:"badge badge-current"},vo={key:3,class:"badge"},Co=["onClick","disabled","title"],So={class:"item-details"},Eo={class:"session-dates"},_o={class:"date-label"},ko=["onClick"],Bo={key:1,class:"empty-state"},Ir={__name:"SessionList",props:{sessions:{type:Array,default:()=>[]},emptyMessage:{type:String,default:"You currently have no other active sessions."},sectionDescription:{type:String,default:"Review where you're signed in and end any sessions you no longer recognize."},terminatingSessions:{type:Object,default:()=>({})},hoveredCredentialUuid:{type:String,default:null},navigationDisabled:{type:Boolean,default:!1}},emits:["terminate","sessionHover","navigate-out"],setup(e,{emit:s}){const r=e,t=s,n=$e(),o=F(null),i=F(null),a=c=>{i.value=c,o.value=c.ip||null,t("sessionHover",c)},l=c=>{c.currentTarget.contains(c.relatedTarget)||(i.value=null,o.value=null,t("sessionHover",null))},u=c=>{c.currentTarget.matches(":focus")||(c.currentTarget.focus(),c.stopPropagation())},f=c=>!!r.terminatingSessions[c],w=(c,S)=>{const I=c.currentTarget,p=I.querySelector(".session-list")?.querySelectorAll(".session-item"),y=Array.from(document.querySelectorAll(".session-group")),m=y.indexOf(I);if(c.key==="Enter"&&c.target===I){S&&I.querySelector("a")?.click();return}if(r.navigationDisabled)return;const E=z(c);if(["down","right"].includes(E)&&c.target===I){c.preventDefault(),p?.[0]?.focus();return}if(["up","left"].includes(E)&&c.target===I){c.preventDefault(),m>0?y[m-1].focus():t("navigate-out","up");return}Dt(c,_=>t("navigate-out",_))},b=(c,S)=>{if(Pt(c,()=>{f(S.id)||t("terminate",S)}),c.defaultPrevented||r.navigationDisabled)return;const I=z(c);if(I){c.preventDefault();const C=c.currentTarget.closest(".session-group"),p=C.querySelector(".session-list");if(Nt(p,c.currentTarget,I,{itemSelector:".session-item"})==="boundary"){if(I==="left"||I==="up")C?.focus();else if(I==="down"||I==="right"){const m=Array.from(document.querySelectorAll(".session-group")),E=m.indexOf(C);E<m.length-1?m[E+1].focus():t("navigate-out","down")}}}c.key==="Escape"&&(c.preventDefault(),c.currentTarget.closest(".session-group")?.focus())},h=c=>`${c.includes(":")?"http":"https"}://${c}`,d=async c=>{if(c)try{await navigator.clipboard.writeText(c),n.showMessage("Full IP copied to clipboard!","success",2e3)}catch(S){console.error("Failed to copy IP:",S),n.showMessage("Failed to copy IP","error",3e3)}},g=c=>ae(c)??c,N=x(()=>{if(o.value)return ae(o.value);const c=r.sessions.find(S=>S.is_current);return c?ae(c.ip):null}),A=c=>N.value&&ae(c)===N.value,P=x(()=>{const c={};for(const p of r.sessions){const y=p.host||"";c[y]||(c[y]={sessions:[],isCurrentSite:!1}),c[y].sessions.push(p),p.is_current_host&&(c[y].isCurrentSite=!0)}for(const p in c)c[p].sessions.sort((y,m)=>new Date(m.last_renewed)-new Date(y.last_renewed));const S=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"}),I=Object.keys(c).sort(S.compare),C={};for(const p of I)C[p]=c[p];return C});return(c,S)=>(T(),R("section",so,[v("div",io,[S[2]||(S[2]=v("h2",null,"Active Sessions",-1)),v("p",ao,D(e.sectionDescription),1)]),v("div",lo,[v("div",null,[Array.isArray(e.sessions)&&e.sessions.length?(T(!0),R(oe,{key:0},ce(P.value,(I,C)=>(T(),R("div",{key:C,class:"session-group",tabindex:"0",onKeydown:p=>w(p,C)},[v("span",{class:se(["session-group-host",{"is-current-site":I.isCurrentSite}])},[S[3]||(S[3]=v("span",{class:"session-group-icon"},"🌐",-1)),C?(T(),R("a",{key:0,href:h(C),tabindex:"-1",target:"_blank",rel:"noopener noreferrer"},D(C),9,co)):(T(),R(oe,{key:1},[xe("Unbound host")],64))],2),v("div",fo,[(T(!0),R(oe,null,ce(I.sessions,p=>(T(),R("div",{key:p.id,class:se(["session-item",{"is-current":p.is_current&&!o.value&&!e.hoveredCredentialUuid,"is-hovered":i.value?.id===p.id,"is-linked-credential":e.hoveredCredentialUuid===p.credential}]),tabindex:"-1",onMousedown:S[0]||(S[0]=de(()=>{},["prevent"])),onClickCapture:u,onFocusin:y=>a(p),onFocusout:S[1]||(S[1]=y=>l(y)),onKeydown:y=>b(y,p)},[v("div",go,[v("h4",mo,D(p.user_agent),1),v("div",yo,[p.is_current&&!o.value&&!e.hoveredCredentialUuid?(T(),R("span",po,"Current")):i.value?.id===p.id?(T(),R("span",wo,"Selected")):e.hoveredCredentialUuid===p.credential?(T(),R("span",bo,"Linked")):!e.hoveredCredentialUuid&&A(p.ip)?(T(),R("span",vo,"Same IP")):L("",!0),v("button",{onClick:y=>c.$emit("terminate",p),class:"btn-card-delete",disabled:f(p.id),title:f(p.id)?"Terminating...":"Terminate session",tabindex:"-1"},"❌",8,Co)])]),v("div",So,[v("div",Eo,[v("span",_o,D(U(G)(p.last_renewed)),1),v("span",{class:"date-value",onClick:y=>d(p.ip),title:"Click to copy full IP"},D(g(p.ip)),9,ko)])])],42,ho))),128))])],40,uo))),128)):(T(),R("div",Bo,[v("p",null,D(e.emptyMessage),1)]))])])]))}};function Io(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var te={},we,et;function Ao(){return et||(et=1,we=function(){return typeof Promise=="function"&&Promise.prototype&&Promise.prototype.then}),we}var be={},$={},tt;function W(){if(tt)return $;tt=1;let e;const s=[0,26,44,70,100,134,172,196,242,292,346,404,466,532,581,655,733,815,901,991,1085,1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,2611,2761,2876,3034,3196,3362,3532,3706];return $.getSymbolSize=function(t){if(!t)throw new Error('"version" cannot be null or undefined');if(t<1||t>40)throw new Error('"version" should be in range from 1 to 40');return t*4+17},$.getSymbolTotalCodewords=function(t){return s[t]},$.getBCHDigit=function(r){let t=0;for(;r!==0;)t++,r>>>=1;return t},$.setToSJISFunction=function(t){if(typeof t!="function")throw new Error('"toSJISFunc" is not a valid function.');e=t},$.isKanjiModeEnabled=function(){return typeof e<"u"},$.toSJIS=function(t){return e(t)},$}var ve={},nt;function Je(){return nt||(nt=1,(function(e){e.L={bit:1},e.M={bit:0},e.Q={bit:3},e.H={bit:2};function s(r){if(typeof r!="string")throw new Error("Param is not a string");switch(r.toLowerCase()){case"l":case"low":return e.L;case"m":case"medium":return e.M;case"q":case"quartile":return e.Q;case"h":case"high":return e.H;default:throw new Error("Unknown EC Level: "+r)}}e.isValid=function(t){return t&&typeof t.bit<"u"&&t.bit>=0&&t.bit<4},e.from=function(t,n){if(e.isValid(t))return t;try{return s(t)}catch{return n}}})(ve)),ve}var Ce,ot;function Ro(){if(ot)return Ce;ot=1;function e(){this.buffer=[],this.length=0}return e.prototype={get:function(s){const r=Math.floor(s/8);return(this.buffer[r]>>>7-s%8&1)===1},put:function(s,r){for(let t=0;t<r;t++)this.putBit((s>>>r-t-1&1)===1)},getLengthInBits:function(){return this.length},putBit:function(s){const r=Math.floor(this.length/8);this.buffer.length<=r&&this.buffer.push(0),s&&(this.buffer[r]|=128>>>this.length%8),this.length++}},Ce=e,Ce}var Se,rt;function To(){if(rt)return Se;rt=1;function e(s){if(!s||s<1)throw new Error("BitMatrix size must be defined and greater than 0");this.size=s,this.data=new Uint8Array(s*s),this.reservedBit=new Uint8Array(s*s)}return e.prototype.set=function(s,r,t,n){const o=s*this.size+r;this.data[o]=t,n&&(this.reservedBit[o]=!0)},e.prototype.get=function(s,r){return this.data[s*this.size+r]},e.prototype.xor=function(s,r,t){this.data[s*this.size+r]^=t},e.prototype.isReserved=function(s,r){return this.reservedBit[s*this.size+r]},Se=e,Se}var Ee={},st;function Mo(){return st||(st=1,(function(e){const s=W().getSymbolSize;e.getRowColCoords=function(t){if(t===1)return[];const n=Math.floor(t/7)+2,o=s(t),i=o===145?26:Math.ceil((o-13)/(2*n-2))*2,a=[o-7];for(let l=1;l<n-1;l++)a[l]=a[l-1]-i;return a.push(6),a.reverse()},e.getPositions=function(t){const n=[],o=e.getRowColCoords(t),i=o.length;for(let a=0;a<i;a++)for(let l=0;l<i;l++)a===0&&l===0||a===0&&l===i-1||a===i-1&&l===0||n.push([o[a],o[l]]);return n}})(Ee)),Ee}var _e={},it;function No(){if(it)return _e;it=1;const e=W().getSymbolSize,s=7;return _e.getPositions=function(t){const n=e(t);return[[0,0],[n-s,0],[0,n-s]]},_e}var ke={},at;function Po(){return at||(at=1,(function(e){e.Patterns={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};const s={N1:3,N2:3,N3:40,N4:10};e.isValid=function(n){return n!=null&&n!==""&&!isNaN(n)&&n>=0&&n<=7},e.from=function(n){return e.isValid(n)?parseInt(n,10):void 0},e.getPenaltyN1=function(n){const o=n.size;let i=0,a=0,l=0,u=null,f=null;for(let w=0;w<o;w++){a=l=0,u=f=null;for(let b=0;b<o;b++){let h=n.get(w,b);h===u?a++:(a>=5&&(i+=s.N1+(a-5)),u=h,a=1),h=n.get(b,w),h===f?l++:(l>=5&&(i+=s.N1+(l-5)),f=h,l=1)}a>=5&&(i+=s.N1+(a-5)),l>=5&&(i+=s.N1+(l-5))}return i},e.getPenaltyN2=function(n){const o=n.size;let i=0;for(let a=0;a<o-1;a++)for(let l=0;l<o-1;l++){const u=n.get(a,l)+n.get(a,l+1)+n.get(a+1,l)+n.get(a+1,l+1);(u===4||u===0)&&i++}return i*s.N2},e.getPenaltyN3=function(n){const o=n.size;let i=0,a=0,l=0;for(let u=0;u<o;u++){a=l=0;for(let f=0;f<o;f++)a=a<<1&2047|n.get(u,f),f>=10&&(a===1488||a===93)&&i++,l=l<<1&2047|n.get(f,u),f>=10&&(l===1488||l===93)&&i++}return i*s.N3},e.getPenaltyN4=function(n){let o=0;const i=n.data.length;for(let l=0;l<i;l++)o+=n.data[l];return Math.abs(Math.ceil(o*100/i/5)-10)*s.N4};function r(t,n,o){switch(t){case e.Patterns.PATTERN000:return(n+o)%2===0;case e.Patterns.PATTERN001:return n%2===0;case e.Patterns.PATTERN010:return o%3===0;case e.Patterns.PATTERN011:return(n+o)%3===0;case e.Patterns.PATTERN100:return(Math.floor(n/2)+Math.floor(o/3))%2===0;case e.Patterns.PATTERN101:return n*o%2+n*o%3===0;case e.Patterns.PATTERN110:return(n*o%2+n*o%3)%2===0;case e.Patterns.PATTERN111:return(n*o%3+(n+o)%2)%2===0;default:throw new Error("bad maskPattern:"+t)}}e.applyMask=function(n,o){const i=o.size;for(let a=0;a<i;a++)for(let l=0;l<i;l++)o.isReserved(l,a)||o.xor(l,a,r(n,l,a))},e.getBestMask=function(n,o){const i=Object.keys(e.Patterns).length;let a=0,l=1/0;for(let u=0;u<i;u++){o(u),e.applyMask(u,n);const f=e.getPenaltyN1(n)+e.getPenaltyN2(n)+e.getPenaltyN3(n)+e.getPenaltyN4(n);e.applyMask(u,n),f<l&&(l=f,a=u)}return a}})(ke)),ke}var le={},lt;function Ot(){if(lt)return le;lt=1;const e=Je(),s=[1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,4,1,2,4,4,2,4,4,4,2,4,6,5,2,4,6,6,2,5,8,8,4,5,8,8,4,5,8,11,4,8,10,11,4,9,12,16,4,9,16,16,6,10,12,18,6,10,17,16,6,11,16,19,6,13,18,21,7,14,21,25,8,16,20,25,8,17,23,25,9,17,23,34,9,18,25,30,10,20,27,32,12,21,29,35,12,23,34,37,12,25,34,40,13,26,35,42,14,28,38,45,15,29,40,48,16,31,43,51,17,33,45,54,18,35,48,57,19,37,51,60,19,38,53,63,20,40,56,66,21,43,59,70,22,45,62,74,24,47,65,77,25,49,68,81],r=[7,10,13,17,10,16,22,28,15,26,36,44,20,36,52,64,26,48,72,88,36,64,96,112,40,72,108,130,48,88,132,156,60,110,160,192,72,130,192,224,80,150,224,264,96,176,260,308,104,198,288,352,120,216,320,384,132,240,360,432,144,280,408,480,168,308,448,532,180,338,504,588,196,364,546,650,224,416,600,700,224,442,644,750,252,476,690,816,270,504,750,900,300,560,810,960,312,588,870,1050,336,644,952,1110,360,700,1020,1200,390,728,1050,1260,420,784,1140,1350,450,812,1200,1440,480,868,1290,1530,510,924,1350,1620,540,980,1440,1710,570,1036,1530,1800,570,1064,1590,1890,600,1120,1680,1980,630,1204,1770,2100,660,1260,1860,2220,720,1316,1950,2310,750,1372,2040,2430];return le.getBlocksCount=function(n,o){switch(o){case e.L:return s[(n-1)*4+0];case e.M:return s[(n-1)*4+1];case e.Q:return s[(n-1)*4+2];case e.H:return s[(n-1)*4+3];default:return}},le.getTotalCodewordsCount=function(n,o){switch(o){case e.L:return r[(n-1)*4+0];case e.M:return r[(n-1)*4+1];case e.Q:return r[(n-1)*4+2];case e.H:return r[(n-1)*4+3];default:return}},le}var Be={},ne={},ut;function Do(){if(ut)return ne;ut=1;const e=new Uint8Array(512),s=new Uint8Array(256);return(function(){let t=1;for(let n=0;n<255;n++)e[n]=t,s[t]=n,t<<=1,t&256&&(t^=285);for(let n=255;n<512;n++)e[n]=e[n-255]})(),ne.log=function(t){if(t<1)throw new Error("log("+t+")");return s[t]},ne.exp=function(t){return e[t]},ne.mul=function(t,n){return t===0||n===0?0:e[s[t]+s[n]]},ne}var ct;function Lo(){return ct||(ct=1,(function(e){const s=Do();e.mul=function(t,n){const o=new Uint8Array(t.length+n.length-1);for(let i=0;i<t.length;i++)for(let a=0;a<n.length;a++)o[i+a]^=s.mul(t[i],n[a]);return o},e.mod=function(t,n){let o=new Uint8Array(t);for(;o.length-n.length>=0;){const i=o[0];for(let l=0;l<n.length;l++)o[l]^=s.mul(n[l],i);let a=0;for(;a<o.length&&o[a]===0;)a++;o=o.slice(a)}return o},e.generateECPolynomial=function(t){let n=new Uint8Array([1]);for(let o=0;o<t;o++)n=e.mul(n,new Uint8Array([1,s.exp(o)]));return n}})(Be)),Be}var Ie,dt;function qo(){if(dt)return Ie;dt=1;const e=Lo();function s(r){this.genPoly=void 0,this.degree=r,this.degree&&this.initialize(this.degree)}return s.prototype.initialize=function(t){this.degree=t,this.genPoly=e.generateECPolynomial(this.degree)},s.prototype.encode=function(t){if(!this.genPoly)throw new Error("Encoder not initialized");const n=new Uint8Array(t.length+this.degree);n.set(t);const o=e.mod(n,this.genPoly),i=this.degree-o.length;if(i>0){const a=new Uint8Array(this.degree);return a.set(o,i),a}return o},Ie=s,Ie}var Ae={},Re={},Te={},ft;function jt(){return ft||(ft=1,Te.isValid=function(s){return!isNaN(s)&&s>=1&&s<=40}),Te}var H={},ht;function zt(){if(ht)return H;ht=1;const e="[0-9]+",s="[A-Z $%*+\\-./:]+";let r="(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";r=r.replace(/u/g,"\\u");const t="(?:(?![A-Z0-9 $%*+\\-./:]|"+r+`)(?:.|[\r
2
- ]))+`;H.KANJI=new RegExp(r,"g"),H.BYTE_KANJI=new RegExp("[^A-Z0-9 $%*+\\-./:]+","g"),H.BYTE=new RegExp(t,"g"),H.NUMERIC=new RegExp(e,"g"),H.ALPHANUMERIC=new RegExp(s,"g");const n=new RegExp("^"+r+"$"),o=new RegExp("^"+e+"$"),i=new RegExp("^[A-Z0-9 $%*+\\-./:]+$");return H.testKanji=function(l){return n.test(l)},H.testNumeric=function(l){return o.test(l)},H.testAlphanumeric=function(l){return i.test(l)},H}var gt;function Z(){return gt||(gt=1,(function(e){const s=jt(),r=zt();e.NUMERIC={id:"Numeric",bit:1,ccBits:[10,12,14]},e.ALPHANUMERIC={id:"Alphanumeric",bit:2,ccBits:[9,11,13]},e.BYTE={id:"Byte",bit:4,ccBits:[8,16,16]},e.KANJI={id:"Kanji",bit:8,ccBits:[8,10,12]},e.MIXED={bit:-1},e.getCharCountIndicator=function(o,i){if(!o.ccBits)throw new Error("Invalid mode: "+o);if(!s.isValid(i))throw new Error("Invalid version: "+i);return i>=1&&i<10?o.ccBits[0]:i<27?o.ccBits[1]:o.ccBits[2]},e.getBestModeForData=function(o){return r.testNumeric(o)?e.NUMERIC:r.testAlphanumeric(o)?e.ALPHANUMERIC:r.testKanji(o)?e.KANJI:e.BYTE},e.toString=function(o){if(o&&o.id)return o.id;throw new Error("Invalid mode")},e.isValid=function(o){return o&&o.bit&&o.ccBits};function t(n){if(typeof n!="string")throw new Error("Param is not a string");switch(n.toLowerCase()){case"numeric":return e.NUMERIC;case"alphanumeric":return e.ALPHANUMERIC;case"kanji":return e.KANJI;case"byte":return e.BYTE;default:throw new Error("Unknown mode: "+n)}}e.from=function(o,i){if(e.isValid(o))return o;try{return t(o)}catch{return i}}})(Re)),Re}var mt;function Fo(){return mt||(mt=1,(function(e){const s=W(),r=Ot(),t=Je(),n=Z(),o=jt(),i=7973,a=s.getBCHDigit(i);function l(b,h,d){for(let g=1;g<=40;g++)if(h<=e.getCapacity(g,d,b))return g}function u(b,h){return n.getCharCountIndicator(b,h)+4}function f(b,h){let d=0;return b.forEach(function(g){const N=u(g.mode,h);d+=N+g.getBitsLength()}),d}function w(b,h){for(let d=1;d<=40;d++)if(f(b,d)<=e.getCapacity(d,h,n.MIXED))return d}e.from=function(h,d){return o.isValid(h)?parseInt(h,10):d},e.getCapacity=function(h,d,g){if(!o.isValid(h))throw new Error("Invalid QR Code version");typeof g>"u"&&(g=n.BYTE);const N=s.getSymbolTotalCodewords(h),A=r.getTotalCodewordsCount(h,d),P=(N-A)*8;if(g===n.MIXED)return P;const c=P-u(g,h);switch(g){case n.NUMERIC:return Math.floor(c/10*3);case n.ALPHANUMERIC:return Math.floor(c/11*2);case n.KANJI:return Math.floor(c/13);case n.BYTE:default:return Math.floor(c/8)}},e.getBestVersionForData=function(h,d){let g;const N=t.from(d,t.M);if(Array.isArray(h)){if(h.length>1)return w(h,N);if(h.length===0)return 1;g=h[0]}else g=h;return l(g.mode,g.getLength(),N)},e.getEncodedBits=function(h){if(!o.isValid(h)||h<7)throw new Error("Invalid QR Code version");let d=h<<12;for(;s.getBCHDigit(d)-a>=0;)d^=i<<s.getBCHDigit(d)-a;return h<<12|d}})(Ae)),Ae}var Me={},yt;function Uo(){if(yt)return Me;yt=1;const e=W(),s=1335,r=21522,t=e.getBCHDigit(s);return Me.getEncodedBits=function(o,i){const a=o.bit<<3|i;let l=a<<10;for(;e.getBCHDigit(l)-t>=0;)l^=s<<e.getBCHDigit(l)-t;return(a<<10|l)^r},Me}var Ne={},Pe,pt;function Ko(){if(pt)return Pe;pt=1;const e=Z();function s(r){this.mode=e.NUMERIC,this.data=r.toString()}return s.getBitsLength=function(t){return 10*Math.floor(t/3)+(t%3?t%3*3+1:0)},s.prototype.getLength=function(){return this.data.length},s.prototype.getBitsLength=function(){return s.getBitsLength(this.data.length)},s.prototype.write=function(t){let n,o,i;for(n=0;n+3<=this.data.length;n+=3)o=this.data.substr(n,3),i=parseInt(o,10),t.put(i,10);const a=this.data.length-n;a>0&&(o=this.data.substr(n),i=parseInt(o,10),t.put(i,a*3+1))},Pe=s,Pe}var De,wt;function Vo(){if(wt)return De;wt=1;const e=Z(),s=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":"];function r(t){this.mode=e.ALPHANUMERIC,this.data=t}return r.getBitsLength=function(n){return 11*Math.floor(n/2)+6*(n%2)},r.prototype.getLength=function(){return this.data.length},r.prototype.getBitsLength=function(){return r.getBitsLength(this.data.length)},r.prototype.write=function(n){let o;for(o=0;o+2<=this.data.length;o+=2){let i=s.indexOf(this.data[o])*45;i+=s.indexOf(this.data[o+1]),n.put(i,11)}this.data.length%2&&n.put(s.indexOf(this.data[o]),6)},De=r,De}var Le,bt;function Ho(){if(bt)return Le;bt=1;const e=Z();function s(r){this.mode=e.BYTE,typeof r=="string"?this.data=new TextEncoder().encode(r):this.data=new Uint8Array(r)}return s.getBitsLength=function(t){return t*8},s.prototype.getLength=function(){return this.data.length},s.prototype.getBitsLength=function(){return s.getBitsLength(this.data.length)},s.prototype.write=function(r){for(let t=0,n=this.data.length;t<n;t++)r.put(this.data[t],8)},Le=s,Le}var qe,vt;function Oo(){if(vt)return qe;vt=1;const e=Z(),s=W();function r(t){this.mode=e.KANJI,this.data=t}return r.getBitsLength=function(n){return n*13},r.prototype.getLength=function(){return this.data.length},r.prototype.getBitsLength=function(){return r.getBitsLength(this.data.length)},r.prototype.write=function(t){let n;for(n=0;n<this.data.length;n++){let o=s.toSJIS(this.data[n]);if(o>=33088&&o<=40956)o-=33088;else if(o>=57408&&o<=60351)o-=49472;else throw new Error("Invalid SJIS character: "+this.data[n]+`
3
- Make sure your charset is UTF-8`);o=(o>>>8&255)*192+(o&255),t.put(o,13)}},qe=r,qe}var Fe={exports:{}},Ct;function jo(){return Ct||(Ct=1,(function(e){var s={single_source_shortest_paths:function(r,t,n){var o={},i={};i[t]=0;var a=s.PriorityQueue.make();a.push(t,0);for(var l,u,f,w,b,h,d,g,N;!a.empty();){l=a.pop(),u=l.value,w=l.cost,b=r[u]||{};for(f in b)b.hasOwnProperty(f)&&(h=b[f],d=w+h,g=i[f],N=typeof i[f]>"u",(N||g>d)&&(i[f]=d,a.push(f,d),o[f]=u))}if(typeof n<"u"&&typeof i[n]>"u"){var A=["Could not find a path from ",t," to ",n,"."].join("");throw new Error(A)}return o},extract_shortest_path_from_predecessor_list:function(r,t){for(var n=[],o=t;o;)n.push(o),r[o],o=r[o];return n.reverse(),n},find_path:function(r,t,n){var o=s.single_source_shortest_paths(r,t,n);return s.extract_shortest_path_from_predecessor_list(o,n)},PriorityQueue:{make:function(r){var t=s.PriorityQueue,n={},o;r=r||{};for(o in t)t.hasOwnProperty(o)&&(n[o]=t[o]);return n.queue=[],n.sorter=r.sorter||t.default_sorter,n},default_sorter:function(r,t){return r.cost-t.cost},push:function(r,t){var n={value:r,cost:t};this.queue.push(n),this.queue.sort(this.sorter)},pop:function(){return this.queue.shift()},empty:function(){return this.queue.length===0}}};e.exports=s})(Fe)),Fe.exports}var St;function zo(){return St||(St=1,(function(e){const s=Z(),r=Ko(),t=Vo(),n=Ho(),o=Oo(),i=zt(),a=W(),l=jo();function u(A){return unescape(encodeURIComponent(A)).length}function f(A,P,c){const S=[];let I;for(;(I=A.exec(c))!==null;)S.push({data:I[0],index:I.index,mode:P,length:I[0].length});return S}function w(A){const P=f(i.NUMERIC,s.NUMERIC,A),c=f(i.ALPHANUMERIC,s.ALPHANUMERIC,A);let S,I;return a.isKanjiModeEnabled()?(S=f(i.BYTE,s.BYTE,A),I=f(i.KANJI,s.KANJI,A)):(S=f(i.BYTE_KANJI,s.BYTE,A),I=[]),P.concat(c,S,I).sort(function(p,y){return p.index-y.index}).map(function(p){return{data:p.data,mode:p.mode,length:p.length}})}function b(A,P){switch(P){case s.NUMERIC:return r.getBitsLength(A);case s.ALPHANUMERIC:return t.getBitsLength(A);case s.KANJI:return o.getBitsLength(A);case s.BYTE:return n.getBitsLength(A)}}function h(A){return A.reduce(function(P,c){const S=P.length-1>=0?P[P.length-1]:null;return S&&S.mode===c.mode?(P[P.length-1].data+=c.data,P):(P.push(c),P)},[])}function d(A){const P=[];for(let c=0;c<A.length;c++){const S=A[c];switch(S.mode){case s.NUMERIC:P.push([S,{data:S.data,mode:s.ALPHANUMERIC,length:S.length},{data:S.data,mode:s.BYTE,length:S.length}]);break;case s.ALPHANUMERIC:P.push([S,{data:S.data,mode:s.BYTE,length:S.length}]);break;case s.KANJI:P.push([S,{data:S.data,mode:s.BYTE,length:u(S.data)}]);break;case s.BYTE:P.push([{data:S.data,mode:s.BYTE,length:u(S.data)}])}}return P}function g(A,P){const c={},S={start:{}};let I=["start"];for(let C=0;C<A.length;C++){const p=A[C],y=[];for(let m=0;m<p.length;m++){const E=p[m],_=""+C+m;y.push(_),c[_]={node:E,lastCount:0},S[_]={};for(let k=0;k<I.length;k++){const B=I[k];c[B]&&c[B].node.mode===E.mode?(S[B][_]=b(c[B].lastCount+E.length,E.mode)-b(c[B].lastCount,E.mode),c[B].lastCount+=E.length):(c[B]&&(c[B].lastCount=E.length),S[B][_]=b(E.length,E.mode)+4+s.getCharCountIndicator(E.mode,P))}}I=y}for(let C=0;C<I.length;C++)S[I[C]].end=0;return{map:S,table:c}}function N(A,P){let c;const S=s.getBestModeForData(A);if(c=s.from(P,S),c!==s.BYTE&&c.bit<S.bit)throw new Error('"'+A+'" cannot be encoded with mode '+s.toString(c)+`.
4
- Suggested mode is: `+s.toString(S));switch(c===s.KANJI&&!a.isKanjiModeEnabled()&&(c=s.BYTE),c){case s.NUMERIC:return new r(A);case s.ALPHANUMERIC:return new t(A);case s.KANJI:return new o(A);case s.BYTE:return new n(A)}}e.fromArray=function(P){return P.reduce(function(c,S){return typeof S=="string"?c.push(N(S,null)):S.data&&c.push(N(S.data,S.mode)),c},[])},e.fromString=function(P,c){const S=w(P,a.isKanjiModeEnabled()),I=d(S),C=g(I,c),p=l.find_path(C.map,"start","end"),y=[];for(let m=1;m<p.length-1;m++)y.push(C.table[p[m]].node);return e.fromArray(h(y))},e.rawSplit=function(P){return e.fromArray(w(P,a.isKanjiModeEnabled()))}})(Ne)),Ne}var Et;function xo(){if(Et)return be;Et=1;const e=W(),s=Je(),r=Ro(),t=To(),n=Mo(),o=No(),i=Po(),a=Ot(),l=qo(),u=Fo(),f=Uo(),w=Z(),b=zo();function h(C,p){const y=C.size,m=o.getPositions(p);for(let E=0;E<m.length;E++){const _=m[E][0],k=m[E][1];for(let B=-1;B<=7;B++)if(!(_+B<=-1||y<=_+B))for(let M=-1;M<=7;M++)k+M<=-1||y<=k+M||(B>=0&&B<=6&&(M===0||M===6)||M>=0&&M<=6&&(B===0||B===6)||B>=2&&B<=4&&M>=2&&M<=4?C.set(_+B,k+M,!0,!0):C.set(_+B,k+M,!1,!0))}}function d(C){const p=C.size;for(let y=8;y<p-8;y++){const m=y%2===0;C.set(y,6,m,!0),C.set(6,y,m,!0)}}function g(C,p){const y=n.getPositions(p);for(let m=0;m<y.length;m++){const E=y[m][0],_=y[m][1];for(let k=-2;k<=2;k++)for(let B=-2;B<=2;B++)k===-2||k===2||B===-2||B===2||k===0&&B===0?C.set(E+k,_+B,!0,!0):C.set(E+k,_+B,!1,!0)}}function N(C,p){const y=C.size,m=u.getEncodedBits(p);let E,_,k;for(let B=0;B<18;B++)E=Math.floor(B/3),_=B%3+y-8-3,k=(m>>B&1)===1,C.set(E,_,k,!0),C.set(_,E,k,!0)}function A(C,p,y){const m=C.size,E=f.getEncodedBits(p,y);let _,k;for(_=0;_<15;_++)k=(E>>_&1)===1,_<6?C.set(_,8,k,!0):_<8?C.set(_+1,8,k,!0):C.set(m-15+_,8,k,!0),_<8?C.set(8,m-_-1,k,!0):_<9?C.set(8,15-_-1+1,k,!0):C.set(8,15-_-1,k,!0);C.set(m-8,8,1,!0)}function P(C,p){const y=C.size;let m=-1,E=y-1,_=7,k=0;for(let B=y-1;B>0;B-=2)for(B===6&&B--;;){for(let M=0;M<2;M++)if(!C.isReserved(E,B-M)){let V=!1;k<p.length&&(V=(p[k]>>>_&1)===1),C.set(E,B-M,V),_--,_===-1&&(k++,_=7)}if(E+=m,E<0||y<=E){E-=m,m=-m;break}}}function c(C,p,y){const m=new r;y.forEach(function(M){m.put(M.mode.bit,4),m.put(M.getLength(),w.getCharCountIndicator(M.mode,C)),M.write(m)});const E=e.getSymbolTotalCodewords(C),_=a.getTotalCodewordsCount(C,p),k=(E-_)*8;for(m.getLengthInBits()+4<=k&&m.put(0,4);m.getLengthInBits()%8!==0;)m.putBit(0);const B=(k-m.getLengthInBits())/8;for(let M=0;M<B;M++)m.put(M%2?17:236,8);return S(m,C,p)}function S(C,p,y){const m=e.getSymbolTotalCodewords(p),E=a.getTotalCodewordsCount(p,y),_=m-E,k=a.getBlocksCount(p,y),B=m%k,M=k-B,V=Math.floor(m/k),K=Math.floor(_/k),q=K+1,Ye=V-K,$t=new l(Ye);let he=0;const ie=new Array(k),Qe=new Array(k);let ge=0;const Jt=new Uint8Array(C.buffer);for(let X=0;X<k;X++){const ye=X<M?K:q;ie[X]=Jt.slice(he,he+ye),Qe[X]=$t.encode(ie[X]),he+=ye,ge=Math.max(ge,ye)}const me=new Uint8Array(m);let Ge=0,O,j;for(O=0;O<ge;O++)for(j=0;j<k;j++)O<ie[j].length&&(me[Ge++]=ie[j][O]);for(O=0;O<Ye;O++)for(j=0;j<k;j++)me[Ge++]=Qe[j][O];return me}function I(C,p,y,m){let E;if(Array.isArray(C))E=b.fromArray(C);else if(typeof C=="string"){let V=p;if(!V){const K=b.rawSplit(C);V=u.getBestVersionForData(K,y)}E=b.fromString(C,V||40)}else throw new Error("Invalid data");const _=u.getBestVersionForData(E,y);if(!_)throw new Error("The amount of data is too big to be stored in a QR Code");if(!p)p=_;else if(p<_)throw new Error(`
5
- The chosen QR Code version cannot contain this amount of data.
6
- Minimum version required to store current data is: `+_+`.
7
- `);const k=c(p,y,E),B=e.getSymbolSize(p),M=new t(B);return h(M,p),d(M),g(M,p),A(M,y,0),p>=7&&N(M,p),P(M,k),isNaN(m)&&(m=i.getBestMask(M,A.bind(null,M,y))),i.applyMask(m,M),A(M,y,m),{modules:M,version:p,errorCorrectionLevel:y,maskPattern:m,segments:E}}return be.create=function(p,y){if(typeof p>"u"||p==="")throw new Error("No input text");let m=s.M,E,_;return typeof y<"u"&&(m=s.from(y.errorCorrectionLevel,s.M),E=u.from(y.version),_=i.from(y.maskPattern),y.toSJISFunc&&e.setToSJISFunction(y.toSJISFunc)),I(p,E,m,_)},be}var Ue={},Ke={},_t;function xt(){return _t||(_t=1,(function(e){function s(r){if(typeof r=="number"&&(r=r.toString()),typeof r!="string")throw new Error("Color should be defined as hex string");let t=r.slice().replace("#","").split("");if(t.length<3||t.length===5||t.length>8)throw new Error("Invalid hex color: "+r);(t.length===3||t.length===4)&&(t=Array.prototype.concat.apply([],t.map(function(o){return[o,o]}))),t.length===6&&t.push("F","F");const n=parseInt(t.join(""),16);return{r:n>>24&255,g:n>>16&255,b:n>>8&255,a:n&255,hex:"#"+t.slice(0,6).join("")}}e.getOptions=function(t){t||(t={}),t.color||(t.color={});const n=typeof t.margin>"u"||t.margin===null||t.margin<0?4:t.margin,o=t.width&&t.width>=21?t.width:void 0,i=t.scale||4;return{width:o,scale:o?4:i,margin:n,color:{dark:s(t.color.dark||"#000000ff"),light:s(t.color.light||"#ffffffff")},type:t.type,rendererOpts:t.rendererOpts||{}}},e.getScale=function(t,n){return n.width&&n.width>=t+n.margin*2?n.width/(t+n.margin*2):n.scale},e.getImageWidth=function(t,n){const o=e.getScale(t,n);return Math.floor((t+n.margin*2)*o)},e.qrToImageData=function(t,n,o){const i=n.modules.size,a=n.modules.data,l=e.getScale(i,o),u=Math.floor((i+o.margin*2)*l),f=o.margin*l,w=[o.color.light,o.color.dark];for(let b=0;b<u;b++)for(let h=0;h<u;h++){let d=(b*u+h)*4,g=o.color.light;if(b>=f&&h>=f&&b<u-f&&h<u-f){const N=Math.floor((b-f)/l),A=Math.floor((h-f)/l);g=w[a[N*i+A]?1:0]}t[d++]=g.r,t[d++]=g.g,t[d++]=g.b,t[d]=g.a}}})(Ke)),Ke}var kt;function $o(){return kt||(kt=1,(function(e){const s=xt();function r(n,o,i){n.clearRect(0,0,o.width,o.height),o.style||(o.style={}),o.height=i,o.width=i,o.style.height=i+"px",o.style.width=i+"px"}function t(){try{return document.createElement("canvas")}catch{throw new Error("You need to specify a canvas element")}}e.render=function(o,i,a){let l=a,u=i;typeof l>"u"&&(!i||!i.getContext)&&(l=i,i=void 0),i||(u=t()),l=s.getOptions(l);const f=s.getImageWidth(o.modules.size,l),w=u.getContext("2d"),b=w.createImageData(f,f);return s.qrToImageData(b.data,o,l),r(w,u,f),w.putImageData(b,0,0),u},e.renderToDataURL=function(o,i,a){let l=a;typeof l>"u"&&(!i||!i.getContext)&&(l=i,i=void 0),l||(l={});const u=e.render(o,i,l),f=l.type||"image/png",w=l.rendererOpts||{};return u.toDataURL(f,w.quality)}})(Ue)),Ue}var Ve={},Bt;function Jo(){if(Bt)return Ve;Bt=1;const e=xt();function s(n,o){const i=n.a/255,a=o+'="'+n.hex+'"';return i<1?a+" "+o+'-opacity="'+i.toFixed(2).slice(1)+'"':a}function r(n,o,i){let a=n+o;return typeof i<"u"&&(a+=" "+i),a}function t(n,o,i){let a="",l=0,u=!1,f=0;for(let w=0;w<n.length;w++){const b=Math.floor(w%o),h=Math.floor(w/o);!b&&!u&&(u=!0),n[w]?(f++,w>0&&b>0&&n[w-1]||(a+=u?r("M",b+i,.5+h+i):r("m",l,0),l=0,u=!1),b+1<o&&n[w+1]||(a+=r("h",f),f=0)):l++}return a}return Ve.render=function(o,i,a){const l=e.getOptions(i),u=o.modules.size,f=o.modules.data,w=u+l.margin*2,b=l.color.light.a?"<path "+s(l.color.light,"fill")+' d="M0 0h'+w+"v"+w+'H0z"/>':"",h="<path "+s(l.color.dark,"stroke")+' d="'+t(f,u,l.margin)+'"/>',d='viewBox="0 0 '+w+" "+w+'"',N='<svg xmlns="http://www.w3.org/2000/svg" '+(l.width?'width="'+l.width+'" height="'+l.width+'" ':"")+d+' shape-rendering="crispEdges">'+b+h+`</svg>
8
- `;return typeof a=="function"&&a(null,N),N},Ve}var It;function Yo(){if(It)return te;It=1;const e=Ao(),s=xo(),r=$o(),t=Jo();function n(o,i,a,l,u){const f=[].slice.call(arguments,1),w=f.length,b=typeof f[w-1]=="function";if(!b&&!e())throw new Error("Callback required as last argument");if(b){if(w<2)throw new Error("Too few arguments provided");w===2?(u=a,a=i,i=l=void 0):w===3&&(i.getContext&&typeof u>"u"?(u=l,l=void 0):(u=l,l=a,a=i,i=void 0))}else{if(w<1)throw new Error("Too few arguments provided");return w===1?(a=i,i=l=void 0):w===2&&!i.getContext&&(l=a,a=i,i=void 0),new Promise(function(h,d){try{const g=s.create(a,l);h(o(g,i,l))}catch(g){d(g)}})}try{const h=s.create(a,l);u(null,o(h,i,l))}catch(h){u(h)}}return te.create=s.create,te.toCanvas=n.bind(null,r.render),te.toDataURL=n.bind(null,r.renderToDataURL),te.toString=n.bind(null,function(o,i,a){return t.render(o,a)}),te}var Qo=Yo();const Go=Io(Qo),Wo={class:"qr-display"},Zo={class:"qr-section"},Xo=["href","onKeydown"],er={key:0,class:"link-text"},tr={__name:"QRCodeDisplay",props:{url:{type:String,required:!0},showLink:{type:Boolean,default:!1}},emits:["copied"],setup(e,{emit:s}){const r=e,t=s,n=F(null),o=x(()=>r.url?r.url.replace(/^https?:\/\//,""):"");function i(){if(!(!r.url||!n.value))try{n.value.getContext("2d").clearRect(0,0,n.value.width,n.value.height),Go.toCanvas(n.value,r.url,{scale:6,margin:0,color:{dark:"#000000",light:"#FFFFFF"}}),n.value.removeAttribute("style")}catch(l){console.error("QR code generation failed:",l)}}async function a(){if(r.url)try{await navigator.clipboard.writeText(r.url),t("copied")}catch(l){console.error("Failed to copy link:",l)}}return He(()=>r.url,()=>{i()},{immediate:!0}),He(n,()=>{n.value&&r.url&&i()},{immediate:!0}),(l,u)=>(T(),R("div",Wo,[v("div",Zo,[v("a",{href:e.url,onClick:de(a,["prevent"]),class:"qr-link",title:"Click to copy link",tabindex:"0",onKeydown:un(de(a,["prevent"]),["enter"])},[v("canvas",{ref_key:"qrCanvas",ref:n,class:"qr-code"},null,512),e.showLink&&e.url?(T(),R("div",er,D(o.value),1)):L("",!0)],40,Xo)])]))}},nr=Y(tr,[["__scopeId","data-v-727427c4"]]),or={class:"device-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"regTitle"},rr={class:"reg-header-row"},sr={id:"regTitle",class:"reg-title"},ir={key:0},ar={key:1},lr={class:"device-link-section"},ur={key:0,class:"expiry-note"},cr={__name:"RegistrationLinkModal",props:{endpoint:{type:String,required:!0},userName:{type:String,default:""}},emits:["close","copied"],setup(e,{emit:s}){const r=e,t=s,n=F(null),o=F(null),i=F(null),a=F(null),l=F(null);async function u(){try{const d=await Q(r.endpoint,{method:"POST"});if(d.url){if(o.value=d.url,i.value=d.expires?new Date(d.expires):null,await ze(),n.value){n.value.showModal();const g=a.value;(g?.querySelector(".btn-primary")||g?.querySelector("button"))?.focus()}}else t("close")}catch{t("close")}}function f(){t("copied")}const w=d=>{const g=z(d)},b=d=>{const g=z(d);g&&(d.preventDefault(),(g==="down"||g==="up")&&a.value?.querySelector("button")?.focus())},h=d=>{const g=z(d);g&&(d.preventDefault(),(g==="up"||g==="down")&&document.querySelector(".qr-link")?.focus())};return qt(()=>{l.value=document.activeElement,u()}),Ft(()=>{const d=l.value;d&&document.body.contains(d)&&!d.disabled&&d.focus()}),(d,g)=>(T(),R("dialog",{ref_key:"dialog",ref:n,onClose:g[2]||(g[2]=N=>d.$emit("close")),onKeydown:w},[v("div",or,[v("div",rr,[v("h2",sr,[g[3]||(g[3]=xe(" 📱 ",-1)),e.userName?(T(),R("span",ir,"Registration for "+D(e.userName),1)):(T(),R("span",ar,"Add Another Device"))]),v("button",{class:"icon-btn",onClick:g[0]||(g[0]=N=>d.$emit("close")),"aria-label":"Close",tabindex:"-1"},"✕")]),v("div",lr,[g[4]||(g[4]=v("p",{class:"reg-help"}," Scan this QR code on the new device, or copy the link and open it there. ",-1)),cn(nr,{url:o.value,"show-link":!0,onCopied:f,onKeydown:b},null,8,["url"]),i.value?(T(),R("p",ur," This link expires "+D(U(G)(i.value).toLowerCase())+". ",1)):L("",!0)]),v("div",{class:"reg-actions",ref_key:"actionsRow",ref:a,onKeydown:h},[v("button",{class:"btn-secondary",onClick:g[1]||(g[1]=N=>d.$emit("close"))},"Close")],544)])],544))}},Ar=Y(cr,[["__scopeId","data-v-e04dd463"]]),dr={class:"loading-container"},fr={__name:"LoadingView",props:{message:{type:String,default:"Loading..."}},setup(e){return(s,r)=>(T(),R("div",dr,[r[0]||(r[0]=v("div",{class:"loading-spinner"},null,-1)),v("p",null,D(e.message),1)]))}},Rr=Y(fr,[["__scopeId","data-v-130f5abf"]]),hr={class:"message-container"},gr={class:"message-content"},mr={key:0,class:"error-detail"},yr={class:"button-row"},pr={__name:"AccessDenied",props:{title:{type:String,default:"Access Denied"},icon:{type:String,default:"🔒"},message:{type:String,default:null}},setup(e){function s(){window.location.reload()}return(r,t)=>(T(),R("div",hr,[v("div",gr,[v("h2",null,D(e.icon)+" "+D(e.title),1),e.message?(T(),R("p",mr,D(e.message),1)):L("",!0),v("div",yr,[v("button",{class:"btn-secondary",onClick:t[0]||(t[0]=(...n)=>U(We)&&U(We)(...n))},"Back"),v("button",{class:"btn-primary",onClick:s},"Reload Page")])])]))}},Tr=Y(pr,[["__scopeId","data-v-a7b258e7"]]);export{Tr as A,Sr as B,Rr as L,kr as M,Br as N,Ar as R,_r as U,Er as _,Ir as a,Cr as b,vr as c,$e as u};
@@ -1 +0,0 @@
1
- :root{--font-sans: "Inter", "Inter var", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", sans-serif;--font-mono: "DM Mono", "JetBrains Mono", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", monospace;--color-canvas: #ffffff;--color-surface: #eff6ff;--color-surface-subtle: #dbeafe;--color-border: #2563eb;--color-border-strong: #1e40af;--color-heading: #1e3a8a;--color-text: #1e293b;--color-text-muted: #475569;--color-link: #1d4ed8;--color-link-hover: #1e40af;--color-accent: #2563eb;--color-accent-strong: #1e40af;--color-accent-contrast: #ffffff;--color-success-text: #166534;--color-success-bg: #dcfce7;--color-error-text: #b91c1c;--color-error-bg: #fee2e2;--color-info-text: #1e40af;--color-info-bg: #dbeafe;--color-danger: #dc2626;--shadow-soft: 0 10px 30px rgba(30, 64, 175, .15);--radius-none: 0;--radius-sm: 4px;--radius-md: 6px;--radius-lg: 10px;--space-xxs: .25rem;--space-xs: .5rem;--space-sm: .75rem;--space-md: 1rem;--space-lg: 1.5rem;--space-xl: 2.25rem;--space-xxl: 3.5rem;--layout-padding: clamp(1.5rem, 3vw + 1rem, 3.25rem);--transition-base: .16s ease;--focus-ring: 0 0 0 2px var(--color-accent)}@media(prefers-color-scheme:dark){:root{--color-canvas: #0f172a;--color-surface: #141b2f;--color-surface-subtle: #1b243b;--color-border: #25304a;--color-border-strong: #3d4d6b;--color-heading: #fff;--color-text: #e2e8f0;--color-text-muted: #94a3b8;--color-link: #60a5fa;--color-link-hover: #93c5fd;--color-accent: #60a5fa;--color-accent-strong: #3b82f6;--color-accent-contrast: #0b1120;--color-success-text: #34d399;--color-success-bg: #1a4d2e;--color-error-text: #fca5a5;--color-error-bg: #4a1f1f;--color-info-text: #bae6fd;--color-info-bg: #1e3a5f;--color-danger: #f87171;--shadow-soft: 0 0 0 #000000}}*,*:before,*:after{box-sizing:border-box}html{overflow:clip;height:100%;background:var(--color-canvas)}body{color-scheme:light dark;overflow:auto;scrollbar-gutter:stable;height:100%;margin:0;font-family:var(--font-sans);background:none;color:var(--color-text);line-height:1.55;-webkit-font-smoothing:antialiased;text-align:justify;hyphens:auto;-webkit-hyphens:auto;-moz-hyphens:auto}body,#app,#admin-app{display:flex;flex-direction:column;min-height:100vh}#app,#admin-app{flex:1}a,a:visited{color:var(--color-link);text-decoration:none}a:hover,a:focus-visible{color:var(--color-link-hover)}.app-shell{flex:1;display:flex;flex-direction:column;min-height:100vh}.app-main{flex:1;display:flex;flex-direction:column}.view-root{flex:1;width:100%;display:flex;flex-direction:column;gap:2rem;padding:var(--layout-padding);box-sizing:border-box;margin:0 auto}.view-root--wide{width:min(100%,1200px)}.view-root--narrow{max-width:540px}.view-header{display:flex;flex-direction:column;gap:.75rem}.view-header h1{margin:0;font-weight:600;color:var(--color-heading)}.view-lede{margin:0;color:var(--color-text-muted);font-size:1rem}.section-block{display:flex;flex-direction:column;gap:1rem}.section-block h2{margin:0;font-size:clamp(1.25rem,1.5vw + 1rem,1.65rem);font-weight:600;color:var(--color-heading)}.section-body{display:flex;flex-direction:column;gap:1rem}.section-description{margin:0;color:var(--color-text-muted)}.button-row{display:flex;flex-wrap:nowrap;gap:.75rem;justify-content:flex-start}.button-row button{min-width:0}.surface{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-md);padding:var(--space-lg);box-shadow:var(--shadow-soft)}.surface--tight{padding:var(--space-md)}button{font-family:inherit;font-size:1rem;font-weight:500;border-radius:var(--radius-sm);border:1px solid transparent;padding:.65rem 1.1rem;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:.4rem;background:var(--color-surface);color:var(--color-text)}button:disabled{cursor:not-allowed;filter:opacity(.6)}.btn-primary{background:var(--color-accent);color:var(--color-accent-contrast);border-color:var(--color-accent);box-shadow:var(--shadow-soft)}.btn-primary:hover:not(:disabled){background:var(--color-accent-strong);border-color:var(--color-accent-strong)}.btn-secondary{background:transparent;color:var(--color-text);border-color:var(--color-border)}.btn-secondary:hover:not(:disabled){border-color:var(--color-border-strong);background:var(--color-surface-subtle)}.btn-danger{background:var(--color-danger);color:var(--color-accent-contrast);border-color:transparent}.btn-danger:hover:not(:disabled){filter:brightness(.92)}.btn-primary:focus-visible,.btn-secondary:focus-visible,.btn-danger:focus-visible{outline:1px solid var(-webkit-focus-ring-color)}input[type=text],input[type=search],input[type=email],textarea,select{font:inherit;width:100%;padding:.65rem .75rem;border-radius:var(--radius-sm);border:1px solid var(--color-border);background:var(--color-surface);color:var(--color-text);transition:border-color var(--transition-base),box-shadow var(--transition-base)}label{display:flex;flex-direction:column;gap:.5rem;color:var(--color-text)}p{margin:0;color:var(--color-text)}small{color:var(--color-text-muted)}.table-wrapper{overflow-x:auto;background:var(--color-surface);border:1px solid var(--color-border)}table{width:100%;border-collapse:collapse;font-size:.95rem}thead tr{background:var(--color-surface-subtle);color:var(--color-text-muted)}td,th{padding:.65rem .75rem;border-bottom:1px solid var(--color-border);text-align:left}.center{text-align:center}.badge{display:inline-flex;align-items:center;gap:.35rem;padding:.2rem .6rem;border-radius:var(--radius-sm);background:var(--color-surface-subtle);border:1px solid var(--color-border);color:var(--color-text-muted);font-size:.75rem}.global-status{position:fixed;top:1.5rem;left:0;right:0;margin:0 auto;z-index:1200;width:fit-content;min-width:min(520px,calc(100% - 2rem));max-width:calc(100% - 2rem);display:none}.global-status .status{display:flex;align-items:center;justify-content:center;padding:.85rem 1.25rem;border-radius:var(--radius-sm);border-width:1px;border-style:solid;background:var(--color-surface);box-shadow:var(--shadow-soft);font-weight:550}.status.info{border-color:#3b82f6;color:var(--color-info-text);background:var(--color-info-bg)}.status.success{border-color:#16a34a;color:var(--color-success-text);background:var(--color-success-bg)}.status.error{border-color:#dc2626;color:var(--color-error-text);background:var(--color-error-bg)}.dialog-overlay{position:fixed;inset:0;background:transparent;z-index:1100;display:flex;align-items:center;justify-content:center;padding:1.5rem}.device-dialog,.modal{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-md);width:min(520px,100%);max-height:calc(100vh - 3rem);overflow-y:auto;padding:1.75rem;box-shadow:var(--shadow-soft);color:var(--color-text)}.qr-container{display:flex;flex-direction:column;align-items:center;gap:.75rem;text-align:center;color:var(--color-text-muted)}.qr-code{padding:1rem;background:#fff;box-shadow:var(--shadow-soft)}.link-container,.token-display,.token-info{background:var(--color-surface-subtle);border:1px solid var(--color-border);border-radius:var(--radius-sm);padding:.75rem;color:var(--color-text)}:root{--card-width: 16rem}.record-list,.credential-list,.session-list{width:100%;display:grid;grid-auto-flow:row;grid-template-columns:repeat(auto-fill,minmax(var(--card-width),1fr));justify-content:start;gap:.5rem;align-items:stretch;margin:0 auto;outline:none}@media(max-width:720px){.record-list{display:flex;flex-direction:column;max-width:100%}}.record-item,.credential-item,.session-item{display:flex;flex-direction:column;padding:.5rem;border-radius:var(--radius-md);background:var(--color-surface);height:100%;transition:border-color .2s ease,box-shadow .2s ease,transform .2s ease;position:relative;cursor:pointer}.record-item:hover,.credential-item:hover,.session-item:hover{border-color:var(--color-border-strong);box-shadow:0 10px 24px #0f172a1f;transform:translateY(-1px)}.record-item.is-current,.credential-item.current-session,.credential-item.is-hovered,.session-item.is-current,.session-item.is-hovered,.credential-item.is-linked-session,.session-item.is-linked-credential{border-color:var(--color-accent);background-color:var(--color-surface-subtle)}.credential-item:focus,.session-item:focus{outline:1px solid var(-webkit-focus-ring-color)}.item-top{display:flex;align-items:center;height:2.5rem}.item-icon{width:40px;height:40px;display:grid;place-items:center;flex-shrink:0}.auth-icon{border-radius:var(--radius-sm)}.icon{flex:0 0 auto;font-size:1.5em;width:40px}.item-title{flex:1;margin:0;font-size:1rem;font-weight:600;color:var(--color-heading);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.item-actions{flex-shrink:0;display:flex;align-items:center}.item-actions .badge+.btn-card-delete{margin-left:.25rem}.item-actions .badge+.badge{margin-left:.25rem}.item-details{margin-left:40px}.credential-dates,.session-dates{display:grid;grid-auto-flow:row;grid-template-columns:8em 1fr;font-size:.75rem;align-items:center}.date-label{font-weight:500;color:var(--color-text-muted);overflow:hidden;text-overflow:ellipsis}.date-value{color:var(--color-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.btn-card-delete{background:transparent;border:none;color:var(--color-danger);padding:.35rem .5rem;font-size:1.05rem;line-height:1;border-radius:var(--radius-sm);cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.btn-card-delete:hover:not(:disabled){background:#fee}.btn-card-delete:disabled{filter:opacity(.4);cursor:not-allowed}.session-emoji{font-size:1.2rem}.session-group{position:relative}.session-group:focus-visible{outline:1px solid var(-webkit-focus-ring-color)}.session-group-host{display:flex;align-items:center;font-size:1.5rem;font-weight:600;margin:.5rem 0}.session-group-icon{margin-left:-1.5rem}.session-group-host a{color:var(--color-text);text-decoration:none}.session-group:focus-visible .session-group-host,.session-group:focus-visible .session-group-host a{color:var(--color-heading)}.btn-card-delete{display:none}.session-item:focus .btn-card-delete{display:block}.badge{padding:.2rem .5rem;border-radius:var(--radius-sm);font-size:.8rem;font-weight:500;white-space:nowrap}.badge-current{background:var(--color-accent);color:var(--color-accent-contrast);box-shadow:0 0 0 1px var(--color-accent) inset}.badge:not(.badge-current){background:var(--color-surface-subtle);color:var(--color-text-muted);border:1px solid var(--color-border)}.session-meta-info{font-size:.75rem;color:var(--color-text-muted);font-family:monospace}.empty-state{text-align:center;padding:var(--space-lg);color:var(--color-text-muted)}.empty-state p{margin:0}.user-info{display:grid;border-radius:var(--radius-md);background:var(--color-surface);padding:1.1rem 1.25rem}.user-details{display:grid;grid-template-columns:7em 1fr;gap:0 .5rem;padding-left:40px;font-size:.75rem}.toggle-link{color:var(--color-link);cursor:pointer}.toggle-link:hover{color:var(--color-link-hover)}.token-info code{font-family:var(--font-mono)}@media(max-width:720px){.view-root{padding:clamp(1rem,3vw + .75rem,2rem);gap:1.75rem}.global-status{top:1rem}}.dialog-backdrop{position:fixed;top:0;left:0;width:100vw;height:100vh;background:transparent;backdrop-filter:blur(.1rem) brightness(.7);-webkit-backdrop-filter:blur(.1rem) brightness(.7);display:flex;align-items:center;justify-content:center;z-index:1000}.dialog-container{max-width:90vw;max-height:90vh;overflow-y:auto}.dialog-content{flex:none;width:100%;max-width:480px;padding:2rem;background:var(--color-surface);border-radius:var(--radius-lg);box-shadow:0 20px 60px #1e293b;border:1px solid var(--color-border)}.dialog-content--wide{max-width:540px}.dialog-content--narrow{max-width:420px}@media(max-width:720px){.dialog-content{padding:1.5rem}}body:before{content:"";position:fixed;inset:0;z-index:1099;background:transparent;backdrop-filter:blur(0) brightness(1);-webkit-backdrop-filter:blur(0) brightness(1);pointer-events:none;visibility:hidden;transition:all .2s ease-out}body.has-backdrop:before{-webkit-backdrop-filter:blur(.2rem) brightness(.5);backdrop-filter:blur(.2rem) brightness(.5);visibility:visible}body.has-backdrop{overflow:auto}#auth-iframe{border:none;position:fixed;top:0;left:0;width:100%;height:100%;z-index:9999;color-scheme:auto;background:transparent}.slot-machine{padding:.875rem 1rem;background:var(--color-surface-hover, rgba(0, 0, 0, .03));border:1px solid var(--color-border);border-radius:var(--radius-sm);font-family:SF Mono,Monaco,Cascadia Code,Roboto Mono,Consolas,Courier New,monospace;display:flex;align-items:center;-webkit-user-select:none;user-select:none;pointer-events:none;white-space:nowrap;overflow:hidden}.slot-reel{display:inline-flex;align-items:center;justify-content:center;flex:1;min-width:0;height:1.8em;position:relative}