diff --git a/apps/web/.claude/REMEDIATION_CTA_PLAN.md b/apps/web/.claude/REMEDIATION_CTA_PLAN.md
new file mode 100644
index 00000000..0c35cdb8
--- /dev/null
+++ b/apps/web/.claude/REMEDIATION_CTA_PLAN.md
@@ -0,0 +1,151 @@
+# Remediation CTA Plan
+
+## Overview
+
+Add special "fancy" treatment to the StartPracticeModal when the student is in remediation mode (has weak skills that need strengthening). This mirrors the existing tutorial CTA treatment.
+
+## Current Tutorial CTA Treatment (lines 1311-1428)
+
+When `sessionMode.type === 'progression' && tutorialRequired`:
+
+1. **Visual Design:**
+ - Green gradient background with border
+ - 🌟 icon
+ - "You've unlocked: [skill name]" heading
+ - "Start with a quick tutorial" subtitle
+ - Green gradient button: "🎓 Begin Tutorial →"
+
+2. **Behavior:**
+ - Replaces the regular "Let's Go!" button
+ - Clicking opens the SkillTutorialLauncher
+
+## Proposed Remediation CTA
+
+When `sessionMode.type === 'remediation'`:
+
+1. **Visual Design:**
+ - Amber/orange gradient background with border (warm "focus" colors)
+ - 💪 icon (strength/building)
+ - "Time to build strength!" heading
+ - "Focusing on [N] skills that need practice" subtitle
+ - Show weak skill badges with pKnown percentages
+ - Amber gradient button: "💪 Start Focus Practice →"
+
+2. **Behavior:**
+ - Replaces the regular "Let's Go!" button
+ - Clicking goes straight to practice (no separate launcher needed)
+ - The session will automatically target weak skills via sessionMode
+
+## Implementation Steps
+
+### Step 1: Add remediation detection
+
+```typescript
+// Derive whether to show remediation CTA
+const showRemediationCta = sessionMode.type === 'remediation' && sessionMode.weakSkills.length > 0
+```
+
+### Step 2: Create RemediationCta component section
+
+Add after the Tutorial CTA section (line ~1428), or restructure to have a single "special CTA" section that handles both cases.
+
+```tsx
+{/* Remediation CTA - Weak skills need strengthening */}
+{showRemediationCta && !showTutorialGate && (
+
+ {/* Info section */}
+
+
💪
+
+
Time to build strength!
+
Focusing on {weakSkills.length} skill{weakSkills.length > 1 ? 's' : ''} that need practice
+
+
+
+ {/* Weak skills badges */}
+
+ {sessionMode.weakSkills.slice(0, 4).map((skill) => (
+
+ {skill.displayName} ({Math.round(skill.pKnown * 100)}%)
+
+ ))}
+ {sessionMode.weakSkills.length > 4 && (
+ +{sessionMode.weakSkills.length - 4} more
+ )}
+
+
+ {/* Integrated start button */}
+
+ {isStarting ? 'Starting...' : (
+ <>
+ 💪
+ Start Focus Practice
+ →
+ >
+ )}
+
+
+)}
+```
+
+### Step 3: Update start button visibility logic
+
+Change from:
+```tsx
+{!showTutorialGate && (
+ Let's Go! →
+)}
+```
+
+To:
+```tsx
+{!showTutorialGate && !showRemediationCta && (
+ Let's Go! →
+)}
+```
+
+## Visual Comparison
+
+| Mode | Icon | Color Theme | Heading | Button Text |
+|------|------|-------------|---------|-------------|
+| Tutorial | 🌟 | Green | "You've unlocked: [skill]" | "🎓 Begin Tutorial →" |
+| Remediation | 💪 | Amber | "Time to build strength!" | "💪 Start Focus Practice →" |
+| Normal | - | Blue | "Ready to practice?" | "Let's Go! →" |
+
+## Files to Modify
+
+1. `apps/web/src/components/practice/StartPracticeModal.tsx`
+ - Add `showRemediationCta` derived state
+ - Add Remediation CTA section (similar structure to Tutorial CTA)
+ - Update regular start button visibility condition
+
+## Testing Considerations
+
+1. Storybook stories should cover:
+ - Remediation mode with 1 weak skill
+ - Remediation mode with 3+ weak skills
+ - Remediation mode with 5+ weak skills (overflow)
+
+2. The existing `StartPracticeModal.stories.tsx` already has sessionMode mocks - add remediation variants.
+
+## Accessibility
+
+- Ensure proper ARIA labels on the remediation CTA
+- Color contrast should meet WCAG guidelines (amber text on amber background needs checking)
+- Screen reader should announce the focus practice intent
diff --git a/apps/web/src/components/practice/StartPracticeModal.stories.tsx b/apps/web/src/components/practice/StartPracticeModal.stories.tsx
index ea4989bc..9ebd3ef6 100644
--- a/apps/web/src/components/practice/StartPracticeModal.stories.tsx
+++ b/apps/web/src/components/practice/StartPracticeModal.stories.tsx
@@ -108,6 +108,25 @@ const mockRemediationMode: RemediationMode = {
focusDescription: 'Strengthening: +3 and +4',
}
+const mockRemediationModeSingleSkill: RemediationMode = {
+ type: 'remediation',
+ weakSkills: [{ skillId: 'add-2', displayName: '+2', pKnown: 0.28 }],
+ focusDescription: 'Strengthening: +2',
+}
+
+const mockRemediationModeManySkills: RemediationMode = {
+ type: 'remediation',
+ weakSkills: [
+ { skillId: 'add-1', displayName: '+1', pKnown: 0.31 },
+ { skillId: 'add-2', displayName: '+2', pKnown: 0.38 },
+ { skillId: 'add-3', displayName: '+3', pKnown: 0.25 },
+ { skillId: 'add-4', displayName: '+4', pKnown: 0.42 },
+ { skillId: 'sub-1', displayName: '-1', pKnown: 0.33 },
+ { skillId: 'sub-2', displayName: '-2', pKnown: 0.29 },
+ ],
+ focusDescription: 'Strengthening: +1, +2, +3, +4, -1, -2',
+}
+
// Default props
const defaultProps = {
studentId: 'test-student-1',
@@ -183,7 +202,7 @@ export const DarkTheme: Story = {
}
/**
- * Remediation mode - student has weak skills to strengthen
+ * Remediation mode - student has weak skills to strengthen (2 skills)
*/
export const RemediationMode: Story = {
render: () => (
@@ -198,6 +217,56 @@ export const RemediationMode: Story = {
),
}
+/**
+ * Remediation mode with a single weak skill
+ */
+export const RemediationModeSingleSkill: Story = {
+ render: () => (
+
+
+
+ ),
+}
+
+/**
+ * Remediation mode with many weak skills (shows overflow)
+ */
+export const RemediationModeManySkills: Story = {
+ render: () => (
+
+
+
+ ),
+}
+
+/**
+ * Remediation mode - dark theme
+ */
+export const RemediationModeDark: Story = {
+ render: () => (
+
+
+
+
+
+ ),
+}
+
/**
* Progression mode - student is ready to learn a new skill
*/
diff --git a/apps/web/src/components/practice/StartPracticeModal.tsx b/apps/web/src/components/practice/StartPracticeModal.tsx
index df998ee7..2948ec22 100644
--- a/apps/web/src/components/practice/StartPracticeModal.tsx
+++ b/apps/web/src/components/practice/StartPracticeModal.tsx
@@ -83,6 +83,10 @@ export function StartPracticeModal({
// Whether to show the tutorial gate prompt
const showTutorialGate = !!tutorialConfig && !showTutorial
+ // Whether to show the remediation CTA (weak skills need strengthening)
+ const showRemediationCta =
+ sessionMode.type === 'remediation' && sessionMode.weakSkills.length > 0
+
// Get skill info for tutorial from sessionMode
const nextSkill = sessionMode.type === 'progression' ? sessionMode.nextSkill : null
@@ -1427,6 +1431,181 @@ export function StartPracticeModal({
)}
+ {/* Remediation CTA - Weak skills need strengthening */}
+ {showRemediationCta && !showTutorialGate && sessionMode.type === 'remediation' && (
+
+ {/* Info section */}
+
+
+ 💪
+
+
+
+ Time to build strength!
+
+
+ Focusing on {sessionMode.weakSkills.length} skill
+ {sessionMode.weakSkills.length > 1 ? 's' : ''} that need practice
+
+ {/* Weak skills badges */}
+
+ {sessionMode.weakSkills.slice(0, 4).map((skill) => (
+
+ {skill.displayName}{' '}
+
+ ({Math.round(skill.pKnown * 100)}%)
+
+
+ ))}
+ {sessionMode.weakSkills.length > 4 && (
+
+ +{sessionMode.weakSkills.length - 4} more
+
+ )}
+
+
+
+ {/* Integrated start button */}
+
+ {isStarting ? (
+ 'Starting...'
+ ) : (
+ <>
+ 💪
+ Start Focus Practice
+ →
+ >
+ )}
+
+
+ )}
+
{/* Error display */}
{displayError && (
)}
- {/* Start button - only shown when no tutorial is pending */}
- {!showTutorialGate && (
+ {/* Start button - only shown when no special CTA is active */}
+ {!showTutorialGate && !showRemediationCta && (