/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

/*
 * 配色。深浅两套都只改这一组变量，别在具体的组件规则里写死颜色 ——
 * 写死一个就多一个在深色下瞎掉的地方。
 *
 * 主题挂在 <html data-theme> 上，服务端按 cookie 直接渲染出来，所以不会先闪一下白的。
 * 注意 Turbo Drive 只替换 body、不更新 html 上的属性 —— 所以切换主题的那个表单
 * 必须 data-turbo: false 走整页加载，见 shared/_theme_switch。
 */
:root {
  --ink: #16181d;
  --ink-soft: #5b6270;
  --ink-faint: #8b93a1;
  --line: #e4e7ec;
  --bg: #fbfbfc;
  --panel: #ffffff;
  /* 品牌色取自 icon.svg：夜空和书页的靛蓝，山与河的青绿 */
  --brand: #2a52b5;
  --brand-alt: #2f9aa8;
  --accent: #2a52b5;
  --accent-soft: #eaf0fd;
  --accent-ink: #1c3a86;
  --on-accent: #ffffff;
  --warn: #b8500f;
  --warn-soft: #fdf0e7;
  --ok: #1c7c4a;
  --alt-soft: #e6f8fb;
  --alt-ink: #10707f;
  --neutral-soft: #f2f3f5;
  --github: #1f2328;
  --github-hover: #32383f;
  --radius: 10px;
  color-scheme: light;
}

/*
 * 深色的两种进法：跟随系统（没显式选浅色时），或者用户自己选了深色。
 * 两条规则内容一样，用 :where() 合起来会把特异性降到 0、反被 :root 盖掉，所以老实写两遍。
 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ink: #e7eaef;
    --ink-soft: #a2aab7;
    --ink-faint: #798391;
    --line: #2a2e37;
    --bg: #0f1115;
    --panel: #171a20;
    --brand: #7fa6f0;
    --brand-alt: #57cdd6;
    --accent: #7fa6f0;
    --accent-soft: #17203a;
    --accent-ink: #b3c8f7;
    --on-accent: #0d1424;
    --warn: #e8935c;
    --warn-soft: #33231a;
    --ok: #4ec98a;
    --alt-soft: #12303a;
    --alt-ink: #6ed3e8;
    --neutral-soft: #22262e;
    --github: #21262d;
    --github-hover: #30363d;
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --ink: #e7eaef;
  --ink-soft: #a2aab7;
  --ink-faint: #798391;
  --line: #2a2e37;
  --bg: #0f1115;
  --panel: #171a20;
  --brand: #7fa6f0;
  --brand-alt: #57cdd6;
  --accent: #7fa6f0;
  --accent-soft: #17203a;
  --accent-ink: #b3c8f7;
  --on-accent: #0d1424;
  --warn: #e8935c;
  --warn-soft: #33231a;
  --ok: #4ec98a;
  --alt-soft: #12303a;
  --alt-ink: #6ed3e8;
  --neutral-soft: #22262e;
  --github: #21262d;
  --github-hover: #30363d;
  color-scheme: dark;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.7 -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB",
        "Microsoft YaHei", "Segoe UI", Roboto, sans-serif;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

.wrap { max-width: 820px; margin: 0 auto; padding: 0 20px 80px; }
.wrap--wide { max-width: 1040px; }

/* 顶栏 */
.masthead { border-bottom: 1px solid var(--line); background: var(--panel); margin-bottom: 32px; }
.masthead__inner {
  max-width: 1040px; margin: 0 auto; padding: 14px 20px;
  display: flex; align-items: center; gap: 22px; flex-wrap: wrap;
}
.masthead__brand { display: flex; align-items: center; gap: 8px; }
.masthead__brand:hover { text-decoration: none; }
.masthead__mark { display: block; border-radius: 6px; }

/* 字标不拆词，整体一个颜色。 */
.wordmark { font-size: 18px; letter-spacing: -0.3px; font-weight: 700; color: var(--ink); }
/* 中文页面上跟在字标后面的那个中文名。小一号、淡一档 —— 它是注解，不是第二个标题。
   和字标之间的空隙由 .masthead__brand 的 gap 给，别再加 margin。 */
.wordmark__aka { font-size: 13px; font-weight: 600; color: var(--ink-faint); letter-spacing: 0; }
.masthead nav { display: flex; gap: 18px; }
.masthead nav a { color: var(--ink-soft); }
/*
 * 当前在哪一段就点亮哪一个（见 ApplicationHelper#nav_link）。
 * 下划线用 ::after 画，不用 border/padding —— 后者会把整条顶栏撑高一圈。
 * 也不贴着顶栏那条底边画：窄屏上这一排会折到第二行，贴底边就飘到别处去了。
 */
.masthead__link { position: relative; }
.masthead nav a.masthead__link--on { color: var(--ink); font-weight: 600; }
.masthead__link--on::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -6px;
  height: 2px; border-radius: 2px; background: var(--accent);
}
.masthead__spacer { flex: 1; }
.masthead__user { color: var(--ink-faint); font-size: 13px; display: flex; align-items: center; gap: 10px; }
/* 头像 + 昵称那一小块是改昵称和头像的入口，颜色不跟一般链接（顶栏里那些是导航） */
.masthead__me { display: flex; align-items: center; gap: 8px; color: inherit; text-decoration: none; }
.masthead__me:hover { color: var(--ink); }

/*
 * 头像。首字母那层永远在，第三方图片盖在它上面 —— 图片取不到时 JS 会把 <img> 摘掉
 * （avatar_controller.js），露出下面这层，而不是一个碎图标。尺寸由 --avatar-size 传进来。
 */
.avatar {
  position: relative; flex: none;
  width: var(--avatar-size, 22px); height: var(--avatar-size, 22px);
}
.avatar__initial, .avatar__img {
  position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 50%;
}
.avatar__initial {
  display: flex; align-items: center; justify-content: center;
  background: var(--accent-soft); color: var(--accent-ink);
  font-size: calc(var(--avatar-size, 22px) * 0.5); font-weight: 600; line-height: 1;
}
/* 图片不给底色：慢或者取不到的时候是透明的，露出下面那层首字母，不是一块灰方块 */
.avatar__img { object-fit: cover; }

/* 改资料那页的头像预览：大一号的头像 + 一句「这张是哪来的」 */
.avatar-preview { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }

/* 通用块 */
.panel {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 20px;
}
.stack > * + * { margin-top: 16px; }
.muted { color: var(--ink-soft); }
.faint { color: var(--ink-faint); font-size: 13px; }
.lede { color: var(--ink-soft); font-size: 16px; margin: -6px 0 28px; }

h1 { font-size: 26px; letter-spacing: -0.4px; margin: 0 0 12px; }
h2 { font-size: 19px; margin: 36px 0 14px; }
h3 { font-size: 15px; margin: 0 0 6px; }

/* 按钮 */
.btn {
  display: inline-block; border: 1px solid var(--line); background: var(--panel);
  color: var(--ink); border-radius: 8px; padding: 8px 16px; font-size: 14px;
  cursor: pointer; font-family: inherit; line-height: 1.5;
}
.btn:hover { text-decoration: none; border-color: var(--ink-faint); }
.btn--primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn--primary:hover { filter: brightness(1.08); }
.btn--danger { color: var(--warn); }
.btn--github, .btn--google { display: inline-flex; align-items: center; gap: 7px; }
.btn--github {
  background: var(--github); border-color: var(--github); color: #fff;
}
.btn--github:hover { background: var(--github-hover); border-color: var(--github-hover); }
/* Google 按钮按品牌规范走中性底色 + 四色 G，底和字都取变量，深色模式下自动跟着变 */
.btn--google { background: var(--panel); border-color: var(--line); color: var(--ink); }
.btn--google:hover { border-color: var(--ink-faint); }
.btn[disabled] { opacity: .45; cursor: not-allowed; }
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.btn--small { padding: 5px 12px; font-size: 13px; }
/* 「复制全文」点完那两秒的样子，见 clipboard_controller.js */
.btn--copied { color: var(--ok); border-color: var(--ok); }
/* 复制那一行摆在标题底下，所以上下都要留一点；position 是给问号那个气泡定位用的
   （气泡贴着这一行的左边展开，不贴问号 —— 问号在行的中间，贴着它会顶出屏幕右侧）。 */
.copy-row { position: relative; margin: 14px 0 20px; }

/* 问号：一句解释藏在后面，鼠标放上去或者键盘 focus 上去才展开。按钮要摆在
   页面靠上的位置才好找，旁边挂一长句话会把标题那块挤散，但那句话不能没有。 */
.hint { display: inline-flex; }
.hint__mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 17px; height: 17px; border-radius: 50%; cursor: help;
  border: 1px solid var(--line); background: var(--panel);
  color: var(--ink-faint); font-size: 11px; line-height: 1;
}
.hint__mark:hover, .hint__mark:focus-visible { color: var(--ink); border-color: var(--ink-faint); }
.hint__bubble {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 20;
  width: max-content; max-width: min(300px, calc(100vw - 40px));
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 8px 11px; font-size: 12px; line-height: 1.7; color: var(--ink-soft);
  box-shadow: 0 8px 24px rgb(0 0 0 / 12%);
  opacity: 0; visibility: hidden; transition: opacity .12s;
}
/* focus-within 那条是给键盘和触屏留的：手机上没有 hover，点一下问号让它得到焦点 */
.hint:hover .hint__bubble, .hint:focus-within .hint__bubble { opacity: 1; visibility: visible; }

/* 表单 */
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 13px; color: var(--ink-soft); margin-bottom: 6px; }
.field input, .field textarea, .field select {
  width: 100%; padding: 9px 12px; border: 1px solid var(--line);
  border-radius: 8px; font: inherit; background: var(--panel); color: var(--ink);
}
/* 勾选框和单选钮不吃那条 width: 100% —— 吃了会被抻满一行，自己占一行居中摆着，
   标签文字掉到下一行去。四处都是「控件在左、文字紧跟在右」的写法（.style-option__label
   那个 margin-left 就是为它留的）。 */
.field input[type="checkbox"], .field input[type="radio"] { width: auto; }
.field input:focus, .field textarea:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
.field textarea { resize: vertical; }
.field__hint { font-size: 12px; color: var(--ink-faint); margin-top: 5px; }

/* 一行摆完的小表单（后台拉黑那条：选时长 + 写原因 + 按钮）。.field 那套是一行一个控件的
   竖排，摆不下这种；颜色照样全走变量，不然深色模式下这一行会瞎掉。 */
.inline-form { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 10px; }
.inline-form input, .inline-form select {
  padding: 7px 10px; border: 1px solid var(--line); border-radius: 8px;
  font: inherit; background: var(--panel); color: var(--ink);
}
/* 输入框自己长起来（下拉框和按钮按内容宽），不然搜索框窄到看不全 placeholder */
.inline-form input { flex: 1 1 220px; max-width: 420px; }
.inline-form input:focus, .inline-form select:focus {
  outline: 2px solid var(--accent-soft); border-color: var(--accent);
}
/* 额度计数器（text_budget_controller 填的「247 / 1000」）。只有数字，不用翻译。 */
.field__hint--count { margin: 5px 0 0; text-align: right; font-variant-numeric: tabular-nums; }
.field__hint--over { color: var(--warn); }

/* 提示条 */
.flash { border-radius: var(--radius); padding: 11px 16px; margin-bottom: 22px; font-size: 14px; }
.flash--notice { background: var(--accent-soft); color: var(--accent-ink); }
.flash--alert { background: var(--warn-soft); color: var(--warn); }
.errors { background: var(--warn-soft); color: var(--warn); border-radius: 8px; padding: 10px 16px; margin-bottom: 16px; font-size: 14px; }
.errors ul { margin: 0; padding-left: 18px; }

/* 配乐。颜色一律走变量，不然深色模式下会瞎掉一块。 */
.soundtrack {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px 18px; margin: 18px 0;
}
.soundtrack__label { font-size: 13px; color: var(--ink-faint); letter-spacing: 1px; margin-bottom: 8px; }
.soundtrack__title { font-weight: 600; margin-bottom: 8px; }
.soundtrack__meta { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }
/* 原生控件占满宽度，高度交给浏览器 —— 各家的控件条不一样高，写死会裁掉按钮 */
.soundtrack__player { width: 100%; }
.soundtrack__credit { margin: 10px 0 0; font-size: 13px; }

/* 问题池 */
.realm-nav { margin-bottom: 28px; }
/* 分类分组。整个 <details> 做成一张卡片，summary 是卡片头，展开后露出里面的题卡。
   折叠时也是一块完整的面，和周围有明确边界；展开后 summary 与网格分两层，不会糊成一屏。 */
.category {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); margin-bottom: 12px;
  overflow: hidden;
}
.category__name {
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  font-size: 14px; font-weight: 600; color: var(--ink-soft);
  letter-spacing: 0.5px;
  padding: 14px 18px;
  list-style: none; /* Firefox 的默认三角 */
}
.category__name::-webkit-details-marker { display: none; }
.category__name:hover { color: var(--ink); background: var(--neutral-soft); }
.category__name:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.category__count { letter-spacing: 0; font-weight: 400; }
/* 折叠箭头顶到最右边，整行都是点击区 */
.category__name::after {
  content: ""; flex: none; width: 6px; height: 6px; margin-left: auto;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(-45deg); transition: transform .15s ease;
}
.category[open] > .category__name::after { transform: translateY(1px) rotate(45deg); }
.category[open] > .category__name { border-bottom: 1px solid var(--line); }
.topic-grid {
  display: grid; gap: 10px;
  padding: 16px 18px; background: var(--bg);
}
/* 问题池以外的地方（比如「我的对话」上那几个引子）直接摆在页面上，不用那层内嵌底色 */
.topic-grid--flush { padding: 0; background: none; }
.topic-card {
  display: block; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px 18px; color: var(--ink);
}
.topic-card:hover { text-decoration: none; border-color: var(--accent); }
.topic-card__title { font-weight: 600; margin-bottom: 4px; }
.topic-card__summary { color: var(--ink-soft); font-size: 14px; }
.topic-card__meta { color: var(--ink-faint); font-size: 12px; margin-top: 8px; }

/* 练功房。卡片和列表复用问题池那一套（.topic-card / .topic-grid），
   新样式只有下面这几条。 */
.drill-stars { letter-spacing: 1px; color: var(--accent); cursor: help; }
/* 一行事实：难度 · 时长 · 主考。**不要用 flex** —— 分隔符是 join 出来的文本节点，
   在 flex 里会变成独立的一格，gap 加在它两边，写出来是「★★★★★ ·约 60 分钟」。 */
.drill-meta { font-size: 13px; line-height: 1.9; margin: 0; }

/* 写回复那一块，跟上面那串回复隔开一点 */
.comment-form { margin-top: 16px; }

/* 按标签筛那一排。徽章本来是不可点的标记，这里当筛选用，所以要有 hover。 */
.tag-filter { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 18px; }
.tag-filter .badge { cursor: pointer; }
.tag-filter a.badge:hover { text-decoration: none; filter: brightness(0.96); }

/* 「我练过的」那条入口。从前是一行 faint 小字，混在筛选和题卡之间看不见，
   所以给它一整条能点的面 —— 和题卡同宽、hover 时边框变色，跟 .topic-card 一个手感。
   里面**只有事实**（这个系列练过几道），不写「该复习了」。 */
.drill-practiced {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--accent-soft); border: 1px solid var(--accent);
  border-radius: var(--radius); padding: 13px 16px; margin: 0 0 18px;
  color: var(--accent-ink); font-size: 14px;
}
.drill-practiced:hover { text-decoration: none; filter: brightness(0.97); }
.drill-practiced__label { font-weight: 600; }
.drill-practiced__count { font-size: 13px; opacity: 0.8; }
/* 右端那个「进去看」的尖角。同 .category__name 那个箭头，只是指向右边。 */
.drill-practiced::after {
  content: ""; flex: none; width: 6px; height: 6px; margin-left: auto;
  border-top: 1.5px solid currentColor; border-right: 1.5px solid currentColor;
  transform: rotate(45deg); color: var(--ink-faint);
}

/* 打卡留下的痕迹。只有事实（几次、上次哪天），所以只是换个颜色，不做徽章。 */
.drill-mark { color: var(--alt-ink); }
/* 打卡时顺手记的那句，只有自己看得到 */
.drill-note {
  margin: 0; padding: 2px 0 2px 12px; border-left: 2px solid var(--line);
  color: var(--ink-soft); font-size: 14px;
}
/* 以前那几次。只列事实（日期 + 当时那句），所以不加序号、不加编号徽章。 */
.drill-history { list-style: none; margin: 6px 0 0; padding: 0; }
.drill-history li + li { margin-top: 10px; }
.drill-history .muted { font-size: 13px; }
.drill-history .drill-note { margin-top: 3px; }

/* 提示词正文在 hero-prompts 那个公开仓库里（见 DrillSeries::REPO_URL），两处指过去。
   都用 GitHub 那个标：铅笔会让人以为能在站上改，「查看源码」把它说成读物 —— 而那些
   文件末尾就是底牌。

   索引页那条带摆在题目列表下面，**有意比 .drill-practiced 素**（那条是通往自己记录
   的路，用强调色；这条是一句关于这批内容的事实，抢不得）。 */
.drill-source {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 13px 16px; margin: 26px 0 0;
  color: var(--ink-soft); font-size: 14px;
}
.drill-source:hover { text-decoration: none; border-color: var(--ink-faint); }
/* 标和第一行文字对齐 —— 两行的时候居中会把它顶到中间，看着像浮着 */
.drill-source svg { flex: none; margin-top: 3px; color: var(--ink-faint); }
.drill-source:hover svg { color: var(--ink); }
.drill-source__text { display: block; }
.drill-source__label { display: block; font-weight: 600; color: var(--ink); }
.drill-source__note { display: block; margin-top: 3px; font-size: 13px; }

/* 题目页 meta 里那一行。只是一行小链接，不是按钮 —— 这一页唯一的主动作是上面那一排。 */
.drill-source-link { margin: 0; font-size: 13px; }
.drill-source-link a { display: inline-flex; align-items: center; gap: 6px; color: var(--ink-soft); }
.drill-source-link a:hover { color: var(--ink); }
.drill-source-link .muted { margin-left: 6px; }

/* 「复制提示词 + 去某一家聊」那一排。摆在标题底下，所以上下都要留一点。 */
.handoff {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px 18px; margin: 14px 0 24px;
}
.handoff__lede { margin: 0 0 12px; font-size: 14px; color: var(--ink-soft); }
.handoff .btn-row { margin-bottom: 10px; }
/* 那句提示常常是空的（还没点过），空着就不该占一行高度 */
.handoff__status { margin: 0; font-size: 13px; color: var(--ink-faint); }
.handoff__status:empty { display: none; }
.handoff__status--ok { color: var(--ok); }
.handoff .faint { margin: 6px 0 0; }

/* 这套东西怎么用。两处都收在折叠里（.category），所以这里不再自带卡片那层面 ——
   索引页上默认摊开、收起来会记住，题目页上默认收着。 */
.guide h3 { color: var(--ink-soft); }
.guide ol, .guide ul { margin: 0; padding-left: 20px; font-size: 14px; line-height: 1.9; color: var(--ink-soft); }
.guide__commands { list-style: none; padding-left: 0; }
.guide__commands code { margin-right: 6px; }
/* 折叠里放文字（不是题卡）时的内边距，跟 .topic-grid 那层底色一致 */
.category__body { padding: 16px 18px; background: var(--bg); }

/* 列表项 */
.item { border-bottom: 1px solid var(--line); padding: 16px 0; }
.item:last-child { border-bottom: 0; }
.item__title { font-weight: 600; font-size: 16px; color: var(--ink); }
.item__meta { color: var(--ink-faint); font-size: 13px; margin-top: 4px; }
.empty { color: var(--ink-faint); padding: 28px 0; text-align: center; }

/* 对话 */
.msg { display: flex; gap: 12px; padding: 14px 0; border-bottom: 1px solid var(--line); }
.msg__who {
  flex: 0 0 56px; font-size: 12px; color: var(--ink-faint); padding-top: 3px;
}
.msg__body { flex: 1; word-break: break-word; min-width: 0; }
.msg__body--plain { white-space: pre-wrap; }
.msg--assistant .msg__who { color: var(--accent); }
.msg__cursor {
  display: inline-block; width: 7px; height: 15px; background: var(--accent);
  vertical-align: text-bottom; animation: blink 1s steps(2) infinite;
}
@keyframes blink { 50% { opacity: 0; } }

.composer { margin-top: 20px; }
.composer__waiting { color: var(--ink-faint); font-size: 14px; padding: 12px 0; }

/* 大模型写的正文渲染成 HTML 之后的排版（见 ApplicationHelper#markdown）：
   顾问回复、解梦解读、帖子正文都套这一组。
   注意这里不能有 white-space: pre-wrap —— markdown 已经把换行变成标签了，
   再留着会多出一倍空行。颜色一律走变量，写死一个就多一个在深色下瞎掉的地方。 */
.prose { word-break: break-word; }
.prose > :first-child { margin-top: 0; }
.prose > :last-child { margin-bottom: 0; }
.prose p { margin: 0 0 14px; }
.prose h1, .prose h2, .prose h3, .prose h4, .prose h5, .prose h6 {
  margin: 22px 0 10px; line-height: 1.35; font-weight: 600;
}
.prose h1 { font-size: 20px; }
.prose h2 { font-size: 18px; }
.prose h3, .prose h4, .prose h5, .prose h6 { font-size: 16px; }
.prose ul, .prose ol { margin: 0 0 14px; padding-left: 22px; }
.prose li { margin: 4px 0; }
.prose li > p { margin: 0; }
.prose blockquote {
  margin: 0 0 14px; padding: 2px 0 2px 14px;
  border-left: 3px solid var(--line); color: var(--ink-soft);
}
.prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.9em;
  background: var(--neutral-soft); padding: 1px 5px; border-radius: 4px;
}
.prose pre {
  margin: 0 0 14px; padding: 12px 14px; overflow-x: auto;
  background: var(--neutral-soft); border-radius: 8px;
}
.prose pre code { background: none; padding: 0; }
.prose hr { border: 0; border-top: 1px solid var(--line); margin: 20px 0; }
.prose table { border-collapse: collapse; margin: 0 0 14px; }
.prose th, .prose td { border: 1px solid var(--line); padding: 6px 10px; text-align: left; }
.prose th { background: var(--neutral-soft); font-weight: 600; }

/* 流式光标接在最后一个块的尾巴上，而不是自己占一个元素 ——
   markdown 渲染出来的 <p> 是块级的，单独一个 <span> 会被挤到下一行去。

   打字机在跑的时候得换一个落脚处（prose--typing 那条）：那会儿后面几块还藏着
   （display: none），挂在最后一个 DOM 子元素上的光标会跟着一起看不见。
   两条同时命中的是同一个 ::after，不会冒出两个光标。 */
.prose--streaming > :last-child::after,
.prose--typing > [data-typewriter-tail]::after {
  content: ""; display: inline-block; width: 7px; height: 15px;
  background: var(--accent); vertical-align: text-bottom; margin-left: 3px;
  animation: blink 1s steps(2) infinite;
}

/* 帖子 */
.post__body { word-break: break-word; }
.takeaway {
  border-left: 3px solid var(--accent); background: var(--accent-soft);
  padding: 14px 18px; border-radius: 0 8px 8px 0; margin: 22px 0;
}
.takeaway__label { font-size: 12px; color: var(--ink-faint); margin-bottom: 4px; }
.badge {
  display: inline-block; font-size: 11px; padding: 2px 8px; border-radius: 20px;
  background: var(--accent-soft); color: var(--accent-ink); vertical-align: middle;
}
.badge--draft { background: var(--neutral-soft); color: var(--ink-soft); }
.badge--alt { background: var(--alt-soft); color: var(--alt-ink); }
.badge--warn { background: var(--warn-soft); color: var(--warn); }

/* 「此刻」。一行一个问法，标签在左，选项按钮在右。 */
.check-in-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  padding: 10px 0; border-bottom: 1px solid var(--line);
}
.check-in-row:last-child { border-bottom: 0; }
.check-in-row__label { flex: 0 0 84px; font-size: 13px; color: var(--ink-faint); }
/* 回看那个汇总在窄列里排不开：交给 flex-wrap 的话，短的那行留在标签右边、长的换到下一行，
   三行对不齐很难看。所以标签和数值一律分两行。 */
.check-in-row--stacked { display: block; }
.check-in-row--stacked .check-in-row__label { margin-bottom: 2px; }
/* 手机上标签和选项排不到一行里。交给 flex-wrap 的话是「选项多的那行标签跑到上面去、
   选项少的还留在右边」，三行参差不齐 —— 所以一律分两行。 */
@media (max-width: 560px) {
  .check-in-row { display: block; }
  .check-in-row__label { margin-bottom: 6px; }
}
/* 正等着人回答的那条。点通知正文过来的人落地就得一眼看见是要答这个。 */
.panel--asking { border-color: var(--accent); background: var(--accent-soft); }
.panel--asking h2 { margin-top: 0; }
.btn--tiny { padding: 2px 8px; font-size: 12px; }

/*
 * 「什么时候问」那两排勾选框（周几 7 个、钟点 24 个）。
 *
 * 24 个原生 checkbox 并排太挤也点不准，所以把勾藏在格子里、拿 :has(:checked) 上色 ——
 * 勾本身还在（键盘和读屏照旧），只是看不见。input 铺满整格，所以点格子任何位置都算点勾。
 */
.pick-grid { display: grid; gap: 6px; margin-bottom: 8px; }
.pick-grid--days { grid-template-columns: repeat(7, minmax(0, 1fr)); }
/* 钟点排 6 的倍数，24 个正好铺满：手机上 6 列 4 行，宽一点 12 列 2 行。
   不排一行 24 个 —— 这一列本来就窄（两列布局的左边那列），24 格挤到 17px 就装不下「23」了。 */
.pick-grid--hours { grid-template-columns: repeat(6, minmax(0, 1fr)); }
@media (min-width: 560px) {
  .pick-grid--hours { grid-template-columns: repeat(12, minmax(0, 1fr)); }
}
.pick {
  position: relative; display: flex; align-items: center; justify-content: center;
  min-height: 30px; padding: 4px 2px; border: 1px solid var(--line); border-radius: 7px;
  font-size: 12px; color: var(--ink-faint); cursor: pointer; user-select: none;
}
.pick input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  margin: 0; opacity: 0; cursor: pointer;
}
.pick:has(input:checked) {
  border-color: var(--accent); background: var(--accent-soft); color: var(--accent-ink); font-weight: 600;
}
.pick:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

/*
 * 「此刻」的两列布局。左列是每天都要用的（记一条、写今天那句），右列专门放回看 ——
 * 回看原来压在整页最底下，翻到才看得见，而它是这个板块唯一的产出。
 *
 * 两列并排页面就矮了一半，所以这一页用 wrap--wide：820px 里塞两列的话，
 * 「现在记一条」那五个选项按钮换到长一点的语言就换行了。
 */
.checkin-head { max-width: 620px; }
/* 上边距自己带着：两列的第一个 h2 把 margin-top 清掉了，不然待答那条紧贴着下面的标题 */
.checkin-layout { display: grid; gap: 28px; align-items: start; margin-top: 28px; }
@media (min-width: 900px) {
  .checkin-layout { grid-template-columns: minmax(0, 62fr) minmax(0, 38fr); gap: 40px; }
}
/* 每列第一个 h2 不要那 36px 上边距，不然两列的顶端对不齐 */
.checkin-layout__main > :first-child,
.checkin-layout__aside > :first-child { margin-top: 0; }

/*
 * 设一次就不动的那两块（节奏、设备）折起来。原生 details，不写 JS ——
 * 和问题池那个分类手风琴（.category）是同一个做法，箭头也用同一套变换。
 * 收起来的时候标题行上必须写当前值，见 ApplicationHelper#check_in_rhythm_summary。
 */
.fold {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); margin-top: 12px;
}
.fold__summary {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  padding: 14px 18px; cursor: pointer;
  list-style: none; /* Firefox 的默认三角 */
}
.fold__summary::-webkit-details-marker { display: none; }
.fold__summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.fold__name { font-weight: 600; }
.fold__value { margin-left: auto; font-size: 13px; color: var(--ink-faint); }
.fold__summary::after {
  content: ""; flex: none; align-self: center; width: 6px; height: 6px;
  border-right: 1.5px solid var(--ink-faint); border-bottom: 1.5px solid var(--ink-faint);
  transform: translateY(-2px) rotate(-45deg); transition: transform .15s ease;
}
.fold[open] > .fold__summary::after { transform: translateY(1px) rotate(45deg); }
.fold__body { padding: 16px 18px 18px; border-top: 1px solid var(--line); }
.fold__body > :last-child { margin-bottom: 0; }

/*
 * 那面日历。一列一周（周一排头，跟别处的周序一致），一格一天，
 * 格子深浅是那天记了几条，写过「想做的」那天多一圈描边。
 *
 * 格子跟着这一列的宽度伸缩（flex: 1），所以不横向滚动 —— 半年 26 列在回看那一列里
 * 一格 11px 上下，正好还点得动。max-width 是给窄屏用的：单列布局下这一列变得很宽，
 * 不压一下格子会大成一堆瓷砖。
 */
.calendar { margin-top: 14px; }
.calendar__grid { display: flex; gap: 3px; max-width: 400px; padding-top: 16px; }
.calendar__week {
  position: relative; flex: 1 1 0; min-width: 0;
  display: grid; grid-template-rows: repeat(7, 1fr); gap: 3px;
}
/* 月份标签浮在这一列上方那 16px 里，不占网格的位置 */
.calendar__month {
  position: absolute; top: -16px; left: 0;
  font-size: 11px; line-height: 1; color: var(--ink-faint); white-space: nowrap;
}
/* 最后一列那个标签靠右对齐 —— 左对齐的话它会顶出网格右边缘（当月的标签总在最后几列） */
.calendar__week:last-child .calendar__month { left: auto; right: 0; }
.calendar__cell { display: block; aspect-ratio: 1; border-radius: 2px; background: var(--line); }
/* 还没到的那天：占位不着色 */
.calendar__cell--void { background: none; }
/* 四档都是主色和面板底色按比例混出来的，所以深浅两套配色各自都成立 */
.calendar__cell--l1 { background: color-mix(in srgb, var(--accent) 28%, var(--panel)); }
.calendar__cell--l2 { background: color-mix(in srgb, var(--accent) 52%, var(--panel)); }
.calendar__cell--l3 { background: color-mix(in srgb, var(--accent) 76%, var(--panel)); }
.calendar__cell--l4 { background: var(--accent); }
/* 那天写过「想做的」。描边而不是换颜色 —— 颜色那一维已经被「记了几条」占了 */
.calendar__cell--wrote { box-shadow: inset 0 0 0 1.5px var(--ink-soft); }
a.calendar__cell:hover, a.calendar__cell:focus-visible { outline: 1px solid var(--ink); outline-offset: 1px; }
.calendar__legend {
  display: flex; align-items: center; gap: 4px;
  margin-top: 8px; font-size: 12px;
}
/* 图例那几格不在网格里，得自己给个尺寸 */
.calendar__legend .calendar__cell { width: 11px; }
.calendar__legend .faint { margin: 0 4px; }

/*
 * 回看那条时间轴。轴线就是条目那一列的左边框，一天接一天连起来是不断的一条，
 * 而且落在回看这一列的左边界上 —— 所以这一段外面不能再套 .panel，套了就又缩回去了。
 *
 * 日期钉在轴线左边那道页边里，position: sticky 让它在自己那一天的范围内跟着滚动停住，
 * 往下翻的时候「现在读的是哪天」一直在视野里。窄屏没有页边可用，见下面那条 media query。
 */
.timeline { margin-top: 18px; }
.timeline__day { display: grid; grid-template-columns: 76px minmax(0, 1fr); }
.timeline__date {
  position: sticky; top: 14px; align-self: start;
  margin: 0; padding: 4px 16px 0 0; text-align: right;
  font-size: 12px; font-weight: 400; color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
/* 日期是那一天的入口，但别让它比条目本身还抢眼 —— 平时跟着页边那个灰，划过去才亮 */
.timeline__date a { color: inherit; text-decoration: none; }
.timeline__date a:hover, .timeline__date a:focus-visible { color: var(--accent); text-decoration: underline; }
.timeline__entries {
  padding: 0 0 20px 20px;
  border-left: 1px solid var(--line);
}
.timeline__day:last-child .timeline__entries { padding-bottom: 0; }
.timeline__list { margin: 0; padding: 0; list-style: none; }
/* 那天写的想做的，压在这一天所有条目上面 —— 「本来打算做什么」和「实际什么状态」要对得上看 */
.timeline__intention {
  margin: 4px 0 2px; padding-left: 10px;
  border-left: 2px solid var(--accent);
  font-size: 14px; color: var(--ink-soft); word-break: break-word;
}
.timeline__entry {
  position: relative;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px;
  padding: 5px 0; line-height: 1.6;
}
/* 轴上那个点。左边距 20px 加 1px 边框，点 7px，-24px 正好压在线上。 */
.timeline__entry::before {
  content: ""; position: absolute; left: -24px; top: 13px;
  width: 7px; height: 7px; border-radius: 50%; background: var(--ink-faint);
}
/* 最近那一条给个亮点，一眼看到上一次是什么状态 */
.timeline__day:first-child .timeline__entry:first-child::before { background: var(--accent); }
.timeline__time { font-size: 13px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.timeline__kind { font-size: 13px; color: var(--ink-soft); }
.timeline__answer { font-size: 14px; color: var(--ink); }

/* 某一天那页。没有轴线（就一天，连不起来），所以是一条条排开，不用 .timeline 那套 */
.day-intention {
  margin: 0; padding-left: 12px;
  border-left: 2px solid var(--accent);
  color: var(--ink); word-break: break-word;
}
.day-entries { margin: 0; padding: 0; list-style: none; }
.day-entry {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px;
  padding: 7px 0; line-height: 1.6; border-top: 1px solid var(--line);
}
.day-entry:first-child { border-top: 0; padding-top: 0; }
.day-entry__time { font-size: 13px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.day-entry__kind { font-size: 13px; color: var(--ink-soft); }
.day-entry__answer { font-size: 14px; color: var(--ink); }

/* 窄屏上左边没有页边可以让日期浮着，改成压在这一天的轴线上方、左对齐 */
@media (max-width: 560px) {
  .timeline__day { grid-template-columns: minmax(0, 1fr); }
  .timeline__date { position: static; text-align: left; padding: 0 0 4px; }
  .timeline__entries { padding-left: 16px; }
  .timeline__entry::before { left: -20px; }
}

/* 积分 */
.credits-balance { display: flex; align-items: baseline; gap: 6px; }
.credits-balance__number { font-size: 40px; font-weight: 700; color: var(--accent); line-height: 1; }
.credits-balance__unit { color: var(--ink-faint); font-size: 14px; }
.credits-delta { display: inline-block; min-width: 46px; font-variant-numeric: tabular-nums; }
.credits-delta--in { color: var(--ok); }
.credits-delta--out { color: var(--warn); }

/* 解梦 */
.dream-composer .field { margin-bottom: 12px; }
.dream__body { white-space: pre-wrap; word-break: break-word; color: var(--ink-soft); }
.dream__reading { word-break: break-word; }

/* 心象图 */
.vision__image { display: block; width: 100%; height: auto; border-radius: 8px; }
.vision__placeholder { color: var(--ink-faint); text-align: center; padding: 48px 0; }
.vision-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 14px; }
.vision-tile {
  display: block; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; color: var(--ink);
}
.vision-tile:hover { text-decoration: none; border-color: var(--accent); }
.vision-tile__image { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; }
.vision-tile__blank {
  aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
  color: var(--ink-faint); font-size: 13px; background: var(--accent-soft);
}
.vision-tile__caption { padding: 10px 12px; font-size: 13px; }
.vision-tile__caption .faint { display: block; margin-top: 2px; }
.style-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.style-option {
  display: block; border: 1px solid var(--line); border-radius: 8px;
  padding: 10px 12px; cursor: pointer;
}
.style-option:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.style-option__label { font-weight: 600; margin-left: 6px; }
.style-option__hint { display: block; color: var(--ink-faint); font-size: 12px; margin-top: 2px; }

/* 首页 */
.hero { margin-bottom: 42px; }
/* 大标题上面那行站名。和别处的小字一样淡，只是把字距拉开一点 —— 它是个名字，不是一句话。 */
.hero__brand { margin: 0; letter-spacing: 0.4px; }
.hero__title { font-size: 32px; letter-spacing: -0.8px; margin: 8px 0 10px; }
.hero__lede { color: var(--ink-soft); font-size: 16px; margin: 0 0 24px; }
.hero__panel { border-color: var(--accent); }
.hero__prompt { font-size: 17px; margin: 0 0 14px; }
/*
 * 首页上那条「此刻」。紧贴解梦那块底下，所以是一行的窄条而不是又一块面板 ——
 * /checkins 上那三行摆在这儿会把首页拉散。选项按钮用 .btn--tiny，整条比一行正文高不了多少。
 */
.now-strip {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px;
  margin-top: 10px; padding: 9px 14px; font-size: 13px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
}
.now-strip__ask { color: var(--ink-soft); }
.now-strip__options { display: flex; flex-wrap: wrap; gap: 6px; }
/* 待答那条（点通知正文落在首页的人）跟 .panel--asking 用同一套提示色 */
.now-strip--asking { border-color: var(--accent); background: var(--accent-soft); }
/* 回看那个链接推到最右边，别夹在选项中间被当成第四个选项 */
.now-strip__more { margin-left: auto; font-size: 12px; color: var(--ink-faint); }
@media (max-width: 560px) {
  .now-strip__more { margin-left: 0; }
}

.pillars { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px; margin-bottom: 12px; }
.pillar {
  display: block; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 18px; color: var(--ink);
}
.pillar:hover { text-decoration: none; border-color: var(--accent); }
.pillar__name { font-size: 12px; color: var(--accent); letter-spacing: 1px; }
.pillar__title { font-weight: 700; font-size: 17px; margin: 6px 0 6px; }
.pillar__desc { color: var(--ink-soft); font-size: 14px; }

/* 页脚与配色开关 */
.footer { border-top: 1px solid var(--line); background: var(--panel); margin-top: 60px; }
.footer__inner {
  max-width: 1040px; margin: 0 auto; padding: 16px 20px;
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
}
.theme-switch { display: inline-flex; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.theme-switch__form { margin: 0; }
.theme-switch__option {
  border: 0; background: transparent; color: var(--ink-soft);
  font: inherit; font-size: 13px; line-height: 1.5; padding: 5px 12px; cursor: pointer;
}
.theme-switch__form + .theme-switch__form .theme-switch__option { border-left: 1px solid var(--line); }
.theme-switch__option:hover { color: var(--ink); background: var(--neutral-soft); }
.theme-switch__option--on { background: var(--accent-soft); color: var(--accent-ink); }

/* 语言菜单 */
.lang-menu { position: relative; }
.lang-menu__current {
  list-style: none; cursor: pointer; font-size: 13px; color: var(--ink-soft);
  border: 1px solid var(--line); border-radius: 8px; padding: 5px 12px;
}
.lang-menu__current::-webkit-details-marker { display: none; }
.lang-menu__current:hover { color: var(--ink); background: var(--neutral-soft); }
.lang-menu__list {
  position: absolute; bottom: calc(100% + 6px); right: 0; z-index: 20;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 6px; min-width: 168px; max-height: 320px; overflow-y: auto;
  box-shadow: 0 8px 24px rgb(0 0 0 / 12%);
}
.lang-menu__form { margin: 0; }
.lang-menu__option {
  display: block; width: 100%; text-align: left; border: 0; background: transparent;
  color: var(--ink); font: inherit; font-size: 13px; padding: 6px 10px;
  border-radius: 6px; cursor: pointer;
}
.lang-menu__option:hover { background: var(--neutral-soft); }
.lang-menu__option--on { background: var(--accent-soft); color: var(--accent-ink); }
