/*
 * 手机竖屏适配层。
 *
 * 纪律（改这个文件的人必须遵守）：
 *   1. 所有规则都必须写在 @media 里。这个文件在宽屏下必须等于不存在，
 *      电脑端的样子只能由 tokens.css / base.css / app.css / pages.css 决定。
 *   2. 不改功能：这里只动排版 —— 尺寸、顺序、方向、间距、可见性。
 *      要改行为请去 js/ 里改，不要用 display:none 把功能藏掉。
 *   3. 断点只用两个：768px（手机/小平板）与 900px（两栏工作台塌成一栏）。
 *      与 app.css 里已有的 (pointer: coarse), (max-width: 768px) 一段对齐。
 *
 * 为什么这里只写 max-width，不跟着 app.css 用 pointer: coarse：
 *   app.css 那一段的判据是"手指还是鼠标"，那是因为它要给真机放大触控目标，
 *   又要在无头浏览器里测得到，所以两个条件取或。
 *   这一份不一样 —— 它是"电脑端零风险"的证明本身：只要带上 pointer: coarse，
 *   一台触屏笔记本（1440 宽、pointer: coarse）就会吃到这里的规则，
 *   "宽屏下这份文件等于不存在"立刻不成立。
 *   所以这里一律只用 max-width，宽度是真的、可复现的判据。
 *
 * 关于 !important：
 *   整个文件只有两处用（都写了原因）—— 因为 h() 写的**内联** style 特异性
 *   高于任何样式表规则，而那几个网格的 grid-template-columns 是内联写死的
 *   （见 js/views/forms.js、js/views/relations.js）。其余地方一律不用，
 *   靠"文件最后加载"这一点赢下同特异性的规则。
 */

/* ==========================================================================
   1. 两栏工作台塌成一栏（900 档）
   --------------------------------------------------------------------------
   关系弹层是"左边图、右边列表"的两栏工作台。窄到一个程度之后，2fr 那一边
   剩不到 200px —— 图画不下、人物名全被截断，而右栏还占着 1/3 的宽度。
   这一档直接塌成一栏：图在上、列表在下。

   注意：**这条规则不在这里**，它跟着组件走。
   `js/views/relations.js` 那个网格原来把宽度比例内联写在 style 上（内联样式
   特异性高过样式表，"塌成一栏"只能靠 !important 硬怼），现在改成了类名
   `.relations-split`，电脑端两栏 / 窄屏一栏的规则都归 `styles/pages.css`
   的"关系图 · 手机竖屏"那一段 —— 和 `.graph-canvas`、`.graph-toolbar`、
   `.graph-fullscreen` 的手机档放在一起，"这一屏在手机上长什么样"一眼看全。
   ========================================================================== */
@media (max-width: 900px) {
  /*
   * 横屏手机（844×390）宽到 768 档够不着，但刘海在**左边** ——
   * 顶栏会顶进刘海底下，系统还不让你点它盖住的地方。
   *
   * app.css 里本来写了 padding-left/right: max(..., env(safe-area-inset-*))，
   * 但那两条**被同一段里后面的 padding-inline: var(--space-4) 覆盖掉了**
   * （同一个规则块里，后写的赢）。所以横屏时安全区其实一直没生效。
   * 这里把它补回来 —— 只在窄屏补，不去动 app.css。
   */
  .app-header {
    padding-left: max(var(--space-4), env(safe-area-inset-left, 0px));
    padding-right: max(var(--space-4), env(safe-area-inset-right, 0px));
  }
}

/* ==========================================================================
   2. 外壳：横向留白、顶栏、底栏
   ========================================================================== */
@media (max-width: 768px) {
  /*
   * 手机上一行只有 390px，而"外壳的 padding + .container 的 padding"是**叠**的：
   *   .app-main 16 + .container 20 = 每边 36，两边 72 —— 内容只剩 318。
   * 318 正好卡在"海报墙两列还是三列"的门槛上：.grid-auto 在窄屏用
   * minmax(6.6rem, 1fr)，三列需要 3×105.6 + 2×12 = 340.8。
   * 于是意图（base.css 注释里写的"一屏能扫到 3 部"）在真机上一直是两列。
   *
   * 改成两边各 12：12+12 = 24，内容 342，三列成立。
   * 不再往下压是因为 390 的机器还有 360 的（iPhone SE），
   * 24 是"够用又不贴边"的那一档。
   */
  .app-main {
    padding-left: max(var(--space-3), env(safe-area-inset-left, 0px));
    padding-right: max(var(--space-3), env(safe-area-inset-right, 0px));
  }
  .container { padding-inline: var(--space-3); }

  /*
   * 底栏三格。app.css 是 repeat(3, 1fr)，1fr 的默认 min-width 是 auto ——
   * 换成别的语言（Settings / Archive）后，文字更宽的格子会把整排顶宽。
   * minmax(0, 1fr) + 标签省略号是廉价的保险，不改任何现有尺寸。
   */
  .app-tabbar { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .app-tabbar__item { min-width: 0; padding-inline: var(--space-1); }
  .app-tabbar__item > span {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* ---------------------------------------------------------------- 页头 */
  /*
   * 页头在电脑上靠 flex-wrap 自然换行，手机上就会变成
   * "标题一行 + 按钮被挤到第二行右边"，左边空一块、右边参差。
   * 干脆让动作独占一行、每个按钮等宽铺开 —— 一排能点的大按钮，
   * 比挤在标题右边好按得多（档案馆页头有"观影宇宙 / 馆长年刊 / 添加影片"三个）。
   */
  .page-head { align-items: flex-start; gap: var(--space-3); }
  .page-head__actions { width: 100%; }
  .page-head__actions > .btn { flex: 1 1 auto; }

  /* ---------------------------------------------------------------- 批处理条 */
  /*
   * 批量操作条。电脑上写的是 position: sticky; top: calc(--header-h + --space-2)。
   *
   * 但那一条**从来没有生效过**：sticky 的活动范围被限制在父盒子里，
   * 而它的父节点（archive.js 里那个没有类名的 bulkHost）高度正好等于它自己 ——
   * 一格都挪不动。实测 scrollY=600 时它的 top 是 -128，早就滚没了；
   * 想真吸顶得改 js/views/archive.js，那不在这次的写入范围里。
   *
   * 而手机上有比"吸顶"更合适的位置：钉在底栏上方。拇指够得到，
   * 顺着海报往下划着选的时候不用再划回顶部。顺带也不会被顶栏盖住
   * （顶栏 z-index 40 比它自己的 20 高）。
   *
   * 代价是它会浮在内容上，所以下面用 :has() 给主区域补一块等高的底部内边距
   * （实测这条高 120px，取 8rem=128 留一点余量），最后一行海报和分页
   * 不会被永久盖住。:has() 的门槛（Chrome 105 / Safari 15.4）比这个应用
   * 本来就在用的 color-mix()（Chrome 111 / Safari 16.2）还低，不算新增风险。
   */
  .bulkbar {
    position: fixed;
    inset-inline: var(--space-3);
    bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + var(--space-3));
    top: auto;
    gap: var(--space-2);
    margin-bottom: 0;
  }
  body:has(.bulkbar) .app-main {
    padding-bottom: calc(var(--space-12) + var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + 8rem);
  }
  /* 勾选框独占一行，三颗动作按钮并排一行 —— 手机上两行比三行省出 44px 高 */
  .bulkbar > .checkbox { flex: 1 1 100%; }
  /* 这颗空 .grow 是电脑端用来把按钮推到右边的，手机上按钮自己铺满，它让位就好。
     改成 display:none 更省事，但那是"把节点藏掉"，这里只用尺寸把它收成 0 宽。 */
  .bulkbar > .grow { flex: 0 0 0; width: 0; min-width: 0; overflow: hidden; }
  .bulkbar > .btn { flex: 1 1 auto; padding-inline: var(--space-2); gap: var(--space-1); }

  /*
   * 状态筛选那一行是"芯片横向滚 + 多选钉在右边"（pages.css 的窄屏段）。
   * 但 .filters--tabs > .btn 那里只给了 flex: 0 0 auto —— 它跟着芯片一起滚。
   * 实测 390 宽下它的位置是 x=346…418：**右边缘已经出屏 28px**，
   * "多选"两个字正好被切掉，只剩半个对勾图标（截图里就是那样）。
   * 改成 sticky right: 0 并给它一块不透明底色之后是 x=298…366，完整地贴在右边。
   */
  .filters--tabs > .btn {
    position: sticky;
    right: 0;
    background: var(--background);
    padding-left: var(--space-2);
  }
  /* 多选打开时它是 secondary（"退出多选"），底色要跟着换成不透明的 secondary，
     否则会露出一条透明缝，底下的芯片透出来 */
  .filters--tabs > .btn.btn--secondary { background: var(--secondary); }
}

/* ==========================================================================
   3. 网格与统计
   ========================================================================== */
@media (max-width: 768px) {
  /*
   * 海报墙：把下限从 6.6rem 收到 6.2rem。
   * 配合上面 24px 的横向留白，390 的机器稳定三列；360 的机器也还有三列
   * （(360-24+8)/(99.2+8) = 3.2）。gap 也收一点，把宽度让给海报本身。
   */
  .grid-auto {
    grid-template-columns: repeat(auto-fill, minmax(6.2rem, 1fr));
    gap: var(--space-3) var(--space-2);
  }

  /* 通用网格（tab 面板里那些 col/row 混排）在手机上不需要 16px 的缝 */
  .grid { gap: var(--space-3); }

  /*
   * 作品详情页的统计条：5 格。
   * 电脑上的 column-gap 是 --space-10（40px）。实测："观影宇宙"那条 4 格的
   * 在手机上不收紧时是**两行、132px 高**，收到 20px 之后并成一行、64px；
   * 作品页 5 格那条也从 132 降到 113。
   */
  .stat-strip { gap: var(--space-3) var(--space-5); padding-block: var(--space-3); margin-bottom: var(--space-4); }
  .stat-strip .stat { min-width: 3.5rem; }
  /* 手机上数字降一档：--text-xl 的 20px 加上"1234 小时"这种值会顶到格子边 */
  .stat__value { font-size: var(--text-lg); }
}

/* ==========================================================================
   4. 列表：搜索结果 / 列表视图 / 回收箱
   ========================================================================== */
@media (max-width: 768px) {
  .result-item { gap: var(--space-3); padding: var(--space-3) 0; }
  .result-item__poster { width: 3.25rem; }

  /*
   * 回收箱一行是"海报 + 正文 + 两颗按钮"。
   * 电脑上有的是宽度，手机上不行：两颗按钮（恢复整部 / 彻底删除）因为 44px 的触控高度
   * 和 nowrap 的文字，加起来要 200px。实测：不换行时 .trash-item__body（标题那一栏）
   * 只有 **50px 宽** —— 片名被截成一个字；改成换行 + 按钮整排靠右之后是 278px。
   * 按钮还是 44 高，谁都没变小。
   */
  .trash-item {
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: flex-start;
    gap: var(--space-2) var(--space-3);
  }
  .trash-item__poster { width: 2.25rem; }
  .trash-item__body { flex: 1 1 55%; }
}

/* ==========================================================================
   5. 作品详情
   ========================================================================== */
@media (max-width: 768px) {
  /* 封面区：竖排时海报不需要占满一行，收半档把宽度让给右边的标题与徽章 */
  .work-hero__poster { width: 6.5rem; }
  .work-hero__overview { padding-left: var(--space-3); }
  /* 五颗动作按钮（记一笔 / 封存 / 关系 / 编辑 / 删除）铺满一行行，
     比"右边挤三个、左边空一块"好按，也不会因为换行把某一颗挤成半宽 */
  .work-hero__actions > .btn { flex: 1 1 auto; }

  /*
   * 作品页的标签页（记录 / 时间胶囊 / 藏品档案 / 配图）本来就横向可滚，
   * 这里只是把缝收小、把滚动条藏掉：手机上一条细横线横在标签下面很难看，
   * 而且它吃掉的那 10px 正好让第四个标签露出一半。
   */
  .tabs__list {
    gap: var(--space-4);
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .tabs__list::-webkit-scrollbar { display: none; }

  /* 时间胶囊/记录的元信息行：电脑上不换行是刻意的（一行读完），
     手机上一条就超宽 —— 允许换行，别让徽章把日期挤出屏幕 */
  .record-card__meta,
  .record-card__head,
  .thread__meta,
  .thread__foot { gap: var(--space-2) var(--space-3); }
  .thread__meta { flex-wrap: wrap; }
  .thread { padding-left: var(--space-4); }
  .thread__answer { padding-left: var(--space-3); }

  /* 记录卡里的小图：342 的内容宽正好排四列，每格约 79px（也是个合格的点击目标） */
  .photo-grid { grid-template-columns: repeat(auto-fill, minmax(4.75rem, 1fr)); gap: var(--space-2); }
}

/* ==========================================================================
   6. 配图墙（手机上换成网格）
   --------------------------------------------------------------------------
   电脑上那是一面"摊在灯箱上的印样"：拼贴、叠压、各带倾角、按 photo.id 派生落点。
   那套东西在 390px 上读不出来，只剩三个毛病（三条都是实测的，不是"看着挤"）：
     · 负的左边距（--pin-pull ≈ -1.5rem）加上倾角，让五张照片排到 x=27…338，
       而 .container 的边界是 36…354 —— **最左那张已经探出容器 9px**，
       容器左右各 20px 的内边距等于没有；
     · img 的 max-width: 22rem（352px）比这一行真正能用的 278px 宽出 74px，
       4:1 的全景图只能靠 flex 居中往两边溢出才放得下；
     · 叠压 20%~40% 之外还按远近压暗，被压住的那张根本看不出是什么。
   所以手机上一律摊平：两列网格、统一比例、说明条允许换行。
   留了一条"节奏"没丢 —— 最新那张（第一张）横跨两列，仍然是主角。
   ========================================================================== */
@media (max-width: 768px) {
  /* 配图墙已从「配图」页去掉（改用叠放堆栈），这一整段移动端规则跟着删 */

  /*
   * 删除按钮：pages.css 里它只在 :hover / :focus-within 时 opacity: 1，
   * 而那一整条包在 @media (hover: hover) 里 —— 触屏永远不 hover，
   * 于是手机上一整排"删除图片"是看不见也点不到的（功能等于没有）。
   * 这里是"可见性"，不是加功能：把按钮常显，顺便放大到能点。
   */
  .photo-tile__del { opacity: 1; width: 1.75rem; height: 1.75rem; }
}

/* ==========================================================================
   7. 弹层与表单
   ========================================================================== */
@media (max-width: 768px) {
  /* 手机上弹层已经是底部抽屉（app.css 的 max-width:640 那段），
     内边距跟着收一档，把宽度让给输入框本身 */
  .modal__head { padding: var(--space-4) var(--space-4) var(--space-2); }
  .modal__body { padding: var(--space-2) var(--space-4) var(--space-4); }
  /*
   * 抽屉贴底（app.css 在 max-width:640 把弹层改成 place-items: end stretch），
   * 页脚正好落在 iOS 的 Home 指示条上 —— 那里系统会截走触摸，
   * "保存/添加"这颗主按钮会变成"看得见、按不动"。
   * 所以底部内边距要再加上安全区那一条。
   */
  .modal__foot {
    padding: var(--space-3) var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
    gap: var(--space-2);
  }

  /*
   * 表单里那些内联写死的网格。
   *
   * 它们是 h('div', { class: 'grid', style: { gridTemplateColumns: ... } })
   * 建出来的（forms.js 的 auto-fit 三处 + '1fr 1fr' 一处，relations.js 的两栏一处）。
   * 内联 style 特异性最高，样式表要覆盖**必须** !important。
   *
   * 为什么不按"能改成类名就改成类名"把它挪进 forms.js：
   * 挪走内联样式之后，电脑端那一份 grid-template-columns 就没有出处了 ——
   * 只能写进 app.css / pages.css（禁止改），或者写进这个文件的宽屏区
   * （那就等于这份文件在宽屏下也生效，"宽屏等于不存在"的证明当场作废）。
   * 所以这里留着内联、用 !important 压过去，并且只压窄屏。
   *
   * 为什么一律塌成一列：实测作品表单里"片种 / 状态 / 我的评分 / 年份 / 片长"那一片
   * 两列并排时每格只有 **166px**（下拉框里的"中国大陆 / 美国…"只能看到前半截），
   * 塌成一列之后是 356px。输入框是手指点的目标，整行宽比省下的那点高度值钱。
   */
  .modal .grid[style] { grid-template-columns: minmax(0, 1fr) !important; }

  /* 类型标签（片签）在手机上铺开成两行更好点，chip 的 44px 触控高度已经由 app.css 保证 */
  .tag-list { gap: var(--space-2); }

  /* 分段控件（片种/状态/主题）：手机上等宽铺满一行，别按文字宽窄参差 */
  .segmented { display: flex; flex-wrap: wrap; }
  .segmented__item { flex: 1 1 auto; text-align: center; }
}

/* ==========================================================================
   8. 设置页 / 年刊 / 图谱
   ========================================================================== */
@media (max-width: 768px) {
  /*
   * 图表行的三列：minmax(4rem,9rem) | 1fr | auto。
   * 电脑上标签最多吃 144px 没问题；年刊那一版外面还套着 .yearbook__section 的内边距，
   * 390 的机器上实测留给进度条的只有 **48px**（标签 144、进度条 48 —— 条比数字还短）。
   * 收窄标签上限 + 缩小列间距之后是标签 96、进度条 160。
   */
  .bar-row {
    grid-template-columns: minmax(3.25rem, 6rem) minmax(0, 1fr) auto;
    gap: var(--space-2);
  }
  .bar-row__value { min-width: 1.75rem; }

  /*
   * 年刊是一本"刊物"：电脑上左右各留 32px 是版面。
   * 手机上这 64px 直接吃掉 19% 的宽度，正文和图表全被挤扁。
   */
  .yearbook__cover { padding: var(--space-6) var(--space-5); }
  .yearbook__section { padding: var(--space-5); }
  .yearbook__section-title { margin-bottom: var(--space-4); }

  /* 设置分组：内边距收一档，行内的说明文字才有地方换行 */
  .settings-section { padding: var(--space-4); gap: var(--space-4); }
  .settings-row { align-items: flex-start; }

  /* 搜索页的两个筛选器（片种 / 年份）：并排两格，别各占一行 */
  .search-filters {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-2);
  }
  .search-filters .toolbar-select { width: 100%; min-width: 0; }
  .search-filters .select { width: 100%; }

  /*
   * 伙伴名单。
   *
   * 这一条是**踩过坑之后钉下来的**：一开始按"电脑上一行能排四五个，手机上两列正好"
   * 写成了 minmax(9rem, 1fr)，截图一看 —— 两列时每张卡片只有 167px，
   * 而卡片里除了头像还有两颗 44px 的图标按钮，留给"老王 / 共看 11 次 · 9 部作品"
   * 的只剩二十来像素，中文直接变成一个汉字一行。
   *
   * 基线（minmax(14rem)）在 342 的内容宽下本来就只排得下一列，所以这条在 390 上
   * 和基线结果相同；写出来是因为内容宽一旦超过 456px（大约 500 宽的机器），
   * 14rem 就允许两列了，而每列 224px 里留给名字的只有 66px —— 一样会挤成一字一行。
   */
  .entity-list { grid-template-columns: minmax(0, 1fr); }

  /*
   * 图谱工具条那两条（横排、图例间距）也搬去了 `styles/pages.css` 的
   * "关系图 · 手机竖屏" 段 —— 和 `.graph-canvas` / `.graph-fullscreen` 同处，
   * 免得"关系图在手机上长什么样"要在两个文件之间来回翻。
   */
}

/* ==========================================================================
   9. 触控目标补漏（44px）
   --------------------------------------------------------------------------
   app.css 末尾那段 (pointer: coarse), (max-width: 768px) 已经把
   .btn / .chip / .tabs__tab / .segmented__item / input / .storage-row 抬到 44。
   但漏掉了下面这几个"不是 .btn 的小按钮"—— 它们在手机上要么只有 22~36px，
   要么只在 hover 时可见（触屏没有 hover）。补在这一段里，尺寸一律对齐 2.75rem。
   ========================================================================== */
@media (max-width: 768px) {
  /* 分页：32×32 → 44×44。一页 24 部作品时它正好出现在海报墙下面，是高频点击 */
  .pagination__btn { min-width: 2.75rem; height: 2.75rem; }

  /* 设置页的主色圆点：30×30 → 44×44（一排会自动换行，不会挤） */
  .accent-swatch { width: 2.75rem; height: 2.75rem; }

  /* 头像右下角那颗"换一张"：24×24 → 32×32。
     不做到 44 是因为它整个压在 64px 的头像角上，再大就把头像盖掉一半 */
  .avatar-edit__btn { width: 2rem; height: 2rem; }

  /*
   * 图片预览的关闭按钮：36 → 44，手机上它常常在拇指够不到的上方，越大越好。
   *
   * 顺带把安全区补上：预览是 position: fixed; inset: 0 的全屏浮层，
   * 而 index.html 带 viewport-fit=cover —— 竖屏时"距顶 16px"正好落在状态栏/刘海底下，
   * 那块地方系统会截走触摸，"点关闭没反应"就是这么来的。
   */
  .lightbox__close {
    width: 2.75rem;
    height: 2.75rem;
    top: max(var(--space-4), calc(env(safe-area-inset-top, 0px) + var(--space-2)));
    right: max(var(--space-4), env(safe-area-inset-right, 0px));
  }
  /* 横屏时刘海在左右，图的左右留白也要让开 */
  .lightbox {
    padding-left: max(var(--space-4), env(safe-area-inset-left, 0px));
    padding-right: max(var(--space-4), env(safe-area-inset-right, 0px));
  }

  /* 搜索框里的清除按钮：靠 padding 撑到约 32px 的点击区。
     做成 44 会把输入框里的文字位置挤歪，这里取折中 */
  .input-icon__clear { padding: var(--space-2); right: var(--space-1); }

  /* 多选模式下的海报勾选框：22×22 → 32×32（整张海报也可点，它只是"看得见的那一下"） */
  .poster__select { width: 2rem; height: 2rem; }

  /*
   * 评分星星：一颗 22×22、五颗挤在一起，手指基本点不准 ——
   * 而"打几分"是记录表单里最常用的控件之一。
   *
   * 放大的是**按钮**（44×44），图标还是原来的 22（尺寸写在 svg 属性上），
   * 所以看上去一模一样，只是好点了。
   * 只动 .stars--interactive：卡片上只读的星星是 disabled + pointer-events: none，
   * 放大它只会平白把行高撑起来。
   */
  .stars--interactive .stars__star {
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
  }

  /*
   * 快速跳转面板（顶栏那个指南针图标）里的每一行。
   * 它是 .cmdk__item，不是 .btn，所以 app.css 末尾那段触控规则没覆盖到 ——
   * 实测每行只有 37 高（13px 字 + 上下各 8px 内边距），
   * 而这一屏本来就是"手指快速点一下就去某个地方"。
   */
  .cmdk__item { min-height: 2.75rem; }
}

/* ==========================================================================
   10. 提示条
   --------------------------------------------------------------------------
   Toast 本身不用动：它的 bottom 已经把 --tabbar-h 和 env(safe-area-inset-bottom)
   算进去了，宽度也是 min(28rem, 100%)。
   要动的是**和批量操作条抢同一块地方**这件事：批量条钉在
   "底栏 + 安全区 + 12px" 那一条上，Toast 也落在那里，于是"已移入回收箱 / 撤销"
   会正好压在批量条上（Toast 的 z-index 90 比批量条高，批量条被糊住）。
   批量条在的时候把 Toast 抬到它上面去 —— 和补内边距用的是同一个 :has()。
   ========================================================================== */
@media (max-width: 768px) {
  body:has(.bulkbar) .toast-region {
    bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + 8rem + var(--space-2));
  }
}
