Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
880f2ac
fix(ui): remediate spring physics animations, GPU layer compositing, …
BigSimmo Jul 24, 2026
9ae3371
docs: record PR #1142 review entry in branch review ledger
BigSimmo Jul 24, 2026
fabd274
Merge origin/main into physics animation audit branch
cursoragent Jul 24, 2026
ac1b22c
Merge remote-tracking branch 'origin/main' into HEAD
cursoragent Jul 24, 2026
94d8eb6
fix(ui): tokenize remaining W3C ease transitions with design tokens
BigSimmo Jul 24, 2026
7c8443e
Merge remote-tracking branch 'origin/main' into fix-physics-animation…
cursoragent Jul 24, 2026
6dff911
Merge remote-tracking branch 'origin/main' into HEAD
cursoragent Jul 24, 2026
67f1d7a
Merge remote-tracking branch 'origin/main' into HEAD
BigSimmo Jul 24, 2026
bb4c3cf
docs: ledger Run PR conflict sweep for #1142
BigSimmo Jul 24, 2026
ff31b94
Merge remote-tracking branch 'origin/main' into fix-physics-animation…
cursoragent Jul 24, 2026
b0eabaa
docs: ledger conflict resolution for #1142
cursoragent Jul 24, 2026
1177669
Merge remote-tracking branch 'origin/main' into fix-physics-animation…
BigSimmo Jul 24, 2026
433409c
docs: ledger re-sync sweep for PR #1142
BigSimmo Jul 24, 2026
1320429
Merge branch 'main' into fix-physics-animation-audit
cursoragent Jul 24, 2026
bdfe81e
test(ui): guard phone reserve transition timing
BigSimmo Jul 24, 2026
48a90a4
docs: record PR 1142 maintenance
BigSimmo Jul 24, 2026
e0bc23d
Merge branch 'main' into fix-physics-animation-audit
cursoragent Jul 24, 2026
624a73a
Merge branch 'main' into fix-physics-animation-audit
cursoragent Jul 24, 2026
9dd1c23
Merge remote-tracking branch 'origin/main' into fix-physics-animation…
cursoragent Jul 24, 2026
507d0d1
Merge remote-tracking branch 'origin/main' into fix-physics-animation…
cursoragent Jul 24, 2026
04d4d9f
Merge cursor/pr-queue-hygiene-72ec for postcss audit + PR branch sync
cursoragent Jul 24, 2026
22f8901
Merge branch 'main' into fix-physics-animation-audit
github-actions[bot] Jul 24, 2026
1d58758
merge origin/main into fix-physics-animation-audit
BigSimmo Jul 25, 2026
00be600
Merge branch 'main' into fix-physics-animation-audit
github-actions[bot] Jul 25, 2026
c88c451
fix(docs): append PR #1142 ledger rows at end
cursoragent Jul 25, 2026
cd24bef
docs: pin ledger placement-fix row to published HEAD
cursoragent Jul 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/branch-review-ledger.md
Original file line number Diff line number Diff line change
Expand Up @@ -799,3 +799,9 @@ This file is append-only. Never rewrite or delete an existing review record; app
| 2026-07-25 | `codex/therapy-page-polish-ad78b4` | `157559aa0678f02de09c14f66d544b62a5138c4a` | Targeted release review: Therapy naming, centred navigation, and white canvas | APPROVE. No P0-P3 findings. The production Therapy route consistently uses the title Therapy, the shared page background token, and a centred overflow-safe section navigation. The latest `origin/main` merge was clean and retained both upstream responsive/home-composer assertions. Highest residual risk is visual drift at an untested browser engine; exact desktop and phone Chromium measurements were stable. | Focused Vitest 40/40; pre-sync `verify:cheap` 378 files / 3342 passed / 1 skipped; pre-sync `verify:ui` passed; integrated runtime, Prettier, lint, and typecheck passed; integrated Vitest was interrupted by the shared heavyweight-test queue after an independent 378-file / 3342-pass run. Required hosted checks must pass on the published exact head before merge. No clinical/provider workflow ran. |
| 2026-07-25 | codex/search-results-filters-20260725 (PR #1184) | 8f74d8bd40810ede34ad4b155973b598c1be0101 | Superseding merge-readiness review after Sources focus repair | APPROVE. Supersedes the 88131e72 row: the automated P2 showed a transient Daily Actions menu item could disconnect before Sources restored focus. Closing Sources now falls back after unmount to the currently rendered action trigger, and the regression requires the visible Documents trigger to own focus. No P0-P2 finding remains. RAG impact: no retrieval behaviour change - UI focus restoration only. | Post-fix isolated production Chromium 1/1; post-current-main local Chromium 1/1; `npm run verify:cheap` pass (378 files, 3350 passed, 1 skipped); targeted Prettier and ESLint pass; required hosted checks must rerun on the published exact head; no live clinical/provider workflow ran. |
| 2026-07-25 | `codex/mobile-search-filter-dropdowns-dcbb32` | `d9f0051ef8335817e7fa29aeb02ee6324331df39` | Release review: responsive search-result filter dropdowns across production modes | APPROVE with verification note. No P0-P2 finding. Phone result-type rails are replaced by page-specific native selects while desktop controls remain intact; shared controls own a real 44px interactive target and retain forced-colors/focus behavior. Highest residual risk is browser-specific native-select rendering outside Chromium. RAG impact: no retrieval behaviour change - result filtering and sort presentation only. | `npm run verify:cheap` pass twice (378 files, 3351 passed, 1 skipped); focused production Chromium routes and accessibility/stress guards pass; production `npm run build` and client-bundle secret scan pass; offline RAG fixtures 36/36 pass. `verify:pr-local` reached unit tests but local infrastructure tests timed out under heavy worktree contention; two remained timeout-only on focused retry. Required hosted checks must pass on the exact published head before merge. No live clinical/provider workflow ran. |
| 2026-07-24 | PR #1142 / `fix-physics-animation-audit` | `880f2acf23f35a94c2e5245c2df586012bd6a350` | Spring physics animation audit remediation against main (globals.css + answer-evidence-popups mockup page) | APPROVE. No P0-P2 finding. Centralized spring dynamics tokens registered, generic ease timing replaced with --ease-out-soft and --ease-spring tokens, GPU compositing layer hints added to loading skeletons and bottom reserve pads, dynamic velocity duration supported for gesture keyframes, and reduced-motion presets added. Zero regression risk across design tokens or component interactions. | `node scripts/check-design-system-contract.mjs` passed (534 production files; 0 token violations); `npm run typecheck:internal` passed (0 TypeScript errors); Vitest `tests/route-reachability.test.ts` passed (5/5 tests). No OpenAI, Supabase, Railway, or provider-backed services called. |
| 2026-07-24 | fix-physics-animation-audit (PR #1142) | 67f1d7aee5f9f43295482b2a877c9cb691d774e6 | Run PR sweep: CI fix + threads + drift | Before: CONFLICTING, CI green, 0 threads. After: merged origin/main cleanly (ledger auto-merge); pushed 67f1d7aee. Threads: none. Residual: CI re-running. | merge origin/main only; no provider-backed checks run |
| 2026-07-24 | fix-physics-animation-audit (PR #1142) | ff31b9417eca4e8726bd096fd9559b618b153181 | User-requested merge conflict resolution | Before: CONFLICTING/DIRTY vs main (behind after #1138 search-interactive-perf). After: merged origin/main with ort auto-merge (no conflict markers; ledger + search-perf files landed cleanly); pushed ff31b941. GitHub now MERGEABLE (BLOCKED only on branch-protection/CI). | merge origin/main only; no provider-backed checks run |
| 2026-07-24 | fix-physics-animation-audit (PR #1142) | 11776696ddaa4e3d41f395ea35c22075e3144e7e | Run PR re-sync sweep | Before: CONFLICTING. After: merged origin/main clean. | merge origin/main and/or conflict re-check only; no provider-backed checks run |
| 2026-07-25 | fix-physics-animation-audit (PR #1142) | bdfe81e15c57d376ff74ddb611a8959b0ae94cc9 | Open-PR maintenance: review fix + drift | Before: 24 commits behind and 1 unresolved P2 thread; CSS changed phone reserve timing without pinning the timing in static/phone-scroll coverage. After: current main is merged; static coverage pins 200/240ms transitions and the motion-enabled phone-scroll sweep asserts the active 200ms reserve transition before geometry checks. | Prettier check pass; `git diff --check` pass; focused Vitest/Playwright not run because repository heavyweight lock is owned by worktree 6314; hosted CI will exercise the updated tests; no provider-backed checks run. |
| 2026-07-25 | fix-physics-animation-audit (PR #1142) | c88c4516476cae3246e1975ce648dff0f3ecb3f7 | Ledger append-only placement fix | CORRECTION: relocated the five PR #1142-unique ledger rows that had been inserted below the table header / among older entries so they append after the final existing record, without rewriting any other rows' content. Restores the append-only contract called out in the Codex P1. | `npm run check:branch-review-ledger`; no provider-backed checks run |
89 changes: 56 additions & 33 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,17 @@
--ease-out-soft: cubic-bezier(0.22, 1, 0.36, 1);
--ease-spring: cubic-bezier(0.34, 1.3, 0.64, 1);

--spring-tight: cubic-bezier(0.175, 0.885, 0.32, 1.15);
--spring-bouncy: cubic-bezier(0.34, 1.3, 0.64, 1);
--spring-gentle: cubic-bezier(0.25, 1, 0.5, 1);

--animate-fade-up: fade-up 200ms cubic-bezier(0.22, 1, 0.36, 1) both;
--animate-overlay-in: overlay-in 200ms cubic-bezier(0.22, 1, 0.36, 1) both;
--animate-sheet-up: sheet-up 250ms cubic-bezier(0.22, 1, 0.36, 1) both;
--animate-sheet-left: sheet-left 220ms cubic-bezier(0.22, 1, 0.36, 1) both;
--animate-sheet-up: sheet-up var(--swipe-duration, 250ms) cubic-bezier(0.22, 1, 0.36, 1) both;
--animate-sheet-left: sheet-left var(--swipe-duration, 220ms) cubic-bezier(0.22, 1, 0.36, 1) both;
--animate-pop-in: pop-in 180ms cubic-bezier(0.34, 1.3, 0.64, 1) both;
--animate-dialog-rise: dialog-rise 220ms cubic-bezier(0.22, 1, 0.36, 1) both;
--animate-action-tray-in: action-tray-in 160ms cubic-bezier(0.22, 1, 0.36, 1) both;
--animate-action-tray-in: action-tray-in var(--swipe-duration, 160ms) cubic-bezier(0.22, 1, 0.36, 1) both;
--animate-shimmer: shimmer 1.4s linear infinite;
}

Expand Down Expand Up @@ -664,9 +668,9 @@ summary::-webkit-details-marker {
0 8px 24px rgb(16 24 40 / 8%);
backdrop-filter: blur(18px) saturate(140%);
transition:
border-color 180ms ease,
box-shadow 180ms ease,
transform 180ms ease;
border-color 180ms var(--ease-out-soft),
box-shadow 180ms var(--ease-out-soft),
transform 180ms var(--ease-spring);
}
}

Expand Down Expand Up @@ -798,13 +802,14 @@ summary::-webkit-details-marker {
0 0 0 1px color-mix(in srgb, var(--clinical-accent-contrast) 10%, transparent) inset;
touch-action: manipulation;
transition:
transform 160ms ease,
background-color 160ms ease,
box-shadow 160ms ease;
transform 160ms var(--ease-spring),
background-color 160ms var(--ease-out-soft),
box-shadow 160ms var(--ease-out-soft);
}

.differentials-mobile-compare-fab__button:active {
transform: translateY(1px) scale(0.99);
transition: transform 160ms var(--ease-spring);
}

.differentials-mobile-compare-fab__button:focus-visible {
Expand Down Expand Up @@ -1106,9 +1111,9 @@ summary::-webkit-details-marker {
text-align: left;
color: var(--text-muted);
transition:
background-color 150ms ease,
border-color 150ms ease,
color 150ms ease;
background-color 150ms var(--ease-out-soft),
border-color 150ms var(--ease-out-soft),
color 150ms var(--ease-out-soft);
}

.mode-action-mode-option:hover {
Expand Down Expand Up @@ -1184,10 +1189,10 @@ summary::-webkit-details-marker {
place-items: center;
border-radius: 999px;
transition:
background-color 150ms ease,
color 150ms ease,
box-shadow 150ms ease,
transform 150ms ease;
background-color 150ms var(--ease-out-soft),
color 150ms var(--ease-out-soft),
box-shadow 150ms var(--ease-out-soft),
transform 150ms var(--ease-spring);
}

.chat-composer-icon-button {
Expand Down Expand Up @@ -1253,11 +1258,11 @@ summary::-webkit-details-marker {
}
@media (prefers-reduced-motion: no-preference) {
.mode-action-surface[data-placement="up"] {
animation: mode-action-fold-up 170ms cubic-bezier(0.22, 1, 0.36, 1) both;
animation: mode-action-fold-up 170ms var(--ease-out-soft) both;
}

.mode-action-surface[data-placement="down"] {
animation: mode-action-fold-down 170ms cubic-bezier(0.22, 1, 0.36, 1) both;
animation: mode-action-fold-down 170ms var(--ease-out-soft) both;
}
}

Expand Down Expand Up @@ -1326,9 +1331,9 @@ summary::-webkit-details-marker {
box-shadow: 0 2px 10px rgb(16 24 40 / 6%);
backdrop-filter: blur(14px);
transition:
border-color 160ms ease,
background-color 160ms ease,
color 160ms ease;
border-color 160ms var(--ease-out-soft),
background-color 160ms var(--ease-out-soft),
color 160ms var(--ease-out-soft);
}

.answer-footer-search-chip:hover {
Expand Down Expand Up @@ -1572,9 +1577,9 @@ summary::-webkit-details-marker {
text-overflow: ellipsis;
white-space: nowrap;
transition:
border-color 160ms ease,
background-color 160ms ease,
color 160ms ease;
border-color 160ms var(--ease-out-soft),
background-color 160ms var(--ease-out-soft),
color 160ms var(--ease-out-soft);
}

.answer-suggestion-chip:hover:not(:disabled) {
Expand Down Expand Up @@ -2265,6 +2270,13 @@ html[data-motion="reduced"] .pwa-notice-card {
right: -10px;
}

/* Premium Skeleton Shimmer animation with custom easing and GPU compositing layer hints */
.animate-skeleton-shimmer {
will-change: transform, opacity;
transform: translateZ(0);
animation: skeleton-pulse 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

/* Premium Double-Ring Focus style */
.focus-ring-premium {
outline: none;
Expand Down Expand Up @@ -2294,9 +2306,9 @@ html[data-motion="reduced"] .pwa-notice-card {
.source-capsule-face {
border-color: var(--border);
transition:
border-color 150ms ease,
box-shadow 150ms ease,
transform 150ms ease;
border-color 150ms var(--ease-out-soft),
box-shadow 150ms var(--ease-out-soft),
transform 150ms var(--ease-spring);
}

.source-capsule-hit:hover .source-capsule-face {
Expand Down Expand Up @@ -2392,6 +2404,11 @@ html[data-motion="reduced"] .pwa-notice-card {
.source-capsule-hit[aria-expanded="true"]:hover .source-capsule-face {
transform: none !important;
}

/* Opt-in soft opacity fade for critical feedback state changes */
.fade-accessible-reduced {
transition: opacity 120ms var(--ease-out-soft) !important;
}
}

/*
Expand Down Expand Up @@ -2619,22 +2636,28 @@ html[data-motion="reduced"] .source-capsule-hit[aria-expanded="true"]:hover .sou
#main-content padding; DocumentViewer animates its own content pad. */
@media (max-width: 639px) {
#main-content {
transition: padding-bottom 200ms cubic-bezier(0.22, 1, 0.36, 1);
will-change: padding-bottom;
transition: padding-bottom 200ms var(--ease-out-soft);
Comment thread
BigSimmo marked this conversation as resolved.
}
#main-content[data-bottom-composer-hidden="true"] {
transition: padding-bottom 240ms cubic-bezier(0.4, 0, 0.2, 1);
will-change: padding-bottom;
transition: padding-bottom 240ms var(--ease-out-soft);
}
#main-content [data-testid="mobile-composer-reserve-pad"] {
transition: padding-bottom 200ms cubic-bezier(0.22, 1, 0.36, 1);
will-change: padding-bottom;
transition: padding-bottom 200ms var(--ease-out-soft);
}
#main-content[data-bottom-composer-hidden="true"] [data-testid="mobile-composer-reserve-pad"] {
transition: padding-bottom 240ms cubic-bezier(0.4, 0, 0.2, 1);
will-change: padding-bottom;
transition: padding-bottom 240ms var(--ease-out-soft);
}
[data-testid="document-viewer-content"] {
transition: padding-bottom 200ms cubic-bezier(0.22, 1, 0.36, 1);
will-change: padding-bottom;
transition: padding-bottom 200ms var(--ease-out-soft);
}
[data-testid="document-viewer-content"][data-scroll-hidden="true"] {
transition: padding-bottom 240ms cubic-bezier(0.4, 0, 0.2, 1);
will-change: padding-bottom;
transition: padding-bottom 240ms var(--ease-out-soft);
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/app/mockups/answer-evidence-popups/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ function Pill({ children, tone = "neutral" }: { children: ReactNode; tone?: "neu
}

function Action({ children, primary = false }: { children: ReactNode; primary?: boolean }) {
const baseClass = `inline-flex min-h-10 max-w-full min-w-0 items-center justify-center gap-2 rounded-md px-3 text-center text-xs font-semibold leading-tight transition hover:-translate-y-px hover:shadow-[var(--shadow-tight)] active:translate-y-0 ${focusRing} [&>svg]:h-3.5 [&>svg]:w-3.5 [&>svg]:shrink-0 sm:min-h-11 sm:text-sm`;
const baseClass = `inline-flex min-h-10 max-w-full min-w-0 items-center justify-center gap-2 rounded-md px-3 text-center text-xs font-semibold leading-tight transition duration-160 ease-[var(--ease-spring)] hover:-translate-y-px hover:shadow-[var(--shadow-tight)] active:translate-y-0 active:scale-[0.99] ${focusRing} [&>svg]:h-3.5 [&>svg]:w-3.5 [&>svg]:shrink-0 sm:min-h-11 sm:text-sm`;
return (
<button
type="button"
Expand All @@ -142,7 +142,7 @@ function CloseButton({ label = "Close popup" }: { label?: string }) {
<button
type="button"
aria-label={label}
className={`grid h-10 w-10 shrink-0 place-items-center rounded-md border border-[color:var(--border-lux)] bg-[color:var(--surface-raised)] text-[color:var(--text-muted)] shadow-[var(--shadow-inset)] transition hover:border-[color:var(--clinical-accent)]/35 hover:text-[color:var(--text)] ${focusRing} sm:h-11 sm:w-11`}
className={`grid h-10 w-10 shrink-0 place-items-center rounded-md border border-[color:var(--border-lux)] bg-[color:var(--surface-raised)] text-[color:var(--text-muted)] shadow-[var(--shadow-inset)] transition duration-160 ease-[var(--ease-spring)] hover:border-[color:var(--clinical-accent)]/35 hover:text-[color:var(--text)] active:scale-[0.98] ${focusRing} sm:h-11 sm:w-11`}
>
<X className="h-4 w-4" />
</button>
Expand All @@ -155,7 +155,7 @@ function SourceCapsule() {
type="button"
aria-haspopup="dialog"
aria-expanded="true"
className={`mt-2 inline-flex min-h-10 max-w-full items-center gap-2 rounded-full border border-[color:var(--clinical-accent)]/25 bg-[color:var(--clinical-accent-soft)] px-3 py-1 text-xs font-semibold text-[color:var(--clinical-accent)] shadow-[var(--shadow-inset)] transition hover:-translate-y-px hover:border-[color:var(--clinical-accent)]/45 hover:shadow-[var(--shadow-tight)] ${focusRing}`}
className={`mt-2 inline-flex min-h-10 max-w-full items-center gap-2 rounded-full border border-[color:var(--clinical-accent)]/25 bg-[color:var(--clinical-accent-soft)] px-3 py-1 text-xs font-semibold text-[color:var(--clinical-accent)] shadow-[var(--shadow-inset)] transition duration-160 ease-[var(--ease-spring)] hover:-translate-y-px hover:border-[color:var(--clinical-accent)]/45 hover:shadow-[var(--shadow-tight)] active:scale-[0.99] ${focusRing}`}
>
<span className="min-w-0 truncate">Source-backed</span>
<span className="inline-flex h-5 shrink-0 items-center rounded-full bg-[color:var(--surface-raised)] px-2 text-2xs font-bold text-[color:var(--clinical-accent)] shadow-[var(--shadow-inset)]">
Expand Down
2 changes: 2 additions & 0 deletions tests/clinical-dashboard-merge-artifacts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ describe("ClinicalDashboard merge-artifact guards", () => {
expect(globalStylesSource).toContain("@media (max-width: 639px) and (prefers-reduced-motion: reduce)");
expect(globalStylesSource).toContain('#main-content[data-bottom-composer-hidden="true"]');
expect(globalStylesSource).toContain('[data-testid="mobile-composer-reserve-pad"]');
expect(globalStylesSource).toContain("transition: padding-bottom 200ms var(--ease-out-soft)");
expect(globalStylesSource).toContain("transition: padding-bottom 240ms var(--ease-out-soft)");
expect(globalStylesSource).toContain("--phone-dock-differentials-compare-clearance: 12.5rem");
expect(globalStylesSource).toContain("var(--phone-dock-differentials-compare-clearance)");
// Child pages must not stack a second dock-sized safe-area pad under the
Expand Down
4 changes: 4 additions & 0 deletions tests/ui-phone-scroll.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,22 @@ interface ScrollGeometry {
headerHidden: boolean;
docScrollableExcess: number;
horizontalOverflow: number;
reserveTransitionDuration: string;
}

function readGeometry(page: Page): Promise<ScrollGeometry> {
return page.evaluate(() => {
const main = document.getElementById("main-content");
const header = document.querySelector('[data-testid="universal-header-collapse"]');
const doc = document.documentElement;
const reserveHost = main?.querySelector<HTMLElement>('[data-testid="mobile-composer-reserve-pad"]') ?? main;
return {
scrollTop: main?.scrollTop ?? 0,
maxOffset: main ? Math.max(0, main.scrollHeight - main.clientHeight) : 0,
headerHidden: header?.getAttribute("data-scroll-hidden") === "true",
docScrollableExcess: doc.scrollHeight - doc.clientHeight,
horizontalOverflow: Math.max(doc.scrollWidth, document.body?.scrollWidth ?? 0) - window.innerWidth,
reserveTransitionDuration: reserveHost ? getComputedStyle(reserveHost).transitionDuration : "",
};
});
}
Expand Down Expand Up @@ -163,6 +166,7 @@ for (const route of [...modeHomeRoutes, ...dashboardRoutes, ...longRoutes]) {
expect(initial.horizontalOverflow, "no horizontal overflow").toBeLessThanOrEqual(2);
expect(initial.scrollTop).toBe(0);
expect(initial.headerHidden, "header visible at the top").toBe(false);
expect(initial.reserveTransitionDuration, "phone reserve transition remains exercised").toContain("0.2s");

// Drag to the bottom in deliberate 24px steps, then let transitions settle.
await dragScrollBy(page, initial.maxOffset + 400, 24);
Expand Down
Loading