@zomako/elearning-components 2.0.5 → 2.0.7

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.
@@ -0,0 +1,343 @@
1
+ import React, {
2
+ useState,
3
+ useCallback,
4
+ useEffect,
5
+ useRef,
6
+ useMemo,
7
+ } from 'react';
8
+ import interact from 'interactjs';
9
+ import styles from './style.module.css';
10
+
11
+ export interface DraggableItem {
12
+ id: string;
13
+ content: string;
14
+ }
15
+
16
+ export interface DropTarget {
17
+ id: string;
18
+ accepts: string[];
19
+ label: string;
20
+ }
21
+
22
+ export interface DragAndDropProps {
23
+ items: DraggableItem[];
24
+ targets: DropTarget[];
25
+ onComplete: (result: {
26
+ score: number;
27
+ correct: number;
28
+ total: number;
29
+ }) => void;
30
+ }
31
+
32
+ function shuffleArray<T>(array: T[]): T[] {
33
+ const shuffled = [...array];
34
+ for (let i = shuffled.length - 1; i > 0; i--) {
35
+ const j = Math.floor(Math.random() * (i + 1));
36
+ [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
37
+ }
38
+ return shuffled;
39
+ }
40
+
41
+ const DragAndDropActivity: React.FC<DragAndDropProps> = ({
42
+ items,
43
+ targets,
44
+ onComplete,
45
+ }) => {
46
+ const [shuffledItems] = useState(() => shuffleArray(items));
47
+ const [placements, setPlacements] = useState<Map<string, string>>(new Map());
48
+ const [snapBackItemId, setSnapBackItemId] = useState<string | null>(null);
49
+ const [incorrectTargetId, setIncorrectTargetId] = useState<string | null>(
50
+ null
51
+ );
52
+ const [targetHoverId, setTargetHoverId] = useState<string | null>(null);
53
+ const [targetFeedback, setTargetFeedback] = useState<
54
+ Map<string, 'correct' | 'incorrect' | null>
55
+ >(new Map());
56
+ const [hasCompleted, setHasCompleted] = useState(false);
57
+
58
+ const itemPositions = useRef<Map<string, { x: number; y: number }>>(
59
+ new Map()
60
+ );
61
+ const itemRefs = useRef<Map<string, HTMLDivElement | null>>(new Map());
62
+ const targetRefs = useRef<Map<string, HTMLDivElement | null>>(new Map());
63
+ const interactables = useRef<{ unset: () => void }[]>([]);
64
+
65
+ const unplacedItems = useMemo(
66
+ () =>
67
+ shuffledItems.filter(
68
+ (item) => ![...placements.values()].includes(item.id)
69
+ ),
70
+ [shuffledItems, placements]
71
+ );
72
+
73
+ const targetById = useMemo(() => {
74
+ const map = new Map<string, DropTarget>();
75
+ targets.forEach((t) => map.set(t.id, t));
76
+ return map;
77
+ }, [targets]);
78
+
79
+ useEffect(() => {
80
+ if (
81
+ placements.size === targets.length &&
82
+ placements.size > 0 &&
83
+ !hasCompleted
84
+ ) {
85
+ setHasCompleted(true);
86
+ const correct = placements.size;
87
+ const total = targets.length;
88
+ const score = total > 0 ? Math.round((correct / total) * 100) : 0;
89
+ onComplete({ score, correct, total });
90
+ }
91
+ }, [placements.size, targets.length, hasCompleted, onComplete]);
92
+
93
+ const handleSnapBackEnd = useCallback((targetIdToClear?: string) => {
94
+ setSnapBackItemId(null);
95
+ setTargetFeedback((prev) => {
96
+ if (targetIdToClear) {
97
+ const next = new Map(prev);
98
+ next.delete(targetIdToClear);
99
+ return next;
100
+ }
101
+ return prev;
102
+ });
103
+ setIncorrectTargetId(null);
104
+ }, []);
105
+
106
+ const handleDrop = useCallback(
107
+ (event: { relatedTarget: Element; target: Element }) => {
108
+ const draggableEl = event.relatedTarget;
109
+ const dropzoneEl = event.target;
110
+ const itemId = draggableEl.getAttribute('data-item-id');
111
+ const targetId = dropzoneEl.getAttribute('data-target-id');
112
+ if (!itemId || !targetId) return;
113
+
114
+ const target = targetById.get(targetId);
115
+ if (!target || placements.has(targetId)) return;
116
+
117
+ const isCorrect = target.accepts.includes(itemId);
118
+
119
+ if (isCorrect) {
120
+ itemPositions.current.set(itemId, { x: 0, y: 0 });
121
+ setPlacements((prev) => {
122
+ const next = new Map(prev).set(targetId, itemId);
123
+ return next;
124
+ });
125
+ setTargetFeedback((prev) => new Map(prev).set(targetId, 'correct'));
126
+ } else {
127
+ setTargetFeedback((prev) => new Map(prev).set(targetId, 'incorrect'));
128
+ setSnapBackItemId(itemId);
129
+ setIncorrectTargetId(targetId);
130
+ }
131
+ },
132
+ [targetById, placements]
133
+ );
134
+
135
+ useEffect(() => {
136
+ const cleanups: (() => void)[] = [];
137
+
138
+ unplacedItems.forEach((item) => {
139
+ const el = itemRefs.current.get(item.id);
140
+ const isPlaced = [...placements.values()].includes(item.id);
141
+ if (!el || isPlaced) return;
142
+
143
+ const pos = itemPositions.current.get(item.id) ?? { x: 0, y: 0 };
144
+ itemPositions.current.set(item.id, pos);
145
+
146
+ const interactable = interact(el)
147
+ .draggable({
148
+ inertia: false,
149
+ listeners: {
150
+ move(event) {
151
+ if (snapBackItemId === item.id) return;
152
+ pos.x += event.dx;
153
+ pos.y += event.dy;
154
+ el.style.transform = `translate(${pos.x}px, ${pos.y}px)`;
155
+ },
156
+ },
157
+ })
158
+ .styleCursor(false);
159
+
160
+ interactables.current.push(interactable);
161
+
162
+ cleanups.push(() => {
163
+ interactable.unset();
164
+ });
165
+ });
166
+
167
+ targets.forEach((target) => {
168
+ const el = targetRefs.current.get(target.id);
169
+ if (!el) return;
170
+
171
+ const interactable = interact(el).dropzone({
172
+ accept: '[data-item-id]',
173
+ overlap: 0.5,
174
+ ondropactivate: () => {
175
+ setTargetHoverId(target.id);
176
+ },
177
+ ondragenter: () => {
178
+ setTargetHoverId(target.id);
179
+ },
180
+ ondragleave: () => {
181
+ setTargetHoverId(null);
182
+ },
183
+ ondropdeactivate: () => {
184
+ setTargetHoverId(null);
185
+ },
186
+ ondrop: (event: { relatedTarget: Element; target: Element }) => {
187
+ handleDrop(event);
188
+ },
189
+ });
190
+
191
+ interactables.current.push(interactable);
192
+ cleanups.push(() => interactable.unset());
193
+ });
194
+
195
+ return () => {
196
+ cleanups.forEach((fn) => fn());
197
+ interactables.current = [];
198
+ };
199
+ }, [unplacedItems, placements, targets, handleDrop, snapBackItemId]);
200
+
201
+ useEffect(() => {
202
+ if (snapBackItemId) {
203
+ const el = itemRefs.current.get(snapBackItemId);
204
+ const targetIdToClear = incorrectTargetId;
205
+ if (el) {
206
+ itemPositions.current.set(snapBackItemId, { x: 0, y: 0 });
207
+ el.style.transition = 'transform 0.4s ease-out';
208
+ el.style.transform = 'translate(0, 0)';
209
+ const onTransitionEnd = () => {
210
+ el.style.transition = '';
211
+ handleSnapBackEnd(targetIdToClear ?? undefined);
212
+ el.removeEventListener('transitionend', onTransitionEnd);
213
+ };
214
+ el.addEventListener('transitionend', onTransitionEnd);
215
+ return () => el.removeEventListener('transitionend', onTransitionEnd);
216
+ } else {
217
+ handleSnapBackEnd(targetIdToClear ?? undefined);
218
+ }
219
+ }
220
+ }, [snapBackItemId, incorrectTargetId, handleSnapBackEnd]);
221
+
222
+ if (!items.length || !targets.length) {
223
+ return (
224
+ <div className={styles.wrapper} role="region" aria-label="Drag and drop activity">
225
+ <p className={styles.empty}>No items or targets to place.</p>
226
+ </div>
227
+ );
228
+ }
229
+
230
+ return (
231
+ <div
232
+ className={styles.wrapper}
233
+ role="region"
234
+ aria-label="Drag and drop quiz activity"
235
+ >
236
+ <p className={styles.instruction}>
237
+ Drag each item to its correct drop target. Items will snap into place
238
+ when correctly matched.
239
+ </p>
240
+
241
+ <div className={styles.layout}>
242
+ <section
243
+ className={styles.column}
244
+ aria-label="Items to place"
245
+ >
246
+ <h3 className={styles.columnTitle}>Items</h3>
247
+ <ul className={styles.list} role="list">
248
+ {unplacedItems.map((item) => (
249
+ <li key={item.id} className={styles.listItem}>
250
+ <div
251
+ ref={(node) => itemRefs.current.set(item.id, node)}
252
+ data-item-id={item.id}
253
+ className={`${styles.item} ${
254
+ snapBackItemId === item.id ? styles.itemSnapBack : ''
255
+ }`}
256
+ draggable={false}
257
+ aria-label={`Draggable item: ${item.content}`}
258
+ tabIndex={hasCompleted ? -1 : 0}
259
+ style={{
260
+ transform:
261
+ snapBackItemId !== item.id
262
+ ? `translate(${
263
+ itemPositions.current.get(item.id)?.x ?? 0
264
+ }px, ${
265
+ itemPositions.current.get(item.id)?.y ?? 0
266
+ }px)`
267
+ : undefined,
268
+ }}
269
+ >
270
+ <span
271
+ className={styles.itemContent}
272
+ dangerouslySetInnerHTML={{ __html: item.content }}
273
+ />
274
+ </div>
275
+ </li>
276
+ ))}
277
+ </ul>
278
+ </section>
279
+
280
+ <section
281
+ className={styles.column}
282
+ aria-label="Drop targets"
283
+ >
284
+ <h3 className={styles.columnTitle}>Targets</h3>
285
+ <ul className={styles.list} role="list">
286
+ {targets.map((target) => {
287
+ const placedItemId = placements.get(target.id);
288
+ const feedback = targetFeedback.get(target.id);
289
+ const isOver = targetHoverId === target.id;
290
+ const isFilled = !!placedItemId;
291
+ const placedItem = placedItemId
292
+ ? shuffledItems.find((i) => i.id === placedItemId)
293
+ : null;
294
+
295
+ return (
296
+ <li key={target.id} className={styles.listItem}>
297
+ <div
298
+ ref={(node) => targetRefs.current.set(target.id, node)}
299
+ data-target-id={target.id}
300
+ className={`${styles.target} ${
301
+ isOver && !isFilled ? styles.targetOver : ''
302
+ } ${
303
+ feedback === 'correct'
304
+ ? styles.targetCorrect
305
+ : feedback === 'incorrect'
306
+ ? styles.targetIncorrect
307
+ : ''
308
+ } ${isFilled ? styles.targetFilled : ''}`}
309
+ aria-label={`Drop target: ${target.label}${placedItemId ? `, contains ${placedItem?.content}` : ', empty'}`}
310
+ role="group"
311
+ >
312
+ <span
313
+ className={styles.targetLabel}
314
+ dangerouslySetInnerHTML={{ __html: target.label }}
315
+ />
316
+ {placedItem ? (
317
+ <span
318
+ className={styles.placedContent}
319
+ dangerouslySetInnerHTML={{
320
+ __html: placedItem.content,
321
+ }}
322
+ aria-hidden="true"
323
+ />
324
+ ) : (
325
+ <span
326
+ className={styles.targetPlaceholder}
327
+ aria-hidden="true"
328
+ >
329
+ Drop here
330
+ </span>
331
+ )}
332
+ </div>
333
+ </li>
334
+ );
335
+ })}
336
+ </ul>
337
+ </section>
338
+ </div>
339
+ </div>
340
+ );
341
+ };
342
+
343
+ export default DragAndDropActivity;
@@ -0,0 +1,216 @@
1
+ /* ---- Wrapper ---- */
2
+ .wrapper {
3
+ --dnd-accent: #2563eb;
4
+ --dnd-accent-hover: #1d4ed8;
5
+ --dnd-bg: #f8fafc;
6
+ --dnd-border: #e2e8f0;
7
+ --dnd-text: #1e293b;
8
+ --dnd-muted: #64748b;
9
+ --dnd-success: #16a34a;
10
+ --dnd-success-bg: #dcfce7;
11
+ --dnd-error: #dc2626;
12
+ --dnd-error-bg: #fee2e2;
13
+ --dnd-over: #93c5fd;
14
+ --dnd-over-bg: #eff6ff;
15
+ --dnd-radius: 12px;
16
+ --dnd-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
17
+ font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
18
+ color: var(--dnd-text);
19
+ max-width: 100%;
20
+ display: flex;
21
+ flex-direction: column;
22
+ gap: 1.25rem;
23
+ }
24
+
25
+ /* ---- Instruction ---- */
26
+ .instruction {
27
+ margin: 0;
28
+ font-size: 0.9375rem;
29
+ color: var(--dnd-muted);
30
+ line-height: 1.5;
31
+ }
32
+
33
+ /* ---- Layout ---- */
34
+ .layout {
35
+ display: grid;
36
+ grid-template-columns: 1fr 1fr;
37
+ gap: 1.5rem;
38
+ align-items: start;
39
+ }
40
+
41
+ @media (max-width: 640px) {
42
+ .layout {
43
+ grid-template-columns: 1fr;
44
+ }
45
+ }
46
+
47
+ .column {
48
+ display: flex;
49
+ flex-direction: column;
50
+ gap: 0.75rem;
51
+ padding: 1.25rem;
52
+ background: var(--dnd-bg);
53
+ border: 2px solid var(--dnd-border);
54
+ border-radius: var(--dnd-radius);
55
+ min-height: 200px;
56
+ transition: border-color 0.25s ease, box-shadow 0.25s ease;
57
+ }
58
+
59
+ .columnTitle {
60
+ margin: 0;
61
+ font-size: 0.875rem;
62
+ font-weight: 700;
63
+ text-transform: uppercase;
64
+ letter-spacing: 0.05em;
65
+ color: var(--dnd-muted);
66
+ }
67
+
68
+ /* ---- Lists ---- */
69
+ .list {
70
+ margin: 0;
71
+ padding: 0;
72
+ list-style: none;
73
+ display: flex;
74
+ flex-direction: column;
75
+ gap: 0.5rem;
76
+ }
77
+
78
+ .listItem {
79
+ position: relative;
80
+ }
81
+
82
+ /* ---- Draggable items ---- */
83
+ .item {
84
+ display: flex;
85
+ align-items: center;
86
+ padding: 1rem 1.25rem;
87
+ background: #fff;
88
+ border: 2px solid var(--dnd-border);
89
+ border-radius: var(--dnd-radius);
90
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
91
+ cursor: grab;
92
+ touch-action: none;
93
+ user-select: none;
94
+ -webkit-user-select: none;
95
+ transition:
96
+ border-color 0.25s ease,
97
+ background-color 0.25s ease,
98
+ box-shadow 0.25s ease;
99
+ }
100
+
101
+ .item:active {
102
+ cursor: grabbing;
103
+ }
104
+
105
+ .item:hover {
106
+ border-color: var(--dnd-accent);
107
+ box-shadow: 0 2px 8px rgba(37, 99, 235, 0.12);
108
+ }
109
+
110
+ .itemSnapBack {
111
+ transition: transform 0.4s ease-out;
112
+ }
113
+
114
+ .itemContent {
115
+ font-size: 1rem;
116
+ font-weight: 500;
117
+ line-height: 1.4;
118
+ flex: 1;
119
+ pointer-events: none;
120
+ }
121
+
122
+ /* ---- Drop targets ---- */
123
+ .target {
124
+ display: flex;
125
+ flex-direction: column;
126
+ gap: 0.35rem;
127
+ padding: 1rem 1.25rem;
128
+ background: #fff;
129
+ border: 2px dashed var(--dnd-border);
130
+ border-radius: var(--dnd-radius);
131
+ min-height: 3.5rem;
132
+ transition:
133
+ border-color 0.25s ease,
134
+ background-color 0.25s ease,
135
+ transform 0.25s ease,
136
+ box-shadow 0.25s ease;
137
+ }
138
+
139
+ .targetOver {
140
+ border-style: solid;
141
+ border-color: var(--dnd-accent);
142
+ background: var(--dnd-over-bg);
143
+ transform: scale(1.01);
144
+ box-shadow: 0 2px 12px rgba(37, 99, 235, 0.15);
145
+ }
146
+
147
+ .targetCorrect {
148
+ border-style: solid;
149
+ border-color: var(--dnd-success);
150
+ background: var(--dnd-success-bg);
151
+ animation: targetCorrect 0.4s ease-out forwards;
152
+ }
153
+
154
+ .targetIncorrect {
155
+ border-style: solid;
156
+ border-color: var(--dnd-error);
157
+ background: var(--dnd-error-bg);
158
+ animation: targetIncorrect 0.3s ease-out;
159
+ }
160
+
161
+ .targetFilled {
162
+ border-style: solid;
163
+ border-color: var(--dnd-success);
164
+ background: var(--dnd-success-bg);
165
+ }
166
+
167
+ @keyframes targetCorrect {
168
+ from {
169
+ transform: scale(1.02);
170
+ box-shadow: 0 0 0 0 rgba(22, 163, 74, 0.4);
171
+ }
172
+ to {
173
+ transform: scale(1);
174
+ box-shadow: 0 2px 8px rgba(22, 163, 74, 0.2);
175
+ }
176
+ }
177
+
178
+ @keyframes targetIncorrect {
179
+ 0%,
180
+ 100% {
181
+ transform: scale(1);
182
+ }
183
+ 50% {
184
+ transform: scale(1.02);
185
+ }
186
+ }
187
+
188
+ .targetLabel {
189
+ font-size: 0.875rem;
190
+ font-weight: 600;
191
+ color: var(--dnd-muted);
192
+ line-height: 1.3;
193
+ }
194
+
195
+ .targetPlaceholder {
196
+ font-size: 0.8125rem;
197
+ color: var(--dnd-border);
198
+ font-style: italic;
199
+ }
200
+
201
+ .placedContent {
202
+ font-size: 1rem;
203
+ font-weight: 500;
204
+ color: var(--dnd-success);
205
+ line-height: 1.4;
206
+ transition: opacity 0.3s ease;
207
+ }
208
+
209
+ /* ---- Empty state ---- */
210
+ .empty {
211
+ margin: 0;
212
+ padding: 2rem;
213
+ text-align: center;
214
+ color: var(--dnd-muted);
215
+ font-size: 1rem;
216
+ }
package/README.md CHANGED
@@ -4,6 +4,10 @@ A collection of reusable React components for e-learning applications.
4
4
 
5
5
  ## Components
6
6
 
7
+ ### Accordion
8
+
9
+ An accessible accordion with collapsible sections. Uses pure CSS for expand/collapse. See `Accordion/README.md` for detailed documentation.
10
+
7
11
  ### FlashcardDeck
8
12
 
9
13
  A fully-featured flashcard component with 3D flip animations. See `FlashcardDeck/README.md` for detailed documentation.
@@ -20,6 +24,14 @@ A drag-and-drop sorting activity component where users reorder items into the co
20
24
 
21
25
  A drag-and-drop matching activity where users match items from one column to the correct targets in another. Uses @dnd-kit/core and pure CSS animations. See `MatchingActivity/README.md` for detailed documentation.
22
26
 
27
+ ### DragAndDropActivity
28
+
29
+ A highly interactive drag-and-drop quiz where users drag items to drop targets. Correct matches snap into place; incorrect drops animate back to the source. Uses interact.js and pure CSS animations. See `DragAndDropActivity/README.md` for detailed documentation.
30
+
31
+ ### BranchingScenario
32
+
33
+ A choose-your-own-path scenario component. Renders narrative nodes with choices and outcomes, tracks path/score/variables, and supports conditional choices. Uses pure CSS for fade and slide transitions. See `BranchingScenario/README.md` for detailed documentation.
34
+
23
35
  ## Getting Started
24
36
 
25
37
  ### Installation
@@ -44,6 +56,10 @@ npm run build
44
56
 
45
57
  ```
46
58
  elearning-components/
59
+ ├── Accordion/ # Accordion component
60
+ │ ├── index.tsx # Component and exports
61
+ │ ├── style.module.css # CSS Modules styles
62
+ │ └── README.md # Documentation
47
63
  ├── FlashcardDeck/ # FlashcardDeck component
48
64
  │ ├── FlashcardDeck.jsx # Component (JavaScript)
49
65
  │ ├── FlashcardDeck.tsx # Component (TypeScript)
@@ -62,6 +78,14 @@ elearning-components/
62
78
  │ ├── index.tsx # Component and exports
63
79
  │ ├── style.module.css # CSS Modules styles
64
80
  │ └── README.md # Documentation
81
+ ├── DragAndDropActivity/ # DragAndDropActivity component
82
+ │ ├── index.tsx # Component and exports
83
+ │ ├── style.module.css # CSS Modules styles
84
+ │ └── README.md # Documentation
85
+ ├── BranchingScenario/ # BranchingScenario component
86
+ │ ├── index.tsx # Component and exports
87
+ │ ├── style.module.css # CSS Modules styles
88
+ │ └── README.md # Documentation
65
89
  ├── src/ # Application source
66
90
  │ ├── App.jsx # Demo app
67
91
  │ └── main.jsx # Entry point
@@ -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}
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_doj4z_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_doj4z_51{margin:0;font-size:.9375rem;color:var(--dnd-muted);line-height:1.5}._layout_doj4z_67{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem;align-items:start}@media(max-width:640px){._layout_doj4z_67{grid-template-columns:1fr}}._column_doj4z_93{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);min-height:200px;transition:border-color .25s ease,box-shadow .25s ease}._columnTitle_doj4z_117{margin:0;font-size:.875rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--dnd-muted)}._list_doj4z_137{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.5rem}._listItem_doj4z_155{position:relative}._item_doj4z_165{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_doj4z_165:active{cursor:grabbing}._item_doj4z_165:hover{border-color:var(--dnd-accent);box-shadow:0 2px 8px #2563eb1f}._itemSnapBack_doj4z_219{transition:transform .4s ease-out}._itemContent_doj4z_227{font-size:1rem;font-weight:500;line-height:1.4;flex:1;pointer-events:none}._target_doj4z_245{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:3.5rem;transition:border-color .25s ease,background-color .25s ease,transform .25s ease,box-shadow .25s ease}._targetOver_doj4z_277{border-style:solid;border-color:var(--dnd-accent);background:var(--dnd-over-bg);transform:scale(1.01);box-shadow:0 2px 12px #2563eb26}._targetCorrect_doj4z_293{border-style:solid;border-color:var(--dnd-success);background:var(--dnd-success-bg);animation:_targetCorrect_doj4z_293 .4s ease-out forwards}._targetIncorrect_doj4z_307{border-style:solid;border-color:var(--dnd-error);background:var(--dnd-error-bg);animation:_targetIncorrect_doj4z_307 .3s ease-out}._targetFilled_doj4z_321{border-style:solid;border-color:var(--dnd-success);background:var(--dnd-success-bg)}@keyframes _targetCorrect_doj4z_293{0%{transform:scale(1.02);box-shadow:0 0 #16a34a66}to{transform:scale(1);box-shadow:0 2px 8px #16a34a33}}@keyframes _targetIncorrect_doj4z_307{0%,to{transform:scale(1)}50%{transform:scale(1.02)}}._targetLabel_doj4z_375{font-size:.875rem;font-weight:600;color:var(--dnd-muted);line-height:1.3}._targetPlaceholder_doj4z_389{font-size:.8125rem;color:var(--dnd-border);font-style:italic}._placedContent_doj4z_401{font-size:1rem;font-weight:500;color:var(--dnd-success);line-height:1.4;transition:opacity .3s ease}._empty_doj4z_419{margin:0;padding:2rem;text-align:center;color:var(--dnd-muted);font-size:1rem}