/* 学生端的样子。**和后台的 app.css 完全分开。**
 *
 * 分开的理由不是好看：学生多半用手机或教室电脑打开，屏幕小、手指点；
 * 后台是老师坐在电脑前用的。两边共用一套样式，改一边就会弄坏另一边。
 *
 * 布局的核心是三段：顶栏固定、消息区自己滚、输入框贴在底部。
 * 用 100dvh 而不是 100vh——手机浏览器的地址栏会伸缩，用 vh 的话
 * 输入框会被地址栏盖住一截，学生看不见自己打的字。
 */

:root {
  --paper: #f4f6f8;
  --card: #ffffff;
  --ink: #16202b;
  --ink-soft: #5a6875;
  --line: #dde3e9;
  --brand: #1f5f8b;
  --brand-soft: #e8f1f7;
  --bubble-me: #1f5f8b;
  --bubble-me-ink: #ffffff;
  --bubble-bot: #ffffff;
  --warn-bg: #fdf1e7;
  --warn-ink: #8a4b16;
  --danger-bg: #fdecec;
  --danger-ink: #962c2c;
  --radius: 14px;
  --sans: "Noto Sans SC", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
}

* { box-sizing: border-box; }

/* 带 hidden 的元素一律不显示。**这条不能省。**
   下面 `.turn` 这类规则自己设了 display，而作者写的样式排在浏览器
   默认样式后面，会把浏览器自带的 `[hidden] { display: none }` 顶掉。
   出过事（2026-09-05，手机上）：模板里那个默认藏着的「正在生成」框
   一直显示着，聊天记录中间凭空多出一个空的「学习助手」和一个空气泡，
   白占掉小半屏。加 !important 是为了将来任何一条新写的 display 都顶不掉它。 */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

/* ---------- 登录页 ---------- */
.login-shell {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 24px;
}
.login-card {
  width: 100%;
  max-width: 380px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 32px 28px;
  box-shadow: 0 6px 24px rgba(22, 32, 43, .06);
}
.login-card h1 {
  margin: 0 0 6px;
  font-size: 22px;
  font-weight: 600;
}
.login-card .sub {
  margin: 0 0 24px;
  color: var(--ink-soft);
  font-size: 14px;
}
.field { margin-bottom: 16px; }
.field label {
  display: block;
  font-size: 13px;
  color: var(--ink-soft);
  margin-bottom: 6px;
}
.field input {
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 9px;
  font-family: inherit;
  font-size: 16px; /* 16px 以下，iOS 会在聚焦时自动放大整页 */
  background: #fff;
  color: var(--ink);
}
.field input:focus {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
  border-color: transparent;
}
.primary-action {
  width: 100%;
  padding: 12px;
  border: none;
  border-radius: 9px;
  background: var(--brand);
  color: #fff;
  font-family: inherit;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
}
.primary-action:hover { background: #18506f; }
.primary-action:disabled { opacity: .5; cursor: not-allowed; }

.alert {
  padding: 10px 13px;
  border-radius: 9px;
  font-size: 14px;
  margin-bottom: 16px;
}
.alert-danger { background: var(--danger-bg); color: var(--danger-ink); }
.alert-warn { background: var(--warn-bg); color: var(--warn-ink); }

/* ---------- 聊天页：三段布局 ---------- */
/* 整个聊天页钉死在屏幕上，自己不滚——只有中间的消息区滚。
   **不钉死会怎样**（2026-09-05 手机上出过）：手机键盘弹出来时，
   浏览器会把整页往上顶，好让输入框露出来；页面一旦能滚，学生往上翻记录
   就把输入框翻出了屏幕，想再打字得先翻回来。
   高度用 100dvh 不用 100vh——地址栏会伸缩，用 vh 的话底下会被盖掉一截。
   真正的高度由脚本按「看得见的那块区域」再校一次，见 study-chat.js。 */
.chat-shell {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  height: 100dvh;
  display: flex;
  flex-direction: column;
}

.chat-top {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  background: var(--card);
  border-bottom: 1px solid var(--line);
}
.chat-top .who { min-width: 0; }
.chat-top .who strong {
  display: block;
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chat-top .who span {
  font-size: 12px;
  color: var(--ink-soft);
}
.chat-top .spacer { flex: 1; }
.top-btn {
  flex: none;
  padding: 7px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
  color: var(--ink);
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
}
.top-btn:hover { background: var(--brand-soft); border-color: var(--brand); }
.top-btn.ghost { color: var(--ink-soft); }

/* 消息区：唯一会滚动的地方 */
.chat-log {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 18px 16px 8px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  scroll-behavior: smooth;
  /* 消息区滚到头之后，别把这一下继续传给整页——传出去就是整页跟着动，
     输入框被顶出屏幕。 */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
@media (prefers-reduced-motion: reduce) {
  .chat-log { scroll-behavior: auto; }
}

.turn { display: flex; }
.turn.me { justify-content: flex-end; }
.bubble {
  max-width: min(76%, 640px);
  padding: 11px 14px;
  border-radius: var(--radius);
  /* 学生贴的题目自带换行，要保留；同时长单词/长数字要能断开，
   * 否则一串数字会把气泡撑破，横向滚出屏幕。 */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.turn.me .bubble {
  background: var(--bubble-me);
  color: var(--bubble-me-ink);
  border-bottom-right-radius: 4px;
}
.turn.bot .bubble {
  background: var(--bubble-bot);
  border: 1px solid var(--line);
  border-bottom-left-radius: 4px;
}
.turn .name {
  font-size: 12px;
  color: var(--ink-soft);
  margin-bottom: 4px;
}

/* ---------- 换个 AI 再问一遍 ---------- */

/* 按钮做得比助手那条回答**轻**：它是一条退路，不是并列的选项。
   做成和发送键一样显眼的话，学生会先看到它、直接绕开引导。 */
.direct-ask {
  margin-top: 8px;
  padding: 5px 11px;
  font: inherit;
  font-size: 12.5px;
  color: var(--ink-soft);
  background: transparent;
  border: 1px dashed var(--line);
  border-radius: 999px;
  cursor: pointer;
}
.direct-ask:hover { color: var(--brand); border-color: var(--brand); }
.direct-ask:disabled { opacity: 0.5; cursor: default; }

/* 「切回学习助手」。切过去之后它一直在顶栏上——学生得随时看得见回去的路，
   否则他只剩「换个问题」可按，而那会连题一起换掉。 */
.top-btn.back-to-tutor {
  border-color: var(--brand);
  color: var(--brand);
  background: var(--brand-soft);
}

/* 裸模型那份回答。左边一道竖线，和助手的回答明确分开——
   两份答案挨在一起，学生必须一眼看出哪份是哪份。 */
.direct-answer {
  margin-top: 10px;
  padding-left: 10px;
  border-left: 3px solid var(--line);
}
.direct-answer .name { color: var(--ink-soft); }
.direct-answer .bubble {
  background: var(--paper);
  border: 1px solid var(--line);
  border-bottom-left-radius: 4px;
  /* 这份没经过课程资料核对，标题里已经写明了。底色比助手那条淡，
     是为了在扫一眼的时候就能分出主次，不是为了好看。 */
}

.stage {
  font-size: 12.5px;
  color: var(--brand);
  margin-bottom: 6px;
}
.stage::after {
  content: "";
  display: inline-block;
  width: 1em;
  text-align: left;
  animation: dots 1.2s steps(4, end) infinite;
}
@keyframes dots {
  0%   { content: ""; }
  25%  { content: "·"; }
  50%  { content: "··"; }
  75%  { content: "···"; }
}
@media (prefers-reduced-motion: reduce) {
  .stage::after { animation: none; content: "···"; }
}

/* 等久了才出现的那一行说明。做得比阶段行更淡——它是补充，不是主信息。 */
.wait-hint {
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ink-soft);
  margin: -2px 0 7px;
  max-width: 34em;
}

/* 第一次打开时就把「要等多久」说在前面。等待本身不可怕，
   可怕的是不知道要等多久、也不知道是不是卡住了。 */
.wait-note {
  display: inline-block;
  margin-top: 8px;
  color: var(--brand);
}

.empty-hint {
  margin: auto;
  max-width: 30em;
  text-align: center;
  color: var(--ink-soft);
  font-size: 14.5px;
}
.empty-hint strong { display: block; color: var(--ink); margin-bottom: 6px; font-size: 16px; }

/* 输入区：贴在底部，不随消息滚动 */
.composer {
  flex: none;
  background: var(--card);
  border-top: 1px solid var(--line);
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
}
.composer .row {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}
.composer textarea {
  flex: 1;
  resize: none;
  min-height: 44px;
  max-height: 180px;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 11px;
  font-family: inherit;
  font-size: 16px;
  line-height: 1.55;
  background: #fff;
  color: var(--ink);
}
.composer textarea:focus {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
  border-color: transparent;
}
.icon-btn {
  flex: none;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: #fff;
  cursor: pointer;
  color: var(--ink-soft);
}
.icon-btn:hover { background: var(--brand-soft); color: var(--brand); border-color: var(--brand); }

/* 正在听的时候按钮要一眼看得出来——学生得知道「现在说话是算数的」。
   用颜色而不是只靠那行小字提示：手机上他的手指正挡在按钮附近，
   眼睛落在的是按钮，不是上面那行字。 */
.icon-btn.listening {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
  animation: listening 1.4s ease-in-out infinite;
}
@keyframes listening {
  50% { opacity: .6; }
}
@media (prefers-reduced-motion: reduce) {
  .icon-btn.listening { animation: none; }
}
.send-btn {
  flex: none;
  height: 44px;
  padding: 0 18px;
  border: none;
  border-radius: 11px;
  background: var(--brand);
  color: #fff;
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.send-btn:hover { background: #18506f; }
.send-btn:disabled, .icon-btn:disabled { opacity: .45; cursor: not-allowed; }

/* 键盘开着的时候，输入框底下那圈「home 条」留白就是纯浪费——
   那块地方已经被键盘盖住了。小屏手机上这一圈值好几行聊天记录。 */
.chat-shell.keyboard-up .composer {
  padding-bottom: 8px;
}

.composer .hint {
  margin: 6px 2px 0;
  font-size: 12px;
  color: var(--ink-soft);
}
.composer .notice {
  margin: 0 0 8px;
  padding: 8px 11px;
  border-radius: 8px;
  font-size: 13.5px;
}

.attachment {
  display: none;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
  padding: 7px 9px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--brand-soft);
  font-size: 13px;
}
.attachment.shown { display: flex; }
.attachment img {
  width: 40px;
  height: 40px;
  object-fit: cover;
  border-radius: 6px;
  flex: none;
}
.attachment .name {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.attachment button {
  flex: none;
  border: none;
  background: none;
  color: var(--danger-ink);
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

@media (max-width: 480px) {
  .bubble { max-width: 86%; }
  .chat-top { padding: 8px 12px; }
  .chat-log { padding: 14px 12px 6px; }
  .composer { padding: 8px 12px calc(8px + env(safe-area-inset-bottom)); }
}
