Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
87 changes: 63 additions & 24 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -1082,13 +1082,18 @@ summary::-webkit-details-marker {
color: var(--clinical-accent);
}

/* The mode-action popover only renders ≥1024px (smaller viewports get the Sheet),
so this block holds no .mode-action-* overrides. */
/* Small-phone pin for the composer icon buttons: hold the 44px tap target and a
1.1rem glyph below 431px (the ≥640px block grows them to 48px/3rem). Single
source of truth — do not re-add a second max-width:430px block for these.
The mode-action popover only renders ≥1024px, so this holds no .mode-action-*
overrides. */
@media (max-width: 430px) {
.answer-footer-search-action,
.answer-footer-search-send {
height: 2.75rem;
width: 2.75rem;
height: 2.75rem !important;
width: 2.75rem !important;
min-height: 2.75rem;
min-width: 2.75rem;
}

.answer-footer-search-action svg,
Expand All @@ -1115,6 +1120,20 @@ summary::-webkit-details-marker {
background: transparent;
color: var(--text-muted);
box-shadow: none;
transition:
background-color 150ms ease,
color 150ms ease;
}

/* The unlayered `background: transparent` above beats the layered hover/open
utilities on the chatComposerIconButton trigger, so the "+" had NO tactile
feedback on hover and stayed flat even while its menu was open. Restore both
as unlayered rules so the primary compose action responds like every other
icon control. `[aria-expanded="true"]` is the trigger's open state. */
.answer-footer-search-action:hover,
.answer-footer-search-action[aria-expanded="true"] {
background: var(--surface-subtle);
color: var(--text);
}

.answer-footer-search-input {
Expand Down Expand Up @@ -1144,7 +1163,15 @@ summary::-webkit-details-marker {
height: 2rem;
width: 1px;
flex: 0 0 auto;
background: color-mix(in srgb, var(--border-strong) 58%, transparent);
/* Hairline that fades at both ends rather than a hard bar — reads as a
premium separator between the field and the send action. */
background: linear-gradient(
to bottom,
transparent,
color-mix(in srgb, var(--border-strong) 58%, transparent) 22%,
color-mix(in srgb, var(--border-strong) 58%, transparent) 78%,
transparent
);
}

.answer-footer-search-send {
Expand All @@ -1164,20 +1191,16 @@ summary::-webkit-details-marker {
box-shadow: 0 5px 14px color-mix(in srgb, var(--clinical-accent) 38%, transparent);
}

@media (max-width: 430px) {
.answer-footer-search-action,
.answer-footer-search-send {
height: 2.75rem !important;
width: 2.75rem !important;
min-height: 2.75rem;
min-width: 2.75rem;
}

.answer-footer-search-action svg,
.answer-footer-search-send svg {
height: 1.1rem;
width: 1.1rem;
}
/* Idle/inactive send: a calm neutral chip, not a faded-teal button. The
chatComposerIconButton `disabled:opacity-50` utility over the accent fill +
colour glow read as muddy/half-broken on the empty hero. Unlayered so it
beats that layered utility; the button turns accent the moment a query makes
it actionable. */
.answer-footer-search-send:disabled {
opacity: 1;
background: var(--surface-subtle);
color: var(--text-soft);
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--border-strong) 42%, transparent);
}

.answer-footer-search-send:active {
Expand Down Expand Up @@ -1558,11 +1581,6 @@ summary::-webkit-details-marker {
}
}

.dark .answer-footer-search-action,
.dark .answer-footer-search-chip {
color: var(--text-muted);
}

.dashboard-composer-edge {
left: max(0.75rem, var(--safe-area-left));
right: max(0.75rem, var(--safe-area-right));
Expand Down Expand Up @@ -1756,6 +1774,10 @@ summary::-webkit-details-marker {
.answer-footer-search-dock .answer-footer-search-pill {
border-color: var(--border-strong);
background: var(--surface);
/* The dock repaints the pill opaque, so the inherited blur has nothing
translucent to sample — drop it to save a compositing layer per scroll
frame (matches the chip override just below). */
backdrop-filter: none;
box-shadow:
0 -1px 0 color-mix(in srgb, var(--border) 60%, transparent),
0 1px 3px rgb(16 24 40 / 5%);
Expand Down Expand Up @@ -2325,6 +2347,23 @@ html[data-motion="reduced"] .source-capsule-hit[aria-expanded="true"]:hover .sou
mask-image: none;
-webkit-mask-image: none;
}

/* Composer pill/divider/chip use color-mix(...transparent) for their border,
fill, and separator, which thins system-color contrast exactly like the
glass header — force them opaque too (unlayered, matching the header
treatment above) so the composer boundary reads at full strength and its
divider stays visible next to the header chrome right above it. */
.answer-footer-search-pill,
.answer-footer-search-chip {
border: 1px solid ButtonBorder;
background: Canvas;
backdrop-filter: none;
box-shadow: none;
}

.answer-footer-search-divider {
background: ButtonBorder;
}
}

@media print {
Expand Down
17 changes: 12 additions & 5 deletions src/components/clinical-dashboard/master-search-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1364,7 +1364,7 @@ export function MasterSearchHeader({
<button
type="button"
onClick={onClearQuery}
className="grid h-11 w-11 shrink-0 place-items-center rounded-full text-[color:var(--text-muted)] transition hover:bg-[color:var(--surface-subtle)] hover:text-[color:var(--text)]"
className="grid h-11 w-11 shrink-0 place-items-center rounded-full text-[color:var(--text-muted)] transition hover:bg-[color:var(--surface-subtle)] hover:text-[color:var(--text)] sm:h-12 sm:w-12"
aria-label="Clear search question"
>
<X aria-hidden="true" className="h-4 w-4" />
Expand All @@ -1386,9 +1386,9 @@ export function MasterSearchHeader({
aria-label={selectedSearch.submitAriaLabel}
>
{loading ? (
<Loader2 aria-hidden="true" className="h-4 w-4 animate-spin" />
<Loader2 aria-hidden="true" className="size-icon-lg animate-spin" />
) : usesSendAffordance ? (
<Send aria-hidden="true" className="h-4 w-4" />
<Send aria-hidden="true" className="size-icon-lg" />
) : usesModeIdentityAffordance ? (
<ModeIdentityIcon className="size-icon-lg" />
) : (
Expand Down Expand Up @@ -1604,8 +1604,15 @@ export function MasterSearchHeader({
}}
onKeyDown={handleModeTriggerKeyDown}
className={cn(
"universal-header-mode-button inline-grid h-12 w-[min(13rem,calc(100vw-11.5rem))] min-w-0 grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-2 rounded-full border border-[color:var(--border)] bg-[color:var(--surface)] px-2.5 text-left transition hover:border-[color:var(--border-strong)] hover:bg-[color:var(--surface-subtle)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)] sm:w-auto sm:min-w-[13rem] sm:pr-3",
isWorkflowHeader && "h-11 w-[min(11rem,calc(100vw-11rem))] sm:w-[12rem] sm:min-w-0 lg:w-[12.5rem]",
// Size utilities live in the per-variant branch, never the shared
// base: cn() is plain concat (no tailwind-merge), so keeping the
// default h-/w-/min-w- here too made the workflow overrides dead —
// Tailwind v4 emits same-property utilities in canonical order and
// the base won at every breakpoint but lg:.
"universal-header-mode-button inline-grid min-w-0 grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-2 rounded-full border border-[color:var(--border)] bg-[color:var(--surface)] px-2.5 text-left transition hover:border-[color:var(--border-strong)] hover:bg-[color:var(--surface-subtle)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]",
isWorkflowHeader
? "h-11 w-[min(11rem,calc(100vw-11rem))] sm:w-[12rem] sm:min-w-0 lg:w-[12.5rem]"
: "h-12 w-[min(13rem,calc(100vw-11.5rem))] sm:w-auto sm:min-w-[13rem] sm:pr-3",
)}
aria-haspopup="menu"
aria-expanded={modeMenuOpen}
Expand Down
6 changes: 5 additions & 1 deletion src/components/clinical-dashboard/mode-action-popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -922,7 +922,11 @@ export function ModeActionPopup({
className={cn(
chatComposerIconButton,
triggerClassName,
open && "bg-[color:var(--surface-subtle)] text-[color:var(--text)] motion-safe:rotate-45",
// `rotate-45` (not `motion-safe:rotate-45`): the open "+"→"×" state is
// information, not decoration. The global reduced-motion rule makes the
// transform instant, so gating it on motion-safe wrongly dropped the
// affordance entirely for those users.
open && "bg-[color:var(--surface-subtle)] text-[color:var(--text)] rotate-45",
)}
aria-label={buttonLabel}
aria-controls={open ? "daily-actions-sheet" : undefined}
Expand Down
Loading