@aquera/nile-elements 2.0.11 → 2.0.12
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 +3 -0
- package/demo/app-shell.html +21 -21
- package/dist/index.js +76 -66
- package/dist/nile-app-shell/nile-app-shell.cjs.js +1 -1
- package/dist/nile-app-shell/nile-app-shell.cjs.js.map +1 -1
- package/dist/nile-app-shell/nile-app-shell.css.cjs.js +1 -1
- package/dist/nile-app-shell/nile-app-shell.css.cjs.js.map +1 -1
- package/dist/nile-app-shell/nile-app-shell.css.esm.js +35 -32
- package/dist/nile-app-shell/nile-app-shell.esm.js +39 -34
- package/dist/nile-app-shell-panel/nile-app-shell-panel.css.cjs.js +1 -1
- package/dist/nile-app-shell-panel/nile-app-shell-panel.css.cjs.js.map +1 -1
- package/dist/nile-app-shell-panel/nile-app-shell-panel.css.esm.js +3 -1
- package/dist/src/nile-app-shell/nile-app-shell-regions.test.js +9 -5
- package/dist/src/nile-app-shell/nile-app-shell-regions.test.js.map +1 -1
- package/dist/src/nile-app-shell/nile-app-shell.css.js +33 -30
- package/dist/src/nile-app-shell/nile-app-shell.css.js.map +1 -1
- package/dist/src/nile-app-shell/nile-app-shell.d.ts +22 -22
- package/dist/src/nile-app-shell/nile-app-shell.js +86 -76
- package/dist/src/nile-app-shell/nile-app-shell.js.map +1 -1
- package/dist/src/nile-app-shell/nile-app-shell.test.d.ts +1 -0
- package/dist/src/nile-app-shell/nile-app-shell.test.js +307 -89
- package/dist/src/nile-app-shell/nile-app-shell.test.js.map +1 -1
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.css.js +3 -1
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.css.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/nile-app-shell/nile-app-shell-regions.test.ts +9 -5
- package/src/nile-app-shell/nile-app-shell.css.ts +33 -30
- package/src/nile-app-shell/nile-app-shell.test.ts +348 -105
- package/src/nile-app-shell/nile-app-shell.ts +89 -82
- package/src/nile-app-shell-panel/nile-app-shell-panel.css.ts +3 -1
- package/vscode-html-custom-data.json +27 -37
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nile-app-shell.cjs.js","sources":["../../../src/nile-app-shell/nile-app-shell.ts"],"sourcesContent":["/**\n * Copyright Aquera Inc 2023\n *\n * This source code is licensed under the BSD-3-Clause license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { html, CSSResultArray, TemplateResult, PropertyValues } from 'lit';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { styles } from './nile-app-shell.css';\nimport { renderGlyph } from '../internal/glyph';\nimport NileElement from '../internal/nile-element';\nimport '../nile-button/nile-button';\n\n/** The mode the AI panel is currently in. */\nexport type NileAppShellPanelMode = 'docked' | 'overlay';\n\n/** Where the top bar is mounted. */\nexport type NileAppShellTopBarPlacement = 'content' | 'shell';\n\n/** How the main region lays its content out. */\nexport type NileAppShellContentAlign = 'fluid' | 'centered';\n\n/** What sits before the page title in the top bar. */\nexport type NileAppShellLeading = 'none' | 'back' | 'app-icon';\n\n/** The shell's own track and region widths, in px. */\ninterface ShellGeometry {\n nav: number;\n rail: number;\n gutter: number;\n content: number;\n aside: number;\n panel: number;\n}\n\n/**\n * @summary The application frame every route inherits: a side nav, a content container, an optional aside and an AI assistant panel.\n *\n * @status stable\n * @since 2.0\n *\n * @tag nile-app-shell\n *\n * @dependency nile-button\n * @dependency nile-glyph\n *\n * @slot - The page body, inside the content container.\n * @slot banner - A full-width strip above every other region.\n * @slot top-bar - The page-title bar, mounted inside the container by default or spanning the shell when `top-bar-placement=\"shell\"`.\n * @slot top-bar-actions - Controls pinned to the end of the top bar.\n * @slot tabs - A hoisted second-level tab strip, flush under the top bar and outside `<main>`'s scroller.\n * @slot app-icon - The mark shown when `leading=\"app-icon\"`, clipped to the shell's box.\n * @slot side-nav - The navigation track. Works best with `<nile-side-bar>`.\n * @slot aside - A secondary column between the content container and the panel.\n * @slot panel - The AI panel's body. When empty the panel is unmounted and `openPanel()` is a no-op.\n * @slot panel-header - Replaces the default panel heading (mark plus title).\n * @slot panel-actions - Controls added before the panel's close button.\n * @slot panel-footer - A bar docked below the panel's scroll region, for a composer.\n *\n * @event nile-nav-toggle - Emitted after the nav's collapsed state or forced-rail lock changes. `detail: { collapsed, locked }`.\n * @event nile-panel-toggle - Emitted after the panel opens or closes. `detail: { open, mode }`.\n * @event nile-panel-mode-change - Emitted when the panel flips between docked and overlay. `detail: { mode }`.\n * @event nile-header-back - Emitted when the header's back control is pressed.\n * @event nile-panel-back - Emitted when the panel's back control is pressed, whether the shell's built-in panel chrome or a slotted `nile-app-shell-panel` draws it.\n *\n * @csspart skip-link - The skip-to-content link.\n * @csspart banner - The banner region.\n * @csspart shell-top-bar - The top bar when it spans the shell.\n * @csspart top-bar - The top bar, in either placement.\n * @csspart nav-toggle - The built-in nav toggle button.\n * @csspart rule - The vertical rule after the nav toggle.\n * @csspart top-bar-actions - The end-aligned top bar action group.\n * @csspart ask - The built-in Ask button, the shell's single door to the panel.\n * @csspart title-area - The header's own title block: leading, title, badge and description.\n * @csspart page-title - The title text, exposed as a heading whose level `headingLevel` sets.\n * @csspart description - The second line under the title.\n * @csspart badge - The pill after the title.\n * @csspart leading - The line box holding the leading control.\n * @csspart back - The back control shown by `leading=\"back\"`.\n * @csspart app-icon - The block shown by `leading=\"app-icon\"`, sized by `--nile-app-shell-app-icon-size`.\n * @csspart tabs - The hoisted tab-strip region, under the top bar.\n * @csspart side-nav - The navigation track.\n * @csspart content-section - The flex row holding container, aside and panel.\n * @csspart container - The content container.\n * @csspart main - The scrolling page body.\n * @csspart aside - The aside region.\n * @csspart panel - The AI panel.\n * @csspart panel-header - The panel's header bar.\n * @csspart panel-back - The panel's back control, shown by `panelBack`.\n * @csspart panel-title - The panel's title text.\n * @csspart panel-actions - The panel's header action group.\n * @csspart panel-close - The panel's close button.\n * @csspart panel-body - The panel's scroll region.\n * @csspart panel-footer - The panel's footer.\n *\n * @cssproperty [--nile-app-shell-side-nav-width=240px] - Expanded nav track.\n * @cssproperty [--nile-app-shell-side-nav-rail-width=70px] - Collapsed track.\n * @cssproperty [--nile-app-shell-side-nav-bg=transparent] - Surface behind a slotted side nav.\n * @cssproperty [--nile-app-shell-side-nav-border=0] - Edge on a slotted side nav.\n * @cssproperty [--nile-app-shell-gutter=4px] - Content-section padding, and the gap between container, aside and panel.\n * @cssproperty [--nile-app-shell-content-padding=24px] - Container inner padding.\n * @cssproperty [--nile-app-shell-top-bar-height=68px] - Top bar height.\n * @cssproperty [--nile-app-shell-panel-header-height=56px] - The panel header's own height.\n * @cssproperty [--nile-app-shell-tabs-height=33px] - Tab strip height.\n * @cssproperty [--nile-app-shell-panel-width=480px] - Docked panel width, and the `min()` ceiling for the overlay drawer.\n * @cssproperty [--nile-app-shell-panel-min-width=360px] - How far a docked panel shrinks to keep pushing rather than covering the page.\n * @cssproperty [--nile-app-shell-aside-width=320px] - Aside width.\n * @cssproperty [--nile-app-shell-aside-min-width=240px] - How far the aside shrinks before the page is asked for room.\n * @cssproperty [--nile-app-shell-content-min-width=640px] - Container floor.\n * @cssproperty [--nile-app-shell-min-width=768px] - Below this the window scrolls rather than the shell compressing.\n * @cssproperty [--nile-app-shell-centered-width=824px] - Column width under `content-align=\"centered\"`.\n * @cssproperty [--nile-app-shell-app-icon-size=20px] - The leading app icon's box.\n * @cssproperty [--nile-app-shell-utility-size=32px] - Box the shell's own icon controls sit in.\n * @cssproperty [--nile-app-shell-radius=16px] - Container, aside and panel radius.\n * @cssproperty [--nile-app-shell-duration=250ms] - Track and panel motion.\n * @cssproperty [--nile-app-shell-ease] - Easing for moves and resizes.\n *\n * @method openPanel() - Open the AI panel. No-op when the panel is unavailable.\n * @method closePanel() - Close the AI panel.\n * @method togglePanel(force?) - Toggle, or force a specific open state.\n * @method expandNav() - Expand the side nav.\n * @method collapseNav() - Collapse the side nav to a rail.\n * @method toggleNav(force?) - Toggle, or force a specific collapsed state.\n * @method goBackHeader() - Emit `nile-header-back`, as the header's back control does.\n * @method goBackPanel() - Emit `nile-panel-back`, as the panel's back control does.\n * @method goBackPage() - Deprecated alias of `goBackHeader()`.\n * @method goBack() - Deprecated alias of `goBackPanel()`.\n */\n@customElement('nile-app-shell')\nexport class NileAppShell extends NileElement {\n public static get styles(): CSSResultArray {\n return [styles];\n }\n\n /** The user's nav preference. The nav can still render as a rail while this is false — see `navLocked`. */\n @property({ type: Boolean, reflect: true, attribute: 'nav-collapsed' })\n navCollapsed: boolean = false;\n\n /** Whether the AI panel is open. */\n @property({ type: Boolean, reflect: true, attribute: 'panel-open' })\n panelOpen: boolean = false;\n\n /** Unmounts the AI panel for this route even when the `panel` slot is filled; `openPanel()` becomes a no-op. */\n @property({ type: Boolean, reflect: true, attribute: 'no-panel' })\n noPanel: boolean = false;\n\n /** The default panel heading. Ignored when `panel-header` is slotted. */\n @property({ type: String, attribute: 'panel-label' })\n panelLabel: string = 'Ask Aquera';\n\n /** The page title, rendered as the top bar's own heading (`role=\"heading\"`, level from `headingLevel`) before anything slotted into `top-bar`; leave unset and no title block renders. */\n @property({ type: String, attribute: true, reflect: true })\n pageTitle?: string;\n\n /** The `aria-level` of the `pageTitle` heading, 1–6, so the title can fit the page's own heading outline; e.g. 2 when the page body or banner already has its h1. Out-of-range values clamp to 1–6 and non-numbers fall back to 1. */\n @property({ type: Number, attribute: true, reflect: true })\n headingLevel: number = 1;\n\n /** A second line under the page title; a modifier on `pageTitle` that renders nothing with no title, and takes the bar to 76px. */\n @property({ type: String, attribute: true, reflect: true })\n description?: string;\n\n /** A pill after the page title; a modifier on `pageTitle` like `description`, so with no title there is no badge. */\n @property({ type: String, attribute: true, reflect: true })\n badge?: string;\n\n /** What sits before the page title: `back` draws a breadcrumb and emits `nile-header-back`; `app-icon` draws a 20px block for the `app-icon` slot. */\n @property({ type: String, attribute: true, reflect: true })\n leading: NileAppShellLeading = 'none';\n\n /** The previous-page label drawn by `leading=\"back\"`. */\n @property({ type: String, attribute: true, reflect: true })\n backLabel: string = 'Back';\n\n /** Hides the built-in nav toggle. Mount `nile-app-shell-nav-toggle` yourself. */\n @property({ type: Boolean, reflect: true, attribute: 'no-nav-toggle' })\n noNavToggle: boolean = false;\n\n /** Drops the Cmd/Ctrl+J and Escape panel shortcuts. */\n @property({ type: Boolean, attribute: 'no-panel-shortcut' })\n noPanelShortcut: boolean = false;\n\n /** Hides the skip-to-content link. */\n @property({ type: Boolean, reflect: true, attribute: 'no-skip-link' })\n noSkipLink: boolean = false;\n\n /** Label for the skip-to-content link. */\n @property({ type: String, attribute: 'skip-link-label' })\n skipLinkLabel: string = 'Skip to main content';\n\n /** Where the top bar is mounted: inside the container, or spanning the shell. */\n @property({ type: String, reflect: true, attribute: 'top-bar-placement' })\n topBarPlacement: NileAppShellTopBarPlacement = 'content';\n\n /** `centered` caps the page body at `--nile-app-shell-centered-width`. */\n @property({ type: String, reflect: true, attribute: 'content-align' })\n contentAlign: NileAppShellContentAlign = 'fluid';\n\n /** Makes the slotted page root a size query container, so page CSS can size against the content container instead of the viewport. */\n @property({ type: Boolean, reflect: true, attribute: 'content-container' })\n contentContainer: boolean = false;\n\n /** Drops the container's card chrome for a full-bleed page. */\n @property({ type: Boolean, reflect: true })\n flat: boolean = false;\n\n /** Removes the container's inner padding. */\n @property({ type: Boolean, reflect: true, attribute: 'no-padding' })\n noPadding: boolean = false;\n\n /** The label on the built-in Ask button. */\n @property({ type: String, attribute: 'ask-label' })\n askLabel: string = 'Ask';\n\n /** Drops the built-in Ask button, for a bar that renders its own. */\n @property({ type: Boolean, reflect: true, attribute: 'no-ask' })\n noAsk: boolean = false;\n\n /** Shows a back control at the start of the panel header for a panel sub-view; emits `nile-panel-back`. */\n @property({ type: Boolean, reflect: true })\n panelBack: boolean = false;\n\n /** Accessible name of the panel's back control. */\n @property({ type: String })\n panelBackLabel: string = 'Back';\n\n /** Hides the tab strip for this route even when the `tabs` slot is filled. */\n @property({ type: Boolean, reflect: true })\n noTabs: boolean = false;\n\n /** Sizes the shell to the viewport instead of its parent. */\n @property({ type: Boolean, reflect: true, attribute: 'full-height' })\n fullHeight: boolean = false;\n\n /** Below this shell width the panel overlays the content instead of pushing it, and the nav is forced to a rail; zero (default) means never. */\n @property({ type: Number, attribute: 'overlay-breakpoint' })\n overlayBreakpoint: number = 0;\n\n /** Below this shell width an open docked panel forces the nav to a rail. */\n @property({ type: Number, attribute: 'docked-rail-breakpoint' })\n dockedRailBreakpoint: number = 1440;\n\n /** Persists the nav preference and docked panel state under this key. Overlay panel state is never persisted. */\n @property({ type: String, attribute: 'persist-key' })\n persistKey?: string;\n\n /** The panel's current mode. Derived from the shell's width. */\n @state() private _panelMode: NileAppShellPanelMode = 'docked';\n\n /** Whether the nav is held at a rail by the shell's width. */\n @state() private _navLocked: boolean = false;\n\n @state() private _hasBanner: boolean = false;\n @state() private _hasSideNav: boolean = false;\n @state() private _hasTopBar: boolean = false;\n @state() private _hasTopBarActions: boolean = false;\n @state() private _hasTabs: boolean = false;\n @state() private _hasPanel: boolean = false;\n @state() private _hasPanelFooter: boolean = false;\n\n /** True when a `nile-app-shell-panel` is slotted, owning the panel's own chrome so the shell renders a bare region. */\n @state() private _panelOwnsChrome: boolean = false;\n @state() private _hasAside: boolean = false;\n\n @query('.main') private _main?: HTMLElement;\n\n private _width: number = 0;\n private _resizeObserver?: ResizeObserver;\n private _restoredPanelOpen: boolean | null = null;\n\n /** The panel's current mode: `docked` or `overlay`. */\n public get panelMode(): NileAppShellPanelMode {\n return this._panelMode;\n }\n\n /** Whether the shell is holding the nav at a rail. The toggle is disabled. */\n public get navLocked(): boolean {\n return this._navLocked;\n }\n\n /** Whether a panel is mounted for this route. */\n public get panelAvailable(): boolean {\n return this._hasPanel && !this.noPanel;\n }\n\n /** Whether the tab strip is rendered: something slotted, and not switched off. */\n public get tabsVisible(): boolean {\n return this._hasTabs && !this.noTabs;\n }\n\n /** Whether the built-in Ask button is rendered. */\n public get askVisible(): boolean {\n return this.panelAvailable && !this.noAsk;\n }\n\n /** Whether the nav renders as a rail right now, preference or lock. */\n public get rail(): boolean {\n return this.navCollapsed || this._navLocked;\n }\n\n public connectedCallback(): void {\n super.connectedCallback();\n this._restore();\n this._resizeObserver = new ResizeObserver(entries => {\n const entry = entries[entries.length - 1];\n this._measure(entry.contentRect.width);\n });\n this._resizeObserver.observe(this);\n document.addEventListener('keydown', this._onKeyDown);\n }\n\n public disconnectedCallback(): void {\n super.disconnectedCallback();\n this._resizeObserver?.disconnect();\n this._resizeObserver = undefined;\n document.removeEventListener('keydown', this._onKeyDown);\n }\n\n protected willUpdate(changed: PropertyValues<this>): void {\n if (\n changed.has('panelOpen') ||\n changed.has('noPanel') ||\n changed.has('overlayBreakpoint') ||\n changed.has('dockedRailBreakpoint') ||\n // Aside/side-nav mounting changes what a docked panel fits beside; ask the map since private state is outside `keyof this`.\n (changed as Map<string, unknown>).has('_hasAside') ||\n (changed as Map<string, unknown>).has('_hasSideNav')\n ) {\n this._recompute();\n }\n }\n\n protected updated(changed: PropertyValues<this>): void {\n super.updated(changed);\n\n // Derived state the stylesheet and consumers read off the host.\n this.toggleAttribute('rail', this.rail);\n this.toggleAttribute('nav-locked', this._navLocked);\n this.toggleAttribute('has-banner', this._hasBanner);\n this.toggleAttribute('has-side-nav', this._hasSideNav);\n this.toggleAttribute(\n 'has-top-bar',\n this._hasTopBar ||\n this._hasTitleBlock ||\n (!this.noNavToggle && this._hasSideNav)\n );\n // Only with a title to sit under: see _hasTitleBlock.\n this.toggleAttribute(\n 'has-description',\n !!this.description && !!this.pageTitle\n );\n this.toggleAttribute('has-top-bar-actions', this._hasTopBarActions);\n this.toggleAttribute('has-ask', this.askVisible);\n this.toggleAttribute('has-tabs', this.tabsVisible);\n this.toggleAttribute('has-aside', this._hasAside);\n this.toggleAttribute('has-panel', this.panelAvailable);\n this.toggleAttribute('has-panel-footer', this._hasPanelFooter);\n this.setAttribute('panel-mode', this._panelMode);\n this.setAttribute(\n 'panel-chrome',\n this._panelOwnsChrome ? 'external' : 'internal'\n );\n\n this._syncSideNav();\n }\n\n /** Open the AI panel. No-op when no panel is mounted for this route. */\n public openPanel(): void {\n if (!this.panelAvailable) return;\n this._setPanelOpen(true);\n }\n\n /** Close the AI panel. */\n public closePanel(): void {\n this._setPanelOpen(false);\n }\n\n /** Toggle the panel, or force a state. */\n public togglePanel(force?: boolean): void {\n const next = force ?? !this.panelOpen;\n if (next) this.openPanel();\n else this.closePanel();\n }\n\n /** Emit `nile-header-back`, as the header's back control does; the page owns the history. */\n public goBackHeader(): void {\n this.emit('nile-header-back');\n }\n\n /** Emit `nile-panel-back`, as the panel's back control does; the page owns the view stack. */\n public goBackPanel(): void {\n this.emit('nile-panel-back');\n }\n\n /** @deprecated Use `goBackHeader()`; kept as an alias that emits `nile-header-back`. */\n public goBackPage(): void {\n this.goBackHeader();\n }\n\n /** @deprecated Use `goBackPanel()`; kept as an alias that emits `nile-panel-back`. */\n public goBack(): void {\n this.goBackPanel();\n }\n\n /** Expand the side nav. */\n public expandNav(): void {\n this._setNavCollapsed(false);\n }\n\n /** Collapse the side nav to a rail. */\n public collapseNav(): void {\n this._setNavCollapsed(true);\n }\n\n /** Toggle the side nav, or force a collapsed state. */\n public toggleNav(force?: boolean): void {\n this._setNavCollapsed(force ?? !this.navCollapsed);\n }\n\n /** Move focus to the page body. */\n public focusMain(): void {\n this._main?.focus();\n }\n\n private _setPanelOpen(value: boolean): void {\n if (this.panelOpen === value) return;\n this.panelOpen = value;\n this._persist();\n this.emit('nile-panel-toggle', { open: value, mode: this._panelMode });\n }\n\n private _setNavCollapsed(value: boolean): void {\n if (this.navCollapsed === value) return;\n this.navCollapsed = value;\n this._persist();\n this.emit('nile-nav-toggle', {\n collapsed: value,\n locked: this._navLocked,\n });\n }\n\n /** Records the shell's width and re-derives everything that depends on it. */\n private _measure(width: number): void {\n if (width === this._width) return;\n const first = this._width === 0;\n this._width = width;\n this._recompute();\n\n // A persisted panel state only applies once we know the panel would dock.\n if (first && this._restoredPanelOpen !== null) {\n const open = this._restoredPanelOpen;\n this._restoredPanelOpen = null;\n if (open && this._panelMode === 'docked') this.openPanel();\n }\n }\n\n /** The shell's geometry, read off its own custom properties, falling back to defaults before a computed style exists. */\n private _geometry(): ShellGeometry {\n const style = getComputedStyle(this);\n const px = (name: string, fallback: number): number => {\n const value = parseFloat(style.getPropertyValue(name));\n return Number.isFinite(value) ? value : fallback;\n };\n return {\n // Read the substituted value so they follow the active theme; the literals are the enterprise fallback.\n nav: px('--nile-app-shell-side-nav-width', 240),\n rail: px('--nile-app-shell-side-nav-rail-width', 70),\n gutter: px('--nile-app-shell-gutter', 4),\n content: px('--nile-app-shell-content-min-width', 640),\n aside: px('--nile-app-shell-aside-width', 320),\n panel: px('--nile-app-shell-panel-width', 480),\n };\n }\n\n /** The shell width a docked panel needs to sit beside the content floor, over a side-nav `track` wide. */\n private _dockRequirement(geo: ShellGeometry, track: number): number {\n const nav = this._hasSideNav ? track : 0;\n const aside = this._hasAside ? geo.aside + geo.gutter : 0;\n /* The content row's chrome is end-edge padding plus one flex gap between container and panel (an aside carries its own gap above), and start-edge padding too when no nav track is there to sit flush against. */\n const gutters = this._hasSideNav ? 2 : 3;\n return nav + geo.content + aside + geo.panel + geo.gutter * gutters;\n }\n\n private _recompute(): void {\n const width = this._width;\n const geo = this._geometry();\n\n /* Overlay is opt-in: the shell only overlays below a width the author names, never from running out of room. */\n const overlay =\n this.overlayBreakpoint > 0 && width > 0 && width < this.overlayBreakpoint;\n const mode: NileAppShellPanelMode = overlay ? 'overlay' : 'docked';\n\n // A docked panel squeezes the container, so a narrow shell trades the expanded nav for content width, measured against the expanded track.\n const railAt = Math.max(\n this.dockedRailBreakpoint,\n this._dockRequirement(geo, geo.nav)\n );\n const squeezed =\n !overlay &&\n this.panelOpen &&\n this.panelAvailable &&\n width > 0 &&\n width < railAt;\n const locked = overlay || squeezed;\n\n if (mode !== this._panelMode) {\n this._panelMode = mode;\n this.emit('nile-panel-mode-change', { mode });\n }\n\n if (locked !== this._navLocked) {\n this._navLocked = locked;\n this.emit('nile-nav-toggle', {\n collapsed: this.navCollapsed,\n locked,\n });\n }\n }\n\n /** Mirrors the effective rail state onto a slotted `nile-side-bar`. */\n private _syncSideNav(): void {\n this.querySelectorAll('[slot=\"side-nav\"]').forEach(el => {\n if (el.tagName === 'NILE-SIDE-BAR')\n el.toggleAttribute('collapsed', this.rail);\n });\n }\n\n /** A slotted sidebar's own expand button is the same toggle. */\n private _onSideNavToggle = (event: Event): void => {\n const detail = (event as CustomEvent).detail;\n if (detail && typeof detail.collapsed === 'boolean') {\n this._setNavCollapsed(detail.collapsed);\n }\n };\n\n private _onKeyDown = (event: KeyboardEvent): void => {\n if (this.noPanelShortcut || !this.panelAvailable) return;\n\n const key = event.key ?? '';\n\n if ((event.metaKey || event.ctrlKey) && key.toLowerCase() === 'j') {\n event.preventDefault();\n this.togglePanel();\n return;\n }\n\n // A docked panel is furniture, not a dismissible overlay.\n if (key === 'Escape' && this.panelOpen && this._panelMode === 'overlay') {\n this.closePanel();\n }\n };\n\n private _storageKey(part: string): string {\n return `nile-app-shell:${this.persistKey}:${part}`;\n }\n\n private _restore(): void {\n if (!this.persistKey) return;\n try {\n const nav = localStorage.getItem(this._storageKey('nav-collapsed'));\n if (nav !== null) this.navCollapsed = nav === 'true';\n const panel = localStorage.getItem(this._storageKey('panel-open'));\n if (panel !== null) this._restoredPanelOpen = panel === 'true';\n } catch {\n /* Storage can be blocked; the shell still works without it. */\n }\n }\n\n private _persist(): void {\n if (!this.persistKey) return;\n try {\n localStorage.setItem(\n this._storageKey('nav-collapsed'),\n String(this.navCollapsed)\n );\n if (this._panelMode === 'docked') {\n localStorage.setItem(\n this._storageKey('panel-open'),\n String(this.panelOpen)\n );\n }\n } catch {\n /* Storage can be blocked; the shell still works without it. */\n }\n }\n\n private _onSlotChange(slot: string, event: Event): void {\n const assigned = (event.target as HTMLSlotElement).assignedNodes({\n flatten: true,\n });\n const filled = assigned.some(\n node =>\n node.nodeType === Node.ELEMENT_NODE ||\n (node.textContent ?? '').trim() !== ''\n );\n\n switch (slot) {\n case 'banner':\n this._hasBanner = filled;\n break;\n case 'side-nav':\n this._hasSideNav = filled;\n this._syncSideNav();\n break;\n case 'top-bar':\n this._hasTopBar = filled;\n break;\n case 'top-bar-actions':\n this._hasTopBarActions = filled;\n break;\n case 'tabs':\n this._hasTabs = filled;\n break;\n case 'aside':\n this._hasAside = filled;\n break;\n case 'panel':\n this._hasPanel = filled;\n this._panelOwnsChrome = assigned.some(\n node =>\n node.nodeType === Node.ELEMENT_NODE &&\n (node as Element).tagName === 'NILE-APP-SHELL-PANEL'\n );\n this._recompute();\n break;\n case 'panel-footer':\n this._hasPanelFooter = filled;\n break;\n default:\n break;\n }\n }\n\n private _renderNavToggle(): TemplateResult | string {\n if (this.noNavToggle || !this._hasSideNav) return '';\n const expanded = !this.rail;\n return html`\n <div class=\"nav-toggle-group\">\n <nile-button\n class=\"nav-toggle utility-control\"\n part=\"nav-toggle\"\n variant=\"ghost\"\n circle\n aria-controls=\"side-nav\"\n aria-expanded=${expanded ? 'true' : 'false'}\n ?disabled=${this._navLocked}\n title=${this._navLocked\n ? 'The navigation stays collapsed at this window width'\n : expanded\n ? 'Collapse navigation'\n : 'Expand navigation'}\n aria-label=${expanded ? 'Collapse navigation' : 'Expand navigation'}\n @click=${() => this.toggleNav()}\n >\n ${renderGlyph(\n expanded ? 'ng-panel-left' : 'ng-panel-right',\n 20,\n 'currentColor'\n )}\n </nile-button>\n ${this._hasTopBar || this._hasTitleBlock\n ? html`<span class=\"rule\" part=\"rule\"></span>`\n : ''}\n </div>\n `;\n }\n\n /** Whether the header has a title block of its own to draw: only a title or a leading control mounts it. */\n private get _hasTitleBlock(): boolean {\n return !!this.pageTitle || this._hasLeading;\n }\n\n /** Whether `leading` names a control that renders; an empty or unknown value draws nothing, like `none`. */\n private get _hasLeading(): boolean {\n return this.leading === 'back' || this.leading === 'app-icon';\n }\n\n /** `headingLevel` as a safe `aria-level`: a whole number clamped to 1–6, and 1 for anything non-numeric. */\n private get _headingLevel(): number {\n const level = Math.trunc(Number(this.headingLevel));\n return Number.isFinite(level) ? Math.min(6, Math.max(1, level)) : 1;\n }\n\n private _renderLeading(): TemplateResult | string {\n if (this.leading === 'app-icon') {\n return html`\n <span class=\"app-icon\" part=\"app-icon\">\n <slot name=\"app-icon\"></slot>\n </span>\n `;\n }\n\n if (this.leading === 'back') {\n return html`\n <button\n class=\"back\"\n part=\"back\"\n type=\"button\"\n @click=${() => this.goBackHeader()}\n >\n ${renderGlyph('ng-chevron-left', 20, 'currentColor')}\n <span>${this.backLabel}</span>\n </button>\n ${this.pageTitle\n ? html`<span class=\"crumb-divider\" aria-hidden=\"true\">\n ${renderGlyph('ng-slash', 16, 'currentColor')}\n </span>`\n : ''}\n `;\n }\n\n return '';\n }\n\n private _renderTitleBlock(): TemplateResult | string {\n if (!this._hasTitleBlock) return '';\n\n /* Both leading modes render beside the title stack, never inside the title row, so the description stays under the page title in every leading mode. */\n return html`\n <div class=\"title-area\" part=\"title-area\">\n ${this._hasLeading\n ? html`<span class=\"leading\" part=\"leading\"\n >${this._renderLeading()}</span\n >`\n : ''}\n ${this.pageTitle\n ? html`\n <div class=\"title-stack\">\n <div class=\"title-row\">\n <div\n class=\"page-title\"\n part=\"page-title\"\n role=\"heading\"\n aria-level=${this._headingLevel}\n >${this.pageTitle}</div>\n ${this.badge\n ? html`<span class=\"badge\" part=\"badge\">${this.badge}</span>`\n : ''}\n </div>\n ${this.description\n ? html`<p class=\"description\" part=\"description\">\n ${this.description}\n </p>`\n : ''}\n </div>\n `\n : ''}\n </div>\n `;\n }\n\n private _renderTopBar(\n placement: NileAppShellTopBarPlacement\n ): TemplateResult {\n return html`\n <div\n class=${placement === 'shell' ? 'top-bar shell-top-bar' : 'top-bar'}\n part=${placement === 'shell' ? 'top-bar shell-top-bar' : 'top-bar'}\n >\n ${this._renderNavToggle()}\n <div class=\"top-bar-content\">\n ${this._renderTitleBlock()}\n <slot\n name=\"top-bar\"\n @slotchange=${(e: Event) => this._onSlotChange('top-bar', e)}\n ></slot>\n </div>\n <div class=\"top-bar-actions\" part=\"top-bar-actions\">\n <slot\n name=\"top-bar-actions\"\n @slotchange=${(e: Event) =>\n this._onSlotChange('top-bar-actions', e)}\n ></slot>\n ${this.askVisible\n ? html`\n <nile-button\n class=\"ask\"\n part=\"ask\"\n exportparts=\"base: ask__base, label: ask__label\"\n variant=\"primary\"\n @click=${() => this.openPanel()}\n >\n <span slot=\"prefix\" class=\"ask-mark\">\n ${renderGlyph('ng-sparkles', 16, 'currentColor')}\n </span>\n ${this.askLabel}\n </nile-button>\n `\n : ''}\n </div>\n </div>\n `;\n }\n\n public render(): TemplateResult {\n const shellBar = this.topBarPlacement === 'shell';\n\n return html`\n <button\n class=\"skip-link\"\n part=\"skip-link\"\n type=\"button\"\n @click=${() => this.focusMain()}\n >\n ${this.skipLinkLabel}\n </button>\n\n <div class=\"banner\" part=\"banner\">\n <slot\n name=\"banner\"\n @slotchange=${(e: Event) => this._onSlotChange('banner', e)}\n ></slot>\n </div>\n\n ${shellBar ? this._renderTopBar('shell') : ''}\n\n <div\n id=\"side-nav\"\n class=\"side-nav\"\n part=\"side-nav\"\n @nile-toggle=${this._onSideNavToggle}\n >\n <slot\n name=\"side-nav\"\n @slotchange=${(e: Event) => this._onSlotChange('side-nav', e)}\n ></slot>\n </div>\n\n <div class=\"content-section\" part=\"content-section\">\n <div class=\"container\" part=\"container\">\n ${shellBar ? '' : this._renderTopBar('content')}\n <div class=\"tabs\" part=\"tabs\">\n <slot\n name=\"tabs\"\n @slotchange=${(e: Event) => this._onSlotChange('tabs', e)}\n ></slot>\n </div>\n <main class=\"main\" part=\"main\" tabindex=\"-1\">\n <div class=\"main-inner\"><slot></slot></div>\n </main>\n </div>\n\n <div class=\"aside\" part=\"aside\">\n <slot\n name=\"aside\"\n @slotchange=${(e: Event) => this._onSlotChange('aside', e)}\n ></slot>\n </div>\n\n <aside\n class=\"panel\"\n part=\"panel\"\n aria-label=${ifDefined(\n this._panelOwnsChrome ? undefined : this.panelLabel\n )}\n aria-hidden=${this.panelOpen ? 'false' : 'true'}\n >\n ${this._panelOwnsChrome\n ? html`<slot\n name=\"panel\"\n @slotchange=${(e: Event) => this._onSlotChange('panel', e)}\n ></slot>`\n : html`\n <header class=\"panel-header\" part=\"panel-header\">\n ${this.panelBack\n ? html`<nile-button\n class=\"panel-back utility-control\"\n part=\"panel-back\"\n variant=\"ghost\"\n circle\n title=${this.panelBackLabel}\n aria-label=${this.panelBackLabel}\n @click=${() => this.goBackPanel()}\n >\n ${renderGlyph('ng-arrow-left', 20, 'currentColor')}\n </nile-button>`\n : ''}\n <slot name=\"panel-header\">\n <span class=\"panel-heading\">\n <span class=\"panel-mark\">\n ${renderGlyph('ng-sparkles', 20, 'currentColor')}\n </span>\n <h2 class=\"panel-title\" part=\"panel-title\">\n ${this.panelLabel}\n </h2>\n </span>\n </slot>\n <div class=\"panel-actions\" part=\"panel-actions\">\n <slot name=\"panel-actions\"></slot>\n <nile-button\n class=\"panel-close utility-control\"\n part=\"panel-close\"\n variant=\"ghost\"\n circle\n title=\"Close ${this.panelLabel}\"\n aria-label=\"Close ${this.panelLabel}\"\n @click=${() => this.closePanel()}\n >\n ${renderGlyph('ng-x-close', 20, 'currentColor')}\n </nile-button>\n </div>\n </header>\n <div class=\"panel-body\" part=\"panel-body\">\n <slot\n name=\"panel\"\n @slotchange=${(e: Event) => this._onSlotChange('panel', e)}\n ></slot>\n </div>\n <div class=\"panel-footer\" part=\"panel-footer\">\n <slot\n name=\"panel-footer\"\n @slotchange=${(e: Event) =>\n this._onSlotChange('panel-footer', e)}\n ></slot>\n </div>\n `}\n </aside>\n </div>\n `;\n }\n}\n\nexport default NileAppShell;\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nile-app-shell': NileAppShell;\n }\n}\n"],"names":["NileAppShell","_j","p","constructor","this","navCollapsed","panelOpen","noPanel","panelLabel","headingLevel","leading","backLabel","noNavToggle","noPanelShortcut","noSkipLink","skipLinkLabel","topBarPlacement","contentAlign","contentContainer","flat","noPadding","askLabel","noAsk","panelBack","panelBackLabel","noTabs","fullHeight","overlayBreakpoint","dockedRailBreakpoint","_panelMode","_navLocked","_hasBanner","_hasSideNav","_hasTopBar","_hasTopBarActions","_hasTabs","_hasPanel","_hasPanelFooter","_panelOwnsChrome","_hasAside","_width","_restoredPanelOpen","_onSideNavToggle","event","detail","collapsed","_setNavCollapsed","_onKeyDown","panelAvailable","key","_i$key","metaKey","ctrlKey","toLowerCase","preventDefault","togglePanel","closePanel","_this","_inherits","_createClass","get","askVisible","value","connectedCallback","super","_restore","_resizeObserver","ResizeObserver","entries","entry","length","_measure","contentRect","width","observe","document","addEventListener","disconnectedCallback","disconnect","undefined","removeEventListener","willUpdate","changed","has","_recompute","updated","toggleAttribute","rail","_hasTitleBlock","description","pageTitle","tabsVisible","setAttribute","_syncSideNav","openPanel","_setPanelOpen","force","goBackHeader","emit","goBackPanel","goBackPage","goBack","expandNav","collapseNav","toggleNav","focusMain","_main","focus","_persist","open","mode","locked","first","_geometry","style","getComputedStyle","px","name","fallback","parseFloat","getPropertyValue","Number","isFinite","nav","gutter","content","aside","panel","_dockRequirement","geo","track","gutters","overlay","railAt","Math","max","squeezed","querySelectorAll","forEach","el","tagName","_storageKey","part","concat","persistKey","localStorage","getItem","_unused","setItem","String","_unused2","_onSlotChange","slot","assigned","target","assignedNodes","flatten","filled","some","node","nodeType","Node","ELEMENT_NODE","textContent","trim","_renderNavToggle","expanded","html","_templateObject","_taggedTemplateLiteral","renderGlyph","_templateObject2","_hasLeading","level","trunc","min","_renderLeading","_templateObject3","_templateObject4","_templateObject5","_renderTitleBlock","_templateObject6","_templateObject7","_templateObject8","_headingLevel","badge","_templateObject9","_templateObject10","_renderTopBar","placement","_templateObject11","e","_templateObject12","render","shellBar","_templateObject13","ifDefined","_templateObject14","_templateObject15","_templateObject16","__decorate","styles","NileElement","property","type","Boolean","reflect","attribute","prototype","state","query","customElement"],"mappings":"w0yDAmIaA,CAAN,uBAAAC,EAAA,EAAA,SAAAC,EAAA,CAAAC,KAAAA,KAAAA,CAAAA,eAAAA,MAAAA,CAAAA,mCAOLC,EAAAA,KAAAA,CAAYC,cAAY,CAIxBD,CAAAA,KAAAA,CAASE,WAAY,CAIrBF,CAAAA,KAAAA,CAAOG,SAAY,CAInBH,CAAAA,KAAAA,CAAUI,WAAW,YAQrBJ,CAAAA,KAAAA,CAAYK,aAAW,CAYvBL,CAAAA,KAAAA,CAAOM,QAAwB,MAI/BN,CAAAA,KAAAA,CAASO,UAAW,MAIpBP,CAAAA,KAAAA,CAAWQ,aAAY,CAIvBR,CAAAA,KAAAA,CAAeS,iBAAY,CAI3BT,CAAAA,KAAAA,CAAUU,YAAY,CAItBV,CAAAA,KAAAA,CAAaW,cAAW,sBAIxBX,CAAAA,KAAAA,CAAeY,gBAAgC,SAI/CZ,CAAAA,KAAAA,CAAYa,aAA6B,OAIzCb,CAAAA,KAAAA,CAAgBc,kBAAY,CAI5Bd,CAAAA,KAAAA,CAAIe,MAAY,CAIhBf,CAAAA,KAAAA,CAASgB,WAAY,CAIrBhB,CAAAA,KAAAA,CAAQiB,SAAW,KAInBjB,CAAAA,KAAAA,CAAKkB,OAAY,CAIjBlB,CAAAA,KAAAA,CAASmB,WAAY,CAIrBnB,CAAAA,KAAAA,CAAcoB,eAAW,MAIzBpB,CAAAA,KAAAA,CAAMqB,QAAY,CAIlBrB,CAAAA,KAAAA,CAAUsB,YAAY,CAItBtB,CAAAA,KAAAA,CAAiBuB,kBAAW,CAI5BvB,CAAAA,KAAAA,CAAoBwB,qBAAW,IAOdxB,CAAAA,KAAAA,CAAUyB,WAA0B,QAGpCzB,CAAAA,KAAAA,CAAU0B,YAAY,CAEtB1B,CAAAA,KAAAA,CAAU2B,YAAY,CACtB3B,CAAAA,KAAAA,CAAW4B,aAAY,CACvB5B,CAAAA,KAAAA,CAAU6B,YAAY,CACtB7B,CAAAA,KAAAA,CAAiB8B,mBAAY,CAC7B9B,CAAAA,KAAAA,CAAQ+B,UAAY,CACpB/B,CAAAA,KAAAA,CAASgC,WAAY,CACrBhC,CAAAA,KAAAA,CAAeiC,iBAAY,CAG3BjC,CAAAA,KAAAA,CAAgBkC,kBAAY,CAC5BlC,CAAAA,KAAAA,CAASmC,WAAY,CAI9BnC,CAAAA,KAAAA,CAAMoC,OAAW,CAEjBpC,CAAAA,KAAAA,CAAkBqC,mBAAmB,IAoQrCrC,CAAAA,KAAAA,CAAAsC,iBAAoBC,SAAAA,CAC1B,CAAA,CAAA,GAAMC,CAAAA,EAAUD,CAAsBC,CAAAA,MAAAA,CAClCA,GAAsC,SAArBA,EAAAA,MAAAA,CAAAA,CAAAA,CAAOC,SAC1BzC,EAAAA,KAAAA,CAAK0C,iBAAiBF,CAAOC,CAAAA,SAAAA,CAC9B,GAGKzC,KAAAA,CAAA2C,UAAAA,CAAcJ,SAAAA,cACpB,GAAIvC,KAAAA,CAAKS,kBAAoBT,KAAAA,CAAK4C,cAAAA,CAAgB,OAElD,GAAMC,CAAAA,CAAAA,EAAAA,MAAAA,CAAMN,EAAMM,GAAO,UAAAC,MAAA,UAAAA,MAAA,CAAA,EAAA,CAEzB,IAAKP,CAAMQ,CAAAA,OAAAA,EAAWR,EAAMS,OAAkC,GAAA,GAAA,GAAtBH,EAAII,WAG1C,CAAA,CAAA,CAAA,MAFAV,CAAAA,EAAMW,cACNlD,CAAAA,CAAAA,CAAAA,IAAAA,CAAAA,KAAAA,CAAKmD,cAKK,QAARN,GAAAA,CAAAA,EAAoB7C,KAAAA,CAAKE,SAAiC,EAAA,SAAA,GAApBF,KAAAA,CAAKyB,UAC7CzB,EAAAA,KAAAA,CAAKoD,YACN,EAmXJ,QAAAC,KAAA,EAtxBQC,SAAA,CAAAxD,CAAA,CAAAD,EAAA,SAAA0D,YAAA,CAAAzD,CAAA,GAAA+C,GAAA,aAAAW,GAAA,CA6IP,SAAAA,IAAA,CACE,CAAA,MAAOxD,MAAKyB,UACb,EAGD,GAAAoB,GAAA,aAAAW,GAAA,UAAAA,IAAA,CACE,CAAA,MAAOxD,MAAK0B,UACb,EAGD,GAAAmB,GAAA,kBAAAW,GAAA,UAAAA,IAAA,CACE,CAAA,MAAOxD,MAAKgC,SAAchC,EAAAA,CAAAA,IAAAA,CAAKG,OAChC,EAGD,GAAA0C,GAAA,eAAAW,GAAA,UAAAA,IAAA,EACE,MAAOxD,KAAAA,CAAK+B,WAAa/B,IAAKqB,CAAAA,MAC/B,EAGD,GAAAwB,GAAA,cAAAW,GAAA,UAAAA,IAAA,CAAWC,CACT,MAAOzD,KAAK4C,CAAAA,cAAAA,EAAAA,CAAmB5C,KAAKkB,KACrC,EAGD,GAAA2B,GAAA,QAAAW,GAAA,UAAAA,IAAA,CACE,CAAA,MAAOxD,MAAKC,YAAgBD,EAAAA,IAAAA,CAAK0B,UAClC,EAEM,GAAAmB,GAAA,qBAAAa,KAAA,UAAAC,iBAAAA,CAAAA,kBACLC,aAAAA,CAAAA,CAAAA,iCACA5D,KAAK6D,QACL7D,CAAAA,CAAAA,CAAAA,IAAAA,CAAK8D,gBAAkB,GAAIC,CAAAA,cAAAA,CAAeC,SAAAA,GACxC,GAAMC,CAAAA,CAAAA,CAAQD,EAAQA,CAAQE,CAAAA,MAAAA,CAAS,GACvClE,MAAKmE,CAAAA,QAAAA,CAASF,EAAMG,WAAYC,CAAAA,KAAAA,CAAM,IAExCrE,IAAK8D,CAAAA,eAAAA,CAAgBQ,QAAQtE,IAC7BuE,CAAAA,CAAAA,QAAAA,CAASC,iBAAiB,SAAWxE,CAAAA,IAAAA,CAAK2C,WAC3C,EAEM,GAAAE,GAAA,wBAAAa,KAAA,UAAAe,oBAAAA,CAAAA,4BACLb,aAAAA,CAAAA,CAAAA,qCAAAA,qBAAAA,CACA5D,KAAK8D,eAAiBY,UAAAA,qBAAAA,WAAtB1E,qBAAAA,CAAsB0E,UAAAA,CAAAA,CAAAA,CACtB1E,KAAK8D,eAAkBa,CAAAA,IAAAA,EAAAA,CACvBJ,SAASK,mBAAoB,CAAA,SAAA,CAAW5E,KAAK2C,UAC9C,CAAA,EAES,GAAAE,GAAA,cAAAa,KAAA,UAAAmB,UAAAA,CAAWC,CAAAA,CAAAA,CAAAA,CAEjBA,EAAQC,GAAI,CAAA,WAAA,CAAA,EACZD,EAAQC,GAAI,CAAA,SAAA,CAAA,EACZD,EAAQC,GAAI,CAAA,mBAAA,CAAA,EACZD,EAAQC,GAAI,CAAA,sBAAA,CAAA,EAEXD,EAAiCC,GAAI,CAAA,WAAA,CAAA,EACrCD,EAAiCC,GAAI,CAAA,aAAA,CAAA,GAEtC/E,KAAKgF,UAER,CAAA,CAAA,EAES,GAAAnC,GAAA,WAAAa,KAAA,UAAAuB,OAAAA,CAAQH,CAAAA,CAAAA,CAChBlB,aAAAA,CAAAA,CAAAA,oBAAckB,CAAAA,GAGd9E,KAAKkF,eAAgB,CAAA,MAAA,CAAQlF,KAAKmF,IAClCnF,CAAAA,CAAAA,IAAAA,CAAKkF,gBAAgB,YAAclF,CAAAA,IAAAA,CAAK0B,YACxC1B,IAAKkF,CAAAA,eAAAA,CAAgB,aAAclF,IAAK2B,CAAAA,UAAAA,CAAAA,CACxC3B,KAAKkF,eAAgB,CAAA,cAAA,CAAgBlF,IAAK4B,CAAAA,WAAAA,CAAAA,CAC1C5B,KAAKkF,eACH,CAAA,aAAA,CACAlF,KAAK6B,UACH7B,EAAAA,IAAAA,CAAKoF,iBACHpF,IAAKQ,CAAAA,WAAAA,EAAeR,KAAK4B,WAG/B5B,CAAAA,CAAAA,IAAAA,CAAKkF,gBACH,iBACElF,CAAAA,CAAAA,CAAAA,IAAAA,CAAKqF,eAAiBrF,IAAKsF,CAAAA,SAAAA,CAAAA,CAE/BtF,KAAKkF,eAAgB,CAAA,qBAAA,CAAuBlF,KAAK8B,iBACjD9B,CAAAA,CAAAA,IAAAA,CAAKkF,gBAAgB,SAAWlF,CAAAA,IAAAA,CAAKyD,YACrCzD,IAAKkF,CAAAA,eAAAA,CAAgB,WAAYlF,IAAKuF,CAAAA,WAAAA,CAAAA,CACtCvF,KAAKkF,eAAgB,CAAA,WAAA,CAAalF,KAAKmC,SACvCnC,CAAAA,CAAAA,IAAAA,CAAKkF,gBAAgB,WAAalF,CAAAA,IAAAA,CAAK4C,gBACvC5C,IAAKkF,CAAAA,eAAAA,CAAgB,mBAAoBlF,IAAKiC,CAAAA,eAAAA,CAAAA,CAC9CjC,KAAKwF,YAAa,CAAA,YAAA,CAAcxF,KAAKyB,UACrCzB,CAAAA,CAAAA,IAAAA,CAAKwF,aACH,cACAxF,CAAAA,IAAAA,CAAKkC,iBAAmB,UAAa,CAAA,UAAA,CAAA,CAGvClC,KAAKyF,YACN,CAAA,CAAA,EAGM,GAAA5C,GAAA,aAAAa,KAAA,UAAAgC,SAAAA,CAAAA,CACA1F,CAAAA,IAAAA,CAAK4C,gBACV5C,IAAK2F,CAAAA,aAAAA,CAAAA,CAAc,EACpB,EAGM,GAAA9C,GAAA,cAAAa,KAAA,UAAAN,UAAAA,CAAAA,EACLpD,IAAK2F,CAAAA,aAAAA,CAAAA,CAAc,EACpB,EAGM,GAAA9C,GAAA,eAAAa,KAAA,UAAAP,WAAAA,CAAYyC,CACJA,CAAAA,CAAAA,CAAAA,CAAAA,SAAAA,CAAAA,UAAAA,CAAAA,CAAAA,CAAU5F,KAAKE,SAClBF,EAAAA,IAAAA,CAAK0F,YACV1F,IAAKoD,CAAAA,UAAAA,CAAAA,CACX,EAGM,GAAAP,GAAA,gBAAAa,KAAA,UAAAmC,YAAAA,CAAAA,CAAAA,CACL7F,KAAK8F,IAAK,CAAA,kBAAA,CACX,EAGM,GAAAjD,GAAA,eAAAa,KAAA,UAAAqC,WAAAA,CAAAA,CAAAA,CACL/F,KAAK8F,IAAK,CAAA,iBAAA,CACX,EAGM,GAAAjD,GAAA,cAAAa,KAAA,UAAAsC,UAAAA,CAAAA,CAAAA,CACLhG,KAAK6F,YACN,CAAA,CAAA,EAGM,GAAAhD,GAAA,UAAAa,KAAA,UAAAuC,MAAAA,CAAAA,CACLjG,CAAAA,IAAAA,CAAK+F,aACN,EAGM,GAAAlD,GAAA,aAAAa,KAAA,UAAAwC,SAAAA,CAAAA,EACLlG,IAAK0C,CAAAA,gBAAAA,CAAAA,CAAiB,EACvB,EAGM,GAAAG,GAAA,eAAAa,KAAA,UAAAyC,WAAAA,CAAAA,EACLnG,IAAK0C,CAAAA,gBAAAA,CAAAA,CAAiB,EACvB,EAGM,GAAAG,GAAA,aAAAa,KAAA,UAAA0C,SAAAA,CAAUR,CACf5F,CAAAA,CAAAA,IAAAA,CAAK0C,iBAAiBkD,CAAU5F,SAAV4F,CAAU5F,UAAV4F,CAAU5F,CAAAA,CAAAA,IAAAA,CAAKC,aACtC,EAGM,GAAA4C,GAAA,aAAAa,KAAA,UAAA2C,SAAAA,CAAAA,kBACLrG,CAAAA,WAAAA,KAAKsG,CAAAA,KAAAA,UAAAA,WAAAA,WAALtG,WAAAA,CAAYuG,OACb,EAEO,GAAA1D,GAAA,iBAAAa,KAAA,UAAAiC,aAAAA,CAAcjC,CAChB1D,CAAAA,CAAAA,IAAAA,CAAKE,YAAcwD,CACvB1D,GAAAA,IAAAA,CAAKE,UAAYwD,CACjB1D,CAAAA,IAAAA,CAAKwG,WACLxG,IAAK8F,CAAAA,IAAAA,CAAK,oBAAqB,CAAEW,IAAAA,CAAM/C,EAAOgD,IAAM1G,CAAAA,IAAAA,CAAKyB,aAC1D,EAEO,GAAAoB,GAAA,oBAAAa,KAAA,UAAAhB,gBAAAA,CAAiBgB,CACnB1D,CAAAA,CAAAA,IAAAA,CAAKC,eAAiByD,CAC1B1D,GAAAA,IAAAA,CAAKC,aAAeyD,CACpB1D,CAAAA,IAAAA,CAAKwG,WACLxG,IAAK8F,CAAAA,IAAAA,CAAK,kBAAmB,CAC3BrD,SAAAA,CAAWiB,EACXiD,MAAQ3G,CAAAA,IAAAA,CAAK0B,aAEhB,EAGO,GAAAmB,GAAA,YAAAa,KAAA,UAAAS,QAAAA,CAASE,CACf,CAAA,CAAA,GAAIA,IAAUrE,IAAKoC,CAAAA,MAAAA,CAAQ,OAC3B,GAAMwE,CAAAA,CAAAA,CAAwB,CAAhB5G,GAAAA,IAAAA,CAAKoC,OAKnB,GAJApC,IAAAA,CAAKoC,OAASiC,CACdrE,CAAAA,IAAAA,CAAKgF,aAGD4B,CAAqC,EAAA,IAAA,GAA5B5G,KAAKqC,kBAA6B,CAAA,CAC7C,GAAMoE,CAAAA,EAAOzG,CAAAA,IAAAA,CAAKqC,mBAClBrC,IAAKqC,CAAAA,kBAAAA,CAAqB,KACtBoE,EAA4B,EAAA,QAAA,GAApBzG,KAAKyB,UAAyBzB,EAAAA,IAAAA,CAAK0F,WAChD,EACF,CAGO,GAAA7C,GAAA,aAAAa,KAAA,UAAAmD,SAAAA,CAAAA,CACN,CAAA,GAAMC,CAAAA,EAAQC,gBAAiB/G,CAAAA,IAAAA,CAAAA,CACzBgH,EAAK,QAALA,CAAAA,EAAMC,EAAAA,CAAcC,GACxB,GAAMxD,CAAAA,CAAAA,CAAQyD,WAAWL,CAAMM,CAAAA,gBAAAA,CAAiBH,KAChD,MAAOI,CAAAA,MAAAA,CAAOC,SAAS5D,CAASA,CAAAA,CAAAA,CAAAA,CAAQwD,CAAQ,EAElD,CAAA,MAAO,CAELK,GAAKP,CAAAA,CAAAA,CAAG,kCAAmC,GAC3C7B,CAAAA,CAAAA,IAAAA,CAAM6B,EAAG,sCAAwC,CAAA,EAAA,CAAA,CACjDQ,OAAQR,CAAG,CAAA,yBAAA,CAA2B,GACtCS,OAAST,CAAAA,CAAAA,CAAG,qCAAsC,GAClDU,CAAAA,CAAAA,KAAAA,CAAOV,EAAG,8BAAgC,CAAA,GAAA,CAAA,CAC1CW,MAAOX,CAAG,CAAA,8BAAA,CAAgC,KAE7C,EAGO,GAAAnE,GAAA,oBAAAa,KAAA,UAAAkE,gBAAAA,CAAiBC,CAAoBC,CAAAA,CAAAA,CAAAA,CAC3C,GAAMP,CAAAA,CAAMvH,CAAAA,IAAAA,CAAK4B,YAAckG,CAAQ,CAAA,CAAA,CACjCJ,EAAQ1H,IAAKmC,CAAAA,SAAAA,CAAY0F,EAAIH,KAAQG,CAAAA,CAAAA,CAAIL,OAAS,CAElDO,CAAAA,CAAAA,CAAU/H,KAAK4B,WAAc,CAAA,CAAA,CAAI,EACvC,MAAO2F,CAAAA,CAAAA,CAAMM,EAAIJ,OAAUC,CAAAA,CAAAA,CAAQG,EAAIF,KAAQE,CAAAA,CAAAA,CAAIL,OAASO,CAC7D,EAEO,GAAAlF,GAAA,cAAAa,KAAA,UAAAsB,UAAAA,CAAAA,CACN,CAAA,GAAMX,CAAAA,EAAQrE,IAAKoC,CAAAA,MAAAA,CACbyF,EAAM7H,IAAK6G,CAAAA,SAAAA,CAAAA,CAAAA,CAGXmB,EACJhI,IAAKuB,CAAAA,iBAAAA,CAAoB,GAAK8C,CAAQ,CAAA,CAAA,EAAKA,EAAQrE,IAAKuB,CAAAA,iBAAAA,CACpDmF,EAA8BsB,CAAU,CAAA,SAAA,CAAY,SAGpDC,CAASC,CAAAA,IAAAA,CAAKC,IAClBnI,IAAKwB,CAAAA,oBAAAA,CACLxB,KAAK4H,gBAAiBC,CAAAA,CAAAA,CAAKA,EAAIN,GAE3Ba,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CACHJ,GACDhI,IAAKE,CAAAA,SAAAA,EACLF,KAAK4C,cACLyB,EAAAA,CAAAA,CAAQ,GACRA,CAAQ4D,CAAAA,CAAAA,CACJtB,EAASqB,CAAWI,EAAAA,CAAAA,CAEtB1B,IAAS1G,IAAKyB,CAAAA,UAAAA,GAChBzB,KAAKyB,UAAaiF,CAAAA,CAAAA,CAClB1G,KAAK8F,IAAK,CAAA,wBAAA,CAA0B,CAAEY,IAGpCC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,GAAW3G,KAAK0B,UAClB1B,GAAAA,IAAAA,CAAK0B,WAAaiF,CAClB3G,CAAAA,IAAAA,CAAK8F,KAAK,iBAAmB,CAAA,CAC3BrD,UAAWzC,IAAKC,CAAAA,YAAAA,CAChB0G,WAGL,EAGO,GAAA9D,GAAA,gBAAAa,KAAA,UAAA+B,YAAAA,CAAAA,kBACNzF,IAAKqI,CAAAA,gBAAAA,CAAiB,qBAAqBC,OAAQC,CAAAA,SAAAA,CAAAA,CAAAA,CAC9B,eAAfA,GAAAA,CAAAA,CAAGC,SACLD,CAAGrD,CAAAA,eAAAA,CAAgB,YAAalF,MAAKmF,CAAAA,IAAAA,CAAK,GAE/C,EA2BO,GAAAtC,GAAA,eAAAa,KAAA,UAAA+E,WAAAA,CAAYC,CAClB,CAAA,CAAA,wBAAAC,MAAA,CAAyB3I,IAAK4I,CAAAA,UAAAA,MAAAA,MAAAA,CAAcF,GAC7C,CAEO,GAAA7F,GAAA,YAAAa,KAAA,UAAAG,QAAAA,CAAAA,EACN,GAAK7D,IAAAA,CAAK4I,WACV,GACE,CAAA,GAAMrB,CAAAA,IAAMsB,YAAaC,CAAAA,OAAAA,CAAQ9I,KAAKyI,WAAY,CAAA,eAAA,CAAA,CAAA,CACtC,OAARlB,GAAcvH,GAAAA,IAAAA,CAAKC,aAAuB,MAARsH,GAAAA,GAAAA,CAAAA,CACtC,GAAMI,CAAAA,GAAQkB,CAAAA,YAAAA,CAAaC,QAAQ9I,IAAKyI,CAAAA,WAAAA,CAAY,eACtC,IAAVd,GAAAA,GAAAA,GAAgB3H,KAAKqC,kBAA+B,CAAA,MAAA,GAAVsF,IAC/C,EAAC,MAAAoB,OAAA,CAAA,CAED,CACF,CAEO,GAAAlG,GAAA,YAAAa,KAAA,UAAA8C,QAAAA,CAAAA,EACN,GAAKxG,IAAAA,CAAK4I,WACV,GACEC,CAAAA,YAAAA,CAAaG,QACXhJ,IAAKyI,CAAAA,WAAAA,CAAY,iBACjBQ,MAAOjJ,CAAAA,IAAAA,CAAKC,eAEU,QAApBD,GAAAA,IAAAA,CAAKyB,YACPoH,YAAaG,CAAAA,OAAAA,CACXhJ,KAAKyI,WAAY,CAAA,YAAA,CAAA,CACjBQ,OAAOjJ,IAAKE,CAAAA,SAAAA,CAAAA,CAGjB,EAAC,MAAAgJ,QAAA,CAED,CAAA,CACF,CAEO,GAAArG,GAAA,iBAAAa,KAAA,UAAAyF,aAAAA,CAAcC,EAAc7G,CAClC,CAAA,CAAA,GAAM8G,CAAAA,EAAY9G,CAAM+G,CAAAA,MAAAA,CAA2BC,cAAc,CAC/DC,OAAAA,CAAAA,CAAS,IAELC,CAASJ,CAAAA,CAAAA,CAASK,KACtBC,SAAAA,CACEA,MAAAA,cAAAA,OAAAA,CAAAA,CAAAA,CAAKC,WAAaC,IAAKC,CAAAA,YAAAA,EACa,sBAAnCH,CAAKI,CAAAA,WAAAA,UAAAA,cAAAA,UAAAA,cAAAA,CAAe,IAAIC,IAG7B,CAAA,CAAA,EAAA,CAAA,CAAA,OAAQZ,GACN,IAAK,QAAA,CACHpJ,KAAK2B,UAAa8H,CAAAA,CAAAA,CAClB,MACF,IAAK,UAAA,CACHzJ,KAAK4B,WAAc6H,CAAAA,CAAAA,CACnBzJ,KAAKyF,YACL,CAAA,CAAA,CAAA,MACF,IAAK,SACHzF,CAAAA,IAAAA,CAAK6B,WAAa4H,CAClB,CAAA,MACF,IAAK,iBACHzJ,CAAAA,IAAAA,CAAK8B,kBAAoB2H,CACzB,CAAA,MACF,IAAK,MACHzJ,CAAAA,IAAAA,CAAK+B,SAAW0H,CAChB,CAAA,MACF,IAAK,OACHzJ,CAAAA,IAAAA,CAAKmC,UAAYsH,CACjB,CAAA,MACF,IAAK,OACHzJ,CAAAA,IAAAA,CAAKgC,UAAYyH,CACjBzJ,CAAAA,IAAAA,CAAKkC,iBAAmBmH,CAASK,CAAAA,IAAAA,CAC/BC,SAAAA,SACEA,CAAAA,CAAKC,CAAAA,QAAAA,GAAaC,KAAKC,YACO,EAAA,sBAAA,GAA7BH,EAAiBnB,OAEtBxI,EAAAA,CAAAA,CAAAA,IAAAA,CAAKgF,aACL,MACF,IAAK,eACHhF,IAAKiC,CAAAA,eAAAA,CAAkBwH,GAK5B,CAEO,GAAA5G,GAAA,oBAAAa,KAAA,UAAAuG,gBAAAA,CAAAA,kBACN,GAAIjK,IAAAA,CAAKQ,cAAgBR,IAAK4B,CAAAA,WAAAA,CAAa,MAAO,EAClD,CAAA,GAAMsI,CAAAA,GAAYlK,IAAKmF,CAAAA,IAAAA,CACvB,MAAOgF,CAAAA,CAAI,CAAAC,eAAA,GAAAA,eAAA,CAAAC,sBAAA,wbAQWH,CAAAA,CAAW,MAAS,CAAA,OAAA,CACxBlK,IAAK0B,CAAAA,UAAAA,CACT1B,IAAK0B,CAAAA,UAAAA,CACT,qDACAwI,CAAAA,CAAAA,CACA,qBACA,CAAA,mBAAA,CACSA,CAAAA,CAAW,qBAAwB,CAAA,mBAAA,CACvC,iBAAMlK,CAAAA,MAAKoG,CAAAA,SAAAA,CAAAA,CAAAA,GAElBkE,CACAJ,CAAAA,CAAAA,CAAW,eAAkB,CAAA,gBAAA,CAC7B,EACA,CAAA,cAAA,CAAA,CAGFlK,IAAAA,CAAK6B,UAAc7B,EAAAA,IAAAA,CAAKoF,cACtB+E,CAAAA,CAAI,CAAAI,gBAAA,GAAAA,gBAAA,CAAAF,sBAAA,mDACJ,EAAA,EAGT,CAGD,GAAAxH,GAAA,kBAAAW,GAAA,UAAAA,IAAA,EACE,MAASxD,CAAAA,CAAAA,IAAAA,CAAKsF,WAAatF,IAAKwK,CAAAA,WACjC,EAGD,GAAA3H,GAAA,eAAAW,GAAA,UAAAA,IAAA,CAAYgH,CACV,MAAwB,MAAjBxK,GAAAA,IAAAA,CAAKM,SAAuC,UAAjBN,GAAAA,IAAAA,CAAKM,OACxC,EAGD,GAAAuC,GAAA,iBAAAW,GAAA,UAAAA,IAAA,CACE,CAAA,GAAMiH,CAAAA,CAAQvC,CAAAA,IAAAA,CAAKwC,MAAMrD,MAAOrH,CAAAA,IAAAA,CAAKK,eACrC,MAAOgH,CAAAA,MAAAA,CAAOC,SAASmD,CAASvC,CAAAA,CAAAA,IAAAA,CAAKyC,IAAI,CAAGzC,CAAAA,IAAAA,CAAKC,IAAI,CAAGsC,CAAAA,CAAAA,CAAAA,CAAAA,CAAU,CACnE,EAEO,GAAA5H,GAAA,kBAAAa,KAAA,UAAAkH,cAAAA,CAAAA,kBACN,MAAqB,UAAA,GAAjB5K,IAAKM,CAAAA,OAAAA,CACA6J,CAAI,CAAAU,gBAAA,GAAAA,gBAAA,CAAAR,sBAAA,kIAOQ,MAAjBrK,GAAAA,IAAAA,CAAKM,QACA6J,CAAI,CAAAW,gBAAA,GAAAA,gBAAA,CAAAT,sBAAA,2NAKE,iBAAMrK,CAAAA,MAAK6F,CAAAA,YAAAA,CAAAA,CAAAA,GAElByE,CAAAA,CAAY,kBAAmB,EAAI,CAAA,cAAA,CAAA,CAC7BtK,IAAKO,CAAAA,SAAAA,CAEbP,IAAAA,CAAKsF,UACH6E,CAAI,CAAAY,gBAAA,GAAAA,gBAAA,CAAAV,sBAAA,mGACAC,CAAAA,CAAY,WAAY,EAAI,CAAA,cAAA,CAAA,EAEhC,EAAA,EAID,EACR,EAEO,GAAAzH,GAAA,qBAAAa,KAAA,UAAAsH,iBAAAA,CAAAA,CAAAA,CACN,MAAKhL,KAAAA,CAAKoF,eAGH+E,CAAI,CAAAc,gBAAA,GAAAA,gBAAA,CAAAZ,sBAAA,4GAELrK,IAAAA,CAAKwK,YACHL,CAAI,CAAAe,gBAAA,GAAAA,gBAAA,CAAAb,sBAAA,yFACCrK,IAAK4K,CAAAA,cAAAA,CAAAA,CAAAA,EAEV,EAAA,CACF5K,IAAAA,CAAKsF,UACH6E,CAAI,CAAAgB,gBAAA,GAAAA,gBAAA,CAAAd,sBAAA,yZAOiBrK,IAAKoL,CAAAA,aAAAA,CACjBpL,IAAKsF,CAAAA,SAAAA,CACNtF,IAAAA,CAAKqL,KACHlB,CAAAA,CAAI,CAAAmB,gBAAA,GAAAA,gBAAA,CAAAjB,sBAAA,uDAAoCrK,IAAAA,CAAKqL,KAC7C,EAAA,EAAA,CAEJrL,IAAAA,CAAKqF,YACH8E,CAAI,CAAAoB,iBAAA,GAAAA,iBAAA,CAAAlB,sBAAA,2GACArK,IAAKqF,CAAAA,WAAAA,EAET,EAAA,EAGR,EAAA,EA/ByB,EAkClC,EAEO,GAAAxC,GAAA,iBAAAa,KAAA,UAAA8H,aAAAA,CACNC,CAAAA,CAAAA,KAAAA,MAAAA,MAEA,MAAOtB,CAAAA,CAAI,CAAAuB,iBAAA,GAAAA,iBAAA,CAAArB,sBAAA,odAEe,OAAA,GAAdoB,EAAwB,uBAA0B,CAAA,SAAA,CACrC,OAAA,GAAdA,EAAwB,uBAA0B,CAAA,SAAA,CAEvDzL,IAAKiK,CAAAA,gBAAAA,CAAAA,CAAAA,CAEHjK,IAAKgL,CAAAA,iBAAAA,CAAAA,CAAAA,CAGUW,SAAAA,CAAa3L,QAAAA,CAAAA,MAAAA,CAAKmJ,cAAc,SAAWwC,CAAAA,CAAAA,CAAAA,GAM3CA,SAAAA,CACb3L,QAAAA,CAAAA,MAAAA,CAAKmJ,cAAc,iBAAmBwC,CAAAA,CAAAA,CAAAA,GAExC3L,IAAAA,CAAKyD,WACH0G,CAAI,CAAAyB,iBAAA,GAAAA,iBAAA,CAAAvB,sBAAA,6bAMS,iBAAMrK,CAAAA,MAAK0F,CAAAA,SAAAA,CAAAA,CAAAA,GAGhB4E,CAAAA,CAAY,cAAe,EAAI,CAAA,cAAA,CAAA,CAEjCtK,IAAKiB,CAAAA,QAAAA,EAGX,EAAA,EAIX,CAEM,GAAA4B,GAAA,UAAAa,KAAA,UAAAmI,MAAAA,CAAAA,kBACL,GAAMC,CAAAA,CAAAA,CAAoC,UAAzB9L,IAAKY,CAAAA,eAAAA,CAEtB,MAAOuJ,CAAAA,CAAI,CAAA4B,iBAAA,GAAAA,iBAAA,CAAA1B,sBAAA,i1CAKE,iBAAMrK,CAAAA,MAAKqG,CAAAA,SAAAA,CAAAA,CAAAA,GAElBrG,IAAKW,CAAAA,aAAAA,CAMUgL,SAAAA,CAAa3L,QAAAA,CAAAA,MAAAA,CAAKmJ,cAAc,QAAUwC,CAAAA,CAAAA,CAAAA,GAI3DG,CAAW9L,CAAAA,IAAAA,CAAKwL,cAAc,OAAW,CAAA,CAAA,EAAA,CAM1BxL,IAAKsC,CAAAA,gBAAAA,CAIHqJ,SAAAA,CAAa3L,QAAAA,CAAAA,MAAAA,CAAKmJ,cAAc,UAAYwC,CAAAA,CAAAA,CAAAA,GAMzDG,CAAW,CAAA,EAAA,CAAK9L,KAAKwL,aAAc,CAAA,SAAA,CAAA,CAIlBG,SAAAA,CAAa3L,QAAAA,CAAAA,MAAAA,CAAKmJ,cAAc,MAAQwC,CAAAA,CAAAA,CAAAA,GAW1CA,SAAAA,CAAa3L,QAAAA,CAAAA,MAAAA,CAAKmJ,cAAc,OAASwC,CAAAA,CAAAA,CAAAA,GAO7CK,CACXhM,CAAAA,IAAAA,CAAKkC,gBAAmByC,CAAAA,IAAAA,EAAAA,CAAY3E,IAAKI,CAAAA,UAAAA,CAAAA,CAE7BJ,IAAAA,CAAKE,UAAY,OAAU,CAAA,MAAA,CAEvCF,IAAAA,CAAKkC,iBACHiI,CAAI,CAAA8B,iBAAA,GAAAA,iBAAA,CAAA5B,sBAAA,sGAEasB,SAAAA,CAAa3L,QAAAA,CAAAA,MAAAA,CAAKmJ,cAAc,OAASwC,CAAAA,CAAAA,CAAAA,IAE1DxB,CAAI,CAAA+B,iBAAA,GAAAA,iBAAA,CAAA7B,sBAAA,qhDAEErK,IAAAA,CAAKmB,UACHgJ,CAAI,CAAAgC,iBAAA,GAAAA,iBAAA,CAAA9B,sBAAA,qZAKMrK,IAAKoB,CAAAA,cAAAA,CACApB,IAAKoB,CAAAA,cAAAA,CACT,iBAAMpB,CAAAA,MAAK+F,CAAAA,WAAAA,CAAAA,CAAAA,GAElBuE,CAAAA,CAAY,gBAAiB,EAAI,CAAA,cAAA,CAAA,EAErC,EAAA,CAIIA,CAAAA,CAAY,cAAe,EAAI,CAAA,cAAA,CAAA,CAG/BtK,IAAKI,CAAAA,UAAAA,CAWMJ,IAAKI,CAAAA,UAAAA,CACAJ,IAAKI,CAAAA,UAAAA,CAChB,iBAAMJ,CAAAA,MAAKoD,CAAAA,UAAAA,CAAAA,CAAAA,GAElBkH,CAAAA,CAAY,aAAc,EAAI,CAAA,cAAA,CAAA,CAOnBqB,SAAAA,CAAa3L,QAAAA,CAAAA,MAAAA,CAAKmJ,cAAc,OAASwC,CAAAA,CAAAA,CAAAA,GAMzCA,SAAAA,CACb3L,QAAAA,CAAAA,MAAAA,CAAKmJ,cAAc,cAAgBwC,CAAAA,CAAAA,CAAAA,KAOtD,CA/wBDS,KAAAA,GAAAA,UAAAA,GAAAA,CANO,SAAA5I,IAAA,CACL,CAAA,MAAO,CAAC6I,CACT,CAAA,EA2ID,MA9IgCC,IAOhCF,CAAAA,CAAA,CADCG,CAAAA,CAAS,CAAEC,IAAAA,CAAMC,QAASC,OAAS,CAAA,CAAA,CAAA,CAAMC,SAAW,CAAA,eAAA,CAAA,CAAA,CAAA,CACvB/M,CAAAgN,CAAAA,SAAAA,CAAA,mBAAA,EAI9BR,CAAAA,CAAAA,CAAAA,CAAA,CADCG,CAAAA,CAAS,CAAEC,IAAAA,CAAMC,QAASC,OAAS,CAAA,CAAA,CAAA,CAAMC,SAAW,CAAA,YAAA,CAAA,CAAA,CAAA,CAC1B/M,CAAAgN,CAAAA,SAAAA,CAAA,gBAAA,EAI3BR,CAAAA,CAAAA,CAAAA,CAAA,CADCG,CAAAA,CAAS,CAAEC,IAAAA,CAAMC,QAASC,OAAS,CAAA,CAAA,CAAA,CAAMC,SAAW,CAAA,UAAA,CAAA,CAAA,CAAA,CAC5B/M,CAAAgN,CAAAA,SAAAA,CAAA,cAAA,EAIzBR,CAAAA,CAAAA,CAAAA,CAAA,CADCG,CAAAA,CAAS,CAAEC,IAAAA,CAAMvD,MAAQ0D,CAAAA,SAAAA,CAAW,aACH/M,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,YAAA,CAAA,IAAA,EAIlCR,CAAAA,CAAAA,CAAAA,CAAA,CADCG,CAAS,CAAA,CAAEC,IAAMvD,CAAAA,MAAAA,CAAQ0D,SAAW,CAAA,CAAA,CAAA,CAAMD,SAAS,CACjC9M,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,WAAA,CAAA,IAAA,EAInBR,CAAAA,CAAAA,CAAAA,CAAA,CADCG,CAAS,CAAA,CAAEC,IAAMnF,CAAAA,MAAAA,CAAQsF,SAAW,CAAA,CAAA,CAAA,CAAMD,OAAS,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAC3B9M,CAAAgN,CAAAA,SAAAA,CAAA,cAAA,CAAA,IAAA,EAAA,CAAA,CAIzBR,CAAA,CAAA,CADCG,EAAS,CAAEC,IAAAA,CAAMvD,MAAQ0D,CAAAA,SAAAA,CAAAA,CAAW,CAAMD,CAAAA,OAAAA,CAAAA,CAAS,KAC/B9M,CAAAgN,CAAAA,SAAAA,CAAA,aAAA,CAAA,IAAA,EAAA,CAAA,CAIrBR,CAAA,CAAA,CADCG,EAAS,CAAEC,IAAAA,CAAMvD,MAAQ0D,CAAAA,SAAAA,CAAAA,CAAW,CAAMD,CAAAA,OAAAA,CAAAA,CAAS,CACrC9M,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,OAAA,CAAA,IAAA,EAIfR,CAAAA,CAAAA,CAAAA,CAAA,CADCG,CAAAA,CAAS,CAAEC,IAAMvD,CAAAA,MAAAA,CAAQ0D,SAAW,CAAA,CAAA,CAAA,CAAMD,OAAS,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACd9M,EAAAgN,SAAA,CAAA,SAAA,CAAA,IAAA,EAItCR,CAAAA,CAAAA,CAAAA,CAAA,CADCG,CAAAA,CAAS,CAAEC,IAAMvD,CAAAA,MAAAA,CAAQ0D,SAAW,CAAA,CAAA,CAAA,CAAMD,OAAS,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACzB9M,CAAAgN,CAAAA,SAAAA,CAAA,WAAA,CAAA,IAAA,EAAA,CAAA,CAI3BR,CAAA,CAAA,CADCG,CAAS,CAAA,CAAEC,KAAMC,OAASC,CAAAA,OAAAA,CAAAA,CAAS,CAAMC,CAAAA,SAAAA,CAAW,eACxB/M,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,UAAA,aAAA,CAAA,IAAA,EAAA,CAAA,CAI7BR,CAAA,CAAA,CADCG,CAAS,CAAA,CAAEC,KAAMC,OAASE,CAAAA,SAAAA,CAAW,mBACL/M,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,iBAAA,CAAA,IAAA,EAIjCR,CAAAA,CAAAA,CAAAA,CAAA,CADCG,CAAAA,CAAS,CAAEC,IAAAA,CAAMC,OAASC,CAAAA,OAAAA,CAAAA,CAAS,EAAMC,SAAW,CAAA,cAAA,CAAA,CAAA,CAAA,CACzB/M,CAAAgN,CAAAA,SAAAA,CAAA,YAAA,CAAA,IAAA,EAAA,CAAA,CAI5BR,EAAA,CADCG,CAAAA,CAAS,CAAEC,IAAAA,CAAMvD,MAAQ0D,CAAAA,SAAAA,CAAW,qBACU/M,CAAAgN,CAAAA,SAAAA,CAAA,eAAA,CAAA,IAAA,EAAA,CAAA,CAI/CR,CAAA,CAAA,CADCG,CAAS,CAAA,CAAEC,IAAMvD,CAAAA,MAAAA,CAAQyD,OAAS,CAAA,CAAA,CAAA,CAAMC,SAAW,CAAA,mBAAA,CAAA,CAAA,CAAA,CACK/M,EAAAgN,SAAA,CAAA,iBAAA,CAAA,IAAA,EAIzDR,CAAAA,CAAAA,CAAAA,CAAA,CADCG,CAAAA,CAAS,CAAEC,IAAMvD,CAAAA,MAAAA,CAAQyD,OAAS,CAAA,CAAA,CAAA,CAAMC,SAAW,CAAA,eAAA,CAAA,CAAA,CAAA,CACH/M,EAAAgN,SAAA,CAAA,cAAA,CAAA,IAAA,EAIjDR,CAAAA,CAAAA,CAAAA,CAAA,CADCG,CAAAA,CAAS,CAAEC,IAAAA,CAAMC,OAASC,CAAAA,OAAAA,CAAAA,CAAS,CAAMC,CAAAA,SAAAA,CAAW,mBACnB/M,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,UAAA,kBAAA,CAAA,IAAA,EAAA,CAAA,CAIlCR,CAAA,CAAA,CADCG,CAAS,CAAA,CAAEC,KAAMC,OAASC,CAAAA,OAAAA,CAAAA,CAAS,CACd9M,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,MAAA,CAAA,IAAA,IAItBR,CAAA,CAAA,CADCG,CAAS,CAAA,CAAEC,IAAMC,CAAAA,OAAAA,CAASC,SAAS,CAAMC,CAAAA,SAAAA,CAAW,YAC1B/M,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,WAAA,CAAA,IAAA,IAI3BR,CAAA,CAAA,CADCG,CAAS,CAAA,CAAEC,IAAMvD,CAAAA,MAAAA,CAAQ0D,UAAW,WACZ/M,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,UAAA,CAAA,IAAA,EAIzBR,CAAAA,CAAAA,CAAAA,CAAA,CADCG,CAAS,CAAA,CAAEC,IAAMC,CAAAA,OAAAA,CAASC,OAAS,CAAA,CAAA,CAAA,CAAMC,SAAW,CAAA,QAAA,CAAA,CAAA,CAAA,CAC9B/M,CAAAgN,CAAAA,SAAAA,CAAA,OAAA,CAAA,IAAA,EAAA,CAAA,CAIvBR,CAAA,CAAA,CADCG,EAAS,CAAEC,IAAAA,CAAMC,OAASC,CAAAA,OAAAA,CAAAA,CAAS,CACT9M,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,UAAA,WAAA,CAAA,IAAA,EAAA,CAAA,CAI3BR,CAAA,CAAA,CADCG,CAAS,CAAA,CAAEC,KAAMvD,MACcrJ,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,gBAAA,CAAA,IAAA,EAIhCR,CAAAA,CAAAA,CAAAA,CAAA,CADCG,CAAAA,CAAS,CAAEC,IAAAA,CAAMC,OAASC,CAAAA,OAAAA,CAAAA,CAAS,CACZ9M,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,UAAA,QAAA,CAAA,IAAA,EAAA,CAAA,CAIxBR,CAAA,CAAA,CADCG,CAAS,CAAA,CAAEC,KAAMC,OAASC,CAAAA,OAAAA,CAAAA,CAAS,CAAMC,CAAAA,SAAAA,CAAW,aACzB/M,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,UAAA,YAAA,CAAA,IAAA,EAAA,CAAA,CAI5BR,CAAA,CAAA,CADCG,CAAS,CAAA,CAAEC,IAAMnF,CAAAA,MAAAA,CAAQsF,SAAW,CAAA,oBAAA,CAAA,CAAA,CAAA,CACP/M,CAAAgN,CAAAA,SAAAA,CAAA,mBAAA,CAAA,IAAA,EAAA,CAAA,CAI9BR,EAAA,CADCG,CAAAA,CAAS,CAAEC,IAAAA,CAAMnF,MAAQsF,CAAAA,SAAAA,CAAW,4BACD/M,CAAAgN,CAAAA,SAAAA,CAAA,sBAAA,CAAA,IAAA,EAAA,CAAA,CAIpCR,CAAA,CAAA,CADCG,EAAS,CAAEC,IAAAA,CAAMvD,MAAQ0D,CAAAA,SAAAA,CAAW,aACjB/M,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,YAAA,CAAA,IAAA,EAGHR,CAAAA,CAAAA,CAAAA,CAAA,CAAhBS,CAAAA,CAAAA,CAAAA,CAAAA,CAA6DjN,CAAAgN,CAAAA,SAAAA,CAAA,iBAAA,EAG7CR,CAAAA,CAAAA,CAAAA,CAAA,CAAhBS,CAAAA,CAAAA,CAAAA,CAAAA,CAA4CjN,CAAAgN,CAAAA,SAAAA,CAAA,iBAAA,EAE5BR,CAAAA,CAAAA,CAAAA,CAAA,CAAhBS,CAAAA,CAAAA,CAAAA,CAAAA,CAA4CjN,CAAAgN,CAAAA,SAAAA,CAAA,iBAAA,EAC5BR,CAAAA,CAAAA,CAAAA,CAAA,CAAhBS,CAAAA,CAAAA,CAAAA,CAAAA,CAA6CjN,CAAAgN,CAAAA,SAAAA,CAAA,aAAA,CAAA,IAAA,EAAA,CAAA,CAC7BR,CAAA,CAAA,CAAhBS,CAA4CjN,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,YAAA,CAAA,IAAA,IAC5BR,CAAA,CAAA,CAAhBS,CAAmDjN,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,mBAAA,CAAA,IAAA,IACnCR,CAAA,CAAA,CAAhBS,CAA0CjN,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,UAAA,CAAA,IAAA,IAC1BR,CAAA,CAAA,CAAhBS,CAA2CjN,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,WAAA,CAAA,IAAA,EAC3BR,CAAAA,CAAAA,CAAAA,CAAA,CAAhBS,CAAAA,CAAAA,CAAAA,CAAAA,CAAiDjN,CAAAgN,CAAAA,SAAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA,CAGjCR,EAAA,CAAhBS,CAAAA,CAAAA,CAAAA,CAAAA,CAAkDjN,CAAAgN,CAAAA,SAAAA,CAAA,kBAAA,CAAA,IAAA,EAAA,CAAA,CAClCR,EAAA,CAAhBS,CAAAA,CAAAA,CAAAA,CAAAA,CAA2CjN,CAAAgN,CAAAA,SAAAA,CAAA,WAAA,CAAA,IAAA,EAAA,CAAA,CAEpBR,EAAA,CAAvBU,CAAAA,CAAM,OAAqClN,CAAAA,CAAAA,CAAAA,CAAAA,CAAAgN,SAAA,CAAA,OAAA,CAAA,IAAA,EAvIjChN,CAAAA,CAAAA,OAAAA,KAAAA,CAAAA,CAAYwM,CAAA,CAAA,CADxBW,CAAc,CAAA,gBAAA,CAAA,CAAA,CACFnN"}
|
|
1
|
+
{"version":3,"file":"nile-app-shell.cjs.js","sources":["../../../src/nile-app-shell/nile-app-shell.ts"],"sourcesContent":["/**\n * Copyright Aquera Inc 2023\n *\n * This source code is licensed under the BSD-3-Clause license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { html, CSSResultArray, TemplateResult, PropertyValues } from 'lit';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { styles } from './nile-app-shell.css';\nimport { renderGlyph } from '../internal/glyph';\nimport NileElement from '../internal/nile-element';\nimport '../nile-button/nile-button';\n\n/** The mode the AI panel is currently in. */\nexport type NileAppShellPanelMode = 'docked' | 'overlay';\n\n/** Where the top bar is mounted. */\nexport type NileAppShellTopBarPlacement = 'content' | 'shell';\n\n/** How the main region lays its content out. */\nexport type NileAppShellContentAlign = 'fluid' | 'centered';\n\n/** The `detail` of the `nile-click` the header back control emits. */\nexport interface NileAppShellClickDetail {\n value: 'back';\n}\n\n/** The shell's own track and region widths, in px. */\ninterface ShellGeometry {\n nav: number;\n rail: number;\n gutter: number;\n content: number;\n aside: number;\n panel: number;\n}\n\n/**\n * @summary The application frame every route inherits: a side nav, a content container, an optional aside and an AI assistant panel.\n *\n * @status stable\n * @since 2.0\n *\n * @tag nile-app-shell\n *\n * @dependency nile-button\n * @dependency nile-glyph\n *\n * @slot - The page body, inside the content container.\n * @slot banner - A full-width strip above every other region.\n * @slot top-bar - The page-title bar, mounted inside the container by default or spanning the shell when `top-bar-placement=\"shell\"`.\n * @slot top-bar-actions - Controls pinned to the end of the top bar.\n * @slot tabs - A hoisted second-level tab strip, flush under the top bar and outside `<main>`'s scroller.\n * @slot app-icon - The mark shown before the page title whenever this slot has content, clipped to the shell's box.\n * @slot side-nav - The navigation track. Works best with `<nile-side-bar>`.\n * @slot aside - A secondary column between the content container and the panel.\n * @slot panel - The AI panel's body. When empty the panel is unmounted and `openPanel()` is a no-op.\n * @slot panel-header - Replaces the default panel heading (mark plus title).\n * @slot panel-actions - Controls added before the panel's close button.\n * @slot panel-footer - A bar docked below the panel's scroll region, for a composer.\n *\n * @event nile-nav-toggle - Emitted after the nav's collapsed state or forced-rail lock changes. `detail: { collapsed, locked }`.\n * @event nile-panel-toggle - Emitted after the panel opens or closes. `detail: { open, mode }`.\n * @event nile-panel-mode-change - Emitted when the panel flips between docked and overlay. `detail: { mode }`.\n * @event nile-click - Emitted when the header's back control is pressed, or `goBackHeader()` is called. `detail: { value: 'back' }`. Emitted on the shell itself, so check `event.target === shell` as well as the value: a `nile-click` from page content bubbles through the shell too.\n * @event nile-panel-back - Emitted when the panel's back control is pressed, whether the shell's built-in panel chrome or a slotted `nile-app-shell-panel` draws it.\n *\n * @csspart skip-link - The skip-to-content link.\n * @csspart banner - The banner region.\n * @csspart shell-top-bar - The top bar when it spans the shell.\n * @csspart top-bar - The top bar, in either placement.\n * @csspart nav-toggle - The built-in nav toggle button.\n * @csspart rule - The vertical rule after the nav toggle.\n * @csspart ask-rule - The vertical rule before the Ask button, drawn when `top-bar-actions` has content.\n * @csspart top-bar-actions - The end-aligned top bar action group.\n * @csspart ask - The built-in Ask button, the shell's single door to the panel.\n * @csspart title-area - The header's own title block: back control, app icon, title, badge and description.\n * @csspart page-title - The title text, exposed as a heading whose level `headingLevel` sets.\n * @csspart description - The second line under the title.\n * @csspart badge - The pill after the title.\n * @csspart back - The header back control, shown by `headerBack`.\n * @csspart app-icon - The block holding the `app-icon` slot, shown when the slot has content and sized by `--nile-app-shell-app-icon-size`.\n * @csspart tabs - The hoisted tab-strip region, under the top bar.\n * @csspart side-nav - The navigation track.\n * @csspart content-section - The flex row holding container, aside and panel.\n * @csspart container - The content container.\n * @csspart main - The scrolling page body.\n * @csspart aside - The aside region.\n * @csspart panel - The AI panel.\n * @csspart panel-header - The panel's header bar.\n * @csspart panel-back - The panel's back control, shown by `panelBack`.\n * @csspart panel-title - The panel's title text.\n * @csspart panel-actions - The panel's header action group.\n * @csspart panel-close - The panel's close button.\n * @csspart panel-body - The panel's scroll region.\n * @csspart panel-footer - The panel's footer.\n *\n * @cssproperty [--nile-app-shell-side-nav-width=240px] - Expanded nav track.\n * @cssproperty [--nile-app-shell-side-nav-rail-width=70px] - Collapsed track.\n * @cssproperty [--nile-app-shell-side-nav-bg=transparent] - Surface behind a slotted side nav.\n * @cssproperty [--nile-app-shell-side-nav-border=0] - Edge on a slotted side nav.\n * @cssproperty [--nile-app-shell-gutter=4px] - Content-section padding, and the gap between container, aside and panel.\n * @cssproperty [--nile-app-shell-content-padding=24px] - Container inner padding.\n * @cssproperty [--nile-app-shell-top-bar-height=68px] - Top bar height.\n * @cssproperty [--nile-app-shell-panel-header-height=56px] - The panel header's own height.\n * @cssproperty [--nile-app-shell-tabs-height=33px] - Tab strip height.\n * @cssproperty [--nile-app-shell-panel-width=480px] - Docked panel width, and the `min()` ceiling for the overlay drawer.\n * @cssproperty [--nile-app-shell-panel-min-width=360px] - How far a docked panel shrinks to keep pushing rather than covering the page.\n * @cssproperty [--nile-app-shell-aside-width=320px] - Aside width.\n * @cssproperty [--nile-app-shell-aside-min-width=240px] - How far the aside shrinks before the page is asked for room.\n * @cssproperty [--nile-app-shell-content-min-width=640px] - Container floor.\n * @cssproperty [--nile-app-shell-min-width=768px] - Below this the window scrolls rather than the shell compressing.\n * @cssproperty [--nile-app-shell-centered-width=824px] - Column width under `content-align=\"centered\"`.\n * @cssproperty [--nile-app-shell-app-icon-size=20px] - The app icon's box.\n * @cssproperty [--nile-app-shell-utility-size=32px] - Box the shell's own icon controls sit in.\n * @cssproperty [--nile-app-shell-radius=16px] - Container, aside and panel radius.\n * @cssproperty [--nile-app-shell-duration=250ms] - Track and panel motion.\n * @cssproperty [--nile-app-shell-ease] - Easing for moves and resizes.\n *\n * @method openPanel() - Open the AI panel. No-op when the panel is unavailable.\n * @method closePanel() - Close the AI panel.\n * @method togglePanel(force?) - Toggle, or force a specific open state.\n * @method expandNav() - Expand the side nav.\n * @method collapseNav() - Collapse the side nav to a rail.\n * @method toggleNav(force?) - Toggle, or force a specific collapsed state.\n * @method goBackHeader() - Emit `nile-click` with `{ value: 'back' }`, as the header's back control does.\n * @method goBackPanel() - Emit `nile-panel-back`, as the panel's back control does.\n * @method goBack() - Deprecated alias of `goBackPanel()`.\n */\n@customElement('nile-app-shell')\nexport class NileAppShell extends NileElement {\n public static get styles(): CSSResultArray {\n return [styles];\n }\n\n /** The user's nav preference. The nav can still render as a rail while this is false — see `navLocked`. */\n @property({ type: Boolean, reflect: true, attribute: 'nav-collapsed' })\n navCollapsed: boolean = false;\n\n /** Whether the AI panel is open. */\n @property({ type: Boolean, reflect: true, attribute: 'panel-open' })\n panelOpen: boolean = false;\n\n /** Unmounts the AI panel for this route even when the `panel` slot is filled; `openPanel()` becomes a no-op. */\n @property({ type: Boolean, reflect: true, attribute: 'no-panel' })\n noPanel: boolean = false;\n\n /** The default panel heading. Ignored when `panel-header` is slotted. */\n @property({ type: String, attribute: 'panel-label' })\n panelLabel: string = 'Ask Aquera';\n\n /** The page title, rendered as the top bar's own heading (`role=\"heading\"`, level from `headingLevel`) before anything slotted into `top-bar`; leave unset and no title block renders. */\n @property({ type: String, attribute: true, reflect: true })\n pageTitle?: string;\n\n /** The `aria-level` of the `pageTitle` heading, 1–6, so the title can fit the page's own heading outline; e.g. 2 when the page body or banner already has its h1. Out-of-range values clamp to 1–6 and non-numbers fall back to 1. */\n @property({ type: Number, attribute: true, reflect: true })\n headingLevel: number = 1;\n\n /** A second line under the page title; a modifier on `pageTitle` that renders nothing with no title, and takes the bar to 76px. */\n @property({ type: String, attribute: true, reflect: true })\n description?: string;\n\n /** A pill after the page title; a modifier on `pageTitle` like `description`, so with no title there is no badge. */\n @property({ type: String, attribute: true, reflect: true })\n badge?: string;\n\n /** Shows the back arrow before the page title; pressing it emits `nile-click` with `{ value: 'back' }`. Independent of the `app-icon` slot. */\n @property({ type: Boolean, attribute: true, reflect: true })\n headerBack: boolean = false;\n\n /** Accessible name of the header back control. Never rendered as visible text. */\n @property({ type: String, attribute: true, reflect: true })\n headerBackLabel: string = 'Back';\n\n /** Hides the built-in nav toggle. Mount `nile-app-shell-nav-toggle` yourself. */\n @property({ type: Boolean, reflect: true, attribute: 'no-nav-toggle' })\n noNavToggle: boolean = false;\n\n /** Drops the Cmd/Ctrl+J and Escape panel shortcuts. */\n @property({ type: Boolean, attribute: 'no-panel-shortcut' })\n noPanelShortcut: boolean = false;\n\n /** Hides the skip-to-content link. */\n @property({ type: Boolean, reflect: true, attribute: 'no-skip-link' })\n noSkipLink: boolean = false;\n\n /** Label for the skip-to-content link. */\n @property({ type: String, attribute: 'skip-link-label' })\n skipLinkLabel: string = 'Skip to main content';\n\n /** Where the top bar is mounted: inside the container, or spanning the shell. */\n @property({ type: String, reflect: true, attribute: 'top-bar-placement' })\n topBarPlacement: NileAppShellTopBarPlacement = 'content';\n\n /** `centered` caps the page body at `--nile-app-shell-centered-width`. */\n @property({ type: String, reflect: true, attribute: 'content-align' })\n contentAlign: NileAppShellContentAlign = 'fluid';\n\n /** Makes the slotted page root a size query container, so page CSS can size against the content container instead of the viewport. */\n @property({ type: Boolean, reflect: true, attribute: 'content-container' })\n contentContainer: boolean = false;\n\n /** Drops the container's card chrome for a full-bleed page. */\n @property({ type: Boolean, reflect: true })\n flat: boolean = false;\n\n /** Removes the container's inner padding. */\n @property({ type: Boolean, reflect: true, attribute: 'no-padding' })\n noPadding: boolean = false;\n\n /** The label on the built-in Ask button. */\n @property({ type: String, attribute: 'ask-label' })\n askLabel: string = 'Ask';\n\n /** Drops the built-in Ask button, for a bar that renders its own. */\n @property({ type: Boolean, reflect: true, attribute: 'no-ask' })\n noAsk: boolean = false;\n\n /** Shows a back control at the start of the panel header for a panel sub-view; emits `nile-panel-back`. */\n @property({ type: Boolean, reflect: true })\n panelBack: boolean = false;\n\n /** Accessible name of the panel's back control. */\n @property({ type: String })\n panelBackLabel: string = 'Back';\n\n /** Hides the tab strip for this route even when the `tabs` slot is filled. */\n @property({ type: Boolean, reflect: true })\n noTabs: boolean = false;\n\n /** Sizes the shell to the viewport instead of its parent. */\n @property({ type: Boolean, reflect: true, attribute: 'full-height' })\n fullHeight: boolean = false;\n\n /** Below this shell width the panel overlays the content instead of pushing it, and the nav is forced to a rail; zero (default) means never. */\n @property({ type: Number, attribute: 'overlay-breakpoint' })\n overlayBreakpoint: number = 0;\n\n /** Below this shell width an open docked panel forces the nav to a rail. */\n @property({ type: Number, attribute: 'docked-rail-breakpoint' })\n dockedRailBreakpoint: number = 1440;\n\n /** Persists the nav preference and docked panel state under this key. Overlay panel state is never persisted. */\n @property({ type: String, attribute: 'persist-key' })\n persistKey?: string;\n\n /** The panel's current mode. Derived from the shell's width. */\n @state() private _panelMode: NileAppShellPanelMode = 'docked';\n\n /** Whether the nav is held at a rail by the shell's width. */\n @state() private _navLocked: boolean = false;\n\n @state() private _hasBanner: boolean = false;\n @state() private _hasSideNav: boolean = false;\n @state() private _hasTopBar: boolean = false;\n @state() private _hasTopBarActions: boolean = false;\n @state() private _hasTabs: boolean = false;\n @state() private _hasAppIcon: boolean = false;\n @state() private _hasPanel: boolean = false;\n @state() private _hasPanelFooter: boolean = false;\n\n /** True when a `nile-app-shell-panel` is slotted, owning the panel's own chrome so the shell renders a bare region. */\n @state() private _panelOwnsChrome: boolean = false;\n @state() private _hasAside: boolean = false;\n\n @query('.main') private _main?: HTMLElement;\n\n private _width: number = 0;\n private _resizeObserver?: ResizeObserver;\n private _restoredPanelOpen: boolean | null = null;\n\n /** The panel's current mode: `docked` or `overlay`. */\n public get panelMode(): NileAppShellPanelMode {\n return this._panelMode;\n }\n\n /** Whether the shell is holding the nav at a rail. The toggle is disabled. */\n public get navLocked(): boolean {\n return this._navLocked;\n }\n\n /** Whether a panel is mounted for this route. */\n public get panelAvailable(): boolean {\n return this._hasPanel && !this.noPanel;\n }\n\n /** Whether the tab strip is rendered: something slotted, and not switched off. */\n public get tabsVisible(): boolean {\n return this._hasTabs && !this.noTabs;\n }\n\n /** Whether the built-in Ask button is rendered. */\n public get askVisible(): boolean {\n return this.panelAvailable && !this.noAsk;\n }\n\n /** Whether the nav renders as a rail right now, preference or lock. */\n public get rail(): boolean {\n return this.navCollapsed || this._navLocked;\n }\n\n public connectedCallback(): void {\n super.connectedCallback();\n this._restore();\n this._resizeObserver = new ResizeObserver(entries => {\n const entry = entries[entries.length - 1];\n this._measure(entry.contentRect.width);\n });\n this._resizeObserver.observe(this);\n document.addEventListener('keydown', this._onKeyDown);\n }\n\n public disconnectedCallback(): void {\n super.disconnectedCallback();\n this._resizeObserver?.disconnect();\n this._resizeObserver = undefined;\n document.removeEventListener('keydown', this._onKeyDown);\n }\n\n protected willUpdate(changed: PropertyValues<this>): void {\n if (\n changed.has('panelOpen') ||\n changed.has('noPanel') ||\n changed.has('overlayBreakpoint') ||\n changed.has('dockedRailBreakpoint') ||\n // Aside/side-nav mounting changes what a docked panel fits beside; ask the map since private state is outside `keyof this`.\n (changed as Map<string, unknown>).has('_hasAside') ||\n (changed as Map<string, unknown>).has('_hasSideNav')\n ) {\n this._recompute();\n }\n }\n\n protected updated(changed: PropertyValues<this>): void {\n super.updated(changed);\n\n // Derived state the stylesheet and consumers read off the host.\n this.toggleAttribute('rail', this.rail);\n this.toggleAttribute('nav-locked', this._navLocked);\n this.toggleAttribute('has-banner', this._hasBanner);\n this.toggleAttribute('has-side-nav', this._hasSideNav);\n this.toggleAttribute(\n 'has-top-bar',\n this._hasTopBar ||\n this._hasTitleBlock ||\n (!this.noNavToggle && this._hasSideNav)\n );\n // Only with a title to sit under: see _hasTitleBlock.\n this.toggleAttribute(\n 'has-description',\n !!this.description && !!this.pageTitle\n );\n this.toggleAttribute('has-top-bar-actions', this._hasTopBarActions);\n this.toggleAttribute('has-app-icon', this._hasAppIcon);\n this.toggleAttribute('has-ask', this.askVisible);\n this.toggleAttribute('has-tabs', this.tabsVisible);\n this.toggleAttribute('has-aside', this._hasAside);\n this.toggleAttribute('has-panel', this.panelAvailable);\n this.toggleAttribute('has-panel-footer', this._hasPanelFooter);\n this.setAttribute('panel-mode', this._panelMode);\n this.setAttribute(\n 'panel-chrome',\n this._panelOwnsChrome ? 'external' : 'internal'\n );\n\n this._syncSideNav();\n }\n\n /** Open the AI panel. No-op when no panel is mounted for this route. */\n public openPanel(): void {\n if (!this.panelAvailable) return;\n this._setPanelOpen(true);\n }\n\n /** Close the AI panel. */\n public closePanel(): void {\n this._setPanelOpen(false);\n }\n\n /** Toggle the panel, or force a state. */\n public togglePanel(force?: boolean): void {\n const next = force ?? !this.panelOpen;\n if (next) this.openPanel();\n else this.closePanel();\n }\n\n /** Emit `nile-click` with `{ value: 'back' }`, as the header's back control does; the page owns the history. */\n public goBackHeader(): void {\n const detail: NileAppShellClickDetail = { value: 'back' };\n this.emit('nile-click', detail);\n }\n\n /** Emit `nile-panel-back`, as the panel's back control does; the page owns the view stack. */\n public goBackPanel(): void {\n this.emit('nile-panel-back');\n }\n\n /** @deprecated Use `goBackPanel()`; kept as an alias that emits `nile-panel-back`. */\n public goBack(): void {\n this.goBackPanel();\n }\n\n /** Expand the side nav. */\n public expandNav(): void {\n this._setNavCollapsed(false);\n }\n\n /** Collapse the side nav to a rail. */\n public collapseNav(): void {\n this._setNavCollapsed(true);\n }\n\n /** Toggle the side nav, or force a collapsed state. */\n public toggleNav(force?: boolean): void {\n this._setNavCollapsed(force ?? !this.navCollapsed);\n }\n\n /** Move focus to the page body. */\n public focusMain(): void {\n this._main?.focus();\n }\n\n private _setPanelOpen(value: boolean): void {\n if (this.panelOpen === value) return;\n this.panelOpen = value;\n this._persist();\n this.emit('nile-panel-toggle', { open: value, mode: this._panelMode });\n }\n\n private _setNavCollapsed(value: boolean): void {\n if (this.navCollapsed === value) return;\n this.navCollapsed = value;\n this._persist();\n this.emit('nile-nav-toggle', {\n collapsed: value,\n locked: this._navLocked,\n });\n }\n\n /** Records the shell's width and re-derives everything that depends on it. */\n private _measure(width: number): void {\n if (width === this._width) return;\n const first = this._width === 0;\n this._width = width;\n this._recompute();\n\n // A persisted panel state only applies once we know the panel would dock.\n if (first && this._restoredPanelOpen !== null) {\n const open = this._restoredPanelOpen;\n this._restoredPanelOpen = null;\n if (open && this._panelMode === 'docked') this.openPanel();\n }\n }\n\n /** The shell's geometry, read off its own custom properties, falling back to defaults before a computed style exists. */\n private _geometry(): ShellGeometry {\n const style = getComputedStyle(this);\n const px = (name: string, fallback: number): number => {\n const value = parseFloat(style.getPropertyValue(name));\n return Number.isFinite(value) ? value : fallback;\n };\n return {\n // Read the substituted value so they follow the active theme; the literals are the enterprise fallback.\n nav: px('--nile-app-shell-side-nav-width', 240),\n rail: px('--nile-app-shell-side-nav-rail-width', 70),\n gutter: px('--nile-app-shell-gutter', 4),\n content: px('--nile-app-shell-content-min-width', 640),\n aside: px('--nile-app-shell-aside-width', 320),\n panel: px('--nile-app-shell-panel-width', 480),\n };\n }\n\n /** The shell width a docked panel needs to sit beside the content floor, over a side-nav `track` wide. */\n private _dockRequirement(geo: ShellGeometry, track: number): number {\n const nav = this._hasSideNav ? track : 0;\n const aside = this._hasAside ? geo.aside + geo.gutter : 0;\n /* The content row's chrome is end-edge padding plus one flex gap between container and panel (an aside carries its own gap above), and start-edge padding too when no nav track is there to sit flush against. */\n const gutters = this._hasSideNav ? 2 : 3;\n return nav + geo.content + aside + geo.panel + geo.gutter * gutters;\n }\n\n private _recompute(): void {\n const width = this._width;\n const geo = this._geometry();\n\n /* Overlay is opt-in: the shell only overlays below a width the author names, never from running out of room. */\n const overlay =\n this.overlayBreakpoint > 0 && width > 0 && width < this.overlayBreakpoint;\n const mode: NileAppShellPanelMode = overlay ? 'overlay' : 'docked';\n\n // A docked panel squeezes the container, so a narrow shell trades the expanded nav for content width, measured against the expanded track.\n const railAt = Math.max(\n this.dockedRailBreakpoint,\n this._dockRequirement(geo, geo.nav)\n );\n const squeezed =\n !overlay &&\n this.panelOpen &&\n this.panelAvailable &&\n width > 0 &&\n width < railAt;\n const locked = overlay || squeezed;\n\n if (mode !== this._panelMode) {\n this._panelMode = mode;\n this.emit('nile-panel-mode-change', { mode });\n }\n\n if (locked !== this._navLocked) {\n this._navLocked = locked;\n this.emit('nile-nav-toggle', {\n collapsed: this.navCollapsed,\n locked,\n });\n }\n }\n\n /** Mirrors the effective rail state onto a slotted `nile-side-bar`. */\n private _syncSideNav(): void {\n this.querySelectorAll('[slot=\"side-nav\"]').forEach(el => {\n if (el.tagName === 'NILE-SIDE-BAR')\n el.toggleAttribute('collapsed', this.rail);\n });\n }\n\n /** A slotted sidebar's own expand button is the same toggle. */\n private _onSideNavToggle = (event: Event): void => {\n const detail = (event as CustomEvent).detail;\n if (detail && typeof detail.collapsed === 'boolean') {\n this._setNavCollapsed(detail.collapsed);\n }\n };\n\n private _onKeyDown = (event: KeyboardEvent): void => {\n if (this.noPanelShortcut || !this.panelAvailable) return;\n\n const key = event.key ?? '';\n\n if ((event.metaKey || event.ctrlKey) && key.toLowerCase() === 'j') {\n event.preventDefault();\n this.togglePanel();\n return;\n }\n\n // A docked panel is furniture, not a dismissible overlay.\n if (key === 'Escape' && this.panelOpen && this._panelMode === 'overlay') {\n this.closePanel();\n }\n };\n\n private _storageKey(part: string): string {\n return `nile-app-shell:${this.persistKey}:${part}`;\n }\n\n private _restore(): void {\n if (!this.persistKey) return;\n try {\n const nav = localStorage.getItem(this._storageKey('nav-collapsed'));\n if (nav !== null) this.navCollapsed = nav === 'true';\n const panel = localStorage.getItem(this._storageKey('panel-open'));\n if (panel !== null) this._restoredPanelOpen = panel === 'true';\n } catch {\n /* Storage can be blocked; the shell still works without it. */\n }\n }\n\n private _persist(): void {\n if (!this.persistKey) return;\n try {\n localStorage.setItem(\n this._storageKey('nav-collapsed'),\n String(this.navCollapsed)\n );\n if (this._panelMode === 'docked') {\n localStorage.setItem(\n this._storageKey('panel-open'),\n String(this.panelOpen)\n );\n }\n } catch {\n /* Storage can be blocked; the shell still works without it. */\n }\n }\n\n private _onSlotChange(slot: string, event: Event): void {\n const assigned = (event.target as HTMLSlotElement).assignedNodes({\n flatten: true,\n });\n const filled = assigned.some(\n node =>\n node.nodeType === Node.ELEMENT_NODE ||\n (node.textContent ?? '').trim() !== ''\n );\n\n switch (slot) {\n case 'banner':\n this._hasBanner = filled;\n break;\n case 'side-nav':\n this._hasSideNav = filled;\n this._syncSideNav();\n break;\n case 'top-bar':\n this._hasTopBar = filled;\n break;\n case 'top-bar-actions':\n this._hasTopBarActions = filled;\n break;\n case 'tabs':\n this._hasTabs = filled;\n break;\n case 'app-icon':\n this._hasAppIcon = filled;\n break;\n case 'aside':\n this._hasAside = filled;\n break;\n case 'panel':\n this._hasPanel = filled;\n this._panelOwnsChrome = assigned.some(\n node =>\n node.nodeType === Node.ELEMENT_NODE &&\n (node as Element).tagName === 'NILE-APP-SHELL-PANEL'\n );\n this._recompute();\n break;\n case 'panel-footer':\n this._hasPanelFooter = filled;\n break;\n default:\n break;\n }\n }\n\n private _renderNavToggle(): TemplateResult | string {\n if (this.noNavToggle || !this._hasSideNav) return '';\n const expanded = !this.rail;\n return html`\n <div class=\"nav-toggle-group\">\n <nile-button\n class=\"nav-toggle utility-control\"\n part=\"nav-toggle\"\n variant=\"ghost\"\n circle\n aria-controls=\"side-nav\"\n aria-expanded=${expanded ? 'true' : 'false'}\n ?disabled=${this._navLocked}\n title=${this._navLocked\n ? 'The navigation stays collapsed at this window width'\n : expanded\n ? 'Collapse navigation'\n : 'Expand navigation'}\n aria-label=${expanded ? 'Collapse navigation' : 'Expand navigation'}\n @click=${() => this.toggleNav()}\n >\n ${renderGlyph(\n expanded ? 'ng-panel-left' : 'ng-panel-right',\n 20,\n 'currentColor'\n )}\n </nile-button>\n ${this._hasTopBar || this._hasTitleBlock\n ? html`<span class=\"rule\" part=\"rule\"></span>`\n : ''}\n </div>\n `;\n }\n\n /** Whether the header has a title block of its own to draw: a title, the back arrow or a slotted app icon mounts it. */\n private get _hasTitleBlock(): boolean {\n return !!this.pageTitle || this.headerBack || this._hasAppIcon;\n }\n\n /** `headingLevel` as a safe `aria-level`: a whole number clamped to 1–6, and 1 for anything non-numeric. */\n private get _headingLevel(): number {\n const level = Math.trunc(Number(this.headingLevel));\n return Number.isFinite(level) ? Math.min(6, Math.max(1, level)) : 1;\n }\n\n private _renderBack(): TemplateResult | string {\n if (!this.headerBack) return '';\n return html`\n <span class=\"back-line\">\n <button\n class=\"back\"\n part=\"back\"\n type=\"button\"\n aria-label=${this.headerBackLabel}\n title=${this.headerBackLabel}\n @click=${() => this.goBackHeader()}\n >\n ${renderGlyph('ng-arrow-narrow-left', 20, 'currentColor')}\n </button>\n </span>\n `;\n }\n\n private _renderAppIconSlot(): TemplateResult {\n return html`<slot\n name=\"app-icon\"\n @slotchange=${(e: Event) => this._onSlotChange('app-icon', e)}\n ></slot>`;\n }\n\n /* The app-icon slot has to exist whenever the stack does not, or a slotted icon could never mount it: park it, hidden. */\n private _renderAppIconProbe(): TemplateResult {\n return html`<span class=\"app-icon-probe\" hidden\n >${this._renderAppIconSlot()}</span\n >`;\n }\n\n private _renderTitleBlock(): TemplateResult {\n if (!this._hasTitleBlock) return this._renderAppIconProbe();\n\n /* The stack is the title and/or the app icon; a back arrow on its own brings no empty stack. */\n if (!this.pageTitle && !this._hasAppIcon) {\n return html`\n <div class=\"title-area\" part=\"title-area\">\n ${this._renderBack()} ${this._renderAppIconProbe()}\n </div>\n `;\n }\n\n /* The back arrow sits beside the stack; the app icon starts the stack's first row, so the description lines up under the icon when there is one and under the title when not. */\n return html`\n <div class=\"title-area\" part=\"title-area\">\n ${this._renderBack()}\n <div class=\"title-stack\">\n <div class=\"title-row\">\n <span class=\"app-icon\" part=\"app-icon\"\n >${this._renderAppIconSlot()}</span\n >\n ${this.pageTitle\n ? html`<div\n class=\"page-title\"\n part=\"page-title\"\n role=\"heading\"\n aria-level=${this._headingLevel}\n >${this.pageTitle}</div>`\n : ''}\n ${this.pageTitle && this.badge\n ? html`<span class=\"badge\" part=\"badge\">${this.badge}</span>`\n : ''}\n </div>\n ${this.pageTitle && this.description\n ? html`<p class=\"description\" part=\"description\">\n ${this.description}\n </p>`\n : ''}\n </div>\n </div>\n `;\n }\n\n private _renderTopBar(\n placement: NileAppShellTopBarPlacement\n ): TemplateResult {\n return html`\n <div\n class=${placement === 'shell' ? 'top-bar shell-top-bar' : 'top-bar'}\n part=${placement === 'shell' ? 'top-bar shell-top-bar' : 'top-bar'}\n >\n ${this._renderNavToggle()}\n <div class=\"top-bar-content\">\n ${this._renderTitleBlock()}\n <slot\n name=\"top-bar\"\n @slotchange=${(e: Event) => this._onSlotChange('top-bar', e)}\n ></slot>\n </div>\n <div class=\"top-bar-actions\" part=\"top-bar-actions\">\n <slot\n name=\"top-bar-actions\"\n @slotchange=${(e: Event) =>\n this._onSlotChange('top-bar-actions', e)}\n ></slot>\n ${this.askVisible && this._hasTopBarActions\n ? html`<span class=\"rule ask-rule\" part=\"ask-rule\"></span>`\n : ''}\n ${this.askVisible\n ? html`\n <nile-button\n class=\"ask\"\n part=\"ask\"\n exportparts=\"base: ask__base, label: ask__label\"\n variant=\"secondary\"\n @click=${() => this.openPanel()}\n >\n <span slot=\"prefix\" class=\"ask-mark\">\n ${renderGlyph('ng-sparkles', 16, 'currentColor')}\n </span>\n ${this.askLabel}\n </nile-button>\n `\n : ''}\n </div>\n </div>\n `;\n }\n\n public render(): TemplateResult {\n const shellBar = this.topBarPlacement === 'shell';\n\n return html`\n <button\n class=\"skip-link\"\n part=\"skip-link\"\n type=\"button\"\n @click=${() => this.focusMain()}\n >\n ${this.skipLinkLabel}\n </button>\n\n <div class=\"banner\" part=\"banner\">\n <slot\n name=\"banner\"\n @slotchange=${(e: Event) => this._onSlotChange('banner', e)}\n ></slot>\n </div>\n\n ${shellBar ? this._renderTopBar('shell') : ''}\n\n <div\n id=\"side-nav\"\n class=\"side-nav\"\n part=\"side-nav\"\n @nile-toggle=${this._onSideNavToggle}\n >\n <slot\n name=\"side-nav\"\n @slotchange=${(e: Event) => this._onSlotChange('side-nav', e)}\n ></slot>\n </div>\n\n <div class=\"content-section\" part=\"content-section\">\n <div class=\"container\" part=\"container\">\n ${shellBar ? '' : this._renderTopBar('content')}\n <div class=\"tabs\" part=\"tabs\">\n <slot\n name=\"tabs\"\n @slotchange=${(e: Event) => this._onSlotChange('tabs', e)}\n ></slot>\n </div>\n <main class=\"main\" part=\"main\" tabindex=\"-1\">\n <div class=\"main-inner\"><slot></slot></div>\n </main>\n </div>\n\n <div class=\"aside\" part=\"aside\">\n <slot\n name=\"aside\"\n @slotchange=${(e: Event) => this._onSlotChange('aside', e)}\n ></slot>\n </div>\n\n <aside\n class=\"panel\"\n part=\"panel\"\n aria-label=${ifDefined(\n this._panelOwnsChrome ? undefined : this.panelLabel\n )}\n aria-hidden=${this.panelOpen ? 'false' : 'true'}\n >\n ${this._panelOwnsChrome\n ? html`<slot\n name=\"panel\"\n @slotchange=${(e: Event) => this._onSlotChange('panel', e)}\n ></slot>`\n : html`\n <header class=\"panel-header\" part=\"panel-header\">\n ${this.panelBack\n ? html`<nile-button\n class=\"panel-back utility-control\"\n part=\"panel-back\"\n variant=\"ghost\"\n circle\n title=${this.panelBackLabel}\n aria-label=${this.panelBackLabel}\n @click=${() => this.goBackPanel()}\n >\n ${renderGlyph('ng-arrow-left', 20, 'currentColor')}\n </nile-button>`\n : ''}\n <slot name=\"panel-header\">\n <span class=\"panel-heading\">\n <span class=\"panel-mark\">\n ${renderGlyph('ng-sparkles', 20, 'currentColor')}\n </span>\n <h2 class=\"panel-title\" part=\"panel-title\">\n ${this.panelLabel}\n </h2>\n </span>\n </slot>\n <div class=\"panel-actions\" part=\"panel-actions\">\n <slot name=\"panel-actions\"></slot>\n <nile-button\n class=\"panel-close utility-control\"\n part=\"panel-close\"\n variant=\"ghost\"\n circle\n title=\"Close ${this.panelLabel}\"\n aria-label=\"Close ${this.panelLabel}\"\n @click=${() => this.closePanel()}\n >\n ${renderGlyph('ng-x-close', 20, 'currentColor')}\n </nile-button>\n </div>\n </header>\n <div class=\"panel-body\" part=\"panel-body\">\n <slot\n name=\"panel\"\n @slotchange=${(e: Event) => this._onSlotChange('panel', e)}\n ></slot>\n </div>\n <div class=\"panel-footer\" part=\"panel-footer\">\n <slot\n name=\"panel-footer\"\n @slotchange=${(e: Event) =>\n this._onSlotChange('panel-footer', e)}\n ></slot>\n </div>\n `}\n </aside>\n </div>\n `;\n }\n}\n\nexport default NileAppShell;\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nile-app-shell': NileAppShell;\n }\n}\n"],"names":["NileAppShell","p","this","navCollapsed","panelOpen","noPanel","panelLabel","headingLevel","headerBack","headerBackLabel","noNavToggle","noPanelShortcut","noSkipLink","skipLinkLabel","topBarPlacement","contentAlign","contentContainer","flat","noPadding","askLabel","noAsk","panelBack","panelBackLabel","noTabs","fullHeight","overlayBreakpoint","dockedRailBreakpoint","_panelMode","_navLocked","_hasBanner","_hasSideNav","_hasTopBar","_hasTopBarActions","_hasTabs","_hasAppIcon","_hasPanel","_hasPanelFooter","_panelOwnsChrome","_hasAside","_width","_restoredPanelOpen","_onSideNavToggle","event","detail","collapsed","_setNavCollapsed","_onKeyDown","panelAvailable","key","metaKey","ctrlKey","toLowerCase","preventDefault","togglePanel","closePanel","_this","_inherits","_j","_createClass","get","tabsVisible","value","connectedCallback","super","_restore","_resizeObserver","ResizeObserver","entries","entry","length","_measure","contentRect","width","observe","document","addEventListener","disconnectedCallback","disconnect","undefined","removeEventListener","willUpdate","changed","has","_recompute","updated","toggleAttribute","rail","_hasTitleBlock","description","pageTitle","askVisible","setAttribute","_syncSideNav","openPanel","_setPanelOpen","force","goBackHeader","emit","goBackPanel","goBack","expandNav","collapseNav","toggleNav","focusMain","_main","focus","_persist","open","mode","locked","first","_geometry","style","getComputedStyle","px","name","fallback","parseFloat","getPropertyValue","Number","isFinite","nav","gutter","content","aside","panel","_dockRequirement","geo","track","gutters","overlay","railAt","Math","max","squeezed","querySelectorAll","forEach","el","tagName","_storageKey","part","concat","persistKey","localStorage","getItem","_unused","setItem","String","_unused2","_onSlotChange","slot","assigned","target","assignedNodes","flatten","filled","some","node","nodeType","Node","ELEMENT_NODE","textContent","trim","_renderNavToggle","_this4","expanded","html","_templateObject","_taggedTemplateLiteral","renderGlyph","_templateObject2","level","trunc","min","_renderBack","_templateObject3","_renderAppIconSlot","_this6","_templateObject4","e","_renderAppIconProbe","_templateObject5","_renderTitleBlock","_templateObject6","_templateObject7","_headingLevel","badge","_templateObject8","_templateObject9","_templateObject10","_renderTopBar","placement","_templateObject11","_templateObject12","_templateObject13","render","shellBar","_templateObject14","ifDefined","_templateObject15","_templateObject16","_templateObject17","__decorate","styles","NileElement","property","type","Boolean","reflect","attribute","prototype","state","query","customElement"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
System.register(["lit","../internal/app-shell-utility-control-styles.cjs.js"],function(_export,_context){"use strict";var e,n,_templateObject,i;function _taggedTemplateLiteral(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}));}return{setters:[function(_lit){e=_lit.css;},function(_internalAppShellUtilityControlStylesCjsJs){n=_internalAppShellUtilityControlStylesCjsJs.u;}],execute:function execute(){_export("s",i=e(_templateObject||(_templateObject=_taggedTemplateLiteral(["\n :host {\n /* Geometry: design tokens where one exists, bare pixels where none does. */\n /* The nav track mirrors nile-side-bar's own width expressions (enterprise 240/70, NxtGen 296/68); keep in step with nile-side-bar.css.ts. */\n --nile-app-shell-side-nav-width: var(\n --nile-width-240px,\n var(--ng-spacing-296, 240px)\n );\n --nile-app-shell-side-nav-rail-width: var(\n --nile-width-70px,\n var(--ng-spacing-68, 70px)\n );\n --nile-app-shell-gutter: var(--nile-spacing-xs, var(--ng-spacing-xs));\n --nile-app-shell-content-padding: var(\n --nile-spacing-3xl,\n var(--ng-spacing-3xl)\n );\n --nile-app-shell-top-bar-height: 68px;\n /* The panel header keeps its own height, distinct from the page header. */\n --nile-app-shell-panel-header-height: 56px;\n --nile-app-shell-tabs-height: 33px;\n /* The leading app icon is its own 20px size, not the 32px utility box. */\n --nile-app-shell-app-icon-size: 20px;\n --nile-app-shell-panel-width: 480px;\n --nile-app-shell-panel-min-width: 360px;\n --nile-app-shell-aside-width: 320px;\n --nile-app-shell-aside-min-width: 240px;\n --nile-app-shell-content-min-width: 640px;\n --nile-app-shell-min-width: 768px;\n --nile-app-shell-centered-width: 824px;\n /* Both tokens are 32px; the literal is the floor with no theme sheet loaded. */\n --nile-app-shell-utility-size: var(\n --nile-spacing-4xl,\n var(--ng-spacing-4xl, 32px)\n );\n --nile-app-shell-radius: var(--nile-radius-xl, var(--ng-radius-2xl));\n --nile-app-shell-duration: var(\n --nile-transition-duration-default,\n var(--ng-transition-duration-default)\n );\n /* NxtGen ships no easing tokens, so the shell names its own. */\n --nile-app-shell-ease: cubic-bezier(0.2, 0, 0, 1);\n\n --_side-nav-track: var(--nile-app-shell-side-nav-width);\n\n position: relative;\n box-sizing: border-box;\n display: grid;\n grid-template-areas:\n 'banner banner'\n 'top-bar top-bar'\n 'side-nav content';\n grid-template-columns: var(--_side-nav-track) minmax(0, 1fr);\n grid-template-rows: auto auto minmax(0, 1fr);\n /* Below this the window scrolls rather than the shell compressing. */\n min-width: var(--nile-app-shell-min-width);\n height: 100%;\n overflow: hidden;\n background: var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n font-family: var(--nile-font-family-sans-serif, var(--ng-font-family-body));\n transition: grid-template-columns var(--nile-app-shell-duration)\n var(--nile-app-shell-ease);\n }\n\n :host([hidden]) {\n display: none;\n }\n\n :host([full-height]) {\n height: 100dvh;\n }\n\n /* Effective rail state: the user's preference, or a forced rail when narrow. */\n :host([rail]) {\n --_side-nav-track: var(--nile-app-shell-side-nav-rail-width);\n }\n\n :host(:not([has-side-nav])) {\n --_side-nav-track: 0px;\n }\n\n /* The Description axis: a present description adds the 8px its second line occupies. */\n :host([has-description]) {\n --nile-app-shell-top-bar-height: 76px;\n }\n\n /* The top bar compresses before the content does. */\n @media (max-height: 600px) {\n :host {\n --nile-app-shell-top-bar-height: 56px;\n }\n\n :host([has-description]) {\n --nile-app-shell-top-bar-height: 64px;\n }\n }\n\n /* ---------------------------------------------------------------- banner */\n\n .banner {\n grid-area: banner;\n min-width: 0;\n }\n\n :host(:not([has-banner])) .banner {\n display: none;\n }\n\n /* ------------------------------------------------------------- side nav */\n\n .side-nav {\n grid-area: side-nav;\n display: flex;\n min-width: 0;\n overflow: hidden;\n }\n\n :host(:not([has-side-nav])) .side-nav {\n display: none;\n }\n\n /* A slotted sidebar fills the shell-owned track and drops its own surface and edge; set --nile-app-shell-side-nav-bg to restore one. */\n /* width is deliberately not !important: the 100% lets a raw <nav> or nile-app-shell-side-nav fill the track, while a slotted\n nile-side-bar sizes itself from the same tokens the track reads (see the :host geometry block). Tests 21/22 in\n nile-app-shell-regions.test.ts lock the two together; change both or neither. */\n ::slotted([slot='side-nav']) {\n width: 100%;\n height: 100%;\n background: var(--nile-app-shell-side-nav-bg, transparent) !important;\n border-right: var(--nile-app-shell-side-nav-border, 0) !important;\n }\n\n /* -------------------------------------------------------- content column */\n\n .content-section {\n grid-area: content;\n position: relative;\n display: flex;\n min-width: 0;\n gap: var(--nile-app-shell-gutter);\n padding: var(--nile-app-shell-gutter);\n /* Flush against the nav track; the gutter insets the other three sides. */\n padding-inline-start: 0;\n box-sizing: border-box;\n }\n\n /* With no nav track there is nothing to sit flush against, so the start edge takes the gutter too. */\n :host(:not([has-side-nav])) .content-section {\n padding-inline-start: var(--nile-app-shell-gutter);\n }\n\n .container {\n box-sizing: border-box;\n /* The floor is the flex basis, not a min-width, so the container yields instead of overflowing the clipped row. */\n flex: 1 1 var(--nile-app-shell-content-min-width);\n display: flex;\n flex-direction: column;\n min-width: 0;\n overflow: hidden;\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-app-shell-radius);\n box-shadow: var(--nile-box-shadow-none, var(--ng-shadow-none));\n /* The container, not the viewport, is the sizing context for page content. */\n container-type: inline-size;\n container-name: nile-content;\n }\n\n /* content-container moves the size query context onto the slotted page root so page CSS can query nile-content; opt-in as it brings containment. */\n :host([content-container]) slot:not([name])::slotted(*) {\n container-type: inline-size;\n container-name: nile-content;\n }\n\n :host([flat]) .container {\n background: transparent;\n border-color: transparent;\n border-radius: 0;\n }\n\n /* ---------------------------------------------------------------- top bar */\n\n .top-bar {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n height: var(--nile-app-shell-top-bar-height);\n padding-inline: var(--nile-app-shell-content-padding);\n }\n\n /* The header bar draws no bottom rule in any variant; the only divider comes from the tab rail (see .tabs). */\n\n .shell-top-bar {\n grid-area: top-bar;\n min-width: 0;\n padding-inline: var(--nile-spacing-xl, var(--ng-spacing-xl));\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n /* No slotted bar content and no nav toggle means no bar at all. */\n :host(:not([has-top-bar])) .top-bar {\n display: none;\n }\n\n .top-bar-content {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n min-width: 0;\n flex: 1 1 auto;\n }\n\n /* The title block: the header's own heading, the Leading axis and the badge; renders before the top-bar slot. */\n .title-area {\n display: flex;\n /* Top-aligned, not centred: the leading element belongs to the title's row, not the title-plus-description stack. */\n align-items: flex-start;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n /* The leading line box: exactly the page title's line height, centring whatever leading control sits in it. */\n .leading {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n }\n\n .title-stack {\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: var(--nile-spacing-xxs, var(--ng-spacing-xxs));\n min-width: 0;\n }\n\n .title-row {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n .page-title {\n margin: 0;\n min-width: 0;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md));\n line-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-semibold));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .description {\n margin: 0;\n min-width: 0;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));\n line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));\n font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-regular));\n color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n /* The badge sits on the title row and never shrinks the title away; each surface token pairs a Nile name with its NxtGen equivalent. */\n .badge {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n padding-inline: var(--nile-spacing-md, var(--ng-spacing-md));\n padding-block: var(--nile-spacing-xxs, var(--ng-spacing-xxs));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(\n --nile-colors-neutral-400,\n var(--ng-componentcolors-utility-gray-200)\n );\n border-radius: var(--nile-radius-full, var(--ng-radius-full));\n background: var(\n --nile-colors-neutral-100,\n var(--ng-componentcolors-utility-gray-50)\n );\n color: var(\n --nile-colors-dark-500,\n var(--ng-componentcolors-utility-gray-700)\n );\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));\n line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-medium));\n white-space: nowrap;\n }\n\n /* Leading=Back: drawn as a breadcrumb label; the shell owns no history, so pressing it only emits nile-header-back. */\n .back {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n margin: 0;\n padding: 0;\n border: 0;\n background: none;\n cursor: pointer;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md));\n line-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-semibold));\n color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600));\n }\n\n .back:hover {\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n }\n\n .crumb-divider {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n color: var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400));\n }\n\n /* Leading=AppIcon: a 20px block before the title; the page slots the mark, the shell owns the box, surface and radius. */\n .app-icon {\n position: relative;\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--nile-app-shell-app-icon-size);\n height: var(--nile-app-shell-app-icon-size);\n border-radius: var(--nile-radius-sm, var(--ng-radius-sm));\n overflow: hidden;\n }\n\n /* The slotted mark fills the wrapper edge to edge, clipped to the box. */\n .app-icon slot::slotted(*) {\n width: 100%;\n height: 100%;\n display: block;\n object-fit: cover;\n }\n\n /* The wrapper takes no fill; the rim is a white-12% gradient drawn as a masked ::before, with literal mask fallbacks for the nxtgen-only tokens. */\n .app-icon::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n z-index: 1;\n background: linear-gradient(\n 180deg,\n rgb(255 255 255 / 12%) 0%,\n rgb(255 255 255 / 0%) 100%\n );\n mask: var(\n --ng-mask-rim,\n linear-gradient(#000 0 0) content-box,\n linear-gradient(#000 0 0)\n );\n mask-composite: var(--ng-mask-composite-exclude, exclude);\n padding: 1.4px;\n }\n\n :host(:not([leading='app-icon'])) .app-icon,\n :host(:not([leading='back'])) .back,\n :host(:not([leading='back'])) .crumb-divider {\n display: none;\n }\n\n .top-bar-actions {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n margin-inline-start: auto;\n }\n\n /* Hidden when empty, so an empty group's gap does not pull the bar's content short of the padding edge. */\n :host(:not([has-top-bar-actions]):not([has-ask])) .top-bar-actions {\n display: none;\n }\n\n /* The Ask button: a stock <nile-button variant=\"primary\"> the shell renders itself; the only rule here is its flex behaviour as a top-bar item. */\n .ask {\n flex: 0 0 auto;\n }\n\n .ask-mark {\n display: inline-flex;\n align-items: center;\n }\n\n .ask-mark nile-glyph {\n --nile-svg-fill: currentColor;\n --nile-svg-stroke-width: var(--ng-svg-stroke-width);\n width: 16px;\n height: 16px;\n }\n\n .nav-toggle-group {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-lg, var(--ng-spacing-lg));\n }\n\n /* Lands the 20px glyph box, not the 32px utility circle, on the 24px origin: (32 - 20) / 2 = 6. */\n .nav-toggle {\n margin-inline-start: -6px;\n }\n\n .rule {\n flex: 0 0 auto;\n width: var(--nile-border-width-1, var(--ng-border-width-1));\n height: 24px;\n background: var(\n --nile-colors-neutral-400,\n var(--ng-colors-border-secondary)\n );\n }\n\n /* ------------------------------------------------------- utility controls */\n\n /* The shell's own icon controls (nav toggle, panel back and close): the shared utility-control recipe. */\n ","\n\n /* --------------------------------------------------------------- tab strip */\n\n /* Hoisted out of the scroller so it never scrolls away; sits flush under the top bar and carries the header block's single bottom rule. */\n .tabs {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: stretch;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n min-width: 0;\n /* A floor, not a fixed box: the strip is as tall as the row it holds plus its rule. */\n min-height: var(--nile-app-shell-tabs-height);\n padding-inline: var(--nile-app-shell-content-padding);\n /* The strip carries the rule for the whole header block. */\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n /* The header tab's 0/4/12/4 padding composes the 32px row; the 12px bottom gives the active indicator its band, set via the group's public padding hook. */\n ::slotted([slot='tabs']) {\n --nile-nav-tab-padding: var(--nile-spacing-none, var(--ng-spacing-none))\n var(--nile-spacing-xs, var(--ng-spacing-xs))\n var(--nile-spacing-lg, var(--ng-spacing-lg))\n var(--nile-spacing-xs, var(--ng-spacing-xs));\n }\n\n .tabs::-webkit-scrollbar {\n display: none;\n }\n\n :host(:not([has-tabs])) .tabs,\n :host([notabs]) .tabs {\n display: none;\n }\n\n /* A slotted nile-nav-tab-group drops its own track (--track-width:0 on the host) and is bottom-aligned so its indicator sits on the region's single rule. */\n /* Scoped to the group, not the slot, so bare tab controls are not stretched to an equal share of the strip. */\n ::slotted(nile-nav-tab-group[slot='tabs']) {\n --track-width: 0px;\n flex: 1 1 auto;\n min-width: 0;\n align-self: flex-end;\n }\n\n /* ------------------------------------------------------------------- main */\n\n .main {\n box-sizing: border-box;\n flex: 1 1 auto;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: auto;\n /* Top and sides only: the page runs to the container's bottom edge. */\n padding: var(--nile-app-shell-content-padding);\n padding-block-end: 0;\n }\n\n .main:focus {\n outline: none;\n }\n\n :host([no-padding]) .main {\n padding: 0;\n }\n\n .main-inner {\n width: 100%;\n min-height: 0;\n }\n\n /* Centred when short, scrolls from the top when tall. */\n :host([content-align='centered']) .main-inner {\n /* width:100% + max-width leaves space for the auto margins to centre it while short, and scroll from the top when tall. */\n width: 100%;\n max-width: var(--nile-app-shell-centered-width);\n margin: auto;\n }\n\n /* ------------------------------------------------------------------ aside */\n\n .aside {\n box-sizing: border-box;\n /* Gives before the page does, down to its own floor. */\n flex: 0 1 var(--nile-app-shell-aside-width);\n min-width: var(--nile-app-shell-aside-min-width);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: auto;\n padding: var(--nile-app-shell-content-padding);\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n border-radius: var(--nile-app-shell-radius);\n }\n\n :host(:not([has-aside])) .aside {\n display: none;\n }\n\n /* -------------------------------------------------------------- AI panel */\n\n .panel {\n box-sizing: border-box;\n /* The panel pushes the page rather than covering it: full width while the row affords it, shrinking to a real min-width floor. */\n flex: 0 1 var(--nile-app-shell-panel-width);\n width: var(--nile-app-shell-panel-width);\n min-width: var(--nile-app-shell-panel-min-width);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n /* The panel is elevated, so its edge sits a rung above the container's. */\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-app-shell-radius);\n box-shadow: var(--nile-box-shadow-2, var(--ng-shadow-lg));\n }\n\n /* Docked: a flex sibling. It squeezes the content, it does not cover it. */\n :host(:not([panel-open])) .panel {\n display: none;\n }\n\n /* Overlay: contained to the content column, above it, and animated in. */\n :host([panel-mode='overlay']) .panel {\n position: absolute;\n z-index: 1001;\n inset-block: var(--nile-app-shell-gutter);\n inset-inline-end: var(--nile-app-shell-gutter);\n flex: none;\n display: flex;\n width: min(var(--nile-app-shell-panel-width), 92%);\n visibility: hidden;\n transform: translateX(calc(100% + var(--nile-app-shell-gutter)));\n transition: transform var(--nile-app-shell-duration)\n var(--nile-app-shell-ease),\n visibility 0s linear var(--nile-app-shell-duration);\n }\n\n :host([panel-mode='overlay'][panel-open]) .panel {\n visibility: visible;\n transform: none;\n transition: transform var(--nile-app-shell-duration)\n var(--nile-app-shell-ease);\n }\n\n /* An unavailable panel is unmounted in either mode. */\n :host(:not([has-panel])) .panel {\n display: none;\n }\n\n .panel-header {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n height: var(--nile-app-shell-panel-header-height);\n padding-inline: var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n /* The back control for a panel sub-view; stands where the brand mark does in the root view. */\n .panel-back {\n flex: 0 0 auto;\n margin-inline-start: -6px;\n }\n\n /* Mirrors the back control's offset on the end edge: the 20px glyph, not the 32px circle, lands on the padding line. */\n .panel-close {\n margin-inline-end: -6px;\n }\n\n :host([panelback]) .panel-mark {\n display: none;\n }\n\n .panel-heading {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n .panel-mark {\n display: inline-flex;\n color: var(\n --nile-colors-primary-600,\n var(--ng-colors-fg-brand-primary-600)\n );\n }\n\n .panel-mark nile-glyph {\n --nile-svg-fill: currentColor;\n --nile-svg-stroke-width: var(--ng-svg-stroke-width);\n width: 20px;\n height: 20px;\n }\n\n .panel-title {\n margin: 0;\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm));\n font-weight: var(\n --nile-font-weight-semi-bold,\n var(--ng-font-weight-semibold)\n );\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .panel-actions {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n margin-inline-start: auto;\n }\n\n .panel-body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n /* 16 under the header, 24 on the sides and bottom. */\n padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n display: flex;\n flex-direction: column;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n }\n\n .panel-footer {\n flex: 0 0 auto;\n padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n border-top: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n :host(:not([has-panel-footer])) .panel-footer {\n display: none;\n }\n\n /* ---------------------------------------------------------- skip link */\n\n .skip-link {\n position: absolute;\n z-index: 1002;\n inset-inline-start: var(--nile-spacing-md, var(--ng-spacing-md));\n inset-block-start: var(--nile-spacing-md, var(--ng-spacing-md));\n display: inline-flex;\n align-items: center;\n padding: var(--nile-spacing-md, var(--ng-spacing-md))\n var(--nile-spacing-lg, var(--ng-spacing-lg));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-radius-md, var(--ng-radius-md));\n background: var(--nile-colors-white-base, var(--ng-colors-bg-primary));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n font: inherit;\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm));\n box-shadow: var(--nile-box-shadow-2, var(--ng-shadow-lg));\n cursor: pointer;\n transform: translateY(-200%);\n transition: transform\n var(--nile-transition-duration-short, var(--ng-transition-duration-fast))\n var(--nile-app-shell-ease);\n }\n\n .skip-link:focus-visible {\n outline: none;\n transform: none;\n box-shadow: 0 0 0 2px\n var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary)),\n 0 0 0 4px\n var(--nile-colors-primary-600, var(--ng-colors-fg-brand-primary-600));\n }\n\n :host([no-skip-link]) .skip-link {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host,\n .panel,\n .skip-link {\n transition: none;\n }\n }\n"])),n));}};});
|
|
1
|
+
System.register(["lit","../internal/app-shell-utility-control-styles.cjs.js"],function(_export,_context){"use strict";var e,n,_templateObject,a;function _taggedTemplateLiteral(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}));}return{setters:[function(_lit){e=_lit.css;},function(_internalAppShellUtilityControlStylesCjsJs){n=_internalAppShellUtilityControlStylesCjsJs.u;}],execute:function execute(){_export("s",a=e(_templateObject||(_templateObject=_taggedTemplateLiteral(["\n :host {\n /* Geometry: design tokens where one exists, bare pixels where none does. */\n /* The nav track mirrors nile-side-bar's own width expressions (enterprise 240/70, NxtGen 296/68); keep in step with nile-side-bar.css.ts. */\n --nile-app-shell-side-nav-width: var(\n --nile-width-240px,\n var(--ng-spacing-296, 240px)\n );\n --nile-app-shell-side-nav-rail-width: var(\n --nile-width-70px,\n var(--ng-spacing-68, 70px)\n );\n --nile-app-shell-gutter: var(--nile-spacing-xs, var(--ng-spacing-xs));\n --nile-app-shell-content-padding: var(\n --nile-spacing-3xl,\n var(--ng-spacing-3xl)\n );\n --nile-app-shell-top-bar-height: 68px;\n /* The panel header keeps its own height, distinct from the page header. */\n --nile-app-shell-panel-header-height: 56px;\n --nile-app-shell-tabs-height: 33px;\n /* The leading app icon is its own 20px size, not the 32px utility box. */\n --nile-app-shell-app-icon-size: 20px;\n --nile-app-shell-panel-width: 480px;\n --nile-app-shell-panel-min-width: 360px;\n --nile-app-shell-aside-width: 320px;\n --nile-app-shell-aside-min-width: 240px;\n --nile-app-shell-content-min-width: 640px;\n --nile-app-shell-min-width: 768px;\n --nile-app-shell-centered-width: 824px;\n /* Both tokens are 32px; the literal is the floor with no theme sheet loaded. */\n --nile-app-shell-utility-size: var(\n --nile-spacing-4xl,\n var(--ng-spacing-4xl, 32px)\n );\n --nile-app-shell-radius: var(--nile-radius-xl, var(--ng-radius-2xl));\n --nile-app-shell-duration: var(\n --nile-transition-duration-default,\n var(--ng-transition-duration-default)\n );\n /* NxtGen ships no easing tokens, so the shell names its own. */\n --nile-app-shell-ease: cubic-bezier(0.2, 0, 0, 1);\n\n --_side-nav-track: var(--nile-app-shell-side-nav-width);\n\n position: relative;\n box-sizing: border-box;\n display: grid;\n grid-template-areas:\n 'banner banner'\n 'top-bar top-bar'\n 'side-nav content';\n grid-template-columns: var(--_side-nav-track) minmax(0, 1fr);\n grid-template-rows: auto auto minmax(0, 1fr);\n /* Below this the window scrolls rather than the shell compressing. */\n min-width: var(--nile-app-shell-min-width);\n height: 100%;\n overflow: hidden;\n background: var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n font-family: var(--nile-font-family-sans-serif, var(--ng-font-family-body));\n transition: grid-template-columns var(--nile-app-shell-duration)\n var(--nile-app-shell-ease);\n }\n\n :host([hidden]) {\n display: none;\n }\n\n :host([full-height]) {\n height: 100dvh;\n }\n\n /* Effective rail state: the user's preference, or a forced rail when narrow. */\n :host([rail]) {\n --_side-nav-track: var(--nile-app-shell-side-nav-rail-width);\n }\n\n :host(:not([has-side-nav])) {\n --_side-nav-track: 0px;\n }\n\n /* The Description axis: a present description adds the 8px its second line occupies. */\n :host([has-description]) {\n --nile-app-shell-top-bar-height: 76px;\n }\n\n /* The top bar compresses before the content does. */\n @media (max-height: 600px) {\n :host {\n --nile-app-shell-top-bar-height: 56px;\n }\n\n :host([has-description]) {\n --nile-app-shell-top-bar-height: 64px;\n }\n }\n\n /* ---------------------------------------------------------------- banner */\n\n .banner {\n grid-area: banner;\n min-width: 0;\n }\n\n :host(:not([has-banner])) .banner {\n display: none;\n }\n\n /* ------------------------------------------------------------- side nav */\n\n .side-nav {\n grid-area: side-nav;\n display: flex;\n min-width: 0;\n overflow: hidden;\n }\n\n :host(:not([has-side-nav])) .side-nav {\n display: none;\n }\n\n /* A slotted sidebar fills the shell-owned track and drops its own surface and edge; set --nile-app-shell-side-nav-bg to restore one. */\n /* width is deliberately not !important: the 100% lets a raw <nav> or nile-app-shell-side-nav fill the track, while a slotted\n nile-side-bar sizes itself from the same tokens the track reads (see the :host geometry block). Tests 21/22 in\n nile-app-shell-regions.test.ts lock the two together; change both or neither. */\n ::slotted([slot='side-nav']) {\n width: 100%;\n height: 100%;\n background: var(--nile-app-shell-side-nav-bg, transparent) !important;\n border-right: var(--nile-app-shell-side-nav-border, 0) !important;\n }\n\n /* -------------------------------------------------------- content column */\n\n .content-section {\n grid-area: content;\n position: relative;\n display: flex;\n min-width: 0;\n gap: var(--nile-app-shell-gutter);\n padding: var(--nile-app-shell-gutter);\n /* Flush against the nav track; the gutter insets the other three sides. */\n padding-inline-start: 0;\n box-sizing: border-box;\n }\n\n /* With no nav track there is nothing to sit flush against, so the start edge takes the gutter too. */\n :host(:not([has-side-nav])) .content-section {\n padding-inline-start: var(--nile-app-shell-gutter);\n }\n\n .container {\n box-sizing: border-box;\n /* The floor is the flex basis, not a min-width, so the container yields instead of overflowing the clipped row. */\n flex: 1 1 var(--nile-app-shell-content-min-width);\n display: flex;\n flex-direction: column;\n min-width: 0;\n overflow: hidden;\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-app-shell-radius);\n box-shadow: var(--nile-box-shadow-none, var(--ng-shadow-none));\n /* The container, not the viewport, is the sizing context for page content. */\n container-type: inline-size;\n container-name: nile-content;\n }\n\n /* content-container moves the size query context onto the slotted page root so page CSS can query nile-content; opt-in as it brings containment. */\n :host([content-container]) slot:not([name])::slotted(*) {\n container-type: inline-size;\n container-name: nile-content;\n }\n\n :host([flat]) .container {\n background: transparent;\n border-color: transparent;\n border-radius: 0;\n }\n\n /* ---------------------------------------------------------------- top bar */\n\n .top-bar {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n height: var(--nile-app-shell-top-bar-height);\n padding-inline: var(--nile-app-shell-content-padding);\n }\n\n /* The header bar draws no bottom rule in any variant; the only divider comes from the tab rail (see .tabs). */\n\n .shell-top-bar {\n grid-area: top-bar;\n min-width: 0;\n padding-inline: var(--nile-spacing-xl, var(--ng-spacing-xl));\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n /* No slotted bar content and no nav toggle means no bar at all. */\n :host(:not([has-top-bar])) .top-bar {\n display: none;\n }\n\n .top-bar-content {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n min-width: 0;\n flex: 1 1 auto;\n }\n\n /* The title block: the back arrow, then the stack (app icon, heading and badge, with the description under them); renders before the top-bar slot. */\n .title-area {\n display: flex;\n /* Top-aligned, not centred: the back arrow belongs to the title's row, not the title-plus-description stack. */\n align-items: flex-start;\n /* Figma's Title Area gap: 16px from the arrow to the stack. */\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n min-width: 0;\n }\n\n /* The back arrow's line box: exactly the page title's line height, centring the arrow on the title row. */\n .back-line {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n min-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n }\n\n .title-stack {\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: var(--nile-spacing-xxs, var(--ng-spacing-xxs));\n min-width: 0;\n }\n\n .title-row {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n .page-title {\n margin: 0;\n min-width: 0;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md));\n line-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-semibold));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .description {\n margin: 0;\n min-width: 0;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));\n line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));\n font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-regular));\n color: var(--nile-colors-dark-500, var(--ng-colors-text-quaternary-500));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n /* The badge sits on the title row and never shrinks the title away; each surface token pairs a Nile name with its NxtGen equivalent. */\n .badge {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n padding-inline: var(--nile-spacing-md, var(--ng-spacing-md));\n padding-block: var(--nile-spacing-xxs, var(--ng-spacing-xxs));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(\n --nile-colors-neutral-400,\n var(--ng-componentcolors-utility-gray-200)\n );\n border-radius: var(--nile-radius-full, var(--ng-radius-full));\n background: var(\n --nile-colors-neutral-100,\n var(--ng-componentcolors-utility-gray-50)\n );\n color: var(\n --nile-colors-dark-500,\n var(--ng-componentcolors-utility-gray-700)\n );\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));\n line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-medium));\n white-space: nowrap;\n }\n\n /* headerBack: an icon-only native button, so the aria-label names it directly; the shell owns no history, so pressing it only emits nile-click { value: 'back' }. */\n .back {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n margin: 0;\n padding: 0;\n border: 0;\n background: none;\n cursor: pointer;\n color: var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400));\n }\n\n .back:hover {\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n }\n\n /* App icon: a 20px block at the start of the title row, so the description lines up under it; shown whenever the app-icon slot has content. */\n .app-icon {\n position: relative;\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--nile-app-shell-app-icon-size);\n height: var(--nile-app-shell-app-icon-size);\n border-radius: var(--nile-radius-sm, var(--ng-radius-sm));\n overflow: hidden;\n }\n\n /* The slotted mark fills the wrapper edge to edge, clipped to the box. */\n .app-icon slot::slotted(*) {\n width: 100%;\n height: 100%;\n display: block;\n object-fit: cover;\n }\n\n /* The wrapper takes no fill; the rim is a white-12% gradient drawn as a masked ::before, with literal mask fallbacks for the nxtgen-only tokens. */\n .app-icon::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n z-index: 1;\n background: linear-gradient(\n 180deg,\n rgb(255 255 255 / 12%) 0%,\n rgb(255 255 255 / 0%) 100%\n );\n mask: var(\n --ng-mask-rim,\n linear-gradient(#000 0 0) content-box,\n linear-gradient(#000 0 0)\n );\n mask-composite: var(--ng-mask-composite-exclude, exclude);\n padding: 1.4px;\n }\n\n :host(:not([has-app-icon])) .app-icon {\n display: none;\n }\n\n /* Figma's Header Bar gap: 16px between every header action, the divider and Ask. */\n .top-bar-actions {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n margin-inline-start: auto;\n }\n\n /* Hidden when empty, so an empty group's gap does not pull the bar's content short of the padding edge. */\n :host(:not([has-top-bar-actions]):not([has-ask])) .top-bar-actions {\n display: none;\n }\n\n /* The Ask button: a stock <nile-button variant=\"secondary\"> the shell renders itself; the only rule here is its flex behaviour as a top-bar item. */\n .ask {\n flex: 0 0 auto;\n }\n\n .ask-mark {\n display: inline-flex;\n align-items: center;\n }\n\n .ask-mark nile-glyph {\n --nile-svg-fill: currentColor;\n --nile-svg-stroke-width: var(--ng-svg-stroke-width);\n width: 16px;\n height: 16px;\n }\n\n /* 10px after the 32px circle is 16px after the 20px glyph (6px overhang + 10), Figma's toggle-to-divider gap. */\n .nav-toggle-group {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md-alt, var(--ng-spacing-md-alt));\n }\n\n /* Lands the 20px glyph box, not the 32px utility circle, on the 24px origin: (32 - 20) / 2 = 6. */\n .nav-toggle {\n margin-inline-start: -6px;\n }\n\n /* Figma's Divider Line: a 16px 1px stroke that takes no layout width, so the items on both sides sit a clean 16px from it. Used after the nav toggle and, as ask-rule, before Ask. */\n .rule {\n flex: 0 0 auto;\n width: var(--nile-border-width-1, var(--ng-border-width-1));\n margin-inline-end: calc(-1 * var(--nile-border-width-1, var(--ng-border-width-1)));\n height: 16px;\n background: var(\n --nile-colors-neutral-400,\n var(--ng-colors-border-secondary)\n );\n }\n\n /* ------------------------------------------------------- utility controls */\n\n /* The shell's own icon controls (nav toggle, panel back and close): the shared utility-control recipe. */\n ","\n\n /* --------------------------------------------------------------- tab strip */\n\n /* Hoisted out of the scroller so it never scrolls away; sits flush under the top bar and carries the header block's single bottom rule. */\n .tabs {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: stretch;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n min-width: 0;\n /* A floor, not a fixed box: the strip is as tall as the row it holds plus its rule. */\n min-height: var(--nile-app-shell-tabs-height);\n padding-inline: var(--nile-app-shell-content-padding);\n /* The strip carries the rule for the whole header block. */\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n /* The header tab's 0/4/12/4 padding composes the 32px row; the 12px bottom gives the active indicator its band, set via the group's public padding hook. */\n ::slotted([slot='tabs']) {\n --nile-nav-tab-padding: var(--nile-spacing-none, var(--ng-spacing-none))\n var(--nile-spacing-xs, var(--ng-spacing-xs))\n var(--nile-spacing-lg, var(--ng-spacing-lg))\n var(--nile-spacing-xs, var(--ng-spacing-xs));\n }\n\n .tabs::-webkit-scrollbar {\n display: none;\n }\n\n :host(:not([has-tabs])) .tabs,\n :host([notabs]) .tabs {\n display: none;\n }\n\n /* A slotted nile-nav-tab-group drops its own track (--track-width:0 on the host) and is bottom-aligned so its indicator sits on the region's single rule. */\n /* Scoped to the group, not the slot, so bare tab controls are not stretched to an equal share of the strip. */\n ::slotted(nile-nav-tab-group[slot='tabs']) {\n --track-width: 0px;\n /*\n * The active indicator (Figma: fg-brand-primary-alt) is NOT set here: the top placement hard-codes\n * var(--nile-colors-primary-600, var(--ng-colors-text-brand-secondary-700)) inside nile-nav-tab-group's shadow tree, and\n * remapping either token from here would also recolour nile-nav-tab's focus ring and focus label. Known limitation (spec A-7).\n */\n /*\n * The inactive label: nile-nav-tab paints it var(--nile-colors-dark-500, var(--ng-colors-text-secondary-700)), so the strip\n * points the NxtGen fallback at text-quaternary-500. Enterprise defines --nile-colors-dark-500 and is untouched. Inside an\n * underline group nothing else reads text-secondary-700 (only the group's other variants and side placements do).\n */\n --ng-colors-text-secondary-700: var(--ng-colors-text-quaternary-500);\n flex: 1 1 auto;\n min-width: 0;\n align-self: flex-end;\n }\n\n /* ------------------------------------------------------------------- main */\n\n .main {\n box-sizing: border-box;\n flex: 1 1 auto;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: auto;\n /* Top and sides only: the page runs to the container's bottom edge. */\n padding: var(--nile-app-shell-content-padding);\n padding-block-end: 0;\n }\n\n .main:focus {\n outline: none;\n }\n\n :host([no-padding]) .main {\n padding: 0;\n }\n\n .main-inner {\n width: 100%;\n min-height: 0;\n }\n\n /* Centred when short, scrolls from the top when tall. */\n :host([content-align='centered']) .main-inner {\n /* width:100% + max-width leaves space for the auto margins to centre it while short, and scroll from the top when tall. */\n width: 100%;\n max-width: var(--nile-app-shell-centered-width);\n margin: auto;\n }\n\n /* ------------------------------------------------------------------ aside */\n\n .aside {\n box-sizing: border-box;\n /* Gives before the page does, down to its own floor. */\n flex: 0 1 var(--nile-app-shell-aside-width);\n min-width: var(--nile-app-shell-aside-min-width);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: auto;\n padding: var(--nile-app-shell-content-padding);\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n border-radius: var(--nile-app-shell-radius);\n }\n\n :host(:not([has-aside])) .aside {\n display: none;\n }\n\n /* -------------------------------------------------------------- AI panel */\n\n .panel {\n box-sizing: border-box;\n /* The panel pushes the page rather than covering it: full width while the row affords it, shrinking to a real min-width floor. */\n flex: 0 1 var(--nile-app-shell-panel-width);\n width: var(--nile-app-shell-panel-width);\n min-width: var(--nile-app-shell-panel-min-width);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n /* The panel is elevated, so its edge sits a rung above the container's. */\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-app-shell-radius);\n box-shadow: var(--nile-box-shadow-2, var(--ng-shadow-lg));\n }\n\n /* Docked: a flex sibling. It squeezes the content, it does not cover it. */\n :host(:not([panel-open])) .panel {\n display: none;\n }\n\n /* Overlay: contained to the content column, above it, and animated in. */\n :host([panel-mode='overlay']) .panel {\n position: absolute;\n z-index: 1001;\n inset-block: var(--nile-app-shell-gutter);\n inset-inline-end: var(--nile-app-shell-gutter);\n flex: none;\n display: flex;\n width: min(var(--nile-app-shell-panel-width), 92%);\n visibility: hidden;\n transform: translateX(calc(100% + var(--nile-app-shell-gutter)));\n transition: transform var(--nile-app-shell-duration)\n var(--nile-app-shell-ease),\n visibility 0s linear var(--nile-app-shell-duration);\n }\n\n :host([panel-mode='overlay'][panel-open]) .panel {\n visibility: visible;\n transform: none;\n transition: transform var(--nile-app-shell-duration)\n var(--nile-app-shell-ease);\n }\n\n /* An unavailable panel is unmounted in either mode. */\n :host(:not([has-panel])) .panel {\n display: none;\n }\n\n .panel-header {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n height: var(--nile-app-shell-panel-header-height);\n padding-inline: var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n /* The back control for a panel sub-view; stands where the brand mark does in the root view. */\n .panel-back {\n flex: 0 0 auto;\n margin-inline-start: -6px;\n }\n\n /* Mirrors the back control's offset on the end edge: the 20px glyph, not the 32px circle, lands on the padding line. */\n .panel-close {\n margin-inline-end: -6px;\n }\n\n :host([panelback]) .panel-mark {\n display: none;\n }\n\n .panel-heading {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n .panel-mark {\n display: inline-flex;\n color: var(\n --nile-colors-primary-600,\n var(--ng-colors-fg-brand-primary-600)\n );\n }\n\n .panel-mark nile-glyph {\n --nile-svg-fill: currentColor;\n --nile-svg-stroke-width: var(--ng-svg-stroke-width);\n width: 20px;\n height: 20px;\n }\n\n .panel-title {\n margin: 0;\n /* Figma's Assistant Title: Text lg/Semibold, 18/28 on NxtGen. Enterprise keeps --nile-type-scale-3, and it defines no --ng-* tokens, so the line-height declaration is invalid there and the title inherits its line height exactly as before. */\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-lg));\n line-height: var(--ng-line-height-text-lg);\n font-weight: var(\n --nile-font-weight-semi-bold,\n var(--ng-font-weight-semibold)\n );\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .panel-actions {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n margin-inline-start: auto;\n }\n\n .panel-body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n /* 16 under the header, 24 on the sides and bottom. */\n padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n display: flex;\n flex-direction: column;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n }\n\n .panel-footer {\n flex: 0 0 auto;\n padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n border-top: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n :host(:not([has-panel-footer])) .panel-footer {\n display: none;\n }\n\n /* ---------------------------------------------------------- skip link */\n\n .skip-link {\n position: absolute;\n z-index: 1002;\n inset-inline-start: var(--nile-spacing-md, var(--ng-spacing-md));\n inset-block-start: var(--nile-spacing-md, var(--ng-spacing-md));\n display: inline-flex;\n align-items: center;\n padding: var(--nile-spacing-md, var(--ng-spacing-md))\n var(--nile-spacing-lg, var(--ng-spacing-lg));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-radius-md, var(--ng-radius-md));\n background: var(--nile-colors-white-base, var(--ng-colors-bg-primary));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n font: inherit;\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm));\n box-shadow: var(--nile-box-shadow-2, var(--ng-shadow-lg));\n cursor: pointer;\n transform: translateY(-200%);\n transition: transform\n var(--nile-transition-duration-short, var(--ng-transition-duration-fast))\n var(--nile-app-shell-ease);\n }\n\n .skip-link:focus-visible {\n outline: none;\n transform: none;\n box-shadow: 0 0 0 2px\n var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary)),\n 0 0 0 4px\n var(--nile-colors-primary-600, var(--ng-colors-fg-brand-primary-600));\n }\n\n :host([no-skip-link]) .skip-link {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host,\n .panel,\n .skip-link {\n transition: none;\n }\n }\n"])),n));}};});
|
|
2
2
|
//# sourceMappingURL=nile-app-shell.css.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nile-app-shell.css.cjs.js","sources":["../../../src/nile-app-shell/nile-app-shell.css.ts"],"sourcesContent":["/**\n * Copyright Aquera Inc 2023\n *\n * This source code is licensed under the BSD-3-Clause license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { css } from 'lit';\nimport { utilityControlStyles } from '../internal/app-shell-utility-control-styles';\n\n/** AppShell CSS: a grid of banner, top bar, side-nav track and content column, whose flex row holds the container, aside and docked AI panel. */\nexport const styles = css`\n :host {\n /* Geometry: design tokens where one exists, bare pixels where none does. */\n /* The nav track mirrors nile-side-bar's own width expressions (enterprise 240/70, NxtGen 296/68); keep in step with nile-side-bar.css.ts. */\n --nile-app-shell-side-nav-width: var(\n --nile-width-240px,\n var(--ng-spacing-296, 240px)\n );\n --nile-app-shell-side-nav-rail-width: var(\n --nile-width-70px,\n var(--ng-spacing-68, 70px)\n );\n --nile-app-shell-gutter: var(--nile-spacing-xs, var(--ng-spacing-xs));\n --nile-app-shell-content-padding: var(\n --nile-spacing-3xl,\n var(--ng-spacing-3xl)\n );\n --nile-app-shell-top-bar-height: 68px;\n /* The panel header keeps its own height, distinct from the page header. */\n --nile-app-shell-panel-header-height: 56px;\n --nile-app-shell-tabs-height: 33px;\n /* The leading app icon is its own 20px size, not the 32px utility box. */\n --nile-app-shell-app-icon-size: 20px;\n --nile-app-shell-panel-width: 480px;\n --nile-app-shell-panel-min-width: 360px;\n --nile-app-shell-aside-width: 320px;\n --nile-app-shell-aside-min-width: 240px;\n --nile-app-shell-content-min-width: 640px;\n --nile-app-shell-min-width: 768px;\n --nile-app-shell-centered-width: 824px;\n /* Both tokens are 32px; the literal is the floor with no theme sheet loaded. */\n --nile-app-shell-utility-size: var(\n --nile-spacing-4xl,\n var(--ng-spacing-4xl, 32px)\n );\n --nile-app-shell-radius: var(--nile-radius-xl, var(--ng-radius-2xl));\n --nile-app-shell-duration: var(\n --nile-transition-duration-default,\n var(--ng-transition-duration-default)\n );\n /* NxtGen ships no easing tokens, so the shell names its own. */\n --nile-app-shell-ease: cubic-bezier(0.2, 0, 0, 1);\n\n --_side-nav-track: var(--nile-app-shell-side-nav-width);\n\n position: relative;\n box-sizing: border-box;\n display: grid;\n grid-template-areas:\n 'banner banner'\n 'top-bar top-bar'\n 'side-nav content';\n grid-template-columns: var(--_side-nav-track) minmax(0, 1fr);\n grid-template-rows: auto auto minmax(0, 1fr);\n /* Below this the window scrolls rather than the shell compressing. */\n min-width: var(--nile-app-shell-min-width);\n height: 100%;\n overflow: hidden;\n background: var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n font-family: var(--nile-font-family-sans-serif, var(--ng-font-family-body));\n transition: grid-template-columns var(--nile-app-shell-duration)\n var(--nile-app-shell-ease);\n }\n\n :host([hidden]) {\n display: none;\n }\n\n :host([full-height]) {\n height: 100dvh;\n }\n\n /* Effective rail state: the user's preference, or a forced rail when narrow. */\n :host([rail]) {\n --_side-nav-track: var(--nile-app-shell-side-nav-rail-width);\n }\n\n :host(:not([has-side-nav])) {\n --_side-nav-track: 0px;\n }\n\n /* The Description axis: a present description adds the 8px its second line occupies. */\n :host([has-description]) {\n --nile-app-shell-top-bar-height: 76px;\n }\n\n /* The top bar compresses before the content does. */\n @media (max-height: 600px) {\n :host {\n --nile-app-shell-top-bar-height: 56px;\n }\n\n :host([has-description]) {\n --nile-app-shell-top-bar-height: 64px;\n }\n }\n\n /* ---------------------------------------------------------------- banner */\n\n .banner {\n grid-area: banner;\n min-width: 0;\n }\n\n :host(:not([has-banner])) .banner {\n display: none;\n }\n\n /* ------------------------------------------------------------- side nav */\n\n .side-nav {\n grid-area: side-nav;\n display: flex;\n min-width: 0;\n overflow: hidden;\n }\n\n :host(:not([has-side-nav])) .side-nav {\n display: none;\n }\n\n /* A slotted sidebar fills the shell-owned track and drops its own surface and edge; set --nile-app-shell-side-nav-bg to restore one. */\n /* width is deliberately not !important: the 100% lets a raw <nav> or nile-app-shell-side-nav fill the track, while a slotted\n nile-side-bar sizes itself from the same tokens the track reads (see the :host geometry block). Tests 21/22 in\n nile-app-shell-regions.test.ts lock the two together; change both or neither. */\n ::slotted([slot='side-nav']) {\n width: 100%;\n height: 100%;\n background: var(--nile-app-shell-side-nav-bg, transparent) !important;\n border-right: var(--nile-app-shell-side-nav-border, 0) !important;\n }\n\n /* -------------------------------------------------------- content column */\n\n .content-section {\n grid-area: content;\n position: relative;\n display: flex;\n min-width: 0;\n gap: var(--nile-app-shell-gutter);\n padding: var(--nile-app-shell-gutter);\n /* Flush against the nav track; the gutter insets the other three sides. */\n padding-inline-start: 0;\n box-sizing: border-box;\n }\n\n /* With no nav track there is nothing to sit flush against, so the start edge takes the gutter too. */\n :host(:not([has-side-nav])) .content-section {\n padding-inline-start: var(--nile-app-shell-gutter);\n }\n\n .container {\n box-sizing: border-box;\n /* The floor is the flex basis, not a min-width, so the container yields instead of overflowing the clipped row. */\n flex: 1 1 var(--nile-app-shell-content-min-width);\n display: flex;\n flex-direction: column;\n min-width: 0;\n overflow: hidden;\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-app-shell-radius);\n box-shadow: var(--nile-box-shadow-none, var(--ng-shadow-none));\n /* The container, not the viewport, is the sizing context for page content. */\n container-type: inline-size;\n container-name: nile-content;\n }\n\n /* content-container moves the size query context onto the slotted page root so page CSS can query nile-content; opt-in as it brings containment. */\n :host([content-container]) slot:not([name])::slotted(*) {\n container-type: inline-size;\n container-name: nile-content;\n }\n\n :host([flat]) .container {\n background: transparent;\n border-color: transparent;\n border-radius: 0;\n }\n\n /* ---------------------------------------------------------------- top bar */\n\n .top-bar {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n height: var(--nile-app-shell-top-bar-height);\n padding-inline: var(--nile-app-shell-content-padding);\n }\n\n /* The header bar draws no bottom rule in any variant; the only divider comes from the tab rail (see .tabs). */\n\n .shell-top-bar {\n grid-area: top-bar;\n min-width: 0;\n padding-inline: var(--nile-spacing-xl, var(--ng-spacing-xl));\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n /* No slotted bar content and no nav toggle means no bar at all. */\n :host(:not([has-top-bar])) .top-bar {\n display: none;\n }\n\n .top-bar-content {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n min-width: 0;\n flex: 1 1 auto;\n }\n\n /* The title block: the header's own heading, the Leading axis and the badge; renders before the top-bar slot. */\n .title-area {\n display: flex;\n /* Top-aligned, not centred: the leading element belongs to the title's row, not the title-plus-description stack. */\n align-items: flex-start;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n /* The leading line box: exactly the page title's line height, centring whatever leading control sits in it. */\n .leading {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n }\n\n .title-stack {\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: var(--nile-spacing-xxs, var(--ng-spacing-xxs));\n min-width: 0;\n }\n\n .title-row {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n .page-title {\n margin: 0;\n min-width: 0;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md));\n line-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-semibold));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .description {\n margin: 0;\n min-width: 0;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));\n line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));\n font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-regular));\n color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n /* The badge sits on the title row and never shrinks the title away; each surface token pairs a Nile name with its NxtGen equivalent. */\n .badge {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n padding-inline: var(--nile-spacing-md, var(--ng-spacing-md));\n padding-block: var(--nile-spacing-xxs, var(--ng-spacing-xxs));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(\n --nile-colors-neutral-400,\n var(--ng-componentcolors-utility-gray-200)\n );\n border-radius: var(--nile-radius-full, var(--ng-radius-full));\n background: var(\n --nile-colors-neutral-100,\n var(--ng-componentcolors-utility-gray-50)\n );\n color: var(\n --nile-colors-dark-500,\n var(--ng-componentcolors-utility-gray-700)\n );\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));\n line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-medium));\n white-space: nowrap;\n }\n\n /* Leading=Back: drawn as a breadcrumb label; the shell owns no history, so pressing it only emits nile-header-back. */\n .back {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n margin: 0;\n padding: 0;\n border: 0;\n background: none;\n cursor: pointer;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md));\n line-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-semibold));\n color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600));\n }\n\n .back:hover {\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n }\n\n .crumb-divider {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n color: var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400));\n }\n\n /* Leading=AppIcon: a 20px block before the title; the page slots the mark, the shell owns the box, surface and radius. */\n .app-icon {\n position: relative;\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--nile-app-shell-app-icon-size);\n height: var(--nile-app-shell-app-icon-size);\n border-radius: var(--nile-radius-sm, var(--ng-radius-sm));\n overflow: hidden;\n }\n\n /* The slotted mark fills the wrapper edge to edge, clipped to the box. */\n .app-icon slot::slotted(*) {\n width: 100%;\n height: 100%;\n display: block;\n object-fit: cover;\n }\n\n /* The wrapper takes no fill; the rim is a white-12% gradient drawn as a masked ::before, with literal mask fallbacks for the nxtgen-only tokens. */\n .app-icon::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n z-index: 1;\n background: linear-gradient(\n 180deg,\n rgb(255 255 255 / 12%) 0%,\n rgb(255 255 255 / 0%) 100%\n );\n mask: var(\n --ng-mask-rim,\n linear-gradient(#000 0 0) content-box,\n linear-gradient(#000 0 0)\n );\n mask-composite: var(--ng-mask-composite-exclude, exclude);\n padding: 1.4px;\n }\n\n :host(:not([leading='app-icon'])) .app-icon,\n :host(:not([leading='back'])) .back,\n :host(:not([leading='back'])) .crumb-divider {\n display: none;\n }\n\n .top-bar-actions {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n margin-inline-start: auto;\n }\n\n /* Hidden when empty, so an empty group's gap does not pull the bar's content short of the padding edge. */\n :host(:not([has-top-bar-actions]):not([has-ask])) .top-bar-actions {\n display: none;\n }\n\n /* The Ask button: a stock <nile-button variant=\"primary\"> the shell renders itself; the only rule here is its flex behaviour as a top-bar item. */\n .ask {\n flex: 0 0 auto;\n }\n\n .ask-mark {\n display: inline-flex;\n align-items: center;\n }\n\n .ask-mark nile-glyph {\n --nile-svg-fill: currentColor;\n --nile-svg-stroke-width: var(--ng-svg-stroke-width);\n width: 16px;\n height: 16px;\n }\n\n .nav-toggle-group {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-lg, var(--ng-spacing-lg));\n }\n\n /* Lands the 20px glyph box, not the 32px utility circle, on the 24px origin: (32 - 20) / 2 = 6. */\n .nav-toggle {\n margin-inline-start: -6px;\n }\n\n .rule {\n flex: 0 0 auto;\n width: var(--nile-border-width-1, var(--ng-border-width-1));\n height: 24px;\n background: var(\n --nile-colors-neutral-400,\n var(--ng-colors-border-secondary)\n );\n }\n\n /* ------------------------------------------------------- utility controls */\n\n /* The shell's own icon controls (nav toggle, panel back and close): the shared utility-control recipe. */\n ${utilityControlStyles}\n\n /* --------------------------------------------------------------- tab strip */\n\n /* Hoisted out of the scroller so it never scrolls away; sits flush under the top bar and carries the header block's single bottom rule. */\n .tabs {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: stretch;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n min-width: 0;\n /* A floor, not a fixed box: the strip is as tall as the row it holds plus its rule. */\n min-height: var(--nile-app-shell-tabs-height);\n padding-inline: var(--nile-app-shell-content-padding);\n /* The strip carries the rule for the whole header block. */\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n /* The header tab's 0/4/12/4 padding composes the 32px row; the 12px bottom gives the active indicator its band, set via the group's public padding hook. */\n ::slotted([slot='tabs']) {\n --nile-nav-tab-padding: var(--nile-spacing-none, var(--ng-spacing-none))\n var(--nile-spacing-xs, var(--ng-spacing-xs))\n var(--nile-spacing-lg, var(--ng-spacing-lg))\n var(--nile-spacing-xs, var(--ng-spacing-xs));\n }\n\n .tabs::-webkit-scrollbar {\n display: none;\n }\n\n :host(:not([has-tabs])) .tabs,\n :host([notabs]) .tabs {\n display: none;\n }\n\n /* A slotted nile-nav-tab-group drops its own track (--track-width:0 on the host) and is bottom-aligned so its indicator sits on the region's single rule. */\n /* Scoped to the group, not the slot, so bare tab controls are not stretched to an equal share of the strip. */\n ::slotted(nile-nav-tab-group[slot='tabs']) {\n --track-width: 0px;\n flex: 1 1 auto;\n min-width: 0;\n align-self: flex-end;\n }\n\n /* ------------------------------------------------------------------- main */\n\n .main {\n box-sizing: border-box;\n flex: 1 1 auto;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: auto;\n /* Top and sides only: the page runs to the container's bottom edge. */\n padding: var(--nile-app-shell-content-padding);\n padding-block-end: 0;\n }\n\n .main:focus {\n outline: none;\n }\n\n :host([no-padding]) .main {\n padding: 0;\n }\n\n .main-inner {\n width: 100%;\n min-height: 0;\n }\n\n /* Centred when short, scrolls from the top when tall. */\n :host([content-align='centered']) .main-inner {\n /* width:100% + max-width leaves space for the auto margins to centre it while short, and scroll from the top when tall. */\n width: 100%;\n max-width: var(--nile-app-shell-centered-width);\n margin: auto;\n }\n\n /* ------------------------------------------------------------------ aside */\n\n .aside {\n box-sizing: border-box;\n /* Gives before the page does, down to its own floor. */\n flex: 0 1 var(--nile-app-shell-aside-width);\n min-width: var(--nile-app-shell-aside-min-width);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: auto;\n padding: var(--nile-app-shell-content-padding);\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n border-radius: var(--nile-app-shell-radius);\n }\n\n :host(:not([has-aside])) .aside {\n display: none;\n }\n\n /* -------------------------------------------------------------- AI panel */\n\n .panel {\n box-sizing: border-box;\n /* The panel pushes the page rather than covering it: full width while the row affords it, shrinking to a real min-width floor. */\n flex: 0 1 var(--nile-app-shell-panel-width);\n width: var(--nile-app-shell-panel-width);\n min-width: var(--nile-app-shell-panel-min-width);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n /* The panel is elevated, so its edge sits a rung above the container's. */\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-app-shell-radius);\n box-shadow: var(--nile-box-shadow-2, var(--ng-shadow-lg));\n }\n\n /* Docked: a flex sibling. It squeezes the content, it does not cover it. */\n :host(:not([panel-open])) .panel {\n display: none;\n }\n\n /* Overlay: contained to the content column, above it, and animated in. */\n :host([panel-mode='overlay']) .panel {\n position: absolute;\n z-index: 1001;\n inset-block: var(--nile-app-shell-gutter);\n inset-inline-end: var(--nile-app-shell-gutter);\n flex: none;\n display: flex;\n width: min(var(--nile-app-shell-panel-width), 92%);\n visibility: hidden;\n transform: translateX(calc(100% + var(--nile-app-shell-gutter)));\n transition: transform var(--nile-app-shell-duration)\n var(--nile-app-shell-ease),\n visibility 0s linear var(--nile-app-shell-duration);\n }\n\n :host([panel-mode='overlay'][panel-open]) .panel {\n visibility: visible;\n transform: none;\n transition: transform var(--nile-app-shell-duration)\n var(--nile-app-shell-ease);\n }\n\n /* An unavailable panel is unmounted in either mode. */\n :host(:not([has-panel])) .panel {\n display: none;\n }\n\n .panel-header {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n height: var(--nile-app-shell-panel-header-height);\n padding-inline: var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n /* The back control for a panel sub-view; stands where the brand mark does in the root view. */\n .panel-back {\n flex: 0 0 auto;\n margin-inline-start: -6px;\n }\n\n /* Mirrors the back control's offset on the end edge: the 20px glyph, not the 32px circle, lands on the padding line. */\n .panel-close {\n margin-inline-end: -6px;\n }\n\n :host([panelback]) .panel-mark {\n display: none;\n }\n\n .panel-heading {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n .panel-mark {\n display: inline-flex;\n color: var(\n --nile-colors-primary-600,\n var(--ng-colors-fg-brand-primary-600)\n );\n }\n\n .panel-mark nile-glyph {\n --nile-svg-fill: currentColor;\n --nile-svg-stroke-width: var(--ng-svg-stroke-width);\n width: 20px;\n height: 20px;\n }\n\n .panel-title {\n margin: 0;\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm));\n font-weight: var(\n --nile-font-weight-semi-bold,\n var(--ng-font-weight-semibold)\n );\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .panel-actions {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n margin-inline-start: auto;\n }\n\n .panel-body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n /* 16 under the header, 24 on the sides and bottom. */\n padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n display: flex;\n flex-direction: column;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n }\n\n .panel-footer {\n flex: 0 0 auto;\n padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n border-top: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n :host(:not([has-panel-footer])) .panel-footer {\n display: none;\n }\n\n /* ---------------------------------------------------------- skip link */\n\n .skip-link {\n position: absolute;\n z-index: 1002;\n inset-inline-start: var(--nile-spacing-md, var(--ng-spacing-md));\n inset-block-start: var(--nile-spacing-md, var(--ng-spacing-md));\n display: inline-flex;\n align-items: center;\n padding: var(--nile-spacing-md, var(--ng-spacing-md))\n var(--nile-spacing-lg, var(--ng-spacing-lg));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-radius-md, var(--ng-radius-md));\n background: var(--nile-colors-white-base, var(--ng-colors-bg-primary));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n font: inherit;\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm));\n box-shadow: var(--nile-box-shadow-2, var(--ng-shadow-lg));\n cursor: pointer;\n transform: translateY(-200%);\n transition: transform\n var(--nile-transition-duration-short, var(--ng-transition-duration-fast))\n var(--nile-app-shell-ease);\n }\n\n .skip-link:focus-visible {\n outline: none;\n transform: none;\n box-shadow: 0 0 0 2px\n var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary)),\n 0 0 0 4px\n var(--nile-colors-primary-600, var(--ng-colors-fg-brand-primary-600));\n }\n\n :host([no-skip-link]) .skip-link {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host,\n .panel,\n .skip-link {\n transition: none;\n }\n }\n`;\n\nexport default [styles];\n"],"names":["styles","css","_templateObject","_taggedTemplateLiteral","utilityControlStyles"],"mappings":"kdAWaA,EAASC,CAAG,CAAAC,eAAA,GAAAA,eAAA,CAAAC,sBAAA,m3wBAobrBC,CAAAA"}
|
|
1
|
+
{"version":3,"file":"nile-app-shell.css.cjs.js","sources":["../../../src/nile-app-shell/nile-app-shell.css.ts"],"sourcesContent":["/**\n * Copyright Aquera Inc 2023\n *\n * This source code is licensed under the BSD-3-Clause license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { css } from 'lit';\nimport { utilityControlStyles } from '../internal/app-shell-utility-control-styles';\n\n/** AppShell CSS: a grid of banner, top bar, side-nav track and content column, whose flex row holds the container, aside and docked AI panel. */\nexport const styles = css`\n :host {\n /* Geometry: design tokens where one exists, bare pixels where none does. */\n /* The nav track mirrors nile-side-bar's own width expressions (enterprise 240/70, NxtGen 296/68); keep in step with nile-side-bar.css.ts. */\n --nile-app-shell-side-nav-width: var(\n --nile-width-240px,\n var(--ng-spacing-296, 240px)\n );\n --nile-app-shell-side-nav-rail-width: var(\n --nile-width-70px,\n var(--ng-spacing-68, 70px)\n );\n --nile-app-shell-gutter: var(--nile-spacing-xs, var(--ng-spacing-xs));\n --nile-app-shell-content-padding: var(\n --nile-spacing-3xl,\n var(--ng-spacing-3xl)\n );\n --nile-app-shell-top-bar-height: 68px;\n /* The panel header keeps its own height, distinct from the page header. */\n --nile-app-shell-panel-header-height: 56px;\n --nile-app-shell-tabs-height: 33px;\n /* The leading app icon is its own 20px size, not the 32px utility box. */\n --nile-app-shell-app-icon-size: 20px;\n --nile-app-shell-panel-width: 480px;\n --nile-app-shell-panel-min-width: 360px;\n --nile-app-shell-aside-width: 320px;\n --nile-app-shell-aside-min-width: 240px;\n --nile-app-shell-content-min-width: 640px;\n --nile-app-shell-min-width: 768px;\n --nile-app-shell-centered-width: 824px;\n /* Both tokens are 32px; the literal is the floor with no theme sheet loaded. */\n --nile-app-shell-utility-size: var(\n --nile-spacing-4xl,\n var(--ng-spacing-4xl, 32px)\n );\n --nile-app-shell-radius: var(--nile-radius-xl, var(--ng-radius-2xl));\n --nile-app-shell-duration: var(\n --nile-transition-duration-default,\n var(--ng-transition-duration-default)\n );\n /* NxtGen ships no easing tokens, so the shell names its own. */\n --nile-app-shell-ease: cubic-bezier(0.2, 0, 0, 1);\n\n --_side-nav-track: var(--nile-app-shell-side-nav-width);\n\n position: relative;\n box-sizing: border-box;\n display: grid;\n grid-template-areas:\n 'banner banner'\n 'top-bar top-bar'\n 'side-nav content';\n grid-template-columns: var(--_side-nav-track) minmax(0, 1fr);\n grid-template-rows: auto auto minmax(0, 1fr);\n /* Below this the window scrolls rather than the shell compressing. */\n min-width: var(--nile-app-shell-min-width);\n height: 100%;\n overflow: hidden;\n background: var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n font-family: var(--nile-font-family-sans-serif, var(--ng-font-family-body));\n transition: grid-template-columns var(--nile-app-shell-duration)\n var(--nile-app-shell-ease);\n }\n\n :host([hidden]) {\n display: none;\n }\n\n :host([full-height]) {\n height: 100dvh;\n }\n\n /* Effective rail state: the user's preference, or a forced rail when narrow. */\n :host([rail]) {\n --_side-nav-track: var(--nile-app-shell-side-nav-rail-width);\n }\n\n :host(:not([has-side-nav])) {\n --_side-nav-track: 0px;\n }\n\n /* The Description axis: a present description adds the 8px its second line occupies. */\n :host([has-description]) {\n --nile-app-shell-top-bar-height: 76px;\n }\n\n /* The top bar compresses before the content does. */\n @media (max-height: 600px) {\n :host {\n --nile-app-shell-top-bar-height: 56px;\n }\n\n :host([has-description]) {\n --nile-app-shell-top-bar-height: 64px;\n }\n }\n\n /* ---------------------------------------------------------------- banner */\n\n .banner {\n grid-area: banner;\n min-width: 0;\n }\n\n :host(:not([has-banner])) .banner {\n display: none;\n }\n\n /* ------------------------------------------------------------- side nav */\n\n .side-nav {\n grid-area: side-nav;\n display: flex;\n min-width: 0;\n overflow: hidden;\n }\n\n :host(:not([has-side-nav])) .side-nav {\n display: none;\n }\n\n /* A slotted sidebar fills the shell-owned track and drops its own surface and edge; set --nile-app-shell-side-nav-bg to restore one. */\n /* width is deliberately not !important: the 100% lets a raw <nav> or nile-app-shell-side-nav fill the track, while a slotted\n nile-side-bar sizes itself from the same tokens the track reads (see the :host geometry block). Tests 21/22 in\n nile-app-shell-regions.test.ts lock the two together; change both or neither. */\n ::slotted([slot='side-nav']) {\n width: 100%;\n height: 100%;\n background: var(--nile-app-shell-side-nav-bg, transparent) !important;\n border-right: var(--nile-app-shell-side-nav-border, 0) !important;\n }\n\n /* -------------------------------------------------------- content column */\n\n .content-section {\n grid-area: content;\n position: relative;\n display: flex;\n min-width: 0;\n gap: var(--nile-app-shell-gutter);\n padding: var(--nile-app-shell-gutter);\n /* Flush against the nav track; the gutter insets the other three sides. */\n padding-inline-start: 0;\n box-sizing: border-box;\n }\n\n /* With no nav track there is nothing to sit flush against, so the start edge takes the gutter too. */\n :host(:not([has-side-nav])) .content-section {\n padding-inline-start: var(--nile-app-shell-gutter);\n }\n\n .container {\n box-sizing: border-box;\n /* The floor is the flex basis, not a min-width, so the container yields instead of overflowing the clipped row. */\n flex: 1 1 var(--nile-app-shell-content-min-width);\n display: flex;\n flex-direction: column;\n min-width: 0;\n overflow: hidden;\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-app-shell-radius);\n box-shadow: var(--nile-box-shadow-none, var(--ng-shadow-none));\n /* The container, not the viewport, is the sizing context for page content. */\n container-type: inline-size;\n container-name: nile-content;\n }\n\n /* content-container moves the size query context onto the slotted page root so page CSS can query nile-content; opt-in as it brings containment. */\n :host([content-container]) slot:not([name])::slotted(*) {\n container-type: inline-size;\n container-name: nile-content;\n }\n\n :host([flat]) .container {\n background: transparent;\n border-color: transparent;\n border-radius: 0;\n }\n\n /* ---------------------------------------------------------------- top bar */\n\n .top-bar {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n height: var(--nile-app-shell-top-bar-height);\n padding-inline: var(--nile-app-shell-content-padding);\n }\n\n /* The header bar draws no bottom rule in any variant; the only divider comes from the tab rail (see .tabs). */\n\n .shell-top-bar {\n grid-area: top-bar;\n min-width: 0;\n padding-inline: var(--nile-spacing-xl, var(--ng-spacing-xl));\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n /* No slotted bar content and no nav toggle means no bar at all. */\n :host(:not([has-top-bar])) .top-bar {\n display: none;\n }\n\n .top-bar-content {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n min-width: 0;\n flex: 1 1 auto;\n }\n\n /* The title block: the back arrow, then the stack (app icon, heading and badge, with the description under them); renders before the top-bar slot. */\n .title-area {\n display: flex;\n /* Top-aligned, not centred: the back arrow belongs to the title's row, not the title-plus-description stack. */\n align-items: flex-start;\n /* Figma's Title Area gap: 16px from the arrow to the stack. */\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n min-width: 0;\n }\n\n /* The back arrow's line box: exactly the page title's line height, centring the arrow on the title row. */\n .back-line {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n min-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n }\n\n .title-stack {\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: var(--nile-spacing-xxs, var(--ng-spacing-xxs));\n min-width: 0;\n }\n\n .title-row {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n .page-title {\n margin: 0;\n min-width: 0;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-md));\n line-height: var(--nile-line-height-medium, var(--ng-line-height-text-md));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-semibold));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .description {\n margin: 0;\n min-width: 0;\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));\n line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));\n font-weight: var(--nile-font-weight-regular, var(--ng-font-weight-regular));\n color: var(--nile-colors-dark-500, var(--ng-colors-text-quaternary-500));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n /* The badge sits on the title row and never shrinks the title away; each surface token pairs a Nile name with its NxtGen equivalent. */\n .badge {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n padding-inline: var(--nile-spacing-md, var(--ng-spacing-md));\n padding-block: var(--nile-spacing-xxs, var(--ng-spacing-xxs));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(\n --nile-colors-neutral-400,\n var(--ng-componentcolors-utility-gray-200)\n );\n border-radius: var(--nile-radius-full, var(--ng-radius-full));\n background: var(\n --nile-colors-neutral-100,\n var(--ng-componentcolors-utility-gray-50)\n );\n color: var(\n --nile-colors-dark-500,\n var(--ng-componentcolors-utility-gray-700)\n );\n font-family: var(--nile-font-family-serif, var(--ng-font-family-body));\n font-size: var(--nile-type-scale-1, var(--ng-font-size-text-xs));\n line-height: var(--nile-line-height-xsmall, var(--ng-line-height-text-xs));\n font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-medium));\n white-space: nowrap;\n }\n\n /* headerBack: an icon-only native button, so the aria-label names it directly; the shell owns no history, so pressing it only emits nile-click { value: 'back' }. */\n .back {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n margin: 0;\n padding: 0;\n border: 0;\n background: none;\n cursor: pointer;\n color: var(--nile-colors-dark-500, var(--ng-colors-fg-quaternary-400));\n }\n\n .back:hover {\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n }\n\n /* App icon: a 20px block at the start of the title row, so the description lines up under it; shown whenever the app-icon slot has content. */\n .app-icon {\n position: relative;\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--nile-app-shell-app-icon-size);\n height: var(--nile-app-shell-app-icon-size);\n border-radius: var(--nile-radius-sm, var(--ng-radius-sm));\n overflow: hidden;\n }\n\n /* The slotted mark fills the wrapper edge to edge, clipped to the box. */\n .app-icon slot::slotted(*) {\n width: 100%;\n height: 100%;\n display: block;\n object-fit: cover;\n }\n\n /* The wrapper takes no fill; the rim is a white-12% gradient drawn as a masked ::before, with literal mask fallbacks for the nxtgen-only tokens. */\n .app-icon::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n z-index: 1;\n background: linear-gradient(\n 180deg,\n rgb(255 255 255 / 12%) 0%,\n rgb(255 255 255 / 0%) 100%\n );\n mask: var(\n --ng-mask-rim,\n linear-gradient(#000 0 0) content-box,\n linear-gradient(#000 0 0)\n );\n mask-composite: var(--ng-mask-composite-exclude, exclude);\n padding: 1.4px;\n }\n\n :host(:not([has-app-icon])) .app-icon {\n display: none;\n }\n\n /* Figma's Header Bar gap: 16px between every header action, the divider and Ask. */\n .top-bar-actions {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n margin-inline-start: auto;\n }\n\n /* Hidden when empty, so an empty group's gap does not pull the bar's content short of the padding edge. */\n :host(:not([has-top-bar-actions]):not([has-ask])) .top-bar-actions {\n display: none;\n }\n\n /* The Ask button: a stock <nile-button variant=\"secondary\"> the shell renders itself; the only rule here is its flex behaviour as a top-bar item. */\n .ask {\n flex: 0 0 auto;\n }\n\n .ask-mark {\n display: inline-flex;\n align-items: center;\n }\n\n .ask-mark nile-glyph {\n --nile-svg-fill: currentColor;\n --nile-svg-stroke-width: var(--ng-svg-stroke-width);\n width: 16px;\n height: 16px;\n }\n\n /* 10px after the 32px circle is 16px after the 20px glyph (6px overhang + 10), Figma's toggle-to-divider gap. */\n .nav-toggle-group {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md-alt, var(--ng-spacing-md-alt));\n }\n\n /* Lands the 20px glyph box, not the 32px utility circle, on the 24px origin: (32 - 20) / 2 = 6. */\n .nav-toggle {\n margin-inline-start: -6px;\n }\n\n /* Figma's Divider Line: a 16px 1px stroke that takes no layout width, so the items on both sides sit a clean 16px from it. Used after the nav toggle and, as ask-rule, before Ask. */\n .rule {\n flex: 0 0 auto;\n width: var(--nile-border-width-1, var(--ng-border-width-1));\n margin-inline-end: calc(-1 * var(--nile-border-width-1, var(--ng-border-width-1)));\n height: 16px;\n background: var(\n --nile-colors-neutral-400,\n var(--ng-colors-border-secondary)\n );\n }\n\n /* ------------------------------------------------------- utility controls */\n\n /* The shell's own icon controls (nav toggle, panel back and close): the shared utility-control recipe. */\n ${utilityControlStyles}\n\n /* --------------------------------------------------------------- tab strip */\n\n /* Hoisted out of the scroller so it never scrolls away; sits flush under the top bar and carries the header block's single bottom rule. */\n .tabs {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: stretch;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n min-width: 0;\n /* A floor, not a fixed box: the strip is as tall as the row it holds plus its rule. */\n min-height: var(--nile-app-shell-tabs-height);\n padding-inline: var(--nile-app-shell-content-padding);\n /* The strip carries the rule for the whole header block. */\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n /* The header tab's 0/4/12/4 padding composes the 32px row; the 12px bottom gives the active indicator its band, set via the group's public padding hook. */\n ::slotted([slot='tabs']) {\n --nile-nav-tab-padding: var(--nile-spacing-none, var(--ng-spacing-none))\n var(--nile-spacing-xs, var(--ng-spacing-xs))\n var(--nile-spacing-lg, var(--ng-spacing-lg))\n var(--nile-spacing-xs, var(--ng-spacing-xs));\n }\n\n .tabs::-webkit-scrollbar {\n display: none;\n }\n\n :host(:not([has-tabs])) .tabs,\n :host([notabs]) .tabs {\n display: none;\n }\n\n /* A slotted nile-nav-tab-group drops its own track (--track-width:0 on the host) and is bottom-aligned so its indicator sits on the region's single rule. */\n /* Scoped to the group, not the slot, so bare tab controls are not stretched to an equal share of the strip. */\n ::slotted(nile-nav-tab-group[slot='tabs']) {\n --track-width: 0px;\n /*\n * The active indicator (Figma: fg-brand-primary-alt) is NOT set here: the top placement hard-codes\n * var(--nile-colors-primary-600, var(--ng-colors-text-brand-secondary-700)) inside nile-nav-tab-group's shadow tree, and\n * remapping either token from here would also recolour nile-nav-tab's focus ring and focus label. Known limitation (spec A-7).\n */\n /*\n * The inactive label: nile-nav-tab paints it var(--nile-colors-dark-500, var(--ng-colors-text-secondary-700)), so the strip\n * points the NxtGen fallback at text-quaternary-500. Enterprise defines --nile-colors-dark-500 and is untouched. Inside an\n * underline group nothing else reads text-secondary-700 (only the group's other variants and side placements do).\n */\n --ng-colors-text-secondary-700: var(--ng-colors-text-quaternary-500);\n flex: 1 1 auto;\n min-width: 0;\n align-self: flex-end;\n }\n\n /* ------------------------------------------------------------------- main */\n\n .main {\n box-sizing: border-box;\n flex: 1 1 auto;\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: auto;\n /* Top and sides only: the page runs to the container's bottom edge. */\n padding: var(--nile-app-shell-content-padding);\n padding-block-end: 0;\n }\n\n .main:focus {\n outline: none;\n }\n\n :host([no-padding]) .main {\n padding: 0;\n }\n\n .main-inner {\n width: 100%;\n min-height: 0;\n }\n\n /* Centred when short, scrolls from the top when tall. */\n :host([content-align='centered']) .main-inner {\n /* width:100% + max-width leaves space for the auto margins to centre it while short, and scroll from the top when tall. */\n width: 100%;\n max-width: var(--nile-app-shell-centered-width);\n margin: auto;\n }\n\n /* ------------------------------------------------------------------ aside */\n\n .aside {\n box-sizing: border-box;\n /* Gives before the page does, down to its own floor. */\n flex: 0 1 var(--nile-app-shell-aside-width);\n min-width: var(--nile-app-shell-aside-min-width);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: auto;\n padding: var(--nile-app-shell-content-padding);\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n border-radius: var(--nile-app-shell-radius);\n }\n\n :host(:not([has-aside])) .aside {\n display: none;\n }\n\n /* -------------------------------------------------------------- AI panel */\n\n .panel {\n box-sizing: border-box;\n /* The panel pushes the page rather than covering it: full width while the row affords it, shrinking to a real min-width floor. */\n flex: 0 1 var(--nile-app-shell-panel-width);\n width: var(--nile-app-shell-panel-width);\n min-width: var(--nile-app-shell-panel-min-width);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n background: var(--nile-colors-white-base, var(--ng-colors-bg-secondary));\n /* The panel is elevated, so its edge sits a rung above the container's. */\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-app-shell-radius);\n box-shadow: var(--nile-box-shadow-2, var(--ng-shadow-lg));\n }\n\n /* Docked: a flex sibling. It squeezes the content, it does not cover it. */\n :host(:not([panel-open])) .panel {\n display: none;\n }\n\n /* Overlay: contained to the content column, above it, and animated in. */\n :host([panel-mode='overlay']) .panel {\n position: absolute;\n z-index: 1001;\n inset-block: var(--nile-app-shell-gutter);\n inset-inline-end: var(--nile-app-shell-gutter);\n flex: none;\n display: flex;\n width: min(var(--nile-app-shell-panel-width), 92%);\n visibility: hidden;\n transform: translateX(calc(100% + var(--nile-app-shell-gutter)));\n transition: transform var(--nile-app-shell-duration)\n var(--nile-app-shell-ease),\n visibility 0s linear var(--nile-app-shell-duration);\n }\n\n :host([panel-mode='overlay'][panel-open]) .panel {\n visibility: visible;\n transform: none;\n transition: transform var(--nile-app-shell-duration)\n var(--nile-app-shell-ease);\n }\n\n /* An unavailable panel is unmounted in either mode. */\n :host(:not([has-panel])) .panel {\n display: none;\n }\n\n .panel-header {\n box-sizing: border-box;\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n height: var(--nile-app-shell-panel-header-height);\n padding-inline: var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n border-bottom: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n /* The back control for a panel sub-view; stands where the brand mark does in the root view. */\n .panel-back {\n flex: 0 0 auto;\n margin-inline-start: -6px;\n }\n\n /* Mirrors the back control's offset on the end edge: the 20px glyph, not the 32px circle, lands on the padding line. */\n .panel-close {\n margin-inline-end: -6px;\n }\n\n :host([panelback]) .panel-mark {\n display: none;\n }\n\n .panel-heading {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-md, var(--ng-spacing-md));\n min-width: 0;\n }\n\n .panel-mark {\n display: inline-flex;\n color: var(\n --nile-colors-primary-600,\n var(--ng-colors-fg-brand-primary-600)\n );\n }\n\n .panel-mark nile-glyph {\n --nile-svg-fill: currentColor;\n --nile-svg-stroke-width: var(--ng-svg-stroke-width);\n width: 20px;\n height: 20px;\n }\n\n .panel-title {\n margin: 0;\n /* Figma's Assistant Title: Text lg/Semibold, 18/28 on NxtGen. Enterprise keeps --nile-type-scale-3, and it defines no --ng-* tokens, so the line-height declaration is invalid there and the title inherits its line height exactly as before. */\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-lg));\n line-height: var(--ng-line-height-text-lg);\n font-weight: var(\n --nile-font-weight-semi-bold,\n var(--ng-font-weight-semibold)\n );\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .panel-actions {\n display: flex;\n align-items: center;\n gap: var(--nile-spacing-xs, var(--ng-spacing-xs));\n margin-inline-start: auto;\n }\n\n .panel-body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n /* 16 under the header, 24 on the sides and bottom. */\n padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n display: flex;\n flex-direction: column;\n gap: var(--nile-spacing-xl, var(--ng-spacing-xl));\n }\n\n .panel-footer {\n flex: 0 0 auto;\n padding: var(--nile-spacing-xl, var(--ng-spacing-xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl)) var(--nile-spacing-3xl, var(--ng-spacing-3xl));\n border-top: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));\n }\n\n :host(:not([has-panel-footer])) .panel-footer {\n display: none;\n }\n\n /* ---------------------------------------------------------- skip link */\n\n .skip-link {\n position: absolute;\n z-index: 1002;\n inset-inline-start: var(--nile-spacing-md, var(--ng-spacing-md));\n inset-block-start: var(--nile-spacing-md, var(--ng-spacing-md));\n display: inline-flex;\n align-items: center;\n padding: var(--nile-spacing-md, var(--ng-spacing-md))\n var(--nile-spacing-lg, var(--ng-spacing-lg));\n border: var(--nile-border-width-1, var(--ng-border-width-1)) solid\n var(--nile-colors-neutral-500, var(--ng-colors-border-primary));\n border-radius: var(--nile-radius-md, var(--ng-radius-md));\n background: var(--nile-colors-white-base, var(--ng-colors-bg-primary));\n color: var(--nile-colors-dark-900, var(--ng-colors-text-primary-900));\n font: inherit;\n font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm));\n box-shadow: var(--nile-box-shadow-2, var(--ng-shadow-lg));\n cursor: pointer;\n transform: translateY(-200%);\n transition: transform\n var(--nile-transition-duration-short, var(--ng-transition-duration-fast))\n var(--nile-app-shell-ease);\n }\n\n .skip-link:focus-visible {\n outline: none;\n transform: none;\n box-shadow: 0 0 0 2px\n var(--nile-colors-neutral-100, var(--ng-colors-bg-tertiary)),\n 0 0 0 4px\n var(--nile-colors-primary-600, var(--ng-colors-fg-brand-primary-600));\n }\n\n :host([no-skip-link]) .skip-link {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host,\n .panel,\n .skip-link {\n transition: none;\n }\n }\n`;\n\nexport default [styles];\n"],"names":["styles","css","_templateObject","_taggedTemplateLiteral","utilityControlStyles"],"mappings":"kdAWaA,EAASC,CAAG,CAAAC,eAAA,GAAAA,eAAA,CAAAC,sBAAA,28yBA0arBC,CAAAA"}
|