From b1c539b560bf07647cdea3486ff5a929108e9231 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 01:18:53 +0000 Subject: [PATCH 01/18] feat: redesign Mission page with immersive war room aesthetic Replace the Flex/Surface two-column layout with a full-viewport conference room design featuring three composited screen panels: - Left: MatrixBackground tenant signal display - Center: checkpoint interaction with progress pips, styled choices - Right: mission briefing with timer widget and abandon controls Background uses room-bg.jpg with darkened filter, vignette overlay, and desk foreground gradient. All screens have scan-line overlays and CRT-inspired styling. Replaced RadioGroup/Radio with custom styled choice divs. Added .jpg module declaration to types.d.ts. https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 913 ++++++++++++++++++++++++++------------- ui/assets/room-bg.jpg | 0 ui/types.d.ts | 5 + 3 files changed, 619 insertions(+), 299 deletions(-) create mode 100644 ui/assets/room-bg.jpg diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index d12d3fa..fc263e3 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -1,22 +1,8 @@ import React, { useState, useEffect, useCallback, useMemo, useRef } from "react"; import { useNavigate, useParams } from "react-router-dom"; -import { Flex } from "@dynatrace/strato-components/layouts"; -import { Surface } from "@dynatrace/strato-components/layouts"; -import { - Heading, - Paragraph, - Strong, - Text, -} from "@dynatrace/strato-components/typography"; -import { Button } from "@dynatrace/strato-components/buttons"; -import { Chip } from "@dynatrace/strato-components-preview/content"; -import { - RadioGroup, - Radio, -} from "@dynatrace/strato-components-preview/forms"; -import { SuccessIcon } from "@dynatrace/strato-icons"; import { getMissionById } from "../data/missions"; import { MatrixBackground } from "../components/MatrixBackground"; +import roomBg from "../assets/room-bg.jpg"; type CheckpointStatus = "locked" | "active" | "completed"; @@ -24,21 +10,76 @@ const TIME_BONUS_PER_SECOND = 0.5; const HINT_PENALTY = 50; const WRONG_ANSWER_PENALTY = 100; +const CHOICE_KEYS = ["A", "B", "C", "D", "E", "F", "G", "H"]; + function formatTime(totalSeconds: number): string { const minutes = Math.floor(totalSeconds / 60); const seconds = totalSeconds % 60; return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`; } +/** Renders checkpoint instruction text, styling backtick-wrapped DQL as inline code */ +function renderInstruction(text: string): React.ReactNode { + const parts = text.split(/(`[^`]+`)/g); + return parts.map((part, i) => { + if (part.startsWith("`") && part.endsWith("`")) { + return ( + + {part.slice(1, -1)} + + ); + } + return {part}; + }); +} + +const DIFFICULTY_COLORS: Record = { + rookie: "rgba(29,187,126,0.7)", + operator: "rgba(255,191,0,0.7)", + elite: "rgba(231,76,60,0.7)", + legend: "rgba(231,76,60,0.7)", +}; + +const DIFFICULTY_BG: Record = { + rookie: "rgba(29,187,126,0.1)", + operator: "rgba(255,191,0,0.1)", + elite: "rgba(231,76,60,0.1)", + legend: "rgba(231,76,60,0.1)", +}; + +const scanLineStyle: React.CSSProperties = { + position: "absolute", + inset: 0, + background: + "repeating-linear-gradient(to bottom, transparent 0px, transparent 3px, rgba(0,0,0,0.05) 3px, rgba(0,0,0,0.05) 4px)", + pointerEvents: "none", + zIndex: 10, +}; + +const screenBase: React.CSSProperties = { + borderRadius: 5, + border: "1px solid rgba(255,255,255,0.07)", + overflow: "hidden", + position: "relative", + background: "rgba(4,6,14,0.88)", +}; + export const Mission = () => { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const mission = id ? getMissionById(id) : undefined; const [currentCheckpoint, setCurrentCheckpoint] = useState(0); - const [completedCheckpoints, setCompletedCheckpoints] = useState( - [] - ); + const [completedCheckpoints, setCompletedCheckpoints] = useState([]); const [timerSeconds, setTimerSeconds] = useState(null); const [isValidating, setIsValidating] = useState(false); const [selectedAnswer, setSelectedAnswer] = useState(""); @@ -50,6 +91,20 @@ export const Mission = () => { const [abandonConfirm, setAbandonConfirm] = useState(false); const hasTimedOutRef = useRef(false); + // Inject keyframes + useEffect(() => { + const styleId = "mission-war-room-keyframes"; + if (document.getElementById(styleId)) return; + const style = document.createElement("style"); + style.id = styleId; + style.textContent = `@keyframes missionLiveDot { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }`; + document.head.appendChild(style); + return () => { + const el = document.getElementById(styleId); + if (el) el.remove(); + }; + }, []); + // Initialize timer when mission loads useEffect(() => { if (mission) { @@ -202,313 +257,573 @@ export const Mission = () => { }); }, [mission, timerSeconds, baseScore, hintsUsed, navigate]); - // Mission not found + // ── Room wrapper (shared by all states) ── + const roomWrapper = (children: React.ReactNode) => ( +
+ {/* Room photo */} +
+ {/* Vignette overlay */} +
+ {/* Desk foreground */} +
+ {/* UI layer */} +
+ {children} +
+
+ ); + + // ── Mission not found ── if (!mission) { - return ( - - - - Mission Not Found - - The requested mission does not exist or has been decommissioned. - - - - - + return roomWrapper( +
+
Mission Not Found
+
+ The requested mission does not exist or has been decommissioned. +
+ +
); } const displaySeconds = timerSeconds ?? mission.timerSeconds; const timerIsLow = displaySeconds < 60; - - return ( -
- - - {/* Left column — Briefing panel */} - 0 : false; + const hintRevealed = checkpoint ? hintsRevealed.includes(checkpoint.id) : false; + + return roomWrapper( + <> + {/* ── Status bar ── */} +
- Mission - - - {/* Title + codename */} - - - {mission.codename} - - - {mission.title} - - {/* Role + difficulty badges */} - - {mission.role} - - {mission.difficulty.toUpperCase()} - - - - {/* Briefing */} - {mission.briefing} - - {/* Timer */} - - - Time Remaining - - - {formatTime(displaySeconds)} - - - - - - {/* Hint cost notice */} - - Intel requested: -{HINT_PENALTY} pts per hint used - - - - - - {/* Abandon Mission */} -
- {!abandonConfirm ? ( - - ) : ( -
+
+ - This will end your mission. -
-
+ + {/* Checkpoint body */} +
+ {/* Progress pips */} +
+ {mission.checkpoints.map((_, i) => { + const st = getCheckpointStatus(i); + let bg = "rgba(255,255,255,0.08)"; + if (st === "completed") bg = "#1dbb7e"; + if (st === "active") bg = "#1496ff"; + return ( +
+ ); + })} + + Checkpoint {currentCheckpoint + 1} + +
+ + {cpStatus === "completed" || completedCheckpoints.includes(currentCheckpoint) ? ( + /* ── Completed state ── */ +
+ + + Checkpoint Complete + + + +{checkpoint?.points ?? 0} pts + +
+ ) : checkpoint ? ( + <> + {/* Section label */} +
- Confirm - -
+ + {/* Question text */} +
+ {renderInstruction(checkpoint.instruction)} +
+ + {/* Hint revealed */} + {hintRevealed && ( +
+ {checkpoint.hint} +
+ )} + + {/* Multiple choice options */} + {isMultipleChoice && checkpoint.choices && ( +
+ {checkpoint.choices.map((option, i) => { + const isSelected = selectedAnswer === option; + return ( +
setSelectedAnswer(option)} + style={{ + padding: "6px 10px", + borderRadius: 4, + border: isSelected + ? "1px solid rgba(20,150,255,0.45)" + : "1px solid rgba(255,255,255,0.07)", + fontSize: 11, + color: isSelected ? "#c8d4e8" : "rgba(180,200,220,0.6)", + background: isSelected + ? "rgba(20,150,255,0.1)" + : "rgba(255,255,255,0.025)", + cursor: "pointer", + display: "flex", + alignItems: "center", + gap: 8, + }} + > + + {CHOICE_KEYS[i] ?? String(i + 1)} + + {option} +
+ ); + })} +
+ )} + + {/* Answer error */} + {answerError && ( +
{answerError}
+ )} + + {/* Action row */} +
- Cancel - -
-
- )} + {/* Hint button */} +
+ {hintAvailable && !hintRevealed && ( + handleRequestHint(checkpoint.id)} + style={{ + fontSize: 10, + textTransform: "uppercase", + color: "rgba(150,170,200,0.32)", + cursor: "pointer", + letterSpacing: "0.08em", + }} + > + ⊹ Request intel (−{HINT_PENALTY} pts) + + )} +
+ {/* Validate button */} + +
+ + ) : null} +
- - {/* Right column — Checkpoints */} - - Checkpoints - - {mission.checkpoints.map((checkpoint, index) => { - const status = getCheckpointStatus(index); - const isMultipleChoice = checkpoint.type === "multiple-choice"; - const hintAvailable = checkpoint.hint.length > 0; - const hintRevealed = hintsRevealed.includes(checkpoint.id); - const isActive = status === "active"; - const isCompleted = status === "completed"; - const isLocked = status === "locked"; - - return ( - - +
+
+ {/* Eyebrow */} +
+ Mission Briefing +
+ + {/* Mission title */} +
{mission.title}
+ + {/* Tags */} +
+ - {/* Step number / status indicator */} - - {isCompleted ? ( - - ) : ( - - - {String(index + 1).padStart(2, "0")} - - - )} - - - {/* Content */} - - - {checkpoint.title} - {isCompleted && ( - - - Complete - - - - {checkpoint.points} pts - - - - )} - {isActive && ( - - Active - - )} - {isLocked && ( - Locked - )} - + {mission.role} + + + {mission.difficulty} + +
- {!isLocked && ( - {checkpoint.instruction} - )} + {/* Divider */} +
- {/* Hint system */} - {isActive && hintAvailable && !hintRevealed && ( - - - - )} - - {hintRevealed && ( - - - - Intel - - {checkpoint.hint} - - Intel requested: -{HINT_PENALTY} pts - - - - )} - - {/* Multiple choice options */} - {isActive && isMultipleChoice && checkpoint.choices && ( - - setSelectedAnswer(value)} - > - {checkpoint.choices.map((option) => ( - - {option} - - ))} - - {answerError && ( - - {answerError} - - )} - - )} + {/* Briefing text */} +
+ {mission.briefing} +
- {/* Validate button */} - {isActive && ( - - - - )} - - - - ); - })} - - -
+ {/* Timer widget */} +
+
+ Time Remaining +
+
+ {formatTime(displaySeconds)} +
+
+ + {/* Abandon section */} +
+ {!abandonConfirm ? ( + setAbandonConfirm(true)} + style={{ + fontSize: 9, + textTransform: "uppercase", + color: "rgba(200,80,80,0.35)", + cursor: "pointer", + letterSpacing: "0.08em", + }} + > + Abandon Mission + + ) : ( +
+ + This will end your mission. + +
+ navigate("/missions")} + style={{ + fontSize: 9, + textTransform: "uppercase", + color: "rgba(231,76,60,0.7)", + cursor: "pointer", + letterSpacing: "0.08em", + }} + > + Confirm + + setAbandonConfirm(false)} + style={{ + fontSize: 9, + textTransform: "uppercase", + color: "rgba(150,170,200,0.4)", + cursor: "pointer", + letterSpacing: "0.08em", + }} + > + Cancel + +
+
+ )} +
+
+
+
+ ); }; diff --git a/ui/assets/room-bg.jpg b/ui/assets/room-bg.jpg new file mode 100644 index 0000000..e69de29 diff --git a/ui/types.d.ts b/ui/types.d.ts index 2e9cb26..4dde23d 100644 --- a/ui/types.d.ts +++ b/ui/types.d.ts @@ -7,3 +7,8 @@ declare module "*.png" { const src: string; export default src; } + +declare module "*.jpg" { + const src: string; + export default src; +} From 35f7540911f660e43de048534ee545c9c04d7708 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 01:29:55 +0000 Subject: [PATCH 02/18] refactor: use plain string constant for room-bg.jpg path Replace JS asset import with a static path string to avoid bundler dependency on the image file. https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index fc263e3..ca175fc 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -2,7 +2,7 @@ import React, { useState, useEffect, useCallback, useMemo, useRef } from "react" import { useNavigate, useParams } from "react-router-dom"; import { getMissionById } from "../data/missions"; import { MatrixBackground } from "../components/MatrixBackground"; -import roomBg from "../assets/room-bg.jpg"; +const roomBg = "/ui/assets/room-bg.jpg"; type CheckpointStatus = "locked" | "active" | "completed"; From d5f60bd6e915c75d95d20a6c24211919905dde31 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 16:26:23 +0000 Subject: [PATCH 03/18] fix: Mission.tsx contrast, brightness, and hint handler form - Darken room bg brightness to 0.28 for better UI contrast - Increase status bar text opacity to 0.75 - Darken panel backgrounds to rgba(4,6,14,0.92) - Brighten checkpoint question text to #e0eaf8 - Brighten choice text to rgba(210,225,240,0.85) - Brighten briefing body text to rgba(170,190,210,0.75) - Brighten mission title to #eef4fc - Use explicit mission.checkpoints[currentCheckpoint].id for hint handler https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index ca175fc..e6aa44f 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -70,7 +70,7 @@ const screenBase: React.CSSProperties = { border: "1px solid rgba(255,255,255,0.07)", overflow: "hidden", position: "relative", - background: "rgba(4,6,14,0.88)", + background: "rgba(4,6,14,0.92)", }; export const Mission = () => { @@ -268,7 +268,7 @@ export const Mission = () => { backgroundImage: `url(${roomBg})`, backgroundSize: "cover", backgroundPosition: "center 15%", - filter: "brightness(0.38) saturate(0.75)", + filter: "brightness(0.28) saturate(0.75)", zIndex: 0, }} /> @@ -369,7 +369,7 @@ export const Mission = () => { fontSize: 10, letterSpacing: "0.12em", textTransform: "uppercase", - color: "rgba(180,200,220,0.4)", + color: "rgba(180,200,220,0.75)", }} > {/* Pulsing red dot */} @@ -543,7 +543,7 @@ export const Mission = () => {
{/* Question text */} -
+
{renderInstruction(checkpoint.instruction)}
@@ -579,7 +579,7 @@ export const Mission = () => { ? "1px solid rgba(20,150,255,0.45)" : "1px solid rgba(255,255,255,0.07)", fontSize: 11, - color: isSelected ? "#c8d4e8" : "rgba(180,200,220,0.6)", + color: isSelected ? "#c8d4e8" : "rgba(210,225,240,0.85)", background: isSelected ? "rgba(20,150,255,0.1)" : "rgba(255,255,255,0.025)", @@ -625,7 +625,7 @@ export const Mission = () => {
{hintAvailable && !hintRevealed && ( handleRequestHint(checkpoint.id)} + onClick={() => handleRequestHint(mission.checkpoints[currentCheckpoint].id)} style={{ fontSize: 10, textTransform: "uppercase", @@ -693,7 +693,7 @@ export const Mission = () => {
{/* Mission title */} -
{mission.title}
+
{mission.title}
{/* Tags */}
@@ -730,7 +730,7 @@ export const Mission = () => {
Date: Wed, 25 Mar 2026 16:54:34 +0000 Subject: [PATCH 04/18] debug: add console.log to choice onClick and handleValidate https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index e6aa44f..ac89e21 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -180,6 +180,7 @@ export const Mission = () => { const handleValidate = useCallback( (index: number) => { + console.log("handleValidate called, index:", index, "selectedAnswer:", selectedAnswer, "isValidating:", isValidating); if (isValidating || !mission) return; const checkpoint = mission.checkpoints[index]; @@ -571,7 +572,10 @@ export const Mission = () => { return (
setSelectedAnswer(option)} + onClick={() => { + console.log("choice clicked:", option); + setSelectedAnswer(option); + }} style={{ padding: "6px 10px", borderRadius: 4, From 28f44a530977bcf0f5d441b7f534bf2cdbac2435 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 17:01:42 +0000 Subject: [PATCH 05/18] fix: add pointer-events:none to desk foreground overlay The desk gradient div (z-index:3) was overlapping the UI layer (z-index:2), blocking clicks on the validate button and action row. https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index ac89e21..e8fdef3 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -295,6 +295,7 @@ export const Mission = () => { background: "linear-gradient(to top, rgba(10,5,2,0.96) 0%, rgba(10,5,2,0.55) 60%, transparent 100%)", zIndex: 3, + pointerEvents: "none", }} /> {/* UI layer */} From b9153d1f46dbcd2b2b15f21441cfadb8ef98ca42 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 21:02:03 +0000 Subject: [PATCH 06/18] fix: remove room-bg photo for better UI readability Remove the background photo div and unused roomBg constant. The outermost wrapper's solid #060810 background now serves as the sole backdrop, improving text contrast and readability. https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index e8fdef3..83aa540 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -2,8 +2,6 @@ import React, { useState, useEffect, useCallback, useMemo, useRef } from "react" import { useNavigate, useParams } from "react-router-dom"; import { getMissionById } from "../data/missions"; import { MatrixBackground } from "../components/MatrixBackground"; -const roomBg = "/ui/assets/room-bg.jpg"; - type CheckpointStatus = "locked" | "active" | "completed"; const TIME_BONUS_PER_SECOND = 0.5; @@ -261,18 +259,6 @@ export const Mission = () => { // ── Room wrapper (shared by all states) ── const roomWrapper = (children: React.ReactNode) => (
- {/* Room photo */} -
{/* Vignette overlay */}
Date: Wed, 25 Mar 2026 21:08:45 +0000 Subject: [PATCH 07/18] fix: restore room-bg photo at brightness(0.15) with opaque panels Re-add the room background photo div with lower brightness (0.15) and saturation (0.7). Change panel backgrounds to rgba(2,4,10,0.97) so text is readable against the nearly-opaque panels, not the photo. https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index 83aa540..7121068 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect, useCallback, useMemo, useRef } from "react" import { useNavigate, useParams } from "react-router-dom"; import { getMissionById } from "../data/missions"; import { MatrixBackground } from "../components/MatrixBackground"; +const roomBg = "/ui/assets/room-bg.jpg"; type CheckpointStatus = "locked" | "active" | "completed"; const TIME_BONUS_PER_SECOND = 0.5; @@ -68,7 +69,7 @@ const screenBase: React.CSSProperties = { border: "1px solid rgba(255,255,255,0.07)", overflow: "hidden", position: "relative", - background: "rgba(4,6,14,0.92)", + background: "rgba(2,4,10,0.97)", }; export const Mission = () => { @@ -259,6 +260,18 @@ export const Mission = () => { // ── Room wrapper (shared by all states) ── const roomWrapper = (children: React.ReactNode) => (
+ {/* Room photo */} +
{/* Vignette overlay */}
Date: Wed, 25 Mar 2026 21:57:16 +0000 Subject: [PATCH 08/18] style: increase room-bg brightness from 0.15 to 0.25 https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index 7121068..c7a50dc 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -268,7 +268,7 @@ export const Mission = () => { backgroundImage: `url(${roomBg})`, backgroundSize: "cover", backgroundPosition: "center 15%", - filter: "brightness(0.15) saturate(0.7)", + filter: "brightness(0.25) saturate(0.7)", zIndex: 0, }} /> From 2f4b28a4d420a8f6bad90dbdc7435d08bb556525 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 21:58:51 +0000 Subject: [PATCH 09/18] style: frosted glass panels with room-bg showing through - Increase room-bg brightness to 0.35 - Lower panel opacity to rgba(2,4,12,0.82) so photo bleeds through - Add backdropFilter blur(2px) for frosted glass effect - Set center panel border to rgba(20,150,255,0.25) https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index c7a50dc..4b1b741 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -69,7 +69,8 @@ const screenBase: React.CSSProperties = { border: "1px solid rgba(255,255,255,0.07)", overflow: "hidden", position: "relative", - background: "rgba(2,4,10,0.97)", + background: "rgba(2,4,12,0.82)", + backdropFilter: "blur(2px)", }; export const Mission = () => { @@ -268,7 +269,7 @@ export const Mission = () => { backgroundImage: `url(${roomBg})`, backgroundSize: "cover", backgroundPosition: "center 15%", - filter: "brightness(0.25) saturate(0.7)", + filter: "brightness(0.35) saturate(0.7)", zIndex: 0, }} /> @@ -434,7 +435,7 @@ export const Mission = () => {
{/* ═══ CENTER screen — Checkpoint ═══ */} -
+
{/* Top bar */}
Date: Wed, 25 Mar 2026 22:10:07 +0000 Subject: [PATCH 10/18] feat: absolute-position panels over room-bg photo Replace CSS grid layout with absolutely positioned panels aligned to the screen positions in room-bg.jpg. Remove vignette overlay, desk foreground, and status bar. Add bottom HUD strip. Panels use frosted glass effect over the photo at brightness(0.55). https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 836 +++++++++++++++++++-------------------- 1 file changed, 399 insertions(+), 437 deletions(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index 4b1b741..4b8884b 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -65,12 +65,14 @@ const scanLineStyle: React.CSSProperties = { }; const screenBase: React.CSSProperties = { - borderRadius: 5, + borderRadius: 4, border: "1px solid rgba(255,255,255,0.07)", overflow: "hidden", - position: "relative", + position: "absolute", background: "rgba(2,4,12,0.82)", backdropFilter: "blur(2px)", + display: "flex", + flexDirection: "column", }; export const Mission = () => { @@ -258,9 +260,9 @@ export const Mission = () => { }); }, [mission, timerSeconds, baseScore, hintsUsed, navigate]); - // ── Room wrapper (shared by all states) ── - const roomWrapper = (children: React.ReactNode) => ( -
+ // ── Room shell (shared by all states) ── + const roomShell = (children: React.ReactNode) => ( +
{/* Room photo */}
{ inset: 0, backgroundImage: `url(${roomBg})`, backgroundSize: "cover", - backgroundPosition: "center 15%", - filter: "brightness(0.35) saturate(0.7)", + backgroundPosition: "center top", + filter: "brightness(0.55) saturate(0.8)", zIndex: 0, }} /> - {/* Vignette overlay */} -
- {/* Desk foreground */} -
{/* UI layer */} -
+
{children}
@@ -316,14 +284,16 @@ export const Mission = () => { // ── Mission not found ── if (!mission) { - return roomWrapper( + return roomShell(
@@ -359,476 +329,468 @@ export const Mission = () => { const hintAvailable = checkpoint ? checkpoint.hint.length > 0 : false; const hintRevealed = checkpoint ? hintsRevealed.includes(checkpoint.id) : false; - return roomWrapper( + return roomShell( <> - {/* ── Status bar ── */} -
- {/* Pulsing red dot */} + {/* ═══ LEFT screen — Tenant Signal / MatrixBackground ═══ */} +
+
+ {/* Header strip */}
- Mission Control - {/* Separator */} -
- - {mission.codename} / {mission.title} - -
- Operator Active -
- Playground Env + > +
+ Tenant Signal +
+ {/* Matrix canvas wrapper */} +
+ +
- {/* ── Screen wall ── */} -
- {/* ═══ LEFT screen — Tenant Signal / MatrixBackground ═══ */} -
-
- {/* Header strip */} -
+
+ {/* Top bar */} +
+ -
- Tenant Signal -
- {/* Matrix canvas wrapper */} -
- -
-
- - {/* ═══ CENTER screen — Checkpoint ═══ */} -
-
- {/* Top bar */} -
+
+ + {formatTime(displaySeconds)} + +
+ + {/* Checkpoint body */} +
+ {/* Progress pips */} +
+ {mission.checkpoints.map((_, i) => { + const st = getCheckpointStatus(i); + let bg = "rgba(255,255,255,0.08)"; + if (st === "completed") bg = "#1dbb7e"; + if (st === "active") bg = "#1496ff"; + return ( +
+ ); + })} - {mission.title} — CP {currentCheckpoint + 1} of {mission.checkpoints.length} + Checkpoint {currentCheckpoint + 1} -
- + + {cpStatus === "completed" || completedCheckpoints.includes(currentCheckpoint) ? ( + /* ── Completed state ── */ +
- {formatTime(displaySeconds)} - -
- - {/* Checkpoint body */} -
- {/* Progress pips */} -
- {mission.checkpoints.map((_, i) => { - const st = getCheckpointStatus(i); - let bg = "rgba(255,255,255,0.08)"; - if (st === "completed") bg = "#1dbb7e"; - if (st === "active") bg = "#1496ff"; - return ( -
- ); - })} - - Checkpoint {currentCheckpoint + 1} + + + Checkpoint Complete + + + +{checkpoint?.points ?? 0} pts
- - {cpStatus === "completed" || completedCheckpoints.includes(currentCheckpoint) ? ( - /* ── Completed state ── */ + ) : checkpoint ? ( + <> + {/* Section label */}
- - - Checkpoint Complete - - - +{checkpoint?.points ?? 0} pts - + {checkpoint.title} +
+ + {/* Question text */} +
+ {renderInstruction(checkpoint.instruction)}
- ) : checkpoint ? ( - <> - {/* Section label */} + + {/* Hint revealed */} + {hintRevealed && (
- {checkpoint.title} -
- - {/* Question text */} -
- {renderInstruction(checkpoint.instruction)} + {checkpoint.hint}
+ )} - {/* Hint revealed */} - {hintRevealed && ( -
- {checkpoint.hint} -
- )} - - {/* Multiple choice options */} - {isMultipleChoice && checkpoint.choices && ( -
- {checkpoint.choices.map((option, i) => { - const isSelected = selectedAnswer === option; - return ( -
{ - console.log("choice clicked:", option); - setSelectedAnswer(option); - }} + {/* Multiple choice options */} + {isMultipleChoice && checkpoint.choices && ( +
+ {checkpoint.choices.map((option, i) => { + const isSelected = selectedAnswer === option; + return ( +
{ + console.log("choice clicked:", option); + setSelectedAnswer(option); + }} + style={{ + padding: "6px 10px", + borderRadius: 4, + border: isSelected + ? "1px solid rgba(20,150,255,0.45)" + : "1px solid rgba(255,255,255,0.07)", + fontSize: 11, + color: isSelected ? "#c8d4e8" : "rgba(210,225,240,0.85)", + background: isSelected + ? "rgba(20,150,255,0.1)" + : "rgba(255,255,255,0.025)", + cursor: "pointer", + display: "flex", + alignItems: "center", + gap: 8, + }} + > + - - {CHOICE_KEYS[i] ?? String(i + 1)} - - {option} -
- ); - })} -
- )} - - {/* Answer error */} - {answerError && ( -
{answerError}
- )} - - {/* Action row */} -
+ {option} +
+ ); + })} +
+ )} + + {/* Answer error */} + {answerError && ( +
{answerError}
+ )} + + {/* Action row */} +
+ {/* Hint button */} +
+ {hintAvailable && !hintRevealed && ( + handleRequestHint(mission.checkpoints[currentCheckpoint].id)} + style={{ + fontSize: 10, + textTransform: "uppercase", + color: "rgba(150,170,200,0.32)", + cursor: "pointer", + letterSpacing: "0.08em", + }} + > + ⊹ Request intel (−{HINT_PENALTY} pts) + + )} +
+ {/* Validate button */} + -
- - ) : null} -
+ {isValidating ? "Confirming..." : "Validate →"} + +
+ + ) : null}
+
- {/* ═══ RIGHT screen — Mission Briefing ═══ */} -
-
+ {/* ═══ RIGHT screen — Mission Briefing ═══ */} +
+
+
+ {/* Eyebrow */}
- {/* Eyebrow */} -
+ + {/* Mission title */} +
{mission.title}
+ + {/* Tags */} +
+ - Mission Briefing -
- - {/* Mission title */} -
{mission.title}
+ {mission.role} + + + {mission.difficulty} + +
- {/* Tags */} -
- - {mission.role} - - - {mission.difficulty} - -
+ {/* Divider */} +
- {/* Divider */} -
+ {/* Briefing text */} +
+ {mission.briefing} +
- {/* Briefing text */} + {/* Timer widget */} +
- {mission.briefing} + Time Remaining
- - {/* Timer widget */}
-
+
+ + {/* Abandon section */} +
+ {!abandonConfirm ? ( + setAbandonConfirm(true)} style={{ fontSize: 9, - color: "rgba(150,170,200,0.28)", textTransform: "uppercase", + color: "rgba(200,80,80,0.35)", + cursor: "pointer", letterSpacing: "0.08em", - marginBottom: 4, }} > - Time Remaining -
-
- {formatTime(displaySeconds)} -
-
- - {/* Abandon section */} -
- {!abandonConfirm ? ( - setAbandonConfirm(true)} - style={{ - fontSize: 9, - textTransform: "uppercase", - color: "rgba(200,80,80,0.35)", - cursor: "pointer", - letterSpacing: "0.08em", - }} - > - Abandon Mission + Abandon Mission + + ) : ( +
+ + This will end your mission. - ) : ( -
- - This will end your mission. +
+ navigate("/missions")} + style={{ + fontSize: 9, + textTransform: "uppercase", + color: "rgba(231,76,60,0.7)", + cursor: "pointer", + letterSpacing: "0.08em", + }} + > + Confirm + + setAbandonConfirm(false)} + style={{ + fontSize: 9, + textTransform: "uppercase", + color: "rgba(150,170,200,0.4)", + cursor: "pointer", + letterSpacing: "0.08em", + }} + > + Cancel -
- navigate("/missions")} - style={{ - fontSize: 9, - textTransform: "uppercase", - color: "rgba(231,76,60,0.7)", - cursor: "pointer", - letterSpacing: "0.08em", - }} - > - Confirm - - setAbandonConfirm(false)} - style={{ - fontSize: 9, - textTransform: "uppercase", - color: "rgba(150,170,200,0.4)", - cursor: "pointer", - letterSpacing: "0.08em", - }} - > - Cancel - -
- )} -
+
+ )}
+ + {/* ── Bottom HUD strip ── */} +
+ {/* Pulsing red dot */} +
+ Mission Control +
+ + {mission.codename} / {mission.title} + +
+ Operator Active +
+ Playground Env +
); }; From 0da20b9a7d9b2a688b43e606ed71c53e7ee12d5d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 22:19:23 +0000 Subject: [PATCH 11/18] style: taller panels, brighter photo, more visible action buttons - Extend all three panel heights from 44% to 52% - Increase room-bg brightness to 0.85 and saturation to 0.95 - Restyle VALIDATE button with bolder colors and larger padding - Restyle REQUEST INTEL as a bordered button with white text - Restyle ABANDON MISSION as a bordered red button https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index 4b8884b..afc37b4 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -271,7 +271,7 @@ export const Mission = () => { backgroundImage: `url(${roomBg})`, backgroundSize: "cover", backgroundPosition: "center top", - filter: "brightness(0.55) saturate(0.8)", + filter: "brightness(0.85) saturate(0.95)", zIndex: 0, }} /> @@ -332,7 +332,7 @@ export const Mission = () => { return roomShell( <> {/* ═══ LEFT screen — Tenant Signal / MatrixBackground ═══ */} -
+
{/* Header strip */}
{
{/* ═══ CENTER screen — Checkpoint ═══ */} -
+
{/* Top bar */}
{ handleRequestHint(mission.checkpoints[currentCheckpoint].id)} style={{ - fontSize: 10, + fontSize: 11, + fontWeight: 600, textTransform: "uppercase", - color: "rgba(150,170,200,0.32)", + color: "rgba(255,255,255,0.8)", cursor: "pointer", letterSpacing: "0.08em", + border: "1px solid rgba(255,255,255,0.3)", + padding: "6px 12px", + borderRadius: 3, + background: "rgba(255,255,255,0.08)", }} > ⊹ Request intel (−{HINT_PENALTY} pts) @@ -573,12 +578,13 @@ export const Mission = () => { onClick={() => handleValidate(currentCheckpoint)} disabled={isValidating || (isMultipleChoice && !selectedAnswer)} style={{ - fontSize: 10, - padding: "5px 14px", + fontSize: 11, + fontWeight: 600, + padding: "8px 20px", borderRadius: 3, - background: "rgba(20,150,255,0.1)", - border: "1px solid rgba(20,150,255,0.28)", - color: "#1496ff", + background: "rgba(20,150,255,0.35)", + border: "1px solid rgba(20,150,255,0.8)", + color: "#ffffff", letterSpacing: "0.1em", textTransform: "uppercase", cursor: @@ -598,7 +604,7 @@ export const Mission = () => {
{/* ═══ RIGHT screen — Mission Briefing ═══ */} -
+
{ setAbandonConfirm(true)} style={{ - fontSize: 9, + fontSize: 11, + fontWeight: 600, textTransform: "uppercase", - color: "rgba(200,80,80,0.35)", + color: "rgba(220,80,80,0.9)", cursor: "pointer", letterSpacing: "0.08em", + border: "1px solid rgba(220,80,80,0.4)", + padding: "6px 12px", + borderRadius: 3, + background: "rgba(220,80,80,0.1)", }} > Abandon Mission From 23794f083d717ad241e165fe09719117c1dfa955 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 22:27:39 +0000 Subject: [PATCH 12/18] feat: redistribute panel content and fix positions - Resize panels: LEFT 24%x56%, CENTER 38%x56%, RIGHT 23%x56% - LEFT: remove Tenant Signal header, add timer + abandon at bottom over MatrixBackground with opaque dock - RIGHT: remove timer + abandon, briefing-only with scrollable text - CENTER: unchanged (checkpoint content) https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 201 ++++++++++++++++++--------------------- 1 file changed, 92 insertions(+), 109 deletions(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index afc37b4..a62d715 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -331,36 +331,107 @@ export const Mission = () => { return roomShell( <> - {/* ═══ LEFT screen — Tenant Signal / MatrixBackground ═══ */} -
+ {/* ═══ LEFT screen — MatrixBackground + Timer + Abandon ═══ */} +
- {/* Header strip */} + {/* Matrix canvas wrapper */} +
+ +
+ {/* Bottom dock: timer + abandon */}
-
- Tenant Signal -
- {/* Matrix canvas wrapper */} -
- +
+ Time Remaining +
+
+ {formatTime(displaySeconds)} +
+
+ {!abandonConfirm ? ( + setAbandonConfirm(true)} + style={{ + fontSize: 11, + fontWeight: 600, + textTransform: "uppercase", + color: "rgba(220,80,80,0.9)", + cursor: "pointer", + letterSpacing: "0.08em", + border: "1px solid rgba(220,80,80,0.4)", + padding: "6px 12px", + borderRadius: 3, + background: "rgba(220,80,80,0.1)", + }} + > + Abandon Mission + + ) : ( +
+ + This will end your mission. + +
+ navigate("/missions")} + style={{ + fontSize: 9, + textTransform: "uppercase", + color: "rgba(231,76,60,0.7)", + cursor: "pointer", + letterSpacing: "0.08em", + }} + > + Confirm + + setAbandonConfirm(false)} + style={{ + fontSize: 9, + textTransform: "uppercase", + color: "rgba(150,170,200,0.4)", + cursor: "pointer", + letterSpacing: "0.08em", + }} + > + Cancel + +
+
+ )} +
{/* ═══ CENTER screen — Checkpoint ═══ */} -
+
{/* Top bar */}
{
{/* ═══ RIGHT screen — Mission Briefing ═══ */} -
+
{ color: "rgba(170,190,210,0.75)", lineHeight: 1.65, flex: 1, - overflow: "hidden", + overflow: "auto", }} > {mission.briefing}
- - {/* Timer widget */} -
-
- Time Remaining -
-
- {formatTime(displaySeconds)} -
-
- - {/* Abandon section */} -
- {!abandonConfirm ? ( - setAbandonConfirm(true)} - style={{ - fontSize: 11, - fontWeight: 600, - textTransform: "uppercase", - color: "rgba(220,80,80,0.9)", - cursor: "pointer", - letterSpacing: "0.08em", - border: "1px solid rgba(220,80,80,0.4)", - padding: "6px 12px", - borderRadius: 3, - background: "rgba(220,80,80,0.1)", - }} - > - Abandon Mission - - ) : ( -
- - This will end your mission. - -
- navigate("/missions")} - style={{ - fontSize: 9, - textTransform: "uppercase", - color: "rgba(231,76,60,0.7)", - cursor: "pointer", - letterSpacing: "0.08em", - }} - > - Confirm - - setAbandonConfirm(false)} - style={{ - fontSize: 9, - textTransform: "uppercase", - color: "rgba(150,170,200,0.4)", - cursor: "pointer", - letterSpacing: "0.08em", - }} - > - Cancel - -
-
- )} -
From 0c0b294c061e1c634d1d49c33fe46f4ae2116a45 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 22:33:42 +0000 Subject: [PATCH 13/18] style: taller panels (64%), narrower right panel, larger title MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Extend all panel heights from 56% to 64% - Right panel width 23% → 21% to stay within photo boundary - Mission title in briefing panel 14px → 20px https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index a62d715..3c3e96a 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -332,7 +332,7 @@ export const Mission = () => { return roomShell( <> {/* ═══ LEFT screen — MatrixBackground + Timer + Abandon ═══ */} -
+
{/* Matrix canvas wrapper */}
@@ -431,7 +431,7 @@ export const Mission = () => {
{/* ═══ CENTER screen — Checkpoint ═══ */} -
+
{/* Top bar */}
{
{/* ═══ RIGHT screen — Mission Briefing ═══ */} -
+
{
{/* Mission title */} -
{mission.title}
+
{mission.title}
{/* Tags */}
From 6470fdae93f81699d91e0bee887600d208f25dc6 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 22:36:41 +0000 Subject: [PATCH 14/18] style: adjust panel positions, larger title and question text - LEFT: left 6.5%, width 22% - CENTER: left 29.5%, width 38% - RIGHT: left 68.5%, width 22% - Mission title: 22px / fontWeight 700 - Checkpoint question text: 14px (was 12px) https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index 3c3e96a..19c706e 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -332,7 +332,7 @@ export const Mission = () => { return roomShell( <> {/* ═══ LEFT screen — MatrixBackground + Timer + Abandon ═══ */} -
+
{/* Matrix canvas wrapper */}
@@ -431,7 +431,7 @@ export const Mission = () => {
{/* ═══ CENTER screen — Checkpoint ═══ */} -
+
{/* Top bar */}
{
{/* Question text */} -
+
{renderInstruction(checkpoint.instruction)}
@@ -675,7 +675,7 @@ export const Mission = () => {
{/* ═══ RIGHT screen — Mission Briefing ═══ */} -
+
{
{/* Mission title */} -
{mission.title}
+
{mission.title}
{/* Tags */}
From 783b845a5ad650952e4bfc959e5b9f8b159b2233 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 22:39:26 +0000 Subject: [PATCH 15/18] =?UTF-8?q?fix:=20panel=20overflow=20=E2=80=94=20sho?= =?UTF-8?q?rter=20height,=20narrower=20right,=20dock=20overflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - All panels height 64% → 58% - RIGHT panel width 22% → 19% - Left panel bottom dock: padding 12→8, overflow hidden - Mission title: explicit fontSize "22px", lineHeight 1.2 - Checkpoint question text confirmed at 14px https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index 19c706e..2b4b7c4 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -332,7 +332,7 @@ export const Mission = () => { return roomShell( <> {/* ═══ LEFT screen — MatrixBackground + Timer + Abandon ═══ */} -
+
{/* Matrix canvas wrapper */}
@@ -345,13 +345,14 @@ export const Mission = () => { bottom: 0, left: 0, right: 0, - padding: 12, + padding: 8, background: "rgba(2,4,12,0.85)", borderTop: "1px solid rgba(255,255,255,0.08)", display: "flex", flexDirection: "column", alignItems: "center", gap: 8, + overflow: "hidden", }} >
{
{/* ═══ CENTER screen — Checkpoint ═══ */} -
+
{/* Top bar */}
{
{/* ═══ RIGHT screen — Mission Briefing ═══ */} -
+
{
{/* Mission title */} -
{mission.title}
+
{mission.title}
{/* Tags */}
From c9b3119ec7ee3ad2614f37b9746507c923306fa7 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 22:43:44 +0000 Subject: [PATCH 16/18] fix: panel positions to cover photo screen boundaries - LEFT: left 1%, width 27%, height 65% - CENTER: left 29%, width 38%, height 65% - RIGHT: left 68%, width 20%, height 65% https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index 2b4b7c4..bf27db4 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -332,7 +332,7 @@ export const Mission = () => { return roomShell( <> {/* ═══ LEFT screen — MatrixBackground + Timer + Abandon ═══ */} -
+
{/* Matrix canvas wrapper */}
@@ -432,7 +432,7 @@ export const Mission = () => {
{/* ═══ CENTER screen — Checkpoint ═══ */} -
+
{/* Top bar */}
{
{/* ═══ RIGHT screen — Mission Briefing ═══ */} -
+
Date: Wed, 25 Mar 2026 22:47:22 +0000 Subject: [PATCH 17/18] style: larger, bolder briefing text in right panel fontSize 15px, fontWeight 600, color #e0eaf8, lineHeight 1.6 https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index bf27db4..1fb890f 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -737,9 +737,10 @@ export const Mission = () => { {/* Briefing text */}
Date: Wed, 25 Mar 2026 22:49:40 +0000 Subject: [PATCH 18/18] style: add fontWeight 700 to panel labels and section headers - Center panel top bar mission ID label: fontWeight 700 - Mission Briefing eyebrow label: fontWeight 700 - Checkpoint section label: fontWeight 700 https://claude.ai/code/session_012xbUB1XfH4Xh6d1JsM2s3a --- ui/app/pages/Mission.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/app/pages/Mission.tsx b/ui/app/pages/Mission.tsx index 1fb890f..1719273 100644 --- a/ui/app/pages/Mission.tsx +++ b/ui/app/pages/Mission.tsx @@ -450,6 +450,7 @@ export const Mission = () => { style={{ color: "rgba(20,150,255,0.6)", fontSize: 9, + fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.13em", }} @@ -533,6 +534,7 @@ export const Mission = () => {
{