exp(06): focused investigation — visual hierarchy without layout changes

Emphasise the active investigation card through stronger elevation,
clearer borders, and improved spacing. Quiet supporting panels by
reducing border opacity, softening heading weight, and lowering
text contrast — making them available without competing for attention.

Facilitator card receives a warm surface tint to read as a briefing
card rather than a generic panel.

Documentation: close experiment 05 with findings, add experiment 06
to the design evolution log, add Attention Hierarchy to UX guidelines,
defer dark mode to a future Investigation Mode experiment.

Presentation changes only — no reasoning, prompts, graph, API, or
backend modifications.
This commit is contained in:
2026-08-05 12:41:13 +01:00
parent f46c419168
commit 46f2d12726
6 changed files with 102 additions and 46 deletions
+25 -25
View File
@@ -99,8 +99,8 @@ function UnexpectedStateCard({ stateName, onRetry, onRestart }) {
function ContinueLaterBanner({ onRestart }) {
return (
<div className="rounded-lg border border-blue-200 bg-blue-50 px-5 py-4 text-center">
<p className="text-sm text-blue-800">
<div className="rounded-lg border border-blue-200/60 bg-blue-50/40 px-5 py-4 text-center">
<p className="text-sm text-blue-700/70">
Your previous investigation state is still saved. You can continue where you left off or start fresh.
</p>
{onRestart && (
@@ -248,13 +248,13 @@ function CurrentInvestigationCard({ selectedQuestion, graph }) {
}
return (
<div className="investigation-card rounded-lg border-2 border-green-300 bg-green-50 p-6">
<h2 className="mb-2 text-sm font-bold tracking-wide text-green-700">
<div className="investigation-card rounded-lg border-[2.5px] border-green-400 bg-gradient-to-b from-green-50 to-white p-8 shadow-sm">
<h2 className="mb-3 text-xs font-bold tracking-widest uppercase text-green-600/70">
Investigation
</h2>
<p className="text-xl font-semibold leading-snug text-gray-900">{q}</p>
<p className="text-2xl font-semibold leading-tight text-gray-900">{q}</p>
{whyMattersText && (
<p className="mt-4 text-sm leading-relaxed text-green-800">
<p className="mt-5 text-sm leading-relaxed text-green-800/80">
{whyMattersText}
</p>
)}
@@ -317,11 +317,11 @@ function CurrentUnderstandingCard({ currentSummary, plainLanguage }) {
if (!summary) return null;
return (
<div className="rounded-lg border border-gray-100 bg-white px-6 pt-5 pb-6">
<h2 className="mb-4 text-xl font-semibold tracking-tight text-gray-800">
<div className="rounded-lg border border-gray-200/60 bg-white/80 px-6 pt-5 pb-6">
<h2 className="mb-4 text-base font-semibold tracking-tight text-gray-400">
Understanding
</h2>
<p className="text-sm leading-relaxed text-gray-700">{summary}</p>
<p className="text-sm leading-relaxed text-gray-600">{summary}</p>
</div>
);
}
@@ -331,11 +331,11 @@ function PlainLanguageCard({ summary }) {
if (!summary) return null;
return (
<div className="rounded-lg border border-gray-100 bg-white px-6 pt-5 pb-6">
<h2 className="mb-4 text-xl font-semibold tracking-tight text-gray-800">
<div className="rounded-lg border border-gray-200/60 bg-white/80 px-6 pt-5 pb-6">
<h2 className="mb-4 text-base font-semibold tracking-tight text-gray-400">
Understanding
</h2>
<p className="text-sm leading-relaxed text-gray-700">{summary}</p>
<p className="text-sm leading-relaxed text-gray-600">{summary}</p>
</div>
);
}
@@ -352,7 +352,7 @@ function InvestigationHistoryCard({ turn }) {
return (
<details
className="rounded-lg border border-gray-100 bg-gray-50/60"
className="rounded-lg border border-gray-200/60 bg-gray-50/30"
key={turn.id}
open={!isCollapsed}
data-testid="investigation-turn"
@@ -383,7 +383,7 @@ function InvestigationHistory({ turns }) {
return (
<div className="space-y-3" data-testid="investigation-history">
<h2 className="text-xs font-semibold tracking-wider text-gray-400">
<h2 className="text-[11px] font-medium tracking-widest uppercase text-gray-300">
History
</h2>
<div className="space-y-2">
@@ -402,12 +402,12 @@ function OriginalSituation({ scenario, centralStatement }) {
if (!text) return null;
return (
<div className="rounded-lg border border-gray-100 bg-gray-50/70 px-5 py-4">
<h2 className="mb-2 text-xs font-semibold tracking-wider text-gray-400">
<div className="rounded-lg border border-gray-200/60 bg-gray-50/40 px-5 py-4">
<h2 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-300">
Situation
</h2>
<p className="whitespace-pre-wrap text-sm leading-relaxed text-gray-700">
<p className="whitespace-pre-wrap text-sm leading-relaxed text-gray-600">
{text}
</p>
</div>
@@ -440,7 +440,7 @@ function UpdateAcknowledgement({ updateResult }) {
className="transition-all duration-1500 ease-in"
style={{ opacity: visible ? 0.7 : 0, maxHeight: visible ? "4rem" : "0", marginBottom: visible ? "1rem" : "0" }}
>
<div className="rounded-lg border border-blue-200 bg-blue-50/60 px-4 py-2 text-xs text-blue-800">
<div className="rounded-md border border-blue-200/60 bg-blue-50/30 px-4 py-2 text-xs text-blue-700/60">
{summary}
</div>
</div>
@@ -450,11 +450,11 @@ function UpdateAcknowledgement({ updateResult }) {
// ── Developer details disclosure ──────────────────────────────
function DeveloperDetails({ graph, selectedQuestion, diagnostics, newlySurfacedNodeIds, updateResult }) {
return (
<details className="rounded-lg border border-gray-200 bg-gray-50">
<summary className="cursor-pointer px-5 py-3 text-sm font-medium text-gray-600 hover:text-gray-800">
<details className="rounded-lg border border-gray-200/60 bg-gray-50/30">
<summary className="cursor-pointer px-5 py-3 text-sm font-medium text-gray-400 hover:text-gray-600">
Developer details
</summary>
<div className="border-t border-gray-200 px-5 pb-4 pt-3 space-y-4">
<div className="border-t border-gray-200/60 px-5 pb-4 pt-3 space-y-4">
{graph && (
<SituationGraphView
situationGraph={graph}
@@ -482,13 +482,13 @@ function LoadingOverlay({ isLoading, elapsed, currentMessage, variant }) {
}
return (
<div className="rounded-lg border border-gray-200 bg-blue-50 px-5 py-6" role="status" aria-busy="true" data-testid="loading-overlay">
<div className="rounded-lg border border-blue-200/60 bg-blue-50/40 px-6 py-7" role="status" aria-busy="true" data-testid="loading-overlay">
<div className="flex items-center gap-3">
<ActivitySpinner />
<span className="text-base font-medium text-blue-900">Working through your situation</span>
<span className="text-base font-medium text-blue-800/70">Working through your situation</span>
</div>
<p className="mt-2 text-sm text-blue-700">{statusText}</p>
<p className="mt-1 text-xs text-blue-500" aria-live="polite">
<p className="mt-3 text-sm text-blue-600/60">{statusText}</p>
<p className="mt-2 text-xs text-blue-400/50" aria-live="polite">
This has been running for {elapsed}s.
{variant === "initial" && elapsed >= 45 && (
<span className="block mt-1">This can take around a minute with the current local model.</span>