@zomako/elearning-components 2.0.8 → 2.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,11 +4,14 @@ A React component for narrative branching scenarios (choose-your-own-path style)
4
4
 
5
5
  ## Features
6
6
 
7
+ - **Ideal path vs. dead-end structure**: Always provide at least 2 choices per scenario. One leads to the ideal/correct path (more branching scenarios); others lead to dead-ends where the learner can "Try again."
7
8
  - **Node-based flow**: Start from a given node and move to the next via choices or outcomes.
9
+ - **Dead-end nodes**: Mark endings with `isDeadEnd: true` to show feedback and a "Try again" button that returns the learner to the previous node.
10
+ - **Choice metadata**: Use `isCorrectPath: true` on choices that lead to the ideal path; `isCorrectPath: false` for dead-end paths (optional styling).
8
11
  - **Choices and outcomes**: Choices can go directly to the next node or expose multiple outcomes (each with optional `scoreModifier` and `variableUpdates`).
9
12
  - **Conditional choices**: Choices can use a `condition(variables)` so only some options are shown.
10
13
  - **Path, score, and variables**: Tracks visited node IDs, a numeric score, and a variables object for state.
11
- - **Endings**: When the current node has `type: 'ending'`, the component calls `onComplete` with the final result.
14
+ - **Endings**: When the current node has `type: 'ending'` and is not a dead-end, the component calls `onComplete` with the final result.
12
15
  - **Animations**: Fade and slide transitions between nodes using CSS only (no JS animation libraries).
13
16
  - **Accessibility**: Keyboard operable (Enter/Space on choices and outcomes), ARIA region/live/status and clear labels for content and actions.
14
17
 
@@ -33,12 +36,13 @@ The component accepts a single props object of type `BranchingScenarioProps`:
33
36
  | Field | Type | Description |
34
37
  |-----------|----------|-------------|
35
38
  | `id` | `string` | Unique node ID. |
36
- | `type` | `'scenario' \| 'ending'` | `'ending'` triggers `onComplete` when reached. |
39
+ | `type` | `'scenario' \| 'ending'` | `'ending'` triggers `onComplete` when reached (unless `isDeadEnd`). |
37
40
  | `title` | `string` | Node heading. |
38
41
  | `content` | `string` | Narrative text. |
39
42
  | `image` | `string?` | Optional image URL. |
40
- | `choices` | `Choice[]` | Choices for this node (can be empty for endings). |
41
- | `feedback`| `string?` | Optional feedback text. |
43
+ | `choices` | `Choice[]` | Choices for this node. **Recommended: at least 2** (one ideal path, one or more dead-ends). |
44
+ | `feedback`| `string?` | Optional feedback text. For dead-ends, shown above the "Try again" button. |
45
+ | `isDeadEnd` | `boolean`? | When `true` and `type` is `'ending'`, this is a wrong-path dead-end. Shows "Try again" instead of calling `onComplete`. |
42
46
 
43
47
  **Choice**
44
48
 
@@ -49,6 +53,7 @@ The component accepts a single props object of type `BranchingScenarioProps`:
49
53
  | `nextNodeId`| `string` | Node to go to if there are no outcomes. |
50
54
  | `condition` | `(variables) => boolean`? | If provided, choice is only shown when this returns `true`. |
51
55
  | `outcomes` | `Outcome[]`? | If present, selecting this choice shows outcome options instead of going directly to `nextNodeId`. |
56
+ | `isCorrectPath` | `boolean`? | When `true`, this choice leads to the ideal path. When `false`, leads to a dead-end. Optional; used for subtle styling. |
52
57
 
53
58
  **Outcome**
54
59
 
@@ -170,6 +175,60 @@ In this example:
170
175
  3. “Go back to the crossroads” goes to `start` with no outcomes.
171
176
  4. Reaching any node with `type: 'ending'` triggers `onComplete` with the current `score`, `path`, and `variables`.
172
177
 
178
+ ### Ideal path + dead-end example
179
+
180
+ Structure each scenario with **at least 2 choices**: one ideal path (`isCorrectPath: true`) and one or more dead-ends (`isCorrectPath: false`). Dead-end nodes use `isDeadEnd: true` and show a "Try again" button:
181
+
182
+ ```tsx
183
+ const nodes = {
184
+ start: {
185
+ id: 'start',
186
+ type: 'scenario',
187
+ title: 'Traffic Sign Decision',
188
+ content: 'You see a yellow traffic light. What do you do?',
189
+ choices: [
190
+ { id: 'slow', text: 'Slow down and prepare to stop', nextNodeId: 'correct-continue', isCorrectPath: true },
191
+ { id: 'speed', text: 'Speed up to beat the light', nextNodeId: 'dead-end-speeding', isCorrectPath: false },
192
+ ],
193
+ },
194
+ 'correct-continue': {
195
+ id: 'correct-continue',
196
+ type: 'scenario',
197
+ title: 'Good choice',
198
+ content: 'You slowed down safely. The light turns red. You stop.',
199
+ choices: [
200
+ { id: 'wait', text: 'Wait for green', nextNodeId: 'success-ending', isCorrectPath: true },
201
+ { id: 'run', text: 'Run the red light', nextNodeId: 'dead-end-red', isCorrectPath: false },
202
+ ],
203
+ },
204
+ 'dead-end-speeding': {
205
+ id: 'dead-end-speeding',
206
+ type: 'ending',
207
+ isDeadEnd: true,
208
+ title: 'Wrong choice',
209
+ content: 'Speeding through a yellow light is dangerous.',
210
+ feedback: "That wasn't the right approach. Try again.",
211
+ choices: [],
212
+ },
213
+ 'dead-end-red': {
214
+ id: 'dead-end-red',
215
+ type: 'ending',
216
+ isDeadEnd: true,
217
+ title: 'Wrong choice',
218
+ content: 'Running a red light causes an accident.',
219
+ feedback: "Never run a red light. Go back and wait for green.",
220
+ choices: [],
221
+ },
222
+ 'success-ending': {
223
+ id: 'success-ending',
224
+ type: 'ending',
225
+ title: 'Scenario complete',
226
+ content: 'You followed the rules and stayed safe.',
227
+ choices: [],
228
+ },
229
+ };
230
+ ```
231
+
173
232
  ## Styling
174
233
 
175
234
  Styles are in `style.module.css`. CSS custom properties (e.g. `--branch-accent`, `--branch-bg`) control colors and spacing. Override them in your own CSS or by wrapping the component in a container with different variables. The narrative block and choice/outcome buttons are clearly separated for readability.
@@ -15,6 +15,8 @@ export interface Choice {
15
15
  nextNodeId: string;
16
16
  condition?: (variables: Record<string, unknown>) => boolean;
17
17
  outcomes?: Outcome[];
18
+ /** When true, this choice leads to the ideal/correct path (more scenarios). When false, leads to a dead-end. */
19
+ isCorrectPath?: boolean;
18
20
  }
19
21
 
20
22
  export interface ScenarioNode {
@@ -25,6 +27,8 @@ export interface ScenarioNode {
25
27
  image?: string;
26
28
  choices: Choice[];
27
29
  feedback?: string;
30
+ /** When true and type is 'ending', this is a wrong-path dead-end. User can "Try again" to go back. */
31
+ isDeadEnd?: boolean;
28
32
  }
29
33
 
30
34
  export interface BranchingScenarioProps {
@@ -41,6 +45,12 @@ interface PendingOutcome {
41
45
  choice: Choice;
42
46
  }
43
47
 
48
+ interface PathState {
49
+ nodeId: string;
50
+ score: number;
51
+ variables: Record<string, unknown>;
52
+ }
53
+
44
54
  const BranchingScenario: React.FC<BranchingScenarioProps> = ({
45
55
  nodes,
46
56
  startNodeId,
@@ -48,6 +58,7 @@ const BranchingScenario: React.FC<BranchingScenarioProps> = ({
48
58
  }) => {
49
59
  const [currentNodeId, setCurrentNodeId] = useState<string>(startNodeId);
50
60
  const [path, setPath] = useState<string[]>([startNodeId]);
61
+ const [pathHistory, setPathHistory] = useState<PathState[]>([]);
51
62
  const [score, setScore] = useState(0);
52
63
  const [variables, setVariables] = useState<Record<string, unknown>>({});
53
64
  const [pendingOutcome, setPendingOutcome] = useState<PendingOutcome | null>(null);
@@ -56,6 +67,8 @@ const BranchingScenario: React.FC<BranchingScenarioProps> = ({
56
67
 
57
68
  const currentNode = nodes[currentNodeId];
58
69
  const isEnding = currentNode?.type === 'ending';
70
+ const isDeadEnd = isEnding && Boolean(currentNode?.isDeadEnd);
71
+ const canTryAgain = isDeadEnd && pathHistory.length > 0;
59
72
 
60
73
  const visibleChoices = useMemo(() => {
61
74
  if (!currentNode?.choices) return [];
@@ -64,6 +77,25 @@ const BranchingScenario: React.FC<BranchingScenarioProps> = ({
64
77
  );
65
78
  }, [currentNode, variables]);
66
79
 
80
+ const hasEnoughChoices = visibleChoices.length >= 2;
81
+
82
+ const navigateTo = useCallback(
83
+ (nextNodeId: string, scoreDelta: number, variableUpdates?: Record<string, unknown>) => {
84
+ setPathHistory((h) => [
85
+ ...h,
86
+ { nodeId: currentNodeId, score, variables },
87
+ ]);
88
+ setPath((p) => [...p, nextNodeId]);
89
+ setCurrentNodeId(nextNodeId);
90
+ setScore((s) => s + scoreDelta);
91
+ if (variableUpdates && Object.keys(variableUpdates).length > 0) {
92
+ setVariables((v) => ({ ...v, ...variableUpdates }));
93
+ }
94
+ setPendingOutcome(null);
95
+ },
96
+ [currentNodeId, score, variables]
97
+ );
98
+
67
99
  const handleChoiceSelect = useCallback(
68
100
  (choice: Choice) => {
69
101
  if (choice.outcomes && choice.outcomes.length > 0) {
@@ -72,38 +104,48 @@ const BranchingScenario: React.FC<BranchingScenarioProps> = ({
72
104
  }
73
105
  setIsExiting(true);
74
106
  setTimeout(() => {
75
- setPath((p) => [...p, choice.nextNodeId]);
76
- setCurrentNodeId(choice.nextNodeId);
77
- setPendingOutcome(null);
107
+ navigateTo(choice.nextNodeId, 0);
78
108
  setIsExiting(false);
79
109
  }, 280);
80
110
  },
81
- []
111
+ [navigateTo]
82
112
  );
83
113
 
84
114
  const handleOutcomeSelect = useCallback(
85
115
  (outcome: Outcome) => {
86
116
  setIsExiting(true);
87
117
  setTimeout(() => {
88
- setScore((s) => s + (outcome.scoreModifier ?? 0));
89
- if (outcome.variableUpdates && Object.keys(outcome.variableUpdates).length > 0) {
90
- setVariables((v) => ({ ...v, ...outcome.variableUpdates }));
91
- }
92
- setPath((p) => [...p, outcome.nextNodeId]);
93
- setCurrentNodeId(outcome.nextNodeId);
94
- setPendingOutcome(null);
118
+ navigateTo(
119
+ outcome.nextNodeId,
120
+ outcome.scoreModifier ?? 0,
121
+ outcome.variableUpdates
122
+ );
95
123
  setIsExiting(false);
96
124
  }, 280);
97
125
  },
98
- []
126
+ [navigateTo]
99
127
  );
100
128
 
129
+ const handleTryAgain = useCallback(() => {
130
+ if (pathHistory.length === 0) return;
131
+ setIsExiting(true);
132
+ setTimeout(() => {
133
+ const prev = pathHistory[pathHistory.length - 1];
134
+ setPathHistory((h) => h.slice(0, -1));
135
+ setPath((p) => p.slice(0, -1));
136
+ setCurrentNodeId(prev.nodeId);
137
+ setScore(prev.score);
138
+ setVariables(prev.variables);
139
+ setIsExiting(false);
140
+ }, 280);
141
+ }, [pathHistory]);
142
+
101
143
  useEffect(() => {
102
- if (isEnding && currentNode && !completedRef.current) {
144
+ if (isEnding && currentNode && !isDeadEnd && !completedRef.current) {
103
145
  completedRef.current = true;
104
146
  onComplete({ score, path, variables });
105
147
  }
106
- }, [isEnding, currentNode, score, path, variables, onComplete]);
148
+ }, [isEnding, isDeadEnd, currentNode, score, path, variables, onComplete]);
107
149
 
108
150
  const handleKeyDown = useCallback(
109
151
  (e: React.KeyboardEvent, choiceOrOutcome: { nextNodeId: string } | Outcome, handler: () => void) => {
@@ -173,6 +215,11 @@ const BranchingScenario: React.FC<BranchingScenarioProps> = ({
173
215
  className={styles.choicesNav}
174
216
  aria-label="Choices"
175
217
  >
218
+ {!hasEnoughChoices && (
219
+ <p className={styles.configWarning} role="status">
220
+ Recommended: provide at least 2 branching options (one ideal path, one or more dead-ends).
221
+ </p>
222
+ )}
176
223
  <p className={styles.choicesLabel} id="choices-label">
177
224
  What do you do?
178
225
  </p>
@@ -181,12 +228,13 @@ const BranchingScenario: React.FC<BranchingScenarioProps> = ({
181
228
  <li key={choice.id} className={styles.choiceItem}>
182
229
  <button
183
230
  type="button"
184
- className={styles.choiceButton}
231
+ className={`${styles.choiceButton} ${choice.isCorrectPath === true ? styles.choiceCorrectPath : ''} ${choice.isCorrectPath === false ? styles.choiceDeadEnd : ''}`}
185
232
  onClick={() => handleChoiceSelect(choice)}
186
233
  onKeyDown={(e) => handleKeyDown(e, choice, () => handleChoiceSelect(choice))}
187
234
  aria-describedby="scenario-content"
188
235
  aria-label={choice.text}
189
236
  data-choice-index={index + 1}
237
+ data-correct-path={choice.isCorrectPath === true ? 'true' : undefined}
190
238
  >
191
239
  {choice.text}
192
240
  </button>
@@ -224,7 +272,26 @@ const BranchingScenario: React.FC<BranchingScenarioProps> = ({
224
272
  </nav>
225
273
  )}
226
274
 
227
- {isEnding && (
275
+ {isDeadEnd && (
276
+ <div className={styles.deadEndBlock}>
277
+ <p className={styles.deadEndMessage} role="status" aria-live="polite">
278
+ {currentNode.feedback || "This wasn't the right path. Review the options and try again."}
279
+ </p>
280
+ {canTryAgain && (
281
+ <button
282
+ type="button"
283
+ className={styles.tryAgainButton}
284
+ onClick={handleTryAgain}
285
+ onKeyDown={(e) => handleKeyDown(e, { nextNodeId: '' }, handleTryAgain)}
286
+ aria-label="Go back and try a different choice"
287
+ >
288
+ Try again
289
+ </button>
290
+ )}
291
+ </div>
292
+ )}
293
+
294
+ {isEnding && !isDeadEnd && (
228
295
  <p className={styles.endingMessage} role="status" aria-live="polite">
229
296
  You have reached the end of this scenario.
230
297
  </p>
@@ -86,6 +86,17 @@
86
86
  border-radius: 0 var(--branch-radius) var(--branch-radius) 0;
87
87
  }
88
88
 
89
+ /* ---- Config warning (min 2 choices) ---- */
90
+ .configWarning {
91
+ margin: 0 0 0.75rem;
92
+ padding: 0.625rem 0.875rem;
93
+ font-size: 0.8125rem;
94
+ color: #92400e;
95
+ background: #fffbeb;
96
+ border: 1px solid #fcd34d;
97
+ border-radius: var(--branch-radius);
98
+ }
99
+
89
100
  /* ---- Choices / Outcomes nav ---- */
90
101
  .choicesNav,
91
102
  .outcomesNav {
@@ -165,6 +176,55 @@
165
176
  border-style: solid;
166
177
  }
167
178
 
179
+ /* Optional: subtle indicator for ideal path (use isCorrectPath: true) */
180
+ .choiceCorrectPath {
181
+ border-left: 4px solid var(--branch-accent);
182
+ }
183
+
184
+ /* Optional: subtle indicator for dead-end path (use isCorrectPath: false) */
185
+ .choiceDeadEnd {
186
+ /* Slightly muted - author can customize */
187
+ }
188
+
189
+ /* ---- Dead-end block (wrong path, try again) ---- */
190
+ .deadEndBlock {
191
+ margin-top: 1.5rem;
192
+ padding: 1.25rem 1.5rem;
193
+ background: #fef2f2;
194
+ border: 2px solid #fecaca;
195
+ border-radius: var(--branch-radius);
196
+ }
197
+
198
+ .deadEndMessage {
199
+ margin: 0 0 1rem;
200
+ font-size: 1rem;
201
+ line-height: 1.5;
202
+ color: #991b1b;
203
+ }
204
+
205
+ .tryAgainButton {
206
+ display: inline-flex;
207
+ align-items: center;
208
+ padding: 0.625rem 1.25rem;
209
+ font-size: 1rem;
210
+ font-weight: 600;
211
+ color: #fff;
212
+ background: var(--branch-accent);
213
+ border: none;
214
+ border-radius: var(--branch-radius);
215
+ cursor: pointer;
216
+ transition: background-color 0.2s ease;
217
+ }
218
+
219
+ .tryAgainButton:hover {
220
+ background: var(--branch-accent-hover);
221
+ }
222
+
223
+ .tryAgainButton:focus-visible {
224
+ outline: 2px solid var(--branch-accent);
225
+ outline-offset: 2px;
226
+ }
227
+
168
228
  /* ---- Ending ---- */
169
229
  .endingMessage {
170
230
  margin: 1.5rem 0 0;
package/README.md CHANGED
@@ -91,7 +91,7 @@ elearning-components/
91
91
  │ └── main.jsx # Entry point
92
92
  ├── package.json # Dependencies
93
93
  ├── vite.config.js # Vite configuration
94
- └── README.md # This file
94
+ npm└── README.md # This file
95
95
  ```
96
96
 
97
97
  ## Technologies
@@ -1 +1 @@
1
- .flashcard-deck-container{display:flex;flex-direction:column;align-items:center;gap:2rem;padding:2rem;max-width:600px;margin:0 auto}.flashcard-deck-header{width:100%;text-align:center}.flashcard-counter{font-size:1rem;color:#666;font-weight:500}.flashcard-wrapper{perspective:1000px;width:100%;min-height:300px}.flashcard{position:relative;width:100%;height:300px;cursor:pointer;transform-style:preserve-3d;transition:transform .6s cubic-bezier(.34,1.56,.64,1)}.flashcard--flipped{transform:rotateY(180deg)}.flashcard-face{position:absolute;width:100%;height:100%;backface-visibility:hidden;border-radius:12px;box-shadow:0 4px 6px #0000001a,0 2px 4px #0000000f;display:flex;align-items:center;justify-content:center;padding:2rem;box-sizing:border-box}.flashcard-front{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;transform:rotateY(0)}.flashcard-back{background:linear-gradient(135deg,#f093fb,#f5576c);color:#fff;transform:rotateY(180deg)}.flashcard-content{font-size:1.25rem;text-align:center;word-wrap:break-word;overflow-wrap:break-word;line-height:1.6;font-weight:500}.flashcard-controls{display:flex;gap:1rem;width:100%;justify-content:center}.flashcard-button{padding:.75rem 2rem;font-size:1rem;font-weight:600;border:none;border-radius:8px;cursor:pointer;transition:all .3s ease;background-color:#667eea;color:#fff;min-width:120px}.flashcard-button:hover:not(:disabled){background-color:#5568d3;transform:translateY(-2px);box-shadow:0 4px 8px #667eea4d}.flashcard-button:active:not(:disabled){transform:translateY(0)}.flashcard-button:disabled{background-color:#e0e0e0;color:#9e9e9e;cursor:not-allowed;opacity:.6}.flashcard-empty-message{text-align:center;color:#666;font-size:1.1rem;padding:2rem}@media(max-width:768px){.flashcard-deck-container{padding:1rem}.flashcard{height:250px}.flashcard-content{font-size:1.1rem}.flashcard-button{padding:.625rem 1.5rem;font-size:.9rem;min-width:100px}}._accordion_1rfb4_1{width:100%;max-width:640px;margin:0 auto;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:#1a1a1a}._empty_1rfb4_17{padding:1rem 0;margin:0;color:#64748b;font-size:.9375rem}._item_1rfb4_31{border:1px solid #e2e8f0;border-bottom:none}._item_1rfb4_31:last-of-type{border-bottom:1px solid #e2e8f0}._item_1rfb4_31:first-of-type{border-radius:8px 8px 0 0}._item_1rfb4_31:last-of-type{border-radius:0 0 8px 8px}._item_1rfb4_31:only-of-type{border-radius:8px}._heading_1rfb4_73{margin:0;font-size:1rem;font-weight:600}._trigger_1rfb4_85{display:flex;align-items:center;justify-content:space-between;width:100%;padding:1rem 1.25rem;background:#f8fafc;border:none;cursor:pointer;text-align:left;font-size:inherit;font-weight:inherit;color:inherit;transition:background-color .2s ease}._trigger_1rfb4_85:hover{background:#f1f5f9}._trigger_1rfb4_85:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}._item_1rfb4_31[data-open=true] ._trigger_1rfb4_85{background:#fff;border-bottom:1px solid #e2e8f0}._title_1rfb4_145{flex:1;padding-right:.75rem}._icon_1rfb4_155{flex-shrink:0;font-size:.65rem;color:#64748b;transition:color .2s ease,transform .25s ease}._trigger_1rfb4_85:hover ._icon_1rfb4_155,._item_1rfb4_31[data-open=true] ._icon_1rfb4_155{color:#3b82f6}._item_1rfb4_31[data-open=true] ._icon_1rfb4_155{transform:rotate(180deg)}._panelWrapper_1rfb4_187{display:grid;grid-template-rows:0fr;transition:grid-template-rows .25s ease-in-out}._panelWrapper_1rfb4_187[data-open=true]{grid-template-rows:1fr}._panel_1rfb4_187{min-height:0;overflow:hidden}._content_1rfb4_217{padding:1rem 1.25rem 1.25rem;background:#fff;font-size:.9375rem;line-height:1.6;color:#334155}._content_1rfb4_217 :first-child{margin-top:0}._content_1rfb4_217 :last-child{margin-bottom:0}._wrapper_ip42z_3{--timeline-accent: #2563eb;--timeline-accent-hover: #1d4ed8;--timeline-bg: #f8fafc;--timeline-line: #e2e8f0;--timeline-text: #1e293b;--timeline-muted: #64748b;--timeline-radius: 12px;--timeline-shadow: 0 4px 20px rgba(0, 0, 0, .08);font-family:Segoe UI,system-ui,-apple-system,sans-serif;color:var(--timeline-text);max-width:100%;display:flex;flex-direction:column;gap:1.5rem}._contentPanel_ip42z_39{background:var(--timeline-bg);border-radius:var(--timeline-radius);padding:1.75rem 2rem;box-shadow:var(--timeline-shadow);min-height:140px;overflow:hidden}._contentSlide_ip42z_57{animation:_contentIn_ip42z_1 .35s ease-out forwards}@keyframes _contentIn_ip42z_1{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}._contentYear_ip42z_87{display:inline-block;font-size:.8125rem;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--timeline-accent);margin-bottom:.35rem}._contentTitle_ip42z_107{font-size:1.375rem;font-weight:700;line-height:1.3;margin:0 0 .75rem;color:var(--timeline-text)}._contentBody_ip42z_123{font-size:1rem;line-height:1.6;color:var(--timeline-muted)}._contentBody_ip42z_123 p{margin:0 0 .5rem}._contentBody_ip42z_123 p:last-child{margin-bottom:0}._timelineSection_ip42z_153{display:flex;align-items:center;gap:.5rem}._navButton_ip42z_165{flex-shrink:0;width:2.5rem;height:2.5rem;border-radius:50%;border:2px solid var(--timeline-line);background:#fff;color:var(--timeline-text);font-size:1.5rem;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:border-color .2s ease,background .2s ease,color .2s ease}._navButton_ip42z_165:hover:not(:disabled){border-color:var(--timeline-accent);background:var(--timeline-accent);color:#fff}._navButton_ip42z_165:disabled{opacity:.4;cursor:not-allowed}._track_ip42z_223{flex:1;overflow-x:auto;overflow-y:hidden;scroll-behavior:smooth;scrollbar-width:thin;scrollbar-color:var(--timeline-line) transparent;cursor:grab;padding:.5rem 0;margin:0 -.5rem}._track_ip42z_223._dragging_ip42z_247{cursor:grabbing;scroll-behavior:auto}._track_ip42z_223::-webkit-scrollbar{height:6px}._track_ip42z_223::-webkit-scrollbar-track{background:transparent}._track_ip42z_223::-webkit-scrollbar-thumb{background:var(--timeline-line);border-radius:3px}._trackInner_ip42z_283{display:flex;gap:.75rem;padding:0 .25rem;min-width:min-content}._marker_ip42z_299{flex-shrink:0;display:flex;flex-direction:column;align-items:center;gap:.25rem;padding:.75rem 1rem;min-width:100px;border:2px solid var(--timeline-line);border-radius:var(--timeline-radius);background:#fff;color:var(--timeline-muted);font:inherit;cursor:pointer;text-align:center;transition:transform .25s ease,border-color .25s ease,background .25s ease,color .25s ease,box-shadow .25s ease}._marker_ip42z_299:hover{border-color:var(--timeline-accent);color:var(--timeline-accent)}._markerActive_ip42z_347{border-color:var(--timeline-accent);background:var(--timeline-accent);color:#fff;transform:scale(1.08);box-shadow:var(--timeline-shadow)}._markerActive_ip42z_347:hover{background:var(--timeline-accent-hover);border-color:var(--timeline-accent-hover);color:#fff}._markerYear_ip42z_375{font-size:.8125rem;font-weight:700;letter-spacing:.02em}._markerTitle_ip42z_387{font-size:.8125rem;font-weight:500;line-height:1.25;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}._empty_ip42z_409{margin:0;padding:2rem;text-align:center;color:var(--timeline-muted);font-size:1rem}._wrapper_1f6cj_3{--match-accent: #2563eb;--match-accent-hover: #1d4ed8;--match-bg: #f8fafc;--match-border: #e2e8f0;--match-text: #1e293b;--match-muted: #64748b;--match-success: #16a34a;--match-success-bg: #dcfce7;--match-over: #93c5fd;--match-over-bg: #eff6ff;--match-radius: 12px;--match-shadow: 0 4px 20px rgba(0, 0, 0, .08);font-family:Segoe UI,system-ui,-apple-system,sans-serif;color:var(--match-text);max-width:100%;display:flex;flex-direction:column;gap:1.25rem}._instruction_1f6cj_47{margin:0;font-size:.9375rem;color:var(--match-muted);line-height:1.5}._columns_1f6cj_63{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem;align-items:start}@media(max-width:640px){._columns_1f6cj_63{grid-template-columns:1fr}}._column_1f6cj_63{display:flex;flex-direction:column;gap:.75rem;padding:1.25rem;background:var(--match-bg);border:2px solid var(--match-border);border-radius:var(--match-radius);min-height:200px;transition:border-color .25s ease,box-shadow .25s ease}._columnTitle_1f6cj_113{margin:0;font-size:.875rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--match-muted)}._list_1f6cj_133{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.5rem}._item_1f6cj_153{display:flex;align-items:center;padding:1rem 1.25rem;background:#fff;border:2px solid var(--match-border);border-radius:var(--match-radius);box-shadow:0 1px 3px #0000000d;cursor:grab;transition:transform .25s ease,border-color .25s ease,background-color .25s ease,box-shadow .25s ease;touch-action:none}._item_1f6cj_153:hover{border-color:var(--match-accent);box-shadow:0 2px 8px #2563eb1f}._item_1f6cj_153:active{cursor:grabbing}._itemDragging_1f6cj_205{opacity:.95;transform:scale(1.02);box-shadow:var(--match-shadow);border-color:var(--match-accent);z-index:10;transition:transform .2s ease,box-shadow .2s ease}._itemDisabled_1f6cj_223{cursor:default;opacity:.7}._itemContent_1f6cj_233{font-size:1rem;font-weight:500;line-height:1.4;flex:1}._target_1f6cj_249{display:flex;flex-direction:column;gap:.35rem;padding:1rem 1.25rem;background:#fff;border:2px dashed var(--match-border);border-radius:var(--match-radius);min-height:3.5rem;transition:border-color .25s ease,background-color .25s ease,transform .25s ease,box-shadow .25s ease}._targetOver_1f6cj_281{border-style:solid;border-color:var(--match-accent);background:var(--match-over-bg);transform:scale(1.01);box-shadow:0 2px 12px #2563eb26}._targetMatched_1f6cj_297{border-style:solid;border-color:var(--match-success);background:var(--match-success-bg);animation:_matchSuccess_1f6cj_1 .4s ease-out forwards}@keyframes _matchSuccess_1f6cj_1{0%{transform:scale(1.02);box-shadow:0 0 #16a34a66}to{transform:scale(1);box-shadow:0 2px 8px #16a34a33}}._targetContent_1f6cj_333{font-size:.875rem;font-weight:600;color:var(--match-muted);line-height:1.3}._targetPlaceholder_1f6cj_347{font-size:.8125rem;color:var(--match-border);font-style:italic}._matchedContent_1f6cj_359{font-size:1rem;font-weight:500;color:var(--match-success);line-height:1.4;transition:opacity .3s ease}._empty_1f6cj_377{margin:0;padding:2rem;text-align:center;color:var(--match-muted);font-size:1rem}._wrapper_1osh8_3{--sort-accent: #2563eb;--sort-accent-hover: #1d4ed8;--sort-bg: #f8fafc;--sort-border: #e2e8f0;--sort-text: #1e293b;--sort-muted: #64748b;--sort-success: #16a34a;--sort-success-bg: #dcfce7;--sort-error: #dc2626;--sort-error-bg: #fee2e2;--sort-radius: 12px;--sort-shadow: 0 4px 20px rgba(0, 0, 0, .08);font-family:Segoe UI,system-ui,-apple-system,sans-serif;color:var(--sort-text);max-width:100%;display:flex;flex-direction:column;gap:1.25rem}._instruction_1osh8_47{margin:0;font-size:.9375rem;color:var(--sort-muted);line-height:1.5}._list_1osh8_63{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.5rem}._item_1osh8_83{display:flex;align-items:center;padding:1rem 1.25rem;background:#fff;border:2px solid var(--sort-border);border-radius:var(--sort-radius);box-shadow:0 1px 3px #0000000d;cursor:grab;transition:transform .25s ease,border-color .25s ease,background-color .25s ease,box-shadow .25s ease;touch-action:none}._item_1osh8_83:hover{border-color:var(--sort-accent);box-shadow:0 2px 8px #2563eb1f}._item_1osh8_83:active{cursor:grabbing}._itemDragging_1osh8_135{opacity:.9;transform:scale(1.02);box-shadow:var(--sort-shadow);border-color:var(--sort-accent);z-index:1}._itemCorrect_1osh8_151{border-color:var(--sort-success);background-color:var(--sort-success-bg);animation:_itemFeedbackIn_1osh8_1 .35s ease-out forwards}._itemIncorrect_1osh8_163{border-color:var(--sort-error);background-color:var(--sort-error-bg);animation:_itemFeedbackIn_1osh8_1 .35s ease-out forwards}@keyframes _itemFeedbackIn_1osh8_1{0%{transform:scale(.98);opacity:.85}to{transform:scale(1);opacity:1}}._itemContent_1osh8_197{font-size:1rem;font-weight:500;line-height:1.4;flex:1}._actions_1osh8_213{display:flex;gap:.75rem;flex-wrap:wrap}._buttonPrimary_1osh8_225{padding:.625rem 1.25rem;font-size:.9375rem;font-weight:600;color:#fff;background:var(--sort-accent);border:none;border-radius:var(--sort-radius);cursor:pointer;transition:background-color .2s ease,transform .2s ease}._buttonPrimary_1osh8_225:hover{background:var(--sort-accent-hover)}._buttonPrimary_1osh8_225:active{transform:scale(.98)}._buttonSecondary_1osh8_269{padding:.625rem 1.25rem;font-size:.9375rem;font-weight:600;color:var(--sort-text);background:#fff;border:2px solid var(--sort-border);border-radius:var(--sort-radius);cursor:pointer;transition:border-color .2s ease,background-color .2s ease,transform .2s ease}._buttonSecondary_1osh8_269:hover{border-color:var(--sort-accent);background:var(--sort-bg)}._buttonSecondary_1osh8_269:active{transform:scale(.98)}._feedbackCorrect_1osh8_319{padding:.875rem 1.25rem;background:var(--sort-success-bg);border:1px solid var(--sort-success);border-radius:var(--sort-radius);color:var(--sort-success);font-weight:600;font-size:.9375rem;animation:_feedbackSlideIn_1osh8_1 .3s ease-out forwards}._feedbackIncorrect_1osh8_341{padding:.875rem 1.25rem;background:var(--sort-error-bg);border:1px solid var(--sort-error);border-radius:var(--sort-radius);color:var(--sort-error);font-weight:600;font-size:.9375rem;animation:_feedbackSlideIn_1osh8_1 .3s ease-out forwards}@keyframes _feedbackSlideIn_1osh8_1{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}._empty_1osh8_387{margin:0;padding:2rem;text-align:center;color:var(--sort-muted);font-size:1rem}._wrapper_xbgog_3{--dnd-accent: #2563eb;--dnd-accent-hover: #1d4ed8;--dnd-bg: #f8fafc;--dnd-border: #e2e8f0;--dnd-text: #1e293b;--dnd-muted: #64748b;--dnd-success: #16a34a;--dnd-success-bg: #dcfce7;--dnd-error: #dc2626;--dnd-error-bg: #fee2e2;--dnd-over: #93c5fd;--dnd-over-bg: #eff6ff;--dnd-radius: 12px;--dnd-shadow: 0 4px 20px rgba(0, 0, 0, .08);font-family:Segoe UI,system-ui,-apple-system,sans-serif;color:var(--dnd-text);max-width:100%;display:flex;flex-direction:column;gap:1.25rem}._instruction_xbgog_51{margin:0;font-size:.9375rem;color:var(--dnd-muted);line-height:1.5}._layout_xbgog_67{display:flex;flex-direction:column;gap:1.5rem}._column_xbgog_79{display:flex;flex-direction:column;gap:.75rem;padding:1.25rem;background:var(--dnd-bg);border:2px solid var(--dnd-border);border-radius:var(--dnd-radius);transition:border-color .25s ease,box-shadow .25s ease}._itemsArea_xbgog_103 ._list_xbgog_103{flex-direction:row;flex-wrap:wrap;gap:.75rem}._itemsArea_xbgog_103{min-height:100px}._targetsArea_xbgog_125 ._list_xbgog_103{flex-direction:row;flex-wrap:wrap;gap:.75rem}._targetsArea_xbgog_125 ._listItem_xbgog_137{flex:1 1 140px;min-width:0}._targetsArea_xbgog_125{min-height:120px}._columnTitle_xbgog_155{margin:0;font-size:.875rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--dnd-muted)}._list_xbgog_103{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.5rem}._listItem_xbgog_137{position:relative}._item_xbgog_103{display:flex;align-items:center;padding:1rem 1.25rem;background:#fff;border:2px solid var(--dnd-border);border-radius:var(--dnd-radius);box-shadow:0 1px 3px #0000000d;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;transition:border-color .25s ease,background-color .25s ease,box-shadow .25s ease}._item_xbgog_103:active{cursor:grabbing}._item_xbgog_103:hover{border-color:var(--dnd-accent);box-shadow:0 2px 8px #2563eb1f}._itemSnapBack_xbgog_257{transition:transform .4s ease-out}._itemContent_xbgog_265{font-size:1rem;font-weight:500;line-height:1.4;flex:1;pointer-events:none}._target_xbgog_125{display:flex;flex-direction:column;gap:.35rem;padding:1rem 1.25rem;background:#fff;border:2px dashed var(--dnd-border);border-radius:var(--dnd-radius);min-height:4rem;height:100%;transition:border-color .25s ease,background-color .25s ease,transform .25s ease,box-shadow .25s ease}._targetOver_xbgog_317{border-style:solid;border-color:var(--dnd-accent);background:var(--dnd-over-bg);transform:scale(1.01);box-shadow:0 2px 12px #2563eb26}._targetCorrect_xbgog_333{border-style:solid;border-color:var(--dnd-success);background:var(--dnd-success-bg);animation:_targetCorrect_xbgog_333 .4s ease-out forwards}._targetIncorrect_xbgog_347{border-style:solid;border-color:var(--dnd-error);background:var(--dnd-error-bg);animation:_targetIncorrect_xbgog_347 .3s ease-out}._targetFilled_xbgog_361{border-style:solid;border-color:var(--dnd-success);background:var(--dnd-success-bg)}@keyframes _targetCorrect_xbgog_333{0%{transform:scale(1.02);box-shadow:0 0 #16a34a66}to{transform:scale(1);box-shadow:0 2px 8px #16a34a33}}@keyframes _targetIncorrect_xbgog_347{0%,to{transform:scale(1)}50%{transform:scale(1.02)}}._targetLabel_xbgog_415{font-size:.875rem;font-weight:600;color:var(--dnd-muted);line-height:1.3}._targetPlaceholder_xbgog_429{font-size:.8125rem;color:var(--dnd-border);font-style:italic}._placedContent_xbgog_441{font-size:1rem;font-weight:500;color:var(--dnd-success);line-height:1.4;transition:opacity .3s ease}._empty_xbgog_459{margin:0;padding:2rem;text-align:center;color:var(--dnd-muted);font-size:1rem}._wrapper_bljp9_3{--branch-accent: #0f766e;--branch-accent-hover: #0d9488;--branch-bg: #f0fdfa;--branch-card-bg: #ffffff;--branch-border: #ccfbf1;--branch-text: #134e4a;--branch-muted: #5eead4;--branch-narrative-bg: #f8fffe;--branch-radius: 12px;--branch-shadow: 0 4px 20px rgba(15, 118, 110, .08);font-family:Segoe UI,system-ui,-apple-system,sans-serif;color:var(--branch-text);max-width:42rem;margin:0 auto}._contentWrap_bljp9_39{opacity:1;transform:translateY(0);transition:opacity .28s ease-out,transform .28s ease-out}._contentEnter_bljp9_55{opacity:1;transform:translateY(0)}._contentExit_bljp9_65{opacity:0;transform:translateY(-8px);pointer-events:none}._title_bljp9_79{margin:0 0 1rem;font-size:1.5rem;font-weight:700;line-height:1.3;color:var(--branch-text)}._imageWrap_bljp9_97{margin-bottom:1.25rem;border-radius:var(--branch-radius);overflow:hidden;box-shadow:var(--branch-shadow);background:var(--branch-border)}._image_bljp9_97{display:block;width:100%;height:auto;vertical-align:middle}._narrative_bljp9_129{padding:1.25rem 1.5rem;margin-bottom:1.5rem;background:var(--branch-narrative-bg);border:1px solid var(--branch-border);border-radius:var(--branch-radius);font-size:1.0625rem;line-height:1.65;color:var(--branch-text);transition:opacity .28s ease-out}._feedback_bljp9_155{margin:0 0 1rem;padding:.75rem 1rem;font-size:.9375rem;line-height:1.5;color:var(--branch-text);background:var(--branch-bg);border-left:4px solid var(--branch-accent);border-radius:0 var(--branch-radius) var(--branch-radius) 0}._choicesNav_bljp9_179,._outcomesNav_bljp9_181{margin-top:1.5rem}._choicesLabel_bljp9_189{margin:0 0 .75rem;font-size:.875rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--branch-accent)}._choicesList_bljp9_207{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.75rem}._choiceItem_bljp9_225{margin:0}._choiceButton_bljp9_235,._outcomeButton_bljp9_237{display:block;width:100%;padding:1rem 1.25rem;font-size:1rem;font-weight:500;line-height:1.4;text-align:left;color:var(--branch-text);background:var(--branch-card-bg);border:2px solid var(--branch-border);border-radius:var(--branch-radius);cursor:pointer;transition:background-color .2s ease,border-color .2s ease,transform .2s ease,box-shadow .2s ease;appearance:none}._choiceButton_bljp9_235:hover,._outcomeButton_bljp9_237:hover{background:var(--branch-bg);border-color:var(--branch-accent);box-shadow:0 2px 12px #0f766e1f}._choiceButton_bljp9_235:focus-visible,._outcomeButton_bljp9_237:focus-visible{outline:2px solid var(--branch-accent);outline-offset:2px}._choiceButton_bljp9_235:active,._outcomeButton_bljp9_237:active{transform:scale(.99)}._outcomeButton_bljp9_237{border-style:dashed;background:var(--branch-bg)}._outcomeButton_bljp9_237:hover{border-style:solid}._endingMessage_bljp9_337{margin:1.5rem 0 0;padding:1rem 1.25rem;font-size:.9375rem;font-weight:500;color:var(--branch-accent);background:var(--branch-bg);border-radius:var(--branch-radius);text-align:center}._error_bljp9_361{margin:0;padding:1rem;color:#b91c1c;background:#fef2f2;border-radius:var(--branch-radius)}._wrapper_jm0vy_3{display:grid;grid-template-rows:auto 1fr auto;min-height:0;height:100dvh;max-height:100dvh;box-sizing:border-box;font-size:clamp(14px,2.5vw,18px);line-height:1.5;color:#1a1a1a;background-color:#fff}._header_jm0vy_31,._footer_jm0vy_33{min-height:0;flex-shrink:0}._body_jm0vy_45{min-height:0;overflow-y:auto;overflow-x:hidden;padding:clamp(.5rem,2vw,1.5rem);-webkit-overflow-scrolling:touch}._body_jm0vy_45:focus{outline:none}._body_jm0vy_45:focus-visible{outline:2px solid #2563eb;outline-offset:2px}._mobile_jm0vy_81 ._body_jm0vy_45{padding:clamp(.5rem,2vw,1.5rem);font-size:clamp(14px,2.5vw,16px)}._mobile_jm0vy_81 ._body_jm0vy_45 button,._mobile_jm0vy_81 ._body_jm0vy_45 a[href],._mobile_jm0vy_81 ._body_jm0vy_45 [role=button]{min-height:44px;min-width:44px;display:inline-flex;align-items:center;justify-content:center}._desktop_jm0vy_115 ._body_jm0vy_45{padding:clamp(.5rem,2vw,1.5rem)}@media(max-width:599px){._wrapper_jm0vy_3{font-size:clamp(14px,2.5vw,16px)}}@media(min-width:600px){._wrapper_jm0vy_3{font-size:clamp(14px,2.5vw,18px)}}
1
+ .flashcard-deck-container{display:flex;flex-direction:column;align-items:center;gap:2rem;padding:2rem;max-width:600px;margin:0 auto}.flashcard-deck-header{width:100%;text-align:center}.flashcard-counter{font-size:1rem;color:#666;font-weight:500}.flashcard-wrapper{perspective:1000px;width:100%;min-height:300px}.flashcard{position:relative;width:100%;height:300px;cursor:pointer;transform-style:preserve-3d;transition:transform .6s cubic-bezier(.34,1.56,.64,1)}.flashcard--flipped{transform:rotateY(180deg)}.flashcard-face{position:absolute;width:100%;height:100%;backface-visibility:hidden;border-radius:12px;box-shadow:0 4px 6px #0000001a,0 2px 4px #0000000f;display:flex;align-items:center;justify-content:center;padding:2rem;box-sizing:border-box}.flashcard-front{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;transform:rotateY(0)}.flashcard-back{background:linear-gradient(135deg,#f093fb,#f5576c);color:#fff;transform:rotateY(180deg)}.flashcard-content{font-size:1.25rem;text-align:center;word-wrap:break-word;overflow-wrap:break-word;line-height:1.6;font-weight:500}.flashcard-controls{display:flex;gap:1rem;width:100%;justify-content:center}.flashcard-button{padding:.75rem 2rem;font-size:1rem;font-weight:600;border:none;border-radius:8px;cursor:pointer;transition:all .3s ease;background-color:#667eea;color:#fff;min-width:120px}.flashcard-button:hover:not(:disabled){background-color:#5568d3;transform:translateY(-2px);box-shadow:0 4px 8px #667eea4d}.flashcard-button:active:not(:disabled){transform:translateY(0)}.flashcard-button:disabled{background-color:#e0e0e0;color:#9e9e9e;cursor:not-allowed;opacity:.6}.flashcard-empty-message{text-align:center;color:#666;font-size:1.1rem;padding:2rem}@media(max-width:768px){.flashcard-deck-container{padding:1rem}.flashcard{height:250px}.flashcard-content{font-size:1.1rem}.flashcard-button{padding:.625rem 1.5rem;font-size:.9rem;min-width:100px}}._accordion_1rfb4_1{width:100%;max-width:640px;margin:0 auto;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:#1a1a1a}._empty_1rfb4_17{padding:1rem 0;margin:0;color:#64748b;font-size:.9375rem}._item_1rfb4_31{border:1px solid #e2e8f0;border-bottom:none}._item_1rfb4_31:last-of-type{border-bottom:1px solid #e2e8f0}._item_1rfb4_31:first-of-type{border-radius:8px 8px 0 0}._item_1rfb4_31:last-of-type{border-radius:0 0 8px 8px}._item_1rfb4_31:only-of-type{border-radius:8px}._heading_1rfb4_73{margin:0;font-size:1rem;font-weight:600}._trigger_1rfb4_85{display:flex;align-items:center;justify-content:space-between;width:100%;padding:1rem 1.25rem;background:#f8fafc;border:none;cursor:pointer;text-align:left;font-size:inherit;font-weight:inherit;color:inherit;transition:background-color .2s ease}._trigger_1rfb4_85:hover{background:#f1f5f9}._trigger_1rfb4_85:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}._item_1rfb4_31[data-open=true] ._trigger_1rfb4_85{background:#fff;border-bottom:1px solid #e2e8f0}._title_1rfb4_145{flex:1;padding-right:.75rem}._icon_1rfb4_155{flex-shrink:0;font-size:.65rem;color:#64748b;transition:color .2s ease,transform .25s ease}._trigger_1rfb4_85:hover ._icon_1rfb4_155,._item_1rfb4_31[data-open=true] ._icon_1rfb4_155{color:#3b82f6}._item_1rfb4_31[data-open=true] ._icon_1rfb4_155{transform:rotate(180deg)}._panelWrapper_1rfb4_187{display:grid;grid-template-rows:0fr;transition:grid-template-rows .25s ease-in-out}._panelWrapper_1rfb4_187[data-open=true]{grid-template-rows:1fr}._panel_1rfb4_187{min-height:0;overflow:hidden}._content_1rfb4_217{padding:1rem 1.25rem 1.25rem;background:#fff;font-size:.9375rem;line-height:1.6;color:#334155}._content_1rfb4_217 :first-child{margin-top:0}._content_1rfb4_217 :last-child{margin-bottom:0}._wrapper_ip42z_3{--timeline-accent: #2563eb;--timeline-accent-hover: #1d4ed8;--timeline-bg: #f8fafc;--timeline-line: #e2e8f0;--timeline-text: #1e293b;--timeline-muted: #64748b;--timeline-radius: 12px;--timeline-shadow: 0 4px 20px rgba(0, 0, 0, .08);font-family:Segoe UI,system-ui,-apple-system,sans-serif;color:var(--timeline-text);max-width:100%;display:flex;flex-direction:column;gap:1.5rem}._contentPanel_ip42z_39{background:var(--timeline-bg);border-radius:var(--timeline-radius);padding:1.75rem 2rem;box-shadow:var(--timeline-shadow);min-height:140px;overflow:hidden}._contentSlide_ip42z_57{animation:_contentIn_ip42z_1 .35s ease-out forwards}@keyframes _contentIn_ip42z_1{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}._contentYear_ip42z_87{display:inline-block;font-size:.8125rem;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--timeline-accent);margin-bottom:.35rem}._contentTitle_ip42z_107{font-size:1.375rem;font-weight:700;line-height:1.3;margin:0 0 .75rem;color:var(--timeline-text)}._contentBody_ip42z_123{font-size:1rem;line-height:1.6;color:var(--timeline-muted)}._contentBody_ip42z_123 p{margin:0 0 .5rem}._contentBody_ip42z_123 p:last-child{margin-bottom:0}._timelineSection_ip42z_153{display:flex;align-items:center;gap:.5rem}._navButton_ip42z_165{flex-shrink:0;width:2.5rem;height:2.5rem;border-radius:50%;border:2px solid var(--timeline-line);background:#fff;color:var(--timeline-text);font-size:1.5rem;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:border-color .2s ease,background .2s ease,color .2s ease}._navButton_ip42z_165:hover:not(:disabled){border-color:var(--timeline-accent);background:var(--timeline-accent);color:#fff}._navButton_ip42z_165:disabled{opacity:.4;cursor:not-allowed}._track_ip42z_223{flex:1;overflow-x:auto;overflow-y:hidden;scroll-behavior:smooth;scrollbar-width:thin;scrollbar-color:var(--timeline-line) transparent;cursor:grab;padding:.5rem 0;margin:0 -.5rem}._track_ip42z_223._dragging_ip42z_247{cursor:grabbing;scroll-behavior:auto}._track_ip42z_223::-webkit-scrollbar{height:6px}._track_ip42z_223::-webkit-scrollbar-track{background:transparent}._track_ip42z_223::-webkit-scrollbar-thumb{background:var(--timeline-line);border-radius:3px}._trackInner_ip42z_283{display:flex;gap:.75rem;padding:0 .25rem;min-width:min-content}._marker_ip42z_299{flex-shrink:0;display:flex;flex-direction:column;align-items:center;gap:.25rem;padding:.75rem 1rem;min-width:100px;border:2px solid var(--timeline-line);border-radius:var(--timeline-radius);background:#fff;color:var(--timeline-muted);font:inherit;cursor:pointer;text-align:center;transition:transform .25s ease,border-color .25s ease,background .25s ease,color .25s ease,box-shadow .25s ease}._marker_ip42z_299:hover{border-color:var(--timeline-accent);color:var(--timeline-accent)}._markerActive_ip42z_347{border-color:var(--timeline-accent);background:var(--timeline-accent);color:#fff;transform:scale(1.08);box-shadow:var(--timeline-shadow)}._markerActive_ip42z_347:hover{background:var(--timeline-accent-hover);border-color:var(--timeline-accent-hover);color:#fff}._markerYear_ip42z_375{font-size:.8125rem;font-weight:700;letter-spacing:.02em}._markerTitle_ip42z_387{font-size:.8125rem;font-weight:500;line-height:1.25;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}._empty_ip42z_409{margin:0;padding:2rem;text-align:center;color:var(--timeline-muted);font-size:1rem}._wrapper_1f6cj_3{--match-accent: #2563eb;--match-accent-hover: #1d4ed8;--match-bg: #f8fafc;--match-border: #e2e8f0;--match-text: #1e293b;--match-muted: #64748b;--match-success: #16a34a;--match-success-bg: #dcfce7;--match-over: #93c5fd;--match-over-bg: #eff6ff;--match-radius: 12px;--match-shadow: 0 4px 20px rgba(0, 0, 0, .08);font-family:Segoe UI,system-ui,-apple-system,sans-serif;color:var(--match-text);max-width:100%;display:flex;flex-direction:column;gap:1.25rem}._instruction_1f6cj_47{margin:0;font-size:.9375rem;color:var(--match-muted);line-height:1.5}._columns_1f6cj_63{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem;align-items:start}@media(max-width:640px){._columns_1f6cj_63{grid-template-columns:1fr}}._column_1f6cj_63{display:flex;flex-direction:column;gap:.75rem;padding:1.25rem;background:var(--match-bg);border:2px solid var(--match-border);border-radius:var(--match-radius);min-height:200px;transition:border-color .25s ease,box-shadow .25s ease}._columnTitle_1f6cj_113{margin:0;font-size:.875rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--match-muted)}._list_1f6cj_133{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.5rem}._item_1f6cj_153{display:flex;align-items:center;padding:1rem 1.25rem;background:#fff;border:2px solid var(--match-border);border-radius:var(--match-radius);box-shadow:0 1px 3px #0000000d;cursor:grab;transition:transform .25s ease,border-color .25s ease,background-color .25s ease,box-shadow .25s ease;touch-action:none}._item_1f6cj_153:hover{border-color:var(--match-accent);box-shadow:0 2px 8px #2563eb1f}._item_1f6cj_153:active{cursor:grabbing}._itemDragging_1f6cj_205{opacity:.95;transform:scale(1.02);box-shadow:var(--match-shadow);border-color:var(--match-accent);z-index:10;transition:transform .2s ease,box-shadow .2s ease}._itemDisabled_1f6cj_223{cursor:default;opacity:.7}._itemContent_1f6cj_233{font-size:1rem;font-weight:500;line-height:1.4;flex:1}._target_1f6cj_249{display:flex;flex-direction:column;gap:.35rem;padding:1rem 1.25rem;background:#fff;border:2px dashed var(--match-border);border-radius:var(--match-radius);min-height:3.5rem;transition:border-color .25s ease,background-color .25s ease,transform .25s ease,box-shadow .25s ease}._targetOver_1f6cj_281{border-style:solid;border-color:var(--match-accent);background:var(--match-over-bg);transform:scale(1.01);box-shadow:0 2px 12px #2563eb26}._targetMatched_1f6cj_297{border-style:solid;border-color:var(--match-success);background:var(--match-success-bg);animation:_matchSuccess_1f6cj_1 .4s ease-out forwards}@keyframes _matchSuccess_1f6cj_1{0%{transform:scale(1.02);box-shadow:0 0 #16a34a66}to{transform:scale(1);box-shadow:0 2px 8px #16a34a33}}._targetContent_1f6cj_333{font-size:.875rem;font-weight:600;color:var(--match-muted);line-height:1.3}._targetPlaceholder_1f6cj_347{font-size:.8125rem;color:var(--match-border);font-style:italic}._matchedContent_1f6cj_359{font-size:1rem;font-weight:500;color:var(--match-success);line-height:1.4;transition:opacity .3s ease}._empty_1f6cj_377{margin:0;padding:2rem;text-align:center;color:var(--match-muted);font-size:1rem}._wrapper_1osh8_3{--sort-accent: #2563eb;--sort-accent-hover: #1d4ed8;--sort-bg: #f8fafc;--sort-border: #e2e8f0;--sort-text: #1e293b;--sort-muted: #64748b;--sort-success: #16a34a;--sort-success-bg: #dcfce7;--sort-error: #dc2626;--sort-error-bg: #fee2e2;--sort-radius: 12px;--sort-shadow: 0 4px 20px rgba(0, 0, 0, .08);font-family:Segoe UI,system-ui,-apple-system,sans-serif;color:var(--sort-text);max-width:100%;display:flex;flex-direction:column;gap:1.25rem}._instruction_1osh8_47{margin:0;font-size:.9375rem;color:var(--sort-muted);line-height:1.5}._list_1osh8_63{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.5rem}._item_1osh8_83{display:flex;align-items:center;padding:1rem 1.25rem;background:#fff;border:2px solid var(--sort-border);border-radius:var(--sort-radius);box-shadow:0 1px 3px #0000000d;cursor:grab;transition:transform .25s ease,border-color .25s ease,background-color .25s ease,box-shadow .25s ease;touch-action:none}._item_1osh8_83:hover{border-color:var(--sort-accent);box-shadow:0 2px 8px #2563eb1f}._item_1osh8_83:active{cursor:grabbing}._itemDragging_1osh8_135{opacity:.9;transform:scale(1.02);box-shadow:var(--sort-shadow);border-color:var(--sort-accent);z-index:1}._itemCorrect_1osh8_151{border-color:var(--sort-success);background-color:var(--sort-success-bg);animation:_itemFeedbackIn_1osh8_1 .35s ease-out forwards}._itemIncorrect_1osh8_163{border-color:var(--sort-error);background-color:var(--sort-error-bg);animation:_itemFeedbackIn_1osh8_1 .35s ease-out forwards}@keyframes _itemFeedbackIn_1osh8_1{0%{transform:scale(.98);opacity:.85}to{transform:scale(1);opacity:1}}._itemContent_1osh8_197{font-size:1rem;font-weight:500;line-height:1.4;flex:1}._actions_1osh8_213{display:flex;gap:.75rem;flex-wrap:wrap}._buttonPrimary_1osh8_225{padding:.625rem 1.25rem;font-size:.9375rem;font-weight:600;color:#fff;background:var(--sort-accent);border:none;border-radius:var(--sort-radius);cursor:pointer;transition:background-color .2s ease,transform .2s ease}._buttonPrimary_1osh8_225:hover{background:var(--sort-accent-hover)}._buttonPrimary_1osh8_225:active{transform:scale(.98)}._buttonSecondary_1osh8_269{padding:.625rem 1.25rem;font-size:.9375rem;font-weight:600;color:var(--sort-text);background:#fff;border:2px solid var(--sort-border);border-radius:var(--sort-radius);cursor:pointer;transition:border-color .2s ease,background-color .2s ease,transform .2s ease}._buttonSecondary_1osh8_269:hover{border-color:var(--sort-accent);background:var(--sort-bg)}._buttonSecondary_1osh8_269:active{transform:scale(.98)}._feedbackCorrect_1osh8_319{padding:.875rem 1.25rem;background:var(--sort-success-bg);border:1px solid var(--sort-success);border-radius:var(--sort-radius);color:var(--sort-success);font-weight:600;font-size:.9375rem;animation:_feedbackSlideIn_1osh8_1 .3s ease-out forwards}._feedbackIncorrect_1osh8_341{padding:.875rem 1.25rem;background:var(--sort-error-bg);border:1px solid var(--sort-error);border-radius:var(--sort-radius);color:var(--sort-error);font-weight:600;font-size:.9375rem;animation:_feedbackSlideIn_1osh8_1 .3s ease-out forwards}@keyframes _feedbackSlideIn_1osh8_1{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}._empty_1osh8_387{margin:0;padding:2rem;text-align:center;color:var(--sort-muted);font-size:1rem}._wrapper_xbgog_3{--dnd-accent: #2563eb;--dnd-accent-hover: #1d4ed8;--dnd-bg: #f8fafc;--dnd-border: #e2e8f0;--dnd-text: #1e293b;--dnd-muted: #64748b;--dnd-success: #16a34a;--dnd-success-bg: #dcfce7;--dnd-error: #dc2626;--dnd-error-bg: #fee2e2;--dnd-over: #93c5fd;--dnd-over-bg: #eff6ff;--dnd-radius: 12px;--dnd-shadow: 0 4px 20px rgba(0, 0, 0, .08);font-family:Segoe UI,system-ui,-apple-system,sans-serif;color:var(--dnd-text);max-width:100%;display:flex;flex-direction:column;gap:1.25rem}._instruction_xbgog_51{margin:0;font-size:.9375rem;color:var(--dnd-muted);line-height:1.5}._layout_xbgog_67{display:flex;flex-direction:column;gap:1.5rem}._column_xbgog_79{display:flex;flex-direction:column;gap:.75rem;padding:1.25rem;background:var(--dnd-bg);border:2px solid var(--dnd-border);border-radius:var(--dnd-radius);transition:border-color .25s ease,box-shadow .25s ease}._itemsArea_xbgog_103 ._list_xbgog_103{flex-direction:row;flex-wrap:wrap;gap:.75rem}._itemsArea_xbgog_103{min-height:100px}._targetsArea_xbgog_125 ._list_xbgog_103{flex-direction:row;flex-wrap:wrap;gap:.75rem}._targetsArea_xbgog_125 ._listItem_xbgog_137{flex:1 1 140px;min-width:0}._targetsArea_xbgog_125{min-height:120px}._columnTitle_xbgog_155{margin:0;font-size:.875rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--dnd-muted)}._list_xbgog_103{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.5rem}._listItem_xbgog_137{position:relative}._item_xbgog_103{display:flex;align-items:center;padding:1rem 1.25rem;background:#fff;border:2px solid var(--dnd-border);border-radius:var(--dnd-radius);box-shadow:0 1px 3px #0000000d;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;transition:border-color .25s ease,background-color .25s ease,box-shadow .25s ease}._item_xbgog_103:active{cursor:grabbing}._item_xbgog_103:hover{border-color:var(--dnd-accent);box-shadow:0 2px 8px #2563eb1f}._itemSnapBack_xbgog_257{transition:transform .4s ease-out}._itemContent_xbgog_265{font-size:1rem;font-weight:500;line-height:1.4;flex:1;pointer-events:none}._target_xbgog_125{display:flex;flex-direction:column;gap:.35rem;padding:1rem 1.25rem;background:#fff;border:2px dashed var(--dnd-border);border-radius:var(--dnd-radius);min-height:4rem;height:100%;transition:border-color .25s ease,background-color .25s ease,transform .25s ease,box-shadow .25s ease}._targetOver_xbgog_317{border-style:solid;border-color:var(--dnd-accent);background:var(--dnd-over-bg);transform:scale(1.01);box-shadow:0 2px 12px #2563eb26}._targetCorrect_xbgog_333{border-style:solid;border-color:var(--dnd-success);background:var(--dnd-success-bg);animation:_targetCorrect_xbgog_333 .4s ease-out forwards}._targetIncorrect_xbgog_347{border-style:solid;border-color:var(--dnd-error);background:var(--dnd-error-bg);animation:_targetIncorrect_xbgog_347 .3s ease-out}._targetFilled_xbgog_361{border-style:solid;border-color:var(--dnd-success);background:var(--dnd-success-bg)}@keyframes _targetCorrect_xbgog_333{0%{transform:scale(1.02);box-shadow:0 0 #16a34a66}to{transform:scale(1);box-shadow:0 2px 8px #16a34a33}}@keyframes _targetIncorrect_xbgog_347{0%,to{transform:scale(1)}50%{transform:scale(1.02)}}._targetLabel_xbgog_415{font-size:.875rem;font-weight:600;color:var(--dnd-muted);line-height:1.3}._targetPlaceholder_xbgog_429{font-size:.8125rem;color:var(--dnd-border);font-style:italic}._placedContent_xbgog_441{font-size:1rem;font-weight:500;color:var(--dnd-success);line-height:1.4;transition:opacity .3s ease}._empty_xbgog_459{margin:0;padding:2rem;text-align:center;color:var(--dnd-muted);font-size:1rem}._wrapper_i8mep_3{--branch-accent: #0f766e;--branch-accent-hover: #0d9488;--branch-bg: #f0fdfa;--branch-card-bg: #ffffff;--branch-border: #ccfbf1;--branch-text: #134e4a;--branch-muted: #5eead4;--branch-narrative-bg: #f8fffe;--branch-radius: 12px;--branch-shadow: 0 4px 20px rgba(15, 118, 110, .08);font-family:Segoe UI,system-ui,-apple-system,sans-serif;color:var(--branch-text);max-width:42rem;margin:0 auto}._contentWrap_i8mep_39{opacity:1;transform:translateY(0);transition:opacity .28s ease-out,transform .28s ease-out}._contentEnter_i8mep_55{opacity:1;transform:translateY(0)}._contentExit_i8mep_65{opacity:0;transform:translateY(-8px);pointer-events:none}._title_i8mep_79{margin:0 0 1rem;font-size:1.5rem;font-weight:700;line-height:1.3;color:var(--branch-text)}._imageWrap_i8mep_97{margin-bottom:1.25rem;border-radius:var(--branch-radius);overflow:hidden;box-shadow:var(--branch-shadow);background:var(--branch-border)}._image_i8mep_97{display:block;width:100%;height:auto;vertical-align:middle}._narrative_i8mep_129{padding:1.25rem 1.5rem;margin-bottom:1.5rem;background:var(--branch-narrative-bg);border:1px solid var(--branch-border);border-radius:var(--branch-radius);font-size:1.0625rem;line-height:1.65;color:var(--branch-text);transition:opacity .28s ease-out}._feedback_i8mep_155{margin:0 0 1rem;padding:.75rem 1rem;font-size:.9375rem;line-height:1.5;color:var(--branch-text);background:var(--branch-bg);border-left:4px solid var(--branch-accent);border-radius:0 var(--branch-radius) var(--branch-radius) 0}._configWarning_i8mep_179{margin:0 0 .75rem;padding:.625rem .875rem;font-size:.8125rem;color:#92400e;background:#fffbeb;border:1px solid #fcd34d;border-radius:var(--branch-radius)}._choicesNav_i8mep_201,._outcomesNav_i8mep_203{margin-top:1.5rem}._choicesLabel_i8mep_211{margin:0 0 .75rem;font-size:.875rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--branch-accent)}._choicesList_i8mep_229{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.75rem}._choiceItem_i8mep_247{margin:0}._choiceButton_i8mep_257,._outcomeButton_i8mep_259{display:block;width:100%;padding:1rem 1.25rem;font-size:1rem;font-weight:500;line-height:1.4;text-align:left;color:var(--branch-text);background:var(--branch-card-bg);border:2px solid var(--branch-border);border-radius:var(--branch-radius);cursor:pointer;transition:background-color .2s ease,border-color .2s ease,transform .2s ease,box-shadow .2s ease;appearance:none}._choiceButton_i8mep_257:hover,._outcomeButton_i8mep_259:hover{background:var(--branch-bg);border-color:var(--branch-accent);box-shadow:0 2px 12px #0f766e1f}._choiceButton_i8mep_257:focus-visible,._outcomeButton_i8mep_259:focus-visible{outline:2px solid var(--branch-accent);outline-offset:2px}._choiceButton_i8mep_257:active,._outcomeButton_i8mep_259:active{transform:scale(.99)}._outcomeButton_i8mep_259{border-style:dashed;background:var(--branch-bg)}._outcomeButton_i8mep_259:hover{border-style:solid}._choiceCorrectPath_i8mep_359{border-left:4px solid var(--branch-accent)}._deadEndBlock_i8mep_379{margin-top:1.5rem;padding:1.25rem 1.5rem;background:#fef2f2;border:2px solid #fecaca;border-radius:var(--branch-radius)}._deadEndMessage_i8mep_395{margin:0 0 1rem;font-size:1rem;line-height:1.5;color:#991b1b}._tryAgainButton_i8mep_409{display:inline-flex;align-items:center;padding:.625rem 1.25rem;font-size:1rem;font-weight:600;color:#fff;background:var(--branch-accent);border:none;border-radius:var(--branch-radius);cursor:pointer;transition:background-color .2s ease}._tryAgainButton_i8mep_409:hover{background:var(--branch-accent-hover)}._tryAgainButton_i8mep_409:focus-visible{outline:2px solid var(--branch-accent);outline-offset:2px}._endingMessage_i8mep_457{margin:1.5rem 0 0;padding:1rem 1.25rem;font-size:.9375rem;font-weight:500;color:var(--branch-accent);background:var(--branch-bg);border-radius:var(--branch-radius);text-align:center}._error_i8mep_481{margin:0;padding:1rem;color:#b91c1c;background:#fef2f2;border-radius:var(--branch-radius)}._wrapper_jm0vy_3{display:grid;grid-template-rows:auto 1fr auto;min-height:0;height:100dvh;max-height:100dvh;box-sizing:border-box;font-size:clamp(14px,2.5vw,18px);line-height:1.5;color:#1a1a1a;background-color:#fff}._header_jm0vy_31,._footer_jm0vy_33{min-height:0;flex-shrink:0}._body_jm0vy_45{min-height:0;overflow-y:auto;overflow-x:hidden;padding:clamp(.5rem,2vw,1.5rem);-webkit-overflow-scrolling:touch}._body_jm0vy_45:focus{outline:none}._body_jm0vy_45:focus-visible{outline:2px solid #2563eb;outline-offset:2px}._mobile_jm0vy_81 ._body_jm0vy_45{padding:clamp(.5rem,2vw,1.5rem);font-size:clamp(14px,2.5vw,16px)}._mobile_jm0vy_81 ._body_jm0vy_45 button,._mobile_jm0vy_81 ._body_jm0vy_45 a[href],._mobile_jm0vy_81 ._body_jm0vy_45 [role=button]{min-height:44px;min-width:44px;display:inline-flex;align-items:center;justify-content:center}._desktop_jm0vy_115 ._body_jm0vy_45{padding:clamp(.5rem,2vw,1.5rem)}@media(max-width:599px){._wrapper_jm0vy_3{font-size:clamp(14px,2.5vw,16px)}}@media(min-width:600px){._wrapper_jm0vy_3{font-size:clamp(14px,2.5vw,18px)}}