ui: the unified ThinkingBlock — one visual language for the learner's thinking

Owner round (2026-10-05): the same act (a human thinking in text) had two
visual languages — the quiz cards' quote block vs the practice container
with a collapsing chevron and raw pre-wrap text that read oversized.

- components/thinking-block.tsx: the quiz quote-block recipe verbatim
  (rail + uppercase label + lh-prose at foreground/90) carried by a
  faint user-side shell — ml-auto, max-w-[95%] mirroring the user
  bubble's geometry, px-4/py-3 rhythm. Never collapsible. Rails reuse
  the existing vocabulary: primary = committed register, muted =
  working register.
- ThinkingCard becomes the practice adapter: 'Your solution' (primary)
  / 'Your thinking' (muted) — one component, two registers.
- The reading channel LIFTS out of the answered card: chronologically
  prior to the question, it renders above it as its own user-side
  block under the plain 'Your thinking' label; the in-card inset and
  the 'while reading' phrasing are gone.
- lh-card-enter (globals.css): the one-shot 150ms fade+rise mount,
  the app's motion register; honors reduced-motion.
This commit is contained in:
amosblomqvist
2026-10-05 02:25:13 +03:00
parent 09480979c4
commit d19df86b13
5 changed files with 110 additions and 34 deletions
+26
View File
@@ -530,3 +530,29 @@ body {
@theme {
--font-title: "lh-cmu", serif;
}
/* Card enter (owner round, 2026-10-05): the transcript cards' one-shot
mount — a subtle fade + 4px rise, the app's motion register (150ms,
dock-variant/settings-pop taste). Nothing on update, nothing on
unmount. Applied by the unified ThinkingBlock and the practice
cards; honors reduced-motion by appearing. */
@keyframes lh-card-enter {
from {
opacity: 0;
transform: translateY(4px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.lh-card-enter {
animation: lh-card-enter 150ms ease-out;
}
@media (prefers-reduced-motion: reduce) {
.lh-card-enter {
animation: none;
}
}