/* FNXC:FloatingWindow 2026-06-22-20:45: FloatingWindow is a non-blocking floating window (generalized from RightDockExpandModal). The overlay is a full-viewport, transparent, NON-dimming, NON-blurring, click-through layer: `pointer-events: none` lets every click pass through to the app and to other windows behind it. Only the panel re-enables `pointer-events: auto`. Multiple overlays/panels coexist with no mutual blocking — z-stacking is driven by inline `z-index` from the component's per-window counter. FNXC:FloatingWindow 2026-06-27-00:00: Click-through overlays cannot implement backdrop clicks in CSS/DOM structure. Outside-click dismissal is therefore a component-level opt-in document listener for transient windows such as Quick Chat; persistent task and terminal pop-outs keep the default non-dismissable page-click behavior. */ .floating-window-overlay { position: fixed; inset: 0; background: transparent; backdrop-filter: none; pointer-events: none; } /* FNXC:FloatingWindow 2026-07-18-00:00: Quick Chat closes by hiding its already-mounted portal instead of unmounting ChatView. `display: none` removes the desktop window and the ≤768px full-screen sheet from paint and interaction while preserving the child DOM and in-memory scroll/session state for an instant reopen. */ .floating-window-overlay--hidden { display: none; } /* FNXC:FloatingWindow 2026-06-22-20:45: Floating panel positioned by state-driven inline `left/top/width/height` and stacked by inline `z-index`. min/max keep the panel usable and on-screen. `resize: none` because resizing is handled by the corner/edge handles. `pointer-events: auto` re-enables interaction on the panel only. */ .floating-window { --floating-window-shadow: var(--shadow-lg); position: fixed; display: flex; flex-direction: column; min-width: calc(var(--space-2xl) * 7.5); min-height: calc(var(--space-2xl) * 5.83); max-width: calc(100vw - (var(--space-lg) * 2)); max-height: calc(100dvh - (var(--space-lg) * 2)); overflow: hidden; background: var(--surface); border: thin solid var(--border); border-radius: var(--radius-lg); /* FNXC:FloatingWindow 2026-06-23-23:25: Floating modals need a gentle, theme-controlled drop shadow. Use a local token with the app's existing shadow fallback instead of the undefined --shadow-xl so themes can soften, strengthen, or remove modal elevation intentionally. */ box-shadow: var(--floating-window-shadow, var(--shadow-lg)); color: var(--text); resize: none; pointer-events: auto; } /* FNXC:FloatingWindow 2026-06-22-20:45: Header is the drag handle. `touch-action: none` (matching the resize handles) hands the whole gesture to the pointer handlers so touch dragging stays smooth and never scrolls the page behind it. A comfortable min-height makes a forgiving touch target. `user-select: none` protects the drag from selecting header text. */ .floating-window__header { display: flex; flex-shrink: 0; align-items: center; gap: var(--space-sm); min-height: 44px; padding: var(--space-sm) var(--space-md); border-bottom: thin solid var(--border); background: var(--surface-2, var(--surface)); cursor: grab; user-select: none; touch-action: none; } .floating-window__header:active { cursor: grabbing; } /* FNXC:FloatingWindow 2026-06-22-12:20: Headerless task pop-outs still need a visible drag affordance. The embedded task-detail modal header becomes the grab handle, matching the one-header "Open task" modal while preserving FloatingWindow's drag and resize behavior. */ .floating-window--headerless .floating-window__body { overflow: hidden; } .floating-window--headerless .task-detail-content--embedded { border-radius: inherit; overflow: hidden; } .floating-window--headerless .task-detail-content--embedded > .modal-header { cursor: grab; user-select: none; touch-action: none; } .floating-window--headerless .task-detail-content--embedded > .modal-header:active { cursor: grabbing; } .floating-window--chat.floating-window--headerless .floating-window__body { overflow: hidden; } .floating-window--chat .chat-view { border-radius: inherit; overflow: hidden; } /* FNXC:ChatModal 2026-06-22-14:49: On mobile/narrow app viewports, opening Quick Chat should present the full Chat modal as a full-screen sheet instead of a small draggable desktop window. Scope this to the chat FloatingWindow and override the inline desktop geometry only at the mobile breakpoint; desktop pop-out behavior remains movable/resizable. */ @media (max-width: 768px) { /* FNXC:FloatingWindow 2026-07-12-17:35: Mobile keeps the global `styles.css` pan-y lockdown so the dashboard cannot drift, but movable FloatingWindow headers must still resolve to an effective `touch-action: none`. Reassert the drag-handle contract at the mobile breakpoint, excluding full-screen sheet variants, so a single-finger header drag stays on the captured pointermove stream instead of being intersected back into page pan by the ancestor chain. Desktop drag/resize and mobile sheet variants are unchanged. */ .floating-window:not(.floating-window--chat):not(.floating-window--github-import-detail):not(.floating-window--task-detail):not(.floating-window--workflow-editor):not(.floating-window--automation):not(.floating-window--mission-interview):not(.floating-window--file-browser):not(.floating-window--pr-create):not(.artifacts-gallery-window) .floating-window__header { touch-action: none; } .floating-window--chat { inset: 0 !important; width: 100vw !important; height: 100dvh !important; min-width: 0 !important; min-height: 0 !important; max-width: 100vw !important; max-height: 100dvh !important; border: none; border-radius: 0; box-shadow: none; } .floating-window--chat .floating-window__resize-handle { display: none; } /* FNXC:QuickAddAttachments 2026-07-16-00:00: Pending task-attachment images open in a movable, resizable FloatingWindow on desktop. On narrow touch viewports the dedicated image-preview variant must instead fill the screen and remove desktop resize handles. */ .floating-window--image-preview { inset: 0 !important; width: 100vw !important; height: 100dvh !important; min-width: 0 !important; min-height: 0 !important; max-width: 100vw !important; max-height: 100dvh !important; border: none; border-radius: 0; box-shadow: none; } .floating-window--image-preview .floating-window__resize-handle { display: none; } /* FNXC:GitHubImport 2026-07-15-16:00: Import details use FloatingWindow for desktop drag and resize; on mobile this scoped variant becomes a full-screen sheet and hides desktop resize affordances. */ .floating-window--github-import-detail { inset: 0 !important; width: 100vw !important; height: 100dvh !important; min-width: 0 !important; min-height: 0 !important; max-width: 100vw !important; max-height: 100dvh !important; border: none; border-radius: 0; box-shadow: none; } .floating-window--github-import-detail .floating-window__resize-handle { display: none; } .floating-window--chat .chat-view { border-radius: 0; } /* FNXC:MobileTaskPopups 2026-06-29-00:00: Mobile board-card popup opens reuse the existing task-detail FloatingWindow, but the shell must behave like a full-screen mobile sheet. Scope the override to task-detail pop-outs, hide resize handles, and remove drag/resize cursors so no invisible desktop affordances remain on touch layouts. */ .floating-window--task-detail { inset: 0 !important; width: 100vw !important; height: 100dvh !important; min-width: 0 !important; min-height: 0 !important; max-width: 100vw !important; max-height: 100dvh !important; border: none; border-radius: 0; box-shadow: none; } .floating-window--task-detail .floating-window__resize-handle { display: none; } /* FNXC:MobileTaskPopups 2026-07-17-08:20: FN-8015 reserves `margin-inline-end: var(--space-lg)` on the shared `.floating-window__body` so a hosted scrollbar clears the desktop east/north-east/south-east resize hot zones. The mobile task-detail sheet is full-screen and hides every resize handle (above), so that gutter protects nothing and instead shifts the whole panel left — leaving an uneven right inset on every row. Zero it here so `.detail-body`'s own symmetric padding defines both insets equally. Desktop resize-handle clearance is untouched (this rule is mobile-only). */ .floating-window--task-detail .floating-window__body { margin-inline-end: 0; } .floating-window--task-detail .task-detail-content--embedded, .floating-window--task-detail .task-detail-content--embedded > .modal-header { border-radius: 0; cursor: default; touch-action: auto; } } /* FNXC:FloatingWindow 2026-07-15-18:20: Long titles (e.g. the GitHub import detail's "#2159 — ") must truncate with an ellipsis rather than hard-cut mid-word against the close button. display MUST stay block, not flex: every caller passes a plain string, so under flex the text became an anonymous flex item, which text-overflow cannot act on — the ellipsis declared here silently never rendered. A block box makes the existing overflow/text-overflow/white-space trio work as written. Reintroducing flex here (e.g. to lay out an element title) re-breaks truncation for all callers; give the title an inner element instead. */ .floating-window__title { display: block; flex: 1; min-width: 0; overflow: hidden; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; } .floating-window__close { display: inline-flex; align-items: center; justify-content: center; padding: var(--space-xs); border: none; border-radius: var(--radius-sm); background: transparent; color: var(--text-muted); cursor: pointer; } .floating-window__close:hover { background: var(--status-todo-bg, var(--surface)); color: var(--text); } /* FNXC:FloatingWindow 2026-06-22-20:45: Body is a flex host that lets its single child stretch to the full panel width/height (min-width/min-height:0 so a wide child cannot collapse the flex line, and the child's own overflow can engage). FNXC:FloatingWindow 2026-07-15-00:00: FN-8015 / issue #2140 requires every shared FloatingWindow caller to keep its hosted vertical scrollbar clear of the right-edge and right-corner resize hot zones. Reserve the corner-width gutter on the body rather than specializing task detail: this applies equally when the body itself scrolls and when a headerless caller delegates scrolling to its full-size child. The panel border and its right handles remain available for desktop resizing, while the scrollbar is always inboard of the east, north-east, and south-east hit targets. */ .floating-window__body { display: flex; flex: 1; min-width: 0; min-height: 0; margin-inline-end: var(--space-lg); overflow: auto; } .floating-window__body > * { flex: 1; min-width: 0; min-height: 0; min-block-size: 0; } /* FNXC:FloatingWindow 2026-06-22-20:45: Edge + corner resize handles. touch-action:none keeps the drag from being hijacked by scroll/gestures so resizing stays smooth. */ .floating-window__resize-handle { position: absolute; z-index: 2; touch-action: none; } .floating-window__resize-handle--n, .floating-window__resize-handle--s { left: var(--space-sm); right: var(--space-sm); height: var(--space-sm); cursor: ns-resize; } .floating-window__resize-handle--n { top: 0; } .floating-window__resize-handle--s { bottom: 0; } .floating-window__resize-handle--e, .floating-window__resize-handle--w { top: var(--space-sm); bottom: var(--space-sm); width: var(--space-sm); cursor: ew-resize; } .floating-window__resize-handle--e { right: 0; } .floating-window__resize-handle--w { left: 0; } .floating-window__resize-handle--ne, .floating-window__resize-handle--nw, .floating-window__resize-handle--se, .floating-window__resize-handle--sw { width: var(--space-lg); height: var(--space-lg); } .floating-window__resize-handle--ne { top: 0; right: 0; cursor: nesw-resize; } .floating-window__resize-handle--nw { top: 0; left: 0; cursor: nwse-resize; } .floating-window__resize-handle--se { bottom: 0; right: 0; cursor: nwse-resize; } .floating-window__resize-handle--sw { bottom: 0; left: 0; cursor: nesw-resize; }