/* practice_word.css – extracted from practice_word.html.erb inline <style> */

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }
}
@keyframes success-pop {
  0%   { transform: scale(1);   box-shadow: 0 0 0 0 rgba(74,222,128,0); }
  40%  { transform: scale(1.03); box-shadow: 0 0 30px 6px rgba(74,222,128,0.35); }
  100% { transform: scale(1);   box-shadow: 0 0 0 0 rgba(74,222,128,0); }
}
/* Glow the continuous match line only — never scale the slot row (that resurfaces per-letter borders). */
@keyframes letter-match-success {
  0%, 100% {
    box-shadow: 0 0 8px rgb(52 211 153 / 0.28);
  }
  45% {
    box-shadow: 0 0 18px rgb(52 211 153 / 0.55);
  }
}
@keyframes feedback-glow {
  0%   { text-shadow: 0 0 0 rgba(74,222,128,0); }
  50%  { text-shadow: 0 0 16px rgba(74,222,128,0.6); }
  100% { text-shadow: 0 0 0 rgba(74,222,128,0); }
}
@keyframes chunk-pop {
  0% { opacity: 0; }
  100% { opacity: 1; }
}
.input-shake { animation: shake 0.4s ease-in-out; }

/* #answer-hint / #feedback-text overlay rules live with #word-input-dock below */

.input-success { animation: success-pop 0.5s ease-out; }
/* Letter slots: suppress scale pop — keep a single continuous underline. */
.word-letter-slots.input-success {
  animation: none;
  box-shadow: none;
}
.feedback-success { animation: feedback-glow 0.6s ease-out; }
#answer-presentation {
  max-height: min(38vh, 16rem);
}
#answer-presentation .answer-token-gloss {
  max-width: 8.5rem;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: break-word;
}
/* cn_to_en: Chinese + phonetic + input as one vertically centered composition */
#word-practice-stage {
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 0;
}
/* ID selector beats Tailwind .hidden — must force collapse when phrase step takes over */
#word-practice-stage.hidden {
  display: none !important;
}
#practice-word-header {
  margin-bottom: 0;
}
/* Wrong-answer overlays: never affect flex centering / cause stage jitter */
#word-input-dock {
  position: relative;
  z-index: 1;
  /* Tight gap under phonetic; quill clearance comes from #word-input-wrapper padding */
  margin-top: 1.35rem;
  width: 100%;
  max-width: 100%;
  overflow: visible;
}
#answer-hint {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 0.35rem);
  transform: translateX(-50%);
  width: min(100%, 48rem);
  margin: 0;
  padding: 0 0.75rem;
  min-height: 0;
  display: flex !important;
  align-items: flex-end;
  justify-content: center;
  z-index: 6;
  pointer-events: none;
}
#answer-hint.hidden {
  visibility: hidden;
  opacity: 0;
  /* Stay out of layout even while “shown” sizing changes — absolute already */
  pointer-events: none;
}
#answer-hint:not(.hidden) {
  visibility: visible;
  opacity: 1;
}
#feedback-text {
  position: absolute;
  left: 50%;
  top: calc(100% + 0.35rem);
  transform: translateX(-50%);
  width: min(100%, 48rem);
  margin: 0;
  padding: 0 0.75rem;
  min-height: 1.75rem;
  text-align: center;
  z-index: 6;
  pointer-events: none;
}
#feedback-text:empty {
  visibility: hidden;
}
#word-practice-form,
#word-input-wrapper {
  max-width: min(100%, 72rem);
}
#practice-word-header.listening-stable {
  min-height: 9rem;
  cursor: pointer;
  padding-top: 0;
}
#practice-word-header.listening-stable #prompt-title {
  min-height: 2.75rem;
}
#practice-word-header.listening-stable #phonetic-text {
  min-height: 1.75rem;
}
#practice-word-header.listening-stable #translation-summary {
  min-height: 2.75rem;
}
#practice-word-header.listening-stable .listening-slot-empty {
  visibility: hidden;
}
#listening-options {
  align-content: start;
}
#listening-options .listening-choice {
  min-height: 4.5rem;
  max-height: 160px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(56, 189, 248, 0.45) transparent;
}
#listening-options .listening-choice::-webkit-scrollbar {
  width: 4px;
}
#listening-options .listening-choice:hover {
  border-color: rgba(56, 189, 248, 0.5);
  background: rgba(56, 189, 248, 0.1);
}
.line-clamp-4 {
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
@keyframes flash-correct {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}
.flash-correct {
  animation: flash-correct 1s ease-in-out 3;
}
#top-progress-bar { transition: width 0.5s ease; }

/* ── 清爽深色主题（练习页） ── */
#immersive-practice-shell {
  --practice-bg: #0c1117;
  --practice-surface: rgba(255, 255, 255, 0.035);
  --practice-surface-2: rgba(255, 255, 255, 0.055);
  --practice-border: rgba(255, 255, 255, 0.08);
  --practice-border-hover: rgba(56, 189, 248, 0.38);
  --practice-text: #eef2f6;
  --practice-text-muted: #94a3b8;
  --practice-text-dim: #64748b;
  --practice-accent: #38bdf8;
  --practice-accent-soft: rgba(56, 189, 248, 0.12);
  --practice-accent-border: rgba(56, 189, 248, 0.32);
  --practice-teal: #2dd4bf;
  --practice-stat-num: #e2e8f0;
  color: var(--practice-text);
  background: var(--practice-bg);
  isolation: isolate;
}
#immersive-practice-shell::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 70% 45% at 50% -8%, rgba(56, 189, 248, 0.07), transparent 58%),
    radial-gradient(ellipse 55% 38% at 100% 100%, rgba(45, 212, 191, 0.05), transparent 52%),
    linear-gradient(180deg, #10161d 0%, #0c1117 100%);
}
.practice-top-card,
.practice-side-card,
.practice-stage-card {
  border: 1px solid var(--practice-border);
  background: var(--practice-surface);
  backdrop-filter: blur(16px);
  box-shadow: 0 20px 60px -48px rgba(0, 0, 0, 0.55);
}
.practice-stage-card {
  box-shadow: 0 24px 70px -52px rgba(0, 0, 0, 0.6);
}
.practice-stage-inner {
  border: 1px solid rgba(255, 255, 255, 0.06);
  background: rgba(0, 0, 0, 0.18);
  border-radius: 2rem;
}
.practice-mode-chip {
  border: 1px solid var(--practice-accent-border);
  background: var(--practice-accent-soft);
  color: #7dd3fc;
}
.practice-scope-chip {
  border: 1px solid var(--practice-border);
  background: var(--practice-surface-2);
  color: var(--practice-text-muted);
}
#immersive-practice-shell .stat-box {
  border: 1px solid var(--practice-border);
  background: var(--practice-surface);
}
#immersive-practice-shell .stat-box p:last-child,
#immersive-practice-shell #session-timer {
  color: var(--practice-stat-num);
}
#immersive-practice-shell header a.flex.h-12 {
  border: 1px solid var(--practice-border);
  background: var(--practice-surface-2);
  color: var(--practice-text);
}
#immersive-practice-shell header a.flex.h-12:hover {
  border-color: var(--practice-border-hover);
  background: rgba(255, 255, 255, 0.08);
}
#immersive-practice-shell header .mt-5.h-2 {
  background: rgba(255, 255, 255, 0.07);
}
.practice-progress-bar {
  background: linear-gradient(90deg, #0ea5e9 0%, #38bdf8 55%, #2dd4bf 100%);
}
.practice-side-section {
  border: 1px solid rgba(255, 255, 255, 0.06);
  background: rgba(0, 0, 0, 0.14);
}
.practice-side-inner {
  border: 1px solid rgba(255, 255, 255, 0.06);
  background: var(--practice-surface);
}
.practice-side-label {
  color: var(--practice-text-dim);
}
.practice-side-btn {
  border: 1px solid var(--practice-border);
  background: var(--practice-surface-2);
  color: var(--practice-text);
}
.practice-side-btn:hover {
  border-color: var(--practice-border-hover);
}
.practice-translation-summary {
  position: relative;
  z-index: 8;
  max-width: 36rem;
  padding: 0 1rem;
  font-size: 1.375rem;
  font-weight: 500;
  line-height: 1.55;
  letter-spacing: 0.01em;
  color: #e2e8f0;
  overflow: visible;
  text-align: center;
  word-break: break-word;
}
@media (min-width: 640px) {
  .practice-translation-summary {
    font-size: 1.5rem;
  }
}
.practice-gloss {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
}
.practice-gloss-primary {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: 0.35rem 0.55rem;
}
.practice-gloss-pos {
  font-size: 0.78em;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #94a3b8;
}
.practice-gloss-main {
  font-weight: 600;
  color: #f1f5f9;
}
.practice-gloss-more-wrap {
  position: relative;
  display: inline-flex;
  justify-content: center;
}
.practice-gloss-more {
  margin: 0.15rem 0 0;
  padding: 0.15rem 0.35rem;
  border: 0;
  background: transparent;
  color: #64748b;
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.3;
  cursor: pointer;
  transition: color 0.15s ease;
}
.practice-gloss-more-wrap:hover .practice-gloss-more,
.practice-translation-summary.is-open .practice-gloss-more {
  color: #94a3b8;
}
.practice-gloss-popover {
  position: fixed;
  z-index: 80;
  max-height: min(42vh, 16rem);
  overflow-x: hidden;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  padding: 0.8rem 0.95rem;
  border-radius: 0.9rem;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(12, 14, 18, 0.97);
  box-shadow: 0 18px 48px -24px rgba(0, 0, 0, 0.85);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  text-align: left;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.14s ease, visibility 0.14s ease;
  scrollbar-width: thin;
}
.practice-translation-summary.is-open .practice-gloss-popover,
body.practice-gloss-popover-open [data-gloss-popover-root="1"] {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}
.practice-gloss-sense {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.3rem 0.45rem;
  font-size: 0.9rem;
  line-height: 1.45;
  color: #94a3b8;
  font-weight: 450;
}
.practice-gloss-sense.is-primary {
  color: #e2e8f0;
  font-weight: 600;
}
.practice-word-header,
#word-practice-stage,
.practice-stage-inner {
  overflow: visible;
}
.practice-phonetic-label {
  font-size: 1.0625rem;
  font-weight: 400;
  letter-spacing: 0.04em;
  color: #7dd3fc;
  opacity: 0.88;
}
@media (min-width: 640px) {
  .practice-phonetic-label {
    font-size: 1.125rem;
  }
}
.practice-word-input {
  border: 1px solid var(--practice-border);
  background: rgba(255, 255, 255, 0.06);
  color: var(--practice-text);
}
.practice-word-input:focus {
  border-color: var(--practice-border-hover);
  box-shadow: 0 0 0 4px rgba(56, 189, 248, 0.12);
}
.practice-inline-input {
  border: 1px solid var(--practice-border);
  background: rgba(255, 255, 255, 0.06);
  color: var(--practice-text);
}
.practice-inline-input:focus {
  border-color: var(--practice-border-hover);
  box-shadow: 0 0 0 2px rgba(56, 189, 248, 0.12);
  outline: none;
}
.practice-word-input:empty::before {
  color: var(--practice-text-dim);
}

/* Per-letter underline input (aligned with phrase blank style) */
#word-input-wrapper {
  min-height: 5.75rem;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 1.85rem 0 1rem;
}
.word-letter-slots {
  --letter-slot-gap: 0.18rem;
  position: relative;
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-end;
  justify-content: center;
  gap: var(--letter-slot-gap);
  width: 100%;
  max-width: min(100%, 72rem);
  min-height: 4.25rem;
  margin: 0 auto;
  pointer-events: auto;
  z-index: 2;
}
.word-letter-slot {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  min-width: 1.7rem;
  height: 3.75rem;
  padding: 0 0.08rem 0.2rem;
  border-bottom: 3px solid rgb(156 163 175);
  border-radius: 2px;
  box-sizing: border-box;
  /* No border-color transition — toggling matched must not flash underlines. */
  transition: color 0.12s ease;
}
.word-letter-slot.is-space {
  min-width: 1.1rem;
  border-bottom-color: transparent;
  pointer-events: none;
}
.word-letter-slot.is-hyphen {
  min-width: 1.25rem;
}
.word-letter-slot.is-active {
  border-bottom-color: #38bdf8;
}
.word-letter-slot.is-filled {
  border-bottom-color: rgb(148 163 184 / 0.7);
}
/* Matched prefix: only the continuous .letter-match-line is visible (no per-slot borders). */
.word-letter-slot.is-matched,
.word-letter-slot.is-matched.is-active {
  border-bottom-color: transparent;
}
.word-letter-slot.is-mismatch {
  border-bottom-color: rgb(251 146 60 / 0.95);
}
.word-letter-slot.is-mismatch .word-letter-glyph {
  color: rgb(251 146 60);
}
.word-letter-slot.is-active.is-filled:not(.is-matched):not(.is-mismatch) {
  border-bottom-color: #38bdf8;
}
.word-letter-glyph {
  display: block;
  position: relative;
  z-index: 2;
  font-size: 2.5rem;
  font-weight: 800;
  line-height: 1;
  color: var(--practice-text);
  user-select: none;
}
.jlb-letter-compact,
.word-letter-compact {
  position: relative;
  display: inline-flex;
  flex-wrap: nowrap;
  align-items: flex-end;
  justify-content: center;
  gap: 0;
  min-width: 0;
  height: 3.75rem;
  padding: 0 0.12rem 0.2rem;
  border-bottom: 3px solid rgb(52 211 153);
  border-radius: 2px;
  box-sizing: border-box;
  font-size: 2.5rem;
  font-weight: 800;
  line-height: 1;
  color: var(--practice-text, #f8fafc);
  letter-spacing: 0;
  white-space: nowrap;
}
.jlb-letter-compact-glyph,
.word-letter-compact-glyph {
  display: inline;
  position: relative;
  z-index: 1;
}
.jlb-blank.is-filled .jlb-letter-compact,
.jlb-blank.phrase-blank-success .jlb-letter-compact,
.word-letter-slots.is-compact .word-letter-compact {
  border-bottom-color: rgb(52 211 153);
}
.word-letter-slots.is-success .word-letter-slot,
.word-letter-slots.is-success .word-letter-slot.is-matched,
.word-letter-slots.is-success .word-letter-slot.is-active {
  border-bottom-color: transparent;
}
.word-letter-slots.has-mismatch .word-letter-slot.is-mismatch {
  border-bottom-color: rgb(251 146 60 / 0.98);
}
.letter-match-line {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 3px;
  border-radius: 999px;
  background: #34d399;
  box-shadow: 0 0 8px rgb(52 211 153 / 0.28);
  pointer-events: none;
  z-index: 3;
  opacity: 1;
  transform-origin: center;
  transition: width 0.12s ease-out;
}
.word-letter-slots.is-success .letter-match-line.is-on,
.word-letter-slots .letter-match-line.is-success-pop {
  animation: letter-match-success 0.45s ease-out;
}
.word-letter-capture {
  position: absolute;
  inset: 0;
  z-index: 3;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
  color: transparent !important;
  caret-color: transparent;
  opacity: 0;
  overflow: hidden;
  white-space: nowrap !important;
  word-break: normal !important;
  -webkit-text-fill-color: transparent;
}
.word-letter-capture:focus {
  border: 0 !important;
  box-shadow: none !important;
}
.word-letter-capture:empty::before {
  content: none !important;
}
@media (min-width: 640px) {
  .word-letter-slot {
    min-width: 2.15rem;
    height: 4.85rem;
  }
  .word-letter-glyph {
    font-size: 3.35rem;
  }
  .jlb-letter-compact,
  .word-letter-compact {
    height: 4.85rem;
    font-size: 3.35rem;
  }
  .word-letter-slots {
    --letter-slot-gap: 0.22rem;
    gap: var(--letter-slot-gap);
    min-height: 5.25rem;
    max-width: min(100%, 72rem);
  }
  #word-input-wrapper {
    min-height: 7rem;
    padding: 2rem 0 1.15rem;
  }
}
.practice-phrase-zh {
  max-width: 36rem;
  font-size: 1.25rem;
  font-weight: 500;
  line-height: 1.6;
  color: #e2e8f0;
}
@media (min-width: 640px) {
  .practice-phrase-zh {
    font-size: 1.375rem;
  }
}

/* Phrase step after word: vertically center zh + blanks as one composition */
#word-phrase-step {
  width: 100%;
  min-height: 0;
}
#word-phrase-step.hidden {
  display: none !important;
}
#word-phrase-step:not(.hidden) {
  display: flex !important;
  flex: 1 1 auto;
  flex-direction: column;
  justify-content: center;
  min-height: 0;
}
.practice-stage-inner.is-phrase-step {
  justify-content: center;
}
.word-phrase-compose {
  width: 100%;
  max-width: 100%;
  flex: 0 1 auto;
  gap: 1.35rem;
  /* Optical lift: absolute token meta under blanks makes the group feel low */
  transform: translateY(-8%);
}
#word-phrase-blanks.phrase-dictation-blanks {
  margin-top: 0;
  min-height: 0;
  /* Reserve room for absolute phonetic/zh under each blank between wrapped rows */
  padding-bottom: 2.4rem;
  align-items: flex-start;
  row-gap: 2.85rem;
  column-gap: 0.85rem;
}
#word-phrase-blanks .jlb-blank {
  margin-bottom: 0;
}
#word-phrase-blanks .jlb-blank.has-letter-slots {
  padding-top: 1.15rem;
  /* Keep padding-bottom tiny so token-meta (top:100%) sits near the underline */
  padding-bottom: 0.15rem;
}
#word-phrase-blanks .jlb-blank.is-wrong.has-letter-slots {
  margin-top: 0;
  padding-top: 1.15rem;
  padding-bottom: 0.15rem;
}
/* Keep wrong-word hint inside the blank so it never overlaps the previous row's gloss */
#word-phrase-blanks .jlb-blank .jlb-hint {
  top: 0.05rem;
  bottom: auto;
}
#word-phrase-blanks .jlb-token-meta {
  top: calc(100% + 0.1rem);
  gap: 0.1rem;
  min-height: 0;
}
#word-phrase-feedback.word-phrase-feedback {
  margin-top: 0;
  margin-bottom: 0.15rem;
  min-height: 0;
}
#word-phrase-feedback.word-phrase-feedback:empty {
  display: none;
}
#word-phrase-feedback.word-phrase-feedback.is-revealed {
  display: block;
  color: rgb(52 211 153);
  font-weight: 700;
  line-height: 1.35;
}
@media (min-width: 768px) {
  .word-phrase-compose {
    gap: 1.6rem;
    transform: translateY(-7%);
  }
  #word-phrase-blanks.phrase-dictation-blanks {
    padding-bottom: 2.6rem;
    row-gap: 3.1rem;
  }
  #word-phrase-blanks .jlb-token-meta {
    top: calc(100% + 0.12rem);
    gap: 0.12rem;
  }
}
.practice-accent-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  color: #fff;
  background: linear-gradient(90deg, #0ea5e9 0%, #38bdf8 55%, #2dd4bf 100%);
  box-shadow: 0 12px 32px -16px rgba(56, 189, 248, 0.55);
  transition: filter 0.15s ease;
}
.practice-accent-btn:hover {
  filter: brightness(1.06);
}
.practice-brand-gradient {
  background: linear-gradient(90deg, #7dd3fc, #67e8f9, #5eead4);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
.auto-play-active {
  border-color: var(--practice-accent-border) !important;
  background-color: var(--practice-accent-soft) !important;
  color: #7dd3fc !important;
  box-shadow: 0 0 10px 0 rgba(56, 189, 248, 0.14);
}
.jlb-blank.is-active {
  color: #38bdf8;
  border-bottom-color: #38bdf8;
}
.writing-instrument-option.is-selected {
  border-color: rgba(56, 189, 248, 0.75);
  background: linear-gradient(135deg, rgba(56, 189, 248, 0.14), rgba(15, 23, 42, 0.72));
  box-shadow: 0 0 0 1px rgba(56, 189, 248, 0.18), 0 18px 36px rgba(14, 116, 144, 0.16);
}
#speaking-wave span {
  animation: speaking-wave 1.1s ease-in-out infinite;
  transform-origin: bottom center;
}
#speaking-wave span:nth-child(2n) { animation-delay: 0.15s; }
#speaking-wave span:nth-child(3n) { animation-delay: 0.3s; }
#speaking-wave span:nth-child(4n) { animation-delay: 0.45s; }
#speaking-wave:not(.recording-active) span {
  animation-play-state: paused;
  opacity: 0.45;
  transform: scaleY(0.45);
}
#speaking-wave.recording-active span {
  opacity: 1;
}
@keyframes speaking-wave {
  0%, 100% { transform: scaleY(0.3); }
  50% { transform: scaleY(1); }
}

/* ── 练习完成庆祝 ── */
@keyframes celebration-glow {
  0%, 100% { text-shadow: 0 0 12px rgba(251,191,36,0.3); }
  50% { text-shadow: 0 0 28px rgba(251,191,36,0.6), 0 0 56px rgba(251,191,36,0.15); }
}
.celebration-title {
  background: linear-gradient(135deg, #fbbf24, #f59e0b, #fcd34d);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  animation: celebration-glow 2.5s ease-in-out infinite;
}
.celebration-subtitle {
  color: #fde68a;
}
#practice-complete-celebration {
  position: absolute;
  inset: 0;
  z-index: 10;
}
.confetti-piece {
  position: absolute;
  width: 8px;
  height: 12px;
  top: -20px;
  opacity: 0;
  animation: confetti-fall linear forwards;
}
@keyframes confetti-fall {
  0%   { transform: translateY(0) rotate(0deg) scale(1); opacity: 1; }
  25%  { opacity: 1; }
  100% { transform: translateY(var(--fall-distance, 600px)) rotate(var(--rotation, 720deg)) scale(0.4); opacity: 0; }
}

/* ── 连击动画 ── */
@keyframes streak-pop {
  0% { transform: scale(0.5); opacity: 0; }
  50% { transform: scale(1.3); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes flame-dance {
  0%, 100% { transform: translateY(0) scale(1); }
  25% { transform: translateY(-10px) scale(1.05); }
  50% { transform: translateY(-5px) scale(1.1); }
  75% { transform: translateY(-15px) scale(1.08); }
}
@keyframes streak-milestone {
  0% { transform: scale(0); opacity: 0; }
  30% { transform: scale(1.5); opacity: 1; }
  60% { transform: scale(0.9); }
  100% { transform: scale(1); opacity: 0; }
}
.streak-pop { animation: streak-pop 0.4s ease-out; }
.streak-flame { animation: flame-dance 0.6s ease-in-out infinite; }
.streak-milestone { animation: streak-milestone 1.2s ease-out forwards; }

/* ── 羽毛笔写字动画 ── */
@keyframes quill-idle-float {
  0%, 100% { transform: translate(-50%, -50%) translate3d(var(--quill-x, 0px), var(--quill-y, 0px), 0) rotate(-23deg) scale(1); }
  50% { transform: translate(-50%, -50%) translate3d(var(--quill-x, 0px), calc(var(--quill-y, 0px) - 6px), 0) rotate(-19deg) scale(1.01); }
}
@keyframes quill-stroke-beat {
  0% { transform: translate(-50%, -50%) translate3d(var(--quill-x, 0px), var(--quill-y, 0px), 0) rotate(-22deg) scale(1); }
  28% { transform: translate(-50%, -50%) translate3d(calc(var(--quill-x, 0px) + 8px), calc(var(--quill-y, 0px) + 11px), 0) rotate(-6deg) scale(1.04); }
  58% { transform: translate(-50%, -50%) translate3d(calc(var(--quill-x, 0px) - 2px), calc(var(--quill-y, 0px) - 2px), 0) rotate(-30deg) scale(1); }
  100% { transform: translate(-50%, -50%) translate3d(var(--quill-x, 0px), var(--quill-y, 0px), 0) rotate(-22deg) scale(1); }
}
@keyframes quill-celebration {
  0% { transform: translate(-50%, -50%) translate3d(var(--quill-x, 0px), var(--quill-y, 0px), 0) rotate(-22deg) scale(1); }
  28% { transform: translate(-50%, -50%) translate3d(calc(var(--quill-x, 0px) + 20px), calc(var(--quill-y, 0px) - 18px), 0) rotate(18deg) scale(1.08); }
  55% { transform: translate(-50%, -50%) translate3d(calc(var(--quill-x, 0px) - 10px), calc(var(--quill-y, 0px) - 20px), 0) rotate(-38deg) scale(1.05); }
  100% { transform: translate(-50%, -50%) translate3d(var(--quill-x, 0px), var(--quill-y, 0px), 0) rotate(-22deg) scale(1); }
}
@keyframes quill-aura-pulse {
  0%, 100% { opacity: 0.3; transform: scale(0.92); }
  50% { opacity: 0.72; transform: scale(1.08); }
}
@keyframes quill-feather-flicker {
  0%, 100% { transform: translateX(0) rotate(0deg); }
  50% { transform: translateX(2px) rotate(2deg); }
}
@keyframes quill-scratch-flash {
  0% { opacity: 0; transform: scaleX(0.2) scaleY(0.7); }
  35% { opacity: 0.85; transform: scaleX(1) scaleY(1); }
  100% { opacity: 0; transform: scaleX(1.2) scaleY(0.35); }
}
@keyframes ink-fade {
  0% { opacity: 0.95; transform: translate3d(0, 0, 0) scale(0.9); }
  100% { opacity: 0; transform: translate3d(var(--ink-dx, 0px), var(--ink-dy, 18px), 0) scale(0.25); }
}
.quill-container {
  --quill-x: 0px;
  --quill-y: 0px;
  --scratch-width: 22px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 56px;
  height: 56px;
  pointer-events: none;
  z-index: 20;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.writing-instrument-caretless {
  caret-color: transparent;
}
.quill-container.visible {
  opacity: 1;
}
.quill-container.idle {
  animation: quill-idle-float 2.8s ease-in-out infinite;
}
.quill-container.writing {
  animation: quill-stroke-beat 0.26s cubic-bezier(0.28, 0.84, 0.42, 1) 1;
}
.quill-container.flourish {
  animation: quill-celebration 0.7s ease-out 1;
}
.quill-aura {
  position: absolute;
  left: 29%;
  top: 32%;
  width: 53%;
  height: 32%;
  border-radius: 999px;
  background: radial-gradient(circle, rgba(251, 191, 36, 0.22), rgba(139, 92, 246, 0.06) 62%, transparent 85%);
  filter: blur(8px);
  opacity: 0;
}
.quill-container.visible .quill-aura {
  opacity: 0.6;
}
.quill-container.writing .quill-aura,
.quill-container.flourish .quill-aura {
  animation: quill-aura-pulse 0.32s ease-out;
}
.quill-graphic {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: visible;
  filter: drop-shadow(0 16px 26px rgba(15, 23, 42, 0.34));
}
.quill-container.writing .quill-graphic,
.quill-container.flourish .quill-graphic {
  filter: drop-shadow(0 0 14px rgba(250, 204, 21, 0.32)) drop-shadow(0 18px 26px rgba(15, 23, 42, 0.38));
}
.quill-feather-main {
  stroke: rgba(126, 89, 38, 0.16);
  stroke-width: 1.2;
}
.quill-container.writing .quill-feather-main,
.quill-container.flourish .quill-feather-main {
  animation: quill-feather-flicker 0.24s ease-out;
}
.quill-feather-highlight,
.quill-feather-ridge,
.quill-feather-barb {
  transform-origin: 74% 28%;
}
.quill-container.writing .quill-feather-highlight,
.quill-container.writing .quill-feather-ridge,
.quill-container.writing .quill-feather-barb,
.quill-container.flourish .quill-feather-highlight,
.quill-container.flourish .quill-feather-ridge,
.quill-container.flourish .quill-feather-barb {
  animation: quill-feather-flicker 0.24s ease-out;
}
.quill-scratch {
  position: absolute;
  left: 8%;
  bottom: 6%;
  width: var(--scratch-width);
  height: 5px;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(255, 244, 214, 0), rgba(255, 244, 214, 0.92) 35%, rgba(216, 180, 74, 0.9) 70%, rgba(124, 58, 237, 0.15));
  filter: blur(0.2px) drop-shadow(0 0 6px rgba(250, 204, 21, 0.28));
  transform-origin: left center;
  opacity: 0;
}
.quill-container.writing .quill-scratch,
.quill-container.flourish .quill-scratch {
  animation: quill-scratch-flash 0.24s ease-out;
}
.ink-particle {
  position: absolute;
  left: 0;
  top: 0;
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: radial-gradient(circle, rgba(255, 248, 219, 0.95) 0%, rgba(212, 183, 124, 0.66) 55%, rgba(124, 58, 237, 0.08) 100%);
  box-shadow: 0 0 8px rgba(250, 204, 21, 0.32);
  animation: ink-fade 0.48s ease-out forwards;
  pointer-events: none;
}
.quill-container[data-instrument="fountain"] .quill-aura {
  background: radial-gradient(circle, rgba(56, 189, 248, 0.24), rgba(14, 165, 233, 0.08) 62%, transparent 86%);
}
.quill-container[data-instrument="brush"] .quill-aura {
  background: radial-gradient(circle, rgba(251, 191, 36, 0.22), rgba(239, 68, 68, 0.08) 62%, transparent 86%);
}
.quill-container[data-instrument="wand"] .quill-aura {
  background: radial-gradient(circle, rgba(196, 181, 253, 0.28), rgba(167, 139, 250, 0.12) 60%, transparent 88%);
}
.quill-container[data-instrument="pencil"] .quill-aura {
  background: radial-gradient(circle, rgba(250, 204, 21, 0.18), rgba(148, 163, 184, 0.08) 62%, transparent 86%);
}
.quill-container[data-instrument="crystal"] .quill-aura {
  background: radial-gradient(circle, rgba(103, 232, 249, 0.26), rgba(129, 140, 248, 0.12) 58%, transparent 88%);
}
.writing-instrument-option.is-selected .writing-instrument-check {
  display: inline-flex;
}
.writing-instrument-thumb {
  isolation: isolate;
}
#current-writing-instrument-preview {
  position: relative;
  overflow: hidden;
}
#current-writing-instrument-preview svg,
.writing-instrument-option-preview svg {
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  display: block;
  object-fit: contain;
}
#current-writing-instrument-preview .quill-graphic,
.writing-instrument-option-preview .quill-graphic {
  filter: none;
  transform: scale(0.55);
  transform-origin: center;
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
}
.writing-instrument-option-preview {
  display: flex;
  height: 3.5rem;
  width: 3.5rem;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border-radius: 0.75rem;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(15, 23, 42, 0.8);
  padding: 0.35rem;
}
.writing-instrument-modal {
  position: fixed;
  inset: 0;
  z-index: 2147483647;
  isolation: isolate;
  background: rgba(2, 6, 23, 0.84);
  backdrop-filter: blur(22px) saturate(0.72);
  opacity: 0;
  transition: opacity 0.22s ease;
}
.writing-instrument-modal.is-open {
  opacity: 1;
}
.writing-instrument-modal-panel {
  position: relative;
  z-index: 1;
  max-height: min(82vh, 52rem);
  overflow-y: auto;
  transform: translateY(18px) scale(0.97);
  opacity: 0;
  transition: transform 0.22s ease, opacity 0.22s ease;
}
.writing-instrument-modal.is-open .writing-instrument-modal-panel {
  transform: translateY(0) scale(1);
  opacity: 1;
}
.writing-instrument-option-preview,
#current-writing-instrument-preview {
  position: relative;
}
.writing-instrument-option-preview svg,
#current-writing-instrument-preview svg {
  overflow: hidden;
}
.instrument-preview-graphic {
  width: 100%;
  height: 100%;
  overflow: visible;
}
@media (max-width: 640px) {
  .quill-container {
    width: 48px;
    height: 48px;
  }
  #word-input-dock {
    margin-top: 1.1rem;
  }
}

@media (min-width: 641px) {
  #word-input-dock {
    margin-top: 1.65rem;
  }
}

/* ── 练习主布局：平板起就左右分栏，练习框占主位 ── */
body.practice-immersive,
body.practice-immersive main {
  height: 100dvh;
  max-height: 100dvh;
  overflow: hidden;
  overscroll-behavior: none;
}
#immersive-practice-shell {
  height: 100dvh;
  max-height: 100dvh;
  min-height: 0;
  overflow: hidden;
}
.practice-shell-inner {
  height: 100%;
  min-height: 0;
  overflow: hidden;
  display: grid;
  width: 100%;
  gap: 1.5rem;
  grid-template-columns: 1fr;
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  grid-template-areas:
    "header"
    "stage"
    "aside"
    "footer";
}
.practice-shell-inner > header {
  grid-area: header;
}
.practice-shell-aside {
  grid-area: aside;
  min-height: 0;
}
.practice-shell-stage {
  grid-area: stage;
}
.practice-shell-footer {
  grid-area: footer;
}
#practice-shortcuts-footer {
  position: relative;
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  padding: 0.75rem 1.5rem 3rem;
  font-size: 0.875rem;
}
.jlb-kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgb(75 85 99);
  border-radius: 0.375rem;
  background: transparent;
  padding: 0.2rem 0.55rem;
  font-size: 0.75rem;
  color: rgb(229 231 235);
  min-width: 1.75rem;
}
.jlb-kbd.is-enter {
  border-color: rgb(209 213 219);
  color: #fff;
}
#practice-shortcuts-footer .practice-touch-btn {
  border: none;
  background: transparent;
  cursor: pointer;
}
#practice-shortcuts-footer .practice-touch-btn.is-primary {
  background: linear-gradient(90deg, #0ea5e9 0%, #38bdf8 55%, #2dd4bf 100%);
  border: 1px solid transparent;
  border-radius: 0.75rem;
  padding: 0.5rem 1rem;
  color: #fff;
  font-weight: 700;
}
#practice-shortcuts-footer .practice-touch-btn.is-primary:hover {
  filter: brightness(1.06);
  color: #fff;
}
#practice-shortcuts-footer .practice-touch-btn.is-primary .text-gray-400 {
  color: rgba(255, 255, 255, 0.85);
}
@media (min-width: 700px) {
  .practice-shell-inner {
    grid-template-columns: minmax(200px, 0.3fr) minmax(0, 0.7fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "header header"
      "aside stage"
      ". footer";
  }
  .practice-shell-aside {
    min-height: 0;
    overflow-y: auto;
    align-self: stretch;
  }
}

/* ── 移动端布局适配（窄屏才叠放，iPad 走电脑左右栏） ── */
.aside-toggle {
  display: none;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  cursor: pointer;
  background: none;
  border: none;
  color: inherit;
  padding: 0;
}
.aside-toggle .toggle-chevron {
  transition: transform 0.2s ease;
}
.practice-aside.is-expanded .aside-toggle .toggle-chevron {
  transform: rotate(180deg);
}
@media (max-width: 699px) {
  /* aside 折叠为紧凑面板，放到练习框下方 */
  .practice-aside {
    padding: 1rem;
    border-radius: 1.25rem;
    overflow: visible;
  }
  .practice-aside .aside-body {
    display: none;
  }
  .practice-aside.is-expanded .aside-body {
    display: grid;
  }
  .practice-aside .aside-toggle {
    display: flex;
  }
  /* header 统计面板精简 */
  .practice-header-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.5rem;
    width: 100%;
  }
  .practice-header-stats .stat-box-hide-mobile {
    display: none;
  }
  .practice-header-stats .stat-box {
    padding: 0.5rem 0.75rem;
  }
}

/* iPad / 矮屏横屏：压缩顶栏，保证练习框首屏可见 */
@media (min-width: 700px) and (max-height: 920px) {
  .practice-shell-inner {
    padding-top: 0.75rem;
    padding-bottom: 0.75rem;
  }
  #immersive-practice-shell header {
    padding: 0.75rem 1.1rem;
    border-radius: 1.5rem;
  }
  #immersive-practice-shell header h1 {
    margin-top: 0.35rem;
    font-size: 1.45rem;
  }
  #immersive-practice-shell header .mt-5 {
    margin-top: 0.65rem;
  }
  .practice-aside {
    padding: 1.05rem;
  }
}

/* Syllable chunk display */
.chunk-display {
  pointer-events: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 4px;
  font-size: 2.2rem;
  font-weight: 900;
  letter-spacing: 0.02em;
  line-height: 1.2;
}
.chunk-display .chunk {
  display: inline-block;
  padding: 2px 6px;
  border-radius: 8px;
  background: rgba(255,255,255,0.08);
  animation: chunk-pop 0.3s ease-out;
  transition: transform 0.15s ease;
}
.chunk-display .chunk:hover {
  transform: scale(1.08);
}
.chunk-display .chunk-phonetic {
  display: block;
  font-size: 0.55em;
  font-weight: 500;
  opacity: 0.5;
  text-align: center;
  margin-top: 1px;
  font-style: italic;
}
.chunk-answer-hint {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  font-size: 1.6rem;
  font-weight: 800;
}
.chunk-answer-hint .chunk {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 10px;
  background: rgba(255,255,255,0.1);
  animation: chunk-pop 0.25s ease-out;
}
.chunk-answer-hint .chunk-label {
  display: block;
  font-size: 0.5em;
  font-weight: 500;
  opacity: 0.5;
  text-align: center;
  margin-top: 1px;
}

/* Phrase dictation (shared with scene / daily phrase practice) */
.phrase-dictation-blanks {
  position: relative;
  min-height: 5.5rem;
  align-items: flex-start;
}
.phrase-dictation-blanks .jlb-blank.has-letter-slots {
  padding-top: 1.2rem;
}
@media (min-width: 640px) {
  .phrase-dictation-blanks { min-height: 7.25rem; }
}
.jlb-blank {
  position: relative;
  z-index: 10;
  display: grid;
  cursor: text;
  border-bottom: 2px solid rgb(156 163 175);
  border-radius: 2px;
  line-height: 1;
  min-height: 42px;
  padding: 0 0.75rem 0.25rem;
  margin-bottom: 2.6rem;
  font-size: 2.5rem;
  font-weight: 800;
  transition: color .15s, border-color .15s;
}
.jlb-blank.has-letter-slots {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  border-bottom: none;
  padding: 1.1rem 0.2rem 0.15rem;
  min-width: 0;
  min-height: 4.25rem;
}
.jlb-blank.has-letter-slots .jlb-typed,
.jlb-blank.has-letter-slots .jlb-letter-row {
  --letter-slot-gap: 0.18rem;
  position: relative;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: flex-end;
  justify-content: center;
  gap: var(--letter-slot-gap);
  width: auto;
  grid-column: auto;
  grid-row: auto;
}
.jlb-letter-row {
  --letter-slot-gap: 0.18rem;
  position: relative;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: flex-end;
  justify-content: center;
  gap: var(--letter-slot-gap);
}
.jlb-letter-slot {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  min-width: 1.7rem;
  height: 3.75rem;
  padding: 0 0.08rem 0.2rem;
  border-bottom: 3px solid rgb(156 163 175);
  border-radius: 2px;
  box-sizing: border-box;
  transition: color 0.12s ease;
}
.jlb-letter-slot.is-space {
  min-width: 1.1rem;
  border-bottom-color: transparent;
}
.jlb-letter-slot.is-mark {
  min-width: 1.25rem;
}
.jlb-blank.is-active .jlb-letter-slot.is-active {
  border-bottom-color: #38bdf8;
}
.jlb-blank.is-active .jlb-letter-slot.is-active .jlb-caret {
  background: #38bdf8;
}
.jlb-letter-slot .jlb-caret {
  position: absolute;
  left: 50%;
  bottom: 0.2rem;
  transform: translateX(-50%);
  width: 2px;
  height: 2.5rem;
  margin-left: 0;
  border-radius: 1px;
}
@media (min-width: 640px) {
  .jlb-letter-slot .jlb-caret {
    height: 3.35rem;
  }
}
.jlb-blank.is-filled .jlb-letter-slot,
.jlb-blank.phrase-blank-success .jlb-letter-slot {
  border-bottom-color: transparent;
}
.jlb-letter-slot.is-filled {
  border-bottom-color: rgb(148 163 184 / 0.7);
}
.jlb-letter-slot.is-matched {
  border-bottom-color: transparent;
}
.jlb-letter-slot.is-mismatch {
  border-bottom-color: rgb(251 146 60 / 0.95);
}
.jlb-letter-slot.is-mismatch .jlb-letter-glyph {
  color: rgb(251 146 60);
}
.jlb-blank.is-wrong .jlb-letter-slot.is-matched {
  border-bottom-color: transparent;
}
.jlb-blank.is-wrong .jlb-letter-slot.is-mismatch {
  border-bottom-color: rgb(239 68 68 / 0.9);
}
.jlb-blank.is-wrong .jlb-letter-slot.is-mismatch .jlb-letter-glyph {
  color: rgb(248 113 113);
}
.jlb-blank.is-filled .letter-match-line,
.jlb-blank.phrase-blank-success .letter-match-line {
  background: #34d399;
}
.jlb-blank.has-letter-slots.phrase-blank-success {
  animation: none;
}
.jlb-blank.has-letter-slots.phrase-blank-success .letter-match-line.is-on,
.jlb-blank.has-letter-slots.is-filled .letter-match-line.is-on {
  animation: letter-match-success 0.45s ease-out;
}
.jlb-letter-glyph {
  display: block;
  position: relative;
  z-index: 2;
  font-size: 2.5rem;
  font-weight: 800;
  line-height: 1;
  color: var(--practice-text, #f8fafc);
  user-select: none;
}
@media (min-width: 640px) {
  .jlb-blank {
    min-height: 72px;
    padding-bottom: 0.5rem;
    margin-bottom: 3.4rem;
    font-size: 3.35rem;
  }
  .jlb-blank.has-letter-slots {
    min-height: 5.25rem;
    padding-bottom: 0.2rem;
  }
  .jlb-letter-slot {
    min-width: 2.15rem;
    height: 4.85rem;
  }
  .jlb-letter-glyph {
    font-size: 3.35rem;
  }
  .jlb-letter-compact {
    height: 4.85rem;
    font-size: 3.35rem;
  }
  .jlb-letter-row,
  .jlb-blank.has-letter-slots .jlb-typed,
  .jlb-blank.has-letter-slots .jlb-letter-row {
    --letter-slot-gap: 0.22rem;
    gap: var(--letter-slot-gap);
  }
}
.jlb-blank.phrase-blank-success {
  animation: none;
  border-bottom-color: rgb(52 211 153 / 0.85);
  color: rgb(52 211 153);
}
.jlb-blank.is-filled { border-bottom-color: rgb(52 211 153 / 0.7); }
.jlb-blank.is-filled .jlb-typed-text { color: rgb(52 211 153); }
.jlb-blank .jlb-chunk {
  display: inline-block;
  padding: 0 1px;
  font-weight: inherit;
}
.jlb-blank .jlb-hint {
  position: absolute;
  left: 0;
  right: 0;
  top: 0.05rem;
  bottom: auto;
  text-align: center;
  font-size: 0.8rem;
  line-height: 1;
  font-weight: 600;
  color: rgb(248 113 113);
  white-space: nowrap;
  pointer-events: none;
  z-index: 2;
}
@media (min-width: 768px) {
  .jlb-blank .jlb-hint { font-size: 1rem; }
}
.jlb-blank.is-wrong { color: rgb(239 68 68); border-bottom-color: rgb(239 68 68); }
.jlb-blank .jlb-sizer { grid-column: 1; grid-row: 1; visibility: hidden; user-select: none; white-space: pre; }
.jlb-blank .jlb-typed { grid-column: 1; grid-row: 1; display: flex; align-items: flex-end; justify-content: center; }
.jlb-blank .jlb-phonetic {
  position: static;
  display: block;
  max-width: 100%;
  box-sizing: border-box;
  padding: 0 0.15rem;
  text-align: center;
  font-size: 0.85rem;
  line-height: 1.15;
  font-weight: 400;
  color: rgb(203 213 225);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}
.jlb-token-meta {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 0.12rem);
  width: 100%;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.12rem;
  overflow: hidden;
  pointer-events: none;
  min-height: 0;
}
.jlb-blank .jlb-zh.is-reserved {
  visibility: hidden;
}
.jlb-blank .jlb-zh {
  position: static;
  transform: none;
  max-width: 100%;
  width: 100%;
  box-sizing: border-box;
  padding: 0 0.15rem;
  text-align: center;
  font-size: 0.78rem;
  line-height: 1.15;
  font-weight: 500;
  color: rgb(148 163 184);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}
@media (min-width: 768px) {
  .jlb-token-meta {
    top: calc(100% + 0.14rem);
    gap: 0.14rem;
  }
  .jlb-blank .jlb-phonetic { font-size: 1rem; }
  .jlb-blank .jlb-zh { font-size: 0.9rem; }
}
.jlb-blank .jlb-caret {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  margin-left: 1px;
  background: currentColor;
  border-radius: 1px;
  vertical-align: text-bottom;
  animation: jlb-caret-blink 1s steps(1) infinite;
}
@keyframes jlb-caret-blink {
  0%, 50% { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}
.jlb-shake { animation: shake 0.4s ease-in-out; }
