/* 绘梦星球 shared components.
   Class prefix `db-` so it can't clash with anything page-local.
   Pair with _app/tokens.css. */

/* ===== reset bits ===== */
.db-reset, .db-reset * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* ===== inline SVG icon (pairs with _app/icons.js) =========================
   <i class="ic" data-icon="moon"></i>  ← icons.js fills the inner SVG
   - Sized to 1em so it scales with the parent's font-size.
   - currentColor stroke so it inherits the parent's text color. */
.ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1em;
  height: 1em;
  line-height: 1;
  vertical-align: -0.15em;     /* baseline-align with text */
  flex-shrink: 0;
}
.ic > svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* ===== Topbar ============================================================ */
/* Layout: [back?] [title (centered, absolute)] [right-slot?]
   - Title is absolutely positioned at 50% so left/right slot widths don't
     drag it off-center.
   - Use class `.db-topbar--floating` to overlay over a frame (player). */
.db-topbar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  gap: var(--s-3);
  padding: max(var(--s-3), calc(env(safe-area-inset-top, 0px) + var(--s-3))) var(--s-4) var(--s-3);
  border-bottom: 1px solid var(--hairline);
  flex: 0 0 auto;
}
.db-topbar__title {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  max-width: 60%;
  text-align: center;
  font-size: var(--t-sm);
  color: var(--muted);
  letter-spacing: 0.08em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  pointer-events: none;
}
.db-topbar__title--strong {
  color: var(--fg);
  font-size: var(--t-md);
  font-weight: 500;
}
.db-topbar__back {
  flex: 0 0 auto;
  width: 36px; height: 36px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-2);
  border: 1px solid var(--hairline);
  color: var(--fg);
  font-size: 20px;
  cursor: pointer;
  text-decoration: none;
}
.db-topbar__right {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--s-2);
}

/* ===== Buttons =========================================================== */
.db-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-5);
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  font-size: var(--t-md);
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  text-decoration: none;
  transition: transform var(--t-fast), background var(--t-base);
  user-select: none;
}
.db-btn:active { transform: scale(0.96); }
.db-btn:disabled { opacity: 0.4; cursor: default; }
.db-btn .db-btn__icon { font-size: 1.2em; line-height: 1; }

.db-btn--primary {
  background: var(--accent);
  color: var(--bg-deep);
  box-shadow: var(--shadow-2);
}
.db-btn--primary:active { background: var(--accent-up); }

.db-btn--ghost {
  background: var(--surface-2);
  border-color: var(--hairline);
  color: var(--fg);
}

.db-btn--positive {
  background: linear-gradient(135deg, var(--positive), var(--positive-down));
  color: #fff;
  box-shadow: 0 4px 14px rgba(76, 175, 80, 0.35);
  font-weight: 600;
}
.db-btn--negative {
  background: linear-gradient(135deg, var(--negative), var(--negative-down));
  color: #fff;
  box-shadow: 0 4px 14px rgba(231, 111, 81, 0.35);
  font-weight: 600;
}

.db-btn--block { width: 100%; padding: var(--s-4) var(--s-5); }

/* ===== Mic — recording button (tell, create) ============================= */
.db-mic-big {
  width: 96px; height: 96px;
  border-radius: 50%;
  border: 0;
  background: var(--accent);
  color: var(--bg-deep);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: 42px;
  box-shadow: var(--accent-glow);
  transition: transform var(--t-fast), background var(--t-base);
  user-select: none;
  touch-action: none;
}
.db-mic-big:active { transform: scale(0.94); }
.db-mic-big:disabled { opacity: 0.4; cursor: default; }
.db-mic-big.is-recording {
  background: var(--negative);
  animation: db-mic-pulse 1.1s infinite;
}
@keyframes db-mic-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(231,111,81,0.55); }
  50%      { box-shadow: 0 0 0 18px rgba(231,111,81,0); }
}

/* ===== Card ============================================================== */
.db-card {
  background: var(--surface-1);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  overflow: hidden;
}

/* ===== Character review card (shared by create.html + tell.html) ========= */
.db-character-card {
  margin: var(--s-1) auto var(--s-4);
  padding: var(--s-4);
  background: var(--surface-3);
  border: 1px solid rgba(146, 200, 120, 0.25);
  border-radius: var(--r-md);
  max-width: 92%;
}
.db-character-card__anchor {
  aspect-ratio: 1/1;
  margin-bottom: var(--s-3);
  background: rgba(0,0,0,0.3);
  border-radius: var(--r-sm);
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  position: relative;
}
.db-character-card__anchor img {
  width: 100%; height: 100%;
  object-fit: contain;
  display: block;
  opacity: 0;
  transition: opacity var(--t-slow);
}
.db-character-card__anchor img.is-ready { opacity: 1; }
.db-character-card__hint {
  color: var(--muted);
  font-size: var(--t-sm);
  text-align: center;
  padding: 0 var(--s-4);
}
.db-character-card__hint .db-typing { margin-top: var(--s-2); justify-content: center; display: flex; }
.db-character-card__name {
  font-size: var(--t-lg);
  color: var(--accent);
  font-weight: bold;
  margin-bottom: var(--s-1);
}
.db-character-card__desc {
  font-size: 14px;
  line-height: 1.65;
  color: var(--fg);
  margin-bottom: var(--s-1);
}
.db-character-card__traits {
  font-size: var(--t-sm);
  color: var(--muted);
  margin-bottom: var(--s-3);
}
.db-character-card__actions {
  display: flex;
  gap: var(--s-3);
}
.db-character-card__actions .db-btn { flex: 1; padding: var(--s-3) var(--s-2); }

/* ===== Length choice card (short vs long story) ========================= */
.db-length-card {
  margin: var(--s-1) auto var(--s-4);
  padding: var(--s-4);
  background: var(--surface-3);
  border: 1px solid rgba(146, 200, 120, 0.25);
  border-radius: var(--r-md);
  max-width: 92%;
}
.db-length-card__title {
  text-align: center;
  font-size: var(--t-md);
  color: var(--fg);
  margin-bottom: var(--s-3);
}
.db-length-card__option {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  margin-bottom: var(--s-2);
  border-radius: var(--r-sm);
  border: 1.5px solid var(--hairline);
  background: var(--surface-2);
  cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast);
}
.db-length-card__option:active { transform: scale(0.98); }
.db-length-card__option:disabled,
.db-length-card__option[disabled] {
  opacity: 0.35;
  cursor: default;
  pointer-events: none;
}
.db-length-card__option .opt-icon { font-size: 28px; flex-shrink: 0; }
.db-length-card__option .opt-body { flex: 1; min-width: 0; }
.db-length-card__option .opt-name {
  font-size: var(--t-md);
  font-weight: 600;
  color: var(--fg);
}
.db-length-card__option .opt-desc {
  font-size: var(--t-xs);
  color: var(--muted);
  margin-top: 2px;
}
.db-length-card__option .opt-quota {
  font-size: var(--t-xs);
  color: var(--accent);
  font-weight: 500;
  flex-shrink: 0;
  white-space: nowrap;
}
.db-length-card__option .opt-quota.is-zero { color: var(--negative); }
.db-length-card__hint {
  text-align: center;
  font-size: var(--t-xs);
  color: var(--muted);
  margin-top: var(--s-2);
}

/* ===== Typing dots ====================================================== */
.db-typing {
  display: inline-flex;
  gap: 4px;
  padding: 4px 0;
}
.db-typing span {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  animation: db-blink 1.2s infinite;
}
.db-typing span:nth-child(2) { animation-delay: 0.2s; }
.db-typing span:nth-child(3) { animation-delay: 0.4s; }
@keyframes db-blink {
  0%, 80%, 100% { opacity: 0.2; }
  40% { opacity: 1; }
}

/* ===== Overlay ========================================================== */
.db-overlay {
  position: fixed; inset: 0;
  background: radial-gradient(ellipse at center, var(--bg-up) 0%, var(--bg-deep) 100%);
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-4);
  z-index: 30;
  padding: var(--s-5);
  text-align: center;
  color: var(--fg);
  animation: db-fade-in var(--t-base);
}
.db-overlay.is-show { display: flex; }
@keyframes db-fade-in { from { opacity: 0; } to { opacity: 1; } }
.db-overlay__title { font-size: var(--t-xl); }
.db-overlay__sub { font-size: var(--t-sm); color: var(--muted); max-width: 320px; line-height: 1.6; }

/* ===== Version tag ====================================================== */
.db-version-tag {
  font-size: var(--t-xs);
  color: rgba(139,122,154,0.5);
  user-select: text;
}
.db-version-tag--fixed {
  position: fixed;
  bottom: max(var(--s-1), calc(env(safe-area-inset-bottom, 0px) + 2px));
  right: var(--s-2);
  z-index: 4;
}

/* ===== Ruby (pinyin) spacing ============================================
   Global fix: prevent ruby annotations from stretching character spacing.
   Applied wherever renderRuby() outputs HTML with <ruby><rt> tags. */
ruby {
  ruby-position: over;
  -webkit-ruby-position: before;
  ruby-align: center;
  letter-spacing: 0;
}
ruby rt {
  font-size: 0.46em;
  font-weight: normal;
  line-height: 1;
  letter-spacing: 0;
  text-shadow: none;
  color: inherit;
  opacity: 0.6;
}
/* Reset within narration (player) — keeps the muted colour */
.narration ruby rt { color: var(--muted); opacity: 1; }
/* Reset within card titles (library) — small pinyin over book titles */
.card .title ruby rt { font-size: 0.42em; }

/* Card titles use an EXPLICIT flex-column stack per character instead of
   relying on `ruby-position: over`. Browser-native ruby has too many
   cross-platform bugs:
     - iOS Safari: pinyin overlaps base char when title wraps to 2nd line
     - Android Chrome: pinyin and base drift apart on long titles
     - Both: line-height math is unpredictable when rt font-size > 0.5em
   inline-flex column-reverse stacks rt visually ABOVE the base char as
   a layout unit. Every character + pinyin pair is its own atomic block,
   so wrapping never separates them. Works identically on all browsers. */
.card .title ruby {
  display: inline-flex;
  flex-direction: column-reverse;
  align-items: center;
  vertical-align: bottom;
  line-height: 1;
  margin: 0 1px;
}
.card .title ruby rt {
  display: block;
  line-height: 1;
  margin-bottom: 1px;
}

/* 小绿 mascot — actual app icon (green dino with glasses on storybook)
   used wherever we used to show a 🦖 emoji. Keeps the brand identity
   consistent across loading screens, chat avatars, and entry buttons. */
.dino-mascot {
  width: 1.1em;
  height: 1.1em;
  border-radius: 50%;
  object-fit: cover;
  /* Crop the icon a touch so the dinosaur sits centered (the original
     icon places the dino in the upper portion above the storybook). */
  object-position: center 38%;
  vertical-align: middle;
  display: inline-block;
  background: transparent;
}
.dino-mascot--med {
  width: 56px; height: 56px;
  box-shadow: 0 4px 14px rgba(0,0,0,0.3);
}
.dino-mascot--big {
  width: 96px; height: 96px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.35);
  /* Animation lives on the wrapper (.cat / .chat-header .cat) — letting
     two independent bobs compose creates a wobble that distracts. */
}
