/* app.css — v2.1-green design system (PR-4c-green / P0)
   Source of truth: docs/v5-spec/engineering/09-green-ui-spec.md
   §1 colours, §2 fonts, §3 響應式 (mobile-first centred 440-480 col),
   §4 components (DayTile / 連線 / Treasure / buttons), §5 page layouts.
   ⚠️ Supersedes all earlier UI (v1 霧綠 / 金棕 / 水彩).

   P0 scope: tokens + body + buttons (.btn-green/.btn-gold/.btn-paper) +
             paper-card / input / pace-radio primitives. Existing class names
             kept so HTML stays untouched at this checkpoint — sections
             (entry / journey / conv / paper-pages / coach) render via the
             new tokens automatically.
             P1 adds logo hero; P2 rebuilds the journey grid (DayTile + snake
             path + treasures); P3 polishes conversation/note/graduation copy;
             P4 adds Phase Report page + weeks→phases endpoint; P5 puts /coach
             in green. */

@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+TC:wght@300;400&family=Noto+Sans+TC:wght@300;400&display=swap');

/* ════════════════════════════════════════════════════════════════
   §1 colour tokens (green-mint palette)
   ════════════════════════════════════════════════════════════════ */
:root {
  /* Backdrop + tiles */
  --bg-mint:        #D7EBD1;        /* 主背景（學員頁、桌面置中欄左右也是它） */
  --green-walked:   #5DA873;        /* 走過的日子格子填色 + focus border */
  --green-forest:   #2C5238;        /* 深森林綠：標題、深色強調 */
  --peach-today:    #F4C9A0;        /* 今天格子（暖色對比、empty + filled 共用） */
  --gold-accent:    #E3B340;        /* ✓ / ✦ / 寶藏 / active 金光 */
  --tile-future:    #EAF4E6;        /* 未到的格子 + 微邊框 */
  --neutral-step:   #B9A88C;        /* 腳印 / locked 寶藏 / 中性 icon（非綠） */
  --paper-card:     #FBF6EC;        /* 卡片：筆記 / 報告 */
  --brand-green:    #3E9D5C;        /* 主按鈕（logo 精確綠、Vivi 上線前微調） */

  /* Text scale (only 3 levels per spec §1 — collapsed v1 quaternary/tertiary) */
  --text-primary:   #2C3A2C;
  --text-secondary: #6E8A6E;
  --text-faint:     #A7BCA4;

  /* Derived */
  --bubble-user:    #C8E4C2;        /* 使用者泡泡淺底（spec §5.3 hint） */
  --border-line:    #BFD7BA;        /* 微分隔線（綠調 hairline） */

  /* Typography */
  --font-serif: 'Noto Serif TC', 'Songti SC', 'Songti TC', serif;
  --font-sans:  'Noto Sans TC', 'PingFang TC', sans-serif;
}

/* ════════════════════════════════════════════════════════════════
   reset + base
   ════════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
  background: var(--bg-mint);                  /* §3: mint fills the screen */
  color: var(--text-primary);
  font-family: var(--font-serif);
  font-size: 17px;
  line-height: 1.8;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
button { background: none; border: none; font-family: inherit; color: inherit; cursor: pointer; }
input, textarea { font-family: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

/* §2 — never bold (CJK weight bumps break the paper feel; rely on size/lts contrast) */
b, strong, h1, h2, h3, h4, h5, h6 { font-weight: 400; }

/* ════════════════════════════════════════════════════════════════
   §3 響應式 — 學員 app 桌面置中 440-480 px col
   ════════════════════════════════════════════════════════════════ */
.view { display: none; min-height: 100vh; max-width: 480px; margin: 0 auto; }
.view.active { display: flex; flex-direction: column; }
.view.fade-out { opacity: 0; transform: translateY(-12px); transition: opacity 400ms ease-in, transform 400ms ease-in; }
.view.fade-in  { opacity: 0; transform: translateY(8px); }
.view.fade-in.shown { opacity: 1; transform: none; transition: opacity 500ms ease-out, transform 500ms ease-out; }

/* ════════════════════════════════════════════════════════════════
   §4.4 buttons — 3 primitives per spec.
   Legacy class names (.entry-btn / .paper-btn / .conv-send-btn) share the
   primitive selectors so existing HTML keeps working before P1/P3 cleanup.
   ════════════════════════════════════════════════════════════════ */
.btn-green,
.entry-btn,
.conv-send-btn {
  background: var(--brand-green);
  color: #FFFFFF;
  font-family: var(--font-serif);
  font-size: 15px;
  letter-spacing: 4px;
  padding: 14px 36px;
  border-radius: 10px;
  transition: background-color 200ms ease-out, opacity 200ms ease-out;
}
.btn-green:hover,
.entry-btn:hover,
.conv-send-btn:hover { background: #348651; }   /* shade darker, calm hover */
.btn-green:disabled,
.entry-btn:disabled,
.conv-send-btn:disabled { opacity: 0.45; cursor: default; background: var(--brand-green); }

.btn-gold {
  background: var(--gold-accent);
  color: #3A2E10;
  font-family: var(--font-serif);
  font-size: 15px;
  letter-spacing: 4px;
  padding: 14px 36px;
  border-radius: 10px;
}

.btn-paper,
.paper-btn {
  background: var(--paper-card);
  color: var(--text-primary);
  border: 0.5px solid var(--green-walked);
  font-family: var(--font-serif);
  font-size: 14px;
  letter-spacing: 2px;
  padding: 12px 28px;
  border-radius: 10px;
  transition: background-color 200ms ease-out, border-color 200ms ease-out;
}
.btn-paper:hover,
.paper-btn:hover { background: #F4ECDA; }
/* Vivi 5/24: coach day-note picker active-day visual mark. Tiny ring so the
   coach knows which day is currently shown + clicking the same day again
   toggles the note collapsed. */
.paper-btn--active {
  background: var(--bg-mint);
  border-color: var(--green-walked);
  color: var(--green-forest);
}

/* Override layout of legacy .conv-send-btn so it stays inline with the textarea */
.conv-send-btn { padding: 12px 22px; letter-spacing: 2px; font-size: 14px;
  border-radius: 14px; white-space: nowrap; min-height: 48px; align-self: flex-end; }

/* ════════════════════════════════════════════════════════════════
   §4.5 input + paper-card + pace-radio (component primitives)
   ════════════════════════════════════════════════════════════════ */
.entry-input,
.conv-input {
  width: 100%;
  padding: 11px 16px;
  background: var(--paper-card);
  border: 0.5px solid var(--border-line);
  border-radius: 10px;
  font-family: var(--font-sans);
  font-size: 15px;
  color: var(--text-primary);
  transition: border-color 200ms ease-out;
}
/* The conv-input textarea keeps the roomier padding — only the entry inputs got tight. */
.conv-input { padding: 14px 18px; }
.entry-input::placeholder,
.conv-input::placeholder {
  color: var(--text-faint);
  font-family: var(--font-serif);
  font-style: italic;
}
.entry-input:focus,
.conv-input:focus {
  outline: none;
  border-color: var(--green-walked);
}
.entry-input.invalid { border-color: var(--green-walked); }   /* validation: §5.1 — no red, brand-green border */
.conv-input { resize: none; min-height: 48px; max-height: 200px; overflow-y: auto; border-radius: 14px; }

/* Paper card — used by 教練筆記 / 週報 / 結業 / Phase Report */
.paper-card {
  background: var(--paper-card);
  border: 0.5px solid var(--border-line);
  border-radius: 10px;
  /* no shadow, no gradient — spec §4.5 */
}

/* Pace radio (entry §5.1) — paper底 + 選中 green-walked 邊 + 深綠圓點 */
.entry-pace { border: none; padding: 0; margin: 16px 0 0; }
.entry-pace .entry-field-label { margin-bottom: 6px; padding: 0; }
.entry-pace-option {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 10px 14px; margin-top: 8px;
  background: var(--paper-card);
  border: 0.5px solid var(--border-line);
  border-radius: 10px;
  cursor: pointer;
  transition: border-color 200ms ease-out, background-color 200ms ease-out;
}
.entry-pace-option:has(input:checked) {
  border-color: var(--green-walked);
  background: var(--paper-card);
}
.entry-pace-option input[type="radio"] {
  margin-top: 6px; flex: 0 0 auto;
  accent-color: var(--brand-green);     /* §4.5: 深綠圓點 */
}
.entry-pace-option__body { display: flex; flex-direction: column; gap: 4px; }
.entry-pace-option__title { font-family: var(--font-serif); font-size: 15px; letter-spacing: 1px; color: var(--text-primary); }
.entry-pace-option__sub { font-family: var(--font-serif); font-style: italic; font-size: 12px; line-height: 1.6; color: var(--text-secondary); }

/* ════════════════════════════════════════════════════════════════
   §5.1 entry — token sweep only at P0; logo hero + new wording lands at P1
   PR-4c-green Vivi A001 mobile fix: tightened vertical rhythm so the whole
   entry page fits within a 390×844 viewport without scrolling. Don't bump
   these back up — they're calibrated against the real device.
   ════════════════════════════════════════════════════════════════ */
#view-entry { justify-content: flex-start; align-items: center; padding-top: 24px; padding-bottom: 24px; }
.entry-container { width: 100%; max-width: 420px; padding: 0 28px; text-align: center; }
/* P1 (PR-4c-green) — logo hero (Vivi 已提供、green 望遠鏡 + ✦) */
.entry-logo { display: block; width: 100%; max-width: 180px; height: auto; margin: 0 auto 14px; user-select: none; }
.entry-title { font-family: var(--font-serif); font-size: 28px; letter-spacing: 6px; line-height: 1.2; color: var(--green-forest); }
.entry-sub { margin-top: 10px; font-family: var(--font-serif); font-style: italic; font-size: 12px; letter-spacing: 2.5px; color: var(--text-secondary); }
.entry-form { margin-top: 24px; text-align: left; }
.entry-field-label { display: block; font-family: var(--font-serif); font-size: 12px; letter-spacing: 1.5px; color: var(--text-secondary); margin-bottom: 6px; }
.entry-field-label--gap { margin-top: 16px; }
.entry-btn { display: block; margin: 20px auto 0; }   /* spacing only; visual via .btn-green grouping above */
.entry-foot { margin-top: 24px; font-family: var(--font-serif); font-style: italic; font-size: 12px; color: var(--text-faint); text-align: center; }
.entry-error { margin-top: 12px; font-family: var(--font-serif); font-style: italic; font-size: 13px; color: var(--green-walked); text-align: center; }

/* ════════════════════════════════════════════════════════════════
   header (used by journey / conversation / note / week / graduation)
   ════════════════════════════════════════════════════════════════ */
.app-header { padding: 16px 28px; border-bottom: 0.5px solid var(--border-line); text-align: center; }
.app-header .label { font-family: var(--font-serif); font-size: 11px; letter-spacing: 3px; color: var(--text-secondary); }

/* ════════════════════════════════════════════════════════════════
   §5.2 journey — P0 ONLY token sweep. P2 rewrites the grid entirely
   (3-col snake DayTile + plant illustrations + path + treasure shelf).
   ════════════════════════════════════════════════════════════════ */
#view-journey { background: var(--bg-mint); }
.journey-title-wrap { text-align: center; padding-top: 28px; padding-bottom: 4px; }
.journey-title { font-family: var(--font-serif); font-size: 19px; letter-spacing: 2px; color: var(--green-forest); }
.journey-sub { margin-top: 8px; font-family: var(--font-serif); font-style: italic; font-size: 12px; letter-spacing: 1px; color: var(--text-secondary); }

/* P2 (PR-4c-green) §5.2 — 3-col snake grid + plant tiles + path + treasure shelf */
.journey-grid-wrap { padding: 28px 24px 0; display: flex; justify-content: center; }
.journey-stage {
  position: relative;
  width: 100%;
  max-width: 360px;          /* 3 cols + gaps, comfortable on phone + the 480 col */
}
.journey-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}

/* SVG snake-path overlays the stage behind tiles (z-index 0 vs tile 1). Lives
   in HTML outside #journey-grid so renderJourney's innerHTML clear leaves it intact. */
.journey-path {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
  overflow: visible;
}

/* ─── §4.1 DayTile — 角色旅程 puzzle reveal (PR-4c-green Patrick 5/24) ───
   ⚠️ Supersedes the old「植物 Option A」: scenes are full-bleed (not去背), the
   whole journey reads as a darkened picture that lights up格一格. States below. */
.day-tile {
  position: relative;
  z-index: 1;
  aspect-ratio: 1 / 1;
  border-radius: 14px;
  border: 0.5px solid var(--border-line);
  background: var(--tile-future);
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  cursor: default;
  overflow: hidden;   /* clip the WebP scene to the tile's rounded corners */
  transition: filter 350ms ease-out, border-color 250ms ease-out;
}
.day-tile:focus-visible { outline: 2px solid var(--gold-accent); outline-offset: 3px; }

/* Scene WebP — fills the tile via object-fit: cover. Common to all states.
   State-specific filters are applied to the IMG (not the tile) so the day
   number + check + footprint overlays stay full-colour. */
.day-tile__scene {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;   /* match parent .day-tile border-radius */
  pointer-events: none;
  user-select: none;
  transition: filter 350ms ease-out, opacity 350ms ease-out;
  z-index: 1;
}

/* future = LOCKED puzzle piece: warm sepia「未翻開的書頁」(Vivi preview-feedback,
   PR-4c-green Patrick 5/24 — 從深綠黑死黑改成 tan-sepia、放亮、讓「今天」那格 pop).
   Tint is brand-neutral tan (#B9A88C = --neutral-step), NOT green — green is
   reserved for the「走過的路」signal on completed tiles. */
.day-tile--future        { background: var(--tile-future); cursor: default; }
.day-tile--future .day-tile__scene {
  /* sepia + reduced saturation + brightened: an aged-paper photo rather than
     a flat grayscale dim. brightness lifted from 0.55 → 0.78 per Patrick. */
  filter: sepia(0.55) saturate(0.5) brightness(0.78) contrast(0.95);
}
.day-tile--future::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(185, 168, 140, 0.28);   /* #B9A88C tan @ 28% — warm 未翻開感 */
  border-radius: inherit;
  pointer-events: none;
  z-index: 2;
}

/* today (active) = LIVE: full colour + brand-green frame + halo via keyframes below */
.day-tile--active-empty,
.day-tile--active-filled {
  border-color: var(--green-walked);
  cursor: pointer;
}

/* completed = REVEALED: full colour scene + gold ✓ (no green wash now — the
   scene itself carries the "warm" full-colour signal of "walked + has memory") */
.day-tile--completed {
  border: 1px solid var(--green-walked);
  cursor: pointer;
}

/* Footprint (future only — sits over the tan overlay as a quiet「鎖」 hint).
   PR-4c-green Patrick 5/24: 淺綠 (--bg-mint #D7EBD1) over warm tan = quiet
   retreat, lets「今天」那格 pop. 不用品牌綠 (--brand-green) — 那是 CTA / 走過
   的路才該亮。If preview shows it disappearing on tan → escalate to
   --green-walked (#5DA873), still NOT saturated brand-green. */
.day-tile__footprint {
  width: 28px;
  height: 28px;
  color: var(--bg-mint);
  opacity: 0.85;
  position: relative;
  z-index: 3;
}

/* Day number — top-left, sans, white with shadow over every state since scenes
   are full-bleed across the board now. (Old per-state colour variants retired
   along with the植物 wash background.) */
.day-tile__day {
  position: absolute;
  top: 6px;
  left: 8px;
  font-family: var(--font-sans);
  font-size: 11px;
  z-index: 3;
  color: #FFFFFF;
  pointer-events: none;
  text-shadow: 0 0 4px rgba(0, 0, 0, 0.45);
}

/* Completed ✓ — gold disc top-right with white check */
.day-tile__check {
  position: absolute;
  top: 5px;
  right: 5px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--gold-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 3;
  pointer-events: none;
}
.day-tile__check svg { width: 9px; height: 9px; color: #FFFFFF; }

/* Active 「開始」 pill — only active-empty (today, still going) */
.day-tile__start-pill {
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  padding: 4px 14px;
  background: var(--brand-green);
  color: #FFFFFF;
  font-family: var(--font-serif);
  font-size: 11px;
  letter-spacing: 2px;
  border-radius: 999px;
  white-space: nowrap;
  z-index: 3;
  pointer-events: none;
  box-shadow: 0 1px 4px rgba(46, 82, 56, 0.18);  /* faint lift, NOT a SaaS shadow */
}

/* Active gold halo (§4.1 「2.5× 半徑」)— box-shadow keyframe animates intensity */
.day-tile--active-empty,
.day-tile--active-filled {
  animation: day-tile-halo 3s ease-in-out infinite;
}
@keyframes day-tile-halo {
  0%, 100% { box-shadow: 0 0 30px 8px rgba(227, 179, 64, 0.32); }
  50%      { box-shadow: 0 0 40px 12px rgba(227, 179, 64, 0.58); }
}

/* ─── §4.3 TreasureBox — 5 phase boxes ABOVE the 21-day grid (Vivi 5/24).
   Was: margin 40px auto 12px (treasures sat below grid, needed top breathing).
   Now: margin 18px auto 10px (treasures sit just under journey-title-wrap,
   tighter so the 5 寶藏 reads as part of the「your journey」 header zone
   rather than an island floating above the grid). */
.treasure-title {
  margin: 18px auto 10px;
  text-align: center;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 11px;
  letter-spacing: 3px;
  color: var(--text-secondary);
}
.treasure-shelf {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  max-width: 360px;
  margin: 0 auto;
  padding: 0 24px;
}
.treasure-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 8px 2px;
  background: transparent;
  color: var(--neutral-step);
  border: none;
  cursor: default;
}
.treasure-box--unlocked {
  color: var(--gold-accent);
  cursor: pointer;
}
.treasure-box__icon {
  width: 32px;
  height: 32px;
}
.treasure-box__roman {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 11px;
  letter-spacing: 1px;
  color: var(--text-faint);
}
.treasure-box--unlocked .treasure-box__roman { color: var(--text-secondary); }
.treasure-box--unlocked .treasure-box__icon { filter: drop-shadow(0 0 6px rgba(227, 179, 64, 0.45)); }

.journey-prompt {
  margin: 28px auto 40px;
  text-align: center;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 12px;
  letter-spacing: 1.5px;
  color: var(--text-secondary);
}

/* ════════════════════════════════════════════════════════════════
   §5.3 conversation — green sweep; structural copy lands in P3
   ════════════════════════════════════════════════════════════════ */
#view-conversation { background: var(--bg-mint); position: relative; }
.conv-scroll { flex: 1; max-width: 540px; width: 100%; margin: 0 auto; padding: 88px 28px 24px; overflow-y: auto; }

/* PR-4c-green Patrick 5/24 — day hero scene shown at the top of #conv-scroll
   (scrolls away with content so the input bar stays docked) AND above the
   paper-card on the note view. 1:1 square asset; max-width caps the visual so
   it doesn't swallow a mobile screen. Subtle paper aesthetic, no shadow. */
.day-hero {
  margin: 0 auto 24px;
  max-width: 360px;       /* ~92vw on a 390px viewport — roomy not overwhelming */
  width: 100%;
  border-radius: 14px;
  overflow: hidden;
  border: 0.5px solid var(--border-line);
  background: var(--paper-card);
}
.day-hero__img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  user-select: none;
}
/* On the note (paper-page) view the hero sits above the paper-card with a bit
   more breathing room and centered within the page's narrower column. */
.day-hero--note { margin: 0 auto 18px; }
@media (max-width: 480px) {
  /* Tighter on phones so the input bar / note buttons stay in view. */
  .day-hero       { max-width: 280px; margin-bottom: 18px; }
  .day-hero--note { max-width: 280px; }
}
/* Conversation messages — Vivi 5/24 polish:「字間距太大、要收緊一點」
   5/25 follow-up: AI 側仍然太鬆、再收一階 (1.55 → 1.4, margin 16 → 10).
   user 側已合適、不動. Font size + family unchanged. */
.msg-ai { font-family: var(--font-serif); font-size: 17px; line-height: 1.4; color: var(--text-primary); margin-bottom: 10px; white-space: pre-wrap; }
.msg-user-wrap { display: flex; justify-content: flex-end; margin-bottom: 12px; }
.msg-user { background: var(--bubble-user); padding: 10px 14px; border-radius: 16px 16px 4px 16px; max-width: 80%;
  font-family: var(--font-sans); font-size: 15px; line-height: 1.5; color: var(--text-primary); white-space: pre-wrap; }
.callback { background: var(--paper-card); border-left: 2px solid var(--green-walked); border-radius: 0 8px 8px 0;
  padding: 14px 18px; margin-bottom: 22px; }
.callback__label { font-family: var(--font-sans); font-size: 11px; letter-spacing: 1px; color: var(--text-secondary); margin-bottom: 8px; }
.callback__quote { font-family: var(--font-serif); font-style: italic; font-size: 15.5px; line-height: 1.75; color: var(--text-primary); }
.hint-italic { font-family: var(--font-serif); font-style: italic; font-size: 13px; color: var(--text-faint); }

.conv-input-bar { border-top: 0.5px solid var(--border-line); padding: 16px 28px 18px; background: var(--bg-mint); }
.conv-input-wrap { max-width: 540px; margin: 0 auto; }
.conv-input-row { display: flex; align-items: flex-end; gap: 10px; }
.conv-send-btn:disabled { opacity: 0.4; cursor: default; }
.conv-hint { margin-top: 10px; font-family: var(--font-sans); font-size: 11px; letter-spacing: 0.5px; color: var(--text-faint); }

/* §5.3 收尾 — token sweep; ✦ now gold per §1 */
/* 收尾 loading — Vivi 5/24:「太淡」 (paper aesthetic, no SaaS spinner).
   5/25 Vivi: 改米白底黑字 (was 薄荷底綠字 — 像 SaaS 通知、不像在等).
   ✦ star 維持金色當唯一點綴、breathe 動畫保留. 文字 JS 來回逐字打
   (student.js startClosureTypewriter) — 「教練在寫今天的字」打進→停→刪→再打 loop. */
.conv-closure { border-top: 0.5px solid var(--border-line); padding: 28px 28px 36px; text-align: center;
  background: var(--paper-card); opacity: 0; transition: opacity 400ms ease-out; }
.conv-closure.shown { opacity: 1; }
.conv-closure .star { color: var(--gold-accent); margin-right: 10px; font-family: var(--font-sans); font-size: 12px; display: inline-block; }
.conv-closure.shown .star { animation: paper-breathe 2.4s ease-in-out infinite; }
.conv-closure .text { font-family: var(--font-serif); font-style: italic; font-size: 16px; letter-spacing: 1.5px; color: var(--text-primary); }

.conv-input-bar.exiting { opacity: 0; transform: translateY(8px); transition: opacity 250ms ease-out, transform 250ms ease-out; }

.conv-waiting { display: flex; justify-content: center; align-items: center; margin: 40px 0 24px;
  opacity: 0; animation: conv-waiting-fade 400ms ease-out 100ms forwards; }
.conv-waiting .star { color: var(--gold-accent); margin-right: 8px; font-family: var(--font-sans); font-size: 9px; display: inline-block;
  animation: paper-breathe 2.4s ease-in-out infinite; }
.conv-waiting .text { font-family: var(--font-serif); font-style: italic; font-size: 13px; letter-spacing: 1px; color: var(--text-secondary); }
@keyframes conv-waiting-fade { to { opacity: 1; } }

/* Mid-conversation typing indicator — Vivi 5/24:「沒回饋會被當壞掉」.
   Left-aligned like AI message side. Tighter margins than .conv-waiting
   (which is a page-level kickoff/closure indicator); this sits snug under
   the user's just-sent bubble. ✦ paper-breathe carries the「I'm composing」
   signal — no SaaS spinner. */
.conv-typing { display: flex; align-items: center; margin: 4px 0 16px;
  opacity: 0; animation: conv-waiting-fade 300ms ease-out forwards; }
.conv-typing .star { color: var(--gold-accent); margin-right: 8px;
  font-family: var(--font-sans); font-size: 10px; display: inline-block;
  animation: paper-breathe 1.6s ease-in-out infinite; }
.conv-typing .text { font-family: var(--font-serif); font-style: italic;
  font-size: 14px; letter-spacing: 0.5px; color: var(--text-secondary); }

@keyframes paper-breathe {
  0%, 100% { opacity: 0.5; }
  50%      { opacity: 1; }
}

.conv-hint--chain {
  margin-top: 6px;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 11px;
  letter-spacing: 0.5px;
  color: var(--text-secondary);
  line-height: 1.55;
}

/* ════════════════════════════════════════════════════════════════
   §5.4 教練卡 / §5.5 Phase Report / §5.6 結業 — shared .paper-card
   ════════════════════════════════════════════════════════════════ */
.paper-page { background: var(--bg-mint); align-items: center; padding: 52px 24px 48px; }
.paper-card { max-width: 440px; width: 100%; padding: 38px 36px 30px; }
.paper-card--wide       { max-width: 480px; padding: 42px 42px 32px; }
.paper-card--graduation { max-width: 540px; padding: 48px 44px 36px; }
.paper-card__header { text-align: center; margin-bottom: 28px; }
.paper-card__eyebrow { font-family: var(--font-serif); font-size: 11px; letter-spacing: 4px; color: var(--green-walked); }
.paper-card__title { margin-top: 4px; font-family: var(--font-serif); font-size: 17px; letter-spacing: 1.5px; color: var(--green-forest); }
.paper-card__subtitle { margin-top: 10px; font-family: var(--font-serif); font-style: italic; font-size: 11px; letter-spacing: 3px; color: var(--text-secondary); }
.paper-card__divider { width: 24px; height: 0.5px; background: var(--gold-accent); margin: 14px auto 0; }
.paper-card__body { font-family: var(--font-serif); font-size: 14.5px; line-height: 2; color: var(--text-primary); white-space: pre-wrap; }
.paper-card__body p { margin-bottom: 18px; }
.paper-card__body p:last-child { margin-bottom: 0; }
.paper-card__sig { margin-top: 32px; text-align: right; font-family: var(--font-serif); font-style: italic; font-size: 14px; letter-spacing: 0.5px; color: var(--text-secondary); }

.status-row { margin-top: 32px; text-align: center; font-family: var(--font-serif); font-style: italic; font-size: 12px; letter-spacing: 1px; color: var(--text-secondary); }
.status-row .star { color: var(--gold-accent); margin-right: 6px; font-family: var(--font-sans); font-size: 9px; }

.btn-row { margin-top: 26px; display: flex; justify-content: center; gap: 12px; }

/* §5.5 Phase Report — 你的寶藏 (P4 green).
   Longer than a daily note (里程碑份量); PHASE N eyebrow in sans + gold;
   ✦ separator between teaching (上半 fixed §8) and breakthrough (下半 generated). */
.paper-card--phase { max-width: 480px; padding: 42px 36px 32px; }
.paper-card__eyebrow--phase {
  font-family: var(--font-sans);     /* §5.5: "PHASE N" sans 10 lts4 --gold-accent */
  font-size: 10px;
  letter-spacing: 4px;
  color: var(--gold-accent);
}
.phase-section-sep {
  margin: 28px auto;
  text-align: center;
  color: var(--gold-accent);
  font-family: var(--font-sans);
  font-size: 16px;
  letter-spacing: 8px;
  opacity: 0.85;
}

/* §5.6 graduation specifics */
.poem-block { margin: 40px auto 36px; text-align: center; }
.poem-line { font-family: var(--font-serif); font-size: 13px; line-height: 2.4; letter-spacing: 0.5px; color: var(--text-secondary); margin-bottom: 6px; }
.declaration-leadin { text-align: center; font-family: var(--font-serif); font-style: italic; font-size: 12px; letter-spacing: 2px; color: var(--green-walked); margin-bottom: 18px; }
.declaration { text-align: center; font-family: var(--font-serif); font-size: 19px; line-height: 2.1; letter-spacing: 1.5px; color: var(--green-forest); margin-bottom: 36px; }
.export-notice { margin-top: 18px; text-align: center; font-family: var(--font-serif); font-style: italic; font-size: 12px; color: var(--text-secondary); }

/* ════════════════════════════════════════════════════════════════
   /coach — separate aesthetic (admin), green sweep only at P0;
   full restyle for /coach lands in P5.
   ════════════════════════════════════════════════════════════════ */
.coach-shell { padding: 32px 28px; max-width: 960px; margin: 0 auto; background: var(--bg-mint); min-height: 100vh; }
.coach-header { padding-bottom: 16px; border-bottom: 0.5px solid var(--border-line); margin-bottom: 24px;
  display: flex; align-items: baseline; justify-content: space-between; }
.coach-title { font-family: var(--font-serif); font-size: 20px; letter-spacing: 2px; color: var(--green-forest); }
.coach-nav { font-family: var(--font-sans); font-size: 13px; color: var(--text-secondary); }
.coach-nav a { margin-left: 14px; }
.coach-list { display: grid; grid-template-columns: 1fr; gap: 8px; }
.coach-list__row { display: grid; grid-template-columns: 110px 1fr 110px 88px; gap: 12px;
  background: var(--paper-card); border: 0.5px solid var(--border-line); border-radius: 6px;
  padding: 12px 16px; align-items: center; font-family: var(--font-sans); font-size: 13px; color: var(--text-primary); cursor: pointer; }
.coach-list__sid { font-family: var(--font-sans); font-size: 13px; letter-spacing: 0.5px; }
.coach-list__email { color: var(--text-secondary); }
.coach-list__day { font-family: var(--font-serif); font-size: 13px; }
.coach-list__open { font-family: var(--font-serif); font-size: 13px; color: var(--text-secondary); text-align: right; }
.coach-section { margin-top: 32px; }
.coach-h2 { font-family: var(--font-serif); font-size: 14px; letter-spacing: 2px; color: var(--text-secondary); margin-bottom: 10px; }
/* P5 (PR-4c-green): 3×7 daily only — 週報 I/II/III column retired (spec 09 §10).
   Phase Reports render in a separate stacked section below the grid. */
.coach-mini-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; max-width: 480px;
  margin-bottom: 16px; }
.coach-mini-cell { height: 38px; border-radius: 4px; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-serif); font-size: 11px; color: var(--text-primary); padding: 0 4px;
  border: 0.5px solid var(--border-line); box-sizing: border-box;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis; min-width: 0; }
.coach-mini-cell--active   { background: var(--peach-today);  border-color: var(--green-walked); }
.coach-mini-cell--revealed { background: var(--green-walked); border-color: var(--green-walked); color: #FFFFFF; }
.coach-mini-cell--graduation { grid-column: 1 / -1; font-size: 12px; letter-spacing: 2px; height: 32px; }
.coach-pre { background: var(--paper-card); border: 0.5px solid var(--border-line); border-radius: 6px;
  padding: 16px 18px; font-family: var(--font-serif); font-size: 14px; line-height: 1.85; color: var(--text-primary); white-space: pre-wrap;
  overflow-wrap: anywhere; word-break: break-word;
  box-sizing: border-box; max-width: 100%; }

/* 5/26 Patrick — transcript 容器 (paper card) 視覺照 .coach-pre、但 white-space: normal.
   .coach-pre 是 pre-wrap、會把 renderTranscript 模板字串的縮排/換行當可見空白
   渲染出來 → 角色標籤跟 body 之間爆出大段空白. 訊息內文自己的換行由
   .coach-transcript-msg__body { white-space: pre-wrap } 保留. */
.coach-transcript-box { background: var(--paper-card); border: 0.5px solid var(--border-line);
  border-radius: 6px; padding: 16px 18px; font-family: var(--font-serif); font-size: 14px;
  line-height: 1.6; color: var(--text-primary); white-space: normal;
  overflow-wrap: anywhere; word-break: break-word; box-sizing: border-box; max-width: 100%; }

/* PR-4c-green Patrick 5/24 — coach-only transcript message rows (audience=coach
   逐字 review). Subtle role label + paper card, no SaaS chat bubbles. */
.coach-transcript-msg { margin-bottom: 9px; padding-bottom: 7px;
  border-bottom: 0.5px dashed var(--border-line); }
.coach-transcript-msg:last-child { border-bottom: none; margin-bottom: 0; padding-bottom: 0; }
.coach-transcript-msg__role { font-family: var(--font-sans); font-size: 10px;
  letter-spacing: 2px; color: var(--text-secondary); margin-bottom: 4px;
  text-transform: uppercase; }
.coach-transcript-msg--user .coach-transcript-msg__role { color: var(--green-walked); }
.coach-transcript-msg__time { font-family: var(--font-sans); font-size: 10px;
  color: var(--text-faint); margin-left: 8px; letter-spacing: 0; text-transform: none; }
.coach-transcript-msg__body { font-family: var(--font-serif); font-size: 14px;
  line-height: 1.55; color: var(--text-primary); white-space: pre-wrap;
  overflow-wrap: anywhere; word-break: break-word; }
.coach-transcript-empty { font-family: var(--font-serif); font-style: italic;
  font-size: 13px; color: var(--text-faint); text-align: center; }

/* ════════════════════════════════════════════════════════════════
   shared utilities
   ════════════════════════════════════════════════════════════════ */
.muted   { color: var(--text-faint); }
.hidden  { display: none !important; }
