From fde3b76a8cdbc159af61aa605144eeda3cccadd8 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Sun, 26 Jul 2026 12:12:35 -0700 Subject: [PATCH] FN-8602: enable tablet touch resizing for task modals Enable touch-driven resizing for task modals on tablet viewports. - Add tablet touch resize handles and pointer interactions for task and new-task modals. - Preserve responsive modal sizing while keeping phone layouts fullscreen. - Add unit, browser, and visual regression coverage with updated documentation. Files changed: .changeset/fn-8602-tablet-touch-resize.md | 7 + docs/dashboard-guide.md | 6 +- docs/testing.md | 4 + packages/dashboard/app/components/NewTaskModal.css | 70 ++++++++++ packages/dashboard/app/components/NewTaskModal.tsx | 19 ++- .../dashboard/app/components/TaskDetailModal.css | 12 ++ .../dashboard/app/components/TaskDetailModal.tsx | 7 +- .../app/components/__tests__/NewTaskModal.test.tsx | 4 + ...etailModal.responsive-and-dependencies.test.tsx | 1 + .../hooks/__tests__/useModalResizePersist.test.tsx | 10 +- .../app/hooks/__tests__/useViewportMode.test.ts | 26 +++- .../dashboard/app/hooks/useModalResizePersist.ts | 26 +++- packages/dashboard/app/hooks/useViewportMode.ts | 13 ++ packages/dashboard/app/styles.css | 16 +++ .../app/task-modal-touch-resize-e2e-fixture.html | 5 + .../app/task-modal-touch-resize-e2e-fixture.tsx | 60 ++++++++ .../__screenshots__/fn-8602/phone-fullscreen.png | Bin 0 -> 43987 bytes .../e2e/__screenshots__/fn-8602/tablet-after.png | Bin 0 -> 52549 bytes .../e2e/__screenshots__/fn-8602/tablet-before.png | Bin 0 -> 11500 bytes .../task-modal-touch-resize-browser.test.ts | 154 +++++++++++++++++++++ 20 files changed, 424 insertions(+), 16 deletions(-) Fusion-Task-Id: FN-8602 Fusion-Task-Lineage: f07ce22f-f529-4be3-ba1b-04063154a1b0 Co-authored-by: Fusion (runfusion.ai) --- .changeset/fn-8602-tablet-touch-resize.md | 7 + docs/dashboard-guide.md | 6 +- docs/testing.md | 4 + .../dashboard/app/components/NewTaskModal.css | 70 ++++++++ .../dashboard/app/components/NewTaskModal.tsx | 19 ++- .../app/components/TaskDetailModal.css | 12 ++ .../app/components/TaskDetailModal.tsx | 7 +- .../__tests__/NewTaskModal.test.tsx | 4 + ...Modal.responsive-and-dependencies.test.tsx | 1 + .../__tests__/useModalResizePersist.test.tsx | 10 +- .../hooks/__tests__/useViewportMode.test.ts | 26 ++- .../app/hooks/useModalResizePersist.ts | 26 ++- .../dashboard/app/hooks/useViewportMode.ts | 13 ++ packages/dashboard/app/styles.css | 16 ++ .../task-modal-touch-resize-e2e-fixture.html | 5 + .../task-modal-touch-resize-e2e-fixture.tsx | 60 +++++++ .../fn-8602/phone-fullscreen.png | Bin 0 -> 43987 bytes .../__screenshots__/fn-8602/tablet-after.png | Bin 0 -> 52549 bytes .../__screenshots__/fn-8602/tablet-before.png | Bin 0 -> 11500 bytes .../task-modal-touch-resize-browser.test.ts | 154 ++++++++++++++++++ 20 files changed, 424 insertions(+), 16 deletions(-) create mode 100644 .changeset/fn-8602-tablet-touch-resize.md create mode 100644 packages/dashboard/app/task-modal-touch-resize-e2e-fixture.html create mode 100644 packages/dashboard/app/task-modal-touch-resize-e2e-fixture.tsx create mode 100644 packages/dashboard/e2e/__screenshots__/fn-8602/phone-fullscreen.png create mode 100644 packages/dashboard/e2e/__screenshots__/fn-8602/tablet-after.png create mode 100644 packages/dashboard/e2e/__screenshots__/fn-8602/tablet-before.png create mode 100644 packages/dashboard/src/__tests__/task-modal-touch-resize-browser.test.ts diff --git a/.changeset/fn-8602-tablet-touch-resize.md b/.changeset/fn-8602-tablet-touch-resize.md new file mode 100644 index 0000000000..993bb1c2ad --- /dev/null +++ b/.changeset/fn-8602-tablet-touch-resize.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Make task modal resize grips reliably usable on touch tablets. +category: fix +dev: Adds tablet-only touch targets and Chromium CDP hit-testing coverage. diff --git a/docs/dashboard-guide.md b/docs/dashboard-guide.md index 8591331d90..8e67f720e5 100644 --- a/docs/dashboard-guide.md +++ b/docs/dashboard-guide.md @@ -89,7 +89,7 @@ Movable dashboard pop-outs remember their last desktop location and size, while ### Task modal resizing on tablets -Task Detail and New Task remain resizable on known touch tablets, including a 768px-wide tablet viewport. Task Detail exposes its accessible bottom-right resize grip; New Task keeps its draggable header and edge/corner resize controls. Their geometry stays within the viewport and is restored from browser storage on later tablet or desktop opens. True phones and narrow folded panes remain full-screen sheets without active resize controls so keyboard and safe-area behavior is unchanged. +Task Detail and New Task remain resizable on known touch tablets, including a 768px-wide tablet viewport. Task Detail exposes its accessible bottom-right resize grip; New Task keeps its draggable header and edge/corner resize controls. On that tablet-touch surface, the painted control remains compact but its explicit resize hit target is at least 44px, sits outside the panel content, and owns touch gestures with pointer capture. Their geometry stays within the viewport and is restored from browser storage on later tablet or desktop opens. True phones, narrow folded panes, and desktop coarse-pointer devices do not receive the enlarged target: phones remain full-screen sheets and desktop preserves cursor-sized resize chrome. ## Mobile/PWA app icons @@ -2293,3 +2293,7 @@ Dictation inserts a live partial transcript at the current caret (or replaces th ### Conversation tags Direct conversations can be organized with reusable tags. Open a conversation's **More** menu to create a tag or toggle its assignments; a conversation can have multiple tags. Use the tag selector beside conversation search to filter pinned and recent conversations without affecting text search. Tags are project-scoped, and deleting a tag only removes its assignments—it never deletes conversations or messages. Chat Rooms do not use conversation tags. + +### Tablet touch modal resize + +Task Detail and New Task retain their desktop resize chrome, but tablet-class touch viewports expose a 44px `data-resize-hit-target` around resize controls. The target is enabled only by the shared tablet-touch viewport classifier; true-phone sheets and desktop coarse-pointer devices do not expose it. diff --git a/docs/testing.md b/docs/testing.md index e4e1056e23..be193e35f6 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -523,3 +523,7 @@ Use the exact heading `## Symptom Verification` and include all three required c - [ ] **Assertion it is gone** — final verification reproduces the original failure condition and asserts it no longer occurs via a real automated test. Symptom-based acceptance is mandatory for bug fixes: reproduce the original failure, prove it is gone, and keep the invariant covered across the `## Surface Enumeration` checklist. Green build/tests alone are insufficient when they do not exercise the reported symptom. + +### Chromium touch hit-testing + +Touch-resize regressions use the dashboard Vite fixture and Chromium CDP `Input.dispatchTouchEvent` start/move/end events. This is required where `elementFromPoint` and real touch hit testing matter; jsdom pointer dispatch does not provide layout hit testing. diff --git a/packages/dashboard/app/components/NewTaskModal.css b/packages/dashboard/app/components/NewTaskModal.css index cc93529d60..f46c593c52 100644 --- a/packages/dashboard/app/components/NewTaskModal.css +++ b/packages/dashboard/app/components/NewTaskModal.css @@ -131,6 +131,76 @@ visible tokenized focus ring so keyboard users can discover the same controls to .new-task-resize-handle--se { bottom: 0; right: 0; cursor: nwse-resize; } .new-task-resize-handle--sw { bottom: 0; left: 0; cursor: nesw-resize; } +/* +FNXC:TaskModalResize 2026-07-26-10:40: +Finger drags need a 44px hit area, unlike the mouse-sized painted edge/corner controls. +These targets expand outward from the floating panel so they cannot cover its footer or +scrollable body. The runtime tablet-touch class is required: true-phone sheets and desktop +coarse-pointer devices must never expose an invisible resize target. +*/ +.task-modal--touch-resize .new-task-resize-handle--touch-target { + z-index: 3; + touch-action: none; +} + +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--n, +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--s { + left: var(--modal-resize-touch-target); + right: var(--modal-resize-touch-target); + height: var(--modal-resize-touch-target); +} + +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--n { + top: calc((var(--modal-resize-touch-target) - var(--space-sm)) * -1); +} + +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--s { + bottom: calc((var(--modal-resize-touch-target) - var(--space-sm)) * -1); +} + +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--e, +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--w { + top: var(--modal-resize-touch-target); + bottom: var(--modal-resize-touch-target); + width: var(--modal-resize-touch-target); +} + +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--e { + right: calc((var(--modal-resize-touch-target) - var(--space-sm)) * -1); +} + +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--w { + left: calc((var(--modal-resize-touch-target) - var(--space-sm)) * -1); +} + +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--ne, +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--nw, +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--se, +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--sw { + width: var(--modal-resize-touch-target); + height: var(--modal-resize-touch-target); +} + +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--ne { + top: calc((var(--modal-resize-touch-target) - var(--space-lg)) * -1); + right: calc((var(--modal-resize-touch-target) - var(--space-lg)) * -1); +} + +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--nw { + top: calc((var(--modal-resize-touch-target) - var(--space-lg)) * -1); + left: calc((var(--modal-resize-touch-target) - var(--space-lg)) * -1); +} + +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--se { + bottom: calc((var(--modal-resize-touch-target) - var(--space-lg)) * -1); + right: calc((var(--modal-resize-touch-target) - var(--space-lg)) * -1); +} + +.task-modal--touch-resize .new-task-resize-handle--touch-target.new-task-resize-handle--sw { + bottom: calc((var(--modal-resize-touch-target) - var(--space-lg)) * -1); + left: calc((var(--modal-resize-touch-target) - var(--space-lg)) * -1); +} + .new-task-modal .modal-body { padding: var(--space-xl); overflow-y: auto; diff --git a/packages/dashboard/app/components/NewTaskModal.tsx b/packages/dashboard/app/components/NewTaskModal.tsx index ebee450274..6403a5d259 100644 --- a/packages/dashboard/app/components/NewTaskModal.tsx +++ b/packages/dashboard/app/components/NewTaskModal.tsx @@ -28,7 +28,7 @@ import { useConfirm } from "../hooks/useConfirm"; import { useMobileKeyboard } from "../hooks/useMobileKeyboard"; import { useMobileScrollLock } from "../hooks/useMobileScrollLock"; import { useNodes } from "../hooks/useNodes"; -import { useViewportMode } from "../hooks/useViewportMode"; +import { isTabletTouchViewport, useViewportMode } from "../hooks/useViewportMode"; import { useAgentsMapCache } from "../hooks/useAgentsMapCache"; import { nextFloatingZ, currentFloatingZ } from "./floatingWindowStack"; @@ -412,6 +412,7 @@ export function NewTaskModal({ isOpen, onClose, projectId, tasks, onCreateTask, const { t } = useTranslation("app"); const { confirm } = useConfirm(); const viewportMode = useViewportMode(); + const isTabletTouchResize = isTabletTouchViewport(viewportMode); useMobileScrollLock(isOpen); const { keyboardOverlap, viewportHeight, viewportOffsetTop, keyboardOpen } = useMobileKeyboard({ enabled: viewportMode === "mobile", @@ -521,6 +522,7 @@ export function NewTaskModal({ isOpen, onClose, projectId, tasks, onCreateTask, const handlePointerMove = (moveEvent: PointerEvent) => { if (moveEvent.pointerId !== pointerId) return; + moveEvent.preventDefault(); const dx = moveEvent.clientX - startX; const dy = moveEvent.clientY - startY; const nextSize = clampFloatSize({ @@ -546,7 +548,15 @@ export function NewTaskModal({ isOpen, onClose, projectId, tasks, onCreateTask, captureTarget.removeEventListener("pointerup", handlePointerUp); captureTarget.removeEventListener("pointercancel", handlePointerUp); }; - function handlePointerUp() { + /* + FNXC:TaskModalResize 2026-07-26-10:51: + A tablet finger resize owns exactly the pointer that started it. Ignore another + finger's terminal event so it cannot release capture or persist partial geometry; + this preserves the established floating-window gesture isolation. + */ + function handlePointerUp(upEvent: PointerEvent) { + if (upEvent.pointerId !== pointerId) return; + upEvent.preventDefault(); if (frame) cancelAnimationFrame(frame); persistSize(latestSize); persistPosition(latestPosition, latestSize); @@ -1206,7 +1216,7 @@ export function NewTaskModal({ isOpen, onClose, projectId, tasks, onCreateTask, style={isFloating ? { zIndex } : undefined} >
(
(null); const viewportMode = useViewportMode(); - useModalResizePersist(modalRef, true, "task-detail-modal-size"); + const isTabletTouchResize = isTabletTouchViewport(viewportMode); + useModalResizePersist(modalRef, true, "task-detail-modal-size", { touchTargets: isTabletTouchResize }); useMobileScrollLock(true); const overlayDismissProps = useOverlayDismiss(onClose); /* @@ -6614,7 +6615,7 @@ export function TaskDetailModal({ onClose, ...props }: TaskDetailModalProps) { aria-modal="true" >
({ isShortViewport: () => false, getViewportMode: () => mockViewportMode, isMobileViewport: () => mockViewportMode === "mobile", + isTabletTouchViewport: () => mockViewportMode === "tablet", useViewportMode: () => mockViewportMode, })); @@ -2193,6 +2194,7 @@ describe("NewTaskModal", () => { expect(screen.getByTestId(`new-task-resize-${dir}`)).toHaveAttribute("role", "separator"); expect(screen.getByTestId(`new-task-resize-${dir}`)).toHaveAttribute("aria-label", "Resize new task window"); expect(screen.getByTestId(`new-task-resize-${dir}`)).toHaveAttribute("tabindex", "0"); + expect(screen.getByTestId(`new-task-resize-${dir}`)).toHaveAttribute("data-resize-hit-target", "true"); } }); @@ -2253,6 +2255,8 @@ describe("NewTaskModal", () => { fireEvent.pointerDown(handle, { pointerId: 4, clientX: 100, clientY: 100, pointerType: "touch" }); fireEvent.pointerMove(handle, { pointerId: 4, clientX: 140, clientY: 130, pointerType: "touch" }); + fireEvent.pointerUp(handle, { pointerId: 9, clientX: 140, clientY: 130, pointerType: "touch" }); + expect(document.body.style.userSelect).toBe("none"); fireEvent.pointerUp(handle, { pointerId: 4, clientX: 140, clientY: 130, pointerType: "touch" }); expect(Number.parseFloat(panel.style.width)).toBeGreaterThan(initialWidth); diff --git a/packages/dashboard/app/components/__tests__/TaskDetailModal.responsive-and-dependencies.test.tsx b/packages/dashboard/app/components/__tests__/TaskDetailModal.responsive-and-dependencies.test.tsx index e08f3170c6..13b252b032 100644 --- a/packages/dashboard/app/components/__tests__/TaskDetailModal.responsive-and-dependencies.test.tsx +++ b/packages/dashboard/app/components/__tests__/TaskDetailModal.responsive-and-dependencies.test.tsx @@ -874,6 +874,7 @@ describe("TaskDetailModal", () => { const grip = modal?.querySelector(".modal-resize-grip") as HTMLElement; expect(grip).toHaveAttribute("aria-label", "Resize modal from bottom-right corner"); expect(grip).toHaveAttribute("tabindex", "0"); + expect(grip).toHaveAttribute("data-resize-hit-target", "true"); // FNXC:TaskModalResize 2026-07-24-19:20: The 768px tablet recovery must // remain keyboard discoverable, not merely restore a touch-only grip. diff --git a/packages/dashboard/app/hooks/__tests__/useModalResizePersist.test.tsx b/packages/dashboard/app/hooks/__tests__/useModalResizePersist.test.tsx index 06a9747ced..974e2fd7fc 100644 --- a/packages/dashboard/app/hooks/__tests__/useModalResizePersist.test.tsx +++ b/packages/dashboard/app/hooks/__tests__/useModalResizePersist.test.tsx @@ -99,14 +99,16 @@ function Harness({ initialWidth, isOpen = true, storageKey = STORAGE_KEY, + touchTargets = false, }: { initialHeight?: string; initialWidth?: string; isOpen?: boolean; storageKey?: string; + touchTargets?: boolean; }) { const modalRef = useRef(null); - useModalResizePersist(modalRef, isOpen, storageKey); + useModalResizePersist(modalRef, isOpen, storageKey, { touchTargets }); return (
{ document.body.style.userSelect = ""; }); - it("injects a touch-capable resize grip on tablet and persists dragged size", () => { + it("injects a tablet touch hit target and persists a touch drag", () => { setViewport(900); - render(); + render(); const modal = screen.getByTestId("modal"); installModalGeometry(modal); @@ -146,6 +148,8 @@ describe("useModalResizePersist", () => { expect(grip).toHaveAttribute("role", "separator"); expect(grip).toHaveAttribute("aria-label", "Resize modal from bottom-right corner"); + expect(grip).toHaveAttribute("data-resize-hit-target", "true"); + expect(grip).toHaveClass("modal-resize-grip--touch-target"); dispatchPointerEvent(grip, "pointerdown", { clientX: 10, clientY: 20, pointerType: "touch" }); dispatchPointerEvent(document, "pointermove", { clientX: 70, clientY: 65, pointerType: "touch" }); diff --git a/packages/dashboard/app/hooks/__tests__/useViewportMode.test.ts b/packages/dashboard/app/hooks/__tests__/useViewportMode.test.ts index fe00ab5024..1640da5873 100644 --- a/packages/dashboard/app/hooks/__tests__/useViewportMode.test.ts +++ b/packages/dashboard/app/hooks/__tests__/useViewportMode.test.ts @@ -1,6 +1,6 @@ import { act, renderHook } from "@testing-library/react"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { getViewportMode, isFullScreenSheetViewport, isMobileViewport, MOBILE_MEDIA_QUERY, useViewportMode } from "../useViewportMode"; +import { getViewportMode, isFullScreenSheetViewport, isMobileViewport, isTabletTouchViewport, MOBILE_MEDIA_QUERY, useViewportMode } from "../useViewportMode"; const TABLET_MEDIA_QUERY = "(min-width: 769px) and (max-width: 1024px)"; const MOBILE_WIDTH_MEDIA_QUERY = "(max-width: 768px)"; @@ -242,6 +242,30 @@ describe("useViewportMode", () => { }); }); + it("enables the resize touch target only for tablet-class touch viewports", () => { + const originalMaxTouchPoints = Object.getOwnPropertyDescriptor(navigator, "maxTouchPoints"); + Object.defineProperty(navigator, "maxTouchPoints", { configurable: true, value: 1 }); + try { + stubScreen(768, 1024); + installViewportMedia({ width: true, height: false, tablet: false }); + expect(isTabletTouchViewport()).toBe(true); + + stubScreen(1024, 768); + installViewportMedia({ width: false, height: false, tablet: true }); + expect(isTabletTouchViewport()).toBe(true); + + stubScreen(1920, 1080); + installViewportMedia({ width: false, height: false, tablet: false }); + expect(isTabletTouchViewport()).toBe(false); + + stubScreen(390, 844); + installViewportMedia({ width: true, height: false, tablet: false }); + expect(isTabletTouchViewport()).toBe(false); + } finally { + if (originalMaxTouchPoints) Object.defineProperty(navigator, "maxTouchPoints", originalMaxTouchPoints); + } + }); + it("keeps a touch tablet at the 768px boundary out of the phone presentation", () => { const originalMaxTouchPoints = Object.getOwnPropertyDescriptor(navigator, "maxTouchPoints"); stubScreen(768, 1024); diff --git a/packages/dashboard/app/hooks/useModalResizePersist.ts b/packages/dashboard/app/hooks/useModalResizePersist.ts index edaec4196c..4680893597 100644 --- a/packages/dashboard/app/hooks/useModalResizePersist.ts +++ b/packages/dashboard/app/hooks/useModalResizePersist.ts @@ -10,6 +10,11 @@ interface PersistedSize { const RESIZE_GRIP_CLASS = "modal-resize-grip"; const RESIZE_GRIP_LABEL = "Resize modal from bottom-right corner"; +interface ModalResizePersistOptions { + /** Enable the explicit 44px hit target on the tablet-touch task-detail surface. */ + touchTargets?: boolean; +} + /* FNXC:TaskModalResize 2026-07-24-19:20: The shared Task Detail grip must offer the same keyboard discovery as floating task windows. @@ -51,11 +56,13 @@ function readPersistableSize(node: HTMLElement): PersistedSize { * @param ref ref to the resizable modal element * @param isOpen the modal's open flag — observation only runs while true * @param storageKey localStorage key, must be stable + unique per modal + * @param options tablet-only touch-target opt-in; other shared modal consumers retain desktop geometry */ export function useModalResizePersist( ref: RefObject, isOpen: boolean, storageKey: string, + options: ModalResizePersistOptions = {}, ): void { useEffect(() => { if (!isOpen) return; @@ -104,7 +111,16 @@ export function useModalResizePersist( }; const grip = document.createElement("div"); - grip.className = RESIZE_GRIP_CLASS; + grip.className = `${RESIZE_GRIP_CLASS}${options.touchTargets ? " modal-resize-grip--touch-target" : ""}`; + if (options.touchTargets) { + /* + FNXC:TaskModalResize 2026-07-26-10:40: + Keep the painted corner grip mouse-sized while exposing a separately queryable + touch hit target. This lets tablet touch input land outside the legacy visual + corner without enlarging borders, footer chrome, or content hit areas. + */ + grip.dataset.resizeHitTarget = "true"; + } grip.setAttribute("role", "separator"); grip.setAttribute("aria-label", RESIZE_GRIP_LABEL); grip.setAttribute("aria-orientation", "vertical"); @@ -165,9 +181,10 @@ export function useModalResizePersist( document.body.style.userSelect = "none"; const onPointerMove = (moveEvent: PointerEvent) => { + if (moveEvent.pointerId !== event.pointerId) return; moveEvent.preventDefault(); - const nextWidth = startWidth + moveEvent.clientX - startX; - const nextHeight = startHeight + moveEvent.clientY - startY; + const nextWidth = Math.min(window.innerWidth, startWidth + moveEvent.clientX - startX); + const nextHeight = Math.min(window.innerHeight, startHeight + moveEvent.clientY - startY); if (nextWidth > 0) node.style.width = `${nextWidth}px`; if (nextHeight > 0) node.style.height = `${nextHeight}px`; syncGripAria(); @@ -175,6 +192,7 @@ export function useModalResizePersist( }; const endDrag = (upEvent: PointerEvent) => { + if (upEvent.pointerId !== event.pointerId) return; if (typeof grip.releasePointerCapture === "function") { grip.releasePointerCapture(upEvent.pointerId); } @@ -227,5 +245,5 @@ export function useModalResizePersist( observer?.disconnect(); if (saveTimer) clearTimeout(saveTimer); }; - }, [ref, isOpen, storageKey]); + }, [ref, isOpen, storageKey, options.touchTargets]); } diff --git a/packages/dashboard/app/hooks/useViewportMode.ts b/packages/dashboard/app/hooks/useViewportMode.ts index 415885a354..43ad02b187 100644 --- a/packages/dashboard/app/hooks/useViewportMode.ts +++ b/packages/dashboard/app/hooks/useViewportMode.ts @@ -134,6 +134,19 @@ export function getViewportMode(): ViewportMode { return "desktop"; } +/** + * Whether a viewport is the tablet-only touch-resize surface. + * + * FNXC:TaskModalResize 2026-07-26-10:40: + * Tablet resize controls need a finger-sized target, but `(pointer: coarse)` alone + * would also enlarge controls on desktop hybrids and true phones. Compose the existing + * physical-screen-aware tablet classifier with touch capability instead; phones retain + * full-screen sheets and desktop coarse-pointer devices retain mouse-sized chrome. + */ +export function isTabletTouchViewport(mode = getViewportMode()): boolean { + return mode === "tablet" && hasTouchScreen() && !isPhoneClassScreen(); +} + export function useViewportMode(): ViewportMode { const [mode, setMode] = useState(getViewportMode); diff --git a/packages/dashboard/app/styles.css b/packages/dashboard/app/styles.css index b6dd1d90c5..d115f14392 100644 --- a/packages/dashboard/app/styles.css +++ b/packages/dashboard/app/styles.css @@ -152,6 +152,14 @@ html { 44px accessibility floor without embedding a raw dimension in component-specific rules. */ --touch-target-min-size: 44px; + /* + FNXC:TaskModalResize 2026-07-26-10:40: + Task-modal resize targets use the accessibility floor as an explicit hit-area + contract. The painted grip remains compact; only the tablet-class touch guard + opts into this token so phones and desktop coarse-pointer layouts do not gain + invisible resize chrome. + */ + --modal-resize-touch-target: var(--touch-target-min-size); /* FNXC:QuickAddActionRow 2026-07-16-14:00: @@ -1344,6 +1352,14 @@ Modal and dock pop-out surfaces should not darken or blur the app behind them. K background: transparent; } +.modal-resize-grip--touch-target { + width: var(--modal-resize-touch-target); + height: var(--modal-resize-touch-target); + right: calc((var(--modal-resize-touch-target) - var(--space-lg)) * -1); + bottom: calc((var(--modal-resize-touch-target) - var(--space-lg)) * -1); + z-index: 3; +} + .modal-resize-grip::after { content: ""; position: absolute; diff --git a/packages/dashboard/app/task-modal-touch-resize-e2e-fixture.html b/packages/dashboard/app/task-modal-touch-resize-e2e-fixture.html new file mode 100644 index 0000000000..2db9a08430 --- /dev/null +++ b/packages/dashboard/app/task-modal-touch-resize-e2e-fixture.html @@ -0,0 +1,5 @@ + + + Task modal touch resize E2E +
+ diff --git a/packages/dashboard/app/task-modal-touch-resize-e2e-fixture.tsx b/packages/dashboard/app/task-modal-touch-resize-e2e-fixture.tsx new file mode 100644 index 0000000000..7c886383ad --- /dev/null +++ b/packages/dashboard/app/task-modal-touch-resize-e2e-fixture.tsx @@ -0,0 +1,60 @@ +import React, { useRef } from "react"; +import { createRoot } from "react-dom/client"; +import i18n from "i18next"; +import { I18nextProvider, initReactI18next } from "react-i18next"; +import "./styles.css"; +import "./components/TaskDetailModal.css"; +import { useModalResizePersist } from "./hooks/useModalResizePersist"; +import { isTabletTouchViewport, useViewportMode } from "./hooks/useViewportMode"; +import { NewTaskModal } from "./components/NewTaskModal"; +import { ConfirmDialogProvider } from "./hooks/useConfirm"; + +const params = new URLSearchParams(window.location.search); +const surface = params.get("surface") ?? "new-task"; +if (params.has("reset")) localStorage.clear(); + +void i18n.use(initReactI18next).init({ + lng: "en", + fallbackLng: "en", + resources: { en: { app: {} } }, + interpolation: { escapeValue: false }, +}); + +// Browser fixtures provide the production form's minimal typed API payloads. The resize assertions +// exercise NewTaskModal itself rather than an API-dependent form failure. +window.fetch = async (input) => { + const url = String(input); + const payload = url.includes("/models") + ? { models: [], favoriteProviders: [], favoriteModels: [] } + : url.includes("/settings") ? {} + : []; + return new Response(JSON.stringify(payload), { headers: { "content-type": "application/json" } }); +}; + +function TaskDetailResizeHarness() { + const ref = useRef(null); + const viewportMode = useViewportMode(); + const touchTargets = isTabletTouchViewport(viewportMode); + useModalResizePersist(ref, true, "task-detail-modal-size", { touchTargets }); + return
+
+
Task detail
Task detail body
+
+
; +} + +function Fixture() { + return + + {surface === "task-detail" ? : undefined} + onCreateTask={async () => ({ id: "FN-E2E" }) as never} + addToast={() => undefined} + />} + + ; +} + +createRoot(document.getElementById("root")!).render(); diff --git a/packages/dashboard/e2e/__screenshots__/fn-8602/phone-fullscreen.png b/packages/dashboard/e2e/__screenshots__/fn-8602/phone-fullscreen.png new file mode 100644 index 0000000000000000000000000000000000000000..519bdd727632c248fc0db80fb3e0354d69b36398 GIT binary patch literal 43987 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 J4+KN$u+OBZw?C&;je$-=_H zuzB{3L8);4gkpp)lIALn%K zrGSs${-*&`aoDYAfK$J~oph zBmKWkp#ndpuPuoM-6DU%owlHfhZSfySm0jayszZ{$GA-kTBpbNmx80IT(+D4SiT*R zy}i9(!vuN=F)%{R32BzTy{FL|^hLpX7#mp(v$~`sQ*$MnS=y=s2TwNr6S@jbOzqWI z`X3%QjEW&*VqSsT?+b*4ZToEhm=3L zQiHYms)KU{fc{sxR;zs6{fx2)smO_h+yy!0S#v{*!o24sk^aUX6AO6V?+;b!58_S!4;SF; zhoOF>l=|v!+rJwbt%!&actF$G++hEGd1P^jmyeI?SY+fO%hMc1yUq?oHN3UAaUbmO z3nByt?94WGy!#Ed1=}waOJJx;>-qH^*f!_qo1&G~)NC~>``3&T`MmlV?<5>C8ca+~ zq^zN){9>O}i2MFML(_3RLI2=vPrpLaoz6OE$#DZAK2qFlO=F_IzFuA~#yJAy&2Mpj z%b6yr(r;)}WN<8ukBMsaI*>F`sm}}Q4I2YpRKgDisH&(WC8|1Y$58VnCMKQ}61cG^ z;MY%pxDCeiN$R(w#6HrT_RhvcBjSyA;%^DThT#A{+gZp2KZZA${IPQ92}K?-Q zt|p53D3QZ954$}h$B4yGcKUC9M`x;H^86;#fS@PHH+fmb2zvPTvYX) zKvSMxJ=AYH{5GBq-X?dK+HRk{$B&5kjtXxPv}6snh9M*)HBs1cIeES&TWbf(46zD{ zhH#E@%}(F1-YPy3^-lg(8arDv@;Vbcdpkz`PBh1qx@13LTeEWC7#Z&q;VRfX{^RpW81cE+sQorzUzI@{ASL~npx+p z^Vj*e*?V{INB4c@UM&|| z@ovAVc$eeO)i^oc6Y>3+$9}zZco?_Iz$ZxVy)c4J6xgpyyM*(>%}hz5Zn0{r5zsOy zJ6rUE4j#y2>eY|ix-~Ny@~WxEG6w;b?-%fCQ7c#c`nZ)~slqd%(~9|eiIR|-UY^Rq z%*H(Qa|x3M$;<3uy{CxdH6<;LvWPMdAJ^^plsqWsXb?^GFy%(gomqZP+LQl#7IY!$ zt^?IMh+LLPdYgT4l7W2(;dw=py2Bw<@UsKU5T1& z(&Of6o@+wS$qLu<3W;CNx_p*)yuQ@7W7}JeRD=}+3s(qHK%Vcmo;MPd8F=Yrov`OE z&eh3eL6h}X6Io6K0&lYi<>B%PfzWSwe{V7hikfTDB`H)~_)*B!QG*-)L|9}j>SQEU z)n8bZ>*$KVYe|D{^gOjdj~9xy2B2KUq^-4OZDrZubwQ+$a2v=1P=9rk@rn12_ChDM?kl4iVsQZ!n@qzUk@7q>vB6!ouGo zz~{U1b2?}5#0yG7=*WVQ%N0|Va`+rE7)L}^Rc&~uxa*$r@On!Ns&sx2kN&Y|U_>f( zic3L48Wv9yezk07FyUjh@IB(7M)~`s^=6g%E+dXo44ri&LMFO8CiaQJbR4&{agYi! zVgWO1OR=d-V?}LVZLv`mJ}>cLeu?{_Ik_3-X+VSedW5ken}FDnz#!VIbYv9N{n@@! zZu7PRv`HXsp)0)|HmA1gW{@e1XgJ+s-_4-8E@Y!4A+IlN1J`?y8U3vW=LDLnwCA#w z5@T+9mENYiWYYe{XO{`)ql`~pWxLyt#JkKf4i1iCKUBVE5KrfFJbajU^9^y4QE-9@VIg-WuSsltn%$09+Y?jWIrUG$po28MsfsF32Y#YC$1@}kb8Ba>hb6O-R86Z!cyN-u}~VOJkcQXDH|1{ z=tC9Bv%{g{-Njtr;NoH3jwb`PAEm{6)!HO2x~jmJoK4?$whRISO-Oc8e#CcoHWlzI z!IZ7F&<4b|4iKMa6;EpW!>%a8d7>S+NMgwlsxq?Gvngx)2+U>-dyg-OMGv?655m-| zJpN7%N-w{#-vqETQ64irI3Re-esUH2%e?3@d59HD0acig%d=T%W&d?cvA0L_r&l*#0doJlCIq|adr`F& z$Hni`5jBHT)aDpw;oToXoPI~1LAT7zO*E*T4k@Xr-JW~(TfnLtj0RrWu?uHdz~zk} zQbc_CwFT=Vj?xP%^v|qvlQ`=DjXLD3-Nh7AN$oVK3@xx&>uos@Ha2g4j&l*jfNd6$ z-o_oBVE$zIA;D{ADv#RL!%I@FOaEv4vHO=6PR z(Wfk2rjjrL-lj5n-@ajzb>-y`Ovk&*b7=|bm&)Tk#z>Fa&%aA_ zio@0FP9nS4#S&=KD9&(bvYp+KYg)U%kSn8o_o-#n=t>Pb>JHOd01zo%~!xDB+B%itlTw^{#1Z}C5~5`s;JXYiui2>^t*N2I|Ei-;&XBMN55 zh}Yse)lRl&QfP$ZWfkMKDGn${U&Ul&kpJ7C{mD%7yVFO)eB!Yk`^_fhB8kHsBYqS5 z@Op_1&sdpnn(v#RO0OLDwq+z>#+dXTnG~>(=ShMq_)5shY4?)}Rn9imy4w+K;Atntpy@Bo;G781%G z$dMzRfnQC9FPXa832U6KJ@FIvw)IrBHLaPJ0T2``3yZqLl#^>^e|SV&ppa&XiFa;Bna>vh<5Q(_n7CXy8)PvpBzkoG3=|@VI^}h;a(nPk)*YO1r8Aw@O==;VX%|c zu{9P?j`04bSMgsGp8c9-*QW@PnaAff+dgSa_NufGXzO52p2)D>j|S z+P%qgG6#F?e0wr*fmV=7IP(9D7YhF%qh@5B=={Da1pMh!z$XoT@@(PwpJ@re(9S48 ztml1;Cx$Bn|0y01&@Tvie}hr_^>e>rs>4uO4A8TZ2EvmE5GUU@*+2_wxUPQl^yHG% zmo5PyFt&4|^w=nDUO=a$=#O=W9b+>yJY3vVE%if*4>~HUe|Q~YQHp{BCdr!G8X#m! z{m0aJZhUNiSs9&@l9Kbb^iUn}F_6yjn-j7!64VBMGT*G^>~g4faWp$U(hks2_>Zf# z?Dh32I5@$wMap4h8k!m;mGKkkV#vb5u+aVT91x8u&-}KVF ze>s?kLY=D4K-Awzw({I}+NFQ}?B97=U;wE3Qv1_8S(yJLN~OX3%{w_2r#Qu-I6MfOk+_UJ1uQ@c66fXXPVtzzi+z? zzsLmB^d#3J7dJ00y~LWD`Y1h}w6yf!b2Bq@Gh)!7w$a%+I61kz%mo)3tLiDHsrrHe zW7ofB<%@p&_v$Wi4*q*}Tb88Km#3Gdvlz=)Zhiu*O^E7G0j@Msw=h!##N0p!jdR;qmA-QFy6IF%<_ z5?6*EJ>n><+qAcrcN7cfck#(Hsnd(gzP%h-gDAMA`jW>P56%kmPO7TVRo#=zh!=W8B52?B5l{-iODZ8gdU61UU zPMj*osPj@cfrEU|mInzU=MGYoAa{)~l2S;aws zPeF^(NSKobX$8$saaMDs0zI0{2PQ=(uXj*kYYTXN3Q_YTE69fAH|)>Co&<<8zVg|; zyv2;4<8}p`@i!4aytJ=SmNBWqr#X2av#W+@Cyr-u z#Jq4L%O_k9WchJ9ou7X92MbQFKU?;_UMhqJ@~qNX-56$){q{$fsw_xpbtc~r#?!R8 zN`RZDD)7<@WzoC;_DKD@v#wMv*f@Nzx~4|6+H&uQ5+#S-lJ{xvRolzMT&Wt;6&NHU zr_27AgyJ*Hxst8OFSe`di}x{0egKsHrc#VZ$alLXM#M~T(s6~)l?eEkmi zPD}($eqFD1CkxCOIkXa7Up$Pyi?wY;f2?@R#>m~jZefVwXpC6(Os+hH%j?5SKo}=mF}2LVM!VA7QM)rjjx{e_*l*ibXLh~+a3R9W#KE36b1~3{w$N?c z%w*Nkp84(v<`+ti@p{#Cwxg<^Dy|!zvgq7f{t(mCDX^Q>)*&)FUoBO=%4<;9;k9O} zi@^ACu^A{gPCAzT+-B^C`wQFQ>PY3a=B7recG|tsErY?aiLGLFv)^j~+3BH2>Ecf& zU0TnsX)ekSnPi3(;=5YiHcy1^-aHxciePBx!^Nq|$;+DwJ|VmAo*pn}Qn9EqjZ#&Y zi{lZs3T#%_$hf#Ee<3K8kGTas0)7wB2Z`0Km-~|ej*p|HER-Kv_6>ik>-ye4ZkJeF z?oVAE91NO+PEeH94tbBzD}1EOOQGxIwGCw}*W1d=%f({wT@EL60F(DhgIx!k!}J=r z8?j=0d!1M$J_wpbeZ9(6PYnM%w;vzU$Lk2=>uW&g{+NMZ*Yfk-!$$J>ATUvV`mmt4 zyRB7c8*I3fNA%S*NDq(K>wdM#3X6_g8*isSO2~aJl3my#*m5wM3C80G^(#t*xJgQF!J#C=z`jFK$4wwj0aExF~6wH(n>gax-z{+88& zB|K0A6T>HkmlWj6VlBQ_6bGo|PiRL6xlXY?jA92o(MUR6yOpP{>2eS6*r~|xItwv# zSV9)I9e1xZUs?Cc$1d~`TG-0_I4c6PWAqx3mVq%mtBY}NsO0f)90<6*chKty=kM}! z;l$r^a&ivFGe-solUZD73=s)Av7cT&oSknkI^JB5XNy}~TPxciYm^FQGg_RNnoUL) z^n8Oc*^Kt#^V0c@JWEx}5%D=MHv%BWK*2l~CIDUG`R?RnJk89?>g9?u*v%pWVS!Wt z^pf)9r~>MsQgEJ4B2pLon4W?{G)zKLGL_4OhGt`W8rBu+Si8t3bMp;}U%lCy`s0d$ zFhM%gz|PKYpvU#z)%E_K=X7(k%IL*4y#euG|KqIMApp&J{%le(eV%(CA-b) zVwnc3nwlDLrYe9l)pe1e7aNl`U58vyePZV8bosFEt3w)3s;0B_=j6Q0Nshs-Y^r~- z^RUB-cEHyCW&ftd44_?%O?F(big($)j<162=d?O2Z%3+|7P{@)I!#!MIk)R)@AK28U*(#|CnrLY088z_yw>jWqA*CREdh}Ie$S^%txY%YPcK;mF+}_x z*Fj!pD|J>_I5}?Kt+!bV_wji-|$Pv?l9@VX(9;Ah1Rl9tQR zMU9@_%V|!0(CI^59l<1)rB}XQAkUI9>Rp4kSy$GDBp6#3@_YKw_uiJSytxl*sPxIF zu7tL9=zKYhnc!-_u^9Ns@bI?i4$%nXU}foBFI`kI)X|P@A@fLSX zbUm9#V3!jV449T_e>y$^7Ky9NEWfe)ySqdw;*;!Fhc`&1Y?T|t#&h?JwFh>a_1m+D zjVu0@KQ?gWZA9onOr!XZgEURezp>@hdwa3Q+Vv_f?IKs_Pm!Kq) zu%)m~u#jAypkk37F zmk>fNH5PE*(EU2we>g~s)Zn;j5%Mefd;J1|xXtvq?8b9i2SSy9%9iu&bcS@`roTF! zP%@nxkCf?leqIt7*tmpcl+IM%t0hg`BJ*H z{e2Nw`bW;^t0@xNUJJgD?@+JdSM-qqub^8!cF%9tW4t0~p}JDzH(_C8 zY3vQQYk==^LrYm1eKrW|6Nr@5h?!g#OEEl5+F;1uzmAvqbZxIaXAA{Ybmpuz*(o~b z56`)y0KVn&g9qb;HFw{_3ac~Mb$Wdv8{ArB*Q|^5a(tASbye}x9Y*f9P$tOb#-Jya z>#xt7U#xL%t2W7SQJ6jjJ|OTO|8wW>-+y>qZSvcRt-riIb_hx~_B?FxyK=J}zSYl! zzf}cup{tC8{vy*g%RgyT`Dxl@+b3W~ca8&!ywN0yR(WV3v3Qqw2U_FzBFUqPB$V z#d6g9c#@tUo5?YHiaU#n;boQb7Z$na&$a(&@$UV2PJSpk^49wcbcOOq!rsL?=7;9jfGO6kjVjmb!r_er?~ zkS^ULgA_QAmFF8Zrqw{F(~Q0V8zORlx(4RxlS)aV#GlTDCe3y=@77<@en@arW81bk9gI&J^r)6=M0M3z z&XtnlcvJmzV5J+Yjjs%;7U~IB4o1^xS9V55CN^sAE*ds`UJj>7)$yetyt@Y&U}1^t zXn!%!WJFX+43t<~I}rqo_u!&1-bp*32gGtw9AoD^|7*>Q7n72M7_3l^8$XXd~d zlxVMgQvLBG$3c0x^a?RD!erl=!ld1FdpT{Ti=&t9o%qcXQ8#8=aBi16VtSRwS{scu z!2rM7(4cOOjDcPC5e*~$w#KXivMZ?zDo5o=VauzbMsR>IQ#^Saz-QhImk0*>VKLxv zop=GF0av7|+MDh4{c(Jp1Qx?F?VFyzIqB2`v$jEtNi*Aa70YMvGr0jmmwzfI3=GNh*QB(BJQ z4Dn!Sz{(+62BX#^u#KA%oT<5wm5XeaPN_3U>>bu=ok=QcDDX)9Ua*x)y#6h`{QEX0 z>7{BHa^bPI7^D1pgqlpE7cVTGP1x=uiPT*6FSPnUlY$EP62l7<3v$$RFucML(FAP7 zc!B<|Z-zdR0=t{pyM%@e{{_g+AZSbt4UMx$mNo8U{PSu+BQ`RAghWIKUY#jQ{a;=! z6rM{50CCYS47GUs(;|?iWI%Q^LPNXn_YdsO8S4Kz{vX&HE|x>mr|_$Fb@lX?E@1@Y z3Ir6NEt>b@P7X*72Y3)*P~aZYzo$ze@%=yVk^BoREl%^u^Q$jg!wV$icMv8L@LNES zEaC?_3dSzMwxGyEWn=!0F4dgSQ}qExtB^+TYs?RPCd^0{_|Z&kK%2(Et_|Q=C=20V zIV|=+^5|JjKAnA3Rv7{iKRg1$7(Lysu3t+dK1fm?Kx-g^=zdbEL}Mnvx6n9KBWuM8 zt=v+uk7Xex6*?-}Zr!1X@XyIf$uEwpW)|IA#Dnc$$R58WvM>z$EeIHSq9P;Vhqs_n zLd5NPyCCF;|HB<%9Z@+yM&r3=rK&eNs^H6$q>4Y`ebXSY=qonJZ@mhY`>(0C0Bsc( z{~W*0qnA5ayqURK6HKFrAX0+Q2GCPXn`VZF0o6mdx3{l`Z4-j%81Qw#RJx{?)V_t< z$01Y(LAg+3B_xoDz}x2s-6{F3@+&fFW0zDC=lz@J@Q7UPkbs$3VNsUL7&suaoJ)4;4Ak1eV@82_G}&seq1c$8`B?a_>2t2K;XBAC+3p;cZsiPTMX@g za{&NLf9P7E`SEGf@9vl_2qpW1I3j4>$CI0ji&_VRh^WD5#Z~kW+YJec<6$_7A>F9= zxwJr2Xxg-DX}IFwo1SeycJznzviEKOVI(GczNBJjgez)GcEYjUsf}o|O=7mE9@u zpIP^Xk_tlE+-e7d+=9w5#30nskciEML8GA4sR92L7Z?a&WJ=KY_xM2^wMv?`-o?d6 zgWM1`20ekr{`q>vd`Vzj1?wF_3OMLKfMKGfQqO_kzZllbD>OEg1TZK5-j>DZXJ~MJ z4T5omM6X<5@*5*$_6|ZWuAK59Y54BQpu;(FMoI_a1S9p@-P5h!C#r^p&}<>d$|{ILkM2jGxcG_J=@ zf0WTcv`qS!qpT(;F1OR$p~9@$VkNV;W*1C_G{e9UC77Up8rxQC?R@Pn2#nz|XSh1V^@t4yXxtV;s zudauSASFR3@Aqdb8$LJX{{8~`H=SxtCr1E@>(SWa_dG;7Qz)Z!*YzvBbDV%1Lqu$| z`{_n%#Aqq4$f;^6c>NF#v8B>s?OrV9-!ltrz973jqTqk=ypv&`X-g z)dXzY?V$*{ys^Eft2{rG0z*g<5pWzeom)Mj)n$tLG`Kw(+-~l>2?H_JWtu81S2Ia^ zK6R#NsTifI-C)z@S{x)dMC~txBMl!MRvZ3r01;t?foI!FC6cIyD7vRt`yp7_WYti? zQy{ZaKX~9PkF1v#AFntxH<#*2S$bkHEFwb0eX`RZWeWuw;OIEX$nv~m&Us{XecuPSNV9DZpAF=T ztr~2-9!?D~P#fLl!7lA-bs|)dan%*WODDGi`kt>Svo85bcqbVtDGQU6vBBx+>9cr! zG-I>$fbNLQPAM8uz&fnXpxJ2uRI>*?dwn%j)=5EA=rCi7vPF1FWY8ET(YB^Y*#HGv z)}4z+`(p%wBjS5$DJ@bbXMi1^W&SZpzKhiY;2_CesQ0|XCApq0PB<(>AY#TR-~u+_ z`jc#Mu&~!xSH)@_d^|F;(^p4IlyW&{SA9u(zin<$Ha;r--Yc{!Gh>I4_}?#Ivi$T* zA>c5p!lRhBA&2^X1kXcNN(ePTFFIZ_FB$f(j0UQLT5vH>yog$nYHv@MY5{UZ@WQLJ z6BsQ_$0ZY&2}WZyx!mlskKJi-AKI?op>0ltJz8ovL2F(9cxT1qw}>Q@jsd1Ep5lQC zo+wfZg0+juoVKd)n09K=ase#(B*s+)!2a!SEa2N!l2}@y)57l4AF1QzYGi)~5N=|_ zG5oJoBtWu7z*EQjJ-{$h&{BOnu$}4_@%8n^2J?JqbBiJ14M917eZ?Z8em_gnThrD- zsWZR&9g0Lq$YcLq#XbDW8=MBPr~QaQ!T_Y5X2YlJei_^ge)nv*i*>CAYhJJY(_dp+ zRo)M64@|uj))0PKKZ>b6ZAyVnM`60#Zx|3L!80y*fLnUv2zM_sfU8XB@&R8Na4x6!sPyEMx&D|E|R z$97PfbJ!uZP37+_|I=+S*R2{A=eh*0y|#*qhPqzmAN*UDFM*F{D37Ig-FcTr43o{t z?nFL5`Oig&gI^92We^O#Vx%gF8)~ziq#6(+Pvt^}B1tW}*JGnBVEvg{5>){fJy!*J zIRIFS`x3}JceDPx_GUnd`0Kgsd%pja<6{5$TK9tt^1m(MMpW zmr>&FR8u==osyAgVs373YmhUb4&n;|5jn|wiHnPem%BWrpmyiZn_HWUXH3fvNLng2 z;Tli4x+(a1%6IifKeQc?1(VGR3JL%tHsqH{c^Z9mutJ`%UvYfE@2HPX%?V1p+01pn z9#bD3esa|-`iyD4P=4lnUWoG4i-6y!#xI0ODR4-oM7*|1Ygcf>uQCaXj?4mX_wm z!gj}~!hQbykigK5Mr&m~^=|?R77h*$Hr9ku=ah_$;{14^f64dJo8(`5;<29Y3^KiV ze10OvaNhfwZUFJR_;uc2#S{-u2zJ(+TtG}}u`e-B*u4gL%13v-%2iiI_Ev?k_ zVy(sPq4+FN$6CF^zc^oLAUbx0L8qlcy*(h2WBHHG&52#dP(K+ZWfqUac8gudj$dYn zyMUaWoO)VD1_8i;c6nX=WkgYe1}DoC|5(iIbNTw#h{gs7_id9$q(QI?J$Cwog(4Cx z*Lc9)LiYltkmsZ+pcf6l*Y*aahwP(Ic{Hd=$ zUn*Uo%<}#Hg;y3Ta{lj%ENKEx!s1LNu|pZzP@CjU#_;*G;qq*;4ws8=ttUbP?AXV; z2bBNo>+1yn+bO`M8<>m*-(an$-eRhWf-rc!<%S>rE)3%_IS+q%&fRpe2=3#>=0$C$p z5(Bu3E^yZ=Wixt_=%HluxqMx!hD*b-3=3qk3bu5kb0Zv&$*h^*4_0bTw|;f|?P zDn#Vb3mdpNyfT_8kUO|4U8v~VS1OR*^JBN3MfM})c1Zt#`SJ8VK!iy2HJ}`ki1&KL zuA>AsofQ-ZSlPpOxv1+x}%gxfV1o`PMNv{nMdUhr3 zx{8fWElp`4WY9^@FFH|q;aFK^^wwEf6O0WlEV@3NU0u7gfKn_$P$HtNdjc+O92^5i z6<`dR)vY2U;}yy`j!>)1E|}@IRBVFKo}RpyQXj2|GUyXf+3-v17k&BeF)S1&Yz!gQ z>Q+Lbw1FZ&FT0zg<8BiP`8)bLe>%6FF0j6DssX04%& zDjUIWqrP0GbiPB%2I_Fl>!PEO!e_=5m4BfkgS*A`Xu4EPE}4*-nHf-5FXmb}c2Pa2 zDr8pfZB}y7a0v;|_s&%}z8q6@z(ZAWsBh?I%v60qks8(tQ z_lWUh4P_f%v_F&-Epl_|5pX*vQ|;I)4bNIIp4ROQ#K6VLdmIuVf@47Qii}np4PXm| z!RtgdHnp9e3X6(fbxw4=D&|{akaW3ict^}v2*}14m@5Y~m@39A`2u@E@V}x>i`)eO zQ|F5mlw_WPuA@JTwred~8d^mBp4PjUD6MHb3QK_!5P*>=ConWy<1iGn`C-0%Tm zc>{&qerTWxP+C`^+XiHwWT~4P8;?GjA%Y$rtT(%q0wSfa%UjTw!=Lo87yN85n(dAv zy0)2xNt8r#z+M*4>t0$NE(0|WHk+u;VuwN$`LmFk>U0~>V)qHP6YO9-qs{Nb*WRA# zgO!$6s;5k!w~LYXb(7XWgoKMr5;{~ev@IijF6xWV`;yrtabv?|&-3$&9hq#p9XY83 zWpoxWM(97BNZaFtWWZ&Am~HP|a(PwU2L=fLn;l74e3j&-^iQnR%nD&1Ks?+M;o;4} zM2e<R0?jM|;wmQwju0=3{WQW6&!@mOd zne8{fB~ykyS>5ZYv)fG>-s{z-{1G}hJ}!|^1s1Q%5m>+efj-)T>ISz>5E06s8MjlE zh;DY|!+*R*D)d^Sb#;>%be8MvHu5acIBlC^&5xB#%wmT{Q*sI3aqBC z?(HP2qs8s4pF_AI462N-JZKfb$*LU!V2xRPubW_mVAVZYTLxP-+&=fW7H`jY21!F0 zY!WsKd&zGH*0U-=Nc>W*nE~E#c?Q29ALNc`G%nlCSqdj3ATO-9`*4#&$K?n;+yj+k z)xu^n_Fj~h>CjAEcKBE+eLFiO83RSH zF*z=#2P!gQ6W?m0$PGF5^j(b;tgmQL7!Fml6KnfDEz1s;RI#$av%9u?Ki?*cn*`zI7*S zUS4oy?B9VF)e4aAFH!&jjFG>g@2bTrl%3q;ExhQoF>R_bZ93(OeE8Ll|V@_kjf zG;3Q9{zC?#7-$X{BeD?>b?2^boE#hk{5xK^;fi2Je*?mz&=ieINsugN>n!IV4Ld1o zgvJR273Sg_JnroYT?b-XAt=If6Z56+Ngt>00Z4lx+)R9f& zLSV4T(T8|~kj4=VwhxrWcw*!bYAF}HwX~Q&-(L(Q5M$XH7)&);Jpe3Tb$rfk ziM`XqA%}gHKO&z9iN2*}2;53nSDcD9um=(njl^a4EGrX*$K_hp+j+_)5d~Vc%nrj8 z%9sD(@mTlvQqMdtbz>YIA6r_{rj*r7)b5X^Hf$adWTc0}6IoERGDCNV3AC2zxO;lc zmFT1;qNtRp2+bJog=+HEkzAF`3!>Qj(wCR1qfj4*0Q(`8QWdrI-~zV~e_#w8^P*{s zu)^n9#GvJ%z{3W|fn&BzF?fORw-f+g68nsXhPwa8`mzN!R9XwDZa23j!^4#0Bv0qEU1$*K2$Be11-wuiV2D z(AGY^FHc)>IW;yh$%u<%_IMs0!<(l~`wk0dIigbQ2O;@2s2%w=2773|`+zXh;2T}m)t!L&d zZGA{da~G47&$Kv9@(ORhOT1^vxGr?EIX!VXtq9cwv_syeKvMzIO>#TP_Yx0pu`o z|NMA`*@Z9QBmtsUk{EQq&B5UPMhgOq`4PQb?E;5tUX#P@c>)FnL~idM?5#C>2wkD~ zWQ*=2;Bj1)s@ZLII8}dT5m4oX>w35#`r4@HNw=nNo|c>nR9aSO*JD4hx1Y_X)J~FG z;V!nyu6d4N(r>CkoLVg&Exz_n<#PVuYyt}IcIwLa^S)2*Q2w^1RlEN=YbiOL1Ll=D z-@1Jl1HX~V4pthQy;wIe%->uWZ>!sZiH5dTE9a-&VC@Y|)H~=_YPUD~j1;u4YGVsK zR)EZUIV#4V%1~c>^fs%|Dk{c1@Y#dl;NTJPHS&}25%PcOa6bBDoSoXhk&5#{GD>=P zOP&U;BMwxmB_t`~cH#G=+Gw$_w>T9_)OG@uA48a6(}Df^1_n)L2lqg_L-r^L0-hd^ zpXrgZf+RQq&i<7_d-chHtiP|<^=MtF z-r5{yk^0Xk19UvGAW5M{OP34vp;;+O7Gare!qyUH5j0-c$L#PgmFBpMpptG^-Ax%Q z_21qQbUpVbnE;;W{$k1Hb};97osBqvd1@;3{-TeDZX%t>zYU&%57x|bV15j!m9k!H zmcck`P^^MON2Np@n#4GstLzBDyT@aKwsh3Lu(j4|(DfE`CeP1To108}Jb$9S z`J_7=JD!hP{PA8DPoC8XbV7MQ#o10Up>Xe{;6&jh;FR7f`9|7V2 z52W=u0d!P)%-iziGlw?N(5vC|jPO%;rE;!y`b1AIM&jUwh0gV?ngcW=rtxgC21jMJ z+>CKae1ppu$U*};F5Z`BCoxX zjf>cXfS&6Eq=;DiUO%Fo>LiQe6!BBzr@uLw$r?Bf)!FD1Yp+yV>Ym-{oh}>Mfj6Hu zG7ptmSj1jd@Oo}_V|*?zE4Qb~!UH9*<8q&_iuKlT6tP zXgA&M7xj)uhFh!ZS}WiBW(y}q2azje-9-uT_XfD_tG7Y-49t;z(I}+aZ@T!ubTg{v zZ8?$cNtvznZRw{ZjC3RxKv9askM70C#%6Pt1c*kH?tXOw$ojzZ^)3~>$tn~s^hSm$ zbce6Qw!sB^8u>Ipjt2{TP)JlNj}LBm&kty%K>C8@Ewp=RkXwq`Q)PC)bkOr!FnMEL z1#f*2BSm24ML!lmG{cez^?W?6ewE9sPSg+mro0;wgPZ*Zhnnpxbbf`=e6J7}CrxiZ zol|7Nh+uZ>pwDu{yCMNvsnzkBn5 z{%tz$^gxs|)te}8VgOnR)D;=DpQTM4Ek(k@#@aeQVRp@O@+`*l-TPyGttKuyIyiC} zh@VkOO0ig3?&s3XQ4kRh>T%Yqk@wZqTD87%a&`45Dwk>?v=<#5N1|-{Shz1&7&(~g z0s8&~Y*yTEuZqViHS=+PAN(GYh0qU$DTH~jS-;r}kI}`GE#0Pgb?zOIuwA=3cpaNd z>EUp5b`JmPYY9PGsQOE_8;0Ilh}#RQo#dHLn%=>Ic@aFczas!FBbZ2&(RLDJekBk;`+&H4hsf4yGc*H@l?9{>id%!YGPw_b&PAY$ zHlaW|6pWDhP^aE<1<{t8b5ksua6#hP0ZWFx*TZh69_ZxMTX7|rRdW|s=X{lHi~A8J zGiNzB#qV={822o*c`G1kVC&9??x~o(%N#&cck-Cy_e*6M; zdpH-GXy$B14s!tK8AHMviFgS-JfeHFz!L=`0vzD%n6vn`J~d>pmHv9b;|xNgV*0U0 zSZDQuxx~{|N1Nn8Ztw-+tq#k}I9x4^Y`?pyHa71np};ujte~)CFzO+OJ6E=vKRxIt~NoTt=CaYLd*5 zVoQG6EZ-6^9o`P1VJmip>DG4cS0SYA&bV+mL~Zv!@_Yt;ccj1wFcL%DYxCvkKi}L8 zBD-lJe+5FPANgaC30zB(w?;0|(V-!fq)F30hK$4r2r?X6rI%%c+Kd{VE~`-NNk(!V zr~b_auu2e7`mC4^iB-#2F5(YB&vjN!)sNvZnf7vzbGms`Ii2+11%^iT#z?G8XJ&AJ zS+k#c?&=Y{;_c=_<1&;K5c4`IK)CFR$+*NUp*mff>6u31IPy^B^ZTmJ9=p$sM)CGC zp%*Serq#w%JBf8i87$!=amMY;66;Ms3&r5EDD22qdHalIYe(f*ZG|+}rNc#5C`~g0 zW%6~3o@TtaSGi3g%E`jY3`t3KOndfK=u;WfWH-=C502Gy;>FzKqxk0h3`)h`nkIRp zfE0=HbPsJ|`0eK9pV*+5~YGosK=KeqgmTHcvsk})ogoZ!bz{w2S|v!m0E zF*mWdkdF^2X6_c{kJ*)M@3GXnI6Y5ShvzGOg*x(S3rLT|9D zbq zZ;$0pP6SXxFf?5<5ww>pMrRL6{EdM88%q)f9sd_6{%gETt}sCp1ze&1JMpfBUMUSb zd3@e#IzA}^p&kX0fAdKqfUXKv{@!)&G0+Jq`wEM zcK5de0s?w_gMjX19Ui~vf!pJmiGhY_>*tUCF$r1ORK61eCnq?dw>TlF3f=bJo253Vmp1MOk5{NHZ$d)Mde=F}pu+KV6AO#JotbGxAtL_u1~aUW zPpu`OMH9$eEbfb8K*zSWyrJRmg>u~#@(f4p7huZn<7Odi))=_mIh}XS0XGt%$J2H& z@Du>@uO!dFRsmYBOW*+r%vfFJUH)_O>FYP{pJlP^N1;doIp~Z^rqEhC&Gzfd{r!Lh zqiVC<*WXKwlk^=hY;2tzp==ol@~wH^!uq_5CtE7%eFTF9lxK%<*lE}PsVX_$+dENP zm>#z5S)MzF&1Uc6dxP@yRPk?JZ};dal~ggGDPrEi`gma6SSamLjq~X656lshSHxGo zQ7y-1vv}V0m0!fW;&l(8BFQI{0L1+vcY3;bM*3>p5>*7l?nFTn56`DjH!wyW4N*Qe;$nPtW2YqyHoW zz_1F)tZ^8=&FimWzi!-3|2WAiRzkqLJo`Ta=eAW3#hZTwgf=-%ZIlezjCOKC8IPm6NuNW zw;cg9->vm~Ns(ybuack4^*`EDtK>60hgw5(EIQW#<0sT@wg)gj9n!^8lhN+t6#=&! zg2&@G84yDwGIqEm7!?Tlgq++2pd{5tP`UzLrA2Afd*_)=C?qP#u0DgN9{6U)oZ;mDu%1>>?RhAEI8Yw>=w76TPB7I-KNnV z7?{dD5Yxfv@-!#}0zUgeCN_x8R8)fU_D?jdL155Q++JPP+1ASvzFC6KseC_Q3 zR(5f53apLfSq1Ns)Qi{0Z)$4kk^31RPbb`Mtzf?=-roA>a-+$f#vn|RAz^pdIA?-< z0I;?Y>pJde*8s|k00gr8{TF2$5M|Rr0szTb;Seqk$lyV%CYH=?uFFb`%Z~~$I7O1V zo=)FgvSQal(nbXWiZ!wj&$&LHDzq{!2K zPla!if+qZ2%z6mPl><;rauTwtC1T+zf3w~eG-`jvw6%e;Tde-U*(M4N0;Et$nRvkV zc)|g_IYHi~0uNPts`*Er#QS{|=c|Z3xGwgqJGRf~uMz=!H7+~P2D$x%qJmHgpD3Po zwQ+g2UvwX+N*TW!hO9JLZv*d_8PCfYa4A(|!Jsm2H`#f94-ENYfjLMTc)r%=dj?Ai zbjr;wwc(P6L(nmrVI@62J_4O|s?KHQHly^Txw*d|h0?$UnEqK0Ali0-*s}j8IXg_z z$8!b9qU`SO?wy_O?EDT~t+v38TEoH$0LUPY6)FGe1TsKPWM!=dPzRv7G^q^%D-Ovs zBqWdkg@}j<+;RZ2FH>f!s;W0?9#~!mm=SD8xHbBJ27bc`-*vG@p#fkD&<`pz7v@RR zm*ic10fdR;SIFQwE|czecej(VDd$s7WJgCwDT%+@QNeRaCxfP9w-8OaL=WP@P3Ujg zGyz>636~|LFgY4{p@BDj=)M$L*fsD^sjM^1Ttp5%?)*`eD7|=}a2=_6+J*ja9@2lU zjsFt7f1i>Mb$4$A6J#$)g!0XHkM^!IEXuY`gLDbvDK%-B(StxhH$q*uXa%SI~T8w znzp}-h)7suIm!R|gVEDrZ|$MgQBMa-h=f#TLeh4l^~%|`0=Ebq1H&1;0u8+I@NlB( zMro0lSf#pWAPN+Hy7E9nqlZH^sr;zQ+1i;c9@)Ty67c^w>F z23wISu9^VE%6(Dl&49~msg*nS)#J4dy#eOCYi3_IJ{g0<1s){jy4}Im96!2aQ8y=O`~cTYN5y~vBPL6Cb8~lNpO%5@`s;NsZ`|XZj`4tZ z0`_u1$2qNzl-M;iFO7{wjk%IU2!9g>vQh3!U#{Nz>ZwF)Nr?w$_Ht~j798mrcJVjOr((FYB@XtdTSM-!J;hZsgs*QtRUgQY`#1yXx@|VJ zZT{rPn?w<3>y9LGX2h9rk8=Oupf_8a{3RIv82ylMMVuLGA-6TQMgBQJ8T$81U}kd$ zLa(#J4Sb1&R+uS`Py=^N!|HG`+4c_VU`2zRJgog;sf?^F*gx?yEspy9w~vL~glqeA z9!+EKdmuAiYUb3rWBiA;wsMk^lTpu_?{hyd*UY$oK`AG`4&|ln+uhcyX)ylyx1P=O zS*Wa}t|+U6gcH&ONGz+?8~N&Cj8)yzBl{QfO?az%EAQRa#nlOH^#j z{kK7~g^KwX!4Y9mM4DXN<>X2K%T-`Rl$6}loW=5U-M*SCUAD`=J@yv)V&(hSOsyP< z?KQ?#!@jC)(7h4Cs;;3C$MdlC*|OHLCuZ>zI2nu6??^ZYm-3dJp6%-Wt}uW*(Gh^jdlN(LYZ~fB@I?@L;~!v~8%$ z<`k5F@!P#7aukKMgbA0f@FL;7O!ghhlPQq!M+QD!myyni3p4G55-}XWsc<+*d zLhS9HZSg!harT9zwJ}fad;`VHD?1OZ2Fqo?!bLB$|Dh7^dxL*S#Qv$e(G&-x2lv89 zqw{%JL~MpgSC>)mQ7n@OR8H~~Hpnx&E1vhcy|ZfMZc7mHNGZRqk&%%xtH3Y3I;CE^ zm>|opyIb48U1?~VPi}^%CfHPsrfXUP!2tfMX6qKy>6l@(|Jm9=OH52m%q(r{S_9oZ zyO2I{_xi6gDO-He4-}K{8&5I87-Uv)oM{u-a6jNEGp^yKE7uP{2fdS3wA7C` zPtP&^6O6bOmkNV;JzTrPAW6gQ=Zn(Qq40JDQQb2+|0$1O-b{pKlG40>UG`{YbzR-J zV1R&J$#<{(-z6orJA||&I5{|8d)<8ppvqeEqMS4+N1onF7aSRe!|wnO?<`$JMRJ;_ zbDzhL^264rV$n`*R#sLpoQjKAoJ)A&2WKYFhUv$Gr`Fah^nm(2cf=!JWcqt7vPFlxckZsPtb#bN^wTyw$BUy; za^N*p&^J9XE9T7kFi}0p<8X0VIa+{^&t@<589d7I4zc5qbz53mvS~bNXb8j=v}0c) zE4FHW00^wy;_Pc@PM;OCgX8ND#3X$5{-i|p6GkCEHEkml-qt~h${XkDb z!QOJ2FC;K9cG!1oyj--YDNR6!Q8JoDsYxkgW+@0i%-aAq)>Ke~=T@F{IdrwFGKd9H zA2&6mIS%i3e(dB314u%@yYi*%wR}t8Ge5GO?MHvmx~gTDim*+rEJlS%F?^^AyMkIY zp%G`l#7-DXQO7F8&A|N;(ux75jh5LT)gBapz41+=uw^&*y`N-=s^=%yP9?K_$$+yQ za$Y&k&&u7k+v!H6%7`Wyw|B}^Lh>X&E8!F(%@~0vXcdB}Z}^!1$uG@B*Wwz+!O>B= z&hz-{Ot;_G{taHb=tZ7i-*wqM7Om9u z^u*M7xW$+beBJ~eCrMrg3f2BR-*PFrWIz9mp;*Xaf$!P-c{VCG)^#l;RrObO6?0ff zXlQMBncQ86%HyS8FPcN+^)+-StBjnuSLkdiXOAIojjw2)b4PDW+{|wW`@QPlH786t z@{c=m=)Ew9QCSSKvJ&7)@Y&Q1nbNe2aiH}(VMnlIc8>VCVtJ{)`8+-VXoeDTc4lS} zm#4mmgHJw91w$;}YS3s=uAJNV?>u?=pgRAvM)4W|gZN*k`EK*OyrZtw7S*|ydr5F4 zOF$C17X3(7e_uNTtuUEYsDZ2N;gDuaNt8l$nmU5LC_B%=(S99eMi_>2o{N6ZT5L1w z8%&%~hq-34nU$42Ss_Il<(lM`Ev@YjZ&qa_{}#oKsC z-R5Rzulq0wrVFw)84U4A#Wklza*-0y(&~Lr&`^)OK*U^~oBv6hzN*x5sZW|<2{T$| zXxQ<1|Gi&gqTa91nwe_T>5#g+;Kif2oow|@vD>^n;!-S7mtATReSN|T=7xsMiB`jN zZ#15^`Z$4H^wJlXg&Q9({^+Tfk$)2NN&6D)xQ5c7doyO0U);PgEfhyV$~%6`5yH^x z{2@a64dJIii8X{OUoq)=;76YJq7=KwxN4*eE<=I? z5i8#f$gPJE?+{c^Pq#0b+O-9yQ_j%0&xZ1-lmP()9BEt_QS!mVZF1RXqV6M(3SH}P zU9W>mIO&!rX&bE_mW^OzOJ2q!94~HZDTc?33o{{@=$M#ZP?1eo`A{Lr$>UnC_><~S z11|fqfN8Vr@7x!t^v}`ySw~>UX&3;N9V6?Z?6tA3I)bk0<$;pSf&!9Vyk}AZIS(sX ztb)lVo#!VDe+iC_UQ|#~k~*L3KL+_#SZF;(vU6-y1afWr$s3Ff4UM&TU#VzWS&=qk zQqJ)QY`kK|xlHM7vp!TQBp`r|=DZ2u*do5=sB#AUO4N;Wuw z(ALh$V&HQMbbeq7vC&@VtJ_A=Ua?x2Dvq|DqCHivGcjScWNPOcUHOOmE^X0yZOn0b zjt6A9ih+tYci;L_gCBjCOZ$GteNGhWv~h>FV9awEK8rV9V_s#w;?#3K6urH(Gv9Vv ztb)Gv;1Wb>#l?xtW;YR#GnTqcN)=S!p7~}oUYYE4{)UKw z$D5zdV;BF~FQK!ClC|oG$koJwO@7~chyxUtFwtQkqqKTGp z90G)MMKYSvc2VxCyP8^A^w*eQ#RlW)ZErU>Ky+Bb@bb*}m+?oB_7~mWni|8lrCzab z>l@kAEsQo^ZhhSH^72<3nlEwT(BM0)b?XQ;c6URQnKTe$I_y!XDiCZX-}I~<9v*J* z>#MGY$ta-X<&8(3f?gbQRSJuXFYgjoBno>RzIsiLI#`%4b6$5^8yReB`r^3UheJSC z>aaQW+oZ*!FRQ7lS^UXd2*hKo4wYOK%U)X*U(7C!o$TXQ^w zKt_&cIA)$wao=k_INY%eD7W2YsR+755fq)qR%G78&Qy((kiZs4PjjdiT69rHAiZ z$r8sl6C!BYmovFpTX-+Sj-5~{;`+D9AelcQ;f6Yg5?Z6kvVX0sfFPAan0IZf1NGX{ z9GrvVZaaq)AIayBZ^-k`)gF)_qrMM3c%X`ema}Gfa!1_(AC4Ww0euCR+Cu2Fk-Q6Q zsj|VB7nc{u%bdwQM3UZvBo`TuMw4CcP7S2oqvGa-vtvi}B5sO;juIs|)4qOuVHf0( z_=`MbaAA>cm!Xlcld-T^%1={1NEX}PVWzUVn?Sl~K9sdsjg8YuzYNN2t-Hw*4|(M# zzPdJ#U!vl{-kx{zK|=W*1x3b)wr=mnJz zbprtZZvHyeE9B=Bao*3H47xHmt8|BlFN4~M%|B0`$-)U{g?`L#$G?YMM2%$^#R|lzU0xKV5eDE=t zb*~MH#`1|+O7^ifzI!?6^@MF01nlbl@6twab90l5HO$#+Gm5!p8JuEH2uKwa6uejc zqyGW{D|;YkK-Ih*gxv${mkm6L%wI(%L32-f5QXb4DRQ%9mW5eU%z4FFwx+q6nAN~+ z!@?-uVM79mq^scfP0>+Pizv@bV+hHwNhV8~^fFq>dUSFKHaDEw@skaYt+_U_LdywX(y^fB76M3r?pC`cFeWqzMM;1=KIV9-K;+Mlm_(_(^SE)2_`lK2S=Sb zoII^Te#OPk$(0^FJUpQc;;u_GoB*l4)$<~+eSj=VHRRawr(z->CS!<0`*&~znu9Z6 zR_SR5HXs>%GEvn%1KREqHaPHTuEc)o*MhyC_+Pt-ajAucf*9KykVi=)Xe?-&{si6) zM$co*sk4AdlDGUc*OMg`K1KVxiE(mrR=xMWAIQ|qX;yAlOH-L}Pl}W~Yc+oDWhKp( zD=>^^0qpiaTM+=c%wD2s(L(n2TUl9I^}e`T*A|W!pXq$R2IeH1PHH;I0EUoUSmjeS z&h36&B|)mEmX<9+Dx5c0VGI+MyZ;f3T4ZsvGMnP|Eiv##`6Z3PBltfj$Xsqfx3fF) zsSI<#?|@hi?VkSr)A1w5E7a8bl`fM55z@%+p3LU(Nmf6>!NI}H?Mb3uYowG_N0S`j z9}7M`5@D7|Qk1|q7dL4fJ~%jldsPF>u|V(WUn^;BXykoZczfXZBn(x@PTQB`Nppzn zbq3+u+Zh%Q+?_!pXb!3^QC2|F-#l98U>H%YR=%vqK9dX7uouVPTC8tO)x{1xx#O_i z{!9 z`@PUT0-)#?E?^vN9SXmFjcCc%9>?e#8ONQ;8?CyChb4$#P}5%uq{AntH8e6}v2r{e zdpNnrv|mZVxVvKh^A$n3EcDQU%!UgBwR`h99;gFpMH(P@xuLr|L#fw7l>tSmghSI$`8uJU2uO7@U&%Z{nAasPxS&VxNb+)7lcAM6I zj*OJQXz4RmK~oq#z9M8bg6mrNcny^oM$z->wEDOlNvNTvMHNLODOPNwsk<^QABGGI zcSl?7fBw40zyQtAn6?Ba!tKW(^b-o?W*#bxgbm;^h%-MW-+E5xC2Tn+Wu6}&Z`LGo zZhHsxm5(#3wR|iF28W-RTUx%>Tu^7$sW_wzHYW;PZoyWnSdCT{diE|WKD$bU}e=rS0?O6a5U zF*YnSvCN7TBg57sJQSVkf0vD29VX@Mt&R8_yWHOuj9nCLsy&f_*+QVRRwIns9bM|n z48uCqzjOFTe?W5c`37slW1`L9IcgdMNDhwqrCH_h_(vXxL=jrTeUX}jOYBZBYY@kG zqGNbiS<#9W(|}yAFpQA<;1gxk*9904$tBW@SoiPuW*TT@pu_ttZBh(J?A^CQrro(GDrkY0))BhN^p|ZVJN2T^R}@AM$*#G%))-9* z1a3y^th*Sg@FWi{Nla5w2oio9e{ONt323LVU_&bAnMSo+V8KMTS z&a}UAL9CT=&1TnTKtaG{heoK=^3?-dJ)+2n#Kho7v?BxjUK7KOx&eP^)m#Y8`d&5C zHY)A3Yi;EQvNLu^=1ppcP9{~*FK-wMd|BFA7qaiNBufaCXT zM7t5Z+X3cXN>fg6_;<+_UBRu-!_CcAQu-U0+Vb_*K>e@!uC72uWb+y1I=NL4)g2EmEfBkL$iJbheU;SbY z<5j73q$B*pXjs`ogF zbL~xaOv~jLq^^qP$%BF$eo?efNw_%|F3_MF3qZ=sZsoZ%tA*^$i!jbwZ7j-^@&V-` ze-rCDY`de;iYJLH$)8l{${Z$hOg=vy4zo{FA^28e@_4hC|`L(a-)jU2gMqq5BgHMqm;PJEdRhdf8P@O zn>Luz_V%~zY#z9^UC{OQQ&kc$7U)`2D4ZpKq@2xgVL6+!Lijgt{9k^~|G)hI7xI65 zZ~pb3k%k7C90e}(c~an0;c@W2`Tqav_LM#w*ILur**P#U(Af!wqCa+JASJ-s8m4bK zSzGh=;KS3UX3Z}m@|xPj)FjO$ZFYWE;KF;G$B&J{TyBkRsHCcDitxW>jjJY+S6FC# zhYukt3f4F_SKND)(FAEygQ*B^$ZWz@JMZlg4I|=G$Zp8Uzqh)|+}xyuuSh8wKrc-s zXVk}fUMaxtLsk|p1mXG)KqUpqy$rWS)pWJa!O}>rRB!+6vO<#7+2-WrWUc(=54X*T zcTCGlOP-D8AIvOjBo?e<>YvOil$ zKXMCu|XSCEg`Ie)Fk-AZlMX#Nmo#(;9{K?TS>#St{VrnkGwfSyxwAB~jv}rtWpJ z`}QVSq{W=qRzOZ+VzM}~@Yu-c_i%0%^l>VV#@rN89*x^t*}C*MZ6~VmNSLId&+&JR zYj6y)G2((u$&axy32|xInEBD*<}5NgAU5lnRgRm)r+hbl@rSB{qT+K02RbopI*b*V zP>qdeR8hx2ibVgIUK{67nPAxczAf7thkW~)rZP?1;r@0U2gJR-4fy!zA6l{Ubaq| zzr4{!t!r@gWlHAZL*66`Zf0xDuc5_|bN%C9_O`bByNNbsPRl{<{f%U_lPZvI7g3p1 zul?~eA9Uf9V#Hs#><3(U@YK|_&QH*Mip|$hPgGQ_K>elr*#hen*&$ZYUUSDiDNlYh zCnb%$A7uvzw?x#*ck)3GFH;LlGwjTMS>>g#p9NgpC#@`f0n;`8RLJ9cxIZohQh>CUxRc$Z^#{R^#)j7` zfADY_*E$3~ih1h^MbU*PmX>jBH{Pb>lMa-Xlt_92Mb{jgkkEvdUwWBH$NMQYm5sR( zeg+0^va|b}hkyaf$mkpwFFbh6P9PWI*X2thQv3zat#{}nJ3C4)-Wg>U!mm+@iBF6l zNVs!f&??u<*}nV;n37q;*(!R#*=F21`*^MJ7k;vCqE%3gjk+ literal 0 HcmV?d00001 diff --git a/packages/dashboard/e2e/__screenshots__/fn-8602/tablet-after.png b/packages/dashboard/e2e/__screenshots__/fn-8602/tablet-after.png new file mode 100644 index 0000000000000000000000000000000000000000..fd486c858900bc4ee810d361118a2cabac118991 GIT binary patch literal 52549 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 literal 0 HcmV?d00001 diff --git a/packages/dashboard/e2e/__screenshots__/fn-8602/tablet-before.png b/packages/dashboard/e2e/__screenshots__/fn-8602/tablet-before.png new file mode 100644 index 0000000000000000000000000000000000000000..19768853688be3e2ebc5cc8b518ada04b7486c71 GIT binary patch literal 11500 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 MvgM`Hi>`nF52bxCWdHyG literal 0 HcmV?d00001 diff --git a/packages/dashboard/src/__tests__/task-modal-touch-resize-browser.test.ts b/packages/dashboard/src/__tests__/task-modal-touch-resize-browser.test.ts new file mode 100644 index 0000000000..ab6f4258e9 --- /dev/null +++ b/packages/dashboard/src/__tests__/task-modal-touch-resize-browser.test.ts @@ -0,0 +1,154 @@ +import { afterAll, beforeAll, describe, expect, it } from "vitest"; +import { createServer, type ViteDevServer } from "vite"; +import { createRequire } from "node:module"; +import { existsSync } from "node:fs"; +import { mkdir } from "node:fs/promises"; +import path from "node:path"; + +const requireFromEngine = createRequire(new URL("../../../engine/package.json", import.meta.url)); +const { chromium } = requireFromEngine("playwright-core") as { chromium: { launch(options: { executablePath: string; headless: boolean; args?: string[] }): Promise } }; +type Browser = { newPage(options: { viewport: { width: number; height: number } }): Promise; close(): Promise }; +type Page = { goto(url: string): Promise; evaluate(fn: (arg: Arg) => T, arg?: Arg): Promise; locator(selector: string): Locator; waitForTimeout(ms: number): Promise; screenshot(options: { path: string }): Promise; close(): Promise; context(): { newCDPSession(page: Page): Promise }; on(event: "console" | "pageerror", listener: (message: { text?(): string; message?: string }) => void): void }; +type Locator = { boundingBox(): Promise<{ x: number; y: number; width: number; height: number } | null> }; +type Cdp = { send(method: string, params: Record): Promise }; +type Point = { x: number; y: number }; +type Rect = { x: number; y: number; width: number; height: number }; + +const browserCandidates = process.platform === "darwin" + ? ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", "/Applications/Chromium.app/Contents/MacOS/Chromium"] + : ["/usr/bin/google-chrome", "/usr/bin/google-chrome-stable", "/usr/bin/chromium", "/usr/bin/chromium-browser"]; +const executablePath = [process.env.FUSION_BROWSER_SMOKE_BROWSER, process.env.CHROME_BIN, ...browserCandidates].find((candidate): candidate is string => Boolean(candidate) && existsSync(candidate)); +const screenshots = path.resolve(process.cwd(), "e2e/__screenshots__/fn-8602"); + +async function touchDrag(cdp: Cdp, point: Point, delta = { x: 48, y: 36 }) { + await cdp.send("Input.dispatchTouchEvent", { type: "touchStart", touchPoints: [{ x: point.x, y: point.y, id: 1 }] }); + for (const fraction of [0.25, 0.5, 0.75, 1]) { + await cdp.send("Input.dispatchTouchEvent", { type: "touchMove", touchPoints: [{ x: point.x + delta.x * fraction, y: point.y + delta.y * fraction, id: 1 }] }); + } + await cdp.send("Input.dispatchTouchEvent", { type: "touchEnd", touchPoints: [] }); +} + +async function setTabletMetrics(cdp: Cdp, width: number, height: number) { + await cdp.send("Emulation.setDeviceMetricsOverride", { + width, + height, + screenWidth: width, + screenHeight: height, + deviceScaleFactor: 1, + mobile: false, + }); + await cdp.send("Emulation.setTouchEmulationEnabled", { enabled: true, maxTouchPoints: 1 }); +} + +async function rect(page: Page, selector: string): Promise { + return page.evaluate((target) => { + const panel = document.querySelector(target); + if (!panel) throw new Error(`Missing ${target}`); + const { x, y, width, height } = panel.getBoundingClientRect(); + return { x, y, width, height }; + }, selector); +} + +async function targetCenter(page: Page, selector: string): Promise { + const box = await page.locator(selector).boundingBox(); + if (!box) throw new Error(`Missing resize target ${selector}`); + return { x: box.x + box.width / 2, y: box.y + box.height / 2 }; +} + +/* +FNXC:TaskModalResize 2026-08-12-15:12: +Browser CDP gestures are required because jsdom cannot resolve CSS hit targets. This fixture mounts +both production resize paths and sends CSS-pixel touch input through Chromium so elementFromPoint, +pointer capture, persistence, and header-drag isolation use the same browser input path. +*/ +describe.runIf(executablePath)("Task modal tablet touch resize browser regression", () => { + let server: ViteDevServer; let browser: Browser; let baseUrl = ""; + beforeAll(async () => { + server = await createServer({ root: process.cwd(), server: { host: "127.0.0.1", port: 0, watch: null }, logLevel: "error" }); + await server.listen(); baseUrl = server.resolvedUrls?.local[0] ?? ""; + browser = await chromium.launch({ executablePath, headless: true, ...(process.env.CI ? { args: ["--no-sandbox", "--disable-dev-shm-usage"] } : {}) }); + }, 30_000); + afterAll(async () => { + await browser?.close(); + await server?.watcher.close(); + server?.ws.close(); + server?.httpServer?.closeAllConnections?.(); + await new Promise((resolve) => server?.httpServer?.close(() => resolve())); + await server?.pluginContainer.close(); + }, 15_000); + + for (const [width, height] of [[768, 1024], [820, 1180]] as const) { + it(`hits and resizes Task Detail and New Task at the ${width}px tablet boundary with CDP touch`, async () => { + const page = await browser.newPage({ viewport: { width, height } }); + const cdp = await page.context().newCDPSession(page); + await setTabletMetrics(cdp, width, height); + page.on("console", (message) => console.log(`[task-modal-touch-resize] ${message.text?.() ?? ""}`)); + page.on("pageerror", (message) => console.error(`[task-modal-touch-resize] ${message.message ?? ""}`)); + await page.goto(`${baseUrl}app/task-modal-touch-resize-e2e-fixture.html?surface=task-detail&reset=1`); + await page.waitForTimeout(350); + expect(await page.evaluate(() => window.scrollX === 0 && window.scrollY === 0)).toBe(true); + expect(await page.evaluate(() => document.querySelectorAll("[data-resize-hit-target='true']").length)).toBe(1); + await mkdir(screenshots, { recursive: true }); + if (width === 820) await page.screenshot({ path: path.join(screenshots, "tablet-before.png") }); + + const detailSelector = "[data-testid='task-detail-modal'] .modal-resize-grip"; + const detailPoint = await targetCenter(page, detailSelector); + expect(await page.evaluate((point) => document.elementFromPoint(point.x, point.y)?.getAttribute("data-resize-hit-target"), detailPoint)).toBe("true"); + const detailBefore = await rect(page, "[data-testid='task-detail-modal']"); + await touchDrag(cdp, detailPoint); + await page.waitForTimeout(250); + const detailAfter = await rect(page, "[data-testid='task-detail-modal']"); + expect(detailAfter.width).toBeGreaterThan(detailBefore.width); + expect(detailAfter.height).toBeGreaterThan(detailBefore.height); + expect(detailAfter.width).toBeLessThanOrEqual(width); + expect(detailAfter.height).toBeLessThanOrEqual(height); + expect(await page.evaluate(() => localStorage.getItem("task-detail-modal-size"))).not.toBeNull(); + + await page.goto(`${baseUrl}app/task-modal-touch-resize-e2e-fixture.html?surface=new-task`); + await page.waitForTimeout(350); + expect(await page.evaluate(() => document.querySelectorAll("[data-resize-hit-target='true']").length)).toBe(8); + const newTaskPanel = ".new-task-modal"; + const headerPoint = await targetCenter(page, "[data-testid='new-task-drag-handle']"); + const newTaskBeforeHeaderDrag = await rect(page, newTaskPanel); + await touchDrag(cdp, headerPoint, { x: 32, y: 28 }); + await page.waitForTimeout(100); + const newTaskAfterHeaderDrag = await rect(page, newTaskPanel); + expect(newTaskAfterHeaderDrag.x).not.toBe(newTaskBeforeHeaderDrag.x); + expect(newTaskAfterHeaderDrag.y).not.toBe(newTaskBeforeHeaderDrag.y); + expect(newTaskAfterHeaderDrag.width).toBe(newTaskBeforeHeaderDrag.width); + expect(newTaskAfterHeaderDrag.height).toBe(newTaskBeforeHeaderDrag.height); + + const newTaskTarget = "[data-testid='new-task-resize-se']"; + const newTaskPoint = await targetCenter(page, newTaskTarget); + expect(await page.evaluate((point) => document.elementFromPoint(point.x, point.y)?.getAttribute("data-resize-hit-target"), newTaskPoint)).toBe("true"); + const newTaskBeforeResize = await rect(page, newTaskPanel); + await touchDrag(cdp, newTaskPoint); + await page.waitForTimeout(100); + const newTaskAfterResize = await rect(page, newTaskPanel); + expect(newTaskAfterResize.width).toBeGreaterThan(newTaskBeforeResize.width); + expect(newTaskAfterResize.height).toBeGreaterThan(newTaskBeforeResize.height); + expect(newTaskAfterResize.width).toBeLessThanOrEqual(width - 32); + expect(newTaskAfterResize.height).toBeLessThanOrEqual(height - 32); + expect(await page.evaluate(() => localStorage.getItem("fusion:new-task-modal-size"))).not.toBeNull(); + expect(await page.evaluate(() => localStorage.getItem("fusion:new-task-modal-position"))).not.toBeNull(); + if (width === 820) await page.screenshot({ path: path.join(screenshots, "tablet-after.png") }); + await page.close(); + }, 30_000); + } + + it("keeps the true-phone sheet free of active resize targets", async () => { + const page = await browser.newPage({ viewport: { width: 390, height: 844 } }); + const cdp = await page.context().newCDPSession(page); + await cdp.send("Emulation.setDeviceMetricsOverride", { width: 390, height: 844, screenWidth: 390, screenHeight: 844, deviceScaleFactor: 1, mobile: true }); + await cdp.send("Emulation.setTouchEmulationEnabled", { enabled: true, maxTouchPoints: 1 }); + await page.goto(`${baseUrl}app/task-modal-touch-resize-e2e-fixture.html?reset=1`); + await page.waitForTimeout(250); + expect(await page.evaluate(() => document.querySelector("[data-resize-hit-target]") === null)).toBe(true); + expect(await page.evaluate(() => { + const panel = document.querySelector(".new-task-modal"); + return panel ? panel.getBoundingClientRect().height >= window.innerHeight * 0.9 : false; + })).toBe(true); + await page.screenshot({ path: path.join(screenshots, "phone-fullscreen.png") }); + await page.close(); + }, 30_000); +});