635 lines
27 KiB
TypeScript
635 lines
27 KiB
TypeScript
import React, { useRef, useState, useEffect } from "react";
|
||
import {
|
||
Check,
|
||
BookOpen,
|
||
Lightbulb,
|
||
Zap,
|
||
Target,
|
||
AlertTriangle,
|
||
} from "lucide-react";
|
||
import { PracticeFromDataset } from "../../../components/lessons/LessonShell";
|
||
import {
|
||
RHETORICAL_EASY,
|
||
RHETORICAL_MEDIUM,
|
||
} from "../../../data/rw/rhetorical-synthesis";
|
||
import EvidenceHunterWidget, {
|
||
type EvidenceExercise,
|
||
} from "../../../components/lessons/EvidenceHunterWidget";
|
||
import RevealCardGrid, {
|
||
type RevealCard,
|
||
} from "../../../components/lessons/RevealCardGrid";
|
||
import useScrollReveal from "../../../components/lessons/useScrollReveal";
|
||
|
||
interface LessonProps {
|
||
onFinish?: () => void;
|
||
}
|
||
|
||
/* ── Data for RevealCardGrid widgets ── */
|
||
const RHETORICAL_GOALS: RevealCard[] = [
|
||
{
|
||
label: "Introduce a Topic",
|
||
sublabel: '"introduce," "background," "context"',
|
||
content: "Present a new subject with context. No strong argument yet.",
|
||
},
|
||
{
|
||
label: "Make a Comparison",
|
||
sublabel: '"compare," "contrast," "differ," "between"',
|
||
content:
|
||
"Explicitly contrast OR compare two things. Must mention BOTH and their relationship.",
|
||
},
|
||
{
|
||
label: "Emphasize Similarity",
|
||
sublabel: '"similarity," "common," "alike," "both"',
|
||
content:
|
||
'Highlight what two things have IN COMMON. Both must appear; "both" or "similarly" usually required.',
|
||
},
|
||
{
|
||
label: "Illustrate with Example",
|
||
sublabel: '"example," "illustrate," "such as"',
|
||
content:
|
||
"Use a specific case to demonstrate a general principle. Must contain a concrete example.",
|
||
},
|
||
{
|
||
label: "State a Limitation",
|
||
sublabel: '"limitation," "drawback," "only," "cannot"',
|
||
content:
|
||
"Acknowledge a restriction, exception, or weakness of a claim or finding.",
|
||
},
|
||
{
|
||
label: "Present Cause-Effect",
|
||
sublabel: '"cause," "result," "lead to," "effect"',
|
||
content:
|
||
"Show a causal chain: X leads to Y, or X results in Y. The relationship must be directional.",
|
||
},
|
||
{
|
||
label: "Provide Supporting Evidence",
|
||
sublabel: '"support," "evidence," "data," "findings"',
|
||
content:
|
||
"Give data, statistics, or findings that back up a claim already made.",
|
||
},
|
||
{
|
||
label: "Acknowledge Opposing View",
|
||
sublabel: '"opposing," "counterargument," "critics"',
|
||
content:
|
||
'Present a counterargument before making your own point. "Critics argue…" structure.',
|
||
},
|
||
];
|
||
|
||
const WRONG_PATTERNS: RevealCard[] = [
|
||
{
|
||
label: "Wrong Goal",
|
||
sublabel: "Check this FIRST",
|
||
content:
|
||
"Achieves a different purpose from what the question asks. Most common wrong answer type — check before verifying facts.",
|
||
},
|
||
{
|
||
label: "Accurate But Irrelevant",
|
||
content:
|
||
"Uses real facts from the notes, but from the wrong notes — not the ones that serve the stated goal.",
|
||
},
|
||
{
|
||
label: "Distorted Fact",
|
||
content:
|
||
"Changes a number, reverses a direction, or misrepresents what a note says. Always verify facts word by word.",
|
||
},
|
||
{
|
||
label: "Incompatible Notes Combined",
|
||
content:
|
||
"Joins two notes that cannot logically work together, producing individually accurate but collectively incoherent sentences.",
|
||
},
|
||
{
|
||
label: "Wrong Scope",
|
||
content:
|
||
"Too broad (covers more than goal requires) or too narrow (picks a detail that misses the stated purpose).",
|
||
},
|
||
{
|
||
label: "Outside Information",
|
||
content:
|
||
"Claims something not found in any provided notes — even if generally true in the real world. If you can't point to the note, eliminate it.",
|
||
},
|
||
];
|
||
|
||
const EVIDENCE_EXERCISES: EvidenceExercise[] = [
|
||
{
|
||
question:
|
||
"A student wants to EMPHASIZE A SIMILARITY between two renewable energy sources. Which sentence best accomplishes this goal?",
|
||
passage: [
|
||
"Wind energy capacity in the US grew by 14% in 2022.",
|
||
"Solar energy capacity in the US also grew by 14% in 2022.",
|
||
"Wind turbines require more land per megawatt than solar panels.",
|
||
"Both wind and solar energy produce no direct carbon emissions during operation.",
|
||
"Government subsidies for renewable energy totaled $15 billion in 2022.",
|
||
],
|
||
evidenceIndex: 3,
|
||
explanation:
|
||
'Sentence 4 directly emphasizes a shared characteristic of both sources. The word "both" signals similarity, and "no direct carbon emissions" is the specific trait they share — this is exactly what the goal requires.',
|
||
},
|
||
{
|
||
question:
|
||
"A student wants to ACKNOWLEDGE AN OPPOSING VIEW about urban farming before presenting their own argument. Which sentence best accomplishes this goal?",
|
||
passage: [
|
||
"Urban farming initiatives have expanded in over 200 American cities.",
|
||
"Critics argue that urban farms cannot produce food at a scale sufficient to affect food insecurity.",
|
||
"Urban farms do provide fresh produce in food deserts, regardless of total volume.",
|
||
"Community gardens have been shown to strengthen neighborhood social ties.",
|
||
"The average urban farm yields 5 times more produce per square foot than conventional farms.",
|
||
],
|
||
evidenceIndex: 1,
|
||
explanation:
|
||
'Sentence 2 explicitly presents a counterargument with "Critics argue..." — the standard structure for acknowledging an opposing view. It sets up the concession the student needs before making their own point.',
|
||
},
|
||
];
|
||
|
||
const EBRWRhetoricalSynthesisLesson: React.FC<LessonProps> = ({ onFinish }) => {
|
||
const [activeSection, setActiveSection] = useState(0);
|
||
const sectionsRef = useRef<(HTMLElement | null)[]>([]);
|
||
|
||
useEffect(() => {
|
||
const observers: IntersectionObserver[] = [];
|
||
sectionsRef.current.forEach((el, idx) => {
|
||
if (!el) return;
|
||
const obs = new IntersectionObserver(
|
||
([entry]) => {
|
||
if (entry.isIntersecting) setActiveSection(idx);
|
||
},
|
||
{ threshold: 0.3 },
|
||
);
|
||
obs.observe(el);
|
||
observers.push(obs);
|
||
});
|
||
return () => observers.forEach((o) => o.disconnect());
|
||
}, []);
|
||
|
||
useScrollReveal();
|
||
|
||
const scrollToSection = (index: number) => {
|
||
setActiveSection(index);
|
||
sectionsRef.current[index]?.scrollIntoView({ behavior: "smooth" });
|
||
};
|
||
|
||
const SectionMarker = ({
|
||
index,
|
||
title,
|
||
icon: Icon,
|
||
}: {
|
||
index: number;
|
||
title: string;
|
||
icon: React.ElementType;
|
||
}) => {
|
||
const isActive = activeSection === index;
|
||
const isPast = activeSection > index;
|
||
return (
|
||
<button
|
||
onClick={() => scrollToSection(index)}
|
||
className={`flex items-center gap-3 p-3 w-full rounded-lg text-left transition-all ${isActive ? "bg-rose-50" : "hover:bg-slate-50"}`}
|
||
>
|
||
<div
|
||
className={`w-8 h-8 rounded-full flex items-center justify-center shrink-0
|
||
${isActive ? "bg-rose-600 text-white" : isPast ? "bg-rose-400 text-white" : "bg-slate-200 text-slate-500"}`}
|
||
>
|
||
{isPast ? (
|
||
<Check className="w-4 h-4" />
|
||
) : (
|
||
// @ts-ignore
|
||
<Icon className="w-4 h-4" />
|
||
)}
|
||
</div>
|
||
<p
|
||
className={`text-sm font-bold ${isActive ? "text-rose-900" : "text-slate-600"}`}
|
||
>
|
||
{title}
|
||
</p>
|
||
</button>
|
||
);
|
||
};
|
||
|
||
return (
|
||
<div className="flex flex-col lg:flex-row min-h-screen">
|
||
<aside className="w-full lg:w-64 lg:fixed lg:top-14 lg:bottom-0 lg:overflow-y-auto p-4 border-r border-slate-200 bg-slate-50 z-0 hidden lg:block">
|
||
<nav className="space-y-2 pt-6">
|
||
<SectionMarker index={0} title="The Core Concept" icon={BookOpen} />
|
||
<SectionMarker
|
||
index={1}
|
||
title="Goals & Strategy"
|
||
icon={AlertTriangle}
|
||
/>
|
||
<SectionMarker index={2} title="Worked Example" icon={Target} />
|
||
<SectionMarker index={3} title="Goal Matcher" icon={Lightbulb} />
|
||
<SectionMarker index={4} title="Practice Questions" icon={Zap} />
|
||
</nav>
|
||
</aside>
|
||
|
||
<div className="flex-1 lg:ml-64 md:p-12 max-w-full mx-auto">
|
||
{/* ── Section 0: The Core Concept ── */}
|
||
<section
|
||
ref={(el) => {
|
||
sectionsRef.current[0] = el;
|
||
}}
|
||
className="min-h-screen flex flex-col justify-center mb-24 pt-20 lg:pt-0"
|
||
>
|
||
<div className="inline-flex items-center gap-2 bg-rose-100 text-rose-700 px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wider mb-4 w-fit">
|
||
Expression of Ideas — Domain 4
|
||
</div>
|
||
<h2 className="text-4xl font-extrabold text-slate-900 mb-2">
|
||
Rhetorical Synthesis
|
||
</h2>
|
||
<p className="text-lg text-slate-500 mb-8">
|
||
Every answer is judged on two things: does it achieve the stated
|
||
goal, and does every fact come from the notes? Failing either test
|
||
means wrong — no exceptions.
|
||
</p>
|
||
|
||
{/* §9.1 — What Makes an Answer Correct */}
|
||
<div className="scroll-reveal stagger-1 rounded-2xl p-6 mb-8 bg-rose-50 border border-rose-200 space-y-4">
|
||
<h3 className="text-lg font-bold text-rose-900">
|
||
The Two-Criteria Rule
|
||
</h3>
|
||
<p className="text-sm text-slate-700">
|
||
Unlike most SAT questions, Rhetorical Synthesis does not ask you
|
||
to find the "best" answer in a general sense. It asks you to find
|
||
the answer that satisfies exactly two requirements simultaneously.
|
||
</p>
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||
<div className="card-tilt bg-white border border-rose-200 rounded-xl p-4">
|
||
<p className="font-bold text-rose-900 text-sm mb-2">
|
||
Criterion 1 — GOAL
|
||
</p>
|
||
<p className="text-xs text-slate-700">
|
||
The answer must accomplish exactly the rhetorical purpose
|
||
stated in the question — no more, no less. An answer that does
|
||
something different from the stated goal is automatically
|
||
wrong, even if every fact is accurate.
|
||
</p>
|
||
</div>
|
||
<div className="card-tilt bg-white border border-rose-200 rounded-xl p-4">
|
||
<p className="font-bold text-rose-900 text-sm mb-2">
|
||
Criterion 2 — ACCURACY
|
||
</p>
|
||
<p className="text-xs text-slate-700">
|
||
Every fact in the answer must come directly from the provided
|
||
notes — nothing added, nothing distorted. Even one wrong
|
||
number or reversed relationship eliminates an answer, even if
|
||
the goal is otherwise met.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div className="bg-rose-100 border border-rose-300 rounded-xl p-4">
|
||
<p className="text-xs text-slate-700">
|
||
<span className="font-bold text-rose-900">
|
||
The key insight:
|
||
</span>{" "}
|
||
These two criteria work independently. You can fail on goal
|
||
while passing accuracy. You can fail on accuracy while passing
|
||
goal. Only the answer that passes both is correct.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
{/* §9.2 — Question Anatomy */}
|
||
<div className="scroll-reveal stagger-2 rounded-2xl p-6 mb-8 bg-white border border-slate-200 space-y-4">
|
||
<h3 className="text-lg font-bold text-slate-900">
|
||
Question Anatomy
|
||
</h3>
|
||
<p className="text-sm text-slate-600">
|
||
Every Rhetorical Synthesis question has the same four-part
|
||
structure. Each part plays a specific role in determining the
|
||
correct answer.
|
||
</p>
|
||
<div className="overflow-x-auto">
|
||
<table className="w-full text-sm border-collapse rounded-xl overflow-hidden">
|
||
<thead>
|
||
<tr className="bg-rose-600 text-white">
|
||
<th className="px-3 py-2 text-left text-xs">Component</th>
|
||
<th className="px-3 py-2 text-left text-xs">
|
||
What It Contains
|
||
</th>
|
||
<th className="px-3 py-2 text-left text-xs">
|
||
What You Need From It
|
||
</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{[
|
||
[
|
||
"Context Header",
|
||
'"While researching a topic, a student took the following notes:"',
|
||
"Sets the topic domain. Establishes what field the notes come from.",
|
||
],
|
||
[
|
||
"Notes (2–4 bullets)",
|
||
"Factual information: data, definitions, examples, findings",
|
||
"The ONLY source of accurate facts. Every claim in the correct answer must trace back here.",
|
||
],
|
||
[
|
||
"Stated Goal",
|
||
'"The student wants to [X]. Which choice best accomplishes this goal?"',
|
||
"Read this FIRST — before notes, before answer choices. It tells you exactly what the correct answer must do.",
|
||
],
|
||
[
|
||
"Four Answer Choices",
|
||
"Sentences combining facts from the notes",
|
||
"Wrong answers fail the goal, distort facts, add outside information, or combine incompatible notes.",
|
||
],
|
||
].map(([comp, contains, need], i) => (
|
||
<tr
|
||
key={comp}
|
||
className={i % 2 === 0 ? "bg-white" : "bg-rose-50"}
|
||
>
|
||
<td className="px-3 py-2 font-bold text-rose-800 text-xs whitespace-nowrap">
|
||
{comp}
|
||
</td>
|
||
<td className="px-3 py-2 text-slate-600 text-xs italic">
|
||
{contains}
|
||
</td>
|
||
<td className="px-3 py-2 text-slate-700 text-xs">
|
||
{need}
|
||
</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── Section 1: Goals & Strategy ── */}
|
||
<section
|
||
ref={(el) => {
|
||
sectionsRef.current[1] = el;
|
||
}}
|
||
className="min-h-screen flex flex-col justify-center mb-24"
|
||
>
|
||
<h2 className="text-4xl font-extrabold text-slate-900 mb-2">
|
||
Goals & Strategy
|
||
</h2>
|
||
<p className="text-lg text-slate-500 mb-8">
|
||
The eight rhetorical goals, the 5-step method, and the six ways
|
||
wrong answers fail.
|
||
</p>
|
||
|
||
{/* §9.3 — The 8 Goals */}
|
||
<div className="scroll-reveal stagger-1 rounded-2xl p-6 mb-8 bg-rose-50 border border-rose-200 space-y-4">
|
||
<h3 className="text-lg font-bold text-rose-900">
|
||
The 8 Rhetorical Goals — tap to reveal what each answer must do:
|
||
</h3>
|
||
<p className="text-sm text-slate-700">
|
||
The stated goal will always be one of these eight types. Knowing
|
||
them lets you immediately identify what structural features the
|
||
correct answer must contain.
|
||
</p>
|
||
<RevealCardGrid
|
||
cards={RHETORICAL_GOALS}
|
||
columns={4}
|
||
accentColor="rose"
|
||
/>
|
||
</div>
|
||
|
||
{/* §9.5 — The 5-Step Strategy */}
|
||
<div className="scroll-reveal stagger-2 rounded-2xl p-6 mb-8 bg-white border border-slate-200 space-y-4">
|
||
<h3 className="text-lg font-bold text-slate-900">
|
||
The 5-Step Strategy
|
||
</h3>
|
||
<div className="space-y-2">
|
||
{[
|
||
{
|
||
step: 1,
|
||
action: "Read the GOAL first",
|
||
tip: 'Before reading notes or answer choices, read the stated goal. Write the goal type in 3–4 words on scratch paper: e.g., "comparison — key difference." The goal determines everything else.',
|
||
},
|
||
{
|
||
step: 2,
|
||
action: "Read the notes with the goal in mind",
|
||
tip: "Identify which 1–2 notes are relevant to your goal. Cross out off-topic notes — they exist only as material for wrong answers.",
|
||
},
|
||
{
|
||
step: 3,
|
||
action: "Predict what the correct answer must contain",
|
||
tip: 'Before looking at choices, write a quick sketch: "must mention both species + a difference." Even a rough prediction blocks you from being swayed by sophisticated wrong answers.',
|
||
},
|
||
{
|
||
step: 4,
|
||
action: "Eliminate wrong goals first",
|
||
tip: "Any answer that achieves a DIFFERENT goal from the one stated is wrong — eliminate it before checking any facts. This alone usually removes 2–3 choices immediately.",
|
||
},
|
||
{
|
||
step: 5,
|
||
action: "Verify accuracy in the remaining answers",
|
||
tip: "Read each remaining answer word by word against the notes. One wrong number, reversed relationship, or unsupported claim eliminates the answer.",
|
||
},
|
||
].map((s) => (
|
||
<div
|
||
key={s.step}
|
||
className="flex gap-3 bg-rose-50 border border-rose-100 rounded-xl px-4 py-3"
|
||
>
|
||
<span className="w-6 h-6 rounded-full bg-rose-600 text-white flex items-center justify-center text-xs font-bold shrink-0">
|
||
{s.step}
|
||
</span>
|
||
<div>
|
||
<p className="font-bold text-slate-800 text-sm">
|
||
{s.action}
|
||
</p>
|
||
<p className="text-xs text-slate-500 mt-0.5">{s.tip}</p>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* §9.4 — Wrong Answer Patterns */}
|
||
<div className="scroll-reveal stagger-3 rounded-2xl p-6 mb-8 bg-white border border-slate-200 space-y-4">
|
||
<h3 className="text-lg font-bold text-slate-900">
|
||
Wrong Answer Patterns — tap to reveal each trap:
|
||
</h3>
|
||
<p className="text-sm text-slate-600">
|
||
Every wrong answer fails in one of these six predictable ways.
|
||
Naming the failure pattern immediately tells you why to eliminate
|
||
it.
|
||
</p>
|
||
<RevealCardGrid
|
||
cards={WRONG_PATTERNS}
|
||
columns={3}
|
||
accentColor="rose"
|
||
/>
|
||
</div>
|
||
|
||
<div className="scroll-reveal-scale golden-rule-glow bg-rose-900 text-white rounded-2xl p-5 mb-8">
|
||
<p className="font-bold mb-1">Golden Rule</p>
|
||
<p className="text-sm text-rose-100">
|
||
Read the GOAL before reading anything else. An accurate answer
|
||
that achieves the wrong goal is wrong. An answer that achieves the
|
||
right goal with one distorted fact is also wrong. Both criteria
|
||
must be met.
|
||
</p>
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── Section 2: Worked Example ── */}
|
||
<section
|
||
ref={(el) => {
|
||
sectionsRef.current[2] = el;
|
||
}}
|
||
className="min-h-screen flex flex-col justify-center mb-24"
|
||
>
|
||
<h2 className="text-4xl font-extrabold text-slate-900 mb-2">
|
||
Worked Example
|
||
</h2>
|
||
<p className="text-lg text-slate-500 mb-8">
|
||
A complete question with full analysis of why each answer succeeds
|
||
or fails against the two criteria.
|
||
</p>
|
||
|
||
<div className="scroll-reveal stagger-1 rounded-2xl p-6 mb-8 bg-slate-50 border border-slate-200 space-y-4">
|
||
<p className="text-xs font-bold text-slate-500 uppercase tracking-wider">
|
||
While researching a topic, a student took the following notes:
|
||
</p>
|
||
<ul className="space-y-2">
|
||
{[
|
||
"Komodo dragons (Varanus komodoensis) are the world's largest living lizard species, reaching up to 3 meters in length.",
|
||
"Komodo dragons are found only on five islands in Indonesia: Komodo, Rinca, Flores, Gili Motang, and Padar.",
|
||
"Komodo dragons have a venomous bite that prevents blood clotting in prey, causing prey to weaken from blood loss.",
|
||
"The IUCN lists Komodo dragons as Endangered, with an estimated 1,383–2,531 individuals remaining in the wild.",
|
||
"Nile monitor lizards, native to Africa, are also large lizards but are not venomous and grow to only 2 meters.",
|
||
].map((note, i) => (
|
||
<li key={i} className="flex gap-2 text-sm text-slate-700">
|
||
<span className="text-rose-500 font-bold shrink-0">
|
||
{i + 1}.
|
||
</span>
|
||
{note}
|
||
</li>
|
||
))}
|
||
</ul>
|
||
<div className="bg-rose-100 border border-rose-300 rounded-xl p-3">
|
||
<p className="text-sm font-bold text-rose-900">
|
||
The student wants to COMPARE the Komodo dragon with another
|
||
large lizard species by highlighting a key difference. Which
|
||
choice best accomplishes this goal?
|
||
</p>
|
||
</div>
|
||
<div className="space-y-3">
|
||
{[
|
||
{
|
||
letter: "A",
|
||
correct: false,
|
||
text: "Komodo dragons, the world's largest living lizards at 3 meters, are endangered, with fewer than 2,531 individuals remaining.",
|
||
analysis:
|
||
"✗ Wrong goal. Only one species is mentioned — no comparison is made. The goal explicitly requires comparing Komodo dragons WITH another species.",
|
||
},
|
||
{
|
||
letter: "B",
|
||
correct: true,
|
||
text: "Unlike Nile monitor lizards, which are not venomous and reach only 2 meters, Komodo dragons possess a venomous bite and can grow up to 3 meters.",
|
||
analysis:
|
||
"✓ Correct. Both species appear. A key difference is highlighted (venomous vs. not venomous, 3m vs. 2m). All facts trace directly to Notes 1 and 5. Goal ✓, Accuracy ✓.",
|
||
},
|
||
{
|
||
letter: "C",
|
||
correct: false,
|
||
text: "Komodo dragons are venomous lizards found on five Indonesian islands, and their numbers have declined to fewer than 2,531 in the wild.",
|
||
analysis:
|
||
"✗ Wrong goal. Only one species mentioned — no comparison. The facts are accurate, but the goal is not achieved.",
|
||
},
|
||
{
|
||
letter: "D",
|
||
correct: false,
|
||
text: "Both Komodo dragons and Nile monitor lizards are large reptiles, with Komodo dragons endangered and Nile monitors thriving across Africa.",
|
||
analysis:
|
||
'✗ Two failures. First, the goal asks for a KEY DIFFERENCE, not similarity — "both are large reptiles" emphasizes similarity. Second, "Nile monitors thriving" appears in no note — outside information.',
|
||
},
|
||
].map((opt) => (
|
||
<div
|
||
key={opt.letter}
|
||
className={`rounded-xl p-4 border ${opt.correct ? "bg-green-50 border-green-300" : "bg-red-50 border-red-200"}`}
|
||
>
|
||
<div className="flex gap-3 items-start">
|
||
<span
|
||
className={`w-7 h-7 rounded-full flex items-center justify-center text-sm font-bold shrink-0 ${opt.correct ? "bg-green-600 text-white" : "bg-red-500 text-white"}`}
|
||
>
|
||
{opt.letter}
|
||
</span>
|
||
<div>
|
||
<p className="text-sm text-slate-800 italic mb-2">
|
||
"{opt.text}"
|
||
</p>
|
||
<p className="text-xs text-slate-600">{opt.analysis}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
<div className="bg-amber-50 border border-amber-200 rounded-xl p-4">
|
||
<p className="font-bold text-amber-900 text-sm mb-1">Takeaways</p>
|
||
<ul className="space-y-1 text-xs text-slate-700">
|
||
<li>
|
||
• "Compare by highlighting a key difference" = two species
|
||
must appear AND a difference must be stated.
|
||
</li>
|
||
<li>
|
||
• A and C both used accurate facts — but both failed the goal
|
||
test. Eliminated without checking accuracy.
|
||
</li>
|
||
<li>
|
||
• D failed on both criteria: wrong goal type (similarity
|
||
instead of difference) AND outside information.
|
||
</li>
|
||
<li>
|
||
• B is the only answer that passes both criteria: goal ✓ (two
|
||
species, key difference stated), accuracy ✓ (all facts from
|
||
Notes 1 and 5).
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── Section 3: Goal Matcher Widget ── */}
|
||
<section
|
||
ref={(el) => {
|
||
sectionsRef.current[3] = el;
|
||
}}
|
||
className="min-h-screen flex flex-col justify-center mb-24"
|
||
>
|
||
<h2 className="text-4xl font-extrabold text-slate-900 mb-2">
|
||
Goal Matcher
|
||
</h2>
|
||
<p className="text-lg text-slate-500 mb-8">
|
||
Find the sentence that best achieves the stated rhetorical goal
|
||
using only facts from the notes.
|
||
</p>
|
||
<EvidenceHunterWidget
|
||
exercises={EVIDENCE_EXERCISES}
|
||
accentColor="rose"
|
||
/>
|
||
</section>
|
||
|
||
{/* ── Section 4: Practice ── */}
|
||
<section
|
||
ref={(el) => {
|
||
sectionsRef.current[4] = el;
|
||
}}
|
||
className="min-h-screen flex flex-col justify-center mb-24"
|
||
>
|
||
<h2 className="text-4xl font-extrabold text-slate-900 mb-6">
|
||
Practice Questions
|
||
</h2>
|
||
{RHETORICAL_EASY.slice(0, 2).map((q) => (
|
||
<PracticeFromDataset key={q.id} question={q} color="rose" />
|
||
))}
|
||
{RHETORICAL_MEDIUM.slice(0, 1).map((q) => (
|
||
<PracticeFromDataset key={q.id} question={q} color="rose" />
|
||
))}
|
||
<div className="mt-8 text-center">
|
||
<button
|
||
onClick={onFinish}
|
||
className="px-6 py-3 bg-rose-900 text-white font-bold rounded-full hover:bg-rose-700 transition-colors"
|
||
>
|
||
Finish Lesson ✓
|
||
</button>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default EBRWRhetoricalSynthesisLesson;
|