web: wrap analysis-card context notes on mobile; fix NaN critical path

The confidence bar and the two fleet-context notes on an analysis finding
shared a non-wrapping flex row, so on phones they squeezed into
word-per-line columns — the row now wraps, each note taking its own line.

Also visible in the same screenshot: "critical path NaNh NaNm" in the
ESP-blocking apps block. The backend omits null fields (WhenWritingNull),
so espAppsOccupancySeconds arrives as undefined and the strict !== null
guard let it through to formatDuration. Loose != null check now hides the
label when the value is absent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Oliver Kieselbach
2026-08-13 14:33:35 +02:00
parent 321ae63c63
commit e1b3ec25fd
2 changed files with 6 additions and 3 deletions
@@ -244,8 +244,10 @@ function AnalysisResultCard({
<span className="text-xs px-2 py-0.5 rounded-full bg-gray-200 text-gray-600">{result.category}</span>
</div>
<h3 className="font-medium text-gray-900">{result.ruleTitle}</h3>
<div className="flex items-center mt-1 space-x-3">
<div className="flex items-center space-x-1">
{/* flex-wrap: on narrow screens the fleet-context notes drop to their own
full-width lines instead of squeezing into word-per-line columns. */}
<div className="flex flex-wrap items-center mt-1 gap-x-3 gap-y-1">
<div className="flex items-center space-x-1 shrink-0">
<span className="text-xs text-gray-500">Confidence:</span>
<div className="w-24 h-2 bg-gray-200 rounded-full overflow-hidden">
<div
@@ -144,7 +144,8 @@ export default function TimeAttributionLane({ breakdown }: { breakdown: SessionT
<div className="mt-4">
<div className="text-xs font-semibold text-gray-600 mb-1.5">
ESP-blocking apps
{breakdown.espAppsOccupancySeconds !== null && (
{/* Loose check: the backend omits null fields (WhenWritingNull), so the client sees undefined. */}
{breakdown.espAppsOccupancySeconds != null && (
<span className="ml-2 font-normal text-gray-400" title="Overlap-merged install time of ESP-blocking apps within the apps phase.">
critical path {formatDuration(breakdown.espAppsOccupancySeconds)}
</span>