@digilogiclabs/saas-factory-ui 1.28.1 → 1.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -5257,15 +5257,28 @@ interface FlowTreeProps {
5257
5257
  hideControls?: boolean;
5258
5258
  /** Hide the breadcrumb legend at the bottom-left. */
5259
5259
  hideLegend?: boolean;
5260
+ /**
5261
+ * When > 0, cycles the focused path through the root's direct children
5262
+ * every N milliseconds until the user interacts with the tree (clicks a
5263
+ * card, pans, zooms, toggles a detail, or clicks a legend chip). Honors
5264
+ * `prefers-reduced-motion` (disabled if reduced motion is requested).
5265
+ * Default: 0 (disabled).
5266
+ */
5267
+ autoCycleMs?: number;
5268
+ /**
5269
+ * Explicit paths to cycle through when `autoCycleMs` is set. If omitted,
5270
+ * the tree auto-cycles through the root's direct children.
5271
+ */
5272
+ autoCyclePaths?: string[][];
5260
5273
  }
5261
- declare function FlowTree({ data, title, eyebrow, tagline, renderIcon: renderIconProp, tierColors: tierColorsProp, resolveHref: resolveHrefProp, layoutOptions, onNodeOpen, defaultFocusedPath, focusedPath: controlledPath, onFocusedPathChange, className, style, hideHeader, hideControls, hideLegend, }: FlowTreeProps): react_jsx_runtime.JSX.Element;
5274
+ declare function FlowTree({ data, title, eyebrow, tagline, renderIcon: renderIconProp, tierColors: tierColorsProp, resolveHref: resolveHrefProp, layoutOptions, onNodeOpen, defaultFocusedPath, focusedPath: controlledPath, onFocusedPathChange, className, style, hideHeader, hideControls, hideLegend, autoCycleMs, autoCyclePaths, }: FlowTreeProps): react_jsx_runtime.JSX.Element;
5262
5275
 
5263
5276
  /**
5264
5277
  * FlowTree CSS — injected once per page at runtime on the first mount.
5265
5278
  * Self-themed via `--ft-*` CSS variables, all with sensible fallbacks so the
5266
5279
  * component works standalone in any light or dark design system.
5267
5280
  */
5268
- declare const FLOW_TREE_CSS = "\n.ft-shell {\n --ft-bg: var(--ft-bg, oklch(0.185 0.008 80));\n --ft-fg: var(--ft-fg, oklch(0.96 0.005 85));\n --ft-muted-fg: var(--ft-muted-fg, oklch(0.68 0.008 80));\n --ft-dim-fg: var(--ft-dim-fg, oklch(0.5 0.008 80));\n --ft-line: var(--ft-line, oklch(0.28 0.008 80));\n --ft-line-strong: var(--ft-line-strong, oklch(0.4 0.008 80));\n --ft-grid-strong: var(--ft-grid-strong, oklch(0.24 0.008 80));\n --ft-card-bg: var(--ft-card-bg, oklch(0.21 0.008 80));\n --ft-card-active-bg: var(--ft-card-active-bg, oklch(0.25 0.015 60));\n --ft-card-hover-bg: var(--ft-card-hover-bg, oklch(0.23 0.01 80 / 0.6));\n --ft-rail-bg: var(--ft-rail-bg, oklch(0.19 0.008 80));\n --ft-icon-bg: var(--ft-icon-bg, oklch(0.17 0.008 80));\n --ft-detail-bg: var(--ft-detail-bg, oklch(0.16 0.008 80));\n --ft-header-bg: var(--ft-header-bg, linear-gradient(180deg, oklch(0.21 0.01 60) 0%, oklch(0.19 0.008 70) 100%));\n --ft-tier-orange: var(--ft-tier-orange, #f16c25);\n --ft-tier-teal: var(--ft-tier-teal, #5fb7b8);\n --ft-tier-blue: var(--ft-tier-blue, oklch(0.72 0.12 240));\n --ft-tier-amber: var(--ft-tier-amber, oklch(0.8 0.14 75));\n --ft-tier-green: var(--ft-tier-green, oklch(0.74 0.14 155));\n --ft-accent: var(--ft-accent, var(--ft-tier-orange));\n --ft-serif: var(--ft-serif, \"Instrument Serif\", Georgia, serif);\n --ft-sans: var(--ft-sans, \"Inter\", system-ui, sans-serif);\n --ft-mono: var(--ft-mono, \"JetBrains Mono\", ui-monospace, Menlo, monospace);\n\n display: flex;\n flex-direction: column;\n min-height: 0;\n background: var(--ft-bg);\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n overflow: hidden;\n color: var(--ft-fg);\n font-family: var(--ft-sans);\n font-size: 14px;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n box-shadow: 0 30px 60px -30px oklch(0 0 0 / 0.5);\n}\n.ft-shell * { box-sizing: border-box; }\n.ft-shell .ft-mono {\n font-family: var(--ft-mono);\n font-size: 11px;\n letter-spacing: 0.02em;\n}\n\n.ft-header {\n padding: 22px 28px 20px;\n border-bottom: 1px solid var(--ft-line);\n background: var(--ft-header-bg);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.ft-header__eyebrow {\n font-family: var(--ft-mono);\n font-size: 10.5px;\n letter-spacing: 0.22em;\n text-transform: uppercase;\n color: var(--ft-accent);\n}\n.ft-header__title {\n margin: 0;\n font-family: var(--ft-serif);\n font-weight: 400;\n font-size: 44px;\n line-height: 1;\n letter-spacing: -0.015em;\n color: var(--ft-fg);\n}\n.ft-header__tagline {\n margin: 6px 0 0;\n max-width: 76ch;\n color: var(--ft-muted-fg);\n font-size: 13px;\n}\n\n.ft-stage {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.ft-svg {\n display: block;\n width: 100%;\n height: 100%;\n background: transparent;\n cursor: grab;\n touch-action: none;\n user-select: none;\n}\n.ft-svg.is-dragging { cursor: grabbing; }\n\n.ft-controls {\n position: absolute;\n top: 14px;\n right: 14px;\n z-index: 5;\n display: flex;\n align-items: center;\n gap: 6px;\n background: oklch(0.2 0.008 80 / 0.94);\n border: 1px solid var(--ft-line-strong);\n padding: 5px 8px;\n backdrop-filter: blur(8px);\n border-radius: 2px;\n}\n.ft-controls button {\n font-family: var(--ft-mono);\n font-size: 12px;\n width: 26px;\n height: 26px;\n background: transparent;\n border: 1px solid var(--ft-line);\n color: var(--ft-fg);\n cursor: pointer;\n padding: 0;\n}\n.ft-controls button:hover { border-color: var(--ft-accent); }\n.ft-controls__reset {\n width: auto !important;\n padding: 0 10px !important;\n font-size: 9.5px !important;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n}\n.ft-controls__hint {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n color: var(--ft-muted-fg);\n letter-spacing: 0.04em;\n padding-left: 8px;\n margin-left: 2px;\n border-left: 1px solid var(--ft-line);\n}\n\n.ft-legend {\n position: absolute;\n left: 18px;\n bottom: 14px;\n z-index: 5;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-family: var(--ft-mono);\n font-size: 10px;\n color: var(--ft-muted-fg);\n background: oklch(0.2 0.008 80 / 0.88);\n border: 1px solid var(--ft-line);\n padding: 6px 10px;\n backdrop-filter: blur(6px);\n max-width: calc(100% - 220px);\n}\n.ft-legend__chip { display: inline-flex; align-items: center; gap: 6px; }\n.ft-legend__dot {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--ft-accent);\n}\n.ft-legend__sep { color: var(--ft-line-strong); margin: 0 2px; }\n\n.ft-edge { fill: none; transition: stroke 260ms, opacity 260ms; }\n.ft-edge--off {\n stroke: var(--ft-line);\n stroke-width: 1;\n opacity: 0.55;\n}\n.ft-edge--on {\n stroke: var(--ft-accent);\n stroke-width: 1.6;\n stroke-dasharray: 4 5;\n opacity: 1;\n animation: ftDashFlow 1.4s linear infinite;\n}\n@keyframes ftDashFlow { to { stroke-dashoffset: -36; } }\n\n.ft-card {\n --tier-local: var(--tier, var(--ft-line-strong));\n width: 100%;\n height: 100%;\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: stretch;\n background: var(--ft-card-bg);\n border: 1px solid var(--ft-line);\n border-left: 3px solid var(--tier-local);\n border-radius: 2px;\n transition:\n background 260ms cubic-bezier(.2,.8,.2,1),\n border-color 260ms, box-shadow 260ms,\n transform 260ms cubic-bezier(.2,.8,.2,1),\n filter 260ms, opacity 260ms, color 260ms;\n overflow: visible;\n animation: ftCardIn 320ms cubic-bezier(.2,.8,.2,1) backwards;\n}\n@keyframes ftCardIn {\n from { opacity: 0; transform: translateX(-6px); }\n to { opacity: 1; transform: translateX(0); }\n}\n.ft-card__main {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 10px;\n align-items: center;\n padding: 0 10px 0 12px;\n background: transparent;\n border: none;\n color: inherit;\n font-family: var(--ft-sans);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n min-width: 0;\n}\n.ft-card__main:hover { background: var(--ft-card-hover-bg); }\n.ft-card__icon {\n width: 24px;\n height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--tier-local);\n border: 1px solid var(--ft-line-strong);\n background: var(--ft-icon-bg);\n flex-shrink: 0;\n}\n.ft-card__body { display: flex; flex-direction: column; min-width: 0; gap: 1px; }\n.ft-card__label {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.15;\n color: var(--ft-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.ft-card__sub {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.02em;\n color: var(--ft-muted-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ft-card__lock { color: var(--ft-muted-fg); display: inline-flex; }\n.ft-card__caret {\n width: 18px;\n height: 18px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--ft-mono);\n font-size: 12px;\n color: var(--ft-muted-fg);\n border: 1px solid var(--ft-line);\n}\n.ft-card--active .ft-card__caret {\n color: var(--tier-local);\n border-color: var(--tier-local);\n}\n\n.ft-card__rail {\n display: flex;\n flex-direction: column;\n border-left: 1px solid var(--ft-line);\n background: var(--ft-rail-bg);\n}\n.ft-card__mini {\n flex: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n min-height: 20px;\n background: transparent;\n border: none;\n color: var(--ft-muted-fg);\n cursor: pointer;\n transition: background 150ms, color 150ms;\n border-bottom: 1px solid var(--ft-line);\n padding: 0;\n text-decoration: none;\n}\n.ft-card__mini:last-child { border-bottom: none; }\n.ft-card__mini:hover {\n background: oklch(0.23 0.01 80);\n color: var(--tier-local);\n}\n.ft-card__mini.is-on {\n color: var(--tier-local);\n background: oklch(0.23 0.01 80);\n}\n\n.ft-card--active {\n background: var(--ft-card-active-bg);\n box-shadow: 0 0 0 1px var(--tier-local), 0 14px 34px -16px oklch(0.5 0.18 50 / 0.55);\n transform: scale(1.02);\n}\n.ft-card--dim {\n filter: grayscale(0.85) brightness(0.82);\n opacity: 0.7;\n transform: scale(0.88);\n transform-origin: center left;\n}\n.ft-card--dim .ft-card__label { color: var(--ft-dim-fg); }\n.ft-card--dim:hover {\n filter: grayscale(0.3) brightness(0.96);\n opacity: 1;\n transform: scale(0.94);\n}\n.ft-card--cta {\n border-left-color: var(--ft-accent);\n background: linear-gradient(180deg, oklch(0.23 0.02 55) 0%, oklch(0.2 0.015 60) 100%);\n}\n.ft-card--root {\n border-left-color: var(--ft-accent);\n background: oklch(0.26 0.015 55);\n}\n.ft-card--root .ft-card__icon {\n color: var(--ft-accent);\n border-color: var(--ft-accent);\n}\n\n.ft-detail {\n position: relative;\n margin-top: 0;\n padding: 16px 18px 14px;\n background: var(--ft-detail-bg);\n border: 1px solid var(--ft-line-strong);\n border-left: 2px solid var(--ft-accent);\n border-radius: 3px;\n animation: ftDetailIn 220ms cubic-bezier(.2,.8,.2,1) backwards;\n color: var(--ft-fg);\n width: 320px;\n box-shadow: 0 18px 40px -8px rgba(0,0,0,0.6), 0 2px 8px rgba(0,0,0,0.4);\n}\n.ft-detail__head {\n display: flex;\n align-items: center;\n margin: -2px 28px 10px 0;\n}\n.ft-detail__title {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n}\n.ft-detail__close {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n color: var(--ft-muted-fg);\n cursor: pointer;\n padding: 0;\n transition: color 120ms, border-color 120ms, background 120ms;\n}\n.ft-detail__close:hover {\n color: var(--ft-fg);\n border-color: var(--ft-line-strong);\n background: oklch(0.22 0.008 80);\n}\n@keyframes ftDetailIn {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.ft-detail__lead {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.35;\n font-style: italic;\n padding-left: 10px;\n border-left: 2px solid var(--ft-accent);\n margin-bottom: 10px;\n}\n.ft-detail__body {\n margin: 0 0 10px;\n font-size: 12px;\n color: var(--ft-muted-fg);\n line-height: 1.5;\n}\n.ft-detail__bullets {\n margin: 0 0 10px;\n padding-left: 16px;\n font-size: 12px;\n color: var(--ft-fg);\n}\n.ft-detail__bullets li { margin-bottom: 3px; }\n.ft-detail__meta {\n margin: 0 0 10px;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.ft-detail__meta-row {\n display: grid;\n grid-template-columns: 96px 1fr;\n gap: 8px;\n font-size: 11px;\n}\n.ft-detail__meta-row dt {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n padding-top: 1px;\n}\n.ft-detail__meta-row dd { margin: 0; color: var(--ft-fg); }\n.ft-detail__actions {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n margin-top: 8px;\n}\n\n.ft-btn {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n padding: 7px 10px;\n background: transparent;\n color: var(--ft-fg);\n border: 1px solid var(--ft-line-strong);\n text-decoration: none;\n cursor: pointer;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n transition: border-color 150ms, background 150ms;\n}\n.ft-btn:hover { border-color: var(--ft-accent); }\n.ft-btn--primary {\n background: var(--ft-accent);\n color: oklch(0.18 0.01 50);\n border-color: var(--ft-accent);\n}\n\n@media (max-width: 760px) {\n .ft-header { padding: 16px 18px 14px; }\n .ft-header__title { font-size: 32px; }\n .ft-controls__hint { display: none; }\n .ft-legend { max-width: calc(100% - 24px); left: 10px; bottom: 10px; }\n}\n";
5281
+ declare const FLOW_TREE_CSS = "\n.ft-shell {\n --ft-bg: var(--ft-bg, oklch(0.185 0.008 80));\n --ft-fg: var(--ft-fg, oklch(0.96 0.005 85));\n --ft-muted-fg: var(--ft-muted-fg, oklch(0.68 0.008 80));\n --ft-dim-fg: var(--ft-dim-fg, oklch(0.5 0.008 80));\n --ft-line: var(--ft-line, oklch(0.28 0.008 80));\n --ft-line-strong: var(--ft-line-strong, oklch(0.4 0.008 80));\n --ft-grid-strong: var(--ft-grid-strong, oklch(0.24 0.008 80));\n --ft-card-bg: var(--ft-card-bg, oklch(0.21 0.008 80));\n --ft-card-active-bg: var(--ft-card-active-bg, oklch(0.25 0.015 60));\n --ft-card-hover-bg: var(--ft-card-hover-bg, oklch(0.23 0.01 80 / 0.6));\n --ft-rail-bg: var(--ft-rail-bg, oklch(0.19 0.008 80));\n --ft-icon-bg: var(--ft-icon-bg, oklch(0.17 0.008 80));\n --ft-detail-bg: var(--ft-detail-bg, oklch(0.16 0.008 80));\n --ft-header-bg: var(--ft-header-bg, linear-gradient(180deg, oklch(0.21 0.01 60) 0%, oklch(0.19 0.008 70) 100%));\n --ft-tier-orange: var(--ft-tier-orange, #f16c25);\n --ft-tier-teal: var(--ft-tier-teal, #5fb7b8);\n --ft-tier-blue: var(--ft-tier-blue, oklch(0.72 0.12 240));\n --ft-tier-amber: var(--ft-tier-amber, oklch(0.8 0.14 75));\n --ft-tier-green: var(--ft-tier-green, oklch(0.74 0.14 155));\n --ft-accent: var(--ft-accent, var(--ft-tier-orange));\n --ft-serif: var(--ft-serif, \"Instrument Serif\", Georgia, serif);\n --ft-sans: var(--ft-sans, \"Inter\", system-ui, sans-serif);\n --ft-mono: var(--ft-mono, \"JetBrains Mono\", ui-monospace, Menlo, monospace);\n\n display: flex;\n flex-direction: column;\n min-height: 0;\n background: var(--ft-bg);\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n overflow: hidden;\n color: var(--ft-fg);\n font-family: var(--ft-sans);\n font-size: 14px;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n box-shadow: 0 30px 60px -30px oklch(0 0 0 / 0.5);\n}\n.ft-shell * { box-sizing: border-box; }\n.ft-shell .ft-mono {\n font-family: var(--ft-mono);\n font-size: 11px;\n letter-spacing: 0.02em;\n}\n\n.ft-header {\n padding: 22px 28px 20px;\n border-bottom: 1px solid var(--ft-line);\n background: var(--ft-header-bg);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.ft-header__eyebrow {\n font-family: var(--ft-mono);\n font-size: 10.5px;\n letter-spacing: 0.22em;\n text-transform: uppercase;\n color: var(--ft-accent);\n}\n.ft-header__title {\n margin: 0;\n font-family: var(--ft-serif);\n font-weight: 400;\n font-size: 44px;\n line-height: 1;\n letter-spacing: -0.015em;\n color: var(--ft-fg);\n}\n.ft-header__tagline {\n margin: 6px 0 0;\n max-width: 76ch;\n color: var(--ft-muted-fg);\n font-size: 13px;\n}\n\n.ft-stage {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n background:\n radial-gradient(1000px 600px at 15% -10%, oklch(0.22 0.012 60 / 0.7), transparent 60%),\n radial-gradient(800px 500px at 110% 110%, oklch(0.2 0.02 200 / 0.35), transparent 65%);\n}\n\n.ft-svg {\n display: block;\n width: 100%;\n height: 100%;\n background: transparent;\n cursor: grab;\n touch-action: none;\n user-select: none;\n}\n.ft-svg.is-dragging { cursor: grabbing; }\n\n.ft-controls {\n position: absolute;\n top: 14px;\n right: 14px;\n z-index: 5;\n display: flex;\n align-items: center;\n gap: 6px;\n background: oklch(0.2 0.008 80 / 0.94);\n border: 1px solid var(--ft-line-strong);\n padding: 5px 8px;\n backdrop-filter: blur(8px);\n border-radius: 2px;\n}\n.ft-controls button {\n font-family: var(--ft-mono);\n font-size: 12px;\n width: 26px;\n height: 26px;\n background: transparent;\n border: 1px solid var(--ft-line);\n color: var(--ft-fg);\n cursor: pointer;\n padding: 0;\n}\n.ft-controls button:hover { border-color: var(--ft-accent); }\n.ft-controls__reset {\n width: auto !important;\n padding: 0 10px !important;\n font-size: 9.5px !important;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n}\n.ft-controls__hint {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n color: var(--ft-muted-fg);\n letter-spacing: 0.04em;\n padding-left: 8px;\n margin-left: 2px;\n border-left: 1px solid var(--ft-line);\n}\n\n.ft-legend {\n position: absolute;\n left: 18px;\n bottom: 14px;\n z-index: 5;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-family: var(--ft-mono);\n font-size: 10px;\n color: var(--ft-muted-fg);\n background: oklch(0.2 0.008 80 / 0.88);\n border: 1px solid var(--ft-line);\n padding: 6px 10px;\n backdrop-filter: blur(6px);\n max-width: calc(100% - 220px);\n}\n.ft-legend__chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 2px 6px;\n margin: -2px 0;\n background: transparent;\n border: none;\n color: inherit;\n font: inherit;\n letter-spacing: inherit;\n cursor: pointer;\n border-radius: 2px;\n transition: background 120ms, color 120ms;\n}\n.ft-legend__chip:hover {\n background: oklch(0.24 0.01 80);\n color: var(--ft-fg);\n}\n.ft-legend__chip:disabled {\n cursor: default;\n color: var(--ft-fg);\n}\n.ft-legend__chip:disabled:hover { background: transparent; }\n.ft-legend__dot {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--ft-accent);\n flex-shrink: 0;\n}\n.ft-legend__sep {\n color: var(--ft-line-strong);\n margin: 0 2px;\n pointer-events: none;\n user-select: none;\n}\n\n.ft-edge {\n fill: none;\n transition: stroke 260ms, opacity 260ms, stroke-width 260ms;\n}\n.ft-edge--off {\n stroke: var(--ft-line-strong);\n stroke-width: 1.1;\n stroke-dasharray: 2 4;\n opacity: 0.5;\n}\n.ft-edge--on {\n stroke: var(--ft-accent);\n stroke-width: 1.8;\n stroke-dasharray: 5 5;\n opacity: 1;\n filter: drop-shadow(0 0 4px var(--ft-accent));\n animation: ftDashFlow 1.4s linear infinite;\n}\n@keyframes ftDashFlow { to { stroke-dashoffset: -40; } }\n@media (prefers-reduced-motion: reduce) {\n .ft-edge--on { animation: none; }\n}\n\n.ft-card {\n --tier-local: var(--tier, var(--ft-line-strong));\n width: 100%;\n height: 100%;\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: stretch;\n background: var(--ft-card-bg);\n border: 1px solid var(--ft-line);\n border-left: 3px solid var(--tier-local);\n border-radius: 2px;\n transition:\n background 260ms cubic-bezier(.2,.8,.2,1),\n border-color 260ms, box-shadow 260ms,\n transform 260ms cubic-bezier(.2,.8,.2,1),\n filter 260ms, opacity 260ms, color 260ms;\n overflow: visible;\n animation: ftCardIn 320ms cubic-bezier(.2,.8,.2,1) backwards;\n}\n@keyframes ftCardIn {\n from { opacity: 0; transform: translateX(-6px); }\n to { opacity: 1; transform: translateX(0); }\n}\n.ft-card__main {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 10px;\n align-items: center;\n padding: 0 10px 0 12px;\n background: transparent;\n border: none;\n color: inherit;\n font-family: var(--ft-sans);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n min-width: 0;\n}\n.ft-card__main:hover { background: var(--ft-card-hover-bg); }\n.ft-card__icon {\n width: 24px;\n height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--tier-local);\n border: 1px solid var(--ft-line-strong);\n background: var(--ft-icon-bg);\n flex-shrink: 0;\n}\n.ft-card__body { display: flex; flex-direction: column; min-width: 0; gap: 1px; }\n.ft-card__label {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.15;\n color: var(--ft-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.ft-card__sub {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.02em;\n color: var(--ft-muted-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ft-card__lock { color: var(--ft-muted-fg); display: inline-flex; }\n.ft-card__caret {\n width: 18px;\n height: 18px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--ft-mono);\n font-size: 12px;\n color: var(--ft-muted-fg);\n border: 1px solid var(--ft-line);\n}\n.ft-card--active .ft-card__caret {\n color: var(--tier-local);\n border-color: var(--tier-local);\n}\n\n.ft-card__rail {\n display: flex;\n flex-direction: column;\n border-left: 1px solid var(--ft-line);\n background: var(--ft-rail-bg);\n}\n.ft-card__mini {\n flex: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n min-height: 20px;\n background: transparent;\n border: none;\n color: var(--ft-muted-fg);\n cursor: pointer;\n transition: background 150ms, color 150ms;\n border-bottom: 1px solid var(--ft-line);\n padding: 0;\n text-decoration: none;\n}\n.ft-card__mini:last-child { border-bottom: none; }\n.ft-card__mini:hover {\n background: oklch(0.23 0.01 80);\n color: var(--tier-local);\n}\n.ft-card__mini.is-on {\n color: var(--tier-local);\n background: oklch(0.23 0.01 80);\n}\n\n.ft-card--active {\n background: var(--ft-card-active-bg);\n box-shadow: 0 0 0 1px var(--tier-local), 0 14px 34px -16px oklch(0.5 0.18 50 / 0.55);\n transform: scale(1.02);\n}\n.ft-card--dim {\n filter: grayscale(0.85) brightness(0.82);\n opacity: 0.7;\n transform: scale(0.88);\n transform-origin: center left;\n}\n.ft-card--dim .ft-card__label { color: var(--ft-dim-fg); }\n.ft-card--dim:hover {\n filter: grayscale(0.3) brightness(0.96);\n opacity: 1;\n transform: scale(0.94);\n}\n.ft-card--cta {\n border-left-color: var(--ft-accent);\n background: linear-gradient(180deg, oklch(0.23 0.02 55) 0%, oklch(0.2 0.015 60) 100%);\n}\n.ft-card--root {\n border-left-color: var(--ft-accent);\n background: oklch(0.26 0.015 55);\n}\n.ft-card--root .ft-card__icon {\n color: var(--ft-accent);\n border-color: var(--ft-accent);\n}\n\n.ft-detail {\n position: relative;\n margin-top: 0;\n padding: 16px 18px 14px;\n background: var(--ft-detail-bg);\n border: 1px solid var(--ft-line-strong);\n border-left: 2px solid var(--ft-accent);\n border-radius: 3px;\n animation: ftDetailIn 220ms cubic-bezier(.2,.8,.2,1) backwards;\n color: var(--ft-fg);\n width: 320px;\n box-shadow: 0 18px 40px -8px rgba(0,0,0,0.6), 0 2px 8px rgba(0,0,0,0.4);\n}\n.ft-detail__head {\n display: flex;\n align-items: center;\n margin: -2px 28px 10px 0;\n}\n.ft-detail__title {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n}\n.ft-detail__close {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n color: var(--ft-muted-fg);\n cursor: pointer;\n padding: 0;\n transition: color 120ms, border-color 120ms, background 120ms;\n}\n.ft-detail__close:hover {\n color: var(--ft-fg);\n border-color: var(--ft-line-strong);\n background: oklch(0.22 0.008 80);\n}\n@keyframes ftDetailIn {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.ft-detail__lead {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.35;\n font-style: italic;\n padding-left: 10px;\n border-left: 2px solid var(--ft-accent);\n margin-bottom: 10px;\n}\n.ft-detail__body {\n margin: 0 0 10px;\n font-size: 12px;\n color: var(--ft-muted-fg);\n line-height: 1.5;\n}\n.ft-detail__bullets {\n margin: 0 0 10px;\n padding-left: 16px;\n font-size: 12px;\n color: var(--ft-fg);\n}\n.ft-detail__bullets li { margin-bottom: 3px; }\n.ft-detail__meta {\n margin: 0 0 10px;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.ft-detail__meta-row {\n display: grid;\n grid-template-columns: 96px 1fr;\n gap: 8px;\n font-size: 11px;\n}\n.ft-detail__meta-row dt {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n padding-top: 1px;\n}\n.ft-detail__meta-row dd { margin: 0; color: var(--ft-fg); }\n.ft-detail__actions {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n margin-top: 8px;\n}\n\n.ft-btn {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n padding: 7px 10px;\n background: transparent;\n color: var(--ft-fg);\n border: 1px solid var(--ft-line-strong);\n text-decoration: none;\n cursor: pointer;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n transition: border-color 150ms, background 150ms;\n}\n.ft-btn:hover { border-color: var(--ft-accent); }\n.ft-btn--primary {\n background: var(--ft-accent);\n color: oklch(0.18 0.01 50);\n border-color: var(--ft-accent);\n}\n\n@media (max-width: 760px) {\n .ft-header { padding: 16px 18px 14px; }\n .ft-header__title { font-size: 32px; }\n .ft-controls__hint { display: none; }\n .ft-legend { max-width: calc(100% - 24px); left: 10px; bottom: 10px; }\n}\n";
5269
5282
 
5270
5283
  type GameTimerMode = "countdown" | "countup";
5271
5284
  type GameTimerThemePreset = "green" | "red" | "blue" | "amber" | "purple" | "pink" | "teal";
package/dist/index.d.ts CHANGED
@@ -5257,15 +5257,28 @@ interface FlowTreeProps {
5257
5257
  hideControls?: boolean;
5258
5258
  /** Hide the breadcrumb legend at the bottom-left. */
5259
5259
  hideLegend?: boolean;
5260
+ /**
5261
+ * When > 0, cycles the focused path through the root's direct children
5262
+ * every N milliseconds until the user interacts with the tree (clicks a
5263
+ * card, pans, zooms, toggles a detail, or clicks a legend chip). Honors
5264
+ * `prefers-reduced-motion` (disabled if reduced motion is requested).
5265
+ * Default: 0 (disabled).
5266
+ */
5267
+ autoCycleMs?: number;
5268
+ /**
5269
+ * Explicit paths to cycle through when `autoCycleMs` is set. If omitted,
5270
+ * the tree auto-cycles through the root's direct children.
5271
+ */
5272
+ autoCyclePaths?: string[][];
5260
5273
  }
5261
- declare function FlowTree({ data, title, eyebrow, tagline, renderIcon: renderIconProp, tierColors: tierColorsProp, resolveHref: resolveHrefProp, layoutOptions, onNodeOpen, defaultFocusedPath, focusedPath: controlledPath, onFocusedPathChange, className, style, hideHeader, hideControls, hideLegend, }: FlowTreeProps): react_jsx_runtime.JSX.Element;
5274
+ declare function FlowTree({ data, title, eyebrow, tagline, renderIcon: renderIconProp, tierColors: tierColorsProp, resolveHref: resolveHrefProp, layoutOptions, onNodeOpen, defaultFocusedPath, focusedPath: controlledPath, onFocusedPathChange, className, style, hideHeader, hideControls, hideLegend, autoCycleMs, autoCyclePaths, }: FlowTreeProps): react_jsx_runtime.JSX.Element;
5262
5275
 
5263
5276
  /**
5264
5277
  * FlowTree CSS — injected once per page at runtime on the first mount.
5265
5278
  * Self-themed via `--ft-*` CSS variables, all with sensible fallbacks so the
5266
5279
  * component works standalone in any light or dark design system.
5267
5280
  */
5268
- declare const FLOW_TREE_CSS = "\n.ft-shell {\n --ft-bg: var(--ft-bg, oklch(0.185 0.008 80));\n --ft-fg: var(--ft-fg, oklch(0.96 0.005 85));\n --ft-muted-fg: var(--ft-muted-fg, oklch(0.68 0.008 80));\n --ft-dim-fg: var(--ft-dim-fg, oklch(0.5 0.008 80));\n --ft-line: var(--ft-line, oklch(0.28 0.008 80));\n --ft-line-strong: var(--ft-line-strong, oklch(0.4 0.008 80));\n --ft-grid-strong: var(--ft-grid-strong, oklch(0.24 0.008 80));\n --ft-card-bg: var(--ft-card-bg, oklch(0.21 0.008 80));\n --ft-card-active-bg: var(--ft-card-active-bg, oklch(0.25 0.015 60));\n --ft-card-hover-bg: var(--ft-card-hover-bg, oklch(0.23 0.01 80 / 0.6));\n --ft-rail-bg: var(--ft-rail-bg, oklch(0.19 0.008 80));\n --ft-icon-bg: var(--ft-icon-bg, oklch(0.17 0.008 80));\n --ft-detail-bg: var(--ft-detail-bg, oklch(0.16 0.008 80));\n --ft-header-bg: var(--ft-header-bg, linear-gradient(180deg, oklch(0.21 0.01 60) 0%, oklch(0.19 0.008 70) 100%));\n --ft-tier-orange: var(--ft-tier-orange, #f16c25);\n --ft-tier-teal: var(--ft-tier-teal, #5fb7b8);\n --ft-tier-blue: var(--ft-tier-blue, oklch(0.72 0.12 240));\n --ft-tier-amber: var(--ft-tier-amber, oklch(0.8 0.14 75));\n --ft-tier-green: var(--ft-tier-green, oklch(0.74 0.14 155));\n --ft-accent: var(--ft-accent, var(--ft-tier-orange));\n --ft-serif: var(--ft-serif, \"Instrument Serif\", Georgia, serif);\n --ft-sans: var(--ft-sans, \"Inter\", system-ui, sans-serif);\n --ft-mono: var(--ft-mono, \"JetBrains Mono\", ui-monospace, Menlo, monospace);\n\n display: flex;\n flex-direction: column;\n min-height: 0;\n background: var(--ft-bg);\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n overflow: hidden;\n color: var(--ft-fg);\n font-family: var(--ft-sans);\n font-size: 14px;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n box-shadow: 0 30px 60px -30px oklch(0 0 0 / 0.5);\n}\n.ft-shell * { box-sizing: border-box; }\n.ft-shell .ft-mono {\n font-family: var(--ft-mono);\n font-size: 11px;\n letter-spacing: 0.02em;\n}\n\n.ft-header {\n padding: 22px 28px 20px;\n border-bottom: 1px solid var(--ft-line);\n background: var(--ft-header-bg);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.ft-header__eyebrow {\n font-family: var(--ft-mono);\n font-size: 10.5px;\n letter-spacing: 0.22em;\n text-transform: uppercase;\n color: var(--ft-accent);\n}\n.ft-header__title {\n margin: 0;\n font-family: var(--ft-serif);\n font-weight: 400;\n font-size: 44px;\n line-height: 1;\n letter-spacing: -0.015em;\n color: var(--ft-fg);\n}\n.ft-header__tagline {\n margin: 6px 0 0;\n max-width: 76ch;\n color: var(--ft-muted-fg);\n font-size: 13px;\n}\n\n.ft-stage {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.ft-svg {\n display: block;\n width: 100%;\n height: 100%;\n background: transparent;\n cursor: grab;\n touch-action: none;\n user-select: none;\n}\n.ft-svg.is-dragging { cursor: grabbing; }\n\n.ft-controls {\n position: absolute;\n top: 14px;\n right: 14px;\n z-index: 5;\n display: flex;\n align-items: center;\n gap: 6px;\n background: oklch(0.2 0.008 80 / 0.94);\n border: 1px solid var(--ft-line-strong);\n padding: 5px 8px;\n backdrop-filter: blur(8px);\n border-radius: 2px;\n}\n.ft-controls button {\n font-family: var(--ft-mono);\n font-size: 12px;\n width: 26px;\n height: 26px;\n background: transparent;\n border: 1px solid var(--ft-line);\n color: var(--ft-fg);\n cursor: pointer;\n padding: 0;\n}\n.ft-controls button:hover { border-color: var(--ft-accent); }\n.ft-controls__reset {\n width: auto !important;\n padding: 0 10px !important;\n font-size: 9.5px !important;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n}\n.ft-controls__hint {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n color: var(--ft-muted-fg);\n letter-spacing: 0.04em;\n padding-left: 8px;\n margin-left: 2px;\n border-left: 1px solid var(--ft-line);\n}\n\n.ft-legend {\n position: absolute;\n left: 18px;\n bottom: 14px;\n z-index: 5;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-family: var(--ft-mono);\n font-size: 10px;\n color: var(--ft-muted-fg);\n background: oklch(0.2 0.008 80 / 0.88);\n border: 1px solid var(--ft-line);\n padding: 6px 10px;\n backdrop-filter: blur(6px);\n max-width: calc(100% - 220px);\n}\n.ft-legend__chip { display: inline-flex; align-items: center; gap: 6px; }\n.ft-legend__dot {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--ft-accent);\n}\n.ft-legend__sep { color: var(--ft-line-strong); margin: 0 2px; }\n\n.ft-edge { fill: none; transition: stroke 260ms, opacity 260ms; }\n.ft-edge--off {\n stroke: var(--ft-line);\n stroke-width: 1;\n opacity: 0.55;\n}\n.ft-edge--on {\n stroke: var(--ft-accent);\n stroke-width: 1.6;\n stroke-dasharray: 4 5;\n opacity: 1;\n animation: ftDashFlow 1.4s linear infinite;\n}\n@keyframes ftDashFlow { to { stroke-dashoffset: -36; } }\n\n.ft-card {\n --tier-local: var(--tier, var(--ft-line-strong));\n width: 100%;\n height: 100%;\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: stretch;\n background: var(--ft-card-bg);\n border: 1px solid var(--ft-line);\n border-left: 3px solid var(--tier-local);\n border-radius: 2px;\n transition:\n background 260ms cubic-bezier(.2,.8,.2,1),\n border-color 260ms, box-shadow 260ms,\n transform 260ms cubic-bezier(.2,.8,.2,1),\n filter 260ms, opacity 260ms, color 260ms;\n overflow: visible;\n animation: ftCardIn 320ms cubic-bezier(.2,.8,.2,1) backwards;\n}\n@keyframes ftCardIn {\n from { opacity: 0; transform: translateX(-6px); }\n to { opacity: 1; transform: translateX(0); }\n}\n.ft-card__main {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 10px;\n align-items: center;\n padding: 0 10px 0 12px;\n background: transparent;\n border: none;\n color: inherit;\n font-family: var(--ft-sans);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n min-width: 0;\n}\n.ft-card__main:hover { background: var(--ft-card-hover-bg); }\n.ft-card__icon {\n width: 24px;\n height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--tier-local);\n border: 1px solid var(--ft-line-strong);\n background: var(--ft-icon-bg);\n flex-shrink: 0;\n}\n.ft-card__body { display: flex; flex-direction: column; min-width: 0; gap: 1px; }\n.ft-card__label {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.15;\n color: var(--ft-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.ft-card__sub {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.02em;\n color: var(--ft-muted-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ft-card__lock { color: var(--ft-muted-fg); display: inline-flex; }\n.ft-card__caret {\n width: 18px;\n height: 18px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--ft-mono);\n font-size: 12px;\n color: var(--ft-muted-fg);\n border: 1px solid var(--ft-line);\n}\n.ft-card--active .ft-card__caret {\n color: var(--tier-local);\n border-color: var(--tier-local);\n}\n\n.ft-card__rail {\n display: flex;\n flex-direction: column;\n border-left: 1px solid var(--ft-line);\n background: var(--ft-rail-bg);\n}\n.ft-card__mini {\n flex: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n min-height: 20px;\n background: transparent;\n border: none;\n color: var(--ft-muted-fg);\n cursor: pointer;\n transition: background 150ms, color 150ms;\n border-bottom: 1px solid var(--ft-line);\n padding: 0;\n text-decoration: none;\n}\n.ft-card__mini:last-child { border-bottom: none; }\n.ft-card__mini:hover {\n background: oklch(0.23 0.01 80);\n color: var(--tier-local);\n}\n.ft-card__mini.is-on {\n color: var(--tier-local);\n background: oklch(0.23 0.01 80);\n}\n\n.ft-card--active {\n background: var(--ft-card-active-bg);\n box-shadow: 0 0 0 1px var(--tier-local), 0 14px 34px -16px oklch(0.5 0.18 50 / 0.55);\n transform: scale(1.02);\n}\n.ft-card--dim {\n filter: grayscale(0.85) brightness(0.82);\n opacity: 0.7;\n transform: scale(0.88);\n transform-origin: center left;\n}\n.ft-card--dim .ft-card__label { color: var(--ft-dim-fg); }\n.ft-card--dim:hover {\n filter: grayscale(0.3) brightness(0.96);\n opacity: 1;\n transform: scale(0.94);\n}\n.ft-card--cta {\n border-left-color: var(--ft-accent);\n background: linear-gradient(180deg, oklch(0.23 0.02 55) 0%, oklch(0.2 0.015 60) 100%);\n}\n.ft-card--root {\n border-left-color: var(--ft-accent);\n background: oklch(0.26 0.015 55);\n}\n.ft-card--root .ft-card__icon {\n color: var(--ft-accent);\n border-color: var(--ft-accent);\n}\n\n.ft-detail {\n position: relative;\n margin-top: 0;\n padding: 16px 18px 14px;\n background: var(--ft-detail-bg);\n border: 1px solid var(--ft-line-strong);\n border-left: 2px solid var(--ft-accent);\n border-radius: 3px;\n animation: ftDetailIn 220ms cubic-bezier(.2,.8,.2,1) backwards;\n color: var(--ft-fg);\n width: 320px;\n box-shadow: 0 18px 40px -8px rgba(0,0,0,0.6), 0 2px 8px rgba(0,0,0,0.4);\n}\n.ft-detail__head {\n display: flex;\n align-items: center;\n margin: -2px 28px 10px 0;\n}\n.ft-detail__title {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n}\n.ft-detail__close {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n color: var(--ft-muted-fg);\n cursor: pointer;\n padding: 0;\n transition: color 120ms, border-color 120ms, background 120ms;\n}\n.ft-detail__close:hover {\n color: var(--ft-fg);\n border-color: var(--ft-line-strong);\n background: oklch(0.22 0.008 80);\n}\n@keyframes ftDetailIn {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.ft-detail__lead {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.35;\n font-style: italic;\n padding-left: 10px;\n border-left: 2px solid var(--ft-accent);\n margin-bottom: 10px;\n}\n.ft-detail__body {\n margin: 0 0 10px;\n font-size: 12px;\n color: var(--ft-muted-fg);\n line-height: 1.5;\n}\n.ft-detail__bullets {\n margin: 0 0 10px;\n padding-left: 16px;\n font-size: 12px;\n color: var(--ft-fg);\n}\n.ft-detail__bullets li { margin-bottom: 3px; }\n.ft-detail__meta {\n margin: 0 0 10px;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.ft-detail__meta-row {\n display: grid;\n grid-template-columns: 96px 1fr;\n gap: 8px;\n font-size: 11px;\n}\n.ft-detail__meta-row dt {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n padding-top: 1px;\n}\n.ft-detail__meta-row dd { margin: 0; color: var(--ft-fg); }\n.ft-detail__actions {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n margin-top: 8px;\n}\n\n.ft-btn {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n padding: 7px 10px;\n background: transparent;\n color: var(--ft-fg);\n border: 1px solid var(--ft-line-strong);\n text-decoration: none;\n cursor: pointer;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n transition: border-color 150ms, background 150ms;\n}\n.ft-btn:hover { border-color: var(--ft-accent); }\n.ft-btn--primary {\n background: var(--ft-accent);\n color: oklch(0.18 0.01 50);\n border-color: var(--ft-accent);\n}\n\n@media (max-width: 760px) {\n .ft-header { padding: 16px 18px 14px; }\n .ft-header__title { font-size: 32px; }\n .ft-controls__hint { display: none; }\n .ft-legend { max-width: calc(100% - 24px); left: 10px; bottom: 10px; }\n}\n";
5281
+ declare const FLOW_TREE_CSS = "\n.ft-shell {\n --ft-bg: var(--ft-bg, oklch(0.185 0.008 80));\n --ft-fg: var(--ft-fg, oklch(0.96 0.005 85));\n --ft-muted-fg: var(--ft-muted-fg, oklch(0.68 0.008 80));\n --ft-dim-fg: var(--ft-dim-fg, oklch(0.5 0.008 80));\n --ft-line: var(--ft-line, oklch(0.28 0.008 80));\n --ft-line-strong: var(--ft-line-strong, oklch(0.4 0.008 80));\n --ft-grid-strong: var(--ft-grid-strong, oklch(0.24 0.008 80));\n --ft-card-bg: var(--ft-card-bg, oklch(0.21 0.008 80));\n --ft-card-active-bg: var(--ft-card-active-bg, oklch(0.25 0.015 60));\n --ft-card-hover-bg: var(--ft-card-hover-bg, oklch(0.23 0.01 80 / 0.6));\n --ft-rail-bg: var(--ft-rail-bg, oklch(0.19 0.008 80));\n --ft-icon-bg: var(--ft-icon-bg, oklch(0.17 0.008 80));\n --ft-detail-bg: var(--ft-detail-bg, oklch(0.16 0.008 80));\n --ft-header-bg: var(--ft-header-bg, linear-gradient(180deg, oklch(0.21 0.01 60) 0%, oklch(0.19 0.008 70) 100%));\n --ft-tier-orange: var(--ft-tier-orange, #f16c25);\n --ft-tier-teal: var(--ft-tier-teal, #5fb7b8);\n --ft-tier-blue: var(--ft-tier-blue, oklch(0.72 0.12 240));\n --ft-tier-amber: var(--ft-tier-amber, oklch(0.8 0.14 75));\n --ft-tier-green: var(--ft-tier-green, oklch(0.74 0.14 155));\n --ft-accent: var(--ft-accent, var(--ft-tier-orange));\n --ft-serif: var(--ft-serif, \"Instrument Serif\", Georgia, serif);\n --ft-sans: var(--ft-sans, \"Inter\", system-ui, sans-serif);\n --ft-mono: var(--ft-mono, \"JetBrains Mono\", ui-monospace, Menlo, monospace);\n\n display: flex;\n flex-direction: column;\n min-height: 0;\n background: var(--ft-bg);\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n overflow: hidden;\n color: var(--ft-fg);\n font-family: var(--ft-sans);\n font-size: 14px;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n box-shadow: 0 30px 60px -30px oklch(0 0 0 / 0.5);\n}\n.ft-shell * { box-sizing: border-box; }\n.ft-shell .ft-mono {\n font-family: var(--ft-mono);\n font-size: 11px;\n letter-spacing: 0.02em;\n}\n\n.ft-header {\n padding: 22px 28px 20px;\n border-bottom: 1px solid var(--ft-line);\n background: var(--ft-header-bg);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.ft-header__eyebrow {\n font-family: var(--ft-mono);\n font-size: 10.5px;\n letter-spacing: 0.22em;\n text-transform: uppercase;\n color: var(--ft-accent);\n}\n.ft-header__title {\n margin: 0;\n font-family: var(--ft-serif);\n font-weight: 400;\n font-size: 44px;\n line-height: 1;\n letter-spacing: -0.015em;\n color: var(--ft-fg);\n}\n.ft-header__tagline {\n margin: 6px 0 0;\n max-width: 76ch;\n color: var(--ft-muted-fg);\n font-size: 13px;\n}\n\n.ft-stage {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n background:\n radial-gradient(1000px 600px at 15% -10%, oklch(0.22 0.012 60 / 0.7), transparent 60%),\n radial-gradient(800px 500px at 110% 110%, oklch(0.2 0.02 200 / 0.35), transparent 65%);\n}\n\n.ft-svg {\n display: block;\n width: 100%;\n height: 100%;\n background: transparent;\n cursor: grab;\n touch-action: none;\n user-select: none;\n}\n.ft-svg.is-dragging { cursor: grabbing; }\n\n.ft-controls {\n position: absolute;\n top: 14px;\n right: 14px;\n z-index: 5;\n display: flex;\n align-items: center;\n gap: 6px;\n background: oklch(0.2 0.008 80 / 0.94);\n border: 1px solid var(--ft-line-strong);\n padding: 5px 8px;\n backdrop-filter: blur(8px);\n border-radius: 2px;\n}\n.ft-controls button {\n font-family: var(--ft-mono);\n font-size: 12px;\n width: 26px;\n height: 26px;\n background: transparent;\n border: 1px solid var(--ft-line);\n color: var(--ft-fg);\n cursor: pointer;\n padding: 0;\n}\n.ft-controls button:hover { border-color: var(--ft-accent); }\n.ft-controls__reset {\n width: auto !important;\n padding: 0 10px !important;\n font-size: 9.5px !important;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n}\n.ft-controls__hint {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n color: var(--ft-muted-fg);\n letter-spacing: 0.04em;\n padding-left: 8px;\n margin-left: 2px;\n border-left: 1px solid var(--ft-line);\n}\n\n.ft-legend {\n position: absolute;\n left: 18px;\n bottom: 14px;\n z-index: 5;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-family: var(--ft-mono);\n font-size: 10px;\n color: var(--ft-muted-fg);\n background: oklch(0.2 0.008 80 / 0.88);\n border: 1px solid var(--ft-line);\n padding: 6px 10px;\n backdrop-filter: blur(6px);\n max-width: calc(100% - 220px);\n}\n.ft-legend__chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 2px 6px;\n margin: -2px 0;\n background: transparent;\n border: none;\n color: inherit;\n font: inherit;\n letter-spacing: inherit;\n cursor: pointer;\n border-radius: 2px;\n transition: background 120ms, color 120ms;\n}\n.ft-legend__chip:hover {\n background: oklch(0.24 0.01 80);\n color: var(--ft-fg);\n}\n.ft-legend__chip:disabled {\n cursor: default;\n color: var(--ft-fg);\n}\n.ft-legend__chip:disabled:hover { background: transparent; }\n.ft-legend__dot {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--ft-accent);\n flex-shrink: 0;\n}\n.ft-legend__sep {\n color: var(--ft-line-strong);\n margin: 0 2px;\n pointer-events: none;\n user-select: none;\n}\n\n.ft-edge {\n fill: none;\n transition: stroke 260ms, opacity 260ms, stroke-width 260ms;\n}\n.ft-edge--off {\n stroke: var(--ft-line-strong);\n stroke-width: 1.1;\n stroke-dasharray: 2 4;\n opacity: 0.5;\n}\n.ft-edge--on {\n stroke: var(--ft-accent);\n stroke-width: 1.8;\n stroke-dasharray: 5 5;\n opacity: 1;\n filter: drop-shadow(0 0 4px var(--ft-accent));\n animation: ftDashFlow 1.4s linear infinite;\n}\n@keyframes ftDashFlow { to { stroke-dashoffset: -40; } }\n@media (prefers-reduced-motion: reduce) {\n .ft-edge--on { animation: none; }\n}\n\n.ft-card {\n --tier-local: var(--tier, var(--ft-line-strong));\n width: 100%;\n height: 100%;\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: stretch;\n background: var(--ft-card-bg);\n border: 1px solid var(--ft-line);\n border-left: 3px solid var(--tier-local);\n border-radius: 2px;\n transition:\n background 260ms cubic-bezier(.2,.8,.2,1),\n border-color 260ms, box-shadow 260ms,\n transform 260ms cubic-bezier(.2,.8,.2,1),\n filter 260ms, opacity 260ms, color 260ms;\n overflow: visible;\n animation: ftCardIn 320ms cubic-bezier(.2,.8,.2,1) backwards;\n}\n@keyframes ftCardIn {\n from { opacity: 0; transform: translateX(-6px); }\n to { opacity: 1; transform: translateX(0); }\n}\n.ft-card__main {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 10px;\n align-items: center;\n padding: 0 10px 0 12px;\n background: transparent;\n border: none;\n color: inherit;\n font-family: var(--ft-sans);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n min-width: 0;\n}\n.ft-card__main:hover { background: var(--ft-card-hover-bg); }\n.ft-card__icon {\n width: 24px;\n height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--tier-local);\n border: 1px solid var(--ft-line-strong);\n background: var(--ft-icon-bg);\n flex-shrink: 0;\n}\n.ft-card__body { display: flex; flex-direction: column; min-width: 0; gap: 1px; }\n.ft-card__label {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.15;\n color: var(--ft-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.ft-card__sub {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.02em;\n color: var(--ft-muted-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ft-card__lock { color: var(--ft-muted-fg); display: inline-flex; }\n.ft-card__caret {\n width: 18px;\n height: 18px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--ft-mono);\n font-size: 12px;\n color: var(--ft-muted-fg);\n border: 1px solid var(--ft-line);\n}\n.ft-card--active .ft-card__caret {\n color: var(--tier-local);\n border-color: var(--tier-local);\n}\n\n.ft-card__rail {\n display: flex;\n flex-direction: column;\n border-left: 1px solid var(--ft-line);\n background: var(--ft-rail-bg);\n}\n.ft-card__mini {\n flex: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n min-height: 20px;\n background: transparent;\n border: none;\n color: var(--ft-muted-fg);\n cursor: pointer;\n transition: background 150ms, color 150ms;\n border-bottom: 1px solid var(--ft-line);\n padding: 0;\n text-decoration: none;\n}\n.ft-card__mini:last-child { border-bottom: none; }\n.ft-card__mini:hover {\n background: oklch(0.23 0.01 80);\n color: var(--tier-local);\n}\n.ft-card__mini.is-on {\n color: var(--tier-local);\n background: oklch(0.23 0.01 80);\n}\n\n.ft-card--active {\n background: var(--ft-card-active-bg);\n box-shadow: 0 0 0 1px var(--tier-local), 0 14px 34px -16px oklch(0.5 0.18 50 / 0.55);\n transform: scale(1.02);\n}\n.ft-card--dim {\n filter: grayscale(0.85) brightness(0.82);\n opacity: 0.7;\n transform: scale(0.88);\n transform-origin: center left;\n}\n.ft-card--dim .ft-card__label { color: var(--ft-dim-fg); }\n.ft-card--dim:hover {\n filter: grayscale(0.3) brightness(0.96);\n opacity: 1;\n transform: scale(0.94);\n}\n.ft-card--cta {\n border-left-color: var(--ft-accent);\n background: linear-gradient(180deg, oklch(0.23 0.02 55) 0%, oklch(0.2 0.015 60) 100%);\n}\n.ft-card--root {\n border-left-color: var(--ft-accent);\n background: oklch(0.26 0.015 55);\n}\n.ft-card--root .ft-card__icon {\n color: var(--ft-accent);\n border-color: var(--ft-accent);\n}\n\n.ft-detail {\n position: relative;\n margin-top: 0;\n padding: 16px 18px 14px;\n background: var(--ft-detail-bg);\n border: 1px solid var(--ft-line-strong);\n border-left: 2px solid var(--ft-accent);\n border-radius: 3px;\n animation: ftDetailIn 220ms cubic-bezier(.2,.8,.2,1) backwards;\n color: var(--ft-fg);\n width: 320px;\n box-shadow: 0 18px 40px -8px rgba(0,0,0,0.6), 0 2px 8px rgba(0,0,0,0.4);\n}\n.ft-detail__head {\n display: flex;\n align-items: center;\n margin: -2px 28px 10px 0;\n}\n.ft-detail__title {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n}\n.ft-detail__close {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n color: var(--ft-muted-fg);\n cursor: pointer;\n padding: 0;\n transition: color 120ms, border-color 120ms, background 120ms;\n}\n.ft-detail__close:hover {\n color: var(--ft-fg);\n border-color: var(--ft-line-strong);\n background: oklch(0.22 0.008 80);\n}\n@keyframes ftDetailIn {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.ft-detail__lead {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.35;\n font-style: italic;\n padding-left: 10px;\n border-left: 2px solid var(--ft-accent);\n margin-bottom: 10px;\n}\n.ft-detail__body {\n margin: 0 0 10px;\n font-size: 12px;\n color: var(--ft-muted-fg);\n line-height: 1.5;\n}\n.ft-detail__bullets {\n margin: 0 0 10px;\n padding-left: 16px;\n font-size: 12px;\n color: var(--ft-fg);\n}\n.ft-detail__bullets li { margin-bottom: 3px; }\n.ft-detail__meta {\n margin: 0 0 10px;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.ft-detail__meta-row {\n display: grid;\n grid-template-columns: 96px 1fr;\n gap: 8px;\n font-size: 11px;\n}\n.ft-detail__meta-row dt {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n padding-top: 1px;\n}\n.ft-detail__meta-row dd { margin: 0; color: var(--ft-fg); }\n.ft-detail__actions {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n margin-top: 8px;\n}\n\n.ft-btn {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n padding: 7px 10px;\n background: transparent;\n color: var(--ft-fg);\n border: 1px solid var(--ft-line-strong);\n text-decoration: none;\n cursor: pointer;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n transition: border-color 150ms, background 150ms;\n}\n.ft-btn:hover { border-color: var(--ft-accent); }\n.ft-btn--primary {\n background: var(--ft-accent);\n color: oklch(0.18 0.01 50);\n border-color: var(--ft-accent);\n}\n\n@media (max-width: 760px) {\n .ft-header { padding: 16px 18px 14px; }\n .ft-header__title { font-size: 32px; }\n .ft-controls__hint { display: none; }\n .ft-legend { max-width: calc(100% - 24px); left: 10px; bottom: 10px; }\n}\n";
5269
5282
 
5270
5283
  type GameTimerMode = "countdown" | "countup";
5271
5284
  type GameTimerThemePreset = "green" | "red" | "blue" | "amber" | "purple" | "pink" | "teal";
package/dist/index.js CHANGED
@@ -35995,6 +35995,9 @@ var FLOW_TREE_CSS = `
35995
35995
  flex: 1;
35996
35996
  min-height: 0;
35997
35997
  overflow: hidden;
35998
+ background:
35999
+ radial-gradient(1000px 600px at 15% -10%, oklch(0.22 0.012 60 / 0.7), transparent 60%),
36000
+ radial-gradient(800px 500px at 110% 110%, oklch(0.2 0.02 200 / 0.35), transparent 65%);
35998
36001
  }
35999
36002
 
36000
36003
  .ft-svg {
@@ -36069,29 +36072,66 @@ var FLOW_TREE_CSS = `
36069
36072
  backdrop-filter: blur(6px);
36070
36073
  max-width: calc(100% - 220px);
36071
36074
  }
36072
- .ft-legend__chip { display: inline-flex; align-items: center; gap: 6px; }
36075
+ .ft-legend__chip {
36076
+ display: inline-flex;
36077
+ align-items: center;
36078
+ gap: 6px;
36079
+ padding: 2px 6px;
36080
+ margin: -2px 0;
36081
+ background: transparent;
36082
+ border: none;
36083
+ color: inherit;
36084
+ font: inherit;
36085
+ letter-spacing: inherit;
36086
+ cursor: pointer;
36087
+ border-radius: 2px;
36088
+ transition: background 120ms, color 120ms;
36089
+ }
36090
+ .ft-legend__chip:hover {
36091
+ background: oklch(0.24 0.01 80);
36092
+ color: var(--ft-fg);
36093
+ }
36094
+ .ft-legend__chip:disabled {
36095
+ cursor: default;
36096
+ color: var(--ft-fg);
36097
+ }
36098
+ .ft-legend__chip:disabled:hover { background: transparent; }
36073
36099
  .ft-legend__dot {
36074
36100
  width: 5px;
36075
36101
  height: 5px;
36076
36102
  border-radius: 50%;
36077
36103
  background: var(--ft-accent);
36104
+ flex-shrink: 0;
36105
+ }
36106
+ .ft-legend__sep {
36107
+ color: var(--ft-line-strong);
36108
+ margin: 0 2px;
36109
+ pointer-events: none;
36110
+ user-select: none;
36078
36111
  }
36079
- .ft-legend__sep { color: var(--ft-line-strong); margin: 0 2px; }
36080
36112
 
36081
- .ft-edge { fill: none; transition: stroke 260ms, opacity 260ms; }
36113
+ .ft-edge {
36114
+ fill: none;
36115
+ transition: stroke 260ms, opacity 260ms, stroke-width 260ms;
36116
+ }
36082
36117
  .ft-edge--off {
36083
- stroke: var(--ft-line);
36084
- stroke-width: 1;
36085
- opacity: 0.55;
36118
+ stroke: var(--ft-line-strong);
36119
+ stroke-width: 1.1;
36120
+ stroke-dasharray: 2 4;
36121
+ opacity: 0.5;
36086
36122
  }
36087
36123
  .ft-edge--on {
36088
36124
  stroke: var(--ft-accent);
36089
- stroke-width: 1.6;
36090
- stroke-dasharray: 4 5;
36125
+ stroke-width: 1.8;
36126
+ stroke-dasharray: 5 5;
36091
36127
  opacity: 1;
36128
+ filter: drop-shadow(0 0 4px var(--ft-accent));
36092
36129
  animation: ftDashFlow 1.4s linear infinite;
36093
36130
  }
36094
- @keyframes ftDashFlow { to { stroke-dashoffset: -36; } }
36131
+ @keyframes ftDashFlow { to { stroke-dashoffset: -40; } }
36132
+ @media (prefers-reduced-motion: reduce) {
36133
+ .ft-edge--on { animation: none; }
36134
+ }
36095
36135
 
36096
36136
  .ft-card {
36097
36137
  --tier-local: var(--tier, var(--ft-line-strong));
@@ -36388,11 +36428,11 @@ var DEFAULT_TIER_COLORS = {
36388
36428
  gray: "var(--ft-line-strong)"
36389
36429
  };
36390
36430
  var DEFAULT_LAYOUT = {
36391
- col: 280,
36392
- row: 64,
36393
- compactRow: 42,
36394
- cardW: 244,
36395
- cardH: 56,
36431
+ col: 290,
36432
+ row: 76,
36433
+ compactRow: 48,
36434
+ cardW: 248,
36435
+ cardH: 60,
36396
36436
  detailMaxW: 320
36397
36437
  };
36398
36438
  var STYLE_ID4 = "dll-flow-tree-styles";
@@ -36745,7 +36785,9 @@ function FlowTree({
36745
36785
  style,
36746
36786
  hideHeader = false,
36747
36787
  hideControls = false,
36748
- hideLegend = false
36788
+ hideLegend = false,
36789
+ autoCycleMs = 0,
36790
+ autoCyclePaths
36749
36791
  }) {
36750
36792
  React87.useEffect(() => {
36751
36793
  ensureStylesInjected4();
@@ -36789,31 +36831,84 @@ function FlowTree({
36789
36831
  },
36790
36832
  [controlledPath, onFocusedPathChange]
36791
36833
  );
36834
+ const [hasUserInteracted, setHasUserInteracted] = React87.useState(false);
36835
+ const markInteracted = React87.useCallback(() => {
36836
+ setHasUserInteracted(true);
36837
+ }, []);
36792
36838
  const [expandedDetails, setExpandedDetails] = React87.useState(
36793
36839
  () => /* @__PURE__ */ new Set()
36794
36840
  );
36795
- const toggleDetail = React87.useCallback((n) => {
36796
- setExpandedDetails((prev) => {
36797
- const next = new Set(prev);
36798
- if (next.has(n.data.id)) next.delete(n.data.id);
36799
- else next.add(n.data.id);
36800
- return next;
36801
- });
36802
- }, []);
36803
- const closeDetail = React87.useCallback((id) => {
36804
- setExpandedDetails((prev) => {
36805
- const next = new Set(prev);
36806
- next.delete(id);
36807
- return next;
36808
- });
36809
- }, []);
36841
+ const toggleDetail = React87.useCallback(
36842
+ (n) => {
36843
+ markInteracted();
36844
+ setExpandedDetails((prev) => {
36845
+ const next = new Set(prev);
36846
+ if (next.has(n.data.id)) next.delete(n.data.id);
36847
+ else next.add(n.data.id);
36848
+ return next;
36849
+ });
36850
+ },
36851
+ [markInteracted]
36852
+ );
36853
+ const closeDetail = React87.useCallback(
36854
+ (id) => {
36855
+ markInteracted();
36856
+ setExpandedDetails((prev) => {
36857
+ const next = new Set(prev);
36858
+ next.delete(id);
36859
+ return next;
36860
+ });
36861
+ },
36862
+ [markInteracted]
36863
+ );
36810
36864
  const activate = React87.useCallback(
36811
36865
  (n) => {
36866
+ markInteracted();
36812
36867
  setFocusedPath(n.pathArr);
36813
36868
  setExpandedDetails(/* @__PURE__ */ new Set());
36814
36869
  },
36815
- [setFocusedPath]
36870
+ [setFocusedPath, markInteracted]
36816
36871
  );
36872
+ const focusPathPrefix = React87.useCallback(
36873
+ (prefixLen) => {
36874
+ if (prefixLen < 1 || prefixLen >= focusedPath.length) return;
36875
+ markInteracted();
36876
+ setFocusedPath(focusedPath.slice(0, prefixLen));
36877
+ setExpandedDetails(/* @__PURE__ */ new Set());
36878
+ },
36879
+ [focusedPath, setFocusedPath, markInteracted]
36880
+ );
36881
+ const resolvedCyclePaths = React87.useMemo(() => {
36882
+ if (!autoCycleMs || autoCycleMs <= 0) return [];
36883
+ if (autoCyclePaths && autoCyclePaths.length) return autoCyclePaths;
36884
+ return (data.children ?? []).map((c) => [data.id, c.id]);
36885
+ }, [autoCycleMs, autoCyclePaths, data]);
36886
+ React87.useEffect(() => {
36887
+ if (!autoCycleMs || autoCycleMs <= 0) return;
36888
+ if (hasUserInteracted) return;
36889
+ if (controlledPath) return;
36890
+ if (resolvedCyclePaths.length === 0) return;
36891
+ if (typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
36892
+ return;
36893
+ }
36894
+ const currentKey = focusedPath.join("/");
36895
+ let i = Math.max(
36896
+ 0,
36897
+ resolvedCyclePaths.findIndex((p) => p.join("/") === currentKey)
36898
+ );
36899
+ const id = window.setInterval(() => {
36900
+ i = (i + 1) % resolvedCyclePaths.length;
36901
+ const next = resolvedCyclePaths[i];
36902
+ if (next) setFocusedPath(next);
36903
+ }, autoCycleMs);
36904
+ return () => window.clearInterval(id);
36905
+ }, [
36906
+ autoCycleMs,
36907
+ hasUserInteracted,
36908
+ controlledPath,
36909
+ resolvedCyclePaths,
36910
+ setFocusedPath
36911
+ ]);
36817
36912
  const { nodes, edges, width, height } = React87.useMemo(
36818
36913
  () => layoutTree(data, focusedPath, opts, expandedDetails),
36819
36914
  [data, focusedPath.join("/"), opts, expandedDetails]
@@ -36873,6 +36968,7 @@ function FlowTree({
36873
36968
  const onPointerDown = (e) => {
36874
36969
  if (e.target.closest("button, a")) return;
36875
36970
  userInteractedRef.current = true;
36971
+ markInteracted();
36876
36972
  dragRef.current = { sx: e.clientX, sy: e.clientY, px: pan.x, py: pan.y };
36877
36973
  e.currentTarget.setPointerCapture?.(e.pointerId);
36878
36974
  e.currentTarget.classList.add("is-dragging");
@@ -36892,6 +36988,7 @@ function FlowTree({
36892
36988
  if (!e.ctrlKey && !e.metaKey) return;
36893
36989
  e.preventDefault();
36894
36990
  userInteractedRef.current = true;
36991
+ markInteracted();
36895
36992
  setZoom((z) => Math.max(0.35, Math.min(2, z + -e.deltaY * 15e-4)));
36896
36993
  };
36897
36994
  const resetView = () => {
@@ -37067,10 +37164,23 @@ function FlowTree({
37067
37164
  ),
37068
37165
  !hideLegend ? /* @__PURE__ */ (0, import_jsx_runtime120.jsx)("div", { className: "ft-legend ft-mono", children: focusedPath.map((id, i) => {
37069
37166
  const n = nodeById[id];
37070
- return /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)("span", { className: "ft-legend__chip", children: [
37071
- /* @__PURE__ */ (0, import_jsx_runtime120.jsx)("span", { className: "ft-legend__dot" }),
37072
- n ? n.data.label : id,
37073
- i < focusedPath.length - 1 ? /* @__PURE__ */ (0, import_jsx_runtime120.jsx)("span", { className: "ft-legend__sep", children: "\u203A" }) : null
37167
+ const isLast = i === focusedPath.length - 1;
37168
+ return /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)(React87.Fragment, { children: [
37169
+ /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)(
37170
+ "button",
37171
+ {
37172
+ type: "button",
37173
+ className: "ft-legend__chip",
37174
+ onClick: () => focusPathPrefix(i + 1),
37175
+ disabled: isLast,
37176
+ title: isLast ? "Current focus" : `Jump back to ${n ? n.data.label : id}`,
37177
+ children: [
37178
+ /* @__PURE__ */ (0, import_jsx_runtime120.jsx)("span", { className: "ft-legend__dot" }),
37179
+ n ? n.data.label : id
37180
+ ]
37181
+ }
37182
+ ),
37183
+ !isLast ? /* @__PURE__ */ (0, import_jsx_runtime120.jsx)("span", { className: "ft-legend__sep", "aria-hidden": true, children: "\u203A" }) : null
37074
37184
  ] }, id);
37075
37185
  }) }) : null
37076
37186
  ] })