+ Tippe auf die Karte oder drücke Leertaste +
+ {/if} +diff --git a/apps/cards/apps/web/src/lib/components/CardFace.svelte b/apps/cards/apps/web/src/lib/components/CardFace.svelte
index 9e14a4161..19d09cf1f 100644
--- a/apps/cards/apps/web/src/lib/components/CardFace.svelte
+++ b/apps/cards/apps/web/src/lib/components/CardFace.svelte
@@ -3,6 +3,19 @@
* CardFace — renders one learnable unit (a single subIndex of a card)
* for any Phase-1 card type. Stateless: the parent owns `showBack`,
* `typedAnswer`, and any timing.
+ *
+ * Card-feel design (Phase A polish):
+ * - Single surface that physically flips on Y axis when revealed.
+ * Both faces share a CSS-grid cell so the parent height is the
+ * max of front/back, no jumpy reflow on flip.
+ * - Tap anywhere on the surface reveals (only while `showBack` is
+ * false). The /learn page keeps the keyboard space/enter shortcut.
+ * - `prefers-reduced-motion: reduce` collapses the rotateY into an
+ * instant cross-fade — same affordance, no vestibular trigger.
+ *
+ * Type-in cards skip the flip: the input field doesn't make sense on
+ * a flippable face, so we keep the historical "input + answer below"
+ * layout for that single card type.
*/
import { renderCloze, renderMarkdown, type Card } from '@mana/cards-core';
@@ -13,9 +26,10 @@
showBack: boolean;
typedAnswer?: string;
onTypedAnswer?: (value: string) => void;
+ onReveal?: () => void;
}
- let { card, subIndex, showBack, typedAnswer = '', onTypedAnswer }: Props = $props();
+ let { card, subIndex, showBack, typedAnswer = '', onTypedAnswer, onReveal }: Props = $props();
const view = $derived.by(() => {
switch (card.type) {
@@ -54,34 +68,127 @@
const matched = $derived(
isTypeIn && typedAnswer.trim().toLowerCase() === view.expected.trim().toLowerCase()
);
+
+ function tryReveal() {
+ if (!showBack && !isTypeIn) onReveal?.();
+ }
-
+ Tippe auf die Karte oder drücke Leertaste
+