staffa 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -293,6 +293,7 @@ Search params and the `#hash` belong to the current panel only. Anything another
293
293
 
294
294
  - `columns: "single"` shows only the current panel, however wide the screen — the phone experience at every size. Only the display changes: the URL, the back button, unsaved panels and the panels' own close buttons all behave the same.
295
295
  - `linkNavigation` sets what a link *without* a `data-panel` attribute does: `"push"` (the default), `"replace"`, or `"open"`. With `"open"` every click replaces the content as a whole — which, with flat routes, is the conventional sidebar-and-content app: one pane, swapped on every click, the crumb line simply naming it.
296
+ - Both are live: pass a proxied options object (or make the field a getter) and a change is adopted in place, every open panel keeping its state.
296
297
  - Only one routed `S.main()` can be mounted at a time; a second one throws — the URL is global, so two of them would fight over it. Nothing else is global: the stack belongs to its shell, and each handler gets its own `$panel`, since several panels are alive at once.
297
298
  - Navigating with `aberdeen/route`'s own `go()` works — an unsaved panel survives it too — but, like a link from outside a panel, it builds the whole stack from the path. So prefer the stack's own methods. A navigation guard your app registered with `route.setGuard` (an auth redirect, say) keeps working untouched: Staffa registers none of its own.
298
299
  - Deep links need your static server to serve the app for unknown paths (the usual SPA fallback). For `http-server` that's `-P`, as in the demo command below.
@@ -349,7 +350,7 @@ Components share naming conventions for options: `attrs` (outermost element), `c
349
350
 
350
351
  ### Layout & containers
351
352
 
352
- - **`S.main(opts)`**: app shell, a sticky header with `logo`, `title`, `subtitle`, `menu` — plus, in routed mode, the breadcrumbs of the open panels; scrollable content area; footer. Set `maxWidth` to center the content. Give it a `nav` for a sidebar that collapses to a hamburger below 640 px — where the nav becomes a full page sliding in from the left, handing over to the chosen screen with a matching slide in from the right. Its `items` may be a reactive array; adding or removing one redraws just the sidebar, never the content beside it. An item with `items` of its own becomes a collapsible submenu: only the branch holding the current page stays unfolded, and clicking a branch selects its first leaf (expanding a branch doesn't dismiss the phone's full-page nav — only picking a leaf does). A sidebar taller than the window scrolls, and follows the highlighted item: navigating to a page whose item sits past the fold scrolls it back into view. A navigation dismisses the collapsed nav by itself, links in your own custom rows included; `S.closeNav()` does it for the rows that *don't* navigate. Instead of a single `content` slot it can take a `routes` table — see [Panel-stack navigation](#panel-stack-navigation).
353
+ - **`S.main(opts)`**: app shell, a sticky header with `logo`, `title`, `subtitle`, `menu` — plus, in routed mode, the breadcrumbs of the open panels; scrollable content area; footer. Set `maxWidth` to center the content. Give it a `nav` for a sidebar that collapses to a hamburger below 640 px — where the nav becomes a full page sliding in from the left, handing over to the chosen screen with a matching slide in from the right. Its `items` may be a reactive array; adding or removing one redraws just the sidebar, never the content beside it. An item with `items` of its own becomes a collapsible submenu: only the branch holding the current page stays unfolded, and clicking a branch selects its first leaf (expanding a branch doesn't dismiss the phone's full-page nav — only picking a leaf does). A page the menu holds nowhere leaves every fold as it was. An item can also `match` pages beyond its own `href` — a path prefix, or a `(path) => boolean` — claiming the detail screens that have no row of their own: it is then highlighted, and the branches above it stay unfolded, cold deep links included. A sidebar taller than the window scrolls, and follows the highlighted item: navigating to a page whose item sits past the fold scrolls it back into view. A navigation dismisses the collapsed nav by itself, links in your own custom rows included; `S.closeNav()` does it for the rows that *don't* navigate. Instead of a single `content` slot it can take a `routes` table — see [Panel-stack navigation](#panel-stack-navigation).
353
354
  - **`S.box(opts | content)`**: surface with optional `header`/`footer` and padded body. Pass a function for shorthand `{ content }`. `close: fn` adds a ✕ that runs your dismissal — in the header row, or floating over the body when there is no header. (It is plain furniture: a routed screen gets its own way out from the shell, see [Panel-declared chrome](#chrome).)
354
355
  - **`S.tabs(opts)`**: tablist with live tab panels and keyboard navigation. More tabs than fit make the strip scroll (see `S.scrollStrip`); selecting a tab any other way (the arrow keys, a `bind` written from elsewhere) scrolls it into view.
355
356
  - **`S.scrollStrip(opts)`**: a horizontal row that scrolls once its content outgrows it, with a ‹ / › button appearing over whichever end still has something to reach — so it isn't just a swipe target. Its own scrollbar is hidden. `S.tabs` and the routed shell's breadcrumbs are built on it; reach for it for any row of chrome that can outgrow its space. `S.revealInStrip(el)` scrolls one of its children into view.
@@ -183,6 +183,10 @@ export interface MainOptions<R = Routes> {
183
183
  * — the phone experience at every size (the nav sidebar still sits beside
184
184
  * it). Only the display differs: the stack, the breadcrumbs, the URL,
185
185
  * Escape and the back button behave identically in both. Routed mode only.
186
+ *
187
+ * Live: pass a proxied options object (or make this field a getter) and a
188
+ * change is adopted in place — one layout pass, every panel keeping its
189
+ * state.
186
190
  */
187
191
  columns?: "auto" | "single";
188
192
  /**
@@ -193,6 +197,9 @@ export interface MainOptions<R = Routes> {
193
197
  * every click replaces the content as a whole — which, with flat routes,
194
198
  * is the conventional sidebar-and-content app: one pane, swapped on every
195
199
  * click, the crumb line simply naming it. Routed mode only.
200
+ *
201
+ * Live, like {@link MainOptions.columns}: change it and the next click
202
+ * uses the new default.
196
203
  */
197
204
  linkNavigation?: "push" | "replace" | "open";
198
205
  /** Footer content, pinned below the scroll area. */
@@ -1,7 +1,7 @@
1
1
  import A from "aberdeen";
2
- import { current as currentRoute, matchCurrent } from "aberdeen/route";
2
+ import { current as currentRoute } from "aberdeen/route";
3
3
  import { drawSlot, focusFirst, NARROW_PX } from "../core.js";
4
- import { drawMenu, isFloatingMenuOpen, consumeBranchNav } from "./menu.js";
4
+ import { drawMenu, isFloatingMenuOpen, consumeBranchNav, anyCurrent } from "./menu.js";
5
5
  // The shell's own chrome glyphs, from the same Lucide set an app draws with —
6
6
  // so a nav trigger sits beside app icons as an equal. Named imports, so a
7
7
  // bundler keeps these two and tree-shakes the other ~1950 away.
@@ -124,10 +124,12 @@ A.insertGlobalCss({
124
124
  // body starts below the bar), but the bar should still win if they ever do.
125
125
  "position:absolute inset:0 z-index:5 display:flex flex-direction:column " +
126
126
  "overflow-y:auto overscroll-behavior:contain border:0 r:0 padding:$2 gap:$1 " +
127
- "transition: transform var(--s-panel-ms) ease;",
127
+ "transition: transform var(--s-panel-ms) ease, visibility var(--s-panel-ms);",
128
128
  // Parked one screen to the left: the state the `create=`/`destroy=` hooks
129
- // transition out of and back into.
130
- "&.s-nav-page-off": "transform:translateX(-100%) pointer-events:none",
129
+ // transition out of and back into. `visibility` flips at the slide's end
130
+ // (see `.s-menu-list` in menu.ts): the dismissed page lingers off screen
131
+ // until Aberdeen's removal timer, and mustn't stay reachable meanwhile.
132
+ "&.s-nav-page-off": "transform:translateX(-100%) pointer-events:none visibility:hidden",
131
133
  // Roomier rows than the dropdown's: this is the whole screen, and every row
132
134
  // is a thumb target.
133
135
  ".s-menu-item": "padding: $2 $3; min-height:3rem font-size:1.05em gap:$3",
@@ -184,12 +186,19 @@ export function main(opts = {}) {
184
186
  routes,
185
187
  notFound: opts.notFound,
186
188
  ancestors: opts.ancestors,
187
- columns: opts.columns,
188
- linkNavigation: opts.linkNavigation,
189
189
  title: opts.title,
190
190
  $shell,
191
191
  })
192
192
  : null;
193
+ if (ctl) {
194
+ // `columns` and `linkNavigation` are live: each is read in a scope of
195
+ // its own, so when the options object is a proxy (or the field a
196
+ // getter), a change re-runs just that scope — the columns relayout in
197
+ // place with every panel's state intact, and the next click picks up
198
+ // the new link default. Nothing else of the shell is touched.
199
+ A(() => ctl.setColumns(opts.columns));
200
+ A(() => ctl.setLinkNavigation(opts.linkNavigation));
201
+ }
193
202
  // Where the brand mark and the app's name link — or nowhere, when the app
194
203
  // said `home: null` (a title slot holding a control of its own, say).
195
204
  const homeHref = ctl && opts.home !== null ? opts.home ?? "/" : null;
@@ -443,24 +452,20 @@ function drawSecondLine(opts, ctl, nav, $shell) {
443
452
  }
444
453
  /**
445
454
  * Whether the stack would only be saying what the sidebar already says: a
446
- * single panel open, the sidebar on screen, and that panel being one of the nav's
447
- * own rows.
455
+ * single panel open, the sidebar on screen, and that panel being one of the
456
+ * nav's own rows — a leaf inside a submenu counts, since the sidebar shows it
457
+ * highlighted (inside its unfolded branch) all the same.
448
458
  *
449
- * The row test is {@link matchCurrent} — the very thing that marks a row
450
- * `aria-current=page` — so "the crumb is redundant" and "the sidebar has it
451
- * highlighted" can never come apart. It compares whole paths, so it is true
452
- * only for a nav item's own screen, never for one opened beneath it.
459
+ * The row test is the menu's own {@link anyCurrent} — the very thing that
460
+ * marks a row `aria-current=page` — so "the crumb is redundant" and "the
461
+ * sidebar has it highlighted" can never come apart.
453
462
  */
454
463
  function taglineFits(ctl, nav, $shell) {
455
464
  if ($shell.narrow || nav == null)
456
465
  return false;
457
466
  if (ctl.panels.length > 1)
458
467
  return false;
459
- return nav.items.some((entry) => typeof entry !== "string" &&
460
- typeof entry !== "function" &&
461
- !("separator" in entry) &&
462
- entry.href != null &&
463
- matchCurrent(entry.href));
468
+ return anyCurrent(nav.items);
464
469
  }
465
470
  /**
466
471
  * Track whether the shell is narrow, for everything that has to agree about it.
@@ -26,6 +26,17 @@ export interface MenuItem {
26
26
  * `attrs: "data-panel=push"` for a row that should stack instead.
27
27
  */
28
28
  href?: string;
29
+ /**
30
+ * Pages this item claims *beyond* its own `href`: a string claims that path
31
+ * and everything under it (`"/mail"` claims `/mail/…`, not `/mailbox`), a
32
+ * function is asked with the current path. While a claimed page is current,
33
+ * the item is highlighted and the branches above it stay unfolded — for the
34
+ * detail screens a menu has no row of their own: the `/thread/[id]` a
35
+ * notification lands on, an icon's page under the gallery's row. Claims
36
+ * work from the very first paint, so they also cover cold deep links,
37
+ * which no amount of fold-state keeping can.
38
+ */
39
+ match?: string | ((path: string) => boolean);
29
40
  /** `target` for the link (`_blank`, etc.). Only meaningful with `href`. */
30
41
  target?: string;
31
42
  /** Disables the item. */
@@ -137,6 +148,13 @@ export type ContextMenuOptions = Omit<FloatingMenuOptions, "anchor" | "at" | "cl
137
148
  * not a selection, so it doesn't run this.
138
149
  */
139
150
  export declare function drawMenu(items: MenuEntry[], onLeafSelect?: () => void): void;
151
+ /**
152
+ * Whether any item anywhere in `items` — branches, their leaves, `match`
153
+ * claims — is the current page. The one question both the fold logic and the
154
+ * shell's tagline rule (see `taglineFits` in main.ts) ask of a menu, exported
155
+ * so the two can never disagree with the highlighting.
156
+ */
157
+ export declare function anyCurrent(items: MenuEntry[]): boolean;
140
158
  /**
141
159
  * Whether the navigation that just landed on `path` was a branch row expanding
142
160
  * (consuming the note it left). Internal — used by the floating menu below and
@@ -9,11 +9,16 @@ import { button } from "./button.js";
9
9
  A.insertGlobalCss({
10
10
  // Border comes from the `.s-s.neutral` surface; the panel only overrides the radius
11
11
  // (lg) and opts into elevation via `.shadow` (added on the element below).
12
+ // `visibility` rides the same transition as the fade (flipping only at its
13
+ // end, per CSS visibility interpolation): a dismissed menu lingers in the
14
+ // DOM for a while — Aberdeen's `destroy=` removes it on a timer, not at
15
+ // the transition's end — and without this it would spend that time
16
+ // invisible yet still hittable by tests and read by assistive tech.
12
17
  ".s-menu-list": "position:fixed z-index:350 min-width:10rem display:flex flex-direction:column p:$1 " +
13
18
  "r:$s-radius-lg " +
14
19
  "overflow-y:auto max-height:min(80vh,28rem) " +
15
- "transition: opacity 0.15s, transform 0.15s;",
16
- ".s-menu-list.hidden": "opacity:0 pointer-events:none transform:translateY(-6px)",
20
+ "transition: opacity 0.15s, transform 0.15s, visibility 0.15s;",
21
+ ".s-menu-list.hidden": "opacity:0 pointer-events:none transform:translateY(-6px) visibility:hidden",
17
22
  // One class for both the `<a>` (link) and `<button>` forms — they look
18
23
  // identical; the element only differs where link semantics matter (see below).
19
24
  // The scroll-margin keeps a revealed row (see the scrollIntoView in
@@ -158,7 +163,7 @@ function drawLeaf(entry, onLeafSelect) {
158
163
  A(() => {
159
164
  const first = !drawn;
160
165
  drawn = true;
161
- if (!matchCurrent(entry.href))
166
+ if (!isCurrent(entry))
162
167
  return;
163
168
  A("aria-current=page");
164
169
  // A list taller than its scrollport (a long sidebar nav, mostly)
@@ -187,6 +192,18 @@ function drawLeaf(entry, onLeafSelect) {
187
192
  drawSlot(entry.label);
188
193
  });
189
194
  }
195
+ /**
196
+ * The last route-derived fold state of every linked branch, keyed by the
197
+ * branch's selection href. Module-level on purpose: the phone's full-page nav
198
+ * (and any dropdown) mounts a fresh menu every time it opens, and per-mount
199
+ * state would hand it three folded sections in the middle of the user's work.
200
+ * Bounded by the number of distinct branch hrefs an app ever shows.
201
+ */
202
+ const foldMemory = new Map();
203
+ function setFold(href, open) {
204
+ foldMemory.set(href, open);
205
+ return open;
206
+ }
190
207
  /**
191
208
  * A branch: a native `<details>` folding a sub-list of entries in and out. The
192
209
  * children stay mounted whether folded or not — closing hides them, it doesn't
@@ -207,14 +224,19 @@ function drawBranch(entry, onLeafSelect, $menuHasCurrent) {
207
224
  // nowhere in the menu, nothing has an opinion, and the fold simply keeps
208
225
  // its last state — folding everything up would answer a question nobody
209
226
  // asked with a menu that forgot where the user was.
210
- let last = false;
227
+ //
228
+ // "Last state" lives in `foldMemory`, not in this closure: menus remount —
229
+ // the phone's full-page nav exists only while it is open — and a remount
230
+ // must find the state where the previous mount left it. It is keyed on the
231
+ // branch's selection href, so the sidebar and the phone nav (two renderings
232
+ // of the same items) share one truth, however often either is rebuilt.
211
233
  const $open = href != null
212
234
  ? A.derive(() => {
213
235
  if (containsCurrent(entry))
214
- return (last = true);
236
+ return setFold(href, true);
215
237
  if ($menuHasCurrent == null || $menuHasCurrent.value)
216
- return (last = false);
217
- return last;
238
+ return setFold(href, false);
239
+ return foldMemory.get(href) ?? false;
218
240
  })
219
241
  : null;
220
242
  A("details.s-menu-details", () => {
@@ -227,9 +249,10 @@ function drawBranch(entry, onLeafSelect, $menuHasCurrent) {
227
249
  if (entry.disabled)
228
250
  A("aria-disabled=true");
229
251
  A(() => {
230
- // Current only on its *own* page: when a descendant is current, that
252
+ // Current only on its *own* page (its `href`, or a `match` claim
253
+ // pages with no row of their own): when a descendant is current, that
231
254
  // row carries the highlight, and two highlights would read as two pages.
232
- if (entry.href != null && matchCurrent(entry.href))
255
+ if (isCurrent(entry))
233
256
  A("aria-current=page");
234
257
  });
235
258
  A("click=", (e) => {
@@ -266,14 +289,36 @@ function foldedAway(el) {
266
289
  }
267
290
  return false;
268
291
  }
269
- /** Whether any page linked anywhere in `items` is the current one. */
270
- function anyCurrent(items) {
292
+ /**
293
+ * Whether any item anywhere in `items` — branches, their leaves, `match`
294
+ * claims — is the current page. The one question both the fold logic and the
295
+ * shell's tagline rule (see `taglineFits` in main.ts) ask of a menu, exported
296
+ * so the two can never disagree with the highlighting.
297
+ */
298
+ export function anyCurrent(items) {
271
299
  return items.some((entry) => typeof entry !== "string" && typeof entry !== "function" && !("separator" in entry) && containsCurrent(entry));
272
300
  }
273
- /** Whether `entry`'s own page, or any page linked below it, is the current one. */
274
- function containsCurrent(entry) {
301
+ /**
302
+ * Whether this item is the current page: its own `href` matches, or its
303
+ * `match` claims the current path. The single test behind `aria-current`,
304
+ * branch unfolding, and {@link anyCurrent} — one truth, three consumers.
305
+ */
306
+ function isCurrent(entry) {
275
307
  if (entry.href != null && matchCurrent(entry.href))
276
308
  return true;
309
+ const m = entry.match;
310
+ if (m == null)
311
+ return false;
312
+ const path = currentRoute.path;
313
+ if (typeof m === "function")
314
+ return m(path);
315
+ const claim = m.replace(/\/+$/, "") || "/";
316
+ return path === claim || path.startsWith(claim === "/" ? "/" : claim + "/");
317
+ }
318
+ /** Whether `entry` is the current page itself, or holds it anywhere below. */
319
+ function containsCurrent(entry) {
320
+ if (isCurrent(entry))
321
+ return true;
277
322
  for (const child of entry.items ?? []) {
278
323
  if (typeof child === "string" || typeof child === "function" || "separator" in child)
279
324
  continue;
@@ -617,6 +617,10 @@ export declare class PanelStackController implements PanelStack {
617
617
  replacePanel(path: string): Promise<boolean>;
618
618
  openPanelStack(path: string, beneath?: readonly string[]): Promise<boolean>;
619
619
  closePanel(path?: string): Promise<boolean>;
620
+ /** Adopt a changed `columns` setting: one layout pass, nothing redrawn. */
621
+ setColumns(columns: "auto" | "single" | undefined): void;
622
+ /** Adopt a changed `linkNavigation` default; the next click reads it. */
623
+ setLinkNavigation(mode: "push" | "replace" | "open" | undefined): void;
620
624
  /**
621
625
  * The breadcrumb stack, drawn by `main()` into the top bar: every open
622
626
  * panel, oldest first, the ones on screen right now in bold, pinned ones
@@ -1001,6 +1001,23 @@ export class PanelStackController {
1001
1001
  return this.closePath(path ?? arr.stack[arr.focus] ?? "");
1002
1002
  });
1003
1003
  }
1004
+ // ── Live settings ──────────────────────────────────────────────────────
1005
+ // `main()` keeps these fed from small reactive scopes of their own, so an
1006
+ // app that reads them off a proxy (or through a getter) can change them at
1007
+ // runtime and the shell adapts in place — nothing is redrawn, no panel
1008
+ // loses its state. Not {@link PanelStack} API: the app talks to `main()`'s
1009
+ // options; these are how `main()` talks to the stack.
1010
+ /** Adopt a changed `columns` setting: one layout pass, nothing redrawn. */
1011
+ setColumns(columns) {
1012
+ if (this.opts.columns === columns)
1013
+ return;
1014
+ this.opts.columns = columns;
1015
+ this.scheduleLayout();
1016
+ }
1017
+ /** Adopt a changed `linkNavigation` default; the next click reads it. */
1018
+ setLinkNavigation(mode) {
1019
+ this.opts.linkNavigation = mode;
1020
+ }
1004
1021
  /**
1005
1022
  * The breadcrumb stack, drawn by `main()` into the top bar: every open
1006
1023
  * panel, oldest first, the ones on screen right now in bold, pinned ones
@@ -1 +1 @@
1
- import E from"aberdeen";var Y="background: linear-gradient(170deg, color-mix(in oklab, $s-bg, white 9%), color-mix(in oklab, $s-bg, black 9%));",v1="staffa:darkMode",O1=E.proxy({value:a2()});function a2(){try{let t=localStorage.getItem(v1);if(t==="dark")return!0;if(t==="light")return!1}catch{}}function h2(t){O1.value=t;try{t===void 0?localStorage.removeItem(v1):localStorage.setItem(v1,t?"dark":"light")}catch{}}function E1(t=!1){let a=O1.value;return a===void 0&&!t?E.darkMode():a}E(()=>{E1()?E.insertGlobalCss({":root, .s-s.neutral":"--s-bg:#0e0f12 --s-text:#e9eaec",".s-s.neutral":"--s-bg:#191b1f --s-text:#e9eaec",".s-s.neutral .s-s.neutral":"--s-bg:#23262b"}):E.insertGlobalCss({":root, .s-s.neutral":"--s-bg:#eef0f3 --s-text:#1d1f24",".s-s.neutral, .s-s.neutral":"--s-bg:#ffffff --s-text:#1d1f24",".s-s.neutral .s-s.neutral":"--s-bg:#f6f7f9"})});E.setSpacingCssVars(1.1);E.insertGlobalCss({"*, *::before, *::after":"box-sizing:border-box",html:"text-size-adjust:100%",body:"m:0 p:$3 line-height:1.5 font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; -webkit-font-smoothing:antialiased background-color:$s-bg text:$s-text",a:"color: $s-link-fg; text-decoration:underline text-underline-offset:2px; transition: color 0.12s, filter 0.12s;","a:hover":"filter: brightness(1.15)","input, button, textarea, select, optgroup":"font:inherit color:inherit","input:where(:not([type=checkbox],[type=radio],[type=range],[type=file],[type=color],[type=image],[type=submit],[type=button],[type=reset],[type=hidden])), textarea, select":"background:$s-bg border: 1px solid $s-faint; r:$s-radius-sm padding: 0.45em 0.65em; max-width:100%","input:where([type=checkbox],[type=radio])":"width:1.15em height:1.15em cursor:pointer","input[type=range]":"appearance:none background:transparent cursor:pointer vertical-align:middle","input[type=range]::-webkit-slider-runnable-track":"height:4px r:99px background:$s-faint","input[type=range]::-moz-range-track":"height:4px r:99px background:$s-faint","input[type=range]::-moz-range-progress":"height:4px r:99px background:$s-accent","input[type=range]::-webkit-slider-thumb":"appearance:none width:16px height:16px margin-top:-6px r:50% background:$s-accent","input[type=range]::-moz-range-thumb":"width:16px height:16px border:0 r:50% background:$s-accent","input[type=file]":"cursor:pointer",progress:"appearance:none border:0 height:6px r:99px background:$s-faint overflow:hidden vertical-align:middle","progress::-webkit-progress-bar":"background:$s-faint r:99px","progress::-webkit-progress-value":"background:$s-accent r:99px","progress::-moz-progress-bar":"background:$s-accent r:99px",meter:"vertical-align:middle",fieldset:"border: 1px solid $s-faint; r:$s-radius-sm padding:$2 min-width:0",legend:"padding: 0 $1; font-weight:600","code, kbd, samp, pre":"font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;",code:"background: color-mix(in oklab, $s-text, $s-bg 86%); padding: 0.12em 0.34em; r:4px font-size:0.9em",pre:"background: color-mix(in oklab, $s-text, $s-bg 92%); p:$3 r: $s-radius; overflow:auto","pre code":"background:transparent p:0","img, svg, video, canvas":"max-width:100% h:auto",hr:"border:0 border-top: 1px solid $s-faint;","::placeholder":"color: $s-muted; opacity:1",":focus-visible":"outline: 2px solid $s-focus; outline-offset:2px",small:"color:$s-muted font-size:0.9em","@media (prefers-reduced-motion: reduce)":{"*, *::before, *::after":"transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; scroll-behavior: auto !important;"},":root":"--s-primary:#00a884 --s-danger:#dc5b41 --s-success:#00a884 --s-warning:#ef6b00 --s-link:#3f8cd8 --s-radius-sm:6px --s-radius:12px --s-radius-lg:18px --s-focus: color-mix(in srgb, $s-primary 38%, transparent); --s-gradient: linear-gradient(135deg, color-mix(in oklab, $s-primary, white 16%), color-mix(in oklab, $s-primary, black 14%));",":root, .s-s.neutral":"--s-accent:$s-primary --s-link-fg:$s-link",".s-s:not(.neutral)":"--s-bg:$s-primary border:0 --s-text:#eee --s-accent:#fff --s-link-fg:#eef --s-muted: color-mix(in srgb, #fff 70%, transparent); --s-faint: color-mix(in srgb, #fff 30%, transparent);",".s-s.danger":"--s-bg:$s-danger",".s-s.success":"--s-bg:$s-success",".s-s.warning":"--s-bg:$s-warning",".s-s.link":"--s-bg:$s-link",".s-s.primary":"--s-bg:$s-primary",":root, .s-s":"--s-muted: color-mix(in oklab, $s-text, $s-bg 42%); --s-faint: color-mix(in oklab, $s-text, $s-bg 80%); color:$s-text accent-color:$s-accent scrollbar-width:thin scrollbar-color: $s-faint transparent;",".s-s, body":Y,".s-s":"r:$s-radius",":where(.s-s.neutral)":"border: 1px solid $s-faint;",".s-s::-webkit-scrollbar, .s-s ::-webkit-scrollbar":"width:10px height:10px",".s-s::-webkit-scrollbar-track, .s-s ::-webkit-scrollbar-track":"background:transparent",".s-s::-webkit-scrollbar-thumb, .s-s ::-webkit-scrollbar-thumb":"background:$s-faint border-radius:99px border: 2px solid transparent; background-clip:padding-box",".s-s.shadow.neutral:not(.s-btn)":"box-shadow: 0 4px 14px rgba(0,0,0,0.13);",".s-s.extra-shadow.neutral:not(.s-btn)":"box-shadow: 0 18px 50px rgba(0,0,0,0.28);",".s-s.shadow:not(.neutral):not(.tonal):not(.outlined)":"box-shadow: 0 4px 14px color-mix(in srgb, $s-bg 30%, transparent);",".s-s.extra-shadow:not(.neutral):not(.tonal):not(.outlined)":"box-shadow: 0 14px 40px color-mix(in srgb, $s-bg 40%, transparent);",".s-s.no-shadow":"box-shadow: none !important;",".s-s:not(.neutral).tonal, .s-s:not(.neutral).outlined":"--s-text:$s-bg --s-accent:$s-bg --s-link-fg:$s-bg --s-faint: color-mix(in srgb, $s-bg 30%, transparent); --s-muted: color-mix(in srgb, $s-bg 70%, transparent);",".s-s:not(.neutral).tonal":"background: color-mix(in srgb, $s-bg 15%, transparent); border: 1px solid $s-faint;",".s-s:not(.neutral).outlined":"background: transparent; border: 1px solid color-mix(in srgb, $s-bg 45%, transparent);",".s-s:not(.neutral) .s-s.tonal, .s-s:not(.neutral) .s-s.outlined":"--s-text:#fff --s-accent:#fff --s-link-fg:#fff "+Y+" border-color: transparent;"});E.insertGlobalCss({".s-preload, .s-preload *, .s-preload *::before, .s-preload *::after":"transition: none !important; animation: none !important;"});if(typeof document<"u"&&typeof requestAnimationFrame=="function"){let t=document.documentElement;t.classList.add("s-preload"),requestAnimationFrame(()=>requestAnimationFrame(()=>t.classList.remove("s-preload")))}E.insertGlobalCss({":disabled, [aria-disabled=true]":"opacity:0.45 filter:saturate(0.6) user-select:none",":disabled, [aria-disabled=true], :disabled *, [aria-disabled=true] *":"pointer-events:none cursor:not-allowed"});var e2="p, ul, ol, dl, blockquote, pre, table, figure, hr, h1, h2, h3, h4, h5, h6";E.insertGlobalCss({[`${e2}`]:{"&":"margin:0","&:not(:first-child)":"margin-top:$3"},"h1, h2, h3, h4, h5, h6":{"&":"line-height:1.15 font-weight:700 text-wrap:balance","&:not(:first-child)":"margin-top:1.4em"},h1:"font-size:2em font-weight:800 letter-spacing:-0.022em",h2:"font-size:1.55em letter-spacing:-0.018em",h3:"font-size:1.3em letter-spacing:-0.011em",h4:"font-size:1.1em",h5:"font-size:0.95em letter-spacing:0.005em",h6:"font-size:0.8em fg:$s-muted text-transform:uppercase letter-spacing:0.07em","ul, ol":{"&":"padding-left:1.5em","> li:not(:first-child), li > &:not(:first-child)":"margin-top:$1"},blockquote:"border-left: 3px solid $s-faint; padding-left: $3; fg: $s-muted",table:"border-collapse:collapse","th, td":"text-align:left padding: $1 $2; border-bottom: 1px solid $s-faint; vertical-align:top",th:"font-weight:600","thead th":"border-bottom: 2px solid $s-faint;",dt:"font-weight:600",dd:"margin-left: 1.5em",figcaption:"fg:$s-muted font-size:0.9em margin-top:$1 text-align:center"});import M from"aberdeen";import q1 from"aberdeen";var r1=640,p2=0;function B(t="s"){return`${t}-${++p2}`}function x(t,...a){t!=null&&(typeof t=="function"?t(...a):q1("rich=",t))}var r2="a[href], button, input, select, textarea, [tabindex]";function j(t,a){let h=p=>p instanceof HTMLElement&&!p.hasAttribute("disabled")&&p.getAttribute("aria-disabled")!=="true"&&p.tabIndex>=0&&p.getClientRects().length>0,e=(a?[...t.querySelectorAll(a)].find(h):void 0)??[...t.querySelectorAll(r2)].find(h);return e?.focus(),e!=null}function F(t){queueMicrotask(()=>q1(t))}import L from"aberdeen";L.insertGlobalCss({".s-field":{"&":"display:flex flex-direction:column gap:$1","> label":"font-weight:600 font-size:0.9em fg:$s-text user-select:none"},".s-req":"fg:$s-danger margin-left:2px",".s-help":"font-size:0.82em fg:$s-muted",".s-error":"font-size:0.82em fg:$s-danger",".s-input":{"&":"w:100% background: color-mix(in oklab, $s-bg, $s-text 4%); color:$s-text border: 1px solid $s-faint; r:$s-radius padding: 0.55em 0.7em; transition: border-color 0.15s, box-shadow 0.15s;","&:hover:not(:disabled)":"border-color: color-mix(in oklab, $s-text, $s-bg 55%);","&:focus-visible":"border-color:$s-accent box-shadow: 0 0 0 3px $s-focus; outline:none","&[aria-invalid=true]":"border-color:$s-danger"}});function I(t,a){let h=t.id??B("field"),e=()=>!!t.error;L("div.s-field",t.attrs,()=>{L(()=>{t.label!=null&&L("label for=",h,()=>{x(t.label),t.required&&L("span.s-req aria-hidden=true #*")})}),a(h,e),L(()=>{t.help!=null&&!t.error&&L("div.s-help",()=>x(t.help))}),L(()=>{t.error&&L("div.s-error role=alert #",t.error)})})}function _(t,a,h,e){L("id=",a),t.name&&L("name=",t.name),L(()=>{t.disabled&&L("disabled=true")}),L(()=>{t.required&&L("aria-required=true")}),L(()=>L("aria-invalid=",h()?"true":"false")),e&&L("bind=",e)}M.insertGlobalCss({".s-ac":{"&":"position:relative","> .s-control":"display:flex flex-wrap:wrap align-items:center gap:$1 background: color-mix(in oklab, $s-bg, $s-text 4%); color:$s-text border: 1px solid $s-faint; r:$s-radius padding: 0.3em 0.4em; cursor:text; transition: border-color 0.15s, box-shadow 0.15s;","> .s-control:hover":"border-color: color-mix(in oklab, $s-text, $s-bg 55%);","> .s-control:focus-within":"border-color:$s-accent box-shadow: 0 0 0 3px $s-focus;","&[aria-invalid=true] > .s-control":"border-color:$s-danger",".s-chip":"display:inline-flex align-items:center gap:$1 font-size:0.85em background: color-mix(in oklab, $s-bg, $s-text 10%); border: 1px solid $s-faint; r:$s-radius padding: 0.1em 0.2em 0.1em 0.5em;",".s-chip > button":"cursor:pointer border:0 background:transparent fg:$s-muted font-size:1.1em line-height:1 padding: 0 0.2em; r:4px",".s-chip > button:hover":"fg:$s-text background:$s-faint",input:"flex:1 min-width:6ch border:0 background:transparent color:inherit outline:none padding:0.25em","> .s-menu":"position:absolute top:100% left:0 right:0 z-index:20 margin-top:4px max-height:15rem overflow-y:auto list-style:none p:$1 margin-bottom:0","> .s-menu li":"margin:0",".s-option":"padding: 0.45em 0.6em; r:6px cursor:pointer transition: background 0.1s;",".s-option[aria-selected=true]":"background: color-mix(in srgb, $s-text 10%, transparent);",".s-add":"fg:$s-accent font-style:italic",".s-empty":"padding: 0.45em 0.6em; fg:$s-muted"}});function d2(t){return typeof t=="string"?{value:t,label:t}:{value:t.value,label:t.label??t.value}}function o2(t){let a=B("ac-menu"),h=M.proxy({query:"",open:!1,active:0}),e=()=>(typeof t.options=="function"?t.options():t.options).map(d2),p=()=>{let n=t.bind?.value;return n==null||n===""?[]:Array.isArray(n)?n:[n]},r=n=>e().find(m=>m.value===n)?.label??n;if(!t.multi){let n=t.bind?M.peek(t.bind,"value"):void 0;typeof n=="string"&&n&&(h.query=M.peek(()=>r(n)))}let d=()=>{let n=new Set(p()),m=e();t.multi&&(m=m.filter(g=>!n.has(g.value)));let y=h.query.trim().toLowerCase();return y&&(m=m.filter(g=>g.label.toLowerCase().includes(y))),m},o=(n,m)=>{if(t.multi){let y=Array.isArray(t.bind?.value)?[...t.bind.value]:[];y.includes(n)||y.push(n),t.bind&&(t.bind.value=y),h.query=""}else t.bind&&(t.bind.value=n),h.query=r(n),h.open=!1;h.active=0,m?.focus()},c=n=>{if(!t.bind)return;let m=t.bind.value??[];t.bind.value=m.filter(y=>y!==n)};I(t,(n,m)=>{M("div.s-ac",t.inputAttrs,()=>{M(()=>M("aria-invalid=",m()?"true":"false"));let y;M("div.s-control",()=>{M("click=",()=>y?.focus()),M(()=>{if(t.multi)for(let g of p())M("span.s-chip",()=>{M("span #",M.peek(()=>r(g))),M("button type=button aria-label=",`Remove ${g}`,()=>{M("#\xD7"),M("click=",s=>{s.stopPropagation(),c(g),y?.focus()})})})}),y=M("input type=text role=combobox autocomplete=off",()=>{M("id=",n,`aria-controls=${a} aria-autocomplete=list`),t.placeholder!=null&&M("placeholder=",t.placeholder),t.disabled&&M("disabled=true"),t.required&&M("aria-required=true"),M("bind=",M.ref(h,"query")),M(()=>M("aria-expanded=",h.open?"true":"false")),M(()=>{let s=d()[h.active];M("aria-activedescendant=",h.open&&s?`${a}-opt-${h.active}`:"")}),M("input=",()=>{h.open=!0,h.active=0}),M("focus=",()=>{h.open=!0}),M("blur=",()=>{setTimeout(()=>f(),150)}),M("keydown=",g=>i(g,y))})}),M(()=>{if(!h.open)return;let g=d(),s=h.query.trim(),b=t.allowCustom!==!1&&s!==""&&!g.some(C=>C.label.toLowerCase()===s.toLowerCase());M("ul.s-menu.s-s.neutral.shadow role=listbox",`id=${a}`,()=>{g.forEach((C,S)=>{M("li.s-option role=option",`id=${a}-opt-${S}`,()=>{M(()=>M("aria-selected=",h.active===S?"true":"false")),M("#",C.label),M("mousedown=",t2=>t2.preventDefault()),M("click=",()=>o(C.value,y)),M("mousemove=",()=>{h.active=S})})}),b&&M("li.s-option.s-add role=option",()=>{M("#",`Add "${s}"`),M("mousedown=",C=>C.preventDefault()),M("click=",()=>o(s,y))}),g.length===0&&!b&&M("li.s-empty #No matches")})}),M(()=>{if(t.name)if(t.multi)for(let g of p())M("input type=hidden",()=>{M("name=",t.name),M("value=",g)});else M("input type=hidden",()=>{M("name=",t.name),M("value=",p()[0]??"")})})})});function i(n,m){let y=d(),g=y.length-1;if(n.key==="ArrowDown")n.preventDefault(),h.open=!0,h.active=Math.min(g,h.active+1);else if(n.key==="ArrowUp")n.preventDefault(),h.active=Math.max(0,h.active-1);else if(n.key==="Enter"){n.preventDefault();let s=y[h.active];s?o(s.value,m):t.allowCustom!==!1&&h.query.trim()?o(h.query.trim(),m):h.open&&(h.open=!1)}else if(n.key==="Escape")h.open&&(n.preventDefault(),h.open=!1,t.multi||(h.query=r(p()[0]??"")));else if(n.key==="Backspace"&&t.multi&&h.query===""){let s=p();s.length&&c(s[s.length-1])}}function f(){h.open=!1,t.multi?h.query="":t.allowCustom!==!1&&h.query.trim()?o(h.query.trim()):h.query=r(p()[0]??"")}}import N from"aberdeen";import c2 from"aberdeen";var t1={size:24,color:"currentColor",strokeWidth:2,cap:"round",join:"round"};function n2(t,a){let h=a.size??t1.size,e=c2('svg.s-icon aria-hidden=true viewBox="0 0 24 24" fill=none',"width=",h,"height=",h,"stroke=",a.color??t1.color,"stroke-width=",a.strokeWidth??t1.strokeWidth,"stroke-linecap=",a.cap??t1.cap,"stroke-linejoin=",a.join??t1.join,a.attrs);e.innerHTML=t}function z(t){return(a={})=>n2(t,a)}var T1=z('<path d="m9 18 6-6-6-6" />');var D1=z('<circle cx="12" cy="12" r="10" />');var R1=z('<path d="M15 3h6v6" /><path d="M10 14 21 3" /><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />');var Z1=z('<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" /><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />');var d1=z('<path d="M4 5h16" /><path d="M4 12h16" /><path d="M4 19h16" />');var B1=z('<path d="M12 17v5" /><path d="M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89" /><path d="m2 2 20 20" /><path d="M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11" />'),m1=z('<path d="M12 17v5" /><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z" />');var F1=z('<path d="M22 2 2 22" />');var Q=z('<path d="M18 6 6 18" /><path d="m6 6 12 12" />');import P from"aberdeen";P.insertGlobalCss({".s-btn":{"&":"display:inline-flex align-items:center justify-content:center gap:$2 font-weight:450 line-height:1.1 white-space:nowrap cursor:pointer text-decoration:none padding: $m2 $m3; transition: background 0.15s, border-color 0.15s, color 0.15s, filter 0.15s, box-shadow 0.15s, transform 0.08s;","&:focus-visible":"outline: 3px solid $s-focus; outline-offset: 1px;","&:hover":"filter: brightness(1.06)","&.tonal:hover, &.outlined:hover":"background: color-mix(in srgb, $s-bg 24%, transparent);","&.neutral:hover":"filter:none background: color-mix(in srgb, $s-text 8%, $s-bg);","> svg":"width:1.25em height:1.25em","&:active:not(:disabled)":"transform: translateY(1px)","&.small, .small > &":"padding: $m1 $m2; font-size:0.85em border-radius:$s-radius-sm","&.large, .large > &":"font-size:1.4em border-radius:$s-radius-lg"},".s-icon-btn":{"&":"display:inline-flex align-items:center justify-content:center flex-shrink:0 width:2rem height:2rem p:0 border:0 background:transparent cursor:pointer fg:$s-muted r:$s-radius-sm line-height:1 font-size:1rem text-decoration:none transition: color 0.12s, background 0.12s;","> svg":"width:1.25em height:1.25em","&:hover:not(:disabled):not([aria-disabled=true])":"fg:$s-text background: color-mix(in srgb, $s-text 10%, transparent);","&:focus-visible":"outline: 3px solid $s-focus; outline-offset:1px","&.small, .small > &":"width:1.6rem height:1.6rem font-size:0.8rem","&.large, .large > &":"width:2.4rem height:2.4rem font-size:1.2rem"}});function a1(t){let a=t.href!=null?"a":"button";P(`${a}.s-icon-btn`,t.attrs,()=>{I1(t),P("aria-label=",t.ariaLabel),x(t.icon)})}function I1(t){t.href!=null?(P("role=button"),t.disabled?P("aria-disabled=true"):P("href=",t.href)):(P("type=",t.type??"button"),t.disabled&&P("disabled=true")),t.click&&!t.disabled&&P("click=",t.click)}function O(t={}){let a=typeof t=="string"||typeof t=="function"?{content:t}:t,h=a.href!=null?"a":"button";P(`${h}.s-btn.s-s.shadow`,a.attrs,()=>{I1(a),a.ariaLabel&&P("aria-label=",a.ariaLabel),x(a.icon),x(a.content)})}N.insertGlobalCss({".s-box":{"&":"display:flex flex-direction:column overflow:hidden r: $s-radius-lg; position:relative","&:not(:first-child)":"margin-top: $3","> header":"display:flex align-items:center gap:$2 padding: $2 $3; border:0 border-bottom: 1px solid $s-faint; r:0 font-weight:600","> footer":"display:flex align-items:center justify-content:flex-end gap:$2 padding: $2 $3; border:0 border-top: 1px solid $s-faint; r:0","> div":"p:$3 gap:$3","> header > .s-box-close":"margin-left:auto","> .s-box-close":"position:absolute top:$2 right:$2 z-index:1"}});function i2(t={}){let a=typeof t=="string"||typeof t=="function"?{content:t}:t;N("section.s-box.s-s.neutral.shadow",a.attrs,()=>{N(()=>{a.header!=null?N("header.s-s.neutral",a.headerAttrs,()=>{x(a.header),typeof a.close=="function"&&U1(a.close)}):typeof a.close=="function"&&U1(a.close)}),N("div",a.contentAttrs,()=>{x(a.content)}),N(()=>{a.footer!=null&&N("footer.s-s.neutral",a.footerAttrs,()=>x(a.footer))})})}function U1(t){a1({icon:Q,ariaLabel:"Close",click:t,attrs:".s-box-close"})}import u1 from"aberdeen";import N1 from"aberdeen";N1.insertGlobalCss({".s-bgroup":{"&":"display:inline-flex align-items:stretch","&.s-spaced":"gap:$2 flex-wrap:wrap","&.s-vertical":"flex-direction:column","&.s-attached":"gap:0","&.s-attached:not(.s-vertical) > .s-btn:not(:first-child)":"margin-left:-1px","&.s-attached:not(.s-vertical) > .s-btn:not(:first-child):not(:last-child)":"r:0","&.s-attached:not(.s-vertical) > .s-btn:first-child:not(:last-child)":"border-top-right-radius:0 border-bottom-right-radius:0","&.s-attached:not(.s-vertical) > .s-btn:last-child:not(:first-child)":"border-top-left-radius:0 border-bottom-left-radius:0","&.s-attached.s-vertical > .s-btn:not(:first-child)":"margin-top:-1px","&.s-attached.s-vertical > .s-btn:not(:first-child):not(:last-child)":"r:0","&.s-attached.s-vertical > .s-btn:first-child:not(:last-child)":"border-bottom-left-radius:0 border-bottom-right-radius:0","&.s-attached.s-vertical > .s-btn:last-child:not(:first-child)":"border-top-left-radius:0 border-top-right-radius:0","&.s-attached > .s-btn:hover, &.s-attached > .s-btn:focus-visible":"z-index:1"}});function W(t={}){let h=`.s-${t.layout??"attached"}${t.vertical?".s-vertical":""}`;N1(`div.s-bgroup${h} role=group`,t.attrs,()=>{if(t.buttons)for(let e of t.buttons)O(e);x(t.content)})}function s2(t){u1(()=>{let a=t.bind.value;W({attrs:t.attrs,buttons:Object.entries(t.options).map(([h,e])=>({content:e,ariaLabel:typeof e=="function"?h:void 0,attrs:a===h?".primary":".neutral",click:()=>{t.bind.value=t.allowDeselect&&a===h?void 0:h}}))})}),t.name&&u1(()=>u1("input type=hidden name=",t.name,"value=",t.bind.value??""))}import k from"aberdeen";k.insertGlobalCss({".s-check":{"&":"display:flex flex-direction:column gap:$1","> label":"display:flex align-items:center gap:$2 cursor:pointer user-select:none","> label:has(input:disabled)":"cursor:not-allowed opacity:0.45 filter:saturate(0.6)",input:"cursor:inherit m:0"}});function l2(t={}){let a=t.id??B("check");k("div.s-check",t.attrs,()=>{k("label for=",a,()=>{k("input type=checkbox",t.inputAttrs,()=>{k("id=",a),t.name&&k("name=",t.name),t.checked&&!t.bind&&k("checked=true"),t.change&&k("change=",t.change),k(()=>{t.disabled&&k("disabled=true")}),k(()=>{t.required&&k("aria-required=true")}),t.bind&&k("bind=",t.bind)}),k(()=>{t.label!=null&&x(t.label),t.required&&k("span.s-req aria-hidden=true #*")})}),k(()=>{t.help!=null&&!t.error&&k("div.s-help",()=>x(t.help))}),k(()=>{t.error&&k("div.s-error role=alert #",t.error)})})}import X from"aberdeen";X.insertGlobalCss({".s-form":{"&":"display:flex flex-direction:column gap:$3","&.grid":"display:grid grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap:$3","&.grid > .s-wide, &.grid > footer":"grid-column: 1 / -1;","> footer":"display:flex align-items:center justify-content:flex-end gap:$2 flex-wrap:wrap margin-top:$1"}});function M2(t={}){let a=typeof t=="string"||typeof t=="function"?{content:t}:t;X("form.s-form",a.attrs,()=>{X(()=>{X(".grid=",a.layout==="grid")}),X("submit=",h=>{if(h.preventDefault(),a.submit){let e=new FormData(h.target),p={};for(let r of new Set(e.keys())){let d=e.getAll(r);p[r]=d.length===1?d[0]:d}a.submit(p,h)}}),x(a.content),X(()=>{a.actions&&X("footer",a.actionsAttrs,()=>x(a.actions))})})}import v from"aberdeen";import{current as S1,matchCurrent as N2}from"aberdeen/route";import u from"aberdeen";import{matchCurrent as f1,current as y1,go as x2}from"aberdeen/route";u.insertGlobalCss({".s-menu-list":"position:fixed z-index:350 min-width:10rem display:flex flex-direction:column p:$1 r:$s-radius-lg overflow-y:auto max-height:min(80vh,28rem) transition: opacity 0.15s, transform 0.15s;",".s-menu-list.hidden":"opacity:0 pointer-events:none transform:translateY(-6px)",".s-menu-item":"display:flex align-items:center gap:$2 w:100% outline:0 scroll-margin:$2 padding: $m2 0; line-height:1.1 r:$s-radius cursor:pointer text-align:left font-weight:450 font-size:0.9em border:0 background:transparent fg:$s-text text-decoration:none transition: color 0.12s, transform 0.12s, text-shadow 0.12s;",".s-menu-item:focus-visible:not([aria-current=page]), .s-menu-item:hover:not([aria-disabled=true]):not([aria-current=page])":"filter:none color: color-mix(in lab, $s-primary 33%, $s-text);",".s-menu-item[aria-current=page]":"color:$s-accent filter:none",".s-menu-list .s-menu-item":"padding-inline:$2",".s-menu-item[aria-disabled=true]":"opacity:0.45 cursor:not-allowed pointer-events:none",".s-menu-icon":"flex-shrink:0",".s-menu-list .s-menu-icon":"display:flex",".s-menu-list .s-menu-icon > svg":"width:1.25em height:1.25em","hr.s-menu-sep":"border:0 height:1px margin: $1 0.6rem; background: linear-gradient(to right, transparent, $s-faint 18%, $s-faint 82%, transparent);",".s-menu-chevron":"margin-left:auto flex-shrink:0 display:flex transition: transform 0.15s ease;",".s-menu-chevron > svg":"width:1em height:1em",".s-menu-details":{"> summary":"list-style:none","> summary::-webkit-details-marker":"display:none","&::details-content":"interpolate-size:allow-keywords block-size:0 overflow-y:clip transition: block-size 0.15s ease, content-visibility 0.15s allow-discrete;","&[open]::details-content":"block-size:auto","&[open] > summary .s-menu-chevron":"transform:rotate(90deg)"},".s-menu-sub":"display:flex flex-direction:column gap:$1 padding-left:$3",".s-menu-inline":"display:flex flex-direction:column gap:$1"});function h1(t,a){u("keydown=",e=>{if(e.key==="Enter"&&e.target.tagName==="A"){queueMicrotask(()=>a?.());return}if(e.key!=="ArrowDown"&&e.key!=="ArrowUp"&&e.key!=="Home"&&e.key!=="End")return;e.preventDefault();let r=[...e.currentTarget.querySelectorAll(".s-menu-item")].filter(i=>i.getAttribute("aria-disabled")!=="true"&&!u2(i));if(!r.length)return;let d=r.indexOf(document.activeElement),o=e.key==="ArrowUp"?-1:1,c=e.key==="Home"?0:e.key==="End"?r.length-1:d<0?o>0?0:r.length-1:(d+o+r.length)%r.length;r[c].focus()});let h=u.derive(()=>y2(t));W1(t,a,h)}function W1(t,a,h){for(let e of t){if(typeof e=="string"||typeof e=="function"){x(e);continue}if("separator"in e){u("hr.s-menu-sep");continue}e.items?m2(e,a,h):v2(e,a)}}function v2(t,a){let h=!1,e=u(t.href?"a.s-menu-item data-panel=open":"button.s-menu-item type=button",t.attrs,()=>{t.href&&(u("href=",t.href),t.target&&u("target=",t.target),u(()=>{let p=!h;h=!0,f1(t.href)&&(u("aria-current=page"),requestAnimationFrame(()=>e.scrollIntoView({block:"nearest",behavior:p?"instant":"smooth"})))})),t.disabled&&u("aria-disabled=true"),u("click=",p=>{if(t.disabled){p.preventDefault();return}a?.(),t.click?.(p)}),t.icon&&u("span.s-menu-icon",()=>x(t.icon)),x(t.label)})}function m2(t,a,h){let e=t.href??X1(t.items),p=!1,r=e!=null?u.derive(()=>g1(t)?p=!0:h==null||h.value?p=!1:p):null;u("details.s-menu-details",()=>{r&&u(()=>{r.value&&u("open=true")}),u("summary.s-menu-item.s-menu-branch",t.attrs,()=>{t.disabled&&u("aria-disabled=true"),u(()=>{t.href!=null&&f1(t.href)&&u("aria-current=page")}),u("click=",d=>{if(t.disabled){d.preventDefault();return}e!=null&&(d.preventDefault(),f2(e),x2(e)),t.click?.(d)}),t.icon&&u("span.s-menu-icon",()=>x(t.icon)),x(t.label),u("span.s-menu-chevron aria-hidden=true",()=>T1())}),u("div.s-menu-sub",()=>W1(t.items,a,h))})}function u2(t){for(let a=t.closest("details");a;a=a.parentElement&&a.parentElement.closest("details"))if(!a.open&&t.closest("summary")?.parentElement!==a)return!0;return!1}function y2(t){return t.some(a=>typeof a!="string"&&typeof a!="function"&&!("separator"in a)&&g1(a))}function g1(t){if(t.href!=null&&f1(t.href))return!0;for(let a of t.items??[])if(!(typeof a=="string"||typeof a=="function"||"separator"in a)&&g1(a))return!0;return!1}function X1(t){for(let a of t){if(typeof a=="string"||typeof a=="function"||"separator"in a)continue;let h=a.href??(a.items?X1(a.items):void 0);if(h!=null)return h}}var o1=null;function f2(t){try{o1=new URL(t,location.href).pathname.replace(/\/+$/,"")||"/"}catch{o1=null}}function b1(t){return o1!==t?!1:(o1=null,!0)}var U=u.proxy({opts:null});function Z(){let t=U.opts?.anchor;U.opts=null,t?.focus()}function c1(t){let a=U.opts;return a!=null&&(t==null||a.anchor===t)}function g2(t){c1(t)&&Z()}function b2(t,a){let h=t.offsetWidth,e=t.offsetHeight,p=window.innerWidth,r=window.innerHeight,d=4,o=a.left;o+h>p-8&&(o=Math.max(8,a.right-h));let c=a.bottom+d;c+e>r-8&&a.top-e-d>=8&&(c=a.top-e-d),t.style.left=Math.max(8,o)+"px",t.style.top=Math.max(8,c)+"px"}F(()=>{let t=U.opts;if(!t)return;let a=u("div.s-menu-list.s-s.neutral.shadow create=hidden destroy=hidden",t.dropdownAttrs,()=>{h1(t.items,Z)}),h=r=>{let d=r.target;!a.contains(d)&&(t.closeOnAnchorClick||!t.anchor.contains(d))&&Z()},e=r=>{(r.key==="Escape"||r.key==="Tab")&&(r.preventDefault(),Z())},p=u.peek(y1,"path");u(()=>{y1.path!==p&&!b1(y1.path)&&Z()}),document.addEventListener("click",h,!0),document.addEventListener("keydown",e,!0),u.clean(()=>{document.removeEventListener("click",h,!0),document.removeEventListener("keydown",e,!0)}),requestAnimationFrame(()=>{if(!document.body.contains(a))return;let r=t.at?{left:t.at.x,right:t.at.x,top:t.at.y,bottom:t.at.y}:t.anchor.getBoundingClientRect();b2(a,r),j(a,".s-menu-item[aria-current=page]")})});function w2(t){u("nav.s-menu-inline",t.attrs,()=>h1(t.items,t.onLeafSelect))}function w1(t){return U.opts=t,Z}function H1(t){let a=null;u.clean(()=>{U.opts?.anchor===a&&Z()}),u("contextmenu=",h=>{h.preventDefault(),a=h.currentTarget,w1({items:t.items,anchor:a,at:{x:h.clientX,y:h.clientY},closeOnAnchorClick:!0,dropdownAttrs:t.dropdownAttrs})})}function H2(t){let a=null;u.clean(()=>{U.opts?.anchor===a&&Z()}),O({icon:d1,...t.button?.content==null?{ariaLabel:"Open menu"}:null,attrs:".neutral",...t.button,click:h=>{if(a=h.currentTarget,U.opts?.anchor===a){Z();return}w1({items:t.items,anchor:a,dropdownAttrs:t.dropdownAttrs})}})}import H from"aberdeen";import G from"aberdeen";function A1(t={}){I(t,(a,h)=>{G("input.s-input",t.inputAttrs,()=>{G("type=",t.type??"text"),t.placeholder!=null&&G("placeholder=",t.placeholder),t.autocomplete!=null&&G("autocomplete=",t.autocomplete),t.value!=null&&!t.bind&&G("value=",t.value),t.input&&G("input=",t.input),t.change&&G("change=",t.change),_(t,a,h,t.bind)})})}H.insertGlobalCss({".s-backdrop":{"&":"position:fixed inset:0 z-index:200 display:block background: rgba(0,0,0,0.55); transition: opacity 0.4s ease-in-out;","&.hidden":"opacity:0 pointer-events:none"},".s-dialog":{"&":"position:fixed z-index:200 top:50% left:50% display:flex flex-direction:column transform:translate(-50%,-50%) min-width:20rem max-width:min(90vw,44rem) max-height:min(88vh,800px) r: $s-radius-lg; overflow:hidden transition: opacity 0.2s ease-out, transform 0.2s ease-out;","> header":"display:flex align-items:center gap:$2 padding: $2 $3; border:0 border-bottom: 1px solid $s-faint; r:0 font-weight:600 flex-shrink:0","> footer":"display:flex align-items:center justify-content:flex-end gap:$2 padding: $2 $3; border:0 border-top: 1px solid $s-faint; r:0 flex-shrink:0","> div":"p:$3 gap:$3 display:flex flex-direction:column overflow-y:auto flex:1 min-height:0","&.hidden":"opacity:0 pointer-events:none transform: translate(-50%, calc(-50% + 20px)); pointer-events:none"}});var K=H.proxy({}),V1=0,G1=H.derive(()=>{let t=Object.keys(K);if(t.length)return t[t.length-1]});function k1(){return G1.value!=null}F(()=>{H.onEach(K,({resolve:t,opts:a},h)=>{let e=()=>{delete K[h]};H.clean(()=>{a.onClose?.(),t()});let p=H.derive(()=>G1.value!=h);H("div.s-backdrop create=hidden destroy=hidden .hidden=",p,"click=",()=>{a.allowCancel!==!1&&e()});let r=H("div.s-dialog.neutral.s-s.extra-shadow create=hidden destroy=hidden",a.attrs,()=>{H(()=>{a.header!=null&&H("header.s-s.neutral",a.headerAttrs,()=>x(a.header))}),H("div",a.contentAttrs,()=>{x(a.content,e)}),H(()=>{a.footer!=null&&H("footer.s-s.neutral",a.footerAttrs,()=>x(a.footer))})});requestAnimationFrame(()=>{document.body.contains(r)&&j(r)})})});function n1(t){V1||document.addEventListener("keydown",h=>{if(h.key!=="Escape"||h.defaultPrevented)return;let e=H.unproxy(K);for(let p=V1;p>0;p--)if(e[p]){h.preventDefault(),e[p].opts.allowCancel!==!1&&delete K[p];break}});let a=++V1;return t.cancelWithScope!==!1&&H.clean(()=>{delete K[a]}),new Promise(h=>{K[a]={resolve:h,opts:t}})}function A2(t,a={}){return n1({header:"Alert",allowCancel:!0,content:h=>{H("p",()=>{H("#",t)}),W({layout:"spaced",attrs:"align-self:flex-end",content:()=>{O({content:"OK",click:h})}})},...a})}function V2(t,a={}){return new Promise(h=>{let e=!1;n1({header:"Confirm",allowCancel:!0,content:p=>{H("p",()=>{H("#",t)}),W({layout:"spaced",attrs:"align-self:flex-end",content:()=>{O({content:"Cancel",attrs:".neutral",click:p}),O({content:"OK",click:()=>{e=!0,p()}})}})},...a,onClose:()=>{h(e),a.onClose?.()}})})}function k2(t,a="",h={}){return new Promise(e=>{let p=null;n1({header:"Input",allowCancel:!0,content:r=>{H("p",()=>{H("#",t)});let d=H.proxy({value:a});H("form display:contents",()=>{H("submit=",o=>{o.preventDefault(),p=d.value,r()}),A1({bind:H.ref(d,"value")}),W({layout:"spaced",attrs:"align-self:flex-end",content:()=>{O({content:"Cancel",attrs:".neutral",type:"button",click:r}),O({content:"OK",type:"submit"})}})})},...h,onClose:()=>{e(p),h.onClose?.()}})})}import l,{OPAQUE as j1}from"aberdeen";import*as w from"aberdeen/route";import A from"aberdeen";var L2=z('<path d="m15 18-6-6 6-6"/>'),C2=z('<path d="m9 18 6-6-6-6"/>');A.insertGlobalCss({".s-strip":{"&":"position:relative display:flex min-width:0","> .s-strip-row":"display:flex align-items:center flex:1 min-width:0 overflow-x:auto overflow-y:hidden scrollbar-width:none scroll-behavior:smooth","> .s-strip-row::-webkit-scrollbar":"display:none","> .s-strip-btn":"position:absolute top:0 bottom:0 z-index:1 display:none align-items:center justify-content:center width:2.4em border:0 padding:0 cursor:pointer fg:$s-muted transition: color 0.15s;","> .s-strip-btn:hover":"fg:$s-text","> .s-strip-btn-left":"left:0 justify-content:flex-start background: linear-gradient(to right, $s-bg 45%, transparent)","> .s-strip-btn-right":"right:0 justify-content:flex-end background: linear-gradient(to left, $s-bg 45%, transparent)","&.s-can-left > .s-strip-btn-left, &.s-can-right > .s-strip-btn-right":"display:flex"},".s-tabs":{"&":"display:flex flex-direction:column gap:$3",".s-tabbar":"border-bottom: 1px solid $s-faint;",".s-tablist":"gap:$1 align-items:stretch margin-bottom:-1px",".s-tab":"display:inline-flex align-items:center gap:$2 cursor:pointer background:transparent border:0 color: $s-muted; font-weight:600 padding: 0.6em 0.9em; white-space:nowrap border-bottom: 3px solid transparent; transition: color 0.15s, background 0.15s, border-color 0.15s;",".s-tab:hover:not(:disabled), .s-tab[aria-selected=true]":"color: $s-text;",".s-tab:focus-visible":"outline:none box-shadow: inset 0 0 0 2px $s-focus; r: $s-radius;",".s-tab[aria-selected=true]":"border-image: $s-gradient 1;",".s-tabpanel":"display:block"}});function i1(t){A("div.s-strip",t.attrs,()=>{let a=A("div.s-strip-row",t.stripAttrs,()=>x(t.content));K1(a,-1),K1(a,1),$2(a)})}function s1(t){let a=t.parentElement;if(!a||!t.isConnected)return;let h=parseFloat(getComputedStyle(a).fontSize)*2.6,e=t.getBoundingClientRect(),p=a.getBoundingClientRect();e.left<p.left+h?a.scrollBy({left:e.left-p.left-h,behavior:"smooth"}):e.right>p.right-h&&a.scrollBy({left:e.right-p.right+h,behavior:"smooth"})}function z2(t){let a=B("tabs"),h=(r,d)=>r.id??String(d),e=t.bind??A.proxy(h(t.tabs[0]??{label:""},0));t.tabs.length>0&&!t.tabs.some((r,d)=>h(r,d)===A.peek(()=>e.value))&&(e.value=h(t.tabs[0],0));let p=(r,d)=>{r.disabled||(e.value=h(r,d))};A("div.s-tabs",t.attrs,()=>{i1({attrs:".s-tabbar",stripAttrs:".s-tablist role=tablist",content:()=>{t.tabs.forEach((r,d)=>{let o=h(r,d),c=A("button.s-tab type=button role=tab",()=>{A("id=",`${a}-tab-${o}`,"aria-controls=",`${a}-panel-${o}`),A(()=>{let i=e.value===o;A("aria-selected=",i?"true":"false"),A("tabindex=",i?"0":"-1"),i&&requestAnimationFrame(()=>s1(c))}),r.disabled&&A("disabled=true"),A("click=",()=>p(r,d)),A("keydown=",i=>S2(i,t.tabs,d,p)),x(r.icon),x(r.label)})})}}),A("div.s-tabpanel role=tabpanel",t.contentAttrs,()=>{A(()=>{let r=e.value,d=t.tabs.findIndex((c,i)=>h(c,i)===r),o=t.tabs[d]??t.tabs[0];o&&(A("id=",`${a}-panel-${h(o,d)}`,"aria-labelledby=",`${a}-tab-${h(o,d)}`),x(o.content))})})})}function K1(t,a){A(`button.s-strip-btn.s-strip-btn-${a<0?"left":"right"} type=button`,()=>{A("tabindex=-1 aria-hidden=true"),A("click=",()=>t.scrollBy({left:a*t.clientWidth*.8,behavior:"smooth"})),(a<0?L2:C2)({size:"1.1em"})})}function $2(t){let a=t.parentElement;if(!a||typeof ResizeObserver>"u")return;let h=()=>{let r=t.scrollWidth-t.clientWidth;a.classList.toggle("s-can-left",t.scrollLeft>1),a.classList.toggle("s-can-right",t.scrollLeft<r-1)};t.addEventListener("scroll",h,{passive:!0});let e=new ResizeObserver(h);e.observe(t);let p=typeof MutationObserver>"u"?void 0:new MutationObserver(r=>{for(let d of r){for(let o of d.addedNodes)o instanceof Element&&e.observe(o);for(let o of d.removedNodes)o instanceof Element&&e.unobserve(o)}h()});p?.observe(t,{childList:!0});for(let r of Array.from(t.children))e.observe(r);h(),A.clean(()=>{t.removeEventListener("scroll",h),e.disconnect(),p?.disconnect()})}function S2(t,a,h,e){let p=h;if(t.key==="ArrowRight"||t.key==="ArrowDown")p=(h+1)%a.length;else if(t.key==="ArrowLeft"||t.key==="ArrowUp")p=(h-1+a.length)%a.length;else if(t.key==="Home")p=0;else if(t.key==="End")p=a.length-1;else return;t.preventDefault();let r=p>=h?1:-1;for(let d=0;d<a.length;d++){let o=a[p];if(o&&!o.disabled){e(o,p),t.currentTarget?.parentElement?.children[p]?.focus();return}p=(p+r+a.length)%a.length}}import V from"aberdeen";import{grow as P2,shrink as O2}from"aberdeen/transitions";V.insertGlobalCss({".s-toasts":"position:fixed bottom:$3 right:$3 z-index:400 display:flex flex-direction:column gap:$2 pointer-events:none max-width:min(90vw,24rem) w:24rem",".s-toast":{"&":"display:flex align-items:flex-start gap:$2 padding: $3; pointer-events:auto position:relative overflow:hidden",".s-toast-body":"display:flex flex-direction:column gap:$1 flex:1 min-width:0",".s-toast-title":"font-weight:700 line-height:1.3",".s-toast-close":"cursor:pointer border:0 background:transparent fg:$s-muted font-size:1.1em line-height:1 padding: 0 0.15em; r:4px flex-shrink:0 align-self:flex-start",".s-toast-close:hover":"fg:$s-text",".s-toast-close:focus-visible":"outline:none box-shadow: 0 0 0 3px $s-focus; fg:$s-text",".s-toast-progress":"position:absolute bottom:0 left:0 right:0 height:2px background:$s-accent width:100%"}});var E2=0,e1=V.proxy({});F(()=>{V.peek(()=>V.isEmpty(e1))&&V.isEmpty(e1)||V("div.s-toasts",()=>{V.onEach(e1,t=>{let{opts:a,id:h}=t,e=a.type==="danger"||a.type==="warning"?"alert":"status",p=a.type==null||a.type==="neutral"?"neutral":a.type,r=a.duration??6e3,d,o=null,c=()=>{clearTimeout(d),o&&(o.style.transition="none",o.style.width="100%",o.offsetWidth,o.style.transition=`width ${r}ms linear`,o.style.width="0%"),d=setTimeout(()=>L1(h),r)},i=()=>{clearTimeout(d),d=void 0,o&&(o.style.transition="none",o.style.width="100%")};V.clean(()=>clearTimeout(d)),V(`div.s-toast.s-s.${p}.extra-shadow aria-live=polite role=${e}`,"create=",P2,"destroy=",O2,a.attrs,()=>{r>0&&(V("mouseenter=",i),V("mouseleave=",c)),V("div.s-toast-body",()=>{V(()=>{a.title!=null&&V("div.s-toast-title",()=>x(a.title))}),V("div.s-toast-msg",()=>x(a.message))}),V(()=>{a.dismissible!==!1&&V("button.s-toast-close type=button aria-label=Dismiss",()=>{V("#\xD7"),V("click=",()=>L1(h))})}),r>0&&(o=V("div.s-toast-progress"))}),r>0&&requestAnimationFrame(c)})})});function L1(t){delete e1[t]}function l1(t){let a=++E2;return e1[a]={id:a,opts:t},()=>L1(a)}var $1={integer(t){if(!/^(0|-?[1-9]\d*)$/.test(t))return;let a=Number(t);return Number.isSafeInteger(a)?a:void 0}};function q(t){let a=String(t).replace(/\/+$/,"");return a.startsWith("/")||(a=`/${a}`),a}function p1(t){let a=q(t);return a==="/"?[]:a.slice(1).split("/")}function _1(t){let a=p1(t),h=a.map((e,p)=>{if(!e.startsWith("[")||!e.endsWith("]"))return{kind:"lit",value:e};let r=/^\[\.\.\.([A-Za-z_$][\w$]*)\]$/.exec(e);if(r){if(p!==a.length-1)throw new Error(`Staffa: "${e}" must be the last segment of route "${t}"`);return{kind:"rest",name:r[1]}}let d=/^\[([A-Za-z_$][\w$]*)(?:=([A-Za-z_$][\w$]*))?\]$/.exec(e);if(!d)throw new Error(`Staffa: malformed param "${e}" in route "${t}"`);let[,o,c]=d;if(c&&!(c in $1))throw new Error(`Staffa: unknown matcher "${c}" in route "${t}" (known: ${Object.keys($1).join(", ")})`);return{kind:"param",name:o,matcher:c}});return{key:t,segs:h}}function q2(t){try{return decodeURIComponent(t)}catch{return t}}function C1(t,a){let h={};for(let e=0;e<t.segs.length;e++){let p=t.segs[e];if(p.kind==="rest")return e>=a.length?null:(h[p.name]=a.slice(e).join("/"),h);if(e>=a.length)return null;let r=a[e];if(p.kind==="lit"){if(r!==p.value)return null}else if(p.matcher){let d=$1[p.matcher](r);if(d===void 0)return null;h[p.name]=d}else h[p.name]=q2(r)}return t.segs.length===a.length?h:null}var J1=250,T2=300,D2=1280,R2=360,Q1=2;l.insertGlobalCss({":root":`--s-panel-ms:${J1}ms`,".s-panels":"flex:1 min-width:0 min-height:0 position:relative overflow:hidden isolation:isolate "+Y,".s-panel":{"&":"position:absolute top:0 bottom:0 left:0 display:flex flex-direction:column "+Y+" visibility:visible transition: left var(--s-panel-ms) ease, transform var(--s-panel-ms) ease-out, opacity var(--s-panel-ms) linear, visibility 0s;","&.s-panel-sep::before":"content:'' position:absolute left:0 top:0.6rem bottom:0.6rem width:1px z-index:1 background: linear-gradient(to bottom, transparent, $s-faint 18%, $s-faint 82%, transparent);","&.s-panel-enter":"opacity:0 transition:none transform: translateX(8cqw);","&.s-panel-closing":"opacity:0 pointer-events:none transform: translateX(8cqw);","&.s-panel-hidden, &.s-panel-parked":"opacity:0 visibility:hidden transition: left var(--s-panel-ms) ease, transform var(--s-panel-ms) ease-out, opacity var(--s-panel-ms) linear, visibility var(--s-panel-ms);","&.s-panel-hidden":"transform: translateX(-8cqw);","&.s-panel-parked":"transform: translateX(8cqw);"},".s-panel > .s-content":"flex:1 min-height:0 overflow-y:auto overflow-x:hidden p:$3",".s-panel-actions":"display:flex align-items:center justify-content:flex-end gap:$1 flex-shrink:0 padding: $3 $3 0;",".s-crumbs > .s-strip-row":"gap:$m1",".s-crumb":{"&":"flex-shrink:0 font-size:0.85em line-height:1.5 fg:$s-muted text-decoration:none white-space:nowrap max-width:14rem overflow:hidden text-overflow:ellipsis transition: color 0.12s;","&.s-crumb-on":"font-weight:600 fg:$s-text","a&:hover":"filter:none color: color-mix(in lab, $s-primary 33%, $s-text);","svg.s-crumb-pin":"vertical-align:-0.12em margin-right:0.3em opacity:0.8 fill:currentColor","svg.s-crumb-unsaved":"vertical-align:0.08em margin-right:0.3em fill:currentColor"},"svg.s-crumb-sep":"flex-shrink:0 opacity:0.4",".s-main.s-shell-snap .s-panel":"transition:none",".s-panel-loading":{"&":"position:absolute inset:0 display:flex align-items:center justify-content:center gap:$1 pointer-events:none",i:"width:0.5rem height:0.5rem r:50% background:$s-muted opacity:0.45 animation: s-panel-pulse 1s ease-in-out infinite;","i:nth-child(2)":"animation-delay:0.15s","i:nth-child(3)":"animation-delay:0.3s"},"@keyframes s-panel-pulse":{"0%, 100%":"opacity:0.25 transform:scale(0.8)","50%":"opacity:0.7 transform:scale(1)"}});var z1=!1,M1=class{[j1]=!0;compiled;ancestors;opts;$state=l.proxy({live:[],focus:0});$open=l.proxy({});nextOrder=0;containerEl;geom;lastBodyW=-1;layoutQueued=!1;timers=new Set;intent=null;settling=null;lastSeen=null;queued=null;constructor(a){if(z1)throw new Error("Staffa: only one routed S.main() (one with `routes`) can be active at a time");z1=!0,this.opts=a,this.compiled=Object.entries(a.routes).map(([h,e])=>({..._1(h),draw:e})),this.ancestors=Object.entries(a.ancestors??{}).filter(h=>h[1]!=null).map(([h,e])=>({..._1(h),fn:e})),l(()=>{let h=this.computeTarget(),e={...w.current.search},p=w.current.hash;l.peek(()=>{let r=this.lastSeen;if(r&&r.path!==w.current.path){let d=this.$state.live.find(o=>o.path===r.path);d&&(d.search=r.search,d.hash=r.hash)}this.lastSeen={path:w.current.path,search:e,hash:p},this.propose(h),Array.isArray(w.current.state.panels)||Object.assign(w.current.state,this.stateFor({stack:this.paths(),focus:this.$state.focus}))})}),this.interceptLinks(),this.watchTitle(),this.guardTabClose(),l.clean(()=>{for(let h of this.timers)clearTimeout(h);this.timers.clear(),this.queued?.settle(!1),this.queued=null,z1=!1})}resolve(a){let h=p1(a);for(let e of this.compiled){let p=C1(e,h);if(p)return{draw:e.draw,params:p}}return{draw:this.opts.notFound??U2,params:{}}}matches(a){let h=p1(a);return this.compiled.some(e=>C1(e,h)!=null)}deriveStack(a){let h=q(a),e=this.askAncestors(h),p=e?e.map(q):this.prefixesOf(h),r=[];for(let d of p)d!==h&&!r.includes(d)&&this.matches(d)&&r.push(d);return r.push(h),r}askAncestors(a){let h=p1(a);for(let e of this.ancestors){let p=C1(e,h);if(p)return e.fn(p,a)??void 0}}prefixesOf(a){let h=p1(a),e=[];for(let p=1;p<h.length;p++)e.push("/"+h.slice(0,p).join("/"));return e}pinnedIn(a,h){return a.filter(e=>h.includes(e)?!1:this.$state.live.find(p=>p.path===e)?.$panel.pinned===!0)}unsavedAt(a){return this.$state.live.find(h=>h.path===a)?.$panel.unsaved===!0}targetFor(a,h){let e=Array.isArray(h?.panels)?h.panels.map(String):null;if(e){let p=Array.isArray(h.parked)?h.parked.map(String):[],r=q(a),d=new Set([r]),o=i=>i.map(q).filter(f=>!d.has(f)&&!!d.add(f)),c=o(e);return{stack:[...c,r,...o(p)],focus:c.length}}return l.peek(()=>{let p=this.deriveStack(a).slice(0,-1),r=[...p,...this.pinnedIn(this.paths(),[...p,q(a)]),q(a)];return{stack:r,focus:r.length-1}})}computeTarget(){return this.targetFor(w.current.path,w.current.state)}paths(){return this.$state.live.map(a=>a.path)}propose(a){let h=this.$state.live.filter(e=>!a.stack.includes(e.path)&&e.$panel.unsaved).map(e=>e.path);h.length&&(a={stack:[...a.stack,...h],focus:a.focus}),!(B2(this.paths(),a.stack)&&a.focus===this.$state.focus)&&this.commit(a,w.current.nav)}commit(a,h){this.geom=void 0;let e=w.current.state.pinned,p=new Set(Array.isArray(e)?e.map(String):[]),r=new Map(this.$state.live.map(o=>[o.path,o])),d=[];for(let o of a.stack){let c=r.get(o);if(c){r.delete(o),d.push(c);continue}let i=this.createEntry(o,d.length<=a.focus,p.has(o));h!=="load"&&h!=="back"&&(i.enter=!0),d.push(i),this.$open[o]=i}for(let o of r.values())this.beginClose(o);this.$state.live=d,this.$state.focus=Math.min(a.focus,d.length-1),this.scheduleLayout()}createEntry(a,h,e){let{draw:p,params:r}=this.resolve(a),d={[j1]:!0,order:this.nextOrder++,path:a,draw:p,$ui:l.proxy({holding:!1}),maxWidth:"full",width:0};return d.$panel=l.proxy({stack:this,params:r,path:a,width:0,visible:h,pinned:e||void 0,close:()=>this.closePath(d.path)}),d}beginClose(a){a.closing=!0,a.$panel.visible=!1,a.el&&(a.el.style.zIndex=String(Q1*this.$state.live.indexOf(a))),delete this.$open[a.path]}playExit(a,h){if(!a.closing){h.remove();return}h.classList.add("s-panel-closing"),h.setAttribute("inert","");let e=()=>{clearTimeout(p),this.timers.delete(p),h.remove()};h.addEventListener("transitionend",r=>{r.target===h&&r.propertyName==="opacity"&&e()});let p=setTimeout(e,J1+80);this.timers.add(p)}intended(){return this.intent??{stack:this.paths(),focus:this.$state.focus}}stateFor(a){return{panels:a.stack.slice(0,a.focus),parked:a.stack.slice(a.focus+1),pinned:this.pinnedPaths()}}pinnedPaths(){return this.$state.live.filter(a=>a.$panel.pinned).map(a=>a.path)}issue(a,h){return this.intent=a,this.settling?(this.queued?.settle(!1),new Promise(e=>{this.queued={run:h,settle:e}})):this.start(h)}start(a){let h=p=>{this.settling=null;let r=this.queued;return this.queued=null,p&&r?this.start(r.run).then(r.settle,()=>r.settle(!1)):(this.intent=null,r?.settle(!1)),p},e=Promise.resolve(a()).then(h,p=>(console.error(p),h(!1)));return this.settling=e,e}focusAt(a,h,e){let p=this.intended();if(a<0||a>=p.stack.length||a===p.focus)return Promise.resolve(!1);let r={stack:p.stack,focus:a},d=p.stack[a];return this.issue(r,()=>{let o=this.$state.live.find(c=>c.path===d);return w.go({path:d,search:h??o?.search,hash:e??o?.hash,state:this.stateFor(r)})})}back(){return l.peek(()=>{let a=this.intended();return a.focus===a.stack.length-1&&!this.unsavedAt(a.stack[a.focus])?this.closePath(a.stack[a.focus]??""):a.focus===0?Promise.resolve(!1):this.focusAt(a.focus-1)})}closePath(a){return l.peek(()=>{let h=this.intended(),e=h.stack.indexOf(q(a));if(e<0||h.stack.length<2||this.unsavedAt(h.stack[e]))return Promise.resolve(!1);let p=h.stack.filter((i,f)=>f!==e),r=e===h.focus?Math.max(0,e-1):h.focus-(e<h.focus?1:0),d={stack:p,focus:r};if(e===h.focus&&e===h.stack.length-1){let i=this.$state.live.find(m=>m.path===p[r]),f={};i?.search&&(f.search=i.search),i?.hash&&(f.hash=i.hash);let n=p.filter(m=>this.$state.live.find(y=>y.path===m)?.$panel.pinned===!0);return this.issue(d,()=>Promise.resolve(w.back({path:p[r],state:{panels:p.slice(0,r),parked:[]}},f)).then(m=>(m&&(w.current.state.pinned=n),m)))}let o=p[r],c=o!==h.stack[h.focus];return this.issue(d,()=>{let i=c?this.$state.live.find(f=>f.path===o):void 0;return w.go({path:o,search:c?i?.search:{...w.current.search},hash:c?i?.hash:w.current.hash,state:this.stateFor(d)})})})}navigate(a,h,e=!1,p){return l.peek(()=>{let r;try{r=new URL(a,location.href)}catch{return Promise.resolve(!1)}let d=q(r.pathname),o=Object.fromEntries(new URLSearchParams(r.search)),c=r.hash,i=this.intended(),f=p?-1:i.stack.indexOf(d);if(f>=0&&f!==i.focus)return this.focusAt(f,r.search?o:void 0,c||void 0);if(f>=0)return r.search===location.search&&(r.hash||"")===(location.hash||"")?Promise.resolve(!0):this.issue(i,()=>w.go({path:d,search:o,hash:c,state:this.stateFor(i)}));let n=h==null?-1:i.stack.indexOf(h),m=p?p.map(q).filter((s,b,C)=>s!==d&&C.indexOf(s)===b):n<0?this.deriveStack(d).slice(0,-1):i.stack.slice(0,e?n:n+1),y=[...m,...this.pinnedIn(i.stack,[...m,d,e?h:null])],g={stack:[...y,d],focus:y.length};return this.issue(g,()=>w.go({path:d,search:o,hash:c,state:this.stateFor(g)}))})}pushPath(a,h){return l.peek(()=>{let e=this.intended();return this.navigate(a,e.stack[e.focus]??null,h)})}interceptLinks(){w.interceptLinks((a,h)=>{let e=h.getAttribute("data-panel")??this.opts.linkNavigation,p=null;if(e!=="open"){let r=h.closest(".s-panel");r?p=this.$state.live.find(d=>d.el===r)?.path??null:h.closest(".s-panel-origin")&&(p=this.$state.live[this.$state.focus]?.path??null)}return this.navigate(a.href,p,e==="replace"),!0})}get currentPanel(){return this.$state.live[this.$state.focus]?.$panel}get panels(){return this.$state.live.map(a=>a.$panel)}get currentPanelIndex(){return this.$state.focus}pushPanel(a){return this.pushPath(a,!1)}replacePanel(a){return this.pushPath(a,!0)}openPanelStack(a,h){return this.navigate(a,null,!1,h)}closePanel(a){return l.peek(()=>{let h=this.intended();return this.closePath(a??h.stack[h.focus]??"")})}drawCrumbs(){i1({attrs:".s-crumbs role=navigation aria-label=Breadcrumbs",content:()=>{l(()=>{let a=this.panels.map(p=>p.path),h=this.currentPanelIndex,e;for(let p=0;p<a.length;p++){p&&F1({size:"0.85em",attrs:".s-crumb-sep"});let r=this.drawCrumb(a[p],p,p===h);p===h&&(e=r)}requestAnimationFrame(()=>{e&&s1(e)})})}})}drawCrumb(a,h,e){let p=this.$state.live[h];return l(e?"span.s-crumb aria-current=page":"a.s-crumb",()=>{e||l("href=",a),l(()=>{p?.$panel.visible&&l(".s-crumb-on")}),l(()=>{p?.$panel.unsaved&&D1({size:"0.45em",attrs:".s-crumb-unsaved"})}),l(()=>{p?.$panel.pinned&&m1({size:"0.85em",attrs:".s-crumb-pin"})}),l(()=>{l("#",p?.$panel.title??p?.$ui.fallback??(a.split("/").pop()||a))}),H1({items:[{label:"Open in new tab",icon:R1,click:()=>{window.open(a,"_blank","noopener")}},{label:"Copy link",icon:Z1,click:()=>{I2(a)}},{separator:!0},{label:()=>{l(()=>{l("#",p?.$panel.pinned?"Unpin":"Pin")})},icon:()=>{l(()=>{(p?.$panel.pinned?B1:m1)()})},click:()=>{p&&this.togglePin(p)}},{label:"Close",icon:Q,disabled:p?.$panel.unsaved===!0,click:()=>{this.closePath(a)}}]})})}togglePin(a){a.$panel.pinned=!a.$panel.pinned||void 0,w.current.state.pinned=this.pinnedPaths()}watchTitle(){let a=document.title;l(()=>{let h=this.$state.live[this.$state.focus],e=h?.$panel.title??h?.$ui.fallback,p=typeof this.opts.title=="string"?this.opts.title:void 0,r=this.$state.live.some(o=>o.$panel.unsaved),d=e&&p?`${e} \xB7 ${p}`:e||p;d&&(document.title=(r?"\u2022 ":"")+d)}),l.clean(()=>{document.title=a})}guardTabClose(){if(typeof window>"u")return;let a=!1,h=()=>{a=!0},e=p=>{a=!1;let r=this.$state.live.find(o=>o.$panel.unsaved);if(!r)return;p.preventDefault(),p.returnValue=!0;let d=r.path;setTimeout(()=>{if(a)return;let o=this.$state.live.find(c=>c.path===d);o&&!o.$panel.visible&&this.focusAt(this.intended().stack.indexOf(d))},0)};l(()=>{this.$state.live.some(p=>p.$panel.unsaved)&&(window.addEventListener("beforeunload",e),window.addEventListener("pagehide",h),l.clean(()=>{window.removeEventListener("beforeunload",e),window.removeEventListener("pagehide",h)}))})}drawColumns(){let a=l("div.s-panels role=main",()=>{this.containerEl=l(),l.onEach(this.$open,h=>this.drawPanel(h),h=>h.order)});if(typeof ResizeObserver<"u"){let h=new ResizeObserver(()=>this.layout());h.observe(a);let e=a.parentElement?.parentElement;e&&h.observe(e),l.clean(()=>h.disconnect())}l.clean(()=>{this.containerEl===a&&(this.containerEl=void 0)}),this.scheduleLayout()}drawPanel(a){let h;l(()=>{let e=a.$panel.maxWidth;a.maxWidth=e==="half"||e==="screen"?e:"full";let p=this.roomFor(a.maxWidth);p&&(a.width=p,l.peek(a.$panel,"width")!==p&&(a.$panel.width=p),h&&(h.style.width=`${p}px`,this.scheduleLayout()))}),h=l(`section.s-panel${a.width?` w:${a.width}px`:""}`,"destroy=",e=>this.playExit(a,e),()=>{l(()=>this.drawActions(a)),l("div.s-content",()=>{if(a.draw(a.$panel),w.persistScroll(a.path),l.peek(a.$panel,"title")==null){let e=F2(l());e&&l.peek(a.$ui,"fallback")!==e&&(a.$ui.fallback=e)}}),l(()=>{!a.$panel.loading||a.$ui.holding||l("div.s-panel-loading aria-hidden=true",()=>{l("i"),l("i"),l("i")})})}),a.el=h,a.placed=!1,h.style.transition="none",l.clean(()=>{a.el===h&&(a.el=void 0)}),l(()=>{a.$panel.loading,this.scheduleLayout()}),this.scheduleLayout()}drawActions(a){this.opts.$shell.narrow||a.$panel.actions==null||l("div.s-panel-actions",()=>x(a.$panel.actions))}scheduleLayout(){this.layoutQueued||(this.layoutQueued=!0,requestAnimationFrame(()=>{this.layoutQueued=!1,this.layout()}))}measure(){let a=this.containerEl,h=a?.parentElement,e=h?.parentElement;if(!a||!h||!e)return;let p=e.getBoundingClientRect().width;if(!p)return;let r=0;for(let c of h.children)c!==a&&(r+=c.getBoundingClientRect().width);let d=Math.max(0,Math.min(D2,p)-r),o=d/2;return{total:p,chrome:r,half:o>=R2?o:d,full:d,screen:Math.max(0,p-r)}}geometry(){return this.geom??=this.measure()}roomFor(a){return this.geometry()?.[a]??0}layout(){let a=this.containerEl,h=a?.closest(".s-main");if(!a||!h)return;let e=this.$state.live,p=e.length;if(!p||e.some(s=>!s.el))return;this.geom=void 0;let r=this.geometry();if(!r)return;let d=this.opts.columns!=="single",o=this.lastBodyW!==r.total;o&&(this.lastBodyW=r.total,h.classList.add("s-shell-snap"));let c=s=>r[s.maxWidth],i=Math.min(this.$state.focus,p-1),f=i,n=c(e[i]);if(d)for(let s=i-1;s>=0;s--){let b=n+c(e[s]);if(b>r.screen)break;n=b,f=s}let m=Math.min(r.screen,Math.max(r.full,n));for(let s=f;s<=i;s++)e[s].width=c(e[s]);for(let s of e)s.width||(s.width=c(s));h.style.setProperty("--s-shell-w",`${r.chrome+m}px`);let y=[],g=0;for(let s=0;s<p;s++){let b=e[s],C=b.el,S=s>=f&&s<=i;Z2(C,S?g:s>i?m:0,b.width,Q1*s+1),b.$panel.visible!==S&&(b.$panel.visible=S),b.$panel.width!==b.width&&(b.$panel.width=b.width),S&&(g+=b.width),C.classList.toggle("s-panel-sep",S&&s>f),C.classList.toggle("s-panel-hidden",s<f),C.classList.toggle("s-panel-parked",s>i),C.toggleAttribute("inert",!S),!b.placed&&(y.push(b),!b.$panel.loading||b.holdDone?b.$ui.holding=!1:b.$ui.holding||(b.$ui.holding=!0,this.holdEnter(b)),b.enter&&S&&C.classList.add("s-panel-enter"))}(y.length||o)&&a.offsetWidth,o&&h.classList.remove("s-shell-snap");for(let s of y)s.$ui.holding||(s.el.style.transition="",s.el.classList.remove("s-panel-enter"),s.enter=!1,s.placed=!0)}holdEnter(a){let h=setTimeout(()=>{this.timers.delete(h),a.holdDone=!0,a.$ui.holding&&(a.$ui.holding=!1,this.scheduleLayout())},T2);this.timers.add(h)}};function Z2(t,a,h,e){t.style.left=`${a}px`,t.style.width=`${h}px`,t.style.zIndex=String(e)}function B2(t,a){return t.length===a.length&&t.every((h,e)=>h===a[e])}function F2(t){let a=document.createTreeWalker(t,NodeFilter.SHOW_TEXT);for(let h=a.nextNode();h;h=a.nextNode()){let e=h.textContent.trim();if(e)return e.length>48?`${e.slice(0,47).trimEnd()}\u2026`:e}}async function I2(t){let a=new URL(t,location.href).href;try{await navigator.clipboard.writeText(a),l1({message:"Link copied."})}catch{l1({message:"Couldn't copy the link.",type:"danger"})}}function U2(t){l("p fg:$s-muted",()=>l("#",`No panel at ${t.path}`))}v.insertGlobalCss({".s-main":{"&":"display:flex flex-direction:column min-height:100vh max-height:100vh container-type:inline-size","body > &":"margin: calc(-1 * $3)","> header":"border:0 border-bottom: 1px solid $s-faint; r:0 position:sticky top:0 z-index:10","> footer":"border-top: 1px solid $s-faint; fg:$s-muted","> header > .s-bar, > footer > .s-bar":"display:flex align-items:center width:100% margin-inline:auto gap:$3 padding: $2 $3;","> header .s-logo, > header .s-nav-trigger":"display:flex align-items:center flex-shrink:0","> header .s-nav-trigger":"margin-left:-0.375rem","> header .s-logo":"font-size:1.4em background: $s-gradient; -webkit-background-clip:text; background-clip:text; color:transparent;","> header .s-titles":"display:flex flex-direction:column min-width:5rem flex: 0 1 auto;","> header .s-subtitle":"fg:$s-muted font-size:0.85em line-height:1.5 overflow:hidden text-overflow:ellipsis white-space:nowrap","> header .s-title":"font-weight:800 font-size:1.1em line-height:1.2 overflow:hidden text-overflow:ellipsis white-space:nowrap letter-spacing:-0.01em background: $s-gradient; -webkit-background-clip:text; background-clip:text; color:transparent; width:fit-content max-width:100%","> header a.s-logo, > header a.s-title":"text-decoration:none filter:none cursor:pointer","> header .s-menu":"display:flex align-items:center justify-content:flex-end gap:$2 flex: 1 1 auto; min-width:0",".s-body":"flex:1 overflow:hidden display:flex flex-direction:row min-height:0 justify-content:center position:relative",".s-body-inner":"flex:1 min-width:0 display:flex flex-direction:row min-height:0","&.s-nav-right .s-body-inner":"flex-direction:row-reverse",".s-nav-sep":"width:1px flex-shrink:0 align-self:stretch margin: 0.6rem 0; border:0 background: linear-gradient(to bottom, transparent, $s-faint 18%, $s-faint 82%, transparent);",".s-body main":"flex:1 min-width:0 min-height:0 overflow-x:hidden overflow-y:auto display:flex flex-direction:column transition: transform var(--s-panel-ms) ease;",".s-body main.s-slide-in":"transform: translateX(100%); transition:none",".s-body main > .s-content":"width:100% flex:1 p:$3",".s-body main.s-scroll-y":"margin-right:$3","&.s-routed > .s-body > .s-body-inner":"max-width: var(--s-shell-w, 100%);","&.s-routed > header > .s-bar":"max-width: var(--s-shell-w, 100%);","&.s-routed > footer > .s-bar":"max-width: var(--s-shell-w, 100%);","&.s-routed > .s-body > .s-body-inner, &.s-routed > header > .s-bar, &.s-routed > footer > .s-bar":"transition: max-width var(--s-panel-ms) ease;","&.s-routed.s-shell-snap > .s-body > .s-body-inner, &.s-routed.s-shell-snap > header > .s-bar, &.s-routed.s-shell-snap > footer > .s-bar":"transition:none"},".s-nav-panel":{"&":"display:flex flex-direction:column overflow-y:auto flex-shrink:0 max-width:228px padding:$3 gap:$1"},".s-nav-page":{"&":"position:absolute inset:0 z-index:5 display:flex flex-direction:column overflow-y:auto overscroll-behavior:contain border:0 r:0 padding:$2 gap:$1 transition: transform var(--s-panel-ms) ease;","&.s-nav-page-off":"transform:translateX(-100%) pointer-events:none",".s-menu-item":"padding: $2 $3; min-height:3rem font-size:1.05em gap:$3"},[`@container (max-width: ${r1}px)`]:{".s-main .s-nav-panel, .s-main .s-nav-sep":"display:none",".s-main > header > .s-bar":"gap:$1 padding: $1 $2;",".s-content > .s-box":"margin-inline: calc(-1 * $3); r:0 border-inline:0",".s-main .s-body main.s-scroll-y":"margin-right:0"}});function W2(t={}){let a=t.nav,h=t.navPosition??"left",e=v.proxy({open:!1}),p=v.proxy({narrow:typeof document<"u"&&document.documentElement.clientWidth<=r1}),r=t.routes;if(r!=null&&t.content!=null)throw new Error("Staffa: S.main() takes either `content` or `routes`, not both");let d=r?new M1({routes:r,notFound:t.notFound,ancestors:t.ancestors,columns:t.columns,linkNavigation:t.linkNavigation,title:t.title,$shell:p}):null,o=d&&t.home!==null?t.home??"/":null,c=d?null:t.maxWidth,i=v(`div.s-main${d?".s-routed":""}`,t.attrs,()=>{v(()=>{a==null||!a.items.length||v(`.s-nav-${h}`)}),v(()=>{(d!=null||t.title!=null||t.subtitle!=null||t.logo!=null||t.menu!=null||a!=null&&a.items.length>0)&&v("header.s-s.neutral",t.topbarAttrs,()=>{v("div.s-bar",()=>{v(()=>{c!=null&&v("max-width:",c)}),v(()=>{if(p.narrow&&a!=null&&a.items.length){v("div.s-nav-trigger",()=>_2(a,e));return}t.logo!=null&&v(o!=null?"a.s-logo aria-label=Home":"div.s-logo",()=>{o!=null&&v("href=",o),x(t.logo)})}),v("div.s-titles",()=>{v(()=>{t.title!=null&&v(o!=null?"a.s-title":"div.s-title",()=>{o!=null&&v("href=",o),x(t.title)})}),G2(t,d,a,p)}),v(()=>{let n=p.narrow?d?.currentPanel?.actions:void 0,m=n??t.menu;m!=null&&v(`div.s-menu${n!=null?".s-panel-origin":""}`,()=>x(m))})})})}),v("div.s-body",()=>{v("div.s-body-inner",()=>{v(()=>{c!=null&&v("max-width:",c)}),v(()=>{a==null||!a.items.length||(v(`nav.s-nav-panel.s-nav-${h}`,t.navAttrs,()=>{h1(a.items)}),v("div.s-nav-sep aria-hidden=true"))}),Y2(t,d)}),v(()=>{a!=null&&a.items.length&&e.open&&Q2(a,t.navPageAttrs,e,p)})}),v(()=>{t.footer!=null&&v("footer",()=>{v("div.s-bar",()=>{v(()=>{c!=null&&v("max-width:",c)}),x(t.footer)})})})});if(j2(i,p),a!=null||d){let f=n=>{if(n.key!=="Escape"||n.defaultPrevented||k1()||c1())return;let m=i.querySelector(".s-nav-trigger button");if(e.open){n.preventDefault(),e.open=!1,m?.focus();return}if(d&&d.currentPanelIndex>0){n.preventDefault(),d.back();return}let y=i.querySelector(".s-nav-panel");if(y?.offsetParent!=null){let g=y.querySelector("[aria-current=page]")??y.querySelector(".s-menu-item:not([aria-disabled=true])");g&&(n.preventDefault(),g.focus());return}m&&(n.preventDefault(),m.click())};document.addEventListener("keydown",f),v.clean(()=>document.removeEventListener("keydown",f))}return d??void 0}var x1=null;function X2(){x1?.()}function G2(t,a,h,e){v(()=>{if(t.subtitle!=null&&(a==null||K2(a,h,e))){v("div.s-subtitle",()=>x(t.subtitle));return}a?.drawCrumbs()})}function K2(t,a,h){return h.narrow||a==null||t.panels.length>1?!1:a.items.some(e=>typeof e!="string"&&typeof e!="function"&&!("separator"in e)&&e.href!=null&&N2(e.href))}function j2(t,a){if(typeof ResizeObserver>"u")return;let h=new ResizeObserver(e=>{let p=e[0]?.contentBoxSize?.[0],r=p?p.inlineSize:e[0]?.contentRect.width;r!=null&&(a.narrow=r<=r1)});h.observe(t),v.clean(()=>h.disconnect())}function _2(t,a){a1({icon:t.button?.icon??(()=>v(()=>(a.open?Q:d1)())),ariaLabel:t.button?.ariaLabel??"Open navigation",attrs:t.button?.attrs,click:()=>{a.open=!a.open}})}function Q2(t,a,h,e){let p=!1,r=()=>{p=!0,h.open=!1},d=v("nav.s-nav-page.s-s.neutral aria-label=Navigation create=s-nav-page-off destroy=s-nav-page-off",a,()=>h1(t.items,r));x1=r,v.clean(()=>{x1===r&&(x1=null)});let o=v.peek(S1,"path");v(()=>{S1.path!==o&&!b1(S1.path)&&r()});let c=d.closest(".s-main"),i=d.parentElement?.querySelector(":scope > .s-body-inner"),f=i?.querySelector(":scope > main");i?.setAttribute("inert",""),v(()=>{e.narrow||(h.open=!1)}),v.clean(()=>{i?.removeAttribute("inert"),p&&(f&&J2(f),c?.querySelector(".s-nav-trigger button")?.focus())}),requestAnimationFrame(()=>{document.body.contains(d)&&j(d,".s-menu-item[aria-current=page]")})}function J2(t){t.classList.add("s-slide-in"),t.offsetWidth,t.classList.remove("s-slide-in")}function Y2(t,a){if(a){a.drawColumns();return}let h=v("main",()=>{v("div.s-content",t.contentAttrs,()=>{x(t.content)})});t0(h)}function t0(t){if(typeof ResizeObserver>"u")return;let a=()=>t.classList.toggle("s-scroll-y",t.offsetWidth>t.clientWidth),h=new ResizeObserver(a);h.observe(t),t.firstElementChild&&h.observe(t.firstElementChild),a(),v.clean(()=>h.disconnect())}import $ from"aberdeen";$.insertGlobalCss({".s-select_wrap":{"&":"position:relative display:block",select:"w:100% cursor:pointer padding-right:2.2em; appearance:none","&::after":"content: '\u25BE'; position:absolute right:0.7em top:50%; transform: translateY(-50%); pointer-events:none fg:$s-muted font-size:0.85em"}});function a0(t){I(t,(a,h)=>{$("div.s-select_wrap",t.inputAttrs,()=>{$("select.s-input",()=>{_(t,a,h),$("change=",e=>{t.bind&&(t.bind.value=e.target.value)}),$(()=>{let e=typeof t.options=="function"?t.options():t.options,p=t.bind?.value??"";t.placeholder!=null&&$("option",()=>{$("value= disabled=true hidden=true"),p||$("selected=true"),$("#",t.placeholder)});for(let r of e){let d=typeof r=="string"?{value:r,label:r}:{value:r.value,label:r.label??r.value};$("option",()=>{$("value=",d.value),d.value===p&&$("selected=true"),$("#",d.label)})}})})})})}import T from"aberdeen";T.insertGlobalCss({"textarea.s-input":"resize:vertical min-height:3em line-height:1.45","textarea.s-input.s-autoGrow":"resize:none min-height:2.5em overflow-y:hidden"});function h0(t={}){let a=t.autoGrow!==!1;I(t,(h,e)=>{let p=T("textarea.s-input",t.inputAttrs,()=>{a?(T(".s-autoGrow"),T("input=",r=>{Y1(r.currentTarget),t.input&&t.input(r)})):(T("rows=",t.rows??4),T("resize:",t.resize??"vertical"),t.input&&T("input=",t.input)),t.placeholder!=null&&T("placeholder=",t.placeholder),t.value!=null&&!t.bind&&T("value=",t.value),t.change&&T("change=",t.change),_(t,h,e,t.bind)});a&&requestAnimationFrame(()=>Y1(p))})}function Y1(t){t.style.height="auto",t.style.height=`${t.scrollHeight}px`}import D from"aberdeen";D.insertGlobalCss({".s-tt-tip":{"&":"position:fixed z-index:500 max-width:20rem w:max-content padding: 0.3em 0.65em; font-size:0.85em line-height:1.4 pointer-events:none"}});var J=D.proxy(void 0),R=null;typeof window<"u"&&window.addEventListener("scroll",()=>{J.value=void 0},{capture:!0,passive:!0});function e0(t,a,h,e){let r=window.innerWidth,d=window.innerHeight,o=0,c=0;return e==="bottom"?(o=t.left+(t.width-a)/2,c=t.bottom+7,c+h>d-8&&(c=t.top-h-7)):e==="left"?(o=t.left-a-7,c=t.top+(t.height-h)/2,o<8&&(o=t.right+7)):e==="right"?(o=t.right+7,c=t.top+(t.height-h)/2,o+a>r-8&&(o=t.left-a-7)):(o=t.left+(t.width-a)/2,c=t.top-h-7,c<8&&(c=t.bottom+7)),{x:Math.max(8,Math.min(o,r-a-8)),y:Math.max(8,Math.min(c,d-h-8))}}function P1(){R&&clearTimeout(R),R=setTimeout(()=>{J.value=void 0,R=null},100)}F(()=>{let t=J.value;if(!t)return;let{opts:a,anchor:h}=t,e=a.placement??"top",p=D("div.s-tt-tip.s-s.neutral.shadow role=tooltip visibility:hidden",a.attrs,()=>{D("mouseenter=",()=>{R&&(clearTimeout(R),R=null)}),D("mouseleave=",P1),x(a.tip)});requestAnimationFrame(()=>{if(!document.body.contains(p))return;let{x:r,y:d}=e0(h.getBoundingClientRect(),p.offsetWidth,p.offsetHeight,e);p.style.left=r+"px",p.style.top=d+"px",p.style.visibility=""})});function p0(t){let a=h=>{R&&(clearTimeout(R),R=null),J.value={opts:t,anchor:h.currentTarget}};D("mouseenter=",a),D("mouseleave=",P1),D("focusin=",a),D("focusout=",P1),D.clean(()=>{J.value?.opts===t&&(J.value=void 0)})}export{H1 as addContextMenu,p0 as addTooltip,A2 as alert,o2 as autocomplete,i2 as box,O as button,s2 as buttonChooser,W as buttonGroup,l2 as checkbox,g2 as closeFloatingMenu,X2 as closeNav,V2 as confirm,n1 as dialog,M2 as form,E1 as getDarkMode,a1 as iconButton,k1 as isDialogOpen,c1 as isFloatingMenuOpen,W2 as main,w2 as menu,H2 as menuButton,k2 as prompt,s1 as revealInStrip,i1 as scrollStrip,a0 as select,h2 as setDarkMode,w1 as showFloatingMenu,z2 as tabs,h0 as textarea,A1 as textline,l1 as toast};
1
+ import E from"aberdeen";var Y="background: linear-gradient(170deg, color-mix(in oklab, $s-bg, white 9%), color-mix(in oklab, $s-bg, black 9%));",m1="staffa:darkMode",E1=E.proxy({value:p2()});function p2(){try{let t=localStorage.getItem(m1);if(t==="dark")return!0;if(t==="light")return!1}catch{}}function r2(t){E1.value=t;try{t===void 0?localStorage.removeItem(m1):localStorage.setItem(m1,t?"dark":"light")}catch{}}function q1(t=!1){let a=E1.value;return a===void 0&&!t?E.darkMode():a}E(()=>{q1()?E.insertGlobalCss({":root, .s-s.neutral":"--s-bg:#0e0f12 --s-text:#e9eaec",".s-s.neutral":"--s-bg:#191b1f --s-text:#e9eaec",".s-s.neutral .s-s.neutral":"--s-bg:#23262b"}):E.insertGlobalCss({":root, .s-s.neutral":"--s-bg:#eef0f3 --s-text:#1d1f24",".s-s.neutral, .s-s.neutral":"--s-bg:#ffffff --s-text:#1d1f24",".s-s.neutral .s-s.neutral":"--s-bg:#f6f7f9"})});E.setSpacingCssVars(1.1);E.insertGlobalCss({"*, *::before, *::after":"box-sizing:border-box",html:"text-size-adjust:100%",body:"m:0 p:$3 line-height:1.5 font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; -webkit-font-smoothing:antialiased background-color:$s-bg text:$s-text",a:"color: $s-link-fg; text-decoration:underline text-underline-offset:2px; transition: color 0.12s, filter 0.12s;","a:hover":"filter: brightness(1.15)","input, button, textarea, select, optgroup":"font:inherit color:inherit","input:where(:not([type=checkbox],[type=radio],[type=range],[type=file],[type=color],[type=image],[type=submit],[type=button],[type=reset],[type=hidden])), textarea, select":"background:$s-bg border: 1px solid $s-faint; r:$s-radius-sm padding: 0.45em 0.65em; max-width:100%","input:where([type=checkbox],[type=radio])":"width:1.15em height:1.15em cursor:pointer","input[type=range]":"appearance:none background:transparent cursor:pointer vertical-align:middle","input[type=range]::-webkit-slider-runnable-track":"height:4px r:99px background:$s-faint","input[type=range]::-moz-range-track":"height:4px r:99px background:$s-faint","input[type=range]::-moz-range-progress":"height:4px r:99px background:$s-accent","input[type=range]::-webkit-slider-thumb":"appearance:none width:16px height:16px margin-top:-6px r:50% background:$s-accent","input[type=range]::-moz-range-thumb":"width:16px height:16px border:0 r:50% background:$s-accent","input[type=file]":"cursor:pointer",progress:"appearance:none border:0 height:6px r:99px background:$s-faint overflow:hidden vertical-align:middle","progress::-webkit-progress-bar":"background:$s-faint r:99px","progress::-webkit-progress-value":"background:$s-accent r:99px","progress::-moz-progress-bar":"background:$s-accent r:99px",meter:"vertical-align:middle",fieldset:"border: 1px solid $s-faint; r:$s-radius-sm padding:$2 min-width:0",legend:"padding: 0 $1; font-weight:600","code, kbd, samp, pre":"font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;",code:"background: color-mix(in oklab, $s-text, $s-bg 86%); padding: 0.12em 0.34em; r:4px font-size:0.9em",pre:"background: color-mix(in oklab, $s-text, $s-bg 92%); p:$3 r: $s-radius; overflow:auto","pre code":"background:transparent p:0","img, svg, video, canvas":"max-width:100% h:auto",hr:"border:0 border-top: 1px solid $s-faint;","::placeholder":"color: $s-muted; opacity:1",":focus-visible":"outline: 2px solid $s-focus; outline-offset:2px",small:"color:$s-muted font-size:0.9em","@media (prefers-reduced-motion: reduce)":{"*, *::before, *::after":"transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; scroll-behavior: auto !important;"},":root":"--s-primary:#00a884 --s-danger:#dc5b41 --s-success:#00a884 --s-warning:#ef6b00 --s-link:#3f8cd8 --s-radius-sm:6px --s-radius:12px --s-radius-lg:18px --s-focus: color-mix(in srgb, $s-primary 38%, transparent); --s-gradient: linear-gradient(135deg, color-mix(in oklab, $s-primary, white 16%), color-mix(in oklab, $s-primary, black 14%));",":root, .s-s.neutral":"--s-accent:$s-primary --s-link-fg:$s-link",".s-s:not(.neutral)":"--s-bg:$s-primary border:0 --s-text:#eee --s-accent:#fff --s-link-fg:#eef --s-muted: color-mix(in srgb, #fff 70%, transparent); --s-faint: color-mix(in srgb, #fff 30%, transparent);",".s-s.danger":"--s-bg:$s-danger",".s-s.success":"--s-bg:$s-success",".s-s.warning":"--s-bg:$s-warning",".s-s.link":"--s-bg:$s-link",".s-s.primary":"--s-bg:$s-primary",":root, .s-s":"--s-muted: color-mix(in oklab, $s-text, $s-bg 42%); --s-faint: color-mix(in oklab, $s-text, $s-bg 80%); color:$s-text accent-color:$s-accent scrollbar-width:thin scrollbar-color: $s-faint transparent;",".s-s, body":Y,".s-s":"r:$s-radius",":where(.s-s.neutral)":"border: 1px solid $s-faint;",".s-s::-webkit-scrollbar, .s-s ::-webkit-scrollbar":"width:10px height:10px",".s-s::-webkit-scrollbar-track, .s-s ::-webkit-scrollbar-track":"background:transparent",".s-s::-webkit-scrollbar-thumb, .s-s ::-webkit-scrollbar-thumb":"background:$s-faint border-radius:99px border: 2px solid transparent; background-clip:padding-box",".s-s.shadow.neutral:not(.s-btn)":"box-shadow: 0 4px 14px rgba(0,0,0,0.13);",".s-s.extra-shadow.neutral:not(.s-btn)":"box-shadow: 0 18px 50px rgba(0,0,0,0.28);",".s-s.shadow:not(.neutral):not(.tonal):not(.outlined)":"box-shadow: 0 4px 14px color-mix(in srgb, $s-bg 30%, transparent);",".s-s.extra-shadow:not(.neutral):not(.tonal):not(.outlined)":"box-shadow: 0 14px 40px color-mix(in srgb, $s-bg 40%, transparent);",".s-s.no-shadow":"box-shadow: none !important;",".s-s:not(.neutral).tonal, .s-s:not(.neutral).outlined":"--s-text:$s-bg --s-accent:$s-bg --s-link-fg:$s-bg --s-faint: color-mix(in srgb, $s-bg 30%, transparent); --s-muted: color-mix(in srgb, $s-bg 70%, transparent);",".s-s:not(.neutral).tonal":"background: color-mix(in srgb, $s-bg 15%, transparent); border: 1px solid $s-faint;",".s-s:not(.neutral).outlined":"background: transparent; border: 1px solid color-mix(in srgb, $s-bg 45%, transparent);",".s-s:not(.neutral) .s-s.tonal, .s-s:not(.neutral) .s-s.outlined":"--s-text:#fff --s-accent:#fff --s-link-fg:#fff "+Y+" border-color: transparent;"});E.insertGlobalCss({".s-preload, .s-preload *, .s-preload *::before, .s-preload *::after":"transition: none !important; animation: none !important;"});if(typeof document<"u"&&typeof requestAnimationFrame=="function"){let t=document.documentElement;t.classList.add("s-preload"),requestAnimationFrame(()=>requestAnimationFrame(()=>t.classList.remove("s-preload")))}E.insertGlobalCss({":disabled, [aria-disabled=true]":"opacity:0.45 filter:saturate(0.6) user-select:none",":disabled, [aria-disabled=true], :disabled *, [aria-disabled=true] *":"pointer-events:none cursor:not-allowed"});var d2="p, ul, ol, dl, blockquote, pre, table, figure, hr, h1, h2, h3, h4, h5, h6";E.insertGlobalCss({[`${d2}`]:{"&":"margin:0","&:not(:first-child)":"margin-top:$3"},"h1, h2, h3, h4, h5, h6":{"&":"line-height:1.15 font-weight:700 text-wrap:balance","&:not(:first-child)":"margin-top:1.4em"},h1:"font-size:2em font-weight:800 letter-spacing:-0.022em",h2:"font-size:1.55em letter-spacing:-0.018em",h3:"font-size:1.3em letter-spacing:-0.011em",h4:"font-size:1.1em",h5:"font-size:0.95em letter-spacing:0.005em",h6:"font-size:0.8em fg:$s-muted text-transform:uppercase letter-spacing:0.07em","ul, ol":{"&":"padding-left:1.5em","> li:not(:first-child), li > &:not(:first-child)":"margin-top:$1"},blockquote:"border-left: 3px solid $s-faint; padding-left: $3; fg: $s-muted",table:"border-collapse:collapse","th, td":"text-align:left padding: $1 $2; border-bottom: 1px solid $s-faint; vertical-align:top",th:"font-weight:600","thead th":"border-bottom: 2px solid $s-faint;",dt:"font-weight:600",dd:"margin-left: 1.5em",figcaption:"fg:$s-muted font-size:0.9em margin-top:$1 text-align:center"});import M from"aberdeen";import T1 from"aberdeen";var r1=640,o2=0;function B(t="s"){return`${t}-${++o2}`}function v(t,...a){t!=null&&(typeof t=="function"?t(...a):T1("rich=",t))}var c2="a[href], button, input, select, textarea, [tabindex]";function j(t,a){let h=p=>p instanceof HTMLElement&&!p.hasAttribute("disabled")&&p.getAttribute("aria-disabled")!=="true"&&p.tabIndex>=0&&p.getClientRects().length>0,e=(a?[...t.querySelectorAll(a)].find(h):void 0)??[...t.querySelectorAll(c2)].find(h);return e?.focus(),e!=null}function F(t){queueMicrotask(()=>T1(t))}import L from"aberdeen";L.insertGlobalCss({".s-field":{"&":"display:flex flex-direction:column gap:$1","> label":"font-weight:600 font-size:0.9em fg:$s-text user-select:none"},".s-req":"fg:$s-danger margin-left:2px",".s-help":"font-size:0.82em fg:$s-muted",".s-error":"font-size:0.82em fg:$s-danger",".s-input":{"&":"w:100% background: color-mix(in oklab, $s-bg, $s-text 4%); color:$s-text border: 1px solid $s-faint; r:$s-radius padding: 0.55em 0.7em; transition: border-color 0.15s, box-shadow 0.15s;","&:hover:not(:disabled)":"border-color: color-mix(in oklab, $s-text, $s-bg 55%);","&:focus-visible":"border-color:$s-accent box-shadow: 0 0 0 3px $s-focus; outline:none","&[aria-invalid=true]":"border-color:$s-danger"}});function I(t,a){let h=t.id??B("field"),e=()=>!!t.error;L("div.s-field",t.attrs,()=>{L(()=>{t.label!=null&&L("label for=",h,()=>{v(t.label),t.required&&L("span.s-req aria-hidden=true #*")})}),a(h,e),L(()=>{t.help!=null&&!t.error&&L("div.s-help",()=>v(t.help))}),L(()=>{t.error&&L("div.s-error role=alert #",t.error)})})}function _(t,a,h,e){L("id=",a),t.name&&L("name=",t.name),L(()=>{t.disabled&&L("disabled=true")}),L(()=>{t.required&&L("aria-required=true")}),L(()=>L("aria-invalid=",h()?"true":"false")),e&&L("bind=",e)}M.insertGlobalCss({".s-ac":{"&":"position:relative","> .s-control":"display:flex flex-wrap:wrap align-items:center gap:$1 background: color-mix(in oklab, $s-bg, $s-text 4%); color:$s-text border: 1px solid $s-faint; r:$s-radius padding: 0.3em 0.4em; cursor:text; transition: border-color 0.15s, box-shadow 0.15s;","> .s-control:hover":"border-color: color-mix(in oklab, $s-text, $s-bg 55%);","> .s-control:focus-within":"border-color:$s-accent box-shadow: 0 0 0 3px $s-focus;","&[aria-invalid=true] > .s-control":"border-color:$s-danger",".s-chip":"display:inline-flex align-items:center gap:$1 font-size:0.85em background: color-mix(in oklab, $s-bg, $s-text 10%); border: 1px solid $s-faint; r:$s-radius padding: 0.1em 0.2em 0.1em 0.5em;",".s-chip > button":"cursor:pointer border:0 background:transparent fg:$s-muted font-size:1.1em line-height:1 padding: 0 0.2em; r:4px",".s-chip > button:hover":"fg:$s-text background:$s-faint",input:"flex:1 min-width:6ch border:0 background:transparent color:inherit outline:none padding:0.25em","> .s-menu":"position:absolute top:100% left:0 right:0 z-index:20 margin-top:4px max-height:15rem overflow-y:auto list-style:none p:$1 margin-bottom:0","> .s-menu li":"margin:0",".s-option":"padding: 0.45em 0.6em; r:6px cursor:pointer transition: background 0.1s;",".s-option[aria-selected=true]":"background: color-mix(in srgb, $s-text 10%, transparent);",".s-add":"fg:$s-accent font-style:italic",".s-empty":"padding: 0.45em 0.6em; fg:$s-muted"}});function n2(t){return typeof t=="string"?{value:t,label:t}:{value:t.value,label:t.label??t.value}}function i2(t){let a=B("ac-menu"),h=M.proxy({query:"",open:!1,active:0}),e=()=>(typeof t.options=="function"?t.options():t.options).map(n2),p=()=>{let n=t.bind?.value;return n==null||n===""?[]:Array.isArray(n)?n:[n]},r=n=>e().find(m=>m.value===n)?.label??n;if(!t.multi){let n=t.bind?M.peek(t.bind,"value"):void 0;typeof n=="string"&&n&&(h.query=M.peek(()=>r(n)))}let d=()=>{let n=new Set(p()),m=e();t.multi&&(m=m.filter(g=>!n.has(g.value)));let y=h.query.trim().toLowerCase();return y&&(m=m.filter(g=>g.label.toLowerCase().includes(y))),m},o=(n,m)=>{if(t.multi){let y=Array.isArray(t.bind?.value)?[...t.bind.value]:[];y.includes(n)||y.push(n),t.bind&&(t.bind.value=y),h.query=""}else t.bind&&(t.bind.value=n),h.query=r(n),h.open=!1;h.active=0,m?.focus()},c=n=>{if(!t.bind)return;let m=t.bind.value??[];t.bind.value=m.filter(y=>y!==n)};I(t,(n,m)=>{M("div.s-ac",t.inputAttrs,()=>{M(()=>M("aria-invalid=",m()?"true":"false"));let y;M("div.s-control",()=>{M("click=",()=>y?.focus()),M(()=>{if(t.multi)for(let g of p())M("span.s-chip",()=>{M("span #",M.peek(()=>r(g))),M("button type=button aria-label=",`Remove ${g}`,()=>{M("#\xD7"),M("click=",s=>{s.stopPropagation(),c(g),y?.focus()})})})}),y=M("input type=text role=combobox autocomplete=off",()=>{M("id=",n,`aria-controls=${a} aria-autocomplete=list`),t.placeholder!=null&&M("placeholder=",t.placeholder),t.disabled&&M("disabled=true"),t.required&&M("aria-required=true"),M("bind=",M.ref(h,"query")),M(()=>M("aria-expanded=",h.open?"true":"false")),M(()=>{let s=d()[h.active];M("aria-activedescendant=",h.open&&s?`${a}-opt-${h.active}`:"")}),M("input=",()=>{h.open=!0,h.active=0}),M("focus=",()=>{h.open=!0}),M("blur=",()=>{setTimeout(()=>f(),150)}),M("keydown=",g=>i(g,y))})}),M(()=>{if(!h.open)return;let g=d(),s=h.query.trim(),b=t.allowCustom!==!1&&s!==""&&!g.some(C=>C.label.toLowerCase()===s.toLowerCase());M("ul.s-menu.s-s.neutral.shadow role=listbox",`id=${a}`,()=>{g.forEach((C,S)=>{M("li.s-option role=option",`id=${a}-opt-${S}`,()=>{M(()=>M("aria-selected=",h.active===S?"true":"false")),M("#",C.label),M("mousedown=",e2=>e2.preventDefault()),M("click=",()=>o(C.value,y)),M("mousemove=",()=>{h.active=S})})}),b&&M("li.s-option.s-add role=option",()=>{M("#",`Add "${s}"`),M("mousedown=",C=>C.preventDefault()),M("click=",()=>o(s,y))}),g.length===0&&!b&&M("li.s-empty #No matches")})}),M(()=>{if(t.name)if(t.multi)for(let g of p())M("input type=hidden",()=>{M("name=",t.name),M("value=",g)});else M("input type=hidden",()=>{M("name=",t.name),M("value=",p()[0]??"")})})})});function i(n,m){let y=d(),g=y.length-1;if(n.key==="ArrowDown")n.preventDefault(),h.open=!0,h.active=Math.min(g,h.active+1);else if(n.key==="ArrowUp")n.preventDefault(),h.active=Math.max(0,h.active-1);else if(n.key==="Enter"){n.preventDefault();let s=y[h.active];s?o(s.value,m):t.allowCustom!==!1&&h.query.trim()?o(h.query.trim(),m):h.open&&(h.open=!1)}else if(n.key==="Escape")h.open&&(n.preventDefault(),h.open=!1,t.multi||(h.query=r(p()[0]??"")));else if(n.key==="Backspace"&&t.multi&&h.query===""){let s=p();s.length&&c(s[s.length-1])}}function f(){h.open=!1,t.multi?h.query="":t.allowCustom!==!1&&h.query.trim()?o(h.query.trim()):h.query=r(p()[0]??"")}}import N from"aberdeen";import s2 from"aberdeen";var t1={size:24,color:"currentColor",strokeWidth:2,cap:"round",join:"round"};function l2(t,a){let h=a.size??t1.size,e=s2('svg.s-icon aria-hidden=true viewBox="0 0 24 24" fill=none',"width=",h,"height=",h,"stroke=",a.color??t1.color,"stroke-width=",a.strokeWidth??t1.strokeWidth,"stroke-linecap=",a.cap??t1.cap,"stroke-linejoin=",a.join??t1.join,a.attrs);e.innerHTML=t}function z(t){return(a={})=>l2(t,a)}var D1=z('<path d="m9 18 6-6-6-6" />');var R1=z('<circle cx="12" cy="12" r="10" />');var Z1=z('<path d="M15 3h6v6" /><path d="M10 14 21 3" /><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />');var B1=z('<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" /><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />');var d1=z('<path d="M4 5h16" /><path d="M4 12h16" /><path d="M4 19h16" />');var F1=z('<path d="M12 17v5" /><path d="M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89" /><path d="m2 2 20 20" /><path d="M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11" />'),u1=z('<path d="M12 17v5" /><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z" />');var I1=z('<path d="M22 2 2 22" />');var Q=z('<path d="M18 6 6 18" /><path d="m6 6 12 12" />');import P from"aberdeen";P.insertGlobalCss({".s-btn":{"&":"display:inline-flex align-items:center justify-content:center gap:$2 font-weight:450 line-height:1.1 white-space:nowrap cursor:pointer text-decoration:none padding: $m2 $m3; transition: background 0.15s, border-color 0.15s, color 0.15s, filter 0.15s, box-shadow 0.15s, transform 0.08s;","&:focus-visible":"outline: 3px solid $s-focus; outline-offset: 1px;","&:hover":"filter: brightness(1.06)","&.tonal:hover, &.outlined:hover":"background: color-mix(in srgb, $s-bg 24%, transparent);","&.neutral:hover":"filter:none background: color-mix(in srgb, $s-text 8%, $s-bg);","> svg":"width:1.25em height:1.25em","&:active:not(:disabled)":"transform: translateY(1px)","&.small, .small > &":"padding: $m1 $m2; font-size:0.85em border-radius:$s-radius-sm","&.large, .large > &":"font-size:1.4em border-radius:$s-radius-lg"},".s-icon-btn":{"&":"display:inline-flex align-items:center justify-content:center flex-shrink:0 width:2rem height:2rem p:0 border:0 background:transparent cursor:pointer fg:$s-muted r:$s-radius-sm line-height:1 font-size:1rem text-decoration:none transition: color 0.12s, background 0.12s;","> svg":"width:1.25em height:1.25em","&:hover:not(:disabled):not([aria-disabled=true])":"fg:$s-text background: color-mix(in srgb, $s-text 10%, transparent);","&:focus-visible":"outline: 3px solid $s-focus; outline-offset:1px","&.small, .small > &":"width:1.6rem height:1.6rem font-size:0.8rem","&.large, .large > &":"width:2.4rem height:2.4rem font-size:1.2rem"}});function a1(t){let a=t.href!=null?"a":"button";P(`${a}.s-icon-btn`,t.attrs,()=>{U1(t),P("aria-label=",t.ariaLabel),v(t.icon)})}function U1(t){t.href!=null?(P("role=button"),t.disabled?P("aria-disabled=true"):P("href=",t.href)):(P("type=",t.type??"button"),t.disabled&&P("disabled=true")),t.click&&!t.disabled&&P("click=",t.click)}function O(t={}){let a=typeof t=="string"||typeof t=="function"?{content:t}:t,h=a.href!=null?"a":"button";P(`${h}.s-btn.s-s.shadow`,a.attrs,()=>{U1(a),a.ariaLabel&&P("aria-label=",a.ariaLabel),v(a.icon),v(a.content)})}N.insertGlobalCss({".s-box":{"&":"display:flex flex-direction:column overflow:hidden r: $s-radius-lg; position:relative","&:not(:first-child)":"margin-top: $3","> header":"display:flex align-items:center gap:$2 padding: $2 $3; border:0 border-bottom: 1px solid $s-faint; r:0 font-weight:600","> footer":"display:flex align-items:center justify-content:flex-end gap:$2 padding: $2 $3; border:0 border-top: 1px solid $s-faint; r:0","> div":"p:$3 gap:$3","> header > .s-box-close":"margin-left:auto","> .s-box-close":"position:absolute top:$2 right:$2 z-index:1"}});function M2(t={}){let a=typeof t=="string"||typeof t=="function"?{content:t}:t;N("section.s-box.s-s.neutral.shadow",a.attrs,()=>{N(()=>{a.header!=null?N("header.s-s.neutral",a.headerAttrs,()=>{v(a.header),typeof a.close=="function"&&N1(a.close)}):typeof a.close=="function"&&N1(a.close)}),N("div",a.contentAttrs,()=>{v(a.content)}),N(()=>{a.footer!=null&&N("footer.s-s.neutral",a.footerAttrs,()=>v(a.footer))})})}function N1(t){a1({icon:Q,ariaLabel:"Close",click:t,attrs:".s-box-close"})}import y1 from"aberdeen";import W1 from"aberdeen";W1.insertGlobalCss({".s-bgroup":{"&":"display:inline-flex align-items:stretch","&.s-spaced":"gap:$2 flex-wrap:wrap","&.s-vertical":"flex-direction:column","&.s-attached":"gap:0","&.s-attached:not(.s-vertical) > .s-btn:not(:first-child)":"margin-left:-1px","&.s-attached:not(.s-vertical) > .s-btn:not(:first-child):not(:last-child)":"r:0","&.s-attached:not(.s-vertical) > .s-btn:first-child:not(:last-child)":"border-top-right-radius:0 border-bottom-right-radius:0","&.s-attached:not(.s-vertical) > .s-btn:last-child:not(:first-child)":"border-top-left-radius:0 border-bottom-left-radius:0","&.s-attached.s-vertical > .s-btn:not(:first-child)":"margin-top:-1px","&.s-attached.s-vertical > .s-btn:not(:first-child):not(:last-child)":"r:0","&.s-attached.s-vertical > .s-btn:first-child:not(:last-child)":"border-bottom-left-radius:0 border-bottom-right-radius:0","&.s-attached.s-vertical > .s-btn:last-child:not(:first-child)":"border-top-left-radius:0 border-top-right-radius:0","&.s-attached > .s-btn:hover, &.s-attached > .s-btn:focus-visible":"z-index:1"}});function W(t={}){let h=`.s-${t.layout??"attached"}${t.vertical?".s-vertical":""}`;W1(`div.s-bgroup${h} role=group`,t.attrs,()=>{if(t.buttons)for(let e of t.buttons)O(e);v(t.content)})}function x2(t){y1(()=>{let a=t.bind.value;W({attrs:t.attrs,buttons:Object.entries(t.options).map(([h,e])=>({content:e,ariaLabel:typeof e=="function"?h:void 0,attrs:a===h?".primary":".neutral",click:()=>{t.bind.value=t.allowDeselect&&a===h?void 0:h}}))})}),t.name&&y1(()=>y1("input type=hidden name=",t.name,"value=",t.bind.value??""))}import k from"aberdeen";k.insertGlobalCss({".s-check":{"&":"display:flex flex-direction:column gap:$1","> label":"display:flex align-items:center gap:$2 cursor:pointer user-select:none","> label:has(input:disabled)":"cursor:not-allowed opacity:0.45 filter:saturate(0.6)",input:"cursor:inherit m:0"}});function v2(t={}){let a=t.id??B("check");k("div.s-check",t.attrs,()=>{k("label for=",a,()=>{k("input type=checkbox",t.inputAttrs,()=>{k("id=",a),t.name&&k("name=",t.name),t.checked&&!t.bind&&k("checked=true"),t.change&&k("change=",t.change),k(()=>{t.disabled&&k("disabled=true")}),k(()=>{t.required&&k("aria-required=true")}),t.bind&&k("bind=",t.bind)}),k(()=>{t.label!=null&&v(t.label),t.required&&k("span.s-req aria-hidden=true #*")})}),k(()=>{t.help!=null&&!t.error&&k("div.s-help",()=>v(t.help))}),k(()=>{t.error&&k("div.s-error role=alert #",t.error)})})}import X from"aberdeen";X.insertGlobalCss({".s-form":{"&":"display:flex flex-direction:column gap:$3","&.grid":"display:grid grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap:$3","&.grid > .s-wide, &.grid > footer":"grid-column: 1 / -1;","> footer":"display:flex align-items:center justify-content:flex-end gap:$2 flex-wrap:wrap margin-top:$1"}});function m2(t={}){let a=typeof t=="string"||typeof t=="function"?{content:t}:t;X("form.s-form",a.attrs,()=>{X(()=>{X(".grid=",a.layout==="grid")}),X("submit=",h=>{if(h.preventDefault(),a.submit){let e=new FormData(h.target),p={};for(let r of new Set(e.keys())){let d=e.getAll(r);p[r]=d.length===1?d[0]:d}a.submit(p,h)}}),v(a.content),X(()=>{a.actions&&X("footer",a.actionsAttrs,()=>v(a.actions))})})}import x from"aberdeen";import{current as P1}from"aberdeen/route";import u from"aberdeen";import{matchCurrent as u2,current as o1,go as y2}from"aberdeen/route";u.insertGlobalCss({".s-menu-list":"position:fixed z-index:350 min-width:10rem display:flex flex-direction:column p:$1 r:$s-radius-lg overflow-y:auto max-height:min(80vh,28rem) transition: opacity 0.15s, transform 0.15s, visibility 0.15s;",".s-menu-list.hidden":"opacity:0 pointer-events:none transform:translateY(-6px) visibility:hidden",".s-menu-item":"display:flex align-items:center gap:$2 w:100% outline:0 scroll-margin:$2 padding: $m2 0; line-height:1.1 r:$s-radius cursor:pointer text-align:left font-weight:450 font-size:0.9em border:0 background:transparent fg:$s-text text-decoration:none transition: color 0.12s, transform 0.12s, text-shadow 0.12s;",".s-menu-item:focus-visible:not([aria-current=page]), .s-menu-item:hover:not([aria-disabled=true]):not([aria-current=page])":"filter:none color: color-mix(in lab, $s-primary 33%, $s-text);",".s-menu-item[aria-current=page]":"color:$s-accent filter:none",".s-menu-list .s-menu-item":"padding-inline:$2",".s-menu-item[aria-disabled=true]":"opacity:0.45 cursor:not-allowed pointer-events:none",".s-menu-icon":"flex-shrink:0",".s-menu-list .s-menu-icon":"display:flex",".s-menu-list .s-menu-icon > svg":"width:1.25em height:1.25em","hr.s-menu-sep":"border:0 height:1px margin: $1 0.6rem; background: linear-gradient(to right, transparent, $s-faint 18%, $s-faint 82%, transparent);",".s-menu-chevron":"margin-left:auto flex-shrink:0 display:flex transition: transform 0.15s ease;",".s-menu-chevron > svg":"width:1em height:1em",".s-menu-details":{"> summary":"list-style:none","> summary::-webkit-details-marker":"display:none","&::details-content":"interpolate-size:allow-keywords block-size:0 overflow-y:clip transition: block-size 0.15s ease, content-visibility 0.15s allow-discrete;","&[open]::details-content":"block-size:auto","&[open] > summary .s-menu-chevron":"transform:rotate(90deg)"},".s-menu-sub":"display:flex flex-direction:column gap:$1 padding-left:$3",".s-menu-inline":"display:flex flex-direction:column gap:$1"});function h1(t,a){u("keydown=",e=>{if(e.key==="Enter"&&e.target.tagName==="A"){queueMicrotask(()=>a?.());return}if(e.key!=="ArrowDown"&&e.key!=="ArrowUp"&&e.key!=="Home"&&e.key!=="End")return;e.preventDefault();let r=[...e.currentTarget.querySelectorAll(".s-menu-item")].filter(i=>i.getAttribute("aria-disabled")!=="true"&&!b2(i));if(!r.length)return;let d=r.indexOf(document.activeElement),o=e.key==="ArrowUp"?-1:1,c=e.key==="Home"?0:e.key==="End"?r.length-1:d<0?o>0?0:r.length-1:(d+o+r.length)%r.length;r[c].focus()});let h=u.derive(()=>f1(t));G1(t,a,h)}function G1(t,a,h){for(let e of t){if(typeof e=="string"||typeof e=="function"){v(e);continue}if("separator"in e){u("hr.s-menu-sep");continue}e.items?g2(e,a,h):f2(e,a)}}function f2(t,a){let h=!1,e=u(t.href?"a.s-menu-item data-panel=open":"button.s-menu-item type=button",t.attrs,()=>{t.href&&(u("href=",t.href),t.target&&u("target=",t.target),u(()=>{let p=!h;h=!0,g1(t)&&(u("aria-current=page"),requestAnimationFrame(()=>e.scrollIntoView({block:"nearest",behavior:p?"instant":"smooth"})))})),t.disabled&&u("aria-disabled=true"),u("click=",p=>{if(t.disabled){p.preventDefault();return}a?.(),t.click?.(p)}),t.icon&&u("span.s-menu-icon",()=>v(t.icon)),v(t.label)})}var K1=new Map;function X1(t,a){return K1.set(t,a),a}function g2(t,a,h){let e=t.href??j1(t.items),p=e!=null?u.derive(()=>b1(t)?X1(e,!0):h==null||h.value?X1(e,!1):K1.get(e)??!1):null;u("details.s-menu-details",()=>{p&&u(()=>{p.value&&u("open=true")}),u("summary.s-menu-item.s-menu-branch",t.attrs,()=>{t.disabled&&u("aria-disabled=true"),u(()=>{g1(t)&&u("aria-current=page")}),u("click=",r=>{if(t.disabled){r.preventDefault();return}e!=null&&(r.preventDefault(),w2(e),y2(e)),t.click?.(r)}),t.icon&&u("span.s-menu-icon",()=>v(t.icon)),v(t.label),u("span.s-menu-chevron aria-hidden=true",()=>D1())}),u("div.s-menu-sub",()=>G1(t.items,a,h))})}function b2(t){for(let a=t.closest("details");a;a=a.parentElement&&a.parentElement.closest("details"))if(!a.open&&t.closest("summary")?.parentElement!==a)return!0;return!1}function f1(t){return t.some(a=>typeof a!="string"&&typeof a!="function"&&!("separator"in a)&&b1(a))}function g1(t){if(t.href!=null&&u2(t.href))return!0;let a=t.match;if(a==null)return!1;let h=o1.path;if(typeof a=="function")return a(h);let e=a.replace(/\/+$/,"")||"/";return h===e||h.startsWith(e==="/"?"/":e+"/")}function b1(t){if(g1(t))return!0;for(let a of t.items??[])if(!(typeof a=="string"||typeof a=="function"||"separator"in a)&&b1(a))return!0;return!1}function j1(t){for(let a of t){if(typeof a=="string"||typeof a=="function"||"separator"in a)continue;let h=a.href??(a.items?j1(a.items):void 0);if(h!=null)return h}}var c1=null;function w2(t){try{c1=new URL(t,location.href).pathname.replace(/\/+$/,"")||"/"}catch{c1=null}}function w1(t){return c1!==t?!1:(c1=null,!0)}var U=u.proxy({opts:null});function Z(){let t=U.opts?.anchor;U.opts=null,t?.focus()}function n1(t){let a=U.opts;return a!=null&&(t==null||a.anchor===t)}function H2(t){n1(t)&&Z()}function A2(t,a){let h=t.offsetWidth,e=t.offsetHeight,p=window.innerWidth,r=window.innerHeight,d=4,o=a.left;o+h>p-8&&(o=Math.max(8,a.right-h));let c=a.bottom+d;c+e>r-8&&a.top-e-d>=8&&(c=a.top-e-d),t.style.left=Math.max(8,o)+"px",t.style.top=Math.max(8,c)+"px"}F(()=>{let t=U.opts;if(!t)return;let a=u("div.s-menu-list.s-s.neutral.shadow create=hidden destroy=hidden",t.dropdownAttrs,()=>{h1(t.items,Z)}),h=r=>{let d=r.target;!a.contains(d)&&(t.closeOnAnchorClick||!t.anchor.contains(d))&&Z()},e=r=>{(r.key==="Escape"||r.key==="Tab")&&(r.preventDefault(),Z())},p=u.peek(o1,"path");u(()=>{o1.path!==p&&!w1(o1.path)&&Z()}),document.addEventListener("click",h,!0),document.addEventListener("keydown",e,!0),u.clean(()=>{document.removeEventListener("click",h,!0),document.removeEventListener("keydown",e,!0)}),requestAnimationFrame(()=>{if(!document.body.contains(a))return;let r=t.at?{left:t.at.x,right:t.at.x,top:t.at.y,bottom:t.at.y}:t.anchor.getBoundingClientRect();A2(a,r),j(a,".s-menu-item[aria-current=page]")})});function V2(t){u("nav.s-menu-inline",t.attrs,()=>h1(t.items,t.onLeafSelect))}function H1(t){return U.opts=t,Z}function A1(t){let a=null;u.clean(()=>{U.opts?.anchor===a&&Z()}),u("contextmenu=",h=>{h.preventDefault(),a=h.currentTarget,H1({items:t.items,anchor:a,at:{x:h.clientX,y:h.clientY},closeOnAnchorClick:!0,dropdownAttrs:t.dropdownAttrs})})}function k2(t){let a=null;u.clean(()=>{U.opts?.anchor===a&&Z()}),O({icon:d1,...t.button?.content==null?{ariaLabel:"Open menu"}:null,attrs:".neutral",...t.button,click:h=>{if(a=h.currentTarget,U.opts?.anchor===a){Z();return}H1({items:t.items,anchor:a,dropdownAttrs:t.dropdownAttrs})}})}import H from"aberdeen";import G from"aberdeen";function V1(t={}){I(t,(a,h)=>{G("input.s-input",t.inputAttrs,()=>{G("type=",t.type??"text"),t.placeholder!=null&&G("placeholder=",t.placeholder),t.autocomplete!=null&&G("autocomplete=",t.autocomplete),t.value!=null&&!t.bind&&G("value=",t.value),t.input&&G("input=",t.input),t.change&&G("change=",t.change),_(t,a,h,t.bind)})})}H.insertGlobalCss({".s-backdrop":{"&":"position:fixed inset:0 z-index:200 display:block background: rgba(0,0,0,0.55); transition: opacity 0.4s ease-in-out;","&.hidden":"opacity:0 pointer-events:none"},".s-dialog":{"&":"position:fixed z-index:200 top:50% left:50% display:flex flex-direction:column transform:translate(-50%,-50%) min-width:20rem max-width:min(90vw,44rem) max-height:min(88vh,800px) r: $s-radius-lg; overflow:hidden transition: opacity 0.2s ease-out, transform 0.2s ease-out;","> header":"display:flex align-items:center gap:$2 padding: $2 $3; border:0 border-bottom: 1px solid $s-faint; r:0 font-weight:600 flex-shrink:0","> footer":"display:flex align-items:center justify-content:flex-end gap:$2 padding: $2 $3; border:0 border-top: 1px solid $s-faint; r:0 flex-shrink:0","> div":"p:$3 gap:$3 display:flex flex-direction:column overflow-y:auto flex:1 min-height:0","&.hidden":"opacity:0 pointer-events:none transform: translate(-50%, calc(-50% + 20px)); pointer-events:none"}});var K=H.proxy({}),k1=0,_1=H.derive(()=>{let t=Object.keys(K);if(t.length)return t[t.length-1]});function L1(){return _1.value!=null}F(()=>{H.onEach(K,({resolve:t,opts:a},h)=>{let e=()=>{delete K[h]};H.clean(()=>{a.onClose?.(),t()});let p=H.derive(()=>_1.value!=h);H("div.s-backdrop create=hidden destroy=hidden .hidden=",p,"click=",()=>{a.allowCancel!==!1&&e()});let r=H("div.s-dialog.neutral.s-s.extra-shadow create=hidden destroy=hidden",a.attrs,()=>{H(()=>{a.header!=null&&H("header.s-s.neutral",a.headerAttrs,()=>v(a.header))}),H("div",a.contentAttrs,()=>{v(a.content,e)}),H(()=>{a.footer!=null&&H("footer.s-s.neutral",a.footerAttrs,()=>v(a.footer))})});requestAnimationFrame(()=>{document.body.contains(r)&&j(r)})})});function i1(t){k1||document.addEventListener("keydown",h=>{if(h.key!=="Escape"||h.defaultPrevented)return;let e=H.unproxy(K);for(let p=k1;p>0;p--)if(e[p]){h.preventDefault(),e[p].opts.allowCancel!==!1&&delete K[p];break}});let a=++k1;return t.cancelWithScope!==!1&&H.clean(()=>{delete K[a]}),new Promise(h=>{K[a]={resolve:h,opts:t}})}function L2(t,a={}){return i1({header:"Alert",allowCancel:!0,content:h=>{H("p",()=>{H("#",t)}),W({layout:"spaced",attrs:"align-self:flex-end",content:()=>{O({content:"OK",click:h})}})},...a})}function C2(t,a={}){return new Promise(h=>{let e=!1;i1({header:"Confirm",allowCancel:!0,content:p=>{H("p",()=>{H("#",t)}),W({layout:"spaced",attrs:"align-self:flex-end",content:()=>{O({content:"Cancel",attrs:".neutral",click:p}),O({content:"OK",click:()=>{e=!0,p()}})}})},...a,onClose:()=>{h(e),a.onClose?.()}})})}function z2(t,a="",h={}){return new Promise(e=>{let p=null;i1({header:"Input",allowCancel:!0,content:r=>{H("p",()=>{H("#",t)});let d=H.proxy({value:a});H("form display:contents",()=>{H("submit=",o=>{o.preventDefault(),p=d.value,r()}),V1({bind:H.ref(d,"value")}),W({layout:"spaced",attrs:"align-self:flex-end",content:()=>{O({content:"Cancel",attrs:".neutral",type:"button",click:r}),O({content:"OK",type:"submit"})}})})},...h,onClose:()=>{e(p),h.onClose?.()}})})}import l,{OPAQUE as J1}from"aberdeen";import*as w from"aberdeen/route";import A from"aberdeen";var $2=z('<path d="m15 18-6-6 6-6"/>'),S2=z('<path d="m9 18 6-6-6-6"/>');A.insertGlobalCss({".s-strip":{"&":"position:relative display:flex min-width:0","> .s-strip-row":"display:flex align-items:center flex:1 min-width:0 overflow-x:auto overflow-y:hidden scrollbar-width:none scroll-behavior:smooth","> .s-strip-row::-webkit-scrollbar":"display:none","> .s-strip-btn":"position:absolute top:0 bottom:0 z-index:1 display:none align-items:center justify-content:center width:2.4em border:0 padding:0 cursor:pointer fg:$s-muted transition: color 0.15s;","> .s-strip-btn:hover":"fg:$s-text","> .s-strip-btn-left":"left:0 justify-content:flex-start background: linear-gradient(to right, $s-bg 45%, transparent)","> .s-strip-btn-right":"right:0 justify-content:flex-end background: linear-gradient(to left, $s-bg 45%, transparent)","&.s-can-left > .s-strip-btn-left, &.s-can-right > .s-strip-btn-right":"display:flex"},".s-tabs":{"&":"display:flex flex-direction:column gap:$3",".s-tabbar":"border-bottom: 1px solid $s-faint;",".s-tablist":"gap:$1 align-items:stretch margin-bottom:-1px",".s-tab":"display:inline-flex align-items:center gap:$2 cursor:pointer background:transparent border:0 color: $s-muted; font-weight:600 padding: 0.6em 0.9em; white-space:nowrap border-bottom: 3px solid transparent; transition: color 0.15s, background 0.15s, border-color 0.15s;",".s-tab:hover:not(:disabled), .s-tab[aria-selected=true]":"color: $s-text;",".s-tab:focus-visible":"outline:none box-shadow: inset 0 0 0 2px $s-focus; r: $s-radius;",".s-tab[aria-selected=true]":"border-image: $s-gradient 1;",".s-tabpanel":"display:block"}});function s1(t){A("div.s-strip",t.attrs,()=>{let a=A("div.s-strip-row",t.stripAttrs,()=>v(t.content));Q1(a,-1),Q1(a,1),O2(a)})}function l1(t){let a=t.parentElement;if(!a||!t.isConnected)return;let h=parseFloat(getComputedStyle(a).fontSize)*2.6,e=t.getBoundingClientRect(),p=a.getBoundingClientRect();e.left<p.left+h?a.scrollBy({left:e.left-p.left-h,behavior:"smooth"}):e.right>p.right-h&&a.scrollBy({left:e.right-p.right+h,behavior:"smooth"})}function P2(t){let a=B("tabs"),h=(r,d)=>r.id??String(d),e=t.bind??A.proxy(h(t.tabs[0]??{label:""},0));t.tabs.length>0&&!t.tabs.some((r,d)=>h(r,d)===A.peek(()=>e.value))&&(e.value=h(t.tabs[0],0));let p=(r,d)=>{r.disabled||(e.value=h(r,d))};A("div.s-tabs",t.attrs,()=>{s1({attrs:".s-tabbar",stripAttrs:".s-tablist role=tablist",content:()=>{t.tabs.forEach((r,d)=>{let o=h(r,d),c=A("button.s-tab type=button role=tab",()=>{A("id=",`${a}-tab-${o}`,"aria-controls=",`${a}-panel-${o}`),A(()=>{let i=e.value===o;A("aria-selected=",i?"true":"false"),A("tabindex=",i?"0":"-1"),i&&requestAnimationFrame(()=>l1(c))}),r.disabled&&A("disabled=true"),A("click=",()=>p(r,d)),A("keydown=",i=>E2(i,t.tabs,d,p)),v(r.icon),v(r.label)})})}}),A("div.s-tabpanel role=tabpanel",t.contentAttrs,()=>{A(()=>{let r=e.value,d=t.tabs.findIndex((c,i)=>h(c,i)===r),o=t.tabs[d]??t.tabs[0];o&&(A("id=",`${a}-panel-${h(o,d)}`,"aria-labelledby=",`${a}-tab-${h(o,d)}`),v(o.content))})})})}function Q1(t,a){A(`button.s-strip-btn.s-strip-btn-${a<0?"left":"right"} type=button`,()=>{A("tabindex=-1 aria-hidden=true"),A("click=",()=>t.scrollBy({left:a*t.clientWidth*.8,behavior:"smooth"})),(a<0?$2:S2)({size:"1.1em"})})}function O2(t){let a=t.parentElement;if(!a||typeof ResizeObserver>"u")return;let h=()=>{let r=t.scrollWidth-t.clientWidth;a.classList.toggle("s-can-left",t.scrollLeft>1),a.classList.toggle("s-can-right",t.scrollLeft<r-1)};t.addEventListener("scroll",h,{passive:!0});let e=new ResizeObserver(h);e.observe(t);let p=typeof MutationObserver>"u"?void 0:new MutationObserver(r=>{for(let d of r){for(let o of d.addedNodes)o instanceof Element&&e.observe(o);for(let o of d.removedNodes)o instanceof Element&&e.unobserve(o)}h()});p?.observe(t,{childList:!0});for(let r of Array.from(t.children))e.observe(r);h(),A.clean(()=>{t.removeEventListener("scroll",h),e.disconnect(),p?.disconnect()})}function E2(t,a,h,e){let p=h;if(t.key==="ArrowRight"||t.key==="ArrowDown")p=(h+1)%a.length;else if(t.key==="ArrowLeft"||t.key==="ArrowUp")p=(h-1+a.length)%a.length;else if(t.key==="Home")p=0;else if(t.key==="End")p=a.length-1;else return;t.preventDefault();let r=p>=h?1:-1;for(let d=0;d<a.length;d++){let o=a[p];if(o&&!o.disabled){e(o,p),t.currentTarget?.parentElement?.children[p]?.focus();return}p=(p+r+a.length)%a.length}}import V from"aberdeen";import{grow as q2,shrink as T2}from"aberdeen/transitions";V.insertGlobalCss({".s-toasts":"position:fixed bottom:$3 right:$3 z-index:400 display:flex flex-direction:column gap:$2 pointer-events:none max-width:min(90vw,24rem) w:24rem",".s-toast":{"&":"display:flex align-items:flex-start gap:$2 padding: $3; pointer-events:auto position:relative overflow:hidden",".s-toast-body":"display:flex flex-direction:column gap:$1 flex:1 min-width:0",".s-toast-title":"font-weight:700 line-height:1.3",".s-toast-close":"cursor:pointer border:0 background:transparent fg:$s-muted font-size:1.1em line-height:1 padding: 0 0.15em; r:4px flex-shrink:0 align-self:flex-start",".s-toast-close:hover":"fg:$s-text",".s-toast-close:focus-visible":"outline:none box-shadow: 0 0 0 3px $s-focus; fg:$s-text",".s-toast-progress":"position:absolute bottom:0 left:0 right:0 height:2px background:$s-accent width:100%"}});var D2=0,e1=V.proxy({});F(()=>{V.peek(()=>V.isEmpty(e1))&&V.isEmpty(e1)||V("div.s-toasts",()=>{V.onEach(e1,t=>{let{opts:a,id:h}=t,e=a.type==="danger"||a.type==="warning"?"alert":"status",p=a.type==null||a.type==="neutral"?"neutral":a.type,r=a.duration??6e3,d,o=null,c=()=>{clearTimeout(d),o&&(o.style.transition="none",o.style.width="100%",o.offsetWidth,o.style.transition=`width ${r}ms linear`,o.style.width="0%"),d=setTimeout(()=>C1(h),r)},i=()=>{clearTimeout(d),d=void 0,o&&(o.style.transition="none",o.style.width="100%")};V.clean(()=>clearTimeout(d)),V(`div.s-toast.s-s.${p}.extra-shadow aria-live=polite role=${e}`,"create=",q2,"destroy=",T2,a.attrs,()=>{r>0&&(V("mouseenter=",i),V("mouseleave=",c)),V("div.s-toast-body",()=>{V(()=>{a.title!=null&&V("div.s-toast-title",()=>v(a.title))}),V("div.s-toast-msg",()=>v(a.message))}),V(()=>{a.dismissible!==!1&&V("button.s-toast-close type=button aria-label=Dismiss",()=>{V("#\xD7"),V("click=",()=>C1(h))})}),r>0&&(o=V("div.s-toast-progress"))}),r>0&&requestAnimationFrame(c)})})});function C1(t){delete e1[t]}function M1(t){let a=++D2;return e1[a]={id:a,opts:t},()=>C1(a)}var S1={integer(t){if(!/^(0|-?[1-9]\d*)$/.test(t))return;let a=Number(t);return Number.isSafeInteger(a)?a:void 0}};function q(t){let a=String(t).replace(/\/+$/,"");return a.startsWith("/")||(a=`/${a}`),a}function p1(t){let a=q(t);return a==="/"?[]:a.slice(1).split("/")}function Y1(t){let a=p1(t),h=a.map((e,p)=>{if(!e.startsWith("[")||!e.endsWith("]"))return{kind:"lit",value:e};let r=/^\[\.\.\.([A-Za-z_$][\w$]*)\]$/.exec(e);if(r){if(p!==a.length-1)throw new Error(`Staffa: "${e}" must be the last segment of route "${t}"`);return{kind:"rest",name:r[1]}}let d=/^\[([A-Za-z_$][\w$]*)(?:=([A-Za-z_$][\w$]*))?\]$/.exec(e);if(!d)throw new Error(`Staffa: malformed param "${e}" in route "${t}"`);let[,o,c]=d;if(c&&!(c in S1))throw new Error(`Staffa: unknown matcher "${c}" in route "${t}" (known: ${Object.keys(S1).join(", ")})`);return{kind:"param",name:o,matcher:c}});return{key:t,segs:h}}function R2(t){try{return decodeURIComponent(t)}catch{return t}}function z1(t,a){let h={};for(let e=0;e<t.segs.length;e++){let p=t.segs[e];if(p.kind==="rest")return e>=a.length?null:(h[p.name]=a.slice(e).join("/"),h);if(e>=a.length)return null;let r=a[e];if(p.kind==="lit"){if(r!==p.value)return null}else if(p.matcher){let d=S1[p.matcher](r);if(d===void 0)return null;h[p.name]=d}else h[p.name]=R2(r)}return t.segs.length===a.length?h:null}var a2=250,Z2=300,B2=1280,F2=360,t2=2;l.insertGlobalCss({":root":`--s-panel-ms:${a2}ms`,".s-panels":"flex:1 min-width:0 min-height:0 position:relative overflow:hidden isolation:isolate "+Y,".s-panel":{"&":"position:absolute top:0 bottom:0 left:0 display:flex flex-direction:column "+Y+" visibility:visible transition: left var(--s-panel-ms) ease, transform var(--s-panel-ms) ease-out, opacity var(--s-panel-ms) linear, visibility 0s;","&.s-panel-sep::before":"content:'' position:absolute left:0 top:0.6rem bottom:0.6rem width:1px z-index:1 background: linear-gradient(to bottom, transparent, $s-faint 18%, $s-faint 82%, transparent);","&.s-panel-enter":"opacity:0 transition:none transform: translateX(8cqw);","&.s-panel-closing":"opacity:0 pointer-events:none transform: translateX(8cqw);","&.s-panel-hidden, &.s-panel-parked":"opacity:0 visibility:hidden transition: left var(--s-panel-ms) ease, transform var(--s-panel-ms) ease-out, opacity var(--s-panel-ms) linear, visibility var(--s-panel-ms);","&.s-panel-hidden":"transform: translateX(-8cqw);","&.s-panel-parked":"transform: translateX(8cqw);"},".s-panel > .s-content":"flex:1 min-height:0 overflow-y:auto overflow-x:hidden p:$3",".s-panel-actions":"display:flex align-items:center justify-content:flex-end gap:$1 flex-shrink:0 padding: $3 $3 0;",".s-crumbs > .s-strip-row":"gap:$m1",".s-crumb":{"&":"flex-shrink:0 font-size:0.85em line-height:1.5 fg:$s-muted text-decoration:none white-space:nowrap max-width:14rem overflow:hidden text-overflow:ellipsis transition: color 0.12s;","&.s-crumb-on":"font-weight:600 fg:$s-text","a&:hover":"filter:none color: color-mix(in lab, $s-primary 33%, $s-text);","svg.s-crumb-pin":"vertical-align:-0.12em margin-right:0.3em opacity:0.8 fill:currentColor","svg.s-crumb-unsaved":"vertical-align:0.08em margin-right:0.3em fill:currentColor"},"svg.s-crumb-sep":"flex-shrink:0 opacity:0.4",".s-main.s-shell-snap .s-panel":"transition:none",".s-panel-loading":{"&":"position:absolute inset:0 display:flex align-items:center justify-content:center gap:$1 pointer-events:none",i:"width:0.5rem height:0.5rem r:50% background:$s-muted opacity:0.45 animation: s-panel-pulse 1s ease-in-out infinite;","i:nth-child(2)":"animation-delay:0.15s","i:nth-child(3)":"animation-delay:0.3s"},"@keyframes s-panel-pulse":{"0%, 100%":"opacity:0.25 transform:scale(0.8)","50%":"opacity:0.7 transform:scale(1)"}});var $1=!1,x1=class{[J1]=!0;compiled;ancestors;opts;$state=l.proxy({live:[],focus:0});$open=l.proxy({});nextOrder=0;containerEl;geom;lastBodyW=-1;layoutQueued=!1;timers=new Set;intent=null;settling=null;lastSeen=null;queued=null;constructor(a){if($1)throw new Error("Staffa: only one routed S.main() (one with `routes`) can be active at a time");$1=!0,this.opts=a,this.compiled=Object.entries(a.routes).map(([h,e])=>({...Y1(h),draw:e})),this.ancestors=Object.entries(a.ancestors??{}).filter(h=>h[1]!=null).map(([h,e])=>({...Y1(h),fn:e})),l(()=>{let h=this.computeTarget(),e={...w.current.search},p=w.current.hash;l.peek(()=>{let r=this.lastSeen;if(r&&r.path!==w.current.path){let d=this.$state.live.find(o=>o.path===r.path);d&&(d.search=r.search,d.hash=r.hash)}this.lastSeen={path:w.current.path,search:e,hash:p},this.propose(h),Array.isArray(w.current.state.panels)||Object.assign(w.current.state,this.stateFor({stack:this.paths(),focus:this.$state.focus}))})}),this.interceptLinks(),this.watchTitle(),this.guardTabClose(),l.clean(()=>{for(let h of this.timers)clearTimeout(h);this.timers.clear(),this.queued?.settle(!1),this.queued=null,$1=!1})}resolve(a){let h=p1(a);for(let e of this.compiled){let p=z1(e,h);if(p)return{draw:e.draw,params:p}}return{draw:this.opts.notFound??X2,params:{}}}matches(a){let h=p1(a);return this.compiled.some(e=>z1(e,h)!=null)}deriveStack(a){let h=q(a),e=this.askAncestors(h),p=e?e.map(q):this.prefixesOf(h),r=[];for(let d of p)d!==h&&!r.includes(d)&&this.matches(d)&&r.push(d);return r.push(h),r}askAncestors(a){let h=p1(a);for(let e of this.ancestors){let p=z1(e,h);if(p)return e.fn(p,a)??void 0}}prefixesOf(a){let h=p1(a),e=[];for(let p=1;p<h.length;p++)e.push("/"+h.slice(0,p).join("/"));return e}pinnedIn(a,h){return a.filter(e=>h.includes(e)?!1:this.$state.live.find(p=>p.path===e)?.$panel.pinned===!0)}unsavedAt(a){return this.$state.live.find(h=>h.path===a)?.$panel.unsaved===!0}targetFor(a,h){let e=Array.isArray(h?.panels)?h.panels.map(String):null;if(e){let p=Array.isArray(h.parked)?h.parked.map(String):[],r=q(a),d=new Set([r]),o=i=>i.map(q).filter(f=>!d.has(f)&&!!d.add(f)),c=o(e);return{stack:[...c,r,...o(p)],focus:c.length}}return l.peek(()=>{let p=this.deriveStack(a).slice(0,-1),r=[...p,...this.pinnedIn(this.paths(),[...p,q(a)]),q(a)];return{stack:r,focus:r.length-1}})}computeTarget(){return this.targetFor(w.current.path,w.current.state)}paths(){return this.$state.live.map(a=>a.path)}propose(a){let h=this.$state.live.filter(e=>!a.stack.includes(e.path)&&e.$panel.unsaved).map(e=>e.path);h.length&&(a={stack:[...a.stack,...h],focus:a.focus}),!(U2(this.paths(),a.stack)&&a.focus===this.$state.focus)&&this.commit(a,w.current.nav)}commit(a,h){this.geom=void 0;let e=w.current.state.pinned,p=new Set(Array.isArray(e)?e.map(String):[]),r=new Map(this.$state.live.map(o=>[o.path,o])),d=[];for(let o of a.stack){let c=r.get(o);if(c){r.delete(o),d.push(c);continue}let i=this.createEntry(o,d.length<=a.focus,p.has(o));h!=="load"&&h!=="back"&&(i.enter=!0),d.push(i),this.$open[o]=i}for(let o of r.values())this.beginClose(o);this.$state.live=d,this.$state.focus=Math.min(a.focus,d.length-1),this.scheduleLayout()}createEntry(a,h,e){let{draw:p,params:r}=this.resolve(a),d={[J1]:!0,order:this.nextOrder++,path:a,draw:p,$ui:l.proxy({holding:!1}),maxWidth:"full",width:0};return d.$panel=l.proxy({stack:this,params:r,path:a,width:0,visible:h,pinned:e||void 0,close:()=>this.closePath(d.path)}),d}beginClose(a){a.closing=!0,a.$panel.visible=!1,a.el&&(a.el.style.zIndex=String(t2*this.$state.live.indexOf(a))),delete this.$open[a.path]}playExit(a,h){if(!a.closing){h.remove();return}h.classList.add("s-panel-closing"),h.setAttribute("inert","");let e=()=>{clearTimeout(p),this.timers.delete(p),h.remove()};h.addEventListener("transitionend",r=>{r.target===h&&r.propertyName==="opacity"&&e()});let p=setTimeout(e,a2+80);this.timers.add(p)}intended(){return this.intent??{stack:this.paths(),focus:this.$state.focus}}stateFor(a){return{panels:a.stack.slice(0,a.focus),parked:a.stack.slice(a.focus+1),pinned:this.pinnedPaths()}}pinnedPaths(){return this.$state.live.filter(a=>a.$panel.pinned).map(a=>a.path)}issue(a,h){return this.intent=a,this.settling?(this.queued?.settle(!1),new Promise(e=>{this.queued={run:h,settle:e}})):this.start(h)}start(a){let h=p=>{this.settling=null;let r=this.queued;return this.queued=null,p&&r?this.start(r.run).then(r.settle,()=>r.settle(!1)):(this.intent=null,r?.settle(!1)),p},e=Promise.resolve(a()).then(h,p=>(console.error(p),h(!1)));return this.settling=e,e}focusAt(a,h,e){let p=this.intended();if(a<0||a>=p.stack.length||a===p.focus)return Promise.resolve(!1);let r={stack:p.stack,focus:a},d=p.stack[a];return this.issue(r,()=>{let o=this.$state.live.find(c=>c.path===d);return w.go({path:d,search:h??o?.search,hash:e??o?.hash,state:this.stateFor(r)})})}back(){return l.peek(()=>{let a=this.intended();return a.focus===a.stack.length-1&&!this.unsavedAt(a.stack[a.focus])?this.closePath(a.stack[a.focus]??""):a.focus===0?Promise.resolve(!1):this.focusAt(a.focus-1)})}closePath(a){return l.peek(()=>{let h=this.intended(),e=h.stack.indexOf(q(a));if(e<0||h.stack.length<2||this.unsavedAt(h.stack[e]))return Promise.resolve(!1);let p=h.stack.filter((i,f)=>f!==e),r=e===h.focus?Math.max(0,e-1):h.focus-(e<h.focus?1:0),d={stack:p,focus:r};if(e===h.focus&&e===h.stack.length-1){let i=this.$state.live.find(m=>m.path===p[r]),f={};i?.search&&(f.search=i.search),i?.hash&&(f.hash=i.hash);let n=p.filter(m=>this.$state.live.find(y=>y.path===m)?.$panel.pinned===!0);return this.issue(d,()=>Promise.resolve(w.back({path:p[r],state:{panels:p.slice(0,r),parked:[]}},f)).then(m=>(m&&(w.current.state.pinned=n),m)))}let o=p[r],c=o!==h.stack[h.focus];return this.issue(d,()=>{let i=c?this.$state.live.find(f=>f.path===o):void 0;return w.go({path:o,search:c?i?.search:{...w.current.search},hash:c?i?.hash:w.current.hash,state:this.stateFor(d)})})})}navigate(a,h,e=!1,p){return l.peek(()=>{let r;try{r=new URL(a,location.href)}catch{return Promise.resolve(!1)}let d=q(r.pathname),o=Object.fromEntries(new URLSearchParams(r.search)),c=r.hash,i=this.intended(),f=p?-1:i.stack.indexOf(d);if(f>=0&&f!==i.focus)return this.focusAt(f,r.search?o:void 0,c||void 0);if(f>=0)return r.search===location.search&&(r.hash||"")===(location.hash||"")?Promise.resolve(!0):this.issue(i,()=>w.go({path:d,search:o,hash:c,state:this.stateFor(i)}));let n=h==null?-1:i.stack.indexOf(h),m=p?p.map(q).filter((s,b,C)=>s!==d&&C.indexOf(s)===b):n<0?this.deriveStack(d).slice(0,-1):i.stack.slice(0,e?n:n+1),y=[...m,...this.pinnedIn(i.stack,[...m,d,e?h:null])],g={stack:[...y,d],focus:y.length};return this.issue(g,()=>w.go({path:d,search:o,hash:c,state:this.stateFor(g)}))})}pushPath(a,h){return l.peek(()=>{let e=this.intended();return this.navigate(a,e.stack[e.focus]??null,h)})}interceptLinks(){w.interceptLinks((a,h)=>{let e=h.getAttribute("data-panel")??this.opts.linkNavigation,p=null;if(e!=="open"){let r=h.closest(".s-panel");r?p=this.$state.live.find(d=>d.el===r)?.path??null:h.closest(".s-panel-origin")&&(p=this.$state.live[this.$state.focus]?.path??null)}return this.navigate(a.href,p,e==="replace"),!0})}get currentPanel(){return this.$state.live[this.$state.focus]?.$panel}get panels(){return this.$state.live.map(a=>a.$panel)}get currentPanelIndex(){return this.$state.focus}pushPanel(a){return this.pushPath(a,!1)}replacePanel(a){return this.pushPath(a,!0)}openPanelStack(a,h){return this.navigate(a,null,!1,h)}closePanel(a){return l.peek(()=>{let h=this.intended();return this.closePath(a??h.stack[h.focus]??"")})}setColumns(a){this.opts.columns!==a&&(this.opts.columns=a,this.scheduleLayout())}setLinkNavigation(a){this.opts.linkNavigation=a}drawCrumbs(){s1({attrs:".s-crumbs role=navigation aria-label=Breadcrumbs",content:()=>{l(()=>{let a=this.panels.map(p=>p.path),h=this.currentPanelIndex,e;for(let p=0;p<a.length;p++){p&&I1({size:"0.85em",attrs:".s-crumb-sep"});let r=this.drawCrumb(a[p],p,p===h);p===h&&(e=r)}requestAnimationFrame(()=>{e&&l1(e)})})}})}drawCrumb(a,h,e){let p=this.$state.live[h];return l(e?"span.s-crumb aria-current=page":"a.s-crumb",()=>{e||l("href=",a),l(()=>{p?.$panel.visible&&l(".s-crumb-on")}),l(()=>{p?.$panel.unsaved&&R1({size:"0.45em",attrs:".s-crumb-unsaved"})}),l(()=>{p?.$panel.pinned&&u1({size:"0.85em",attrs:".s-crumb-pin"})}),l(()=>{l("#",p?.$panel.title??p?.$ui.fallback??(a.split("/").pop()||a))}),A1({items:[{label:"Open in new tab",icon:Z1,click:()=>{window.open(a,"_blank","noopener")}},{label:"Copy link",icon:B1,click:()=>{W2(a)}},{separator:!0},{label:()=>{l(()=>{l("#",p?.$panel.pinned?"Unpin":"Pin")})},icon:()=>{l(()=>{(p?.$panel.pinned?F1:u1)()})},click:()=>{p&&this.togglePin(p)}},{label:"Close",icon:Q,disabled:p?.$panel.unsaved===!0,click:()=>{this.closePath(a)}}]})})}togglePin(a){a.$panel.pinned=!a.$panel.pinned||void 0,w.current.state.pinned=this.pinnedPaths()}watchTitle(){let a=document.title;l(()=>{let h=this.$state.live[this.$state.focus],e=h?.$panel.title??h?.$ui.fallback,p=typeof this.opts.title=="string"?this.opts.title:void 0,r=this.$state.live.some(o=>o.$panel.unsaved),d=e&&p?`${e} \xB7 ${p}`:e||p;d&&(document.title=(r?"\u2022 ":"")+d)}),l.clean(()=>{document.title=a})}guardTabClose(){if(typeof window>"u")return;let a=!1,h=()=>{a=!0},e=p=>{a=!1;let r=this.$state.live.find(o=>o.$panel.unsaved);if(!r)return;p.preventDefault(),p.returnValue=!0;let d=r.path;setTimeout(()=>{if(a)return;let o=this.$state.live.find(c=>c.path===d);o&&!o.$panel.visible&&this.focusAt(this.intended().stack.indexOf(d))},0)};l(()=>{this.$state.live.some(p=>p.$panel.unsaved)&&(window.addEventListener("beforeunload",e),window.addEventListener("pagehide",h),l.clean(()=>{window.removeEventListener("beforeunload",e),window.removeEventListener("pagehide",h)}))})}drawColumns(){let a=l("div.s-panels role=main",()=>{this.containerEl=l(),l.onEach(this.$open,h=>this.drawPanel(h),h=>h.order)});if(typeof ResizeObserver<"u"){let h=new ResizeObserver(()=>this.layout());h.observe(a);let e=a.parentElement?.parentElement;e&&h.observe(e),l.clean(()=>h.disconnect())}l.clean(()=>{this.containerEl===a&&(this.containerEl=void 0)}),this.scheduleLayout()}drawPanel(a){let h;l(()=>{let e=a.$panel.maxWidth;a.maxWidth=e==="half"||e==="screen"?e:"full";let p=this.roomFor(a.maxWidth);p&&(a.width=p,l.peek(a.$panel,"width")!==p&&(a.$panel.width=p),h&&(h.style.width=`${p}px`,this.scheduleLayout()))}),h=l(`section.s-panel${a.width?` w:${a.width}px`:""}`,"destroy=",e=>this.playExit(a,e),()=>{l(()=>this.drawActions(a)),l("div.s-content",()=>{if(a.draw(a.$panel),w.persistScroll(a.path),l.peek(a.$panel,"title")==null){let e=N2(l());e&&l.peek(a.$ui,"fallback")!==e&&(a.$ui.fallback=e)}}),l(()=>{!a.$panel.loading||a.$ui.holding||l("div.s-panel-loading aria-hidden=true",()=>{l("i"),l("i"),l("i")})})}),a.el=h,a.placed=!1,h.style.transition="none",l.clean(()=>{a.el===h&&(a.el=void 0)}),l(()=>{a.$panel.loading,this.scheduleLayout()}),this.scheduleLayout()}drawActions(a){this.opts.$shell.narrow||a.$panel.actions==null||l("div.s-panel-actions",()=>v(a.$panel.actions))}scheduleLayout(){this.layoutQueued||(this.layoutQueued=!0,requestAnimationFrame(()=>{this.layoutQueued=!1,this.layout()}))}measure(){let a=this.containerEl,h=a?.parentElement,e=h?.parentElement;if(!a||!h||!e)return;let p=e.getBoundingClientRect().width;if(!p)return;let r=0;for(let c of h.children)c!==a&&(r+=c.getBoundingClientRect().width);let d=Math.max(0,Math.min(B2,p)-r),o=d/2;return{total:p,chrome:r,half:o>=F2?o:d,full:d,screen:Math.max(0,p-r)}}geometry(){return this.geom??=this.measure()}roomFor(a){return this.geometry()?.[a]??0}layout(){let a=this.containerEl,h=a?.closest(".s-main");if(!a||!h)return;let e=this.$state.live,p=e.length;if(!p||e.some(s=>!s.el))return;this.geom=void 0;let r=this.geometry();if(!r)return;let d=this.opts.columns!=="single",o=this.lastBodyW!==r.total;o&&(this.lastBodyW=r.total,h.classList.add("s-shell-snap"));let c=s=>r[s.maxWidth],i=Math.min(this.$state.focus,p-1),f=i,n=c(e[i]);if(d)for(let s=i-1;s>=0;s--){let b=n+c(e[s]);if(b>r.screen)break;n=b,f=s}let m=Math.min(r.screen,Math.max(r.full,n));for(let s=f;s<=i;s++)e[s].width=c(e[s]);for(let s of e)s.width||(s.width=c(s));h.style.setProperty("--s-shell-w",`${r.chrome+m}px`);let y=[],g=0;for(let s=0;s<p;s++){let b=e[s],C=b.el,S=s>=f&&s<=i;I2(C,S?g:s>i?m:0,b.width,t2*s+1),b.$panel.visible!==S&&(b.$panel.visible=S),b.$panel.width!==b.width&&(b.$panel.width=b.width),S&&(g+=b.width),C.classList.toggle("s-panel-sep",S&&s>f),C.classList.toggle("s-panel-hidden",s<f),C.classList.toggle("s-panel-parked",s>i),C.toggleAttribute("inert",!S),!b.placed&&(y.push(b),!b.$panel.loading||b.holdDone?b.$ui.holding=!1:b.$ui.holding||(b.$ui.holding=!0,this.holdEnter(b)),b.enter&&S&&C.classList.add("s-panel-enter"))}(y.length||o)&&a.offsetWidth,o&&h.classList.remove("s-shell-snap");for(let s of y)s.$ui.holding||(s.el.style.transition="",s.el.classList.remove("s-panel-enter"),s.enter=!1,s.placed=!0)}holdEnter(a){let h=setTimeout(()=>{this.timers.delete(h),a.holdDone=!0,a.$ui.holding&&(a.$ui.holding=!1,this.scheduleLayout())},Z2);this.timers.add(h)}};function I2(t,a,h,e){t.style.left=`${a}px`,t.style.width=`${h}px`,t.style.zIndex=String(e)}function U2(t,a){return t.length===a.length&&t.every((h,e)=>h===a[e])}function N2(t){let a=document.createTreeWalker(t,NodeFilter.SHOW_TEXT);for(let h=a.nextNode();h;h=a.nextNode()){let e=h.textContent.trim();if(e)return e.length>48?`${e.slice(0,47).trimEnd()}\u2026`:e}}async function W2(t){let a=new URL(t,location.href).href;try{await navigator.clipboard.writeText(a),M1({message:"Link copied."})}catch{M1({message:"Couldn't copy the link.",type:"danger"})}}function X2(t){l("p fg:$s-muted",()=>l("#",`No panel at ${t.path}`))}x.insertGlobalCss({".s-main":{"&":"display:flex flex-direction:column min-height:100vh max-height:100vh container-type:inline-size","body > &":"margin: calc(-1 * $3)","> header":"border:0 border-bottom: 1px solid $s-faint; r:0 position:sticky top:0 z-index:10","> footer":"border-top: 1px solid $s-faint; fg:$s-muted","> header > .s-bar, > footer > .s-bar":"display:flex align-items:center width:100% margin-inline:auto gap:$3 padding: $2 $3;","> header .s-logo, > header .s-nav-trigger":"display:flex align-items:center flex-shrink:0","> header .s-nav-trigger":"margin-left:-0.375rem","> header .s-logo":"font-size:1.4em background: $s-gradient; -webkit-background-clip:text; background-clip:text; color:transparent;","> header .s-titles":"display:flex flex-direction:column min-width:5rem flex: 0 1 auto;","> header .s-subtitle":"fg:$s-muted font-size:0.85em line-height:1.5 overflow:hidden text-overflow:ellipsis white-space:nowrap","> header .s-title":"font-weight:800 font-size:1.1em line-height:1.2 overflow:hidden text-overflow:ellipsis white-space:nowrap letter-spacing:-0.01em background: $s-gradient; -webkit-background-clip:text; background-clip:text; color:transparent; width:fit-content max-width:100%","> header a.s-logo, > header a.s-title":"text-decoration:none filter:none cursor:pointer","> header .s-menu":"display:flex align-items:center justify-content:flex-end gap:$2 flex: 1 1 auto; min-width:0",".s-body":"flex:1 overflow:hidden display:flex flex-direction:row min-height:0 justify-content:center position:relative",".s-body-inner":"flex:1 min-width:0 display:flex flex-direction:row min-height:0","&.s-nav-right .s-body-inner":"flex-direction:row-reverse",".s-nav-sep":"width:1px flex-shrink:0 align-self:stretch margin: 0.6rem 0; border:0 background: linear-gradient(to bottom, transparent, $s-faint 18%, $s-faint 82%, transparent);",".s-body main":"flex:1 min-width:0 min-height:0 overflow-x:hidden overflow-y:auto display:flex flex-direction:column transition: transform var(--s-panel-ms) ease;",".s-body main.s-slide-in":"transform: translateX(100%); transition:none",".s-body main > .s-content":"width:100% flex:1 p:$3",".s-body main.s-scroll-y":"margin-right:$3","&.s-routed > .s-body > .s-body-inner":"max-width: var(--s-shell-w, 100%);","&.s-routed > header > .s-bar":"max-width: var(--s-shell-w, 100%);","&.s-routed > footer > .s-bar":"max-width: var(--s-shell-w, 100%);","&.s-routed > .s-body > .s-body-inner, &.s-routed > header > .s-bar, &.s-routed > footer > .s-bar":"transition: max-width var(--s-panel-ms) ease;","&.s-routed.s-shell-snap > .s-body > .s-body-inner, &.s-routed.s-shell-snap > header > .s-bar, &.s-routed.s-shell-snap > footer > .s-bar":"transition:none"},".s-nav-panel":{"&":"display:flex flex-direction:column overflow-y:auto flex-shrink:0 max-width:228px padding:$3 gap:$1"},".s-nav-page":{"&":"position:absolute inset:0 z-index:5 display:flex flex-direction:column overflow-y:auto overscroll-behavior:contain border:0 r:0 padding:$2 gap:$1 transition: transform var(--s-panel-ms) ease, visibility var(--s-panel-ms);","&.s-nav-page-off":"transform:translateX(-100%) pointer-events:none visibility:hidden",".s-menu-item":"padding: $2 $3; min-height:3rem font-size:1.05em gap:$3"},[`@container (max-width: ${r1}px)`]:{".s-main .s-nav-panel, .s-main .s-nav-sep":"display:none",".s-main > header > .s-bar":"gap:$1 padding: $1 $2;",".s-content > .s-box":"margin-inline: calc(-1 * $3); r:0 border-inline:0",".s-main .s-body main.s-scroll-y":"margin-right:0"}});function G2(t={}){let a=t.nav,h=t.navPosition??"left",e=x.proxy({open:!1}),p=x.proxy({narrow:typeof document<"u"&&document.documentElement.clientWidth<=r1}),r=t.routes;if(r!=null&&t.content!=null)throw new Error("Staffa: S.main() takes either `content` or `routes`, not both");let d=r?new x1({routes:r,notFound:t.notFound,ancestors:t.ancestors,title:t.title,$shell:p}):null;d&&(x(()=>d.setColumns(t.columns)),x(()=>d.setLinkNavigation(t.linkNavigation)));let o=d&&t.home!==null?t.home??"/":null,c=d?null:t.maxWidth,i=x(`div.s-main${d?".s-routed":""}`,t.attrs,()=>{x(()=>{a==null||!a.items.length||x(`.s-nav-${h}`)}),x(()=>{(d!=null||t.title!=null||t.subtitle!=null||t.logo!=null||t.menu!=null||a!=null&&a.items.length>0)&&x("header.s-s.neutral",t.topbarAttrs,()=>{x("div.s-bar",()=>{x(()=>{c!=null&&x("max-width:",c)}),x(()=>{if(p.narrow&&a!=null&&a.items.length){x("div.s-nav-trigger",()=>J2(a,e));return}t.logo!=null&&x(o!=null?"a.s-logo aria-label=Home":"div.s-logo",()=>{o!=null&&x("href=",o),v(t.logo)})}),x("div.s-titles",()=>{x(()=>{t.title!=null&&x(o!=null?"a.s-title":"div.s-title",()=>{o!=null&&x("href=",o),v(t.title)})}),j2(t,d,a,p)}),x(()=>{let n=p.narrow?d?.currentPanel?.actions:void 0,m=n??t.menu;m!=null&&x(`div.s-menu${n!=null?".s-panel-origin":""}`,()=>v(m))})})})}),x("div.s-body",()=>{x("div.s-body-inner",()=>{x(()=>{c!=null&&x("max-width:",c)}),x(()=>{a==null||!a.items.length||(x(`nav.s-nav-panel.s-nav-${h}`,t.navAttrs,()=>{h1(a.items)}),x("div.s-nav-sep aria-hidden=true"))}),a0(t,d)}),x(()=>{a!=null&&a.items.length&&e.open&&Y2(a,t.navPageAttrs,e,p)})}),x(()=>{t.footer!=null&&x("footer",()=>{x("div.s-bar",()=>{x(()=>{c!=null&&x("max-width:",c)}),v(t.footer)})})})});if(Q2(i,p),a!=null||d){let f=n=>{if(n.key!=="Escape"||n.defaultPrevented||L1()||n1())return;let m=i.querySelector(".s-nav-trigger button");if(e.open){n.preventDefault(),e.open=!1,m?.focus();return}if(d&&d.currentPanelIndex>0){n.preventDefault(),d.back();return}let y=i.querySelector(".s-nav-panel");if(y?.offsetParent!=null){let g=y.querySelector("[aria-current=page]")??y.querySelector(".s-menu-item:not([aria-disabled=true])");g&&(n.preventDefault(),g.focus());return}m&&(n.preventDefault(),m.click())};document.addEventListener("keydown",f),x.clean(()=>document.removeEventListener("keydown",f))}return d??void 0}var v1=null;function K2(){v1?.()}function j2(t,a,h,e){x(()=>{if(t.subtitle!=null&&(a==null||_2(a,h,e))){x("div.s-subtitle",()=>v(t.subtitle));return}a?.drawCrumbs()})}function _2(t,a,h){return h.narrow||a==null||t.panels.length>1?!1:f1(a.items)}function Q2(t,a){if(typeof ResizeObserver>"u")return;let h=new ResizeObserver(e=>{let p=e[0]?.contentBoxSize?.[0],r=p?p.inlineSize:e[0]?.contentRect.width;r!=null&&(a.narrow=r<=r1)});h.observe(t),x.clean(()=>h.disconnect())}function J2(t,a){a1({icon:t.button?.icon??(()=>x(()=>(a.open?Q:d1)())),ariaLabel:t.button?.ariaLabel??"Open navigation",attrs:t.button?.attrs,click:()=>{a.open=!a.open}})}function Y2(t,a,h,e){let p=!1,r=()=>{p=!0,h.open=!1},d=x("nav.s-nav-page.s-s.neutral aria-label=Navigation create=s-nav-page-off destroy=s-nav-page-off",a,()=>h1(t.items,r));v1=r,x.clean(()=>{v1===r&&(v1=null)});let o=x.peek(P1,"path");x(()=>{P1.path!==o&&!w1(P1.path)&&r()});let c=d.closest(".s-main"),i=d.parentElement?.querySelector(":scope > .s-body-inner"),f=i?.querySelector(":scope > main");i?.setAttribute("inert",""),x(()=>{e.narrow||(h.open=!1)}),x.clean(()=>{i?.removeAttribute("inert"),p&&(f&&t0(f),c?.querySelector(".s-nav-trigger button")?.focus())}),requestAnimationFrame(()=>{document.body.contains(d)&&j(d,".s-menu-item[aria-current=page]")})}function t0(t){t.classList.add("s-slide-in"),t.offsetWidth,t.classList.remove("s-slide-in")}function a0(t,a){if(a){a.drawColumns();return}let h=x("main",()=>{x("div.s-content",t.contentAttrs,()=>{v(t.content)})});h0(h)}function h0(t){if(typeof ResizeObserver>"u")return;let a=()=>t.classList.toggle("s-scroll-y",t.offsetWidth>t.clientWidth),h=new ResizeObserver(a);h.observe(t),t.firstElementChild&&h.observe(t.firstElementChild),a(),x.clean(()=>h.disconnect())}import $ from"aberdeen";$.insertGlobalCss({".s-select_wrap":{"&":"position:relative display:block",select:"w:100% cursor:pointer padding-right:2.2em; appearance:none","&::after":"content: '\u25BE'; position:absolute right:0.7em top:50%; transform: translateY(-50%); pointer-events:none fg:$s-muted font-size:0.85em"}});function e0(t){I(t,(a,h)=>{$("div.s-select_wrap",t.inputAttrs,()=>{$("select.s-input",()=>{_(t,a,h),$("change=",e=>{t.bind&&(t.bind.value=e.target.value)}),$(()=>{let e=typeof t.options=="function"?t.options():t.options,p=t.bind?.value??"";t.placeholder!=null&&$("option",()=>{$("value= disabled=true hidden=true"),p||$("selected=true"),$("#",t.placeholder)});for(let r of e){let d=typeof r=="string"?{value:r,label:r}:{value:r.value,label:r.label??r.value};$("option",()=>{$("value=",d.value),d.value===p&&$("selected=true"),$("#",d.label)})}})})})})}import T from"aberdeen";T.insertGlobalCss({"textarea.s-input":"resize:vertical min-height:3em line-height:1.45","textarea.s-input.s-autoGrow":"resize:none min-height:2.5em overflow-y:hidden"});function p0(t={}){let a=t.autoGrow!==!1;I(t,(h,e)=>{let p=T("textarea.s-input",t.inputAttrs,()=>{a?(T(".s-autoGrow"),T("input=",r=>{h2(r.currentTarget),t.input&&t.input(r)})):(T("rows=",t.rows??4),T("resize:",t.resize??"vertical"),t.input&&T("input=",t.input)),t.placeholder!=null&&T("placeholder=",t.placeholder),t.value!=null&&!t.bind&&T("value=",t.value),t.change&&T("change=",t.change),_(t,h,e,t.bind)});a&&requestAnimationFrame(()=>h2(p))})}function h2(t){t.style.height="auto",t.style.height=`${t.scrollHeight}px`}import D from"aberdeen";D.insertGlobalCss({".s-tt-tip":{"&":"position:fixed z-index:500 max-width:20rem w:max-content padding: 0.3em 0.65em; font-size:0.85em line-height:1.4 pointer-events:none"}});var J=D.proxy(void 0),R=null;typeof window<"u"&&window.addEventListener("scroll",()=>{J.value=void 0},{capture:!0,passive:!0});function r0(t,a,h,e){let r=window.innerWidth,d=window.innerHeight,o=0,c=0;return e==="bottom"?(o=t.left+(t.width-a)/2,c=t.bottom+7,c+h>d-8&&(c=t.top-h-7)):e==="left"?(o=t.left-a-7,c=t.top+(t.height-h)/2,o<8&&(o=t.right+7)):e==="right"?(o=t.right+7,c=t.top+(t.height-h)/2,o+a>r-8&&(o=t.left-a-7)):(o=t.left+(t.width-a)/2,c=t.top-h-7,c<8&&(c=t.bottom+7)),{x:Math.max(8,Math.min(o,r-a-8)),y:Math.max(8,Math.min(c,d-h-8))}}function O1(){R&&clearTimeout(R),R=setTimeout(()=>{J.value=void 0,R=null},100)}F(()=>{let t=J.value;if(!t)return;let{opts:a,anchor:h}=t,e=a.placement??"top",p=D("div.s-tt-tip.s-s.neutral.shadow role=tooltip visibility:hidden",a.attrs,()=>{D("mouseenter=",()=>{R&&(clearTimeout(R),R=null)}),D("mouseleave=",O1),v(a.tip)});requestAnimationFrame(()=>{if(!document.body.contains(p))return;let{x:r,y:d}=r0(h.getBoundingClientRect(),p.offsetWidth,p.offsetHeight,e);p.style.left=r+"px",p.style.top=d+"px",p.style.visibility=""})});function d0(t){let a=h=>{R&&(clearTimeout(R),R=null),J.value={opts:t,anchor:h.currentTarget}};D("mouseenter=",a),D("mouseleave=",O1),D("focusin=",a),D("focusout=",O1),D.clean(()=>{J.value?.opts===t&&(J.value=void 0)})}export{A1 as addContextMenu,d0 as addTooltip,L2 as alert,i2 as autocomplete,M2 as box,O as button,x2 as buttonChooser,W as buttonGroup,v2 as checkbox,H2 as closeFloatingMenu,K2 as closeNav,C2 as confirm,i1 as dialog,m2 as form,q1 as getDarkMode,a1 as iconButton,L1 as isDialogOpen,n1 as isFloatingMenuOpen,G2 as main,V2 as menu,k2 as menuButton,z2 as prompt,l1 as revealInStrip,s1 as scrollStrip,e0 as select,r2 as setDarkMode,H1 as showFloatingMenu,P2 as tabs,p0 as textarea,V1 as textline,M1 as toast};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "staffa",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "An opinionated component library for the Aberdeen reactive UI library.",
5
5
  "license": "ISC",
6
6
  "author": "",
@@ -35,13 +35,13 @@
35
35
  "aberdeen": "^1.20.0"
36
36
  },
37
37
  "devDependencies": {
38
- "aberdeen": "^1.20.0",
38
+ "aberdeen": "^1.22.0",
39
39
  "esbuild": "^0.28.0",
40
40
  "http-server": "^14.1.1",
41
41
  "jsdom": "^29.1.1",
42
42
  "lucide-static": "^1.17.0",
43
43
  "readme-tsdoc": "^1.2.1",
44
- "shotest": "^1.8.4",
44
+ "shotest": "^2.2.0",
45
45
  "typescript": "^5.9.3"
46
46
  },
47
47
  "allowScripts": {
@@ -211,6 +211,10 @@ panel; `"single"` shows only the current panel, however wide the screen
211
211
  it). Only the display differs: the stack, the breadcrumbs, the URL,
212
212
  Escape and the back button behave identically in both. Routed mode only.
213
213
 
214
+ Live: pass a proxied options object (or make this field a getter) and a
215
+ change is adopted in place — one layout pass, every panel keeping its
216
+ state.
217
+
214
218
  **Type:** `"auto" | "single"`
215
219
 
216
220
  ### mainOptions.linkNavigation · member
@@ -223,6 +227,9 @@ every click replaces the content as a whole — which, with flat routes,
223
227
  is the conventional sidebar-and-content app: one pane, swapped on every
224
228
  click, the crumb line simply naming it. Routed mode only.
225
229
 
230
+ Live, like `MainOptions.columns`: change it and the next click
231
+ uses the new default.
232
+
226
233
  **Type:** `"push" | "replace" | "open"`
227
234
 
228
235
  ### mainOptions.footer · member
package/skill/MenuItem.md CHANGED
@@ -38,6 +38,19 @@ columns rather than on top of whatever panel the menu was drawn in. Pass
38
38
 
39
39
  **Type:** `string`
40
40
 
41
+ ### menuItem.match · member
42
+
43
+ Pages this item claims *beyond* its own `href`: a string claims that path
44
+ and everything under it (`"/mail"` claims `/mail/…`, not `/mailbox`), a
45
+ function is asked with the current path. While a claimed page is current,
46
+ the item is highlighted and the branches above it stay unfolded — for the
47
+ detail screens a menu has no row of their own: the `/thread/[id]` a
48
+ notification lands on, an icon's page under the gallery's row. Claims
49
+ work from the very first paint, so they also cover cold deep links,
50
+ which no amount of fold-state keeping can.
51
+
52
+ **Type:** `string | ((path: string) => boolean)`
53
+
41
54
  ### menuItem.target · member
42
55
 
43
56
  `target` for the link (`_blank`, etc.). Only meaningful with `href`.
package/skill/SKILL.md CHANGED
@@ -298,6 +298,7 @@ Search params and the `#hash` belong to the current panel only. Anything another
298
298
 
299
299
  - `columns: "single"` shows only the current panel, however wide the screen — the phone experience at every size. Only the display changes: the URL, the back button, unsaved panels and the panels' own close buttons all behave the same.
300
300
  - `linkNavigation` sets what a link *without* a `data-panel` attribute does: `"push"` (the default), `"replace"`, or `"open"`. With `"open"` every click replaces the content as a whole — which, with flat routes, is the conventional sidebar-and-content app: one pane, swapped on every click, the crumb line simply naming it.
301
+ - Both are live: pass a proxied options object (or make the field a getter) and a change is adopted in place, every open panel keeping its state.
301
302
  - Only one routed `S.main()` can be mounted at a time; a second one throws — the URL is global, so two of them would fight over it. Nothing else is global: the stack belongs to its shell, and each handler gets its own `$panel`, since several panels are alive at once.
302
303
  - Navigating with `aberdeen/route`'s own `go()` works — an unsaved panel survives it too — but, like a link from outside a panel, it builds the whole stack from the path. So prefer the stack's own methods. A navigation guard your app registered with `route.setGuard` (an auth redirect, say) keeps working untouched: Staffa registers none of its own.
303
304
  - Deep links need your static server to serve the app for unknown paths (the usual SPA fallback). For `http-server` that's `-P`, as in the demo command below.
@@ -354,7 +355,7 @@ Components share naming conventions for options: `attrs` (outermost element), `c
354
355
 
355
356
  ### Layout & containers
356
357
 
357
- - **`S.main(opts)`**: app shell, a sticky header with `logo`, `title`, `subtitle`, `menu` — plus, in routed mode, the breadcrumbs of the open panels; scrollable content area; footer. Set `maxWidth` to center the content. Give it a `nav` for a sidebar that collapses to a hamburger below 640 px — where the nav becomes a full page sliding in from the left, handing over to the chosen screen with a matching slide in from the right. Its `items` may be a reactive array; adding or removing one redraws just the sidebar, never the content beside it. An item with `items` of its own becomes a collapsible submenu: only the branch holding the current page stays unfolded, and clicking a branch selects its first leaf (expanding a branch doesn't dismiss the phone's full-page nav — only picking a leaf does). A sidebar taller than the window scrolls, and follows the highlighted item: navigating to a page whose item sits past the fold scrolls it back into view. A navigation dismisses the collapsed nav by itself, links in your own custom rows included; `S.closeNav()` does it for the rows that *don't* navigate. Instead of a single `content` slot it can take a `routes` table — see [Panel-stack navigation](#panel-stack-navigation).
358
+ - **`S.main(opts)`**: app shell, a sticky header with `logo`, `title`, `subtitle`, `menu` — plus, in routed mode, the breadcrumbs of the open panels; scrollable content area; footer. Set `maxWidth` to center the content. Give it a `nav` for a sidebar that collapses to a hamburger below 640 px — where the nav becomes a full page sliding in from the left, handing over to the chosen screen with a matching slide in from the right. Its `items` may be a reactive array; adding or removing one redraws just the sidebar, never the content beside it. An item with `items` of its own becomes a collapsible submenu: only the branch holding the current page stays unfolded, and clicking a branch selects its first leaf (expanding a branch doesn't dismiss the phone's full-page nav — only picking a leaf does). A page the menu holds nowhere leaves every fold as it was. An item can also `match` pages beyond its own `href` — a path prefix, or a `(path) => boolean` — claiming the detail screens that have no row of their own: it is then highlighted, and the branches above it stay unfolded, cold deep links included. A sidebar taller than the window scrolls, and follows the highlighted item: navigating to a page whose item sits past the fold scrolls it back into view. A navigation dismisses the collapsed nav by itself, links in your own custom rows included; `S.closeNav()` does it for the rows that *don't* navigate. Instead of a single `content` slot it can take a `routes` table — see [Panel-stack navigation](#panel-stack-navigation).
358
359
  - **`S.box(opts | content)`**: surface with optional `header`/`footer` and padded body. Pass a function for shorthand `{ content }`. `close: fn` adds a ✕ that runs your dismissal — in the header row, or floating over the body when there is no header. (It is plain furniture: a routed screen gets its own way out from the shell, see [Panel-declared chrome](#chrome).)
359
360
  - **`S.tabs(opts)`**: tablist with live tab panels and keyboard navigation. More tabs than fit make the strip scroll (see `S.scrollStrip`); selecting a tab any other way (the arrow keys, a `bind` written from elsewhere) scrolls it into view.
360
361
  - **`S.scrollStrip(opts)`**: a horizontal row that scrolls once its content outgrows it, with a ‹ / › button appearing over whichever end still has something to reach — so it isn't just a swipe target. Its own scrollbar is hidden. `S.tabs` and the routed shell's breadcrumbs are built on it; reach for it for any row of chrome that can outgrow its space. `S.revealInStrip(el)` scrolls one of its children into view.
@@ -1,7 +1,7 @@
1
1
  import A from "aberdeen";
2
- import { current as currentRoute, matchCurrent } from "aberdeen/route";
2
+ import { current as currentRoute } from "aberdeen/route";
3
3
  import { type Slot, type Attributes, drawSlot, focusFirst, NARROW_PX } from "../core.js";
4
- import { type MenuOptions, type MenuEntry, drawMenu, isFloatingMenuOpen, consumeBranchNav } from "./menu.js";
4
+ import { type MenuOptions, drawMenu, isFloatingMenuOpen, consumeBranchNav, anyCurrent } from "./menu.js";
5
5
  // The shell's own chrome glyphs, from the same Lucide set an app draws with —
6
6
  // so a nav trigger sits beside app icons as an equal. Named imports, so a
7
7
  // bundler keeps these two and tree-shakes the other ~1950 away.
@@ -195,6 +195,10 @@ export interface MainOptions<R = Routes> {
195
195
  * — the phone experience at every size (the nav sidebar still sits beside
196
196
  * it). Only the display differs: the stack, the breadcrumbs, the URL,
197
197
  * Escape and the back button behave identically in both. Routed mode only.
198
+ *
199
+ * Live: pass a proxied options object (or make this field a getter) and a
200
+ * change is adopted in place — one layout pass, every panel keeping its
201
+ * state.
198
202
  */
199
203
  columns?: "auto" | "single";
200
204
  /**
@@ -205,6 +209,9 @@ export interface MainOptions<R = Routes> {
205
209
  * every click replaces the content as a whole — which, with flat routes,
206
210
  * is the conventional sidebar-and-content app: one pane, swapped on every
207
211
  * click, the crumb line simply naming it. Routed mode only.
212
+ *
213
+ * Live, like {@link MainOptions.columns}: change it and the next click
214
+ * uses the new default.
208
215
  */
209
216
  linkNavigation?: "push" | "replace" | "open";
210
217
  /** Footer content, pinned below the scroll area. */
@@ -372,10 +379,12 @@ A.insertGlobalCss({
372
379
  // body starts below the bar), but the bar should still win if they ever do.
373
380
  "position:absolute inset:0 z-index:5 display:flex flex-direction:column " +
374
381
  "overflow-y:auto overscroll-behavior:contain border:0 r:0 padding:$2 gap:$1 " +
375
- "transition: transform var(--s-panel-ms) ease;",
382
+ "transition: transform var(--s-panel-ms) ease, visibility var(--s-panel-ms);",
376
383
  // Parked one screen to the left: the state the `create=`/`destroy=` hooks
377
- // transition out of and back into.
378
- "&.s-nav-page-off": "transform:translateX(-100%) pointer-events:none",
384
+ // transition out of and back into. `visibility` flips at the slide's end
385
+ // (see `.s-menu-list` in menu.ts): the dismissed page lingers off screen
386
+ // until Aberdeen's removal timer, and mustn't stay reachable meanwhile.
387
+ "&.s-nav-page-off": "transform:translateX(-100%) pointer-events:none visibility:hidden",
379
388
  // Roomier rows than the dropdown's: this is the whole screen, and every row
380
389
  // is a thumb target.
381
390
  ".s-menu-item": "padding: $2 $3; min-height:3rem font-size:1.05em gap:$3",
@@ -483,12 +492,19 @@ export function main<R extends RouteTable<R>>(opts: MainOptions<R> = {}): PanelS
483
492
  routes,
484
493
  notFound: opts.notFound,
485
494
  ancestors: opts.ancestors,
486
- columns: opts.columns,
487
- linkNavigation: opts.linkNavigation,
488
495
  title: opts.title,
489
496
  $shell,
490
497
  })
491
498
  : null;
499
+ if (ctl) {
500
+ // `columns` and `linkNavigation` are live: each is read in a scope of
501
+ // its own, so when the options object is a proxy (or the field a
502
+ // getter), a change re-runs just that scope — the columns relayout in
503
+ // place with every panel's state intact, and the next click picks up
504
+ // the new link default. Nothing else of the shell is touched.
505
+ A(() => ctl.setColumns(opts.columns));
506
+ A(() => ctl.setLinkNavigation(opts.linkNavigation));
507
+ }
492
508
  // Where the brand mark and the app's name link — or nowhere, when the app
493
509
  // said `home: null` (a title slot holding a control of its own, say).
494
510
  const homeHref = ctl && opts.home !== null ? opts.home ?? "/" : null;
@@ -743,23 +759,18 @@ function drawSecondLine(
743
759
 
744
760
  /**
745
761
  * Whether the stack would only be saying what the sidebar already says: a
746
- * single panel open, the sidebar on screen, and that panel being one of the nav's
747
- * own rows.
762
+ * single panel open, the sidebar on screen, and that panel being one of the
763
+ * nav's own rows — a leaf inside a submenu counts, since the sidebar shows it
764
+ * highlighted (inside its unfolded branch) all the same.
748
765
  *
749
- * The row test is {@link matchCurrent} — the very thing that marks a row
750
- * `aria-current=page` — so "the crumb is redundant" and "the sidebar has it
751
- * highlighted" can never come apart. It compares whole paths, so it is true
752
- * only for a nav item's own screen, never for one opened beneath it.
766
+ * The row test is the menu's own {@link anyCurrent} — the very thing that
767
+ * marks a row `aria-current=page` — so "the crumb is redundant" and "the
768
+ * sidebar has it highlighted" can never come apart.
753
769
  */
754
770
  function taglineFits(ctl: PanelStackController, nav: MenuOptions | undefined, $shell: { narrow: boolean }): boolean {
755
771
  if ($shell.narrow || nav == null) return false;
756
772
  if (ctl.panels.length > 1) return false;
757
- return nav.items.some((entry: MenuEntry) =>
758
- typeof entry !== "string" &&
759
- typeof entry !== "function" &&
760
- !("separator" in entry) &&
761
- entry.href != null &&
762
- matchCurrent(entry.href));
773
+ return anyCurrent(nav.items);
763
774
  }
764
775
 
765
776
  /**
@@ -30,6 +30,17 @@ export interface MenuItem {
30
30
  * `attrs: "data-panel=push"` for a row that should stack instead.
31
31
  */
32
32
  href?: string;
33
+ /**
34
+ * Pages this item claims *beyond* its own `href`: a string claims that path
35
+ * and everything under it (`"/mail"` claims `/mail/…`, not `/mailbox`), a
36
+ * function is asked with the current path. While a claimed page is current,
37
+ * the item is highlighted and the branches above it stay unfolded — for the
38
+ * detail screens a menu has no row of their own: the `/thread/[id]` a
39
+ * notification lands on, an icon's page under the gallery's row. Claims
40
+ * work from the very first paint, so they also cover cold deep links,
41
+ * which no amount of fold-state keeping can.
42
+ */
43
+ match?: string | ((path: string) => boolean);
33
44
  /** `target` for the link (`_blank`, etc.). Only meaningful with `href`. */
34
45
  target?: string;
35
46
  /** Disables the item. */
@@ -133,12 +144,17 @@ export type ContextMenuOptions = Omit<FloatingMenuOptions, "anchor" | "at" | "cl
133
144
  A.insertGlobalCss({
134
145
  // Border comes from the `.s-s.neutral` surface; the panel only overrides the radius
135
146
  // (lg) and opts into elevation via `.shadow` (added on the element below).
147
+ // `visibility` rides the same transition as the fade (flipping only at its
148
+ // end, per CSS visibility interpolation): a dismissed menu lingers in the
149
+ // DOM for a while — Aberdeen's `destroy=` removes it on a timer, not at
150
+ // the transition's end — and without this it would spend that time
151
+ // invisible yet still hittable by tests and read by assistive tech.
136
152
  ".s-menu-list":
137
153
  "position:fixed z-index:350 min-width:10rem display:flex flex-direction:column p:$1 " +
138
154
  "r:$s-radius-lg " +
139
155
  "overflow-y:auto max-height:min(80vh,28rem) " +
140
- "transition: opacity 0.15s, transform 0.15s;",
141
- ".s-menu-list.hidden": "opacity:0 pointer-events:none transform:translateY(-6px)",
156
+ "transition: opacity 0.15s, transform 0.15s, visibility 0.15s;",
157
+ ".s-menu-list.hidden": "opacity:0 pointer-events:none transform:translateY(-6px) visibility:hidden",
142
158
  // One class for both the `<a>` (link) and `<button>` forms — they look
143
159
  // identical; the element only differs where link semantics matter (see below).
144
160
  // The scroll-margin keeps a revealed row (see the scrollIntoView in
@@ -282,7 +298,7 @@ function drawLeaf(entry: MenuItem, onLeafSelect?: () => void): void {
282
298
  A(() => {
283
299
  const first = !drawn;
284
300
  drawn = true;
285
- if (!matchCurrent(entry.href!)) return;
301
+ if (!isCurrent(entry)) return;
286
302
  A("aria-current=page");
287
303
  // A list taller than its scrollport (a long sidebar nav, mostly)
288
304
  // highlights nothing when the current row is scrolled out of it,
@@ -307,6 +323,20 @@ function drawLeaf(entry: MenuItem, onLeafSelect?: () => void): void {
307
323
  });
308
324
  }
309
325
 
326
+ /**
327
+ * The last route-derived fold state of every linked branch, keyed by the
328
+ * branch's selection href. Module-level on purpose: the phone's full-page nav
329
+ * (and any dropdown) mounts a fresh menu every time it opens, and per-mount
330
+ * state would hand it three folded sections in the middle of the user's work.
331
+ * Bounded by the number of distinct branch hrefs an app ever shows.
332
+ */
333
+ const foldMemory = new Map<string, boolean>();
334
+
335
+ function setFold(href: string, open: boolean): boolean {
336
+ foldMemory.set(href, open);
337
+ return open;
338
+ }
339
+
310
340
  /**
311
341
  * A branch: a native `<details>` folding a sub-list of entries in and out. The
312
342
  * children stay mounted whether folded or not — closing hides them, it doesn't
@@ -327,12 +357,17 @@ function drawBranch(entry: MenuItem, onLeafSelect?: () => void, $menuHasCurrent?
327
357
  // nowhere in the menu, nothing has an opinion, and the fold simply keeps
328
358
  // its last state — folding everything up would answer a question nobody
329
359
  // asked with a menu that forgot where the user was.
330
- let last = false;
360
+ //
361
+ // "Last state" lives in `foldMemory`, not in this closure: menus remount —
362
+ // the phone's full-page nav exists only while it is open — and a remount
363
+ // must find the state where the previous mount left it. It is keyed on the
364
+ // branch's selection href, so the sidebar and the phone nav (two renderings
365
+ // of the same items) share one truth, however often either is rebuilt.
331
366
  const $open = href != null
332
367
  ? A.derive(() => {
333
- if (containsCurrent(entry)) return (last = true);
334
- if ($menuHasCurrent == null || $menuHasCurrent.value) return (last = false);
335
- return last;
368
+ if (containsCurrent(entry)) return setFold(href, true);
369
+ if ($menuHasCurrent == null || $menuHasCurrent.value) return setFold(href, false);
370
+ return foldMemory.get(href) ?? false;
336
371
  })
337
372
  : null;
338
373
 
@@ -344,9 +379,10 @@ function drawBranch(entry: MenuItem, onLeafSelect?: () => void, $menuHasCurrent?
344
379
  A("summary.s-menu-item.s-menu-branch", entry.attrs, () => {
345
380
  if (entry.disabled) A("aria-disabled=true");
346
381
  A(() => {
347
- // Current only on its *own* page: when a descendant is current, that
382
+ // Current only on its *own* page (its `href`, or a `match` claim
383
+ // pages with no row of their own): when a descendant is current, that
348
384
  // row carries the highlight, and two highlights would read as two pages.
349
- if (entry.href != null && matchCurrent(entry.href)) A("aria-current=page");
385
+ if (isCurrent(entry)) A("aria-current=page");
350
386
  });
351
387
  A("click=", (e: Event) => {
352
388
  if (entry.disabled) { e.preventDefault(); return; }
@@ -384,15 +420,35 @@ function foldedAway(el: HTMLElement): boolean {
384
420
  return false;
385
421
  }
386
422
 
387
- /** Whether any page linked anywhere in `items` is the current one. */
388
- function anyCurrent(items: MenuEntry[]): boolean {
423
+ /**
424
+ * Whether any item anywhere in `items` branches, their leaves, `match`
425
+ * claims — is the current page. The one question both the fold logic and the
426
+ * shell's tagline rule (see `taglineFits` in main.ts) ask of a menu, exported
427
+ * so the two can never disagree with the highlighting.
428
+ */
429
+ export function anyCurrent(items: MenuEntry[]): boolean {
389
430
  return items.some((entry) =>
390
431
  typeof entry !== "string" && typeof entry !== "function" && !("separator" in entry) && containsCurrent(entry));
391
432
  }
392
433
 
393
- /** Whether `entry`'s own page, or any page linked below it, is the current one. */
394
- function containsCurrent(entry: MenuItem): boolean {
434
+ /**
435
+ * Whether this item is the current page: its own `href` matches, or its
436
+ * `match` claims the current path. The single test behind `aria-current`,
437
+ * branch unfolding, and {@link anyCurrent} — one truth, three consumers.
438
+ */
439
+ function isCurrent(entry: MenuItem): boolean {
395
440
  if (entry.href != null && matchCurrent(entry.href)) return true;
441
+ const m = entry.match;
442
+ if (m == null) return false;
443
+ const path = currentRoute.path;
444
+ if (typeof m === "function") return m(path);
445
+ const claim = m.replace(/\/+$/, "") || "/";
446
+ return path === claim || path.startsWith(claim === "/" ? "/" : claim + "/");
447
+ }
448
+
449
+ /** Whether `entry` is the current page itself, or holds it anywhere below. */
450
+ function containsCurrent(entry: MenuItem): boolean {
451
+ if (isCurrent(entry)) return true;
396
452
  for (const child of entry.items ?? []) {
397
453
  if (typeof child === "string" || typeof child === "function" || "separator" in child) continue;
398
454
  if (containsCurrent(child)) return true;
@@ -1509,6 +1509,25 @@ export class PanelStackController implements PanelStack {
1509
1509
  });
1510
1510
  }
1511
1511
 
1512
+ // ── Live settings ──────────────────────────────────────────────────────
1513
+ // `main()` keeps these fed from small reactive scopes of their own, so an
1514
+ // app that reads them off a proxy (or through a getter) can change them at
1515
+ // runtime and the shell adapts in place — nothing is redrawn, no panel
1516
+ // loses its state. Not {@link PanelStack} API: the app talks to `main()`'s
1517
+ // options; these are how `main()` talks to the stack.
1518
+
1519
+ /** Adopt a changed `columns` setting: one layout pass, nothing redrawn. */
1520
+ setColumns(columns: "auto" | "single" | undefined): void {
1521
+ if (this.opts.columns === columns) return;
1522
+ this.opts.columns = columns;
1523
+ this.scheduleLayout();
1524
+ }
1525
+
1526
+ /** Adopt a changed `linkNavigation` default; the next click reads it. */
1527
+ setLinkNavigation(mode: "push" | "replace" | "open" | undefined): void {
1528
+ this.opts.linkNavigation = mode;
1529
+ }
1530
+
1512
1531
  /**
1513
1532
  * The breadcrumb stack, drawn by `main()` into the top bar: every open
1514
1533
  * panel, oldest first, the ones on screen right now in bold, pinned ones