🦄 Sync 2026-07-26 23:49:39

This commit is contained in:
github-actions[bot] committed 2026-07-26 23:49:39 +08:00
1 parent 2450ea7cca
commit bf03fd23d8
20 files changed
+482 -145

No files matched your search

+80 -14
View File
@@ -1,5 +1,9 @@
/* The bar carries no colour transition: one would ease its bg/text over
--mega-menu-duration on every data-darkmode flip, lagging the bar behind
the untransitioned page in all three nav modes. The mega-menu wipe colour
lives on .desktop-menu-sheet below, which owns its transition. */
header {
@apply bg-bg sticky top-0 z-40 mb-2 transition-colors duration-(--mega-menu-duration,300ms) ease-[cubic-bezier(0.4,0,0.6,1)];
@apply bg-bg sticky top-0 z-40 mb-2;
& .header-content {
@apply relative z-10 flex h-14 items-center justify-between px-6 py-3 max-md:px-4 max-md:py-2;
@@ -266,9 +270,11 @@ header {
@apply md:flex;
}
/* D1 底线呼吸:展开态沿用短底线汉堡;折叠后底线伸满(三线齐整 =
侧栏收纳完毕)。dasharray 只改可见长度,线帽形状不受影响。 */
[data-nav-type="sidebar"].sidebar-collapsed
/* D1 底线呼吸(2026-07 反转):展开后底线伸满 —— 三线齐整 = 内容
全部亮出;折叠态回落到短底线 = 还有内容收着,缺口招手可展开。
与耦合滑动同向:侧栏进场线补齐,退场线让位。dasharray 只改可见
长度,线帽形状不受影响。 */
[data-nav-type="sidebar"]:not(.sidebar-collapsed)
&
.navigation-toggle-line-bottom {
@apply md:[stroke-dasharray:15_15];
@@ -284,6 +290,12 @@ header {
& .navigation-toggle-line {
transform-box: fill-box;
@apply origin-center transition-[transform,opacity,stroke-dasharray] duration-150 ease-in-out;
/* Desktop sidebar: the dasharray breath runs in step with the
250ms coupled slide (the mobile X morph keeps its snappy 150). */
[data-nav-type="sidebar"] & {
@apply md:duration-[250ms];
}
}
/* Tabler menu-2 geometry: all three lines are full-length equals.
@@ -356,8 +368,11 @@ body[data-nav-type="sidebar"] {
overflow-x-clip keeps the sliding sidebar out of horizontal overflow. */
/* Single source of truth for the sidebar column, so collapsing only has to
zero this one value instead of restating the grid template. */
--sidebar-w: 17rem;
zero this one value instead of restating the grid template.
--sidebar-w-full stays constant: the inner panel width and the slide
keyframes read it, and must not see the zeroed collapsed value. */
--sidebar-w-full: 17rem;
--sidebar-w: var(--sidebar-w-full);
@apply md:grid md:grid-cols-[var(--sidebar-w)_minmax(0,1fr)] md:grid-rows-[auto_minmax(0,1fr)] md:overflow-x-clip;
@@ -410,29 +425,60 @@ body[data-nav-type="sidebar"] {
}
& .sidebar-panel {
@apply border-hairline sticky top-0 hidden h-dvh w-full overflow-hidden rounded-none border-r transition-[visibility] duration-[250ms] md:block;
@apply sticky top-0 hidden h-dvh w-full overflow-hidden rounded-none md:block;
}
/* The grid column snaps closed to avoid a full-page layout animation.
Visibility removes collapsed controls from the tab order; on expansion,
the inner panel still enters via compositor-only translate + opacity. */
/* The grid column still snaps (one reflow, never a per-frame layout
animation); visibility removes collapsed controls from the tab order.
The hairline lives on the inner panel, not the frame, so it tracks the
sliding edge during the run animations below. */
&.sidebar-collapsed .sidebar-panel {
@apply invisible;
}
& .sidebar-panel-inner {
@apply bg-bg flex h-full w-68 flex-col overflow-hidden transition-[translate,opacity] duration-[250ms];
@apply bg-bg border-hairline flex h-full w-(--sidebar-w-full) flex-col overflow-hidden border-r;
}
&.sidebar-collapsed .sidebar-panel-inner {
@apply -translate-x-full opacity-0;
@apply -translate-x-full;
}
/* Coupled slide: the column width snaps in the same frame the
sidebar-anim-* class lands, then the sidebar and the whole content
column (header + #maincontent) slide the same 17rem with the same
curve — compositor-only, so the seam moves as one wall with zero
per-frame reflow. menu-aurora.js swaps the class per direction
(distinct animation-names restart cleanly on rapid toggles) and
clears it after the run. */
&.sidebar-anim-open > header,
&.sidebar-anim-open > #maincontent,
&.sidebar-anim-open .sidebar-panel-inner {
@apply md:animate-[sidebar-run-in_250ms_var(--ease-in-out)_both];
}
&.sidebar-anim-close > header,
&.sidebar-anim-close > #maincontent {
@apply md:animate-[sidebar-run-back_250ms_var(--ease-in-out)_both];
}
/* Closing: the column is already zero, so the panel holds its old spot
as a fixed overlay for one run while its content slides off. */
&.sidebar-anim-close .sidebar-panel {
@apply md:visible md:fixed md:top-0 md:left-0 md:w-(--sidebar-w-full);
}
&.sidebar-anim-close .sidebar-panel-inner {
@apply md:animate-[sidebar-run-out_250ms_var(--ease-in-out)_both];
}
/* Sidebar head: logo + hostname. h-14 matches the header row so its
bottom hairline continues the header's border in one unbroken line
across the viewport. */
across the viewport. box-content: the header is auto-height (56px
content + border OUTSIDE), so this border must sit outside its 56px
too — border-box would paint it one pixel higher than the header's. */
& .sidebar-head {
@apply border-hairline flex h-14 shrink-0 items-center gap-2.5 border-b px-4;
@apply border-hairline box-content flex h-14 shrink-0 items-center gap-2.5 border-b px-4;
& .sidebar-logo {
@apply size-5 shrink-0 rounded-md;
@@ -475,6 +521,26 @@ body[data-nav-type="sidebar"] {
}
}
/* Shared travel distance for the coupled sidebar slide: content column and
panel move the same 17rem, so the seam between them never separates. */
@keyframes sidebar-run-in {
from {
translate: calc(-1 * var(--sidebar-w-full)) 0;
}
}
@keyframes sidebar-run-back {
from {
translate: var(--sidebar-w-full) 0;
}
}
@keyframes sidebar-run-out {
to {
translate: calc(-1 * var(--sidebar-w-full)) 0;
}
}
#maincontent {
/* Centred shells (top-bar navigation) clamp here and gutter the remainder.
The sidebar shell overrides this — it caps the shell instead, see
@@ -33,7 +33,9 @@
}
.navigation-group-toggle {
@apply after:size-3.5 after:shrink-0 after:bg-current after:opacity-55 after:transition-[transform,opacity] after:duration-[250ms] after:content-[''] after:[mask:var(--icon-arrow-right)_center/cover_no-repeat] hover:after:opacity-100;
/* size-4.5 ≈ the row's text height — 3.5 read as undersized next to the
text-lg category labels, on desktop and in the mobile drawer alike. */
@apply after:size-4.5 after:shrink-0 after:bg-current after:opacity-55 after:transition-[transform,opacity] after:duration-[250ms] after:content-[''] after:[mask:var(--icon-arrow-right)_center/cover_no-repeat] hover:after:opacity-100;
}
.nav-category-label {
@@ -47,7 +47,7 @@
}
.cmdk-panel {
@apply border-hairline bg-surface/85 fixed top-24 left-1/2 z-120 w-[min(36rem,calc(100vw-2.5rem))] -translate-x-1/2 overflow-hidden rounded-3xl border shadow-xl backdrop-blur-xl backdrop-saturate-150 transition-[opacity,translate] duration-150 ease-out starting:-translate-y-2 starting:opacity-0;
@apply border-hairline bg-surface/85 fixed top-24 left-1/2 z-120 w-[min(36rem,calc(100vw-2.5rem))] -translate-x-1/2 overflow-hidden rounded-2xl border shadow-xl backdrop-blur-xl backdrop-saturate-150 transition-[opacity,translate] duration-150 ease-out starting:-translate-y-2 starting:opacity-0;
/* <md: the same panel becomes a full-screen takeover (Algolia DocSearch
manner) — opaque page background (no full-screen blur cost on phones),
@@ -30,6 +30,7 @@ return baseclass.extend({
const mobileList = overlay.querySelector("#mobile-nav-list");
const desktop = window.matchMedia("(min-width: 768px)");
const SIDEBAR_COLLAPSED_KEY = "aurora.sidebarCollapsed";
let sidebarAnimTimer;
const isDesktopSidebar = () =>
desktop.matches && document.body.dataset.navType === "sidebar";
@@ -79,7 +80,23 @@ return baseclass.extend({
closeMobileNavigation();
const collapsed = !expanded;
document.body.classList.toggle("sidebar-collapsed", collapsed);
const body = document.body;
// Coupled slide (_layout.css): the class must land in the same
// frame as the column snap. Open/close carry distinct
// animation-names, so alternating toggles restart the run without
// a forced reflow; the timer (not animationend — three elements
// animate) clears the class once the 250ms run is over.
body.classList.remove("sidebar-anim-open", "sidebar-anim-close");
body.classList.add(
collapsed ? "sidebar-anim-close" : "sidebar-anim-open",
);
clearTimeout(sidebarAnimTimer);
sidebarAnimTimer = setTimeout(() => {
body.classList.remove("sidebar-anim-open", "sidebar-anim-close");
}, 300);
body.classList.toggle("sidebar-collapsed", collapsed);
localStorage.setItem(SIDEBAR_COLLAPSED_KEY, collapsed);
updateToggleState(expanded);
return;
@@ -488,7 +505,7 @@ return baseclass.extend({
this.bindNavigationAccordion(list);
crumb.forEach((title, i) => {
if (i) crumbEl?.appendChild(E("li", { class: "crumb-sep" }, ["›"]));
if (i) crumbEl?.appendChild(E("li", { class: "crumb-sep" }, ["/"]));
crumbEl?.appendChild(
E("li", { class: i === crumb.length - 1 ? "current" : "" }, [title]),
);
@@ -533,12 +550,14 @@ return baseclass.extend({
// index — matched and rendered like pages, grouped under _("Design")
// (the System → Language and Style label) — but execute header.ut's
// global setTheme() instead of navigating, so the panel stays open and
// previews the switch live. luci-base has no Light/Dark msgids — they
// stay English literals, wrapped in _() so a future catalog entry would
// take effect (the same trade the icon-only switcher makes).
// previews the switch live. luci-base carries no mode msgids, so the
// labels borrow luci-app-aurora-config's already-translated "Light
// Mode"/"Dark Mode" — matching its msgids verbatim is what makes the
// palette follow the UI language wherever the config app is installed,
// and they fall back to English where it isn't.
[
["light", _("Light")],
["dark", _("Dark")],
["light", _("Light Mode")],
["dark", _("Dark Mode")],
["device", _("Automatic")],
].forEach(([mode, title]) =>
this.paletteIndex.push({
@@ -549,8 +568,9 @@ return baseclass.extend({
}),
);
// Only msgids that already exist in the luci-base catalog are used —
// the theme intentionally ships no translations of its own.
// Only msgids that already exist in a shipped catalog (luci-base, or the
// config app's as above) are used — the theme intentionally ships no
// translations of its own.
const isMac = /Mac|iP(ad|hone|od)/.test(navigator.platform);
this.paletteKey = isMac ? "⌘K" : "Ctrl+K";
toggle.setAttribute("aria-keyshortcuts", isMac ? "Meta+K" : "Control+K");
@@ -1039,8 +1059,9 @@ return baseclass.extend({
);
}
// Both vars live on the header, not the container: the container
// inherits the height, and the header's own transition-colors reads
// the duration so the bar colour fades in lockstep with the wipe.
// inherits both, and the close fallback timer reads the duration
// back off the header (the bar itself must stay transition-free so
// theme flips repaint it in the same frame as the page).
header.style.setProperty("--mega-menu-height", `${canvasHeight}px`);
header.style.setProperty("--mega-menu-duration", `${revealDuration}ms`);
};
@@ -729,7 +729,7 @@ test("renders sidebar items, logout, and translated crumbs without duplication",
assert.equal(crumb.children.length, 3);
assert.deepEqual(
crumb.children.map((child) => textContent(child)),
["translated:Network", "›", "translated:Wireless"],
["translated:Network", "/", "translated:Wireless"],
);
assert.equal(crumb.children[2].getAttribute("class"), "current");
assert.equal(list.dataset.accordionBound, "true");
@@ -83,7 +83,7 @@ test("shared navigation styles define active and expanded states", () => {
assertIncludesUtilities(sublink, [
"font-medium",
"hover:bg-hover-faint",
"rounded-lg",
"rounded-xl",
]);
assertIncludesUtilities(activeSublink, [
"text-brand",
@@ -212,6 +212,20 @@ test("mega-menu reveal and retract share the page-top origin", () => {
assert.doesNotMatch(headerLift ?? "", /bg-mega-menu-bg/);
});
test("theme flips repaint the bar in the same frame as the page", () => {
const headerDeclaration = layoutStyles.match(
/^header \{\s*@apply ([^;]+);/m,
)?.[1];
assert.ok(headerDeclaration, "Missing header root declaration");
assertIncludesUtilities(headerDeclaration, ["bg-bg", "sticky"]);
// A colour transition on the bar itself would ease its bg/text over
// --mega-menu-duration on every data-darkmode flip, lagging the bar behind
// the untransitioned page in all three nav modes. The mega-menu wipe colour
// lives on .desktop-menu-sheet, which carries its own transition.
assert.doesNotMatch(headerDeclaration, /\btransition/);
});
test("mega-menu category masks use Tailwind arbitrary utilities", () => {
const title = getBlock(layoutStyles, "& .desktop-nav-title");
const icon = getBlock(title, "&::before");
@@ -167,7 +167,8 @@ test("content dropdowns stay above the closed header and below the open mega-men
/\[data-nav-type="mega-menu"\]\s*&:has\([\s\S]*?\.desktop-menu-container[\s\S]*?\.active[\s\S]*?\)\s*\{\s*@apply\s+([^;]+);/,
)?.[1] ?? "";
const dropdownRule = dropdown.match(/&\.dropdown\s*\{\s*@apply\s+([^;]+);/)?.[1] ?? "";
const messageRule = message.match(/\.alert-message\s*\{\s*@apply\s+([^;]+);/)?.[1] ?? "";
const messageRule =
message.match(/\.alert-message\s*\{[\s\S]*?@apply\s+([^;]+);/)?.[1] ?? "";
const overlayRule =
overlay.match(/& \.desktop-menu-overlay\s*\{\s*@apply\s+([^;]+);/)?.[1] ?? "";
+2 -2
View File
@@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk
LUCI_TITLE:=Aurora Theme (A modern browser theme built with Vite and Tailwind CSS)
LUCI_DEPENDS:=+luci-base
PKG_VERSION:=1.1.4
PKG_RELEASE:=58
PKG_VERSION:=1.1.6
PKG_RELEASE:=59
PKG_LICENSE:=Apache-2.0
LUCI_MINIFY_CSS:=
@@ -1,2 +1,2 @@
/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-border-style:solid;--tw-duration:initial;--tw-ease:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-content:"";--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-space-y-reverse:0;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-border-spacing-x:0;--tw-border-spacing-y:0}}}@layer theme{:root,:host{--font-sans:var(--font-sans);--font-mono:var(--font-mono);--spacing:var(--spacing);--container-xs:20rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--leading-tight:1.25;--leading-snug:1.375;--leading-normal:1.5;--leading-relaxed:1.625;--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--blur-md:12px;--blur-lg:16px;--blur-xl:24px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1Line truncated
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-border-style:solid;--tw-duration:initial;--tw-ease:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-content:"";--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-space-y-reverse:0;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-border-spacing-x:0;--tw-border-spacing-y:0}}}@layer theme{:root,:host{--font-sans:var(--font-sans);--font-mono:var(--font-mono);--spacing:var(--spacing);--container-xs:20rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--leading-tight:1.25;--leading-snug:1.375;--leading-normal:1.5;--leading-relaxed:1.625;--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--blur-md:12px;--blur-lg:16px;--blur-xl:24px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1Line truncated
@@ -1 +1 @@
"use strict";"require baseclass";"require ui";return baseclass.extend({__init__(){ui.menu.load().then(e=>this.render(e)),this.initNavigationControls(),this.initUciIndicator()},initUciIndicator(){const e=ui.changes?.setIndicator;e&&(ui.changes.setIndicator=function(t){e.call(this,t),document.querySelector('[data-indicator="uci-changes"]')?.setAttribute("data-count",t||0)})},initNavigationControls(){const e=document.querySelector("#mobile-menu-overlay"),t=document.querySelector("#navigation-toggle");if(!t||!e)return;const i=e.querySelector("#mobile-nav-list"),n=window.matchMedia("(min-width: 768px)"),a="aurora.sidebarCollapsed",s=()=>n.matches&&"sidebar"===document.body.dataset.navType,o=e=>{const i=s();t.classList.toggle("is-expanded",e&&!n.matches),t.setAttribute("aria-expanded",e?"true":"false"),t.setAttribute("aria-controls",i?"sidebar-panel":"mobile-menu-overlay");const a=e&&!i?_("Close"):_("Navigation");t.setAttribute("title",a),t.setAttribute("aria-label",a)},l=()=>{e.classList.remove("mobile-menu-open"),document.body.classList.remove("mobile-navigation-open"),document.body.style.overflow="",this.resetNavigationGroups(i)},r=t=>{if(s()){l();const e=!t;return document.body.classList.toggle("sidebar-collapsed",e),localStorage.setItem(a,e),void o(t)}if(n.matches)return l(),void o(!1);e.classList.toggle("mobile-menu-open",t),document.body.classList.toggle("mobile-navigation-open",t),document.body.style.overflow=t?"hidden":"",t?this.expandActiveNavigationGroup(i):this.resetNavigationGroups(i),o(t)},c=()=>{if(l(),s()){const e="true"===localStorage.getItem(a);return document.body.classList.toggle("sidebar-collapsed",e),void o(!e)}o(!1)};t.addEventListener("click",t=>{t.stopPropagation(),r(!(s()?!document.body.classList.contains("sidebar-collapsed"):!n.matches&&e.classList.contains("mobile-menu-open")))}),e.addEventListener("click",t=>{t.target===e&&r(!1)}),document.addEventListener("keydown",t=>{"Escape"===t.key&&e.classList.contains("mobile-menu-open")&&r(!1)}),n.addEventListener("change",c),c(),document.addEventListener("click",t=>{const i=t.target?.closest?.(".navigation-direct, .navigation-sublink, .mobile-nav-logout");i&&e.contains(i)&&r(!1)})},renderMobileMenu(e){const t=document.querySelector("#mobile-nav-list"),i=document.querySelector("#mobile-nav-footer-action");t&&(t.innerHTML=""),i&&(i.innerHTML=""),t&&(e.forEach(e=>{e.isLogout?i&&i.appendChild(E("a",{class:"mobile-nav-logout",href:e.href},[e.title])):t.appendChild(this.renderNavigationItem(e,"mobile"))}),this.bindNavigationAccordion(t))},render(e){if(this.renderModeMenu(e),L.env.dispatchpath.length>=3){let t=e,i="";for(let e=0;e<3&&t;e++){const n=L.env.dispatchpath[e];t=t.children?.[n],i+=(i?"/":"")+n}t&&this.renderTabMenu(t,i)}},renderTabMenu(e,t,i=0){const n=document.querySelector("#tabmenu"),a=E("ul",{class:"tabs"}),s=ui.menu.getChildren(e);let o=null;return s.forEach(e=>{const n=L.env.dispatchpath[3+i]===e.name;a.appendChild(E("li",{class:`tabmenu-item-${e.name}${n?" active":""}`},[E("a",{href:L.url(t,e.name)},[_(e.title)])])),n&&(o=e)}),a.children.length?(n.appendChild(a),n.style.display="",o&&this.renderTabMenu(o,`${t}/${o.name}`,i+1),a):E([])},renderMainMenu(e,t,i=0,n=null){const a=i?E("ul",{class:"desktop-nav-list"}):document.querySelector("#topmenu"),s=ui.menu.getChildren(e);if(i>1)return E([]);if(0===i){const e=document.body?.dataset?.navType||"mega-menu";if("sidebar"===e)return this.renderSidebar(n||[]),a||E([]);if(!a||!s.length)return E([]);"mega-menu"===e?this.initMegaMenu(s,t,a):this.initDropdown(s,t,a)}else{if(!s.length)return E([]);s.forEach(i=>{const n=this.isActivePath(e.name,i.name),s={class:n?"is-active-page":"",href:L.url(t,i.name)};n&&(s["aria-current"]="page"),a.appendChild(E("li",{},[E("a",s,[_(i.title)])]))})}return a.style.display="",a},isActivePath:(e,t)=>L.env.dispatchpath[1]===e&&(null==t||L.env.dispatchpath[2]===t),buildNavigationModel(e,t){return e.filter(e=>e?.name).map(e=>{const i=ui.menu.getChildren(e).filter(e=>e?.name).map(i=>({name:i.name,title:_(i.title),href:L.url(t,e.name,i.name),isActivePage:this.isActivePath(e.name,i.name)})),n=i.length>0,a=this.isActivePath(e.name);return{name:e.name,title:_(e.title),href:L.url(t,e.name),hasChildren:n,isLogout:"logout"===e.name,isActiveGroup:n&&a,isActivePage:!n&&a,activePage:i.find(e=>e.isActivePage)||null,pages:i}})},navigationSubmenuId:(e,t)=>`${e}-submenu-${encodeURIComponent(String(t))}`,renderNavigationItem(e,t){const i="mobile"===t,n=i?"mobile-nav-item":"",a=i?"navigation-direct mobile-nav-link":"navigation-direct nav-link";if(!e.hasChildren){const t={class:`${a}${e.isActivePage?" is-active-page":""}`,href:e.href};return e.isActivePage&&(t["aria-current"]="page"),E("li",{class:n},[E("a",t,[e.title])])}const s=this.navigationSubmenuId(t,e.name),o=["navigation-group",i?"mobile-nav-item":"sidebar-group",e.isActiveGroup?"is-active-group":"",e.isActiveGroup?"is-expanded":""].filter(Boolean),l={class:i?"navigation-group-toggle mobile-nav-link mobile-nav-toggle":"navigatLine truncated
"use strict";"require baseclass";"require ui";return baseclass.extend({__init__(){ui.menu.load().then(e=>this.render(e)),this.initNavigationControls(),this.initUciIndicator()},initUciIndicator(){const e=ui.changes?.setIndicator;e&&(ui.changes.setIndicator=function(t){e.call(this,t),document.querySelector('[data-indicator="uci-changes"]')?.setAttribute("data-count",t||0)})},initNavigationControls(){const e=document.querySelector("#mobile-menu-overlay"),t=document.querySelector("#navigation-toggle");if(!t||!e)return;const i=e.querySelector("#mobile-nav-list"),a=window.matchMedia("(min-width: 768px)"),n="aurora.sidebarCollapsed";let s;const o=()=>a.matches&&"sidebar"===document.body.dataset.navType,l=e=>{const i=o();t.classList.toggle("is-expanded",e&&!a.matches),t.setAttribute("aria-expanded",e?"true":"false"),t.setAttribute("aria-controls",i?"sidebar-panel":"mobile-menu-overlay");const n=e&&!i?_("Close"):_("Navigation");t.setAttribute("title",n),t.setAttribute("aria-label",n)},r=()=>{e.classList.remove("mobile-menu-open"),document.body.classList.remove("mobile-navigation-open"),document.body.style.overflow="",this.resetNavigationGroups(i)},c=t=>{if(o()){r();const e=!t,i=document.body;return i.classList.remove("sidebar-anim-open","sidebar-anim-close"),i.classList.add(e?"sidebar-anim-close":"sidebar-anim-open"),clearTimeout(s),s=setTimeout(()=>{i.classList.remove("sidebar-anim-open","sidebar-anim-close")},300),i.classList.toggle("sidebar-collapsed",e),localStorage.setItem(n,e),void l(t)}if(a.matches)return r(),void l(!1);e.classList.toggle("mobile-menu-open",t),document.body.classList.toggle("mobile-navigation-open",t),document.body.style.overflow=t?"hidden":"",t?this.expandActiveNavigationGroup(i):this.resetNavigationGroups(i),l(t)},d=()=>{if(r(),o()){const e="true"===localStorage.getItem(n);return document.body.classList.toggle("sidebar-collapsed",e),void l(!e)}l(!1)};t.addEventListener("click",t=>{t.stopPropagation(),c(!(o()?!document.body.classList.contains("sidebar-collapsed"):!a.matches&&e.classList.contains("mobile-menu-open")))}),e.addEventListener("click",t=>{t.target===e&&c(!1)}),document.addEventListener("keydown",t=>{"Escape"===t.key&&e.classList.contains("mobile-menu-open")&&c(!1)}),a.addEventListener("change",d),d(),document.addEventListener("click",t=>{const i=t.target?.closest?.(".navigation-direct, .navigation-sublink, .mobile-nav-logout");i&&e.contains(i)&&c(!1)})},renderMobileMenu(e){const t=document.querySelector("#mobile-nav-list"),i=document.querySelector("#mobile-nav-footer-action");t&&(t.innerHTML=""),i&&(i.innerHTML=""),t&&(e.forEach(e=>{e.isLogout?i&&i.appendChild(E("a",{class:"mobile-nav-logout",href:e.href},[e.title])):t.appendChild(this.renderNavigationItem(e,"mobile"))}),this.bindNavigationAccordion(t))},render(e){if(this.renderModeMenu(e),L.env.dispatchpath.length>=3){let t=e,i="";for(let e=0;e<3&&t;e++){const a=L.env.dispatchpath[e];t=t.children?.[a],i+=(i?"/":"")+a}t&&this.renderTabMenu(t,i)}},renderTabMenu(e,t,i=0){const a=document.querySelector("#tabmenu"),n=E("ul",{class:"tabs"}),s=ui.menu.getChildren(e);let o=null;return s.forEach(e=>{const a=L.env.dispatchpath[3+i]===e.name;n.appendChild(E("li",{class:`tabmenu-item-${e.name}${a?" active":""}`},[E("a",{href:L.url(t,e.name)},[_(e.title)])])),a&&(o=e)}),n.children.length?(a.appendChild(n),a.style.display="",o&&this.renderTabMenu(o,`${t}/${o.name}`,i+1),n):E([])},renderMainMenu(e,t,i=0,a=null){const n=i?E("ul",{class:"desktop-nav-list"}):document.querySelector("#topmenu"),s=ui.menu.getChildren(e);if(i>1)return E([]);if(0===i){const e=document.body?.dataset?.navType||"mega-menu";if("sidebar"===e)return this.renderSidebar(a||[]),n||E([]);if(!n||!s.length)return E([]);"mega-menu"===e?this.initMegaMenu(s,t,n):this.initDropdown(s,t,n)}else{if(!s.length)return E([]);s.forEach(i=>{const a=this.isActivePath(e.name,i.name),s={class:a?"is-active-page":"",href:L.url(t,i.name)};a&&(s["aria-current"]="page"),n.appendChild(E("li",{},[E("a",s,[_(i.title)])]))})}return n.style.display="",n},isActivePath:(e,t)=>L.env.dispatchpath[1]===e&&(null==t||L.env.dispatchpath[2]===t),buildNavigationModel(e,t){return e.filter(e=>e?.name).map(e=>{const i=ui.menu.getChildren(e).filter(e=>e?.name).map(i=>({name:i.name,title:_(i.title),href:L.url(t,e.name,i.name),isActivePage:this.isActivePath(e.name,i.name)})),a=i.length>0,n=this.isActivePath(e.name);return{name:e.name,title:_(e.title),href:L.url(t,e.name),hasChildren:a,isLogout:"logout"===e.name,isActiveGroup:a&&n,isActivePage:!a&&n,activePage:i.find(e=>e.isActivePage)||null,pages:i}})},navigationSubmenuId:(e,t)=>`${e}-submenu-${encodeURIComponent(String(t))}`,renderNavigationItem(e,t){const i="mobile"===t,a=i?"mobile-nav-item":"",n=i?"navigation-direct mobile-nav-link":"navigation-direct nav-link";if(!e.hasChildren){const t={class:`${n}${e.isActivePage?" is-active-page":""}`,href:e.href};return e.isActivePage&&(t["aria-current"]="page"),E("li",{class:a},[E("a",t,[e.title])])}const s=this.navigationSubmenLine truncated