{"version":3,"sources":["../src/styles.ts","../src/webStyle.ts","../src/CommandPaletteTrigger.tsx","../src/sidebarFilter.ts","../src/isRouteActive.ts","../src/useReducedMotion.ts","../src/SidebarChevron.tsx","../src/NavExpandableItem.tsx","../src/searchAffordance.ts","../src/SidebarSearch.tsx","../src/textSlot.tsx","../src/Sidebar.tsx","../src/constants.ts","../src/FocusableTouchable.tsx","../src/Topbar.tsx","../src/NavBarLink.tsx","../src/NavOverflowMenu.tsx","../src/computeVisibleCount.ts","../src/useNavOverflow.ts","../src/stackedMenuMaxHeight.ts","../src/NavBar.tsx","../src/Nav.tsx","../src/appShellContent.tsx","../src/MobileDrawer.tsx","../src/railMode.ts","../src/useContentMaxWidth.ts","../src/AppShell.tsx","../src/CollapsedRail.tsx","../src/NavShell.tsx","../src/PillNav.tsx","../src/DarkModeControl.tsx","../src/commandPaletteFilter.ts","../src/CommandPalette.tsx","../src/useCommandPaletteHotkey.ts","../src/roleNav.ts"],"names":["StyleSheet","jsx","Text","View","useState","useUi","jsxs","Pressable","styles","React","useCallback","TEXT_ON_PRIMARY","ariaCurrentProps","useMemo","useEffect","useWindowDimensions","MENU_GLYPH","LAYOUT_COLLAPSE_BREAKPOINT","ScrollView","ActivityIndicator","SCRIM_COLOR","Z_INDEX","useRef","TextInput"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Layout styles for the nav shell — ported verbatim (dimensions unchanged) from\n * erevna-web / katalogos-web `theme/utils/layoutSidebar.ts` + `layoutTopbar.ts`,\n * so a migrated app's sidebar/topbar keep the exact same metrics. Colours are\n * NOT baked in here; they are applied at render time from the UiProvider theme.\n */\nimport { StyleSheet } from 'react-native';\n\n/**\n * Mobile hit-box floor (px) for every interactive box: 44x44 per\n * BaseClient/docs/code-standards/mobile-first.md. On RN-web `hitSlop` is inert, so\n * the RENDERED box is the target — size the pressable itself, never pad the glyph.\n */\nexport const MIN_TOUCH_TARGET = 44;\n\nexport const ACTIVE_BORDER_RADIUS = 4;\n/** Width (px) of the active-leaf left accent bar (reserved on every leaf). */\nexport const ACTIVE_ACCENT_WIDTH = 3;\n/** Corner radius (px) of a sidebar row's hover/active pill — the docs-rail softness. */\nexport const NAV_ROW_RADIUS = 8;\n/**\n * Opacity of the primary-tinted overlay behind the ACTIVE sidebar leaf — a soft\n * brand pill (the aml-screening docs `.active` fill, flattened from its gradient).\n */\nexport const ACTIVE_TINT_OPACITY = 0.14;\n/** Opacity of the same overlay on HOVER — the subtle docs-rail hover wash. */\nexport const HOVER_TINT_OPACITY = 0.06;\n\n/**\n * Resolve a sidebar row's primary-tint overlay opacity from its state — the pure\n * rule the {@link NavExpandableItem} `TintOverlay` renders. ACTIVE wins over hover\n * (a stronger brand pill), hover is the subtle wash, and an idle unselected row is\n * fully transparent. Extracted so the hover/active branch is unit-testable without\n * a browser (the render wiring — that RN-web `Pressable` actually drives `hovered`\n * — is covered separately). Group headers are never \"active\" here, so they call it\n * as `rowTintOpacity(false, hovered)`.\n */\nexport function rowTintOpacity(isActive: boolean, hovered: boolean): number {\n  if (isActive) return ACTIVE_TINT_OPACITY;\n  return hovered ? HOVER_TINT_OPACITY : 0;\n}\n\n/**\n * Horizontal gap (px) between adjacent inline items in the `NavBar` links row.\n * Single source of truth: it is both the row's `columnGap` AND the gap the\n * priority+ overflow fit ({@link computeVisibleCount}) reasons about, so the two\n * can never drift apart.\n */\nexport const NAV_LINK_GAP = 4;\n\nexport const navStyles = StyleSheet.create({\n  // --- Sidebar ---\n  sidebarContainer: {\n    width: 220,\n    paddingTop: 24,\n    paddingHorizontal: 12,\n    borderRightWidth: 1,\n    height: '100%',\n  },\n  sidebarTitle: {\n    fontWeight: '700',\n    marginBottom: 12,\n  },\n  sidebarItem: {\n    paddingVertical: 10,\n    paddingHorizontal: 6,\n    borderRadius: 4,\n  },\n  sidebarItemText: {\n    fontSize: 16,\n  },\n  sidebarSpacer: {\n    flex: 1,\n  },\n  // Bottom rhythm under the ⌘K palette trigger (the narrow-viewport search\n  // affordance), matching the inline field's own `marginBottom` so swapping\n  // affordances by width keeps the same gap above the nav list.\n  sidebarTriggerSlot: {\n    marginBottom: 12,\n  },\n  // Inline-search no-match text — sits where the nav list would, muted + padded.\n  sidebarEmpty: {\n    fontSize: 13,\n    paddingVertical: 10,\n    paddingHorizontal: 12,\n  },\n\n  // --- Topbar ---\n  topbarContainer: {\n    height: 64,\n    paddingHorizontal: 12,\n    borderBottomWidth: 1,\n    flexDirection: 'row',\n    alignItems: 'center',\n    justifyContent: 'space-between',\n  },\n  topbarLeft: { flex: 1 },\n  topbarRight: { flexDirection: 'row', alignItems: 'center' },\n  topbarRowItem: {\n    marginHorizontal: 8,\n    alignItems: 'center',\n    justifyContent: 'center',\n    minHeight: MIN_TOUCH_TARGET,\n    minWidth: MIN_TOUCH_TARGET,\n  },\n  topbarLabel: { fontSize: 14 },\n  userBlock: { marginHorizontal: 12, alignItems: 'flex-end' },\n  userName: { fontWeight: '600' },\n  accountNameBtn: {\n    minHeight: MIN_TOUCH_TARGET,\n    minWidth: MIN_TOUCH_TARGET,\n    justifyContent: 'center',\n    alignItems: 'flex-end',\n  },\n  userEmail: { fontSize: 12 },\n  accountBtn: {\n    marginLeft: 8,\n    paddingHorizontal: 10,\n    paddingVertical: 6,\n    borderRadius: 4,\n    minHeight: MIN_TOUCH_TARGET,\n    minWidth: MIN_TOUCH_TARGET,\n    justifyContent: 'center',\n  },\n  accountText: { fontWeight: '600' },\n  // --- Rich account-state header (Move 1c) ---\n  accountTenant: { fontSize: 12 },\n  planBadge: { marginTop: 2, paddingHorizontal: 8, paddingVertical: 2, borderRadius: 10, alignSelf: 'flex-end' },\n  planBadgeText: { fontSize: 11, fontWeight: '700' },\n});\n\nexport const navBarStyles = StyleSheet.create({\n  // --- Horizontal top NavBar ---\n  container: {\n    borderBottomWidth: 1,\n    paddingHorizontal: 12,\n  },\n  inner: {\n    minHeight: 56,\n    flexDirection: 'row',\n    alignItems: 'center',\n    flexWrap: 'wrap',\n    columnGap: 8,\n    rowGap: 4,\n    paddingVertical: 8,\n  },\n  // EXPANDED: the row must NOT wrap — otherwise flexbox drops the right slot onto a 2nd line the\n  // moment brand+links+right overflow, instead of SHRINKING the (scrollable) links. `flex-shrink`\n  // only distributes negative space on a `nowrap` line; with `wrap` it wraps first and never shrinks.\n  // Collapsed keeps `wrap` so the stacked links/right (width:100%) can drop to their own lines.\n  innerNoWrap: {\n    flexWrap: 'nowrap',\n  },\n  brand: { marginRight: 16, flexShrink: 0 },\n  toggle: {\n    marginLeft: 'auto',\n    paddingHorizontal: 10,\n    paddingVertical: 6,\n    borderRadius: 4,\n    // a11y: keep the hamburger a comfortable ≥44×44 touch target.\n    minWidth: MIN_TOUCH_TARGET,\n    minHeight: MIN_TOUCH_TARGET,\n    alignItems: 'center',\n    justifyContent: 'center',\n  },\n  toggleGlyph: { fontSize: 20, fontWeight: '700' },\n  // Expanded links live on ONE ROW that never wraps: it is a shrinkable/growable flex child that\n  // fills the space between the pinned brand (left) and right slot, and CLIPS overflow. A measure\n  // pass (priority+) then keeps only the leading items that fit inline and collapses the rest behind\n  // the \"More ▾\" overflow trigger — so no item is ever cut off; the surplus moves into a dropdown.\n  // `overflow:'hidden'` only masks the single unmeasured first frame before the fit resolves.\n  linksRow: {\n    flexGrow: 1,\n    flexShrink: 1,\n    minWidth: 0,\n    flexDirection: 'row',\n    alignItems: 'center',\n    flexWrap: 'nowrap',\n    columnGap: NAV_LINK_GAP,\n    overflow: 'hidden',\n  },\n  // Each inline link + the overflow trigger sit in a natural-width cell that never shrinks, so their\n  // measured widths are their true content widths (what the priority+ fit computation reasons about).\n  linkCell: { flexShrink: 0 },\n  overflowTrigger: { columnGap: 4 },\n  overflowChevron: { fontSize: 12, fontWeight: '700' },\n  // Collapsed (below breakpoint): links drop onto their own full-width line,\n  // stacked vertically — mirrors the v1 `.gn-links` responsive behaviour.\n  // SHOWCASE-1: this is a ScrollView — `maxHeight` (viewport minus bar) is applied at render time,\n  // so a long menu scrolls within the viewport instead of running off a body:overflow:hidden page.\n  linksStacked: {\n    width: '100%',\n    flexBasis: '100%',\n    flexGrow: 0,\n    flexShrink: 0,\n    marginTop: 8,\n  },\n  linksStackedContent: {\n    flexDirection: 'column',\n    alignItems: 'stretch',\n    rowGap: 2,\n  },\n  link: {\n    paddingVertical: 8,\n    paddingHorizontal: 14,\n    borderRadius: 8,\n    flexDirection: 'row',\n    alignItems: 'center',\n    // a11y: comfortable ≥44 tall touch target (rounded-pill hover/active affordance).\n    minHeight: MIN_TOUCH_TARGET,\n    justifyContent: 'center',\n  },\n  linkStacked: { paddingVertical: 10 },\n  linkIcon: { marginRight: 6 },\n  linkText: { fontSize: 15, fontWeight: '600' },\n  right: {\n    marginLeft: 'auto',\n    flexShrink: 0,\n    flexDirection: 'row',\n    alignItems: 'center',\n    columnGap: 8,\n  },\n  rightStacked: {\n    width: '100%',\n    flexBasis: '100%',\n    marginTop: 4,\n    flexDirection: 'row',\n    alignItems: 'center',\n    columnGap: 8,\n  },\n});\n\nexport const pillNavStyles = StyleSheet.create({\n  // Cross-nav pill row (kefi coral dashboard switcher): fully-rounded pills, wraps.\n  container: {\n    flexDirection: 'row',\n    flexWrap: 'wrap',\n    alignItems: 'center',\n    columnGap: 8,\n    rowGap: 8,\n    paddingVertical: 8,\n  },\n  pill: {\n    paddingHorizontal: 16,\n    paddingVertical: 8,\n    borderRadius: 999,\n    minHeight: MIN_TOUCH_TARGET,\n    flexDirection: 'row',\n    alignItems: 'center',\n    columnGap: 6,\n    justifyContent: 'center',\n  },\n  pillText: { fontSize: 14, fontWeight: '600' },\n});\n\nexport const darkModeStyles = StyleSheet.create({\n  // Segmented Light / Dark / System control.\n  segmentRow: {\n    flexDirection: 'row',\n    alignItems: 'center',\n    borderWidth: 1,\n    borderRadius: 8,\n    overflow: 'hidden',\n    alignSelf: 'flex-start',\n  },\n  segment: {\n    paddingHorizontal: 12,\n    paddingVertical: 8,\n    minHeight: MIN_TOUCH_TARGET,\n    minWidth: MIN_TOUCH_TARGET,\n    flexDirection: 'row',\n    alignItems: 'center',\n    columnGap: 6,\n    justifyContent: 'center',\n  },\n  segmentText: { fontSize: 13, fontWeight: '600' },\n  // Cycle-button variant.\n  cycle: {\n    paddingHorizontal: 12,\n    paddingVertical: 8,\n    minHeight: MIN_TOUCH_TARGET,\n    minWidth: MIN_TOUCH_TARGET,\n    borderRadius: 8,\n    flexDirection: 'row',\n    alignItems: 'center',\n    columnGap: 6,\n    justifyContent: 'center',\n  },\n  cycleText: { fontSize: 13, fontWeight: '600' },\n});\n\nexport const collapsedRailStyles = StyleSheet.create({\n  // Intermediate (tablet) icon-only rail: a narrow vertical strip of icon buttons.\n  container: {\n    width: 64,\n    paddingTop: 16,\n    paddingHorizontal: 8,\n    borderRightWidth: 1,\n    height: '100%',\n    alignItems: 'center',\n  },\n  // Each item is a ≥44×44 centred touch target with a rounded active/hover pill.\n  item: {\n    width: 48,\n    height: 48,\n    marginVertical: 4,\n    borderRadius: 8,\n    alignItems: 'center',\n    justifyContent: 'center',\n  },\n  // Glyph fallback (the label's first character) when an item has no renderIcon.\n  glyph: { fontSize: 18, fontWeight: '700' },\n  spacer: { flex: 1 },\n  slot: { alignItems: 'center' },\n});\n\nexport const expandableStyles = StyleSheet.create({\n  // Every leaf reserves the accent-bar gutter (a TRANSPARENT left border of the\n  // same width the active item colours in) so activation never shifts the row.\n  // `overflow: hidden` clips the rounded {@link tintOverlay} to the row's corners;\n  // `position: relative` anchors that absolutely-filled overlay to the row.\n  childItem: {\n    position: 'relative',\n    overflow: 'hidden',\n    borderRadius: NAV_ROW_RADIUS,\n    flexDirection: 'row',\n    alignItems: 'center',\n    paddingVertical: 9,\n    minHeight: MIN_TOUCH_TARGET,\n    borderLeftWidth: ACTIVE_ACCENT_WIDTH,\n    borderLeftColor: 'transparent',\n  },\n  childItemText: { fontSize: 14 },\n  childItemTextWithIcon: { fontSize: 14, marginLeft: 6 },\n  chevron: { marginLeft: 'auto' },\n  childrenContainer: { overflow: 'hidden', marginBottom: 4 },\n  // The hover/active brand wash: a rounded fill behind the row's icon + label,\n  // its opacity eased between 0 / hover / active. Colour + opacity are applied at\n  // render time (theme primary); this only positions and rounds it.\n  tintOverlay: {\n    position: 'absolute',\n    top: 0,\n    left: 0,\n    right: 0,\n    bottom: 0,\n    borderRadius: NAV_ROW_RADIUS,\n    // `style.pointerEvents` (not the deprecated prop) so the overlay never\n    // intercepts the row's press/hover — RNW forwards this style key to the DOM.\n    pointerEvents: 'none',\n  },\n  header: {\n    position: 'relative',\n    overflow: 'hidden',\n    borderRadius: NAV_ROW_RADIUS,\n    flexDirection: 'row',\n    alignItems: 'center',\n    paddingVertical: 8,\n    minHeight: MIN_TOUCH_TARGET,\n  },\n  // Depth-0 module groups render as docs-style SECTION HEADERS: extra top rhythm\n  // to separate one module from the next.\n  sectionHeader: { marginTop: 12 },\n  headerText: { fontSize: 15, fontWeight: '600', marginLeft: 6 },\n  // The section-label look: small, uppercased, tracked, muted — the aml-screening\n  // docs treatment (\"START HERE\" / \"REFERENCE\"), kept on an interactive toggle.\n  sectionHeaderText: {\n    fontSize: 12,\n    fontWeight: '700',\n    marginLeft: 6,\n    textTransform: 'uppercase',\n    letterSpacing: 0.8,\n  },\n  iconWrapper: { width: 20, alignItems: 'center' },\n});\n\n/** Base indent applied per nesting depth in the expandable item. */\nexport const BASE_INDENT = 12;\n/** Default icon size for nav item icons. */\nexport const NAV_ICON_SIZE = 14;\n/** Chevron icon size for expandable sections. */\nexport const CHEVRON_ICON_SIZE = 12;\n","/**\n * Web-only style helpers for the nav shell. React Native's `ViewStyle` has no\n * `outline*` or `transition*` keys, but react-native-web forwards them to the DOM,\n * so we build them as typed web-style objects and cast ONCE to `ViewStyle` (no\n * `any`). On native these CSS-only props are meaningless — every helper returns\n * `undefined` when `IS_WEB` is false, so nothing is applied off the web.\n */\nimport { Platform, type ViewStyle } from 'react-native';\n\n/** True only under react-native-web. Gates the CSS-only focus ring + hover transition. */\nexport const IS_WEB = Platform.OS === 'web';\n\n/** Keyboard focus-ring width (px). */\nconst FOCUS_RING_WIDTH = 2;\n/** Gap between the ring and the element edge (px) so the ring reads clearly. */\nconst FOCUS_RING_OFFSET = 2;\n/** Hover-pill colour/background cross-fade duration (ms). */\nconst HOVER_TRANSITION_MS = 150;\n/** Sidebar hover/active tint-overlay fade + chevron-rotate duration (ms). */\nconst TINT_TRANSITION_MS = 160;\n\n/** DOM `outline-*` shape — not part of RN `ViewStyle`, but honoured by react-native-web. */\ninterface WebOutlineStyle {\n  outlineWidth: number;\n  outlineStyle: 'solid';\n  outlineColor: string;\n  outlineOffset: number;\n}\n\n/** DOM `transition-*` shape — not part of RN `ViewStyle`, but honoured by react-native-web. */\ninterface WebTransitionStyle {\n  transitionProperty: string;\n  transitionDuration: string;\n}\n\n/**\n * A visible keyboard-focus ring in the theme accent colour. Returns `undefined`\n * on native, and when the element is not focused, so nothing is applied. Never\n * removes the outline without a replacement — it ADDS a themed ring on focus.\n */\nexport function focusRingStyle(focused: boolean, ringColor: string): ViewStyle | undefined {\n  if (!IS_WEB || !focused) return undefined;\n  const ring: WebOutlineStyle = {\n    outlineWidth: FOCUS_RING_WIDTH,\n    outlineStyle: 'solid',\n    outlineColor: ringColor,\n    outlineOffset: FOCUS_RING_OFFSET,\n  };\n  return ring as unknown as ViewStyle;\n}\n\n/** Build a typed web transition, disabled (`0ms`) under reduced motion, web-only. */\nfunction webTransition(properties: string, durationMs: number, reducedMotion: boolean): ViewStyle | undefined {\n  if (!IS_WEB) return undefined;\n  const transition: WebTransitionStyle = {\n    transitionProperty: properties,\n    transitionDuration: reducedMotion ? '0ms' : `${durationMs}ms`,\n  };\n  return transition as unknown as ViewStyle;\n}\n\n/**\n * A cheap CSS cross-fade for the hover-pill colour/background. Disabled (`0ms`)\n * when the user prefers reduced motion, and omitted entirely on native. No JS\n * animation — the transition is pure CSS applied by react-native-web.\n */\nexport function hoverTransitionStyle(reducedMotion: boolean): ViewStyle | undefined {\n  return webTransition('color, background-color', HOVER_TRANSITION_MS, reducedMotion);\n}\n\n/**\n * CSS opacity fade for the sidebar item's primary-tinted hover/active overlay —\n * the tint eases in/out instead of snapping. Reduced-motion snaps (`0ms`); native\n * omits it (the overlay still shows, just without the fade).\n */\nexport function tintTransitionStyle(reducedMotion: boolean): ViewStyle | undefined {\n  return webTransition('opacity', TINT_TRANSITION_MS, reducedMotion);\n}\n\n/**\n * CSS transform transition for the expand/collapse chevron so it ROTATES smoothly\n * between its collapsed and expanded angle. Reduced-motion snaps (`0ms`); native\n * omits it (the chevron still flips to the correct angle, just without the tween).\n */\nexport function rotateTransitionStyle(reducedMotion: boolean): ViewStyle | undefined {\n  return webTransition('transform', TINT_TRANSITION_MS, reducedMotion);\n}\n","/**\n * CommandPaletteTrigger — the VISIBLE, discoverable affordance that opens the\n * {@link CommandPalette}. A ⌘K shortcut alone is invisible; a docs-style search\n * pill (muted placeholder on the left, a keyboard-shortcut badge on the right)\n * tells operators the palette exists and is one click away. Place it in a shell\n * header / sidebar; wire `onPress` to the same open handler as the ⌘K hotkey.\n *\n * Self-contained on purpose: the shared icon set has no magnifier, so this uses\n * text + a shortcut badge (the recognizable \"Search … ⌘K\" pattern) rather than a\n * render-slot icon — one less thing every consumer must supply. Colours come from\n * the `@dloizides/ui-feedback` UiProvider theme; the label/shortcut are\n * pre-localized strings (package discipline: no FM/router imports).\n */\nimport React from 'react';\n\nimport { Pressable, StyleSheet, Text, View } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { MIN_TOUCH_TARGET } from './styles';\nimport { focusRingStyle } from './webStyle';\n\nexport interface CommandPaletteTriggerProps {\n  /** Placeholder-style label, e.g. \"Search\". */\n  label: string;\n  /** a11y hint describing what activating it does. */\n  hint: string;\n  /** The shortcut badge text, e.g. \"⌘K\" (already chosen per-platform by the caller). */\n  shortcut: string;\n  /** Open the palette (same handler as the ⌘K hotkey). */\n  onPress: () => void;\n  /** testID for the trigger. */\n  testID: string;\n}\n\nconst styles = StyleSheet.create({\n  trigger: {\n    flexDirection: 'row',\n    alignItems: 'center',\n    justifyContent: 'space-between',\n    columnGap: 8,\n    paddingHorizontal: 12,\n    minHeight: MIN_TOUCH_TARGET,\n    borderWidth: 1,\n    borderRadius: 8,\n  },\n  label: { fontSize: 14 },\n  badge: { paddingHorizontal: 6, paddingVertical: 2, borderRadius: 4, borderWidth: 1 },\n  badgeText: { fontSize: 11, fontWeight: '700' },\n});\n\n/** The visible \"Search … ⌘K\" pill that opens the command palette. */\nexport const CommandPaletteTrigger = ({\n  label,\n  hint,\n  shortcut,\n  onPress,\n  testID,\n}: CommandPaletteTriggerProps): React.ReactElement => {\n  const { theme } = useUi();\n  const colors = theme.colors;\n  const primary = theme.palette.primary['500'];\n  const [focused, setFocused] = React.useState(false);\n  return (\n    <Pressable\n      accessibilityHint={hint}\n      accessibilityLabel={label}\n      accessibilityRole=\"button\"\n      style={[\n        styles.trigger,\n        { backgroundColor: colors.surface, borderColor: colors.border },\n        focusRingStyle(focused, primary),\n      ]}\n      testID={testID}\n      onBlur={() => setFocused(false)}\n      onFocus={() => setFocused(true)}\n      onPress={onPress}\n    >\n      <Text style={[styles.label, { color: colors.textSecondary }]}>{label}</Text>\n      <View style={[styles.badge, { borderColor: colors.border }]}>\n        <Text style={[styles.badgeText, { color: colors.textSecondary }]}>{shortcut}</Text>\n      </View>\n    </Pressable>\n  );\n};\n\nexport default CommandPaletteTrigger;\n","/**\n * Pure tree-filter for the desktop inline sidebar search. Kept framework-free so\n * the narrowing is unit-testable without rendering. Given a `NavItem[]` tree and\n * a query, it returns a PRUNED tree: a leaf survives when every whitespace-token\n * of the query appears (case-insensitively) in its label; a group survives when\n * it matches itself (kept with ALL its children, so the whole section stays\n * browsable) OR when any descendant survives (kept with only the surviving\n * descendants, so ancestors of a match are never orphaned). An empty/whitespace\n * query returns the tree unchanged — the sidebar shows everything.\n *\n * Requiring ALL tokens lets an operator narrow with \"pay dash\" the way a fuzzy\n * launcher would, matching the {@link filterCommands} palette semantics so the\n * inline field and the ⌘K palette rank identically.\n */\nimport type { NavItem } from './types';\n\n/** Split a raw query into lower-cased match tokens (empty ⇒ no filtering). */\nexport function searchTokens(query: string): string[] {\n  return query.trim().toLowerCase().split(/\\s+/).filter(Boolean);\n}\n\n/** True when every token appears in the item's (lower-cased) label. */\nfunction labelMatches(item: NavItem, tokens: readonly string[]): boolean {\n  const label = item.label.toLowerCase();\n  return tokens.every((token) => label.includes(token));\n}\n\n/**\n * Prune `items` to those matching `query`. Empty query ⇒ a shallow clone of the\n * input (unchanged). A matching group keeps all its children; a non-matching\n * group is kept only if it has surviving descendants (and then carries only\n * those). Order is preserved.\n */\nexport function filterNavItems(items: readonly NavItem[], query: string): NavItem[] {\n  const tokens = searchTokens(query);\n  if (tokens.length === 0) return [...items];\n  return filterByTokens(items, tokens);\n}\n\nfunction filterByTokens(items: readonly NavItem[], tokens: readonly string[]): NavItem[] {\n  const kept: NavItem[] = [];\n  for (const item of items) {\n    const selfMatch = labelMatches(item, tokens);\n    const children = item.children ?? [];\n    if (selfMatch) {\n      kept.push(item);\n      continue;\n    }\n    if (children.length === 0) continue;\n    const prunedChildren = filterByTokens(children, tokens);\n    if (prunedChildren.length > 0) kept.push({ ...item, children: prunedChildren });\n  }\n  return kept;\n}\n\n/** True when the query is non-empty (filtering is active) — drives the empty state. */\nexport function isFilterActive(query: string): boolean {\n  return searchTokens(query).length > 0;\n}\n","/**\n * Active-route matching for the nav shells.\n *\n * `isRouteActive` is the low-level per-route predicate (prefix-based, ported\n * verbatim from the twin app sidebars): a route is active when the current\n * pathname equals it or is nested under it (`/foo` matches `/foo` and `/foo/bar`,\n * but `/` only matches `/`). With `exact`, only an exact path matches.\n *\n * `resolveActiveRoute` is the CROSS-ITEM resolver that fixes the sidebar\n * co-activation bug: because a module-home leaf (`/accounting`) is a prefix of\n * every sibling (`/accounting/journals`), the naive per-item predicate lights up\n * BOTH on `/accounting/journals`. `resolveActiveRoute` instead returns the ONE\n * most-specific (longest) leaf route that matches — so at most one leaf is ever\n * active, the longest wins on nested paths, and the module-home leaf is active\n * only on its own exact path. For a nav model with no parent/child route overlap\n * (the common case) this is identical to the old behaviour.\n */\nimport type { NavItem } from './types';\n\nexport function isRouteActive(pathname: string, route: string, exact = false): boolean {\n  if (exact) return pathname === route;\n  if (route === '/') return pathname === '/';\n  return pathname === route || pathname.startsWith(`${route}/`);\n}\n\n/** A navigable (leaf) route plus its exact-match flag. */\ninterface LeafRoute {\n  route: string;\n  exact: boolean;\n}\n\n/**\n * Flatten a nav tree to its LEAF routes (items with no children). Group headers\n * navigate nothing — they toggle — so they never participate in active resolution.\n */\nfunction leafRoutes(items: NavItem[]): LeafRoute[] {\n  return items.flatMap((item) => {\n    const children = item.children ?? [];\n    const isGroup = children.length > 0;\n    return isGroup ? leafRoutes(children) : [{ route: item.route, exact: item.exact === true }];\n  });\n}\n\n/**\n * The single active leaf route for `pathname`: the LONGEST leaf route that\n * matches (most-specific wins). Returns `undefined` when no leaf matches. Marking\n * a leaf active iff `item.route === resolveActiveRoute(items, pathname)` guarantees\n * at most one active leaf — the whack-a-mole prefix co-activation fix.\n */\nexport function resolveActiveRoute(items: NavItem[], pathname: string): string | undefined {\n  let winner: string | undefined;\n  let winnerLength = -1;\n  for (const leaf of leafRoutes(items)) {\n    const matches = isRouteActive(pathname, leaf.route, leaf.exact);\n    const isLonger = leaf.route.length > winnerLength;\n    if (matches && isLonger) {\n      winner = leaf.route;\n      winnerLength = leaf.route.length;\n    }\n  }\n  return winner;\n}\n","/**\n * `useReducedMotion` — `true` when the user has asked the OS/browser to minimise\n * motion (`prefers-reduced-motion: reduce`). It is a WEB-only signal read from\n * `window.matchMedia`; on native (no `matchMedia`) it is always `false`. The\n * `NavBar` uses it to drop the hover-pill CSS transition for motion-sensitive\n * users. Cheap: one media-query subscription, no JS animation.\n */\nimport { useEffect, useState } from 'react';\n\nconst REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\n\n/** The slice of `MediaQueryList` we rely on — kept minimal so native builds needn't provide it. */\ninterface MediaQueryListLike {\n  matches: boolean;\n  addEventListener?: (type: 'change', listener: () => void) => void;\n  removeEventListener?: (type: 'change', listener: () => void) => void;\n}\n\n/** Resolve the reduced-motion media query on web; `undefined` where `matchMedia` is unavailable. */\nfunction getReducedMotionQuery(): MediaQueryListLike | undefined {\n  if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return undefined;\n  return window.matchMedia(REDUCED_MOTION_QUERY);\n}\n\nexport function useReducedMotion(): boolean {\n  const [reduced, setReduced] = useState<boolean>(() => getReducedMotionQuery()?.matches ?? false);\n\n  useEffect(() => {\n    const mql = getReducedMotionQuery();\n    if (mql === undefined || mql.addEventListener === undefined) return undefined;\n    const onChange = (): void => setReduced(mql.matches);\n    mql.addEventListener('change', onChange);\n    return () => {\n      mql.removeEventListener?.('change', onChange);\n    };\n  }, []);\n\n  return reduced;\n}\n\nexport default useReducedMotion;\n","/**\n * SidebarChevron — the built-in disclosure caret for an expandable sidebar\n * group. A single \"›\" glyph that ROTATES from pointing-right (collapsed) to\n * pointing-down (expanded); on web the rotation is a smooth CSS transform tween\n * (reduced-motion snaps). Used as the DEFAULT when a `Sidebar`/`NavExpandableItem`\n * caller supplies no `renderChevron`, so grouped rails get an animated caret for\n * free while callers keep the option to render their own icon set.\n *\n * Package discipline: no icon-set import (the glyph is a plain character); the\n * colour is passed in from the theme by the caller.\n */\nimport React from 'react';\n\nimport { Text, type TextStyle } from 'react-native';\n\nimport { rotateTransitionStyle } from './webStyle';\nimport { useReducedMotion } from './useReducedMotion';\n\n/** Glyph rotated 90° between states — a right-pointing caret when collapsed. */\nconst CHEVRON_GLYPH = '›';\nconst EXPANDED_ROTATION = '90deg';\nconst COLLAPSED_ROTATION = '0deg';\n/** Nudge the optical weight so the caret reads at small sizes. */\nconst CHEVRON_FONT_WEIGHT = '700';\n\nexport interface SidebarChevronProps {\n  /** Whether the section is expanded (rotates the caret down). */\n  expanded: boolean;\n  /** Resolved caret colour (from the theme). */\n  color: string;\n  /** Caret font size (px). */\n  size: number;\n}\n\n/** The default animated disclosure caret for expandable sidebar sections. */\nexport const SidebarChevron = ({ expanded, color, size }: SidebarChevronProps): React.ReactElement => {\n  const reducedMotion = useReducedMotion();\n  const style: TextStyle = {\n    color,\n    fontSize: size,\n    fontWeight: CHEVRON_FONT_WEIGHT,\n    transform: [{ rotate: expanded ? EXPANDED_ROTATION : COLLAPSED_ROTATION }],\n  };\n  return (\n    <Text\n      accessibilityElementsHidden\n      importantForAccessibility=\"no\"\n      style={[style, rotateTransitionStyle(reducedMotion)]}\n    >\n      {CHEVRON_GLYPH}\n    </Text>\n  );\n};\n\nexport default SidebarChevron;\n","/**\n * NavExpandableItem — a single sidebar entry that is either a leaf (navigates)\n * or an expandable section (toggles nested children). Ported from the twin\n * erevna/katalogos `Sidebar/NavExpandableItem`, made config-driven: labels are\n * pre-localized strings, icons are render slots, colours come from `useUi`.\n *\n * Docs-sidebar polish (v1.16): each row carries a PRIMARY-TINTED overlay whose\n * opacity eases 0 → hover → active (a smooth ~160ms cross-fade on web, gated by\n * reduced motion), over the transparent left-accent gutter every leaf reserves —\n * so the active leaf reads as a tinted pill with a coloured left bar, and any row\n * lights up subtly on hover, matching the aml-screening docs rail. Expandable\n * groups get a built-in rotating {@link SidebarChevron} when the caller supplies\n * no `renderChevron`.\n */\nimport React, { useCallback, useMemo, useState } from 'react';\n\nimport { Pressable, Text, View, type PressableProps } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\nimport { Collapse } from '@dloizides/ui-motion';\n\nimport {\n  BASE_INDENT,\n  CHEVRON_ICON_SIZE,\n  NAV_ICON_SIZE,\n  ACTIVE_ACCENT_WIDTH,\n  rowTintOpacity,\n  expandableStyles as styles,\n} from './styles';\nimport { isRouteActive } from './isRouteActive';\nimport { SidebarChevron } from './SidebarChevron';\nimport type { NavItem } from './types';\nimport { focusRingStyle, tintTransitionStyle, IS_WEB } from './webStyle';\nimport { useReducedMotion } from './useReducedMotion';\n\n/**\n * `aria-current=\"page\"` marks the active leaf for assistive tech. RN's prop types\n * omit `aria-current`; react-native-web forwards `aria-*` to the DOM — attach it\n * (no `any`) only when the leaf is active.\n */\nfunction ariaCurrentProps(isActive: boolean): PressableProps & { 'aria-current'?: 'page' } {\n  return isActive ? { 'aria-current': 'page' } : {};\n}\n\n/**\n * `aria-expanded` marks an expandable section header as a disclosure control for\n * assistive tech — and, just as importantly, is the DOM signal `MobileDrawer` uses\n * to tell a group TOGGLE apart from a navigating leaf (so expanding a group on\n * mobile no longer dismisses the drawer). RNW forwards `aria-*` props to the DOM\n * but does NOT synthesize `aria-expanded` from `accessibilityState.expanded` in\n * this version, so set it explicitly (same pattern as `aria-current` above).\n */\nfunction ariaExpandedProps(expanded: boolean): PressableProps & { 'aria-expanded'?: boolean } {\n  return { 'aria-expanded': expanded };\n}\n\n/**\n * Web-only pointer hover handlers. These MUST sit on a {@link Pressable}: RN-web's\n * `TouchableOpacity` has no hover support and silently drops `onHoverIn`/`onHoverOut`\n * (the 1.16 hover-wash bug — the wash never appeared). `Pressable` wires them through\n * its `useHover` responder, so the row's `hovered` state actually toggles on the web.\n * `PressableProps` already types both; gate on `IS_WEB` so native attaches nothing.\n */\nfunction hoverHandlerProps(onIn: () => void, onOut: () => void): Pick<PressableProps, 'onHoverIn' | 'onHoverOut'> {\n  return IS_WEB ? { onHoverIn: onIn, onHoverOut: onOut } : {};\n}\n\n/**\n * True when the current route is inside this item — its own route is active, or\n * any descendant's is. Drives the initial expansion so a group that contains the\n * active route opens on mount and its active leaf is visible; a group with no\n * active descendant mounts collapsed (the prior behaviour). Recursive so it holds\n * at any nesting depth.\n */\nfunction hasActiveDescendant(item: NavItem, pathname: string): boolean {\n  if (isRouteActive(pathname, item.route)) return true;\n  return (item.children ?? []).some((child) => hasActiveDescendant(child, pathname));\n}\n\nexport interface NavExpandableItemProps {\n  item: NavItem;\n  pathname: string;\n  onNavigate: (route: string) => void;\n  /**\n   * The single winning active leaf route for the whole nav model, resolved once by\n   * the parent via `resolveActiveRoute` (most-specific/longest match wins). A leaf\n   * is active iff `item.route === activeRoute`, so at most one leaf ever carries\n   * `aria-current=\"page\"` — the fix for `/accounting` co-activating with\n   * `/accounting/journals`. When omitted (standalone use) each leaf falls back to\n   * the per-item prefix predicate, preserving the pre-1.18 behaviour.\n   */\n  activeRoute?: string;\n  /** a11y hint for a leaf item, given its label. */\n  navigateHint: (label: string) => string;\n  /** a11y hint shown when the section is collapsed (press expands). */\n  expandHint: string;\n  /** a11y hint shown when the section is expanded (press collapses). */\n  collapseHint: string;\n  /**\n   * Optional chevron icon renderer for expandable sections. When omitted, a\n   * built-in rotating {@link SidebarChevron} is drawn — so grouped rails animate\n   * their disclosure caret without the caller supplying an icon set.\n   */\n  renderChevron?: (expanded: boolean, color: string, size: number) => React.ReactNode;\n  depth?: number;\n}\n\n/** The primary-tinted hover/active overlay — a rounded fill behind the row content. */\nfunction TintOverlay({\n  opacity,\n  color,\n  testID,\n}: {\n  opacity: number;\n  color: string;\n  testID?: string;\n}): React.ReactElement {\n  const reducedMotion = useReducedMotion();\n  return (\n    <View\n      style={[styles.tintOverlay, { backgroundColor: color, opacity }, tintTransitionStyle(reducedMotion)]}\n      testID={testID}\n    />\n  );\n}\n\nexport const NavExpandableItem = ({\n  item,\n  pathname,\n  onNavigate,\n  navigateHint,\n  expandHint,\n  collapseHint,\n  renderChevron,\n  activeRoute,\n  depth = 0,\n}: NavExpandableItemProps): React.ReactElement => {\n  const [expanded, setExpanded] = useState(() => hasActiveDescendant(item, pathname));\n  const [focused, setFocused] = useState(false);\n  const [hovered, setHovered] = useState(false);\n  const { theme } = useUi();\n  const colors = theme.colors;\n  const primaryColor = theme.palette.primary['500'];\n\n  const toggle = useCallback(() => setExpanded((v) => !v), []);\n  const onHoverIn = useCallback(() => setHovered(true), []);\n  const onHoverOut = useCallback(() => setHovered(false), []);\n\n  const indent = depth * BASE_INDENT;\n  const hasChildren = Array.isArray(item.children) && item.children.length > 0;\n  // Most-specific-wins: when the parent resolved the single winning leaf route,\n  // this leaf is active iff it IS that winner — so `/accounting` no longer lights\n  // up alongside `/accounting/journals`. Standalone use (no `activeRoute`) falls\n  // back to the per-item prefix predicate (honouring `exact`), unchanged from before.\n  const isActive =\n    activeRoute !== undefined\n      ? item.route === activeRoute\n      : isRouteActive(pathname, item.route, item.exact === true);\n  // A top-level expandable group is a docs-style section header (uppercase, muted);\n  // nested groups keep the plain header look.\n  const isSectionHeader = hasChildren && depth === 0;\n\n  // Active leaf: the docs-style strong treatment — a coloured left accent bar\n  // (over the transparent gutter every leaf reserves, so there is no layout\n  // shift). The tinted surface is the separate {@link TintOverlay}, so the accent\n  // colour and the tint both come from the theme primary — each portal's brand.\n  const activeAccentStyle = useMemo(\n    () => ({ borderLeftWidth: ACTIVE_ACCENT_WIDTH, borderLeftColor: primaryColor }),\n    [primaryColor],\n  );\n  const paddingStyle = useMemo(() => ({ paddingLeft: indent + BASE_INDENT }), [indent]);\n  const headerPaddingStyle = useMemo(() => ({ paddingLeft: indent }), [indent]);\n  const leafTintOpacity = rowTintOpacity(isActive, hovered);\n  const headerTintOpacity = rowTintOpacity(false, hovered);\n  const rowTestID = item.testID ?? item.key;\n\n  if (!hasChildren)\n    return (\n      <Pressable\n        accessibilityHint={navigateHint(item.label)}\n        accessibilityLabel={item.label}\n        accessibilityRole=\"button\"\n        accessibilityState={{ selected: isActive }}\n        style={[\n          styles.childItem,\n          paddingStyle,\n          isActive ? activeAccentStyle : undefined,\n          focusRingStyle(focused, primaryColor),\n        ]}\n        testID={rowTestID}\n        onBlur={() => setFocused(false)}\n        onFocus={() => setFocused(true)}\n        onPress={() => onNavigate(item.route)}\n        {...hoverHandlerProps(onHoverIn, onHoverOut)}\n        {...ariaCurrentProps(isActive)}\n      >\n        <TintOverlay color={primaryColor} opacity={leafTintOpacity} testID={`${rowTestID}-tint`} />\n        {typeof item.renderIcon === 'function' ? (\n          <View style={styles.iconWrapper}>{item.renderIcon(colors.textSecondary, NAV_ICON_SIZE)}</View>\n        ) : null}\n        <Text\n          style={[\n            typeof item.renderIcon === 'function' ? styles.childItemTextWithIcon : styles.childItemText,\n            { color: isActive ? primaryColor : colors.text },\n          ]}\n        >\n          {item.label}\n        </Text>\n      </Pressable>\n    );\n\n  const chevronColor = colors.textSecondary;\n\n  return (\n    <View>\n      <Pressable\n        accessibilityHint={expanded ? collapseHint : expandHint}\n        accessibilityLabel={item.label}\n        accessibilityRole=\"button\"\n        accessibilityState={{ expanded }}\n        style={[\n          styles.header,\n          isSectionHeader ? styles.sectionHeader : undefined,\n          headerPaddingStyle,\n          focusRingStyle(focused, primaryColor),\n        ]}\n        testID={rowTestID}\n        onBlur={() => setFocused(false)}\n        onFocus={() => setFocused(true)}\n        onPress={toggle}\n        {...hoverHandlerProps(onHoverIn, onHoverOut)}\n        {...ariaExpandedProps(expanded)}\n      >\n        <TintOverlay color={primaryColor} opacity={headerTintOpacity} testID={`${rowTestID}-tint`} />\n        {typeof item.renderIcon === 'function' ? (\n          <View style={styles.iconWrapper}>\n            {item.renderIcon(isSectionHeader ? colors.textSecondary : colors.text, NAV_ICON_SIZE)}\n          </View>\n        ) : null}\n        <Text\n          style={[\n            isSectionHeader ? styles.sectionHeaderText : styles.headerText,\n            { color: isSectionHeader ? colors.textSecondary : colors.text },\n          ]}\n        >\n          {item.label}\n        </Text>\n        <View style={styles.chevron}>\n          {typeof renderChevron === 'function' ? (\n            renderChevron(expanded, chevronColor, CHEVRON_ICON_SIZE)\n          ) : (\n            <SidebarChevron color={chevronColor} expanded={expanded} size={CHEVRON_ICON_SIZE} />\n          )}\n        </View>\n      </Pressable>\n\n      {/*\n       * Animate the expand/collapse instead of snapping. `Collapse` measures the\n       * children's natural height and animates a real `Animated.Value` height on\n       * web AND native (reduced-motion snaps). Per its contract the children stay\n       * MOUNTED at all times — when collapsed they are clipped to zero height under\n       * `overflow: hidden`, so the group's leaves are neither visible nor tappable\n       * even though they remain in the tree (state + a11y focus order preserved).\n       * The header keeps emitting `aria-expanded` above, so `MobileDrawer` still\n       * tells a group toggle apart from a navigating leaf.\n       */}\n      <Collapse open={expanded}>\n        <View style={styles.childrenContainer}>\n          {item.children?.map((child) => (\n            <NavExpandableItem\n              key={child.key}\n              activeRoute={activeRoute}\n              collapseHint={collapseHint}\n              depth={depth + 1}\n              expandHint={expandHint}\n              item={child}\n              navigateHint={navigateHint}\n              pathname={pathname}\n              renderChevron={renderChevron}\n              onNavigate={onNavigate}\n            />\n          ))}\n        </View>\n      </Collapse>\n    </View>\n  );\n};\n\nexport default NavExpandableItem;\n","/**\n * The desktop-vs-mobile search decision, split out as a pure rule so it is\n * directly unit-testable. On a WIDE viewport a persistent inline field lives at\n * the top of the sidebar (space is cheap, one keystroke narrows the rail); on a\n * NARROW viewport a persistent field would steal scarce vertical space, so the\n * ⌘K command palette is the search affordance instead. The ⌘K hotkey itself\n * stays bound at every width (see {@link useCommandPaletteHotkey}); this rule\n * only decides which VISIBLE affordance the shell renders.\n *\n * Expressed as a string union (not a `const enum`) to match the package's other\n * public mode types ({@link RailMode}, {@link NavShellLayout}) and to stay safe\n * for the Babel/Expo `isolatedModules` builds of the seven consuming portals,\n * which cannot read a `declare const enum` across the package boundary.\n */\n\nimport { LAYOUT_COLLAPSE_BREAKPOINT } from '@dloizides/ui-layout';\n\n/** Which search affordance the shell shows at a given viewport. */\nexport type SearchAffordance = 'inline' | 'palette';\n\n/**\n * Viewport width (px) at/above which the inline field shows. Mirrors the nav\n * shell's {@link RAIL_FULL_BREAKPOINT} / {@link MOBILE_BREAKPOINT} so the inline\n * field appears exactly where the persistent full rail does.\n */\nexport const DEFAULT_SEARCH_BREAKPOINT = LAYOUT_COLLAPSE_BREAKPOINT;\n\n/**\n * Resolve the affordance: `'inline'` at/above `breakpoint`, `'palette'` below.\n * `breakpoint` defaults to {@link DEFAULT_SEARCH_BREAKPOINT}.\n */\nexport function resolveSearchAffordance(\n  viewport: number,\n  breakpoint: number = DEFAULT_SEARCH_BREAKPOINT,\n): SearchAffordance {\n  return viewport >= breakpoint ? 'inline' : 'palette';\n}\n","/**\n * SidebarSearch — the persistent, DESKTOP inline search field that lives at the\n * top of the {@link Sidebar} and narrows the nav list live as the operator types.\n * On a wide viewport a field is cheap and one keystroke filters the rail; on a\n * narrow viewport the ⌘K {@link CommandPalette} is used instead (a persistent\n * field would steal scarce vertical space) — see {@link resolveSearchAffordance}.\n *\n * Package discipline (as the rest of ui-nav): no FM / router / icon-set imports.\n * The placeholder + a11y strings are pre-localized by the caller; every colour is\n * read from the `@dloizides/ui-feedback` UiProvider theme. A clear (\"✕\") button\n * appears once there is a query, wired to `onClear`.\n */\nimport React, { useState } from 'react';\n\nimport { Pressable, StyleSheet, Text, TextInput, View } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { MIN_TOUCH_TARGET } from './styles';\nimport { focusRingStyle } from './webStyle';\n\nconst FIELD_MIN_HEIGHT = 38;\nconst CLEAR_GLYPH = '✕';\n\n/** Pre-localized labels/strings for the inline search field. */\nexport interface SidebarSearchLabels {\n  /** Placeholder + accessible name of the input, e.g. \"Search\". */\n  placeholder: string;\n  /** a11y hint describing what typing does. */\n  hint: string;\n  /** Accessible name of the clear (\"✕\") button. */\n  clearLabel: string;\n  /** Accessible hint of the clear (\"✕\") button. */\n  clearHint: string;\n}\n\nexport interface SidebarSearchProps {\n  /** Current query value (controlled). */\n  value: string;\n  /** Called with the new query on every keystroke. */\n  onChangeText: (query: string) => void;\n  /** Clear the query (also called by the ✕ button). */\n  onClear: () => void;\n  /** Pre-localized chrome strings. */\n  labels: SidebarSearchLabels;\n  /** testID for the input (the clear button is `${testID}-clear`). */\n  testID: string;\n}\n\nconst styles = StyleSheet.create({\n  wrap: {\n    flexDirection: 'row',\n    alignItems: 'center',\n    borderWidth: 1,\n    borderRadius: 8,\n    paddingLeft: 12,\n    paddingRight: 6,\n    marginBottom: 12,\n  },\n  input: {\n    flex: 1,\n    fontSize: 14,\n    paddingVertical: 8,\n    minHeight: FIELD_MIN_HEIGHT,\n  },\n  clear: {\n    minWidth: MIN_TOUCH_TARGET,\n    minHeight: MIN_TOUCH_TARGET,\n    alignItems: 'center',\n    justifyContent: 'center',\n    borderRadius: 6,\n  },\n  clearGlyph: { fontSize: 13, fontWeight: '700' },\n});\n\n/** The inline sidebar search field (desktop) with a clear button. */\nexport const SidebarSearch = ({\n  value,\n  onChangeText,\n  onClear,\n  labels,\n  testID,\n}: SidebarSearchProps): React.ReactElement => {\n  const { theme } = useUi();\n  const colors = theme.colors;\n  const primary = theme.palette.primary['500'];\n  const [focused, setFocused] = useState(false);\n  const hasQuery = value.length > 0;\n\n  return (\n    <View\n      style={[\n        styles.wrap,\n        { backgroundColor: colors.surface, borderColor: focused ? primary : colors.border },\n        focusRingStyle(focused, primary),\n      ]}\n    >\n      <TextInput\n        accessibilityHint={labels.hint}\n        accessibilityLabel={labels.placeholder}\n        placeholder={labels.placeholder}\n        placeholderTextColor={colors.textSecondary}\n        style={[styles.input, { color: colors.text }]}\n        testID={testID}\n        value={value}\n        onBlur={() => setFocused(false)}\n        onChangeText={onChangeText}\n        onFocus={() => setFocused(true)}\n      />\n      {hasQuery ? (\n        <Pressable\n          accessibilityHint={labels.clearHint}\n          accessibilityLabel={labels.clearLabel}\n          accessibilityRole=\"button\"\n          style={styles.clear}\n          testID={`${testID}-clear`}\n          onPress={onClear}\n        >\n          <Text style={[styles.clearGlyph, { color: colors.textSecondary }]}>{CLEAR_GLYPH}</Text>\n        </Pressable>\n      ) : null}\n    </View>\n  );\n};\n\nexport default SidebarSearch;\n","/**\n * `renderTextSlot` — the single guard for every caller-supplied `React.ReactNode`\n * slot in this kit (brand, right, left, header, footer, banner, notificationSlot…).\n *\n * Why this exists. React Native Web refuses to render a bare text node inside a\n * `<View>`: it logs `Unexpected text node: <s>. A text node cannot be a child of a\n * <View>.` through `console.error` on EVERY render. Slots are typed `React.ReactNode`,\n * which legitimately includes `string`, and callers do exactly that — Digital Kin's\n * shell passes `brand: FM('app.name')`, a plain localized string. Nothing in the type\n * system objects, so the defect only ever surfaces as console noise in the browser,\n * which is why it survived in all seven portals.\n *\n * Rather than push the `<Text>` wrapper onto every consuming app (seven chances to\n * forget, and the type would still permit the mistake), the kit absorbs it here: a\n * string or number slot is wrapped in `<Text>`, and an element slot is passed through\n * untouched so existing callers are byte-identical. `React.Children.map` is used so an\n * ARRAY slot (`['Digital', <Logo key=\"l\" />]`) has each string member wrapped\n * individually while keys are preserved.\n *\n * `style` lets the call site route the wrapper through the theme — an unwrapped\n * `<Text>` would otherwise default to black and ignore dark mode.\n */\nimport React from 'react';\n\nimport { Text, type TextStyle } from 'react-native';\n\n/** Is this node a bare text node that RN-web would refuse to render inside a `<View>`? */\nfunction isBareText(node: React.ReactNode): node is string | number {\n  return typeof node === 'string' || typeof node === 'number';\n}\n\n/**\n * Wrap bare string / number members of `node` in `<Text>`; pass elements through as-is.\n * Returns `node` unchanged when it is `undefined` / `null` so callers can keep their\n * existing `!== undefined` guards.\n */\nexport function renderTextSlot(node: React.ReactNode, style?: TextStyle): React.ReactNode {\n  if (node === undefined || node === null) return node;\n  if (isBareText(node)) return <Text style={style}>{node}</Text>;\n  return React.Children.map(node, (child) =>\n    isBareText(child) ? <Text style={style}>{child}</Text> : child,\n  );\n}\n","/**\n * Sidebar — the config-driven left navigation shell promoted from the\n * byte-identical erevna-web / katalogos-web `Sidebar`. It renders a caller\n * supplied `NavItem[]` (leaf + expandable), highlights the active route, and\n * exposes header/footer slots for app-specific chrome (title, dark-mode toggle,\n * logout, notification bell). Every colour is read from the UiProvider theme.\n *\n * Desktop inline search (v1.16, opt-in): pass `enableInlineSearch` + `search`\n * labels and a persistent {@link SidebarSearch} field renders under the title and\n * narrows the nav list live (via {@link filterNavItems}). It is OFF by default,\n * so existing consumers — and the mobile drawer, which should use the ⌘K palette\n * instead (see {@link resolveSearchAffordance}) — are byte-identical to before.\n */\nimport React, { useCallback, useState } from 'react';\n\nimport { Text, View, useWindowDimensions, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { CommandPaletteTrigger } from './CommandPaletteTrigger';\nimport { filterNavItems, isFilterActive } from './sidebarFilter';\nimport { isRouteActive, resolveActiveRoute } from './isRouteActive';\nimport { NavExpandableItem } from './NavExpandableItem';\nimport { resolveSearchAffordance } from './searchAffordance';\nimport { SidebarSearch, type SidebarSearchLabels } from './SidebarSearch';\nimport { navStyles as styles } from './styles';\nimport type { NavItem } from './types';\nimport { renderTextSlot } from './textSlot';\n\n/** Inline-search chrome strings — the field labels plus the no-match empty text. */\nexport interface SidebarSearchConfig extends SidebarSearchLabels {\n  /** Shown in place of the list when the query matches nothing. */\n  emptyText: string;\n}\n\n/**\n * The ⌘K command-palette trigger the sidebar renders as its NARROW-viewport search\n * affordance (a persistent inline field would steal scarce vertical space on mobile\n * — see {@link resolveSearchAffordance}). Pre-localized strings + the open handler;\n * wire `onOpen` to the same handler as the ⌘K hotkey ({@link useCommandPaletteHotkey}).\n */\nexport interface SidebarPaletteTriggerConfig {\n  /** Placeholder-style label, e.g. \"Search\". */\n  label: string;\n  /** a11y hint describing what activating it does. */\n  hint: string;\n  /** The shortcut badge text, e.g. \"⌘K\". */\n  shortcut: string;\n  /** Open the palette (same handler as the ⌘K hotkey). */\n  onOpen: () => void;\n  /** testID for the trigger. Defaults to `sidebar-command-palette-trigger`. */\n  testID?: string;\n}\n\n/** Default testID for the sidebar's palette trigger when the config omits one. */\nconst DEFAULT_TRIGGER_TEST_ID = 'sidebar-command-palette-trigger';\n\nexport interface SidebarProps {\n  /** Nav entries — already role-filtered / grouped by the app. */\n  items: NavItem[];\n  /** Current active route/path. */\n  pathname: string;\n  /** Navigation callback — receives a `NavItem.route`. */\n  onNavigate: (route: string) => void;\n  /** Localized menu title (heading). */\n  title: string;\n  /** Localized accessibility label for the navigation landmark. */\n  regionLabel: string;\n  /** a11y hint for a leaf item, given its label. Defaults to the label. */\n  navigateHint?: (label: string) => string;\n  /** a11y hint shown when an expandable section is collapsed. */\n  expandHint?: string;\n  /** a11y hint shown when an expandable section is expanded. */\n  collapseHint?: string;\n  /** Optional chevron renderer for expandable sections. */\n  renderChevron?: (expanded: boolean, color: string, size: number) => React.ReactNode;\n  /**\n   * Opt into the persistent inline search field (desktop). Requires `search`\n   * labels; when omitted the sidebar renders exactly as before. The field shows\n   * ONLY at the inline affordance (viewport ≥ 768, {@link resolveSearchAffordance});\n   * on a narrow viewport the ⌘K `paletteTrigger` is the search affordance instead.\n   */\n  enableInlineSearch?: boolean;\n  /** Pre-localized inline-search strings — required for `enableInlineSearch`. */\n  search?: SidebarSearchConfig;\n  /**\n   * Opt into the ⌘K {@link CommandPaletteTrigger} as the NARROW-viewport search\n   * affordance. Rendered ONLY at the palette affordance (viewport < 768); on a wide\n   * viewport it is suppressed so the inline field and the trigger are never both\n   * shown — they are mutually exclusive by affordance. The ⌘K hotkey stays bound at\n   * every width independently ({@link useCommandPaletteHotkey}).\n   */\n  paletteTrigger?: SidebarPaletteTriggerConfig;\n  /** Controlled search query (optional — the sidebar owns the state when omitted). */\n  searchQuery?: string;\n  /** Called on each query change (with either controlled or internal state). */\n  onSearchChange?: (query: string) => void;\n  /** Optional header slot rendered above the items (e.g. a Home shortcut). */\n  header?: React.ReactNode;\n  /** Optional footer slot rendered after a flex spacer (dark-mode toggle, logout). */\n  footer?: React.ReactNode;\n  /** Extra container style overrides. */\n  containerStyle?: ViewStyle | ViewStyle[];\n}\n\nexport const Sidebar = ({\n  items,\n  pathname,\n  onNavigate,\n  title,\n  regionLabel,\n  navigateHint = (label) => label,\n  expandHint = '',\n  collapseHint = '',\n  renderChevron,\n  enableInlineSearch = false,\n  search,\n  paletteTrigger,\n  searchQuery,\n  onSearchChange,\n  header,\n  footer,\n  containerStyle,\n}: SidebarProps): React.ReactElement => {\n  const { theme } = useUi();\n  const colors = theme.colors;\n  const { width } = useWindowDimensions();\n\n  const [internalQuery, setInternalQuery] = useState('');\n  const controlled = searchQuery !== undefined;\n  const query = controlled ? searchQuery : internalQuery;\n  const setQuery = useCallback(\n    (next: string) => {\n      if (!controlled) setInternalQuery(next);\n      onSearchChange?.(next);\n    },\n    [controlled, onSearchChange],\n  );\n  const clearQuery = useCallback(() => setQuery(''), [setQuery]);\n\n  // Exactly ONE search affordance renders, chosen by viewport width: the inline\n  // field at the wide/'inline' affordance, the ⌘K trigger at the narrow/'palette'\n  // one. They can never both show — the two-search-bars regression this fixes.\n  const affordance = resolveSearchAffordance(width);\n  const isInlineAffordance = affordance === 'inline';\n  const showInlineSearch = enableInlineSearch && search !== undefined && isInlineAffordance;\n  const showPaletteTrigger = paletteTrigger !== undefined && !isInlineAffordance;\n  const visibleItems = showInlineSearch ? filterNavItems(items, query) : items;\n  const showEmpty = showInlineSearch && isFilterActive(query) && visibleItems.length === 0;\n\n  // Resolve the SINGLE active leaf across the whole model (most-specific/longest\n  // route wins) once, then hand it to every row — so `/accounting` never lights up\n  // alongside `/accounting/journals`. Computed over the full `items`, not the\n  // filtered view, so search never changes which leaf is active.\n  const activeRoute = resolveActiveRoute(items, pathname);\n\n  return (\n    <View\n      accessibilityRole=\"none\"\n      aria-label={regionLabel}\n      role=\"navigation\"\n      style={[\n        styles.sidebarContainer,\n        { backgroundColor: colors.surface, borderRightColor: colors.border },\n        containerStyle,\n      ]}\n    >\n      <Text accessibilityRole=\"header\" style={[styles.sidebarTitle, { color: colors.text }]}>\n        {title}\n      </Text>\n\n      {showInlineSearch && search !== undefined ? (\n        <SidebarSearch\n          labels={search}\n          testID=\"sidebar-search\"\n          value={query}\n          onChangeText={setQuery}\n          onClear={clearQuery}\n        />\n      ) : null}\n\n      {showPaletteTrigger && paletteTrigger !== undefined ? (\n        <View style={styles.sidebarTriggerSlot}>\n          <CommandPaletteTrigger\n            hint={paletteTrigger.hint}\n            label={paletteTrigger.label}\n            shortcut={paletteTrigger.shortcut}\n            testID={paletteTrigger.testID ?? DEFAULT_TRIGGER_TEST_ID}\n            onPress={paletteTrigger.onOpen}\n          />\n        </View>\n      ) : null}\n\n      {renderTextSlot(header, { color: colors.text })}\n\n      {showEmpty && search !== undefined ? (\n        <Text style={[styles.sidebarEmpty, { color: colors.textSecondary }]} testID=\"sidebar-search-empty\">\n          {search.emptyText}\n        </Text>\n      ) : (\n        visibleItems.map((item) => (\n          <NavExpandableItem\n            key={item.key}\n            activeRoute={activeRoute}\n            collapseHint={collapseHint}\n            expandHint={expandHint}\n            item={item}\n            navigateHint={navigateHint}\n            pathname={pathname}\n            renderChevron={renderChevron}\n            onNavigate={onNavigate}\n          />\n        ))\n      )}\n\n      <View style={styles.sidebarSpacer} />\n\n      {renderTextSlot(footer, { color: colors.text })}\n    </View>\n  );\n};\n\nexport { isRouteActive };\nexport default Sidebar;\n","/**\n * Default testIDs for `@dloizides/ui-nav`. Kept as a small central map (mirrors\n * `@dloizides/ui-layout`'s `LAYOUT_TEST_IDS`) so the app-agnostic chrome exposes\n * stable Playwright selectors. The existing Topbar logout/account buttons keep\n * their *caller-supplied* testIDs (via `TopbarAction.testID`) — these constants\n * only name the NEW account-state bits and the AppShell region suffixes.\n */\nexport const NAV_TEST_IDS = {\n  /** displayName line in the rich account header (tappable when `onAccount` set). */\n  accountName: 'topbar-account-name',\n  /** muted tenant-name line under the displayName. */\n  accountTenant: 'topbar-account-tenant',\n  /** small plan badge (free / pro / enterprise). */\n  accountPlan: 'topbar-account-plan',\n  /** default testID for the rich header's upgrade action (overridable per-action). */\n  accountUpgrade: 'topbar-account-upgrade',\n  /** responsive hamburger toggle in the horizontal NavBar (shown below the breakpoint). */\n  navBarToggle: 'navbar-toggle',\n  /** links container in the horizontal NavBar. */\n  navBarLinks: 'navbar-links',\n  /** the \"More ▾\" priority+ overflow trigger in the horizontal NavBar (shown when items spill). */\n  navBarOverflow: 'navbar-overflow',\n} as const;\n\n/** Suffixes appended to an `AppShell`'s required `testID` to name its regions. */\nexport const APP_SHELL_SUFFIX = {\n  content: '-content',\n  header: '-header',\n  nav: '-nav',\n  /** The persistent left rail of the back-office layout (only when `sidebar` is supplied). */\n  sidebar: '-sidebar',\n  /** The intermediate persistent COLLAPSED (icon-only) rail (3-tier layout, tablet band). */\n  collapsedSidebar: '-collapsed-sidebar',\n  /** Mobile hamburger that opens the nav drawer (back-office layout, below the breakpoint). */\n  menuToggle: '-menu-toggle',\n  /** The mobile nav drawer panel (holds the `sidebar` slot when opened on a narrow viewport). */\n  drawer: '-drawer',\n  /** The mobile nav drawer scrim (tap to close). */\n  scrim: '-drawer-scrim',\n  banner: '-banner',\n  pending: '-pending',\n  loading: '-loading',\n  error: '-error',\n  forbidden: '-forbidden',\n} as const;\n","/**\n * FocusableTouchable — a thin `Pressable` wrapper that adds a THEMED keyboard\n * focus ring (via `focusRingStyle`) to any tappable, while forwarding the usual\n * accessibility props. Used by `Topbar` (and available to any nav element that\n * needs a focus ring without its own hover logic). Native-safe: the ring is\n * web-only; on native the focus state simply never drives a visible outline.\n */\nimport React, { useState } from 'react';\n\nimport { Pressable, type StyleProp, type ViewStyle } from 'react-native';\n\nimport { focusRingStyle } from './webStyle';\n\nexport interface FocusableTouchableProps {\n  /** Press handler. */\n  onPress: () => void;\n  /** Accessible name. */\n  accessibilityLabel: string;\n  /** Accessible hint. */\n  accessibilityHint: string;\n  /** ARIA role — button (default) or link. */\n  accessibilityRole?: 'button' | 'link';\n  /** Focus-ring colour (theme accent). */\n  ringColor: string;\n  /** Base style(s) applied under the focus ring. */\n  style?: StyleProp<ViewStyle>;\n  /** Optional testID. */\n  testID?: string;\n  children: React.ReactNode;\n}\n\nexport const FocusableTouchable = ({\n  onPress,\n  accessibilityLabel,\n  accessibilityHint,\n  accessibilityRole = 'button',\n  ringColor,\n  style,\n  testID,\n  children,\n}: FocusableTouchableProps): React.ReactElement => {\n  const [focused, setFocused] = useState(false);\n  return (\n    <Pressable\n      accessibilityHint={accessibilityHint}\n      accessibilityLabel={accessibilityLabel}\n      accessibilityRole={accessibilityRole}\n      style={[style, focusRingStyle(focused, ringColor)]}\n      testID={testID}\n      onBlur={() => setFocused(false)}\n      onFocus={() => setFocused(true)}\n      onPress={onPress}\n    >\n      {children}\n    </Pressable>\n  );\n};\n\nexport default FocusableTouchable;\n","/**\r\n * Topbar — the config-driven top navigation bar promoted from the byte-identical\r\n * erevna-web / katalogos-web `Topbar`. Structured slots replace the app-specific\r\n * wiring: a `left` logo slot, an optional language toggle, a notification slot,\r\n * an optional user block, an optional account button, and a required logout\r\n * action. Every colour comes from the UiProvider theme.\r\n *\r\n * Move 1c enriches this WITHOUT breaking the promoted contract: `account` now\r\n * accepts EITHER the legacy `TopbarAction` (today's erevna/katalogos calls) OR a\r\n * richer `AccountState` (displayName + muted tenant line + plan badge + upgrade\r\n * action). The `logout` action stays required, so every existing call keeps\r\n * compiling and the logout button keeps its caller-supplied testID.\r\n */\r\nimport React from 'react';\r\n\r\nimport { Text, View, type ViewStyle } from 'react-native';\r\n\r\nimport { useUi, type UiTheme } from '@dloizides/ui-feedback';\r\n\r\nimport { NAV_TEST_IDS } from './constants';\r\nimport { FocusableTouchable } from './FocusableTouchable';\r\nimport { navStyles as styles } from './styles';\r\nimport { renderTextSlot } from './textSlot';\r\n\r\n/** Text color for elements on primary/coloured badge backgrounds. */\r\nconst TEXT_ON_PRIMARY = '#ffffff';\r\n\r\nexport interface TopbarAction {\r\n  label: string;\r\n  hint: string;\r\n  onPress: () => void;\r\n  testID?: string;\r\n}\r\n\r\nexport interface TopbarUser {\r\n  name: string;\r\n  email: string;\r\n}\r\n\r\n/** Plan tier shown as a small badge in the rich account header. */\r\nexport interface AccountPlan {\r\n  label: string;\r\n  tone?: 'free' | 'pro' | 'enterprise';\r\n}\r\n\r\n/**\r\n * Richer account model for the header (Move 1c). Supplied via `account` as an\r\n * alternative to the legacy `TopbarAction` — the Topbar renders the display name\r\n * (tappable when `onAccount` is set), a muted tenant line, a plan badge, and an\r\n * `upgrade` action beside logout. No FM/router/store — everything is a\r\n * pre-localized string or a callback.\r\n */\r\nexport interface AccountState {\r\n  displayName: string;\r\n  tenantName?: string;\r\n  plan?: AccountPlan;\r\n  onLogout: () => void;\r\n  onAccount?: () => void;\r\n  /**\r\n   * a11y hint for the account-name button (what pressing it DOES).\r\n   *\r\n   * Without this the hint fell back to `displayName` — byte-identical to the\r\n   * accessibility LABEL, so a screen reader announced the name twice and never\r\n   * said where the button goes. The sibling `upgrade?: TopbarAction` on this very\r\n   * interface has always carried a `hint`; this closes that inconsistency. The\r\n   * `displayName` fallback is retained so existing callers are unaffected.\r\n   */\r\n  accountHint?: string;\r\n  /** testID for the account-name button. Defaults to `NAV_TEST_IDS.accountName`. */\r\n  accountTestID?: string;\r\n  upgrade?: TopbarAction;\r\n}\r\n\r\n/** Type guard: distinguishes the rich `AccountState` from a legacy `TopbarAction`. */\r\nfunction isAccountState(account: TopbarAction | AccountState): account is AccountState {\r\n  return 'displayName' in account;\r\n}\r\n\r\n/** Resolve a plan badge background from its tone, routed through the theme. */\r\nfunction planToneColor(theme: UiTheme, tone: AccountPlan['tone']): string {\r\n  const palette = theme.palette;\r\n  if (tone === 'pro') return palette.primary['500'];\r\n  if (tone === 'enterprise') return palette.accent?.['500'] ?? palette.primary['500'];\r\n  return theme.colors.textSecondary;\r\n}\r\n\r\nexport interface TopbarProps {\r\n  /** Left slot — typically the tenant logo. */\r\n  left?: React.ReactNode;\r\n  /**\r\n   * Optional language toggle. `testID` is optional but the repo standard wants\r\n   * one — before 1.10.0 this inline type declared none, so a testID was\r\n   * structurally unreachable for this button while every other Topbar action\r\n   * (which use `TopbarAction`) accepted one.\r\n   */\r\n  language?: { label: string; hint: string; onPress: () => void; testID?: string };\r\n  /** Optional notification slot (e.g. a notification bell). */\r\n  notificationSlot?: React.ReactNode;\r\n  /** Optional user identity block. */\r\n  user?: TopbarUser;\r\n  /**\r\n   * Optional account slot. Legacy callers pass a `TopbarAction` (an account\r\n   * button). Move-1c callers pass an `AccountState` for the richer header.\r\n   */\r\n  account?: TopbarAction | AccountState;\r\n  /** Required logout action (drives the stable logout button testID). */\r\n  logout: TopbarAction;\r\n  /** Extra container style overrides. */\r\n  containerStyle?: ViewStyle | ViewStyle[];\r\n}\r\n\r\nexport const Topbar = ({\r\n  left,\r\n  language,\r\n  notificationSlot,\r\n  user,\r\n  account,\r\n  logout,\r\n  containerStyle,\r\n}: TopbarProps): React.ReactElement => {\r\n  const { theme } = useUi();\r\n  const colors = theme.colors;\r\n  const primaryColor = theme.palette.primary['500'];\r\n\r\n  const richAccount = account !== undefined && isAccountState(account) ? account : undefined;\r\n  const legacyAccount = account !== undefined && !isAccountState(account) ? account : undefined;\r\n  const upgrade = richAccount?.upgrade;\r\n\r\n  return (\r\n    <View\r\n      style={[\r\n        styles.topbarContainer,\r\n        { borderBottomColor: colors.border, backgroundColor: colors.background },\r\n        containerStyle,\r\n      ]}\r\n    >\r\n      <View style={styles.topbarLeft}>{renderTextSlot(left, { color: colors.text })}</View>\r\n      <View style={styles.topbarRight}>\r\n        {language ? (\r\n          <FocusableTouchable\r\n            accessibilityHint={language.hint}\r\n            accessibilityLabel={language.label}\r\n            ringColor={primaryColor}\r\n            style={styles.topbarRowItem}\r\n            testID={language.testID}\r\n            onPress={language.onPress}\r\n          >\r\n            <Text style={[styles.topbarLabel, { color: colors.text }]}>{language.label}</Text>\r\n          </FocusableTouchable>\r\n        ) : null}\r\n\r\n        {renderTextSlot(notificationSlot, { color: colors.text })}\r\n\r\n        {user ? (\r\n          <View style={styles.userBlock}>\r\n            <Text style={[styles.userName, { color: colors.text }]}>{user.name}</Text>\r\n            <Text style={[styles.userEmail, { color: colors.textSecondary }]}>{user.email}</Text>\r\n          </View>\r\n        ) : null}\r\n\r\n        {richAccount ? (\r\n          <View style={styles.userBlock}>\r\n            {richAccount.onAccount ? (\r\n              <FocusableTouchable\r\n                accessibilityHint={richAccount.accountHint ?? richAccount.displayName}\r\n                accessibilityLabel={richAccount.displayName}\r\n                ringColor={primaryColor}\r\n                style={styles.accountNameBtn}\r\n                testID={richAccount.accountTestID ?? NAV_TEST_IDS.accountName}\r\n                onPress={richAccount.onAccount}\r\n              >\r\n                <Text style={[styles.userName, { color: colors.text }]}>{richAccount.displayName}</Text>\r\n              </FocusableTouchable>\r\n            ) : (\r\n              <Text style={[styles.userName, { color: colors.text }]} testID={NAV_TEST_IDS.accountName}>\r\n                {richAccount.displayName}\r\n              </Text>\r\n            )}\r\n\r\n            {richAccount.tenantName !== undefined ? (\r\n              <Text\r\n                style={[styles.accountTenant, { color: colors.textSecondary }]}\r\n                testID={NAV_TEST_IDS.accountTenant}\r\n              >\r\n                {richAccount.tenantName}\r\n              </Text>\r\n            ) : null}\r\n\r\n            {richAccount.plan ? (\r\n              <View\r\n                style={[styles.planBadge, { backgroundColor: planToneColor(theme, richAccount.plan.tone) }]}\r\n                testID={NAV_TEST_IDS.accountPlan}\r\n              >\r\n                <Text style={[styles.planBadgeText, { color: TEXT_ON_PRIMARY }]}>{richAccount.plan.label}</Text>\r\n              </View>\r\n            ) : null}\r\n          </View>\r\n        ) : null}\r\n\r\n        {legacyAccount ? (\r\n          <FocusableTouchable\r\n            accessibilityHint={legacyAccount.hint}\r\n            accessibilityLabel={legacyAccount.label}\r\n            ringColor={primaryColor}\r\n            style={[styles.accountBtn, { backgroundColor: primaryColor }]}\r\n            testID={legacyAccount.testID}\r\n            onPress={legacyAccount.onPress}\r\n          >\r\n            <Text style={[styles.accountText, { color: TEXT_ON_PRIMARY }]}>{legacyAccount.label}</Text>\r\n          </FocusableTouchable>\r\n        ) : null}\r\n\r\n        {upgrade ? (\r\n          <FocusableTouchable\r\n            accessibilityHint={upgrade.hint}\r\n            accessibilityLabel={upgrade.label}\r\n            ringColor={primaryColor}\r\n            style={[styles.accountBtn, { backgroundColor: primaryColor }]}\r\n            testID={upgrade.testID ?? NAV_TEST_IDS.accountUpgrade}\r\n            onPress={upgrade.onPress}\r\n          >\r\n            <Text style={[styles.accountText, { color: TEXT_ON_PRIMARY }]}>{upgrade.label}</Text>\r\n          </FocusableTouchable>\r\n        ) : null}\r\n\r\n        <FocusableTouchable\r\n          accessibilityHint={logout.hint}\r\n          accessibilityLabel={logout.label}\r\n          ringColor={primaryColor}\r\n          style={[styles.accountBtn, { backgroundColor: primaryColor }]}\r\n          testID={logout.testID}\r\n          onPress={richAccount ? richAccount.onLogout : logout.onPress}\r\n        >\r\n          <Text style={[styles.accountText, { color: TEXT_ON_PRIMARY }]}>{logout.label}</Text>\r\n        </FocusableTouchable>\r\n      </View>\r\n    </View>\r\n  );\r\n};\r\n\r\nexport default Topbar;\r\n","/**\n * NavBarLink — a SINGLE horizontal `NavBar` link, extracted so each link owns its\n * own hover/focus state (React hooks can't be per-item inside a map otherwise).\n *\n * It renders the v1 `.gn-links a` affordance, THEME-DRIVEN (no hard-coded colours\n * beyond white ink on the accent pill):\n *   - rest    → muted text (`colors.rest`), no background\n *   - hover   → text brightens to full contrast (`colors.hoverText`) + a subtle\n *               rounded-pill background (`colors.hoverBg`, e.g. v1 `#16223a`)\n *   - active  → solid accent pill (`colors.activeBg`) with white ink + aria-current\n *   - focus   → a themed keyboard focus ring (`colors.ring`)\n * Hover/focus are WEB-only (react-native-web fires `onHoverIn/Out`); on native\n * those handlers never fire, so the link stays at its rest style.\n */\nimport React, { useState } from 'react';\n\nimport { Pressable, Text, View, type PressableProps, type ViewStyle } from 'react-native';\n\nimport { navBarStyles as styles } from './styles';\nimport { focusRingStyle, hoverTransitionStyle } from './webStyle';\nimport type { NavItem } from './types';\n\n/** Ink for a link sitting on the primary (active) pill — always full-contrast white. */\nconst TEXT_ON_PRIMARY = '#ffffff';\n\n/** Theme-resolved colours a link needs, computed once by `NavBar`. */\nexport interface NavBarLinkColors {\n  /** Muted link text at rest. */\n  rest: string;\n  /** Brightened link text on hover. */\n  hoverText: string;\n  /** Subtle hover-pill background. */\n  hoverBg: string;\n  /** Active-pill background (accent). */\n  activeBg: string;\n  /** Focus-ring colour. */\n  ring: string;\n}\n\nexport interface NavBarLinkProps {\n  item: NavItem;\n  isActive: boolean;\n  collapsed: boolean;\n  iconSize: number;\n  reducedMotion: boolean;\n  colors: NavBarLinkColors;\n  navigateHint: (label: string) => string;\n  onPress: (route: string) => void;\n}\n\n/**\n * `aria-current=\"page\"` marks the active link for assistive tech. RN's prop types\n * omit `aria-current`, but react-native-web forwards `aria-*` to the DOM — so we\n * attach it (no `any`) only when a link is active.\n */\nfunction ariaCurrentProps(isActive: boolean): PressableProps & { 'aria-current'?: 'page' } {\n  return isActive ? { 'aria-current': 'page' } : {};\n}\n\nexport const NavBarLink = ({\n  item,\n  isActive,\n  collapsed,\n  iconSize,\n  reducedMotion,\n  colors,\n  navigateHint,\n  onPress,\n}: NavBarLinkProps): React.ReactElement => {\n  const [hovered, setHovered] = useState(false);\n  const [focused, setFocused] = useState(false);\n\n  const isHovered = hovered && !isActive;\n  const textColor = isActive ? TEXT_ON_PRIMARY : isHovered ? colors.hoverText : colors.rest;\n\n  // Only the pill BACKGROUND changes per state — the ~8px rounding comes from the\n  // base `styles.link` so the hover + active pills share the same rounded shape.\n  const pillStyle: ViewStyle | undefined = isActive\n    ? { backgroundColor: colors.activeBg }\n    : isHovered\n      ? { backgroundColor: colors.hoverBg }\n      : undefined;\n\n  return (\n    <Pressable\n      accessibilityHint={navigateHint(item.label)}\n      accessibilityLabel={item.label}\n      accessibilityRole=\"link\"\n      accessibilityState={{ selected: isActive }}\n      style={[\n        styles.link,\n        collapsed ? styles.linkStacked : undefined,\n        pillStyle,\n        hoverTransitionStyle(reducedMotion),\n        focusRingStyle(focused, colors.ring),\n      ]}\n      testID={item.testID ?? item.key}\n      onBlur={() => setFocused(false)}\n      onFocus={() => setFocused(true)}\n      onHoverIn={() => setHovered(true)}\n      onHoverOut={() => setHovered(false)}\n      onPress={() => onPress(item.route)}\n      {...ariaCurrentProps(isActive)}\n    >\n      {typeof item.renderIcon === 'function' ? (\n        <View style={styles.linkIcon}>{item.renderIcon(textColor, iconSize)}</View>\n      ) : null}\n      <Text style={[styles.linkText, { color: textColor }]}>{item.label}</Text>\n    </Pressable>\n  );\n};\n\nexport default NavBarLink;\n","/**\n * NavOverflowMenu — the \"More ▾\" trigger + dropdown that holds the `NavBar` items\n * which don't fit inline (the priority+ overflow set).\n *\n * It REUSES the shared `@dloizides/ui-layout` `ModalDropdown` — the exact component\n * every other menu in the app uses — so the overflow menu is portalled, keyboard\n * navigable, dismissed on outside-click / Escape, and opens on click, looking\n * identical to the rest of the app's menus. The overflow entries are the same\n * `NavItem`s (label + route + active state); selecting one navigates via the same\n * `onNavigate` the inline links use.\n *\n * The trigger is a rounded pill matching a `NavBarLink`: muted at rest, and — when\n * the ACTIVE route lives in the overflow set — it wears the accent pill so the\n * active item stays visibly reachable behind the \"…\". The dropdown marks that same\n * item selected (its `value` is the active overflow route). a11y: `ModalDropdown`\n * owns the trigger's `role=\"button\"` + `aria-expanded` + caller-supplied label/hint,\n * and gives the options keyboard navigation.\n *\n * Contract discipline (as the rest of `@dloizides/ui-nav`): no FM / router / icon\n * set / store; the label + hint are pre-localized strings from the caller and every\n * colour comes from the theme (via the `NavBarLinkColors` the `NavBar` computed).\n */\nimport React, { useMemo } from 'react';\n\nimport { Text, View } from 'react-native';\n\nimport { ModalDropdown, type DropdownVariant } from '@dloizides/ui-layout';\n\nimport { resolveActiveRoute } from './isRouteActive';\nimport type { NavBarLinkColors } from './NavBarLink';\nimport { navBarStyles as styles } from './styles';\nimport type { NavItem } from './types';\n\n/** Ink for the trigger while it wears the active accent pill — full-contrast white. */\nconst TEXT_ON_PRIMARY = '#ffffff';\n/** No overflow item is active → a value that matches no option (nothing selected). */\nconst NO_ACTIVE_ROUTE = '';\n/**\n * Width floor for the open overflow menu. The \"More ▾\" trigger is a COMPACT pill (only as wide as\n * its own label), so without a floor the shared `ModalDropdown` would open a menu that narrow —\n * wrapping option labels (\"Settings\", \"API docs\") onto two lines and pushing the lower items past\n * the menu's max-height, so they read as missing. This floor gives it a readable single-line width\n * (matching the kit's modal min-width); `ModalDropdown` clamps a floored menu inside the viewport,\n * so the extra width never pushes it off the right edge.\n */\nconst OVERFLOW_MENU_MIN_WIDTH = 200;\n\nexport interface NavOverflowMenuProps {\n  /** The items that spilled out of the inline row. */\n  items: NavItem[];\n  /** Current active route/path — decides the active-pill + selected option. */\n  pathname: string;\n  /** Navigation callback — receives the chosen item's `route`. */\n  onNavigate: (route: string) => void;\n  /** Theme-resolved link colours (same set the inline links use). */\n  colors: NavBarLinkColors;\n  /** Localized visible + accessible label for the trigger (e.g. \"More\"). */\n  label: string;\n  /** Localized accessibility hint for the trigger. */\n  hint: string;\n  /** testID for the trigger (options default to `` `${testID}-option-${route}` ``). */\n  testID: string;\n  /** Force a dropdown variant (default: responsive — inline menu on desktop). */\n  variant?: DropdownVariant;\n}\n\nexport const NavOverflowMenu = ({\n  items,\n  pathname,\n  onNavigate,\n  colors,\n  label,\n  hint,\n  testID,\n  variant,\n}: NavOverflowMenuProps): React.ReactElement => {\n  const options = useMemo(() => items.map((item) => ({ label: item.label, value: item.route })), [items]);\n  const activeRoute = useMemo(\n    () => resolveActiveRoute(items, pathname) ?? NO_ACTIVE_ROUTE,\n    [items, pathname],\n  );\n  const optionTestID = useMemo(() => {\n    const byRoute = new Map(items.map((item) => [item.route, item.testID ?? item.key]));\n    return (route: string): string => byRoute.get(route) ?? `${testID}-option-${route}`;\n  }, [items, testID]);\n\n  const hasActive = activeRoute !== NO_ACTIVE_ROUTE;\n  const textColor = hasActive ? TEXT_ON_PRIMARY : colors.rest;\n  const pillStyle = hasActive ? { backgroundColor: colors.activeBg } : undefined;\n\n  return (\n    <ModalDropdown<string>\n      accessibilityHint={hint}\n      accessibilityLabel={label}\n      menuMinWidth={OVERFLOW_MENU_MIN_WIDTH}\n      optionTestID={optionTestID}\n      options={options}\n      testID={testID}\n      value={activeRoute}\n      variant={variant}\n      onChange={onNavigate}\n      renderTrigger={({ isOpen }) => (\n        <View style={[styles.link, styles.overflowTrigger, pillStyle]}>\n          <Text style={[styles.linkText, { color: textColor }]}>{label}</Text>\n          <Text style={[styles.overflowChevron, { color: textColor }]}>{isOpen ? '▴' : '▾'}</Text>\n        </View>\n      )}\n    />\n  );\n};\n\nexport default NavOverflowMenu;\n","/**\n * Priority+ (\"overflow menu\") fit computation for the horizontal `NavBar`.\n *\n * Pure + framework-free so it can be unit-tested directly: given the available\n * width of the inline links row, the measured natural width of each nav item, and\n * the width of the overflow (\"More ▾\") trigger, it returns how many of the LEADING\n * items fit inline on a single row. Any items beyond the returned count spill into\n * the overflow dropdown.\n *\n * Graceful degradation: it returns `itemWidths.length` (everything inline, no\n * overflow trigger) whenever measurements are not ready yet — `availableWidth <= 0`\n * or any item width `<= 0` — so a first paint before layout resolves (and jsdom /\n * SSR, where there is no layout) shows every item rather than flashing a truncated\n * row. It also returns the full count when every item already fits without a trigger.\n */\nexport interface OverflowMeasurements {\n  /** Width available for the inline links row (the flex space between brand + right). */\n  availableWidth: number;\n  /** Natural pixel width of each nav item, in item order. */\n  itemWidths: number[];\n  /** Natural pixel width of the overflow (\"More\") trigger. */\n  moreWidth: number;\n  /** Horizontal gap (px) between adjacent inline items (the row's `columnGap`). */\n  gap: number;\n}\n\nfunction sum(values: number[]): number {\n  return values.reduce((acc, value) => acc + value, 0);\n}\n\nexport function computeVisibleCount({ availableWidth, itemWidths, moreWidth, gap }: OverflowMeasurements): number {\n  const total = itemWidths.length;\n  if (total === 0) return 0;\n\n  // Unmeasured (pre-layout / SSR / jsdom) → show everything; never truncate before\n  // the row has actually been measured, which would flash items in and back out.\n  if (availableWidth <= 0 || itemWidths.some((width) => width <= 0)) return total;\n\n  // Does the FULL row fit with no overflow trigger at all? Gaps sit BETWEEN items,\n  // so `total` items carry `total - 1` gaps.\n  const fullRowWidth = sum(itemWidths) + gap * (total - 1);\n  if (fullRowWidth <= availableWidth) return total;\n\n  // Overflow is needed: reserve room for the More trigger (plus the gap before it)\n  // and greedily fit the leading items. `used` grows by each item plus the gap that\n  // precedes it (every item after the first).\n  const reservedForMore = moreWidth + gap;\n  let used = 0;\n  let count = 0;\n  for (let index = 0; index < total; index += 1) {\n    const width = itemWidths[index] ?? 0;\n    const withGap = used + (count > 0 ? gap : 0) + width;\n    if (withGap + reservedForMore > availableWidth) break;\n    used = withGap;\n    count += 1;\n  }\n  return count;\n}\n","/**\n * `useNavOverflow` — the measurement state behind the `NavBar` priority+ overflow.\n *\n * It owns the measured widths (available row width, each item's natural width, the\n * \"More\" trigger width) and derives, via the pure {@link computeVisibleCount}, how\n * many leading items fit inline. The actual measuring is done by the caller wiring\n * RN's `onLayout` (react-native-web backs it with a `ResizeObserver`, so it re-fires\n * on resize — no manual `window` access, SSR-safe) into the setters returned here.\n *\n * Widths are cached per item index: an item measured while inline keeps its width\n * after it spills into the overflow menu (its content width does not change), so a\n * resize narrower reuses the cached width and a resize wider brings it back inline\n * and re-measures (a no-op). When the item COUNT changes the buffer is reset to\n * unmeasured (0), so `computeVisibleCount` shows every item until the new row is\n * measured again.\n */\nimport { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { computeVisibleCount } from './computeVisibleCount';\n\nexport interface NavOverflowState {\n  /** How many leading items to render inline; the rest go into the overflow menu. */\n  visibleCount: number;\n  /** Wire to the links row's `onLayout` (its resolved flex width = available space). */\n  setAvailableWidth: (width: number) => void;\n  /** Wire to item `index`'s `onLayout` to record its natural width. */\n  setItemWidth: (index: number, width: number) => void;\n  /** Wire to the overflow (\"More\") trigger's `onLayout`. */\n  setMoreWidth: (width: number) => void;\n}\n\nfunction resizeWidthBuffer(previous: number[], count: number): number[] {\n  const next = new Array<number>(count).fill(0);\n  const shared = Math.min(previous.length, count);\n  for (let index = 0; index < shared; index += 1) next[index] = previous[index] ?? 0;\n  return next;\n}\n\nexport function useNavOverflow(itemCount: number, gap: number): NavOverflowState {\n  const [availableWidth, setAvailableWidthState] = useState(0);\n  const [moreWidth, setMoreWidthState] = useState(0);\n  const [itemWidths, setItemWidths] = useState<number[]>(() => new Array<number>(itemCount).fill(0));\n\n  // Item count changed (items added / removed) → reset to unmeasured so we show all\n  // and re-measure, preserving any still-valid leading widths.\n  useEffect(() => {\n    setItemWidths((previous) => (previous.length === itemCount ? previous : resizeWidthBuffer(previous, itemCount)));\n  }, [itemCount]);\n\n  const setItemWidth = useCallback((index: number, width: number) => {\n    setItemWidths((previous) => {\n      if (index < 0 || index >= previous.length || previous[index] === width) return previous;\n      const next = previous.slice();\n      next[index] = width;\n      return next;\n    });\n  }, []);\n\n  const setAvailableWidth = useCallback(\n    (width: number) => setAvailableWidthState((previous) => (previous === width ? previous : width)),\n    [],\n  );\n  const setMoreWidth = useCallback(\n    (width: number) => setMoreWidthState((previous) => (previous === width ? previous : width)),\n    [],\n  );\n\n  const visibleCount = useMemo(\n    () => computeVisibleCount({ availableWidth, itemWidths, moreWidth, gap }),\n    [availableWidth, itemWidths, moreWidth, gap],\n  );\n\n  return { visibleCount, setAvailableWidth, setItemWidth, setMoreWidth };\n}\n","/**\n * Max height for the NavBar's OPEN stacked (hamburger) menu below the breakpoint.\n *\n * Pure + framework-free so it can be unit-tested directly. The stacked menu used\n * to grow to its natural height (734px with ~15 items), which on a 640px-tall\n * phone pushed the last items below the fold — and portals set\n * `body { overflow: hidden }`, so nothing could scroll to them. The menu is now\n * capped to the viewport space left under the bar and scrolls on its own.\n *\n * - `barHeight` is the measured height of the CLOSED bar (0 = not measured yet;\n *   {@link DEFAULT_BAR_HEIGHT} is used until layout resolves).\n * - `reservedBelow` is the space kept for chrome under the list (the stacked right\n *   slot + margins), so the auth/user block stays reachable too.\n * - The result never drops below {@link MIN_STACKED_MENU_HEIGHT} (three 44px rows)\n *   so a very short viewport still shows a usable, scrollable list.\n */\n\n/** Fallback closed-bar height (px) before the first layout pass reports one. */\nexport const DEFAULT_BAR_HEIGHT = 64;\n/** Row floor (px): the menu always shows at least three 44px touch rows. */\nexport const MIN_STACKED_MENU_HEIGHT = 3 * 44;\n\nexport interface StackedMenuMeasurements {\n  /** Viewport height from `useWindowDimensions()`. */\n  windowHeight: number;\n  /** Measured height of the closed bar, or 0 when not measured yet. */\n  barHeight: number;\n  /** Space (px) reserved below the list for the stacked right slot + margins. */\n  reservedBelow: number;\n}\n\nexport function computeStackedMenuMaxHeight({\n  windowHeight,\n  barHeight,\n  reservedBelow,\n}: StackedMenuMeasurements): number {\n  const bar = barHeight > 0 ? barHeight : DEFAULT_BAR_HEIGHT;\n  const reserved = Math.max(0, reservedBelow);\n  return Math.max(MIN_STACKED_MENU_HEIGHT, windowHeight - bar - reserved);\n}\n","/**\r\n * NavBar — the config-driven HORIZONTAL top navigation bar. It is the top-bar\r\n * counterpart to `Sidebar`: it renders the SAME caller-supplied `NavItem[]`\r\n * (already role-filtered / localized by the app) as inline links across the top\r\n * instead of a left rail, with an optional brand slot on the left and a free-form\r\n * right slot (auth link / user / logout). Below a configurable breakpoint it\r\n * collapses the links behind a hamburger toggle — mirroring the v1 AML console's\r\n * responsive `.global-nav`.\r\n *\r\n * Look + feel: each link is a rounded-pill target with the v1 `.gn-links a`\r\n * affordance — muted at rest, brightening text + a subtle pill background on\r\n * HOVER, and a solid accent pill when ACTIVE. All colours are THEME-DRIVEN from\r\n * the `@dloizides/ui-feedback` UiProvider (rest=`textSecondary`, hover text=`text`,\r\n * hover bg=`surfaceElevated`, active=`palette.primary`, ring=`palette.primary`).\r\n * Hover/focus are web-only (react-native-web); native stays at the rest style.\r\n *\r\n * Overflow (\"…\" priority+ menu). Above the `collapseBelow` breakpoint the links sit\r\n * on ONE row; when they don't all fit, a measure pass ({@link useNavOverflow} +\r\n * {@link computeVisibleCount}) keeps the leading items that fit inline and collapses\r\n * the rest behind a \"More ▾\" trigger — the shared `ModalDropdown` (see\r\n * {@link NavOverflowMenu}) — so no item is ever cut off. BELOW `collapseBelow` the\r\n * whole set still collapses into the responsive hamburger drawer (all items stacked),\r\n * so the two mechanisms don't overlap: hamburger for true mobile, \"…\" for the\r\n * in-between desktop case where only SOME items spill.\r\n *\r\n * Contract discipline (same as the rest of `@dloizides/ui-nav`): NO FM, router,\r\n * icon set, or store imports. Labels are pre-localized strings, icons are render\r\n * slots, and every colour is read from the theme. This is purely additive —\r\n * `Sidebar`/`Topbar` are unchanged and the new overflow labels are optional.\r\n */\r\nimport React, { useCallback, useMemo, useState } from 'react';\r\n\r\nimport {\r\n  Pressable,\r\n  ScrollView,\r\n  Text,\r\n  useWindowDimensions,\r\n  View,\r\n  type LayoutChangeEvent,\r\n  type PressableProps,\r\n  type ViewStyle,\r\n} from 'react-native';\r\n\r\nimport { useUi, UiProvider, type UiTheme } from '@dloizides/ui-feedback';\r\n\r\nimport { NAV_TEST_IDS } from './constants';\r\nimport { isRouteActive, resolveActiveRoute } from './isRouteActive';\r\nimport { NavBarLink, type NavBarLinkColors } from './NavBarLink';\r\nimport { NavOverflowMenu } from './NavOverflowMenu';\r\nimport { navBarStyles as styles, NAV_ICON_SIZE, NAV_LINK_GAP } from './styles';\r\nimport type { NavItem } from './types';\r\nimport { useNavOverflow } from './useNavOverflow';\r\nimport { useReducedMotion } from './useReducedMotion';\r\nimport { focusRingStyle } from './webStyle';\r\nimport { computeStackedMenuMaxHeight } from './stackedMenuMaxHeight';\r\nimport { renderTextSlot } from './textSlot';\r\n\r\n/** DOM id linking the toggle (`aria-controls`) to the collapsible links region. */\r\nconst LINKS_REGION_ID = 'navbar-links-region';\r\n/** Collapse to a hamburger at/under this viewport width (matches v1's 760px). */\r\nconst DEFAULT_COLLAPSE_BELOW = 760;\r\n/** Default hamburger glyph (☰) when no `renderMenuIcon` is supplied. */\r\nconst MENU_GLYPH = '☰';\r\n/** Open-menu chrome under the closed bar: inner rowGap (4) + `linksStacked` marginTop (8). */\r\nconst STACKED_MENU_CHROME = 12;\r\n/** Extra chrome when a stacked right slot follows: inner rowGap (4) + `rightStacked` marginTop (4). */\r\nconst STACKED_RIGHT_CHROME = 8;\r\n\r\nexport interface NavBarProps {\r\n  /** Nav entries — already role-filtered / grouped by the app. */\r\n  items: NavItem[];\r\n  /** Current active route/path. */\r\n  pathname: string;\r\n  /** Navigation callback — receives a `NavItem.route`. */\r\n  onNavigate: (route: string) => void;\r\n  /** Localized accessibility label for the navigation landmark. */\r\n  regionLabel: string;\r\n  /** a11y hint for a link, given its label. Defaults to the label. */\r\n  navigateHint?: (label: string) => string;\r\n  /** Left slot — typically the brand / tenant logo. */\r\n  brand?: React.ReactNode;\r\n  /** Right slot — free-form (auth link, user block, logout). */\r\n  right?: React.ReactNode;\r\n  /** Localized accessibility label for the responsive menu toggle. */\r\n  menuLabel?: string;\r\n  /** Localized accessibility hint for the responsive menu toggle. */\r\n  menuHint?: string;\r\n  /** Optional custom glyph renderer for the toggle; defaults to ☰. */\r\n  renderMenuIcon?: (color: string, open: boolean) => React.ReactNode;\r\n  /** Collapse the links behind a hamburger below this viewport width (default 760). */\r\n  collapseBelow?: number;\r\n  /**\r\n   * Localized visible + accessible label for the \"More ▾\" overflow trigger shown when\r\n   * the inline links don't all fit on one row (priority+ menu). Defaults to `\"More\"`.\r\n   */\r\n  overflowLabel?: string;\r\n  /** Localized accessibility hint for the overflow trigger. */\r\n  overflowHint?: string;\r\n  /** Extra container style overrides. */\r\n  containerStyle?: ViewStyle | ViewStyle[];\r\n  /**\r\n   * Optional content-column cap (px). When set, the OUTER container — which carries\r\n   * the background + bottom border (`barTheme`/theme surface + any `containerStyle`,\r\n   * e.g. the AML radial-glow appbar) — stays FULL WIDTH (full-bleed), while the INNER\r\n   * row (brand + links + right) is capped to this width and centred. Omit for the\r\n   * default where the inner spans the full container. The priority+ overflow \"…\" fit\r\n   * measures the (now capped) inner's rendered width via `onLayout`, so it keeps\r\n   * working against the capped column, not the full-bleed container.\r\n   */\r\n  contentMaxWidth?: number;\r\n  /**\r\n   * Optional CHROME theme override — re-provisions the `@dloizides/ui-feedback`\r\n   * theme for the bar ONLY, so the top bar can be dark while the page below keeps\r\n   * the light workspace theme (the AML v1-console \"dark appbar over light content\"\r\n   * pattern). The live `t` (+ `navigate`) from the surrounding provider are\r\n   * re-passed, so nav labels keep localizing. Omit for a bar that shares the page\r\n   * theme. Style-only: every colour still flows through the theme — no per-app fork.\r\n   */\r\n  barTheme?: UiTheme;\r\n}\r\n\r\n/**\r\n * `aria-controls` links the toggle to the collapsible links region. RN's prop\r\n * types omit `aria-controls`, but react-native-web forwards `aria-*` to the DOM —\r\n * so we attach it (no `any`).\r\n */\r\nfunction ariaControlsProps(id: string): PressableProps & { 'aria-controls'?: string } {\r\n  return { 'aria-controls': id };\r\n}\r\n\r\nconst NavBarInner = ({\r\n  items,\r\n  pathname,\r\n  onNavigate,\r\n  regionLabel,\r\n  navigateHint = (label) => label,\r\n  brand,\r\n  right,\r\n  menuLabel = 'Menu',\r\n  menuHint = '',\r\n  renderMenuIcon,\r\n  collapseBelow = DEFAULT_COLLAPSE_BELOW,\r\n  overflowLabel = 'More',\r\n  overflowHint = '',\r\n  containerStyle,\r\n  contentMaxWidth,\r\n}: Omit<NavBarProps, 'barTheme'>): React.ReactElement => {\r\n  const { theme } = useUi();\r\n  const colors = theme.colors;\r\n  const primaryColor = theme.palette.primary['500'];\r\n  const { width, height } = useWindowDimensions();\r\n  const reducedMotion = useReducedMotion();\r\n  const [open, setOpen] = useState(false);\r\n  const [toggleFocused, setToggleFocused] = useState(false);\r\n  const { visibleCount, setAvailableWidth, setItemWidth, setMoreWidth } = useNavOverflow(items.length, NAV_LINK_GAP);\r\n\r\n  const collapsed = width < collapseBelow;\r\n  const showLinks = !collapsed || open;\r\n\r\n  // SHOWCASE-1: the open stacked menu is capped to the viewport space left under the (closed) bar\r\n  // and scrolls on its own — body is overflow:hidden in the portals, so an uncapped list pushed its\r\n  // last items out of reach. The closed bar + stacked right slot heights are measured via onLayout.\r\n  const [barHeight, setBarHeight] = useState(0);\r\n  const [rightHeight, setRightHeight] = useState(0);\r\n  const hasRight = right !== undefined;\r\n  const stackedMaxHeight = computeStackedMenuMaxHeight({\r\n    windowHeight: height,\r\n    barHeight,\r\n    reservedBelow: STACKED_MENU_CHROME + (hasRight ? STACKED_RIGHT_CHROME + rightHeight : 0),\r\n  });\r\n  const measureBar = collapsed && !open;\r\n\r\n  // Content-column cap: keep the OUTER container full-bleed (its background + bottom\r\n  // border span the viewport) and cap only the INNER row, centred. Omitted ⇒ null ⇒\r\n  // the inner spans the full container (unchanged). The overflow \"…\" fit still measures\r\n  // the inner's rendered width, so it reasons about the capped column, not the container.\r\n  const innerCapStyle = useMemo<ViewStyle | null>(\r\n    () => (contentMaxWidth === undefined ? null : { maxWidth: contentMaxWidth, width: '100%', alignSelf: 'center' }),\r\n    [contentMaxWidth],\r\n  );\r\n\r\n  const toggleMenu = useCallback(() => setOpen((v) => !v), []);\r\n  const handlePress = useCallback(\r\n    (route: string) => {\r\n      setOpen(false);\r\n      onNavigate(route);\r\n    },\r\n    [onNavigate],\r\n  );\r\n\r\n  // Most-specific-wins: resolve the single winning link route across the FULL item\r\n  // set (so it holds across the inline/overflow split) — a link is active iff it is\r\n  // that winner, so a shorter module-home route never co-activates with a deeper one.\r\n  const activeRoute = resolveActiveRoute(items, pathname);\r\n\r\n  // Theme-driven link colours (v1 `.gn-links a`): muted → brightened-on-hover text,\r\n  // a subtle raised pill on hover, the accent pill when active, accent focus ring.\r\n  const linkColors = useMemo<NavBarLinkColors>(\r\n    () => ({\r\n      rest: colors.textSecondary,\r\n      hoverText: colors.text,\r\n      hoverBg: colors.surfaceElevated,\r\n      activeBg: primaryColor,\r\n      ring: primaryColor,\r\n    }),\r\n    [colors.textSecondary, colors.text, colors.surfaceElevated, primaryColor],\r\n  );\r\n\r\n  return (\r\n    <View\r\n      accessibilityRole=\"none\"\r\n      aria-label={regionLabel}\r\n      role=\"navigation\"\r\n      style={[\r\n        styles.container,\r\n        { backgroundColor: colors.surface, borderBottomColor: colors.border },\r\n        containerStyle,\r\n      ]}\r\n      onLayout={measureBar ? (event: LayoutChangeEvent) => setBarHeight(event.nativeEvent.layout.height) : undefined}\r\n    >\r\n      <View style={[styles.inner, collapsed ? null : styles.innerNoWrap, innerCapStyle]}>\r\n        {brand !== undefined ? (\r\n          <View style={styles.brand}>{renderTextSlot(brand, { color: colors.text })}</View>\r\n        ) : null}\r\n\r\n        {collapsed ? (\r\n          <Pressable\r\n            accessibilityHint={menuHint}\r\n            accessibilityLabel={menuLabel}\r\n            accessibilityRole=\"button\"\r\n            accessibilityState={{ expanded: open }}\r\n            aria-expanded={open}\r\n            style={[styles.toggle, focusRingStyle(toggleFocused, primaryColor)]}\r\n            testID={NAV_TEST_IDS.navBarToggle}\r\n            onBlur={() => setToggleFocused(false)}\r\n            onFocus={() => setToggleFocused(true)}\r\n            onPress={toggleMenu}\r\n            {...ariaControlsProps(LINKS_REGION_ID)}\r\n          >\r\n            {typeof renderMenuIcon === 'function' ? (\r\n              renderMenuIcon(colors.text, open)\r\n            ) : (\r\n              <Text style={[styles.toggleGlyph, { color: colors.text }]}>{MENU_GLYPH}</Text>\r\n            )}\r\n          </Pressable>\r\n        ) : null}\r\n\r\n        {showLinks\r\n          ? (() => {\r\n              const renderLink = (item: NavItem): React.ReactElement => (\r\n                <NavBarLink\r\n                  collapsed={collapsed}\r\n                  colors={linkColors}\r\n                  iconSize={NAV_ICON_SIZE}\r\n                  isActive={item.route === activeRoute}\r\n                  item={item}\r\n                  navigateHint={navigateHint}\r\n                  reducedMotion={reducedMotion}\r\n                  onPress={handlePress}\r\n                />\r\n              );\r\n              // Collapsed (mobile): every item stacks vertically on its own full-width line — the\r\n              // responsive hamburger drawer. No overflow menu here; the drawer already holds them all.\r\n              if (collapsed) {\r\n                return (\r\n                  <ScrollView\r\n                    contentContainerStyle={styles.linksStackedContent}\r\n                    nativeID={LINKS_REGION_ID}\r\n                    style={[styles.linksStacked, { maxHeight: stackedMaxHeight }]}\r\n                    testID={NAV_TEST_IDS.navBarLinks}\r\n                  >\r\n                    {items.map((item) => (\r\n                      <React.Fragment key={item.key}>{renderLink(item)}</React.Fragment>\r\n                    ))}\r\n                  </ScrollView>\r\n                );\r\n              }\r\n              // Expanded (desktop): ONE non-wrapping row. A measure pass keeps the leading items\r\n              // that fit inline and collapses the rest behind the \"More ▾\" overflow trigger. Each\r\n              // inline cell reports its natural width via onLayout; the row reports the available\r\n              // width. Until measured, every item shows (computeVisibleCount returns the full count).\r\n              const visibleItems = items.slice(0, visibleCount);\r\n              const overflowItems = items.slice(visibleCount);\r\n              return (\r\n                <View\r\n                  nativeID={LINKS_REGION_ID}\r\n                  style={styles.linksRow}\r\n                  testID={NAV_TEST_IDS.navBarLinks}\r\n                  onLayout={(event: LayoutChangeEvent) => setAvailableWidth(event.nativeEvent.layout.width)}\r\n                >\r\n                  {visibleItems.map((item, index) => (\r\n                    <View\r\n                      key={item.key}\r\n                      style={styles.linkCell}\r\n                      onLayout={(event: LayoutChangeEvent) => setItemWidth(index, event.nativeEvent.layout.width)}\r\n                    >\r\n                      {renderLink(item)}\r\n                    </View>\r\n                  ))}\r\n                  {overflowItems.length > 0 ? (\r\n                    <View\r\n                      style={styles.linkCell}\r\n                      onLayout={(event: LayoutChangeEvent) => setMoreWidth(event.nativeEvent.layout.width)}\r\n                    >\r\n                      <NavOverflowMenu\r\n                        colors={linkColors}\r\n                        hint={overflowHint}\r\n                        items={overflowItems}\r\n                        label={overflowLabel}\r\n                        pathname={pathname}\r\n                        testID={NAV_TEST_IDS.navBarOverflow}\r\n                        onNavigate={handlePress}\r\n                      />\r\n                    </View>\r\n                  ) : null}\r\n                </View>\r\n              );\r\n            })()\r\n          : null}\r\n\r\n        {showLinks && hasRight ? (\r\n          <View\r\n            style={collapsed ? styles.rightStacked : styles.right}\r\n            onLayout={collapsed ? (event: LayoutChangeEvent) => setRightHeight(event.nativeEvent.layout.height) : undefined}\r\n          >\r\n            {renderTextSlot(right, { color: colors.text })}\r\n          </View>\r\n        ) : null}\r\n      </View>\r\n    </View>\r\n  );\r\n};\r\n\r\n/**\r\n * `NavBar` — the horizontal top bar. When `barTheme` is supplied it re-provisions\r\n * the `@dloizides/ui-feedback` theme around the bar (dark bar over a light page),\r\n * re-passing the live `t` / `navigate` so labels keep localizing; otherwise it\r\n * renders directly against the surrounding theme (byte-identical to before).\r\n */\r\nexport const NavBar = ({ barTheme, ...props }: NavBarProps): React.ReactElement => {\r\n  const { t, navigate } = useUi();\r\n  if (barTheme === undefined) return <NavBarInner {...props} />;\r\n  return (\r\n    <UiProvider navigate={navigate} t={t} theme={barTheme}>\r\n      <NavBarInner {...props} />\r\n    </UiProvider>\r\n  );\r\n};\r\n\r\nexport { isRouteActive };\r\nexport default NavBar;\r\n","/**\n * `Nav` — ONE component that renders EITHER the horizontal top bar (`NavBar`) or the\n * vertical rail (`Sidebar`) from the same `NavItem[]`, chosen by a single\n * `orientation` prop. It lets an app flip its navigation between a top bar and a side\n * menu without swapping components or re-plumbing props:\n *\n *   <Nav orientation=\"horizontal\" items={items} pathname={p} onNavigate={go} .../>  // NavBar\n *   <Nav orientation=\"vertical\"   items={items} pathname={p} onNavigate={go} .../>  // Sidebar\n *\n * `orientation` defaults to `\"horizontal\"`. The remaining props are exactly the\n * delegate's props — a discriminated union — so TypeScript enforces the right prop\n * set per orientation (e.g. `title` is required only for the vertical/Sidebar side,\n * `collapseBelow` / `overflowLabel` only for the horizontal/NavBar side).\n *\n * `Nav` is purely additive: `NavBar` and `Sidebar` remain exported and unchanged, so\n * every existing consumer (erevna / katalogos / kefi / agora) is untouched. Vertical\n * navigation is the existing Sidebar — stacked links that scroll vertically, so it\n * needs no overflow menu; the priority+ \"…\" overflow is a horizontal-bar concern.\n */\nimport React from 'react';\n\nimport { NavBar, type NavBarProps } from './NavBar';\nimport { Sidebar, type SidebarProps } from './Sidebar';\n\n/** Which axis the navigation renders on. */\nexport type NavOrientation = 'horizontal' | 'vertical';\n\nexport type NavProps =\n  | ({ orientation?: 'horizontal' } & NavBarProps)\n  | ({ orientation: 'vertical' } & SidebarProps);\n\nexport const Nav = (props: NavProps): React.ReactElement => {\n  // `orientation` is only the discriminant; the delegates (`Sidebar` / `NavBar`)\n  // read their own known props and ignore the extra field, so the whole narrowed\n  // props object can be spread straight through (a JSX spread is not excess-checked).\n  if (props.orientation === 'vertical') {\n    return <Sidebar {...props} />;\n  }\n  return <NavBar {...props} />;\n};\n\nexport default Nav;\n","/**\n * AppShell content-body helpers — the page-state cards (loading / error /\n * forbidden) and the precedence rule that picks what renders inside the content\n * column. Split out of `AppShell` so the shell file stays focused on layout /\n * responsive composition. Colours are routed through the `@dloizides/ui-feedback`\n * theme, same as the rest of `@dloizides/ui-nav`.\n */\nimport React from 'react';\n\nimport { ActivityIndicator, StyleSheet, Text, View } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { APP_SHELL_SUFFIX } from './constants';\n\nconst CARD_PADDING = 20;\nconst CARD_BORDER_RADIUS = 12;\nconst CARD_BORDER_WIDTH = 1;\nconst CARD_TITLE_FONT_SIZE = 16;\nconst CARD_MESSAGE_FONT_SIZE = 14;\nconst CARD_TITLE_MARGIN_BOTTOM = 8;\n\nconst styles = StyleSheet.create({\n  // Loading is a TRANSITIONAL state: the spinner is an absolute overlay ON TOP of\n  // stably-mounted children, never a replacement for them. Replacing children here\n  // would unmount whatever they host (e.g. a navigator), and on remount React\n  // Navigation re-derives its default route — silently discarding a deep link.\n  // The host wraps children whenever a `state` is passed (not only while loading),\n  // so its element type is invariant across the loading toggle — see `useContentBody`.\n  loadingHost: { flex: 1 },\n  loadingOverlay: {\n    alignItems: 'center',\n    bottom: 0,\n    justifyContent: 'center',\n    left: 0,\n    position: 'absolute',\n    right: 0,\n    top: 0,\n  },\n  card: {\n    padding: CARD_PADDING,\n    borderRadius: CARD_BORDER_RADIUS,\n    borderWidth: CARD_BORDER_WIDTH,\n  },\n  cardTitle: { fontSize: CARD_TITLE_FONT_SIZE, fontWeight: '700', marginBottom: CARD_TITLE_MARGIN_BOTTOM },\n  cardMessage: { fontSize: CARD_MESSAGE_FONT_SIZE },\n});\n\n/** A titled message card (error / forbidden). Colours come from the theme. */\nexport interface ShellMessage {\n  titleText: string;\n  messageText: string;\n}\n\n/** Page-state model — a loading spinner card, or a titled error / forbidden card. */\nexport interface ShellState {\n  loading?: boolean;\n  error?: ShellMessage | null;\n  forbidden?: ShellMessage | null;\n}\n\nfunction MessageCard({\n  message,\n  accentColor,\n  testID,\n}: {\n  message: ShellMessage;\n  accentColor: string;\n  testID: string;\n}): React.ReactElement {\n  const { theme } = useUi();\n  const colors = theme.colors;\n  return (\n    <View style={[styles.card, { backgroundColor: colors.surface, borderColor: accentColor }]} testID={testID}>\n      <Text style={[styles.cardTitle, { color: accentColor }]}>{message.titleText}</Text>\n      <Text style={[styles.cardMessage, { color: colors.textSecondary }]}>{message.messageText}</Text>\n    </View>\n  );\n}\n\n/** Pick what renders inside the content column, honouring state precedence. */\nexport function useContentBody(\n  state: ShellState | undefined,\n  children: React.ReactNode,\n  testID: string,\n): React.ReactNode {\n  const { theme } = useUi();\n  const primary = theme.palette.primary['500'];\n  const errorColor = theme.semantic.error['500'];\n\n  // No page-state model passed → render children bare. This keeps the tree\n  // BYTE-IDENTICAL to pre-1.20.0 for the 7 portals that don't opt into `state`.\n  if (!state) return children;\n\n  // Error / forbidden are TERMINAL and deliberately REPLACE children.\n  if (state.forbidden)\n    return <MessageCard accentColor={errorColor} message={state.forbidden} testID={`${testID}${APP_SHELL_SUFFIX.forbidden}`} />;\n  if (state.error)\n    return <MessageCard accentColor={errorColor} message={state.error} testID={`${testID}${APP_SHELL_SUFFIX.error}`} />;\n\n  // A `state`-using consumer, non-terminal: children ALWAYS live under the SAME\n  // `loadingHost` View and only the absolute overlay toggles. The wrapper is\n  // conditioned on `state` being DEFINED, not on `loading`'s live value — so the\n  // element type at this position never changes across a `loading` true↔false\n  // toggle. Were it gated on `loading` (host when true, bare when false), React\n  // would see a type change at a fixed position and REMOUNT children on the edge\n  // — tearing down any navigator they host and dropping its deep-linked route.\n  return (\n    <View style={styles.loadingHost}>\n      {children}\n      {state.loading === true ? (\n        <View\n          style={[styles.loadingOverlay, { backgroundColor: theme.colors.background }]}\n          testID={`${testID}${APP_SHELL_SUFFIX.loading}`}\n        >\n          <ActivityIndicator color={primary} size=\"large\" />\n        </View>\n      ) : null}\n    </View>\n  );\n}\n","/**\n * MobileDrawer — the below-the-breakpoint face of `AppShell`'s back-office\n * `sidebar` layout. On a narrow viewport (<768px) the persistent left rail would\n * starve the content column, so instead of the rail we render a hamburger toggle\n * (`MenuToggle`) in the header and slide the same `Sidebar` in as an overlay\n * drawer (a scrim + a left panel). The drawer closes on a scrim tap and on any\n * nav-item press inside the panel (web: a bubbled click on a `role=\"button\"` /\n * link element). Desktop is untouched — AppShell never mounts this above 768px.\n *\n * Contract discipline (same as the rest of `@dloizides/ui-nav`): NO FM / router /\n * store imports. Labels are pre-localized strings (English defaults, overridable\n * by the consumer via `AppShell`'s `mobileMenu` prop); every colour is read from\n * the `@dloizides/ui-feedback` UiProvider theme.\n */\nimport React, { useEffect, useRef } from 'react';\n\nimport { Pressable, StyleSheet, Text, View } from 'react-native';\n\nimport { Z_INDEX } from '@dloizides/design-tokens';\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { FocusableTouchable } from './FocusableTouchable';\nimport { MIN_TOUCH_TARGET } from './styles';\nimport { renderTextSlot } from './textSlot';\n\n/** Collapse the persistent rail into a drawer at/under this viewport width. */\nexport const MOBILE_BREAKPOINT = 768;\n\nconst SCRIM_COLOR = 'rgba(0, 0, 0, 0.5)';\nconst MENU_GLYPH = '☰';\nconst MENU_GLYPH_FONT_SIZE = 20;\nconst MENU_TOGGLE_PADDING = 12;\nconst DRAWER_Z_INDEX = Z_INDEX.drawer;\n/**\n * Fixed width (px) of the sliding drawer panel. It must be > 0 and anchored so the\n * scrim can sit BESIDE it (see below): a panel with no width — the pre-1.10.2 bug —\n * establishes no hit area, and a full-bleed scrim then swallowed every nav tap.\n */\nconst DRAWER_WIDTH = 280;\n/**\n * The panel stacks ABOVE the scrim within the overlay. Equal zIndex (both 0, the\n * old geometry) left react-native-web to break the tie by DOM order — unreliable\n * for pointer capture, which is how the full-bleed scrim intercepted panel presses.\n */\nconst SCRIM_Z_INDEX = 1;\nconst PANEL_Z_INDEX = 2;\n/**\n * A nav element that, when clicked inside the open drawer, should close it.\n * react-native-web maps `accessibilityRole` -> the DOM `role`, so the Sidebar's\n * leaf `TouchableOpacity`s render as `role=\"button\"` and match here.\n */\nconst NAV_ACTIVATABLE_SELECTOR = 'a, [role=\"button\"], [role=\"link\"]';\n/**\n * An expandable GROUP HEADER is also a `role=\"button\"` (see `NavExpandableItem`),\n * but its press only TOGGLES the section — it does not navigate — so the drawer\n * must stay open. A toggle carries `aria-expanded` (from `accessibilityState.\n * expanded`); a navigating leaf never does. So we treat a click whose closest\n * activatable is (or is inside) an `aria-expanded` element as a toggle, not a\n * navigation, and leave the drawer open. Without this, tapping a group to expand\n * it dismissed the whole drawer (the 1.11.0 grouped-nav regression).\n */\nconst NAV_TOGGLE_SELECTOR = '[aria-expanded]';\n\n/**\n * Run `close` on the NEXT macrotask rather than synchronously. See the load-bearing\n * comment on the panel's click watcher: the drawer's close must not unmount the panel\n * until React has finished dispatching the tapped leaf's `onPress` (the navigation)\n * for the CURRENT click. `setTimeout(…, 0)` yields to the browser after this click's\n * full dispatch (native listeners → React's synthetic listeners) completes, so the\n * route has changed before the panel goes away. Falls back to a synchronous call where\n * `setTimeout` is unavailable (non-DOM host), which is harmless — the race is web-only.\n */\nfunction deferClose(close: () => void): void {\n  if (typeof setTimeout === 'function') setTimeout(close, 0);\n  else close();\n}\n\n/** Pre-localized labels for the drawer's hamburger + scrim. */\nexport interface DrawerLabels {\n  /** Accessible name of the hamburger that opens the drawer. */\n  openLabel: string;\n  /** Accessible hint of the hamburger that opens the drawer. */\n  openHint: string;\n  /** Accessible name of the scrim (tap to close). */\n  closeLabel: string;\n  /** Accessible hint of the scrim (tap to close). */\n  closeHint: string;\n}\n\n/** English defaults — the consumer overrides these with localized strings. */\nexport const DEFAULT_DRAWER_LABELS: DrawerLabels = {\n  openLabel: 'Menu',\n  openHint: 'Open the navigation menu',\n  closeLabel: 'Close menu',\n  closeHint: 'Close the navigation menu',\n};\n\nconst styles = StyleSheet.create({\n  overlay: { ...StyleSheet.absoluteFillObject, zIndex: DRAWER_Z_INDEX },\n  // The scrim's tap-to-close hit area is anchored to the RIGHT of the panel\n  // (`left: DRAWER_WIDTH`), so it NEVER overlaps the panel: nav-item taps always\n  // reach the Sidebar's TouchableOpacity, while taps beside the drawer still close.\n  scrim: {\n    position: 'absolute',\n    top: 0,\n    bottom: 0,\n    left: DRAWER_WIDTH,\n    right: 0,\n    backgroundColor: SCRIM_COLOR,\n    zIndex: SCRIM_Z_INDEX,\n  },\n  // The panel gets an explicit width (a real drawer) AND a zIndex above the scrim,\n  // so on react-native-web it — and the nav leaves inside it — sit above the scrim\n  // and receive presses instead of the scrim swallowing them.\n  panel: { position: 'absolute', top: 0, bottom: 0, left: 0, width: DRAWER_WIDTH, zIndex: PANEL_Z_INDEX },\n  menuToggle: {\n    minWidth: MIN_TOUCH_TARGET,\n    minHeight: MIN_TOUCH_TARGET,\n    alignItems: 'center',\n    justifyContent: 'center',\n    paddingHorizontal: MENU_TOGGLE_PADDING,\n  },\n  menuToggleGlyph: { fontSize: MENU_GLYPH_FONT_SIZE, fontWeight: '700' },\n});\n\nexport interface MenuToggleProps {\n  label: string;\n  hint: string;\n  onOpen: () => void;\n  testID: string;\n}\n\n/** The mobile hamburger button, rendered in the header region below the breakpoint. */\nexport const MenuToggle = ({ label, hint, onOpen, testID }: MenuToggleProps): React.ReactElement => {\n  const { theme } = useUi();\n  return (\n    <FocusableTouchable\n      accessibilityHint={hint}\n      accessibilityLabel={label}\n      ringColor={theme.palette.primary['500']}\n      style={styles.menuToggle}\n      testID={testID}\n      onPress={onOpen}\n    >\n      <Text style={[styles.menuToggleGlyph, { color: theme.colors.text }]}>{MENU_GLYPH}</Text>\n    </FocusableTouchable>\n  );\n};\n\nexport interface MobileDrawerProps {\n  /** The `Sidebar` slot to render inside the drawer panel. */\n  sidebar: React.ReactNode;\n  /** Pre-localized close (scrim) labels. */\n  labels: DrawerLabels;\n  /** Close the drawer. */\n  onClose: () => void;\n  /** testID for the drawer panel. */\n  drawerTestID: string;\n  /** testID for the scrim. */\n  scrimTestID: string;\n}\n\n/** The open drawer overlay: a tap-to-close scrim + the sidebar panel. */\nexport const MobileDrawer = ({\n  sidebar,\n  labels,\n  onClose,\n  drawerTestID,\n  scrimTestID,\n}: MobileDrawerProps): React.ReactElement => {\n  const { theme } = useUi();\n  const panelRef = useRef<View | null>(null);\n\n  // Close on a nav-item press. The consumer wires the Sidebar's `onNavigate`\n  // directly to the router, so we cannot intercept that callback; instead (on\n  // web) we watch for a bubbled click on an activatable element inside the panel.\n  //\n  // 🔴 THE CLOSE MUST BE DEFERRED, and the defer is load-bearing — removing it\n  // reintroduces a real, ship-blocking bug (a leaf tap dismissed the drawer WITHOUT\n  // navigating). Why: react-native-web's `PressResponder` fires a leaf's `onPress`\n  // from its `onClick`, dispatched through REACT's synthetic event system — whose\n  // root listener lives on the app-root container, an ANCESTOR of this panel. This\n  // handler is a NATIVE `addEventListener('click')` on the panel, so it fires during\n  // the real DOM bubble BEFORE the event ever reaches React's root. If we closed\n  // synchronously here, `setDrawerOpen(false)` would unmount the panel — tearing the\n  // leaf out of the tree — and React would then have no leaf to dispatch `onPress`\n  // to: the drawer vanishes and navigation never runs. Deferring the close to a\n  // macrotask lets React finish dispatching the leaf's `onPress` (the navigation)\n  // during THIS click; the drawer then unmounts on the next tick, after the route\n  // has already changed. (jsdom's `fireEvent.click` + an inert `jest.fn()` onClose\n  // never unmounts, so a unit test alone cannot catch this — see the regression test\n  // that renders a real unmounting onClose, and the live Playwright repro.)\n  useEffect(() => {\n    const node = panelRef.current as unknown as HTMLElement | null;\n    if (node === null || typeof node.addEventListener !== 'function') return undefined;\n    const handleClick = (event: MouseEvent): void => {\n      const target = event.target as HTMLElement | null;\n      if (target === null) return;\n      const activatable = target.closest(NAV_ACTIVATABLE_SELECTOR);\n      // A group-header toggle is a `role=\"button\"` too — only a real navigation\n      // (a leaf, never an `aria-expanded` toggle) should dismiss the drawer.\n      const isToggle = activatable !== null && activatable.closest(NAV_TOGGLE_SELECTOR) !== null;\n      if (activatable !== null && !isToggle) deferClose(onClose);\n    };\n    node.addEventListener('click', handleClick);\n    return () => node.removeEventListener('click', handleClick);\n  }, [onClose]);\n\n  return (\n    <View style={styles.overlay}>\n      <Pressable\n        accessibilityHint={labels.closeHint}\n        accessibilityLabel={labels.closeLabel}\n        accessibilityRole=\"button\"\n        style={styles.scrim}\n        testID={scrimTestID}\n        onPress={onClose}\n      />\n      <View\n        ref={panelRef}\n        aria-modal\n        role=\"dialog\"\n        style={[styles.panel, { backgroundColor: theme.colors.surface }]}\n        testID={drawerTestID}\n      >\n        {renderTextSlot(sidebar, { color: theme.colors.text })}\n      </View>\n    </View>\n  );\n};\n\nexport default MobileDrawer;\n","/**\n * Rail responsive mode — the pure (viewport → which rail face) rule behind\n * `AppShell`'s optional THREE-tier layout, split out so it is directly\n * unit-testable.\n *\n * Two-tier (default, back-compat): a persistent full rail at/above\n * {@link RAIL_FULL_BREAKPOINT}, an overlay drawer below it. This is what every\n * existing `AppShell` `sidebar` consumer already gets.\n *\n * Three-tier (opt-in — supply a `collapsedSidebar`): a persistent full rail on\n * desktop, an intermediate persistent COLLAPSED (icon-only) rail on tablet, and\n * the overlay drawer on a phone — the erevna / katalogos responsive scheme.\n */\n\nimport { LAYOUT_COLLAPSE_BREAKPOINT } from '@dloizides/ui-layout';\n\n/** At/above this viewport width the persistent FULL rail shows (two-tier boundary). */\nexport const RAIL_FULL_BREAKPOINT = LAYOUT_COLLAPSE_BREAKPOINT;\n/** Default upper bound of the collapsed-rail band (full rail at/above this). */\nexport const DEFAULT_COLLAPSED_RAIL_MAX = 1024;\n\n/** Which face the rail takes at a given viewport. */\nexport type RailMode = 'none' | 'full' | 'collapsed' | 'drawer';\n\n/**\n * Viewport band in which the intermediate COLLAPSED icon-rail shows: `[min, max)`.\n * At/above `max` the full rail shows; below `min` the overlay drawer shows.\n */\nexport interface CollapsedRailRange {\n  min: number;\n  max: number;\n}\n\nexport interface ResolveRailModeArgs {\n  viewport: number;\n  /** Whether a `sidebar` (full rail) node was supplied at all. */\n  hasSidebar: boolean;\n  /** Whether an intermediate `collapsedSidebar` node was supplied (enables 3-tier). */\n  hasCollapsed: boolean;\n  /** The collapsed-rail band; only consulted in 3-tier mode. */\n  range: CollapsedRailRange;\n}\n\n/**\n * Resolve the rail mode. No sidebar ⇒ `'none'`. With a `collapsedSidebar`\n * (3-tier): full at/above `range.max`, collapsed in `[range.min, range.max)`,\n * drawer below `range.min`. Without one (2-tier, unchanged): full at/above\n * {@link RAIL_FULL_BREAKPOINT}, drawer below.\n */\nexport function resolveRailMode({ viewport, hasSidebar, hasCollapsed, range }: ResolveRailModeArgs): RailMode {\n  if (!hasSidebar) return 'none';\n  if (hasCollapsed) {\n    if (viewport >= range.max) return 'full';\n    if (viewport >= range.min) return 'collapsed';\n    return 'drawer';\n  }\n  return viewport >= RAIL_FULL_BREAKPOINT ? 'full' : 'drawer';\n}\n","/**\n * Width-discipline helper for `AppShell` (Move 1c). Split out from the component\n * so the (viewport → max-width) rule is a small, directly unit-testable pure\n * function, with a thin hook wrapper that feeds it the live viewport width.\n */\nimport { useWindowDimensions } from 'react-native';\n\n/** Content-width policy: a capped column, optionally wider past a viewport breakpoint, or full-bleed. */\nexport type AppShellWidth =\n  | { max: number; wideMax?: number; wideMinViewport?: number }\n  | 'full';\n\n/**\n * Resolve the content column's max width for a given viewport. `'full'` passes\n * through (no cap); an object caps at `max`, widening to `wideMax` once the\n * viewport reaches `wideMinViewport`.\n */\nexport function resolveContentMaxWidth(width: AppShellWidth, viewport: number): number | 'full' {\n  if (width === 'full') return 'full';\n  const wideMinViewport = width.wideMinViewport ?? Number.POSITIVE_INFINITY;\n  const isWide = viewport >= wideMinViewport;\n  return isWide ? (width.wideMax ?? width.max) : width.max;\n}\n\n/** Hook wrapper: resolves the content max width against the live window width. */\nexport function useContentMaxWidth(width: AppShellWidth): number | 'full' {\n  const { width: viewport } = useWindowDimensions();\n  return resolveContentMaxWidth(width, viewport);\n}\n","/**\r\n * AppShell — the shared dashboard-chrome composition (Move 1c). It hosts, top to\r\n * bottom: an app-supplied header (full-bleed), an optional per-app nav region, an\r\n * optional banner, and a width-disciplined scrollable content column. It also\r\n * folds in the two things every product page re-implements: an auth gate\r\n * (pending spinner / redirect-when-unauthenticated) and page state cards\r\n * (loading / error / forbidden).\r\n *\r\n * OVERLAY DISCIPLINE (do not regress): a TRANSITIONAL status — `gate.pending` and\r\n * `state.loading` — renders as an absolute overlay OVER stably-mounted `children`,\r\n * never as a replacement. Replacing the subtree unmounts whatever `children` host\r\n * (typically a navigator/`<Slot/>`); on remount React Navigation re-derives its\r\n * default route, so a deep-linked sub-route silently collapses to its default on\r\n * every reload. Only TERMINAL states replace: unauthenticated returns null (we are\r\n * navigating away) and error/forbidden cards win inside the content column.\r\n * Corollary for consumers: `children` mount BENEATH the pending overlay, so gate\r\n * your data FETCHES on auth state (`enabled: isAuthenticated`), not on mount.\r\n *\r\n * A BACK-OFFICE variant is supported via the optional `sidebar` slot (added for\r\n * Agora's merchant admin): supply a `<Sidebar>` and the body below the header /\r\n * nav / banner becomes a ROW — a persistent left rail beside the scrolling\r\n * content column — instead of the default single vertical stack. Omit `sidebar`\r\n * and the render tree is byte-identical to before, so every existing consumer\r\n * (erevna / katalogos / kefi) is untouched.\r\n *\r\n * Contract discipline (same as the rest of `@dloizides/ui-nav`): NO FM, router,\r\n * or store imports. The app passes wired elements, pre-localized strings, and\r\n * callbacks; every colour is routed through the `@dloizides/ui-feedback` theme.\r\n */\r\nimport React, { useCallback, useEffect, useState } from 'react';\r\n\r\nimport {\r\n  ActivityIndicator,\r\n  ScrollView,\r\n  StyleSheet,\r\n  useWindowDimensions,\r\n  View,\r\n  type ViewStyle,\r\n} from 'react-native';\r\n\r\nimport { useUi } from '@dloizides/ui-feedback';\r\n\r\nimport { useContentBody, type ShellState } from './appShellContent';\r\nimport { APP_SHELL_SUFFIX } from './constants';\r\nimport {\r\n  DEFAULT_DRAWER_LABELS,\r\n  MenuToggle,\r\n  MobileDrawer,\r\n  type DrawerLabels,\r\n} from './MobileDrawer';\r\nimport {\r\n  DEFAULT_COLLAPSED_RAIL_MAX,\r\n  RAIL_FULL_BREAKPOINT,\r\n  resolveRailMode,\r\n  type CollapsedRailRange,\r\n} from './railMode';\r\nimport { useContentMaxWidth, type AppShellWidth } from './useContentMaxWidth';\r\nimport { renderTextSlot } from './textSlot';\r\n\r\nconst DEFAULT_CONTENT_PADDING = 24;\r\n\r\nconst styles = StyleSheet.create({\r\n  root: { flex: 1 },\r\n  // Auth-pending spinner: an opaque absolute overlay over the mounted shell, so\r\n  // `children` (and any navigator they host) are never unmounted while the gate\r\n  // resolves. See the `gatePending` note in the render body.\r\n  pendingOverlay: { alignItems: 'center', bottom: 0, justifyContent: 'center', left: 0, position: 'absolute', right: 0, top: 0 },\r\n  scroll: { flex: 1 },\r\n  scrollContent: { flexGrow: 1 },\r\n  // Mobile back-office header: the hamburger sits inline before the header slot.\r\n  headerRow: { flexDirection: 'row', alignItems: 'center' },\r\n  headerFill: { flex: 1 },\r\n  // Back-office layout: a persistent left rail beside the scrolling content column.\r\n  bodyRow: { flex: 1, flexDirection: 'row' },\r\n  columnFull: { flex: 1 },\r\n  columnCapped: { flex: 1, width: '100%', alignSelf: 'center' },\r\n  // Non-flex variant used to cap the nav strip's inner content to the content\r\n  // column so the nav aligns with the page content instead of running full-bleed.\r\n  chromeCapped: { width: '100%', alignSelf: 'center' },\r\n});\r\n\r\nexport type { ShellMessage } from './appShellContent';\r\n\r\nexport interface AppShellProps {\r\n  /** App-supplied wired header (Topbar / AppHeader), rendered full-bleed. */\r\n  header: React.ReactNode;\r\n  /** Per-app nav region (kefi coral pills / erevna sidebar+drawer). */\r\n  nav?: React.ReactNode;\r\n  /**\r\n   * Optional persistent LEFT RAIL (a `<Sidebar>`), for back-office surfaces. When\r\n   * supplied, the region below header/nav/banner lays out as a row: the rail on the\r\n   * left, the scrolling content column on the right. Omit for the default vertical\r\n   * stack — the tree is then byte-identical to the pre-`sidebar` AppShell.\r\n   *\r\n   * Responsive: at/under ~768px the persistent rail is REPLACED by a hamburger (in\r\n   * the header) that opens the same `sidebar` as an overlay drawer, so the content\r\n   * takes the full width. Desktop (≥768px) is unchanged. No effect without `sidebar`.\r\n   */\r\n  sidebar?: React.ReactNode;\r\n  /**\r\n   * Optional intermediate COLLAPSED (icon-only) rail — opts the `sidebar` layout\r\n   * into a THREE-tier responsive scheme (erevna / katalogos): the full `sidebar`\r\n   * on desktop, this collapsed rail on a tablet-width band, and the overlay drawer\r\n   * (hosting the full `sidebar`) on a phone. Omit it and the layout stays the\r\n   * unchanged two-tier scheme (full rail ≥768px, drawer below). No effect without\r\n   * `sidebar`. Exposed as `${testID}${APP_SHELL_SUFFIX.collapsedSidebar}`.\r\n   */\r\n  collapsedSidebar?: React.ReactNode;\r\n  /**\r\n   * The viewport band `[min, max)` in which `collapsedSidebar` shows: at/above\r\n   * `max` the full rail shows, below `min` the drawer shows. Defaults to\r\n   * `{ min: 768, max: 1024 }`. Only consulted when `collapsedSidebar` is supplied.\r\n   */\r\n  collapsedRailRange?: CollapsedRailRange;\r\n  /**\r\n   * Pre-localized labels for the mobile nav drawer (only used in the `sidebar`\r\n   * layout, below the breakpoint): the hamburger's open label/hint and the scrim's\r\n   * close label/hint. Optional — English defaults apply. NO i18n in this package.\r\n   */\r\n  mobileMenu?: Partial<DrawerLabels>;\r\n  /** Banner slot (e.g. verification-pending). */\r\n  banner?: React.ReactNode;\r\n  /** Content-width policy. Defaults to full-bleed. */\r\n  width?: AppShellWidth;\r\n  /** Content padding inside the scroll column. Defaults to 24. */\r\n  contentPadding?: number;\r\n  /**\r\n   * Whether the nav strip aligns with the width-capped content column\r\n   * (`'content'`) or runs full-bleed (`'full'`, the default). Only has an effect\r\n   * when `width` caps the content. The header always renders full-bleed.\r\n   */\r\n  chromeAlignment?: 'full' | 'content';\r\n  /** Auth gate — spinner while pending, `onRedirect` when unauthenticated. */\r\n  gate?: { pending: boolean; authenticated: boolean; onRedirect: () => void };\r\n  /** Page state — loading spinner card, or a titled error / forbidden card. */\r\n  state?: ShellState;\r\n  /** Root testID; the content region is exposed as `${testID}-content`. */\r\n  testID: string;\r\n  children: React.ReactNode;\r\n}\r\n\r\nexport const AppShell = ({\r\n  header,\r\n  nav,\r\n  sidebar,\r\n  collapsedSidebar,\r\n  collapsedRailRange,\r\n  mobileMenu,\r\n  banner,\r\n  width = 'full',\r\n  contentPadding = DEFAULT_CONTENT_PADDING,\r\n  chromeAlignment = 'full',\r\n  gate,\r\n  state,\r\n  testID,\r\n  children,\r\n}: AppShellProps): React.ReactElement | null => {\r\n  const { theme } = useUi();\r\n  const primary = theme.palette.primary['500'];\r\n  const maxWidth = useContentMaxWidth(width);\r\n  const body = useContentBody(state, children, testID);\r\n\r\n  // Back-office responsive behaviour: the rail takes one of three faces by\r\n  // viewport — the persistent full rail, an optional intermediate collapsed\r\n  // (icon-only) rail, or an overlay drawer. Without `collapsedSidebar` this stays\r\n  // the unchanged two-tier scheme (full rail ≥768px, drawer below).\r\n  const { width: viewportWidth } = useWindowDimensions();\r\n  const railRange: CollapsedRailRange = collapsedRailRange ?? { min: RAIL_FULL_BREAKPOINT, max: DEFAULT_COLLAPSED_RAIL_MAX };\r\n  const railMode = resolveRailMode({\r\n    viewport: viewportWidth,\r\n    hasSidebar: sidebar !== undefined,\r\n    hasCollapsed: collapsedSidebar !== undefined,\r\n    range: railRange,\r\n  });\r\n  const useDrawer = railMode === 'drawer';\r\n  const [drawerOpen, setDrawerOpen] = useState(false);\r\n  const openDrawer = useCallback(() => setDrawerOpen(true), []);\r\n  const closeDrawer = useCallback(() => setDrawerOpen(false), []);\r\n  useEffect(() => {\r\n    if (!useDrawer && drawerOpen) setDrawerOpen(false);\r\n  }, [useDrawer, drawerOpen]);\r\n  const drawerLabels: DrawerLabels = { ...DEFAULT_DRAWER_LABELS, ...mobileMenu };\r\n\r\n  const isUnauthenticated = gate !== undefined && !gate.pending && !gate.authenticated;\r\n  useEffect(() => {\r\n    if (isUnauthenticated && gate !== undefined) gate.onRedirect();\r\n  }, [isUnauthenticated, gate]);\r\n\r\n  // `pending` is a TRANSITIONAL status, so it OVERLAYS the mounted shell (see the\r\n  // absolute overlay at the end of the tree) rather than replacing it. Replacing\r\n  // the subtree here would unmount `children` — and any navigator they host — so a\r\n  // deep-linked sub-route would collapse to its default on every reload once the\r\n  // gate resolves. Only TERMINAL states replace: `isUnauthenticated` returns null\r\n  // (navigating away), and error/forbidden cards win inside the content column.\r\n  const gatePending = gate?.pending === true;\r\n\r\n  if (isUnauthenticated) return null;\r\n\r\n  const columnStyle: ViewStyle | ViewStyle[] =\r\n    maxWidth === 'full' ? styles.columnFull : [styles.columnCapped, { maxWidth }];\r\n\r\n  // Align the nav strip's inner content with the capped content column when asked\r\n  // (and only when the content is actually capped); otherwise it runs full-bleed.\r\n  const navInnerStyle: ViewStyle | ViewStyle[] | undefined =\r\n    chromeAlignment === 'content' && maxWidth !== 'full'\r\n      ? [styles.chromeCapped, { maxWidth, paddingHorizontal: contentPadding }]\r\n      : undefined;\r\n\r\n  const scroller = (\r\n    <ScrollView\r\n      contentContainerStyle={[styles.scrollContent, { padding: contentPadding }]}\r\n      style={styles.scroll}\r\n      testID={`${testID}${APP_SHELL_SUFFIX.content}`}\r\n    >\r\n      <View style={columnStyle}>{body}</View>\r\n    </ScrollView>\r\n  );\r\n\r\n  // Header region: below the breakpoint (with a sidebar) the hamburger sits inline\r\n  // before the header slot; otherwise the header wrapper is unchanged.\r\n  const headerRegion = useDrawer ? (\r\n    <View style={styles.headerRow} testID={`${testID}${APP_SHELL_SUFFIX.header}`}>\r\n      <MenuToggle\r\n        hint={drawerLabels.openHint}\r\n        label={drawerLabels.openLabel}\r\n        testID={`${testID}${APP_SHELL_SUFFIX.menuToggle}`}\r\n        onOpen={openDrawer}\r\n      />\r\n      <View style={styles.headerFill}>{renderTextSlot(header, { color: theme.colors.text })}</View>\r\n    </View>\r\n  ) : (\r\n    <View testID={`${testID}${APP_SHELL_SUFFIX.header}`}>\r\n      {renderTextSlot(header, { color: theme.colors.text })}\r\n    </View>\r\n  );\r\n\r\n  // Body: the persistent rail (full or collapsed) sits beside the content in a\r\n  // row; in drawer mode the content takes the full width and the rail moves into\r\n  // the overlay drawer.\r\n  const railRegion =\r\n    railMode === 'full' ? (\r\n      <View testID={`${testID}${APP_SHELL_SUFFIX.sidebar}`}>\r\n        {renderTextSlot(sidebar, { color: theme.colors.text })}\r\n      </View>\r\n    ) : railMode === 'collapsed' ? (\r\n      <View testID={`${testID}${APP_SHELL_SUFFIX.collapsedSidebar}`}>\r\n        {renderTextSlot(collapsedSidebar, { color: theme.colors.text })}\r\n      </View>\r\n    ) : null;\r\n\r\n  return (\r\n    <View style={[styles.root, { backgroundColor: theme.colors.background }]} testID={testID}>\r\n      {headerRegion}\r\n      {nav !== undefined ? (\r\n        <View testID={`${testID}${APP_SHELL_SUFFIX.nav}`}>\r\n          {navInnerStyle !== undefined ? (\r\n            <View style={navInnerStyle}>{renderTextSlot(nav, { color: theme.colors.text })}</View>\r\n          ) : (\r\n            renderTextSlot(nav, { color: theme.colors.text })\r\n          )}\r\n        </View>\r\n      ) : null}\r\n      {banner !== undefined ? (\r\n        <View testID={`${testID}${APP_SHELL_SUFFIX.banner}`}>\r\n          {renderTextSlot(banner, { color: theme.colors.text })}\r\n        </View>\r\n      ) : null}\r\n      {railRegion !== null ? (\r\n        <View style={styles.bodyRow}>\r\n          {railRegion}\r\n          {scroller}\r\n        </View>\r\n      ) : (\r\n        scroller\r\n      )}\r\n      {useDrawer && drawerOpen ? (\r\n        <MobileDrawer\r\n          drawerTestID={`${testID}${APP_SHELL_SUFFIX.drawer}`}\r\n          labels={drawerLabels}\r\n          scrimTestID={`${testID}${APP_SHELL_SUFFIX.scrim}`}\r\n          sidebar={sidebar}\r\n          onClose={closeDrawer}\r\n        />\r\n      ) : null}\r\n      {gatePending ? (\r\n        <View\r\n          style={[styles.pendingOverlay, { backgroundColor: theme.colors.background }]}\r\n          testID={`${testID}${APP_SHELL_SUFFIX.pending}`}\r\n        >\r\n          <ActivityIndicator color={primary} size=\"large\" />\r\n        </View>\r\n      ) : null}\r\n    </View>\r\n  );\r\n};\r\n\r\nexport default AppShell;\r\n","/**\r\n * CollapsedRail — the icon-only vertical rail for the intermediate (tablet) tier\r\n * of `AppShell`'s three-tier responsive layout (the erevna / katalogos collapsed\r\n * rail). It renders the SAME caller-supplied `NavItem[]` as `Sidebar`, but as a\r\n * narrow strip of icon buttons: each item shows its `renderIcon` (or a first-letter\r\n * glyph fallback), labelled for assistive tech, with the active route highlighted.\r\n * Optional `header` / `footer` slots carry app chrome (a home shortcut, a\r\n * dark-mode toggle, logout) top and bottom.\r\n *\r\n * A collapsed rail cannot expand a section inline, so pressing ANY item — leaf or\r\n * parent — navigates to its `route`; an app that wants a parent to open the full\r\n * drawer instead can special-case that in its `onNavigate`.\r\n *\r\n * Contract discipline (same as the rest of `@dloizides/ui-nav`): NO FM, router,\r\n * icon-set, or store imports. Labels are pre-localized strings, icons are render\r\n * slots, and every colour is read from the `@dloizides/ui-feedback` theme.\r\n */\r\nimport React from 'react';\r\n\r\nimport { Text, View, type ViewStyle } from 'react-native';\r\n\r\nimport { useUi } from '@dloizides/ui-feedback';\r\n\r\nimport { FocusableTouchable } from './FocusableTouchable';\r\nimport { resolveActiveRoute } from './isRouteActive';\r\nimport { collapsedRailStyles as styles } from './styles';\r\nimport type { NavItem } from './types';\r\nimport { renderTextSlot } from './textSlot';\r\n\r\n/** Icon size for a collapsed-rail item. */\r\nconst COLLAPSED_ICON_SIZE = 22;\r\n\r\nexport interface CollapsedRailProps {\r\n  /** Nav entries — the same role-filtered `NavItem[]` the full `Sidebar` renders. */\r\n  items: NavItem[];\r\n  /** Current active route/path. */\r\n  pathname: string;\r\n  /** Navigation callback — receives a `NavItem.route`. */\r\n  onNavigate: (route: string) => void;\r\n  /** Localized accessibility label for the navigation landmark. */\r\n  regionLabel: string;\r\n  /** a11y hint for an item, given its label. Defaults to the label. */\r\n  navigateHint?: (label: string) => string;\r\n  /** Optional header slot rendered above the items (e.g. a home shortcut). */\r\n  header?: React.ReactNode;\r\n  /** Optional footer slot rendered after a flex spacer (dark-mode toggle, logout). */\r\n  footer?: React.ReactNode;\r\n  /** Extra container style overrides. */\r\n  containerStyle?: ViewStyle | ViewStyle[];\r\n}\r\n\r\n/** First character of a label, uppercased — the icon fallback glyph. */\r\nfunction glyphFor(label: string): string {\r\n  return label.trim().charAt(0).toUpperCase();\r\n}\r\n\r\nexport const CollapsedRail = ({\r\n  items,\r\n  pathname,\r\n  onNavigate,\r\n  regionLabel,\r\n  navigateHint = (label) => label,\r\n  header,\r\n  footer,\r\n  containerStyle,\r\n}: CollapsedRailProps): React.ReactElement => {\r\n  const { theme } = useUi();\r\n  const colors = theme.colors;\r\n  const primaryColor = theme.palette.primary['500'];\r\n\r\n  // Most-specific-wins: only the longest matching route is highlighted, so a\r\n  // module-home rail icon never co-activates with a deeper sibling on a nested path.\r\n  const activeRoute = resolveActiveRoute(items, pathname);\r\n\r\n  return (\r\n    <View\r\n      accessibilityRole=\"none\"\r\n      aria-label={regionLabel}\r\n      role=\"navigation\"\r\n      style={[\r\n        styles.container,\r\n        { backgroundColor: colors.surface, borderRightColor: colors.border },\r\n        containerStyle,\r\n      ]}\r\n    >\r\n      {header !== undefined ? (\r\n        <View style={styles.slot}>{renderTextSlot(header, { color: colors.text })}</View>\r\n      ) : null}\r\n\r\n      {items.map((item) => {\r\n        const active = item.route === activeRoute;\r\n        const iconColor = active ? primaryColor : colors.textSecondary;\r\n        return (\r\n          <FocusableTouchable\r\n            key={item.key}\r\n            accessibilityHint={navigateHint(item.label)}\r\n            accessibilityLabel={item.label}\r\n            ringColor={primaryColor}\r\n            style={[styles.item, active ? { backgroundColor: colors.border } : undefined]}\r\n            testID={item.testID ?? item.key}\r\n            onPress={() => onNavigate(item.route)}\r\n          >\r\n            {typeof item.renderIcon === 'function' ? (\r\n              item.renderIcon(iconColor, COLLAPSED_ICON_SIZE)\r\n            ) : (\r\n              <Text style={[styles.glyph, { color: iconColor }]}>{glyphFor(item.label)}</Text>\r\n            )}\r\n          </FocusableTouchable>\r\n        );\r\n      })}\r\n\r\n      <View style={styles.spacer} />\r\n\r\n      {footer !== undefined ? (\r\n        <View style={styles.slot}>{renderTextSlot(footer, { color: colors.text })}</View>\r\n      ) : null}\r\n    </View>\r\n  );\r\n};\r\n\r\nexport default CollapsedRail;\r\n","/**\n * NavShell — the ONE first-class navigation shell that renders a **top bar**, a\n * **side rail**, or **BOTH together**, chosen by a single `layout` prop\n * (`'top' | 'side' | 'both'`). It is the shell-level answer to `Nav`'s\n * single-axis question: where `Nav` returns one element (a `NavBar` OR a\n * `Sidebar`), `NavShell` owns the whole page composition — it wires a top bar\n * into `AppShell`'s `header` slot and a side rail into `AppShell`'s `sidebar`\n * slot, and inherits every `AppShell` capability (auth gate, loading / error /\n * forbidden state cards, width discipline, banner, the responsive\n * hamburger + overlay drawer for the rail).\n *\n *   layout=\"top\"   → a horizontal top bar only (brand + links + overflow \"…\" + right).\n *   layout=\"side\"  → a header + a persistent left rail of sections (the erevna / katalogos shape).\n *   layout=\"both\"  → a top bar (brand / global links + overflow \"…\" / user) AND a side rail\n *                    (sections), together — the AML-console shape, now first-class.\n *\n * \"both\" is inherently a shell composition (a top region + a side region + a\n * content column), which a single-element `Nav` cannot own; `NavShell` is that\n * composition, so no app hand-wires `Topbar` + `Sidebar` + a `ScrollView` row\n * again. Customizability is STYLE-only: every colour flows through the\n * `@dloizides/ui-feedback` UiProvider theme, and brand / user / language /\n * notification / section content are render slots. Structure + behaviour are\n * shared.\n *\n * Contract discipline (same as the rest of `@dloizides/ui-nav`): NO FM, router,\n * icon-set, or store imports. Labels are pre-localized strings, icons are render\n * slots, and every colour is read from the theme.\n */\nimport React from 'react';\n\nimport type { ViewStyle } from 'react-native';\n\nimport type { UiTheme } from '@dloizides/ui-feedback';\n\nimport { AppShell, type AppShellProps } from './AppShell';\nimport { CollapsedRail } from './CollapsedRail';\nimport { NavBar } from './NavBar';\nimport type { CollapsedRailRange } from './railMode';\nimport { Sidebar, type SidebarPaletteTriggerConfig, type SidebarSearchConfig } from './Sidebar';\nimport type { NavItem } from './types';\n\n/** Which regions the shell renders: a top bar, a side rail, or both together. */\nexport type NavShellLayout = 'top' | 'side' | 'both';\n\n/**\n * Config for the TOP bar (rendered as a `NavBar` in `AppShell`'s header slot).\n * Used when `layout` is `'top'` or `'both'`. Every field is optional except the\n * items — an empty `items` array renders a bar with just the brand + right slots\n * (a plain top bar with no nav links), which is the natural `'side'`-mode header.\n */\nexport interface NavShellTopBar {\n  /** Top-bar nav entries (global links). Empty ⇒ brand + right only. */\n  items: NavItem[];\n  /** Left slot — typically the tenant brand / logo. */\n  brand?: React.ReactNode;\n  /** Right slot — free-form (language toggle, notification bell, user chip, logout). */\n  right?: React.ReactNode;\n  /** Collapse the links behind a hamburger below this viewport width (default 760). */\n  collapseBelow?: number;\n  /** Localized visible + accessible label for the \"More ▾\" overflow trigger (default \"More\"). */\n  overflowLabel?: string;\n  /** Localized accessibility hint for the overflow trigger. */\n  overflowHint?: string;\n  /** Localized accessibility label for the responsive menu toggle. */\n  menuLabel?: string;\n  /** Localized accessibility hint for the responsive menu toggle. */\n  menuHint?: string;\n  /** Optional custom glyph renderer for the responsive toggle; defaults to ☰. */\n  renderMenuIcon?: (color: string, open: boolean) => React.ReactNode;\n  /**\n   * Extra container style overrides (e.g. an app-specific appbar background —\n   * including a web `background`/`backgroundImage` gradient cast through\n   * `ViewStyle`, the AML radial-glow appbar). Style-only.\n   */\n  containerStyle?: ViewStyle | ViewStyle[];\n  /**\n   * Optional content-column cap (px) for the top bar. When set, the bar's\n   * background + bottom border (from `containerStyle` / `barTheme`) stay FULL WIDTH\n   * (full-bleed) while the inner brand + links + right row is capped to this width\n   * and centred — the AML v1-console appbar shape. Forwarded to `NavBar.contentMaxWidth`.\n   */\n  contentMaxWidth?: number;\n  /**\n   * Optional CHROME theme override for the top bar only (dark bar over a light\n   * page). Forwarded to `NavBar.barTheme`. Style-only — see `NavBar`.\n   */\n  barTheme?: UiTheme;\n}\n\n/**\n * Config for the intermediate COLLAPSED (icon-only) rail — opts the side layout\n * into a THREE-tier responsive scheme (full rail → collapsed rail → drawer). When\n * present, NavShell builds a `<CollapsedRail>` and hands it to `AppShell` for the\n * tablet band; omit it and the layout stays two-tier.\n */\nexport interface NavShellCollapsedRail {\n  /** Items for the icon rail. Defaults to the full rail's `items`. */\n  items?: NavItem[];\n  /** Optional header slot (e.g. a home shortcut). */\n  header?: React.ReactNode;\n  /** Optional footer slot (dark-mode toggle, logout). */\n  footer?: React.ReactNode;\n  /** The `[min, max)` viewport band for the collapsed rail (default `{ min: 768, max: 1024 }`). */\n  range?: CollapsedRailRange;\n}\n\n/**\n * Config for the SIDE rail (rendered as a `Sidebar` in `AppShell`'s sidebar\n * slot). Used when `layout` is `'side'` or `'both'`.\n */\nexport interface NavShellSideRail {\n  /** Side-rail nav entries (sections — leaf + expandable). */\n  items: NavItem[];\n  /** Localized menu title (heading). */\n  title: string;\n  /** Optional header slot rendered above the items (e.g. a Home shortcut). */\n  header?: React.ReactNode;\n  /** Optional footer slot rendered after a flex spacer (dark-mode toggle, logout). */\n  footer?: React.ReactNode;\n  /** a11y hint shown when an expandable section is collapsed. */\n  expandHint?: string;\n  /** a11y hint shown when an expandable section is expanded. */\n  collapseHint?: string;\n  /** Optional chevron renderer for expandable sections. */\n  renderChevron?: (expanded: boolean, color: string, size: number) => React.ReactNode;\n  /** Extra container style overrides. */\n  containerStyle?: ViewStyle | ViewStyle[];\n  /** Optional collapsed (icon-only) rail config → the intermediate tablet tier. */\n  collapsed?: NavShellCollapsedRail;\n  /**\n   * Opt the inner `Sidebar` into its persistent desktop inline-search field.\n   * Requires `search` labels; when omitted the rail renders exactly as before.\n   * The ⌘K palette remains the search affordance on narrow viewports\n   * (see {@link resolveSearchAffordance}). Forwarded to `Sidebar.enableInlineSearch`.\n   */\n  enableInlineSearch?: boolean;\n  /** Pre-localized inline-search strings — required for `enableInlineSearch`. Forwarded to `Sidebar.search`. */\n  search?: SidebarSearchConfig;\n  /**\n   * Opt the inner `Sidebar` into the ⌘K palette trigger as its narrow-viewport\n   * search affordance. Mutually exclusive with the inline field by viewport width\n   * (never both shown). Forwarded to `Sidebar.paletteTrigger`.\n   */\n  paletteTrigger?: SidebarPaletteTriggerConfig;\n  /** Controlled search query (optional — the Sidebar owns the state when omitted). Forwarded to `Sidebar.searchQuery`. */\n  searchQuery?: string;\n  /** Called on each query change (controlled or internal). Forwarded to `Sidebar.onSearchChange`. */\n  onSearchChange?: (query: string) => void;\n}\n\n/**\n * `AppShell` props NavShell forwards straight through. It composes the `header`\n * and `sidebar` (+ `collapsedSidebar`) regions itself, so those are handled here;\n * everything else — including the optional `nav` strip (e.g. a `PillNav`), the\n * auth gate, state cards, banner, and width policy — passes through untouched.\n */\ntype ForwardedShellProps = Omit<AppShellProps, 'header' | 'sidebar' | 'children'>;\n\nexport interface NavShellProps extends ForwardedShellProps {\n  /** Which regions to render: a top bar, a side rail, or both. */\n  layout: NavShellLayout;\n  /** Current active route/path — drives active highlighting on both regions. */\n  pathname: string;\n  /** Navigation callback — receives a `NavItem.route`. */\n  onNavigate: (route: string) => void;\n  /** Localized accessibility label for the navigation landmark(s). */\n  regionLabel: string;\n  /** a11y hint for a nav item, given its label. Defaults to the label. */\n  navigateHint?: (label: string) => string;\n  /**\n   * Top-bar config → a `NavBar` in the header slot. Required for `'top'` /\n   * `'both'`; **ignored for `'side'`** — `layout` decides which regions exist, so\n   * a `'side'` app that also wants a bar asks for `layout=\"both\"`. A `'side'` app\n   * that wants its OWN header node uses the `header` escape hatch instead.\n   */\n  topBar?: NavShellTopBar;\n  /**\n   * Escape hatch: a ready-made header node (e.g. an app-composed `<Topbar>`).\n   * When supplied it REPLACES the `topBar`-built `NavBar` — used by `'side'`\n   * apps that want the structured `Topbar` (language / notification / user\n   * slots) instead of a `NavBar` header.\n   */\n  header?: React.ReactNode;\n  /**\n   * Side-rail config → a `Sidebar` in the sidebar slot. Required for `'side'` /\n   * `'both'`; ignored for `'top'`.\n   */\n  sideRail?: NavShellSideRail;\n  children: React.ReactNode;\n}\n\n/**\n * Should the top bar render? Yes for `'top'`/`'both'`, or when an explicit\n * `header` NODE is supplied.\n *\n * `layout` is the AUTHORITY over which regions exist: a `topBar` **config** is\n * the content of the top region, never the decision to have one, so passing a\n * `topBar` with `layout=\"side\"` renders NO top bar (use `'both'` — that is what\n * a rail plus a bar means). Before 1.10.0 an extra `layout === 'side' && hasTopBar`\n * clause made `'side'` + a `topBar` render identically to `'both'`, so `layout`\n * stopped being observable.\n *\n * `hasHeader` is a DIFFERENT concern and is deliberately kept: `header` is the\n * documented escape hatch by which a `'side'` app supplies its own ready-made\n * header node (the structured `Topbar` with language / notification / user slots)\n * instead of a `NavBar`. It is an explicit \"render THIS node in the header slot\",\n * not a config whose mere presence is read as an orientation change — and four\n * portals (erevna, katalogos, zygos, agora) depend on it.\n */\nfunction wantsTopBar(layout: NavShellLayout, hasHeader: boolean): boolean {\n  return layout === 'top' || layout === 'both' || hasHeader;\n}\n\n/** Should the side rail render? Yes for `'side'`/`'both'` (when a rail is configured). */\nfunction wantsSideRail(layout: NavShellLayout, hasSideRail: boolean): boolean {\n  return (layout === 'side' || layout === 'both') && hasSideRail;\n}\n\nexport const NavShell = ({\n  layout,\n  pathname,\n  onNavigate,\n  regionLabel,\n  navigateHint,\n  topBar,\n  header,\n  sideRail,\n  children,\n  collapsedSidebar: collapsedSidebarProp,\n  collapsedRailRange: collapsedRailRangeProp,\n  ...shellProps\n}: NavShellProps): React.ReactElement | null => {\n  const showTopBar = wantsTopBar(layout, header !== undefined);\n  const showSideRail = wantsSideRail(layout, sideRail !== undefined);\n\n  // Header region: an app-supplied node wins; otherwise build a NavBar from topBar.\n  const headerNode: React.ReactNode =\n    header !== undefined\n      ? header\n      : showTopBar && topBar !== undefined\n        ? (\n            <NavBar\n              barTheme={topBar.barTheme}\n              brand={topBar.brand}\n              collapseBelow={topBar.collapseBelow}\n              containerStyle={topBar.containerStyle}\n              contentMaxWidth={topBar.contentMaxWidth}\n              items={topBar.items}\n              menuHint={topBar.menuHint}\n              menuLabel={topBar.menuLabel}\n              navigateHint={navigateHint}\n              overflowHint={topBar.overflowHint}\n              overflowLabel={topBar.overflowLabel}\n              pathname={pathname}\n              regionLabel={regionLabel}\n              renderMenuIcon={topBar.renderMenuIcon}\n              right={topBar.right}\n              onNavigate={onNavigate}\n            />\n          )\n        : null;\n\n  // Side-rail region: a Sidebar built from sideRail config.\n  const sidebarNode: React.ReactNode =\n    showSideRail && sideRail !== undefined ? (\n      <Sidebar\n        collapseHint={sideRail.collapseHint}\n        containerStyle={sideRail.containerStyle}\n        enableInlineSearch={sideRail.enableInlineSearch}\n        expandHint={sideRail.expandHint}\n        footer={sideRail.footer}\n        header={sideRail.header}\n        items={sideRail.items}\n        navigateHint={navigateHint}\n        paletteTrigger={sideRail.paletteTrigger}\n        pathname={pathname}\n        regionLabel={regionLabel}\n        renderChevron={sideRail.renderChevron}\n        search={sideRail.search}\n        searchQuery={sideRail.searchQuery}\n        title={sideRail.title}\n        onNavigate={onNavigate}\n        onSearchChange={sideRail.onSearchChange}\n      />\n    ) : undefined;\n\n  // Collapsed (tablet) rail: build a CollapsedRail from `sideRail.collapsed`\n  // config when present (config-driven, not hand-wired); otherwise fall back to a\n  // raw `collapsedSidebar` node the caller may have passed straight through.\n  const collapsedCfg = showSideRail ? sideRail?.collapsed : undefined;\n  const collapsedNode: React.ReactNode =\n    collapsedCfg !== undefined && sideRail !== undefined ? (\n      <CollapsedRail\n        footer={collapsedCfg.footer}\n        header={collapsedCfg.header}\n        items={collapsedCfg.items ?? sideRail.items}\n        navigateHint={navigateHint}\n        pathname={pathname}\n        regionLabel={regionLabel}\n        onNavigate={onNavigate}\n      />\n    ) : (\n      collapsedSidebarProp\n    );\n  const collapsedRange = collapsedCfg?.range ?? collapsedRailRangeProp;\n\n  return (\n    <AppShell\n      {...shellProps}\n      collapsedRailRange={collapsedRange}\n      collapsedSidebar={collapsedNode}\n      header={headerNode}\n      sidebar={sidebarNode}\n    >\n      {children}\n    </AppShell>\n  );\n};\n\nexport default NavShell;\n","/**\n * PillNav — a horizontal row of fully-rounded \"pills\", the cross-navigation\n * switcher promoted from kefi's coral dashboard nav. It renders the same\n * caller-supplied `NavItem[]` as the other nav components, as pills that wrap,\n * with the active route wearing the accent pill.\n *\n * It also folds in kefi's **visibility rule**: the whole nav hides (renders\n * `null`) unless there are at least `minItems` entries — a single destination is\n * not worth a switcher. Default `minItems` is 1 (always show when there is at\n * least one item); kefi passes `2`.\n *\n * \"Coral pills\" is STYLE, not structure: the accent colour is the theme\n * `palette.primary` (kefi's coral), the resting pill is `surfaceElevated`, and\n * `containerStyle` / theme tokens carry any per-app tweak — no layout fork.\n *\n * Contract discipline (same as the rest of `@dloizides/ui-nav`): NO FM, router,\n * icon-set, or store imports. Labels are pre-localized strings, icons are render\n * slots, and every colour is read from the `@dloizides/ui-feedback` theme.\n */\nimport React from 'react';\n\nimport { Text, View, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { FocusableTouchable } from './FocusableTouchable';\nimport { resolveActiveRoute } from './isRouteActive';\nimport { NAV_ICON_SIZE, pillNavStyles as styles } from './styles';\nimport type { NavItem } from './types';\n\n/** Ink for a pill sitting on the accent (active) background — full-contrast white. */\nconst TEXT_ON_PRIMARY = '#ffffff';\n/** Default minimum item count to show the switcher (kefi passes 2). */\nconst DEFAULT_MIN_ITEMS = 1;\n\nexport interface PillNavProps {\n  /** Nav entries — the cross-navigation destinations. */\n  items: NavItem[];\n  /** Current active route/path. */\n  pathname: string;\n  /** Navigation callback — receives a `NavItem.route`. */\n  onNavigate: (route: string) => void;\n  /** Localized accessibility label for the navigation landmark. */\n  regionLabel: string;\n  /** a11y hint for a pill, given its label. Defaults to the label. */\n  navigateHint?: (label: string) => string;\n  /**\n   * Hide the whole switcher unless there are at least this many items. Default 1\n   * (show when non-empty); kefi passes 2 (a lone dashboard needs no switcher).\n   */\n  minItems?: number;\n  /** Extra container style overrides. */\n  containerStyle?: ViewStyle | ViewStyle[];\n}\n\nexport const PillNav = ({\n  items,\n  pathname,\n  onNavigate,\n  regionLabel,\n  navigateHint = (label) => label,\n  minItems = DEFAULT_MIN_ITEMS,\n  containerStyle,\n}: PillNavProps): React.ReactElement | null => {\n  const { theme } = useUi();\n  const colors = theme.colors;\n  const primaryColor = theme.palette.primary['500'];\n\n  if (items.length < minItems) return null;\n\n  // Most-specific-wins: only the longest matching route wears the accent pill, so a\n  // module-home pill never co-activates with a deeper sibling on a nested path.\n  const activeRoute = resolveActiveRoute(items, pathname);\n\n  return (\n    <View\n      accessibilityRole=\"none\"\n      aria-label={regionLabel}\n      role=\"navigation\"\n      style={[styles.container, containerStyle]}\n    >\n      {items.map((item) => {\n        const active = item.route === activeRoute;\n        const textColor = active ? TEXT_ON_PRIMARY : colors.textSecondary;\n        const pillStyle: ViewStyle = active\n          ? { backgroundColor: primaryColor }\n          : { backgroundColor: colors.surfaceElevated };\n        return (\n          <FocusableTouchable\n            key={item.key}\n            accessibilityHint={navigateHint(item.label)}\n            accessibilityLabel={item.label}\n            accessibilityRole=\"link\"\n            ringColor={primaryColor}\n            style={[styles.pill, pillStyle]}\n            testID={item.testID ?? item.key}\n            onPress={() => onNavigate(item.route)}\n          >\n            {typeof item.renderIcon === 'function' ? item.renderIcon(textColor, NAV_ICON_SIZE) : null}\n            <Text style={[styles.pillText, { color: textColor }]}>{item.label}</Text>\n          </FocusableTouchable>\n        );\n      })}\n    </View>\n  );\n};\n\nexport default PillNav;\n","/**\n * DarkModeControl — the shared colour-scheme control promoted from erevna /\n * katalogos (their Light / Dark / System toggle + the icon-only \"cycle\" button).\n * It is a CONTROLLED component: the app owns the current `value` and applies the\n * chosen scheme; this component only renders the choices and reports changes.\n *\n * Two variants encode the two behaviours the apps shipped:\n *   - `\"segmented\"` (default): a row of segments (Light / Dark / System), the\n *     active one highlighted — the desktop control.\n *   - `\"cycle\"`: a single icon+label button that advances to the NEXT option on\n *     each press (wrapping) — the compact mobile control.\n *\n * The options are pre-localized (`label` + `hint`) and value-agnostic (a string),\n * so the app maps its own `DarkModePreference` enum to strings without this\n * package importing it. Every colour flows through the `@dloizides/ui-feedback`\n * theme; STYLE is the only per-app variation.\n */\nimport React, { useCallback } from 'react';\n\nimport { Text, View, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { FocusableTouchable } from './FocusableTouchable';\nimport { darkModeStyles as styles } from './styles';\n\n/** Ink for the active (accent-filled) segment / cycle button. */\nconst TEXT_ON_PRIMARY = '#ffffff';\n/** Icon size for a dark-mode option. */\nconst DARK_MODE_ICON_SIZE = 16;\n\n/** Which control shape to render. */\nexport type DarkModeVariant = 'segmented' | 'cycle';\n\n/** One pre-localized colour-scheme choice (e.g. Light / Dark / System). */\nexport interface DarkModeOption {\n  /** App-defined value (its own preference enum mapped to a string). */\n  value: string;\n  /** Localized visible + accessible label. */\n  label: string;\n  /** Localized accessibility hint. */\n  hint: string;\n  /** Optional leading icon. Receives the resolved colour + size. */\n  renderIcon?: (color: string, size: number) => React.ReactNode;\n}\n\nexport interface DarkModeControlProps {\n  /** Current selected value — must match one of `options[].value`. */\n  value: string;\n  /** The pre-localized choices (typically Light / Dark / System). */\n  options: DarkModeOption[];\n  /** Change callback — receives the newly-selected value. */\n  onChange: (value: string) => void;\n  /** Localized accessibility label for the control group. */\n  regionLabel: string;\n  /** Control shape — a segmented row (default) or a single cycling button. */\n  variant?: DarkModeVariant;\n  /** testID for the control; segments are `${testID}-${value}`. */\n  testID?: string;\n  /** Extra container style overrides. */\n  containerStyle?: ViewStyle | ViewStyle[];\n}\n\nexport const DarkModeControl = ({\n  value,\n  options,\n  onChange,\n  regionLabel,\n  variant = 'segmented',\n  testID,\n  containerStyle,\n}: DarkModeControlProps): React.ReactElement | null => {\n  const { theme } = useUi();\n  const colors = theme.colors;\n  const primaryColor = theme.palette.primary['500'];\n\n  const currentIndex = options.findIndex((option) => option.value === value);\n  const current = currentIndex >= 0 ? options[currentIndex] : options[0];\n\n  const advance = useCallback(() => {\n    if (options.length === 0) return;\n    const from = currentIndex >= 0 ? currentIndex : 0;\n    const next = options[(from + 1) % options.length];\n    if (next !== undefined) onChange(next.value);\n  }, [options, currentIndex, onChange]);\n\n  if (options.length === 0 || current === undefined) return null;\n\n  if (variant === 'cycle') {\n    const iconColor = colors.text;\n    return (\n      <View aria-label={regionLabel} style={containerStyle}>\n        <FocusableTouchable\n          accessibilityHint={current.hint}\n          accessibilityLabel={current.label}\n          ringColor={primaryColor}\n          style={[styles.cycle, { backgroundColor: colors.surfaceElevated }]}\n          testID={testID}\n          onPress={advance}\n        >\n          {typeof current.renderIcon === 'function' ? current.renderIcon(iconColor, DARK_MODE_ICON_SIZE) : null}\n          <Text style={[styles.cycleText, { color: colors.text }]}>{current.label}</Text>\n        </FocusableTouchable>\n      </View>\n    );\n  }\n\n  return (\n    <View\n      aria-label={regionLabel}\n      role=\"group\"\n      style={[styles.segmentRow, { borderColor: colors.border }, containerStyle]}\n    >\n      {options.map((option) => {\n        const active = option.value === value;\n        const textColor = active ? TEXT_ON_PRIMARY : colors.textSecondary;\n        return (\n          <FocusableTouchable\n            key={option.value}\n            accessibilityHint={option.hint}\n            accessibilityLabel={option.label}\n            ringColor={primaryColor}\n            style={[styles.segment, active ? { backgroundColor: primaryColor } : undefined]}\n            testID={testID !== undefined ? `${testID}-${option.value}` : undefined}\n            onPress={() => onChange(option.value)}\n          >\n            {typeof option.renderIcon === 'function' ? option.renderIcon(textColor, DARK_MODE_ICON_SIZE) : null}\n            <Text style={[styles.segmentText, { color: textColor }]}>{option.label}</Text>\n          </FocusableTouchable>\n        );\n      })}\n    </View>\n  );\n};\n\nexport default DarkModeControl;\n","/**\n * Pure matching logic for the {@link CommandPalette}. Kept framework-free so the\n * ranking/filtering is unit-testable without rendering: a command matches when\n * every whitespace-separated token of the query appears (case-insensitively) in\n * its haystack (label + hint + keywords). Requiring ALL tokens lets an operator\n * narrow with \"pay dash\" the way a fuzzy launcher would, without a fuzzy lib.\n */\nimport type React from 'react';\n\n/** One actionable destination/command shown in the palette. */\nexport interface CommandItem {\n  /** Stable key + default testID. */\n  key: string;\n  /** Optional testID override (defaults to `key`). */\n  testID?: string;\n  /** Localized display label (what the operator reads). */\n  label: string;\n  /** Optional localized secondary line (e.g. the module it lives in). */\n  hint?: string;\n  /** Optional extra search terms not shown but matched (synonyms, route words). */\n  keywords?: readonly string[];\n  /** Invoked when the item is chosen (the consumer navigates / runs the action). */\n  onSelect: () => void;\n  /** Optional leading icon slot, same contract as `NavItem.renderIcon`. */\n  renderIcon?: (color: string, size: number) => React.ReactNode;\n}\n\n/** The searchable text for one command, lower-cased once. */\nfunction haystack(item: CommandItem): string {\n  return [item.label, item.hint ?? '', ...(item.keywords ?? [])].join(' ').toLowerCase();\n}\n\n/**\n * Filter `items` to those matching `query`. An empty/whitespace query returns\n * the list unchanged (the palette opens showing everything). Order is preserved\n * — the caller supplies items in a meaningful order (nav order).\n */\nexport function filterCommands(items: readonly CommandItem[], query: string): CommandItem[] {\n  const tokens = query.trim().toLowerCase().split(/\\s+/).filter(Boolean);\n  if (tokens.length === 0) return [...items];\n  return items.filter((item) => {\n    const hay = haystack(item);\n    return tokens.every((token) => hay.includes(token));\n  });\n}\n","/**\n * CommandPalette — the shared ⌘K launcher for `@dloizides/ui-nav`. An overlay\n * (scrim + centred panel) with a search input over a keyboard-navigable list of\n * {@link CommandItem}s — jump to any nav destination (or run any action) without\n * hunting the rail. Web-first (RN-web), but degrades safely: when `open` is\n * false it renders nothing.\n *\n * Package discipline (as the rest of ui-nav): NO FM / router / store / icon-set\n * imports. Labels are pre-localized strings; icons are render slots; every colour\n * comes from the `@dloizides/ui-feedback` UiProvider theme. The consumer owns the\n * `open` state (pair with {@link useCommandPaletteHotkey}) and each item's\n * `onSelect` (navigate / run) — the palette just closes after a choice.\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport {\n  Pressable,\n  ScrollView,\n  StyleSheet,\n  Text,\n  TextInput,\n  View,\n  type NativeSyntheticEvent,\n  type TextInputKeyPressEventData,\n} from 'react-native';\n\nimport { Z_INDEX } from '@dloizides/design-tokens';\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { filterCommands, type CommandItem } from './commandPaletteFilter';\nimport { NAV_ICON_SIZE } from './styles';\n\nconst SCRIM_COLOR = 'rgba(0, 0, 0, 0.5)';\nconst OVERLAY_Z_INDEX = Z_INDEX.palette;\nconst PANEL_MAX_WIDTH = 560;\nconst PANEL_TOP_OFFSET = 88;\nconst LIST_MAX_HEIGHT = 360;\nconst KEY_DOWN = 'ArrowDown';\nconst KEY_UP = 'ArrowUp';\nconst KEY_ENTER = 'Enter';\nconst KEY_ESCAPE = 'Escape';\n\n/** Pre-localized labels for the palette chrome. */\nexport interface CommandPaletteLabels {\n  /** Search input placeholder. */\n  placeholder: string;\n  /** Accessible name of the scrim (tap to close). */\n  closeLabel: string;\n  /** Accessible hint of the scrim (tap to close). */\n  closeHint: string;\n  /** Shown when the query matches nothing. */\n  emptyText: string;\n  /** Accessible label for the palette dialog landmark. */\n  regionLabel: string;\n}\n\nexport interface CommandPaletteProps {\n  /** Whether the palette overlay is shown. */\n  open: boolean;\n  /** The commands to search over, in a meaningful (nav) order. */\n  items: readonly CommandItem[];\n  /** Close the palette (scrim tap / Escape / after a selection). */\n  onClose: () => void;\n  /** Pre-localized chrome labels. */\n  labels: CommandPaletteLabels;\n  /** testID for the panel (defaults to `command-palette`). */\n  testID?: string;\n}\n\nconst styles = StyleSheet.create({\n  overlay: { ...StyleSheet.absoluteFillObject, zIndex: OVERLAY_Z_INDEX, alignItems: 'center' },\n  scrim: { ...StyleSheet.absoluteFillObject, backgroundColor: SCRIM_COLOR },\n  panel: {\n    marginTop: PANEL_TOP_OFFSET,\n    width: '92%',\n    maxWidth: PANEL_MAX_WIDTH,\n    borderRadius: 12,\n    borderWidth: 1,\n    overflow: 'hidden',\n  },\n  input: { fontSize: 16, paddingHorizontal: 16, paddingVertical: 14, borderBottomWidth: 1 },\n  list: { maxHeight: LIST_MAX_HEIGHT },\n  row: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 12, columnGap: 10 },\n  rowText: { flex: 1 },\n  rowLabel: { fontSize: 15, fontWeight: '600' },\n  rowHint: { fontSize: 12, marginTop: 2 },\n  empty: { paddingHorizontal: 16, paddingVertical: 20, fontSize: 14 },\n});\n\ninterface PaletteRowProps {\n  item: CommandItem;\n  selected: boolean;\n  onChoose: (item: CommandItem) => void;\n}\n\n/** One result row — highlighted when it is the active (keyboard) selection. */\nconst PaletteRow = ({ item, selected, onChoose }: PaletteRowProps): React.ReactElement => {\n  const { theme } = useUi();\n  const colors = theme.colors;\n  return (\n    <Pressable\n      accessibilityHint={item.hint}\n      accessibilityLabel={item.label}\n      accessibilityRole=\"button\"\n      accessibilityState={{ selected }}\n      style={[styles.row, selected ? { backgroundColor: colors.border } : undefined]}\n      testID={item.testID ?? item.key}\n      onPress={() => onChoose(item)}\n    >\n      {typeof item.renderIcon === 'function' ? item.renderIcon(colors.textSecondary, NAV_ICON_SIZE) : null}\n      <View style={styles.rowText}>\n        <Text style={[styles.rowLabel, { color: colors.text }]}>{item.label}</Text>\n        {item.hint ? <Text style={[styles.rowHint, { color: colors.textSecondary }]}>{item.hint}</Text> : null}\n      </View>\n    </Pressable>\n  );\n};\n\n/** The overlay palette. Renders null when closed. */\nexport const CommandPalette = ({ open, items, onClose, labels, testID }: CommandPaletteProps): React.ReactElement | null => {\n  const { theme } = useUi();\n  const colors = theme.colors;\n  const [query, setQuery] = useState('');\n  const [selected, setSelected] = useState(0);\n  const inputRef = useRef<TextInput | null>(null);\n\n  const results = useMemo(() => filterCommands(items, query), [items, query]);\n\n  // Reset + focus each time the palette opens; clamp the selection as results shrink.\n  useEffect(() => {\n    if (!open) return;\n    setQuery('');\n    setSelected(0);\n    inputRef.current?.focus();\n  }, [open]);\n  useEffect(() => {\n    setSelected((prev) => Math.min(prev, Math.max(0, results.length - 1)));\n  }, [results.length]);\n\n  const choose = useCallback(\n    (item: CommandItem) => {\n      item.onSelect();\n      onClose();\n    },\n    [onClose],\n  );\n\n  const onKeyPress = useCallback(\n    (event: NativeSyntheticEvent<TextInputKeyPressEventData>) => {\n      const key = event.nativeEvent.key;\n      if (key === KEY_DOWN) setSelected((i) => Math.min(i + 1, results.length - 1));\n      else if (key === KEY_UP) setSelected((i) => Math.max(i - 1, 0));\n      else if (key === KEY_ESCAPE) onClose();\n      else if (key === KEY_ENTER && results[selected]) choose(results[selected]);\n    },\n    [results, selected, choose, onClose],\n  );\n\n  if (!open) return null;\n\n  return (\n    <View style={styles.overlay}>\n      <Pressable\n        accessibilityHint={labels.closeHint}\n        accessibilityLabel={labels.closeLabel}\n        accessibilityRole=\"button\"\n        style={styles.scrim}\n        testID={`${testID ?? 'command-palette'}-scrim`}\n        onPress={onClose}\n      />\n      <View\n        aria-modal\n        aria-label={labels.regionLabel}\n        role=\"dialog\"\n        style={[styles.panel, { backgroundColor: colors.surface, borderColor: colors.border }]}\n        testID={testID ?? 'command-palette'}\n      >\n        <TextInput\n          ref={inputRef}\n          accessibilityLabel={labels.placeholder}\n          placeholder={labels.placeholder}\n          placeholderTextColor={colors.textSecondary}\n          style={[styles.input, { color: colors.text, borderBottomColor: colors.border }]}\n          testID={`${testID ?? 'command-palette'}-input`}\n          value={query}\n          onChangeText={setQuery}\n          onKeyPress={onKeyPress}\n        />\n        {results.length === 0 ? (\n          <Text style={[styles.empty, { color: colors.textSecondary }]}>{labels.emptyText}</Text>\n        ) : (\n          <ScrollView keyboardShouldPersistTaps=\"handled\" style={styles.list}>\n            {results.map((item, index) => (\n              <PaletteRow key={item.key} item={item} selected={index === selected} onChoose={choose} />\n            ))}\n          </ScrollView>\n        )}\n      </View>\n    </View>\n  );\n};\n\nexport default CommandPalette;\n","/**\n * Binds the ⌘K / Ctrl-K launcher shortcut for {@link CommandPalette}. Web-only\n * (guards `document`), so it is a no-op under native RN and in SSR/tests without\n * a DOM. `preventDefault` stops the browser's own Ctrl-K (address-bar search) so\n * the palette wins. The consumer owns the open state; this only requests opening.\n */\nimport { useEffect } from 'react';\n\n/** The launcher key (with ⌘ on macOS or Ctrl elsewhere). */\nconst LAUNCH_KEY = 'k';\n\n/**\n * Call `onOpen` when the operator presses ⌘K (macOS) or Ctrl-K (Windows/Linux),\n * anywhere in the document. `enabled=false` unbinds (e.g. when the shell has no\n * palette configured), so the shortcut never fires without a handler behind it.\n */\nexport function useCommandPaletteHotkey(onOpen: () => void, enabled = true): void {\n  useEffect(() => {\n    if (!enabled || typeof document === 'undefined') return undefined;\n    const handler = (event: KeyboardEvent): void => {\n      const isLauncher = event.key.toLowerCase() === LAUNCH_KEY && (event.metaKey || event.ctrlKey);\n      if (!isLauncher) return;\n      event.preventDefault();\n      onOpen();\n    };\n    document.addEventListener('keydown', handler);\n    return () => document.removeEventListener('keydown', handler);\n  }, [onOpen, enabled]);\n}\n","/**\n * Role-gated nav helpers — build a `NavItem[]` from a user's roles, reusing the\n * existing `resolveAccessibleRoutes` from `@dloizides/auth-web` (the same helper\n * the multi-role dashboard nav uses) rather than reimplementing role filtering.\n *\n * The app supplies its ordered `RoleRouteTable` (role → route + optional\n * `labelKey`) and a `translate` fn (its `FM`); this returns the ordered set of\n * `NavItem`s the user's roles unlock — most privileged first, empty when none.\n */\nimport { resolveAccessibleRoutes } from '@dloizides/auth-web';\nimport type { RoleRoute, RoleRouteTable } from '@dloizides/auth-web';\n\nimport type { NavItem } from './types';\n\n/** The user shape `resolveAccessibleRoutes` accepts (derived — no extra dep). */\nexport type NavUser = Parameters<typeof resolveAccessibleRoutes>[0];\n\n/** Map already-resolved role routes to nav items, localizing each `labelKey`. */\nexport function roleRoutesToNavItems(\n  routes: RoleRoute[],\n  translate: (key: string) => string,\n): NavItem[] {\n  return routes.map((entry) => ({\n    key: entry.role,\n    route: entry.route,\n    label: entry.labelKey !== undefined ? translate(entry.labelKey) : entry.route,\n  }));\n}\n\n/**\n * Resolve the nav items a user can reach, in table (priority) order. Wraps\n * `resolveAccessibleRoutes` so role gating lives in one place.\n */\nexport function accessibleNavItems(\n  user: NavUser,\n  table: RoleRouteTable,\n  translate: (key: string) => string,\n): NavItem[] {\n  return roleRoutesToNavItems(resolveAccessibleRoutes(user, table), translate);\n}\n"]}