/* 蜗牛助手 - 移动端优先样式 */
:root {
  --bg: #f5f6f8;
  --surface: #ffffff;
  --surface-2: #f0f1f4;
  --text: #1a1c1f;
  --text-2: #6b7280;
  --border: #e3e5e9;
  --primary: #2f6fed;
  --primary-text: #ffffff;
  --danger: #dc3545;
  --success: #16a34a;
  --warn: #d97706;
  --radius: 12px;
  --tabbar-h: 56px;
  /* 助手页底部固定操作区的高度（不含安全区）：输入区 44 + 间距 8 + 操作行 44 + 上下内边距 10+10 + 上边框 1 */
  --assistant-composer-h: 117px;
  --shadow: 0 1px 3px rgba(0, 0, 0, .08);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #14161a;
    --surface: #1d2025;
    --surface-2: #262a30;
    --text: #e8eaed;
    --text-2: #9aa0a6;
    --border: #33383f;
    --primary: #4a86f7;
    --shadow: 0 1px 3px rgba(0, 0, 0, .4);
  }
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
  font-size: 16px;
  line-height: 1.5;
  padding-bottom: env(safe-area-inset-bottom);
}

a { color: var(--primary); text-decoration: none; }

/* ---------- 布局 ---------- */
.content {
  max-width: 680px;
  margin: 0 auto;
  padding: 12px 12px calc(var(--tabbar-h) + 24px + env(safe-area-inset-bottom));
}

.content.no-tabbar { padding-bottom: 24px; }

/* 有助手悬浮按钮的页面（底部 Tab 那几个主页面）：底部多留出按钮的高度，
   免得最后一屏内容被浮在 Tab 上方的按钮盖住 */
.content.has-fab { padding-bottom: calc(var(--tabbar-h) + 84px + env(safe-area-inset-bottom)); }

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 52px;
  padding: 0 12px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.topbar h1 { font-size: 17px; margin: 0; flex: 1; font-weight: 600; }
.topbar .brand-logo { width: 26px; height: 26px; border-radius: 7px; flex: 0 0 auto; object-fit: contain; }
.topbar .back {
  font-size: 22px;
  line-height: 1;
  min-width: 44px;
  justify-content: center;
  color: var(--text);
}
.topbar a { display: inline-flex; align-items: center; min-height: 44px; }

/* ---------- 底部 Tab ---------- */
.tabbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 30;
  display: flex;
  background: var(--surface);
  border-top: 1px solid var(--border);
  padding-bottom: env(safe-area-inset-bottom);
}

.tabbar a,
.tabbar button {
  flex: 1;
  min-height: var(--tabbar-h);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  font-size: 11px;
  color: var(--text-2);
}

/* 「更多」是 button（点了要开二级菜单，不能是链接），补上浏览器默认样式重置 */
.tabbar button {
  background: none;
  border: 0;
  padding: 0;
  font-family: inherit;
  cursor: pointer;
}

.tabbar a .ico, .tabbar button .ico { font-size: 20px; line-height: 1; }
.tabbar a.active, .tabbar button.active { color: var(--primary); }

/* 助手悬浮按钮：手机上取代底部 Tab 里的「助手」（见 partials/page_foot.php），
   浮在底部 Tab 上方、靠右；桌面端有左侧边栏，用下面的媒体查询隐藏它。 */
.assistant-fab {
  position: fixed;
  right: 14px;
  bottom: calc(var(--tabbar-h) + 16px + env(safe-area-inset-bottom));
  z-index: 25;
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--primary);
  color: var(--primary-text);
  box-shadow: 0 6px 18px rgba(47, 111, 237, .38);
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
  transition: transform .12s ease;
}
.assistant-fab:active { transform: scale(.94); }
/* 图标尺寸写在 CSS 里，覆盖 SVG 自带的 width/height 属性 */
.assistant-fab svg { width: 26px; height: 26px; }

/* 左侧边栏只在桌面端出现；手机/平板一律走底部 Tab */
.sidebar { display: none; }
.topbar .t-desktop { display: none; }

/* 顶栏 / 边栏品牌区的「蜗牛助手」文字和 LOGO 图标都支持三连点跳转外部系统（见 app.js）。
   touch-action 挡掉手机端浏览器自带的双击缩放，否则触发跳转时页面还会顺带放大一下；
   user-select 挡掉电脑端鼠标三连点把「蜗牛助手」选成蓝底高亮（手机上长按才会选，不受影响）。 */
.topbar .t-mobile,
.topbar .brand-logo,
.sidebar-brand {
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
}

@media (min-width: 1024px) {
  :root { --sidebar-w: 147px; }

  /* ---------- 桌面端外壳：左固定边栏取代底部 Tab ---------- */
  .tabbar { display: none; }

  .sidebar {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    z-index: 40;
    display: flex;
    flex-direction: column;
    gap: 4px;
    width: var(--sidebar-w);
    padding: 14px 12px;
    background: var(--surface);
    border-right: 1px solid var(--border);
    overflow-y: auto;
  }

  .sidebar-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 10px 16px;
    font-size: 16px;
    font-weight: 600;
  }
  .sidebar-brand img { width: 26px; height: 26px; border-radius: 7px; object-fit: contain; }

  .sidebar .nav-item {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 44px;
    padding: 0 12px;
    border-radius: 10px;
    color: var(--text);
    font-size: 15px;
  }
  /* 边栏变窄后菜单名可能一行放不下：让它自动折成两行（必要时允许拆字），
     不用省略号截断。147px 下三字以内的菜单名仍然是一行。 */
  .sidebar .nav-item .ico { flex: 0 0 auto; width: 20px; font-size: 18px; text-align: center; }
  .sidebar .nav-item > span:not(.ico) { min-width: 0; white-space: normal; overflow-wrap: anywhere; line-height: 1.3; }
  .sidebar .nav-item:hover { background: var(--surface-2); }
  .sidebar .nav-item.active { background: var(--surface-2); color: var(--primary); font-weight: 600; }

  /* 顶栏与内容给边栏让位；品牌已在边栏里，顶栏不再重复显示 */
  .topbar { margin-left: var(--sidebar-w); }
  .topbar .brand-logo,
  .topbar .t-mobile { display: none; }
  .topbar .t-desktop { display: inline; }

  .content {
    margin-left: var(--sidebar-w);
    margin-right: auto;
    /* 边栏收窄到 147px 后，这里跟着放宽：普通页面 1100 → 1280，
       收件箱另见下面 .content.inbox-page（直接用满可用宽度） */
    max-width: 1280px;
    padding: 16px 20px 32px;
  }
  .content.no-tabbar { padding-bottom: 32px; }
  .content.has-fab { padding-bottom: 32px; }

  /* 桌面端有左侧边栏，助手悬浮按钮不显示 */
  .assistant-fab { display: none; }
}

/* ---------- 卡片 ---------- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 14px;
  margin-bottom: 10px;
}

.card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.card-head .time { font-size: 13px; color: var(--text-2); margin-left: auto; }
.card-text { white-space: pre-wrap; word-break: break-word; margin: 0 0 8px; }
.card-meta { font-size: 13px; color: var(--text-2); display: flex; flex-wrap: wrap; gap: 8px; }

.section-title { font-size: 14px; color: var(--text-2); margin: 18px 4px 8px; }
.section-title:first-child { margin-top: 4px; }

/* ---------- 徽标 ---------- */
.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  line-height: 1.6;
  background: var(--surface-2);
  color: var(--text-2);
  white-space: nowrap;
}

.badge.primary { background: rgba(47,111,237,.12); color: var(--primary); }
.badge.success { background: rgba(22,163,74,.14); color: var(--success); }
.badge.warn    { background: rgba(217,119,6,.15); color: var(--warn); }
.badge.danger  { background: rgba(220,53,69,.14); color: var(--danger); }

/* 收件箱列表里可点的「类型」标签：点一下在 事务 / 笔记 之间快捷切换。
   虚线描边 + 手型光标，和只读的徽标区分开（必须写在上面的 .badge.primary 之后，
   否则同特异性下 background 会被它盖掉）。 */
.badge.type-toggle {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 0 10px;
  font-family: inherit;
  cursor: pointer;
  background: var(--surface);
  border: 1px dashed var(--border);
  color: var(--text-2);
}
.badge.type-toggle:hover,
.badge.type-toggle:focus-visible {
  border-style: solid;
  border-color: var(--primary);
  color: var(--primary);
  outline: none;
}
.badge.type-toggle.primary {
  border-color: rgba(47, 111, 237, .45);
  color: var(--primary);
}

.amount { font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums; }
.amount.expense { color: var(--danger); }
.amount.income  { color: var(--success); }

/* ---------- 表单 ---------- */
.field { margin-bottom: 14px; }

.field label {
  display: block;
  font-size: 13px;
  color: var(--text-2);
  margin-bottom: 6px;
}

input[type=text], input[type=password], input[type=number], input[type=date],
input[type=search], input[type=datetime-local], input[type=time], select, textarea {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  font-size: 16px;
  font-family: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  appearance: none;
}

textarea { min-height: 90px; line-height: 1.5; resize: vertical; }

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(47,111,237,.15);
}

.hint { font-size: 12px; color: var(--text-2); margin-top: 4px; }

.row { display: flex; gap: 10px; }
.row > * { flex: 1; min-width: 0; }

/* ---------- 按钮 ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 44px;
  padding: 0 16px;
  font-size: 16px;
  font-family: inherit;
  font-weight: 500;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  cursor: pointer;
  text-align: center;
}

.btn:active { opacity: .75; }
.btn[disabled] { opacity: .5; pointer-events: none; }
.btn-primary { background: var(--primary); border-color: var(--primary); color: var(--primary-text); }
.btn-success { background: var(--success); border-color: var(--success); color: #ffffff; }
.btn-danger  { background: transparent; border-color: var(--danger); color: var(--danger); }
.btn-ghost   { background: transparent; border-color: transparent; color: var(--primary); }
.btn-sm      { min-height: 36px; padding: 0 12px; font-size: 14px; }
.btn-block   { width: 100%; }

.btn-group { display: flex; flex-wrap: wrap; gap: 8px; }
.btn-group .btn { flex: 1; min-width: 100px; }

/* 通用「只在手机端出现」：桌面端隐藏。
   （.t-mobile / .t-desktop 只作用于 topbar，别的地方要用得另起一个通用类） */
@media (min-width: 1024px) {
  .only-mobile { display: none !important; }
}

/* 底部固定操作栏 */
.actionbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 30;
  display: flex;
  gap: 8px;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--border);
}

.actionbar .btn { flex: 1; min-width: 0; padding: 0 10px; font-size: 15px; }

/* 桌面端左侧被边栏占了，操作栏要让开。
   这条必须写在上面 .actionbar 之后：两者选择器特异性相同，写前面会被 left:0 盖掉。 */
@media (min-width: 1024px) {
  .actionbar { left: var(--sidebar-w); }
}

/* ---------- 分类 chips ---------- */
.chips { display: flex; flex-wrap: wrap; gap: 8px; }

.chip {
  min-height: 36px;
  display: inline-flex;
  align-items: center;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: 14px;
  cursor: pointer;
}

.chip.active { background: var(--primary); border-color: var(--primary); color: var(--primary-text); }

/* ---------- 列表 ---------- */
.list { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }

.list-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 52px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
}

.list-row:last-child { border-bottom: none; }
.list-row .grow { flex: 1; min-width: 0; }
.list-row .sub { font-size: 13px; color: var(--text-2); }

.empty { text-align: center; color: var(--text-2); padding: 48px 16px; font-size: 15px; }

/* ---------- 开关 ---------- */
.switch {
  position: relative;
  display: inline-block;
  flex: 0 0 auto;
  width: 56px;
  height: 44px;
}

.switch input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.switch .track {
  position: absolute;
  left: 0; right: 0;
  top: 6px;
  height: 32px;
  background: var(--border);
  border-radius: 999px;
  transition: background .18s;
  pointer-events: none;
}

.switch .track::before {
  content: '';
  position: absolute;
  left: 3px; top: 3px;
  width: 26px; height: 26px;
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
  transition: transform .18s;
}

.switch input:checked + .track { background: var(--primary); }
.switch input:checked + .track::before { transform: translateX(24px); }
.switch input:focus-visible + .track { box-shadow: 0 0 0 3px rgba(47, 111, 237, .3); }

/* ---------- 其它 ---------- */
.toast {
  position: fixed;
  left: 50%;
  top: calc(52px + 20px);
  transform: translateX(-50%);
  z-index: 100;
  max-width: 86vw;
  padding: 10px 16px;
  border-radius: 10px;
  background: rgba(0,0,0,.82);
  color: #fff;
  font-size: 14px;
  opacity: 0;
  transition: opacity .2s;
  pointer-events: none;
}

.toast.show { opacity: 1; }

.muted { color: var(--text-2); }
.small { font-size: 13px; }
.mono  { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; word-break: break-all; }
.center { text-align: center; }
.mt { margin-top: 14px; }
.mb { margin-bottom: 14px; }
.hidden { display: none !important; }

/* ---------- 日程 ---------- */
/* 列表页卡片：左边正文（整块是链接）+ 右边的置顶按钮 */
.sch-card { display: flex; align-items: flex-start; gap: 6px; color: inherit; }
.sch-card .task-body { flex: 1; min-width: 0; color: inherit; }
.sch-card-head { display: flex; align-items: center; gap: 8px; }
.sch-card-title { flex: 1; min-width: 0; font-size: 16px; font-weight: 600;
                  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sch-card-meta { margin-top: 6px; }
.sch-card.is-pinned { border-color: var(--primary); }
.sch-copy { flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
            width: 44px; min-height: 44px; padding: 0; border: 0; background: transparent;
            color: var(--text-2); border-radius: 8px; cursor: pointer;
            -webkit-user-select: none; user-select: none; }
.sch-copy:active { opacity: .6; }
.sch-copy[data-busy="1"] { opacity: .5; }
.sch-pin { flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
           width: 44px; min-height: 44px; padding: 0; border: 0; background: transparent;
           color: var(--text-2); border-radius: 8px; cursor: pointer;
           -webkit-user-select: none; user-select: none; }
.sch-pin:active { opacity: .6; }
.sch-pin.active { color: var(--primary); }

/* 左滑删除：外面套一层裁切，卡片往左移，露出右边的红色删除按钮 */
.sch-swipe { position: relative; margin-bottom: 10px; border-radius: var(--radius);
             overflow: hidden; touch-action: pan-y; }
.sch-swipe > .card { margin-bottom: 0; position: relative; z-index: 1;
                     transition: transform .18s ease; will-change: transform; }
.sch-swipe.open > .card { transform: translateX(-84px); }
.sch-swipe-del { position: absolute; top: 0; right: 0; bottom: 0; width: 84px; margin: 0;
                 display: flex; align-items: center; justify-content: center;
                 border: 0; background: var(--danger); color: #fff; cursor: pointer;
                 font-family: inherit; }
.sch-swipe-del:active { filter: brightness(.92); }
.sch-swipe-del svg { display: block; }

/* 编辑页：标题输入框 + 右上角的「切换列表/笔记」图标按钮 */
.sch-title-row { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.sch-title-row #schTitle { flex: 1; min-width: 0; }
.sch-mode-btn { flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
                width: 44px; height: 44px; padding: 0; border: 1px solid var(--border);
                border-radius: 10px; background: var(--surface); cursor: pointer; }
.sch-mode-btn:active { opacity: .75; }
.sch-mode-btn svg { width: 22px; height: 22px; display: block; }

/* 清单容器 */
.sch-lines { background: var(--surface); border: 1px solid var(--border);
             border-radius: var(--radius); box-shadow: var(--shadow); padding: 4px 6px; }
/* 内容行做紧凑些，一屏能多看几条。
   .sch-line 是「左滑容器」（裁切 + 承接手势），.sch-line-body 才是那一行 —— 滑动时只平移它 */
.sch-line { position: relative; overflow: hidden; border-bottom: 1px solid var(--border);
            touch-action: pan-y; }
.sch-line:last-of-type { border-bottom: none; }
.sch-line.dragging { background: var(--surface-2); border-radius: 8px; }
.sch-line-body { display: flex; align-items: center; gap: 6px; min-height: 36px; padding: 2px 4px;
                 position: relative; z-index: 1; background: var(--surface);
                 transition: transform .18s ease; will-change: transform; }
.sch-line.dragging .sch-line-body { background: var(--surface-2); }
.sch-line.open .sch-line-body { transform: translateX(-56px); }
/* 右滑后从左边露出的「记入收件箱」按钮 */
.sch-line.open-right .sch-line-body { transform: translateX(56px); }
/* 左滑后从右边露出的删除按钮 */
.sch-line-del { position: absolute; top: 0; right: 0; bottom: 0; width: 56px; margin: 0;
                display: flex; align-items: center; justify-content: center;
                border: 0; background: var(--danger); color: #fff; cursor: pointer; }
.sch-line-del:active { filter: brightness(.92); }
.sch-line-del svg { display: block; }
/* 右滑后从左边露出的「记入收件箱」按钮 */
.sch-line-ins { position: absolute; top: 0; left: 0; bottom: 0; width: 56px; margin: 0;
                display: flex; align-items: center; justify-content: center;
                border: 0; background: var(--primary); color: #fff; cursor: pointer; }
.sch-line-ins:active { filter: brightness(.92); }
.sch-line-ins svg { display: block; }
/* 复选框用系统控件，但把选中色改成灰的（默认蓝色太扎眼） */
.sch-check { flex: 0 0 auto; width: 20px; height: 20px; min-height: 0; margin: 0;
             accent-color: var(--text-2); }
/* 用 .sch-line 前缀提高优先级，压过全局的 input / textarea 规则；
   平时 15px 显紧凑，聚焦时回到 16px —— 手机浏览器对 <16px 的输入框会自动放大整页。
   每条用多行输入框：内容长了自动换行并自动长高（高度由 JS growText 算），
   所以关掉默认 resize / 滚动条，长单词也强制断行 */
.sch-line .sch-text { flex: 1; min-width: 0; width: auto; min-height: 32px; padding: 4px 8px;
                      font-size: 15px; line-height: 1.3;
                      border: 1px solid transparent; background: transparent;
                      resize: none; overflow: hidden; display: block;
                      white-space: pre-wrap; overflow-wrap: anywhere; }
.sch-line .sch-text:focus { font-size: 16px; border-color: var(--primary); background: var(--surface); }
.sch-line.done .sch-text { color: var(--text-2); text-decoration: line-through; }
.sch-grip { flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
            width: 36px; min-height: 36px; padding: 0; border: 0; background: transparent;
            color: var(--text-2); font-size: 16px; cursor: grab; touch-action: none;
            -webkit-user-select: none; user-select: none; }
/* 笔记框高度由 JS 按内容算（autoGrowNote），这里只关掉默认最小高度和滚动条；
   同样平时 15px、聚焦回 16px */
.sch-note { min-height: 0; resize: none; overflow: hidden; font-size: 15px; line-height: 1.35; }
.sch-note:focus { font-size: 16px; }

/* 编辑页底部那一行：删除靠左、「查看事务」靠最右 */
.sch-foot-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }

/* 「查看事务」弹窗：一条一条列出未完成事务 / 收件箱原文，每条带「完成 / 插入」两个按钮 */
.tp-filter { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.tp-search { flex: 1 1 auto; width: auto; min-width: 0; }
.tp-only { flex: 0 0 auto; display: flex; align-items: center; gap: 4px; white-space: nowrap;
           font-size: 13px; color: var(--text-2); -webkit-user-select: none; user-select: none; }
.tp-only input { width: auto; min-height: 0; margin: 0; }
.tp-group { margin: 10px 2px 6px; font-size: 13px; color: var(--text-2); }
.tp-group:first-child { margin-top: 0; }
.tp-item { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
           margin: 0 0 8px; padding: 10px 12px;
           background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
           font-family: inherit; font-size: 15px; color: inherit; }
.tp-item.added { opacity: .55; }
/* 左边正文：占满剩余宽度，长文本在按钮左边换行，不挤压按钮 */
.tp-main { flex: 1 1 auto; min-width: 0; }
.tp-title { font-weight: 600; word-break: break-word; }
.tp-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
           margin-top: 4px; font-size: 13px; color: var(--text-2); }
.tp-due.over { color: var(--danger); }
.tp-added { color: var(--success); }
/* 右边「完成 / 插入」两个小按钮：跟在内容右侧，不换行 */
.tp-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; }
.tp-actions .btn { min-height: 30px; padding: 0 10px; font-size: 13px; white-space: nowrap; }

.divider { height: 1px; background: var(--border); margin: 16px 0; }

/* 快捷记录页 */
.quick-page {
  min-height: 100vh;
  /* --kb = 输入法键盘高度（由 quick_script.php 写入），弹键盘时整页跟着变矮 */
  min-height: calc(100dvh - var(--kb, 0px));
  display: flex;
  flex-direction: column;
  max-width: 680px;
  margin: 0 auto;
  /* 给底部固定栏（大圆麦克风 + 记录按钮）预留空间，避免遮挡 */
  padding: 16px 12px calc(178px + env(safe-area-inset-bottom));
}

.quick-form {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.quick-form > .row { flex: 0 0 auto; }

.quick-form textarea {
  flex: 1;
  min-height: 140px;
  margin: 10px 0;
  font-size: 17px;
}

/* 外壳版快捷输入框（管理后台里的「快捷」页）。
   目标：和独立快捷页观感一致 —— 输入框吃掉剩余高度，直接给到最大可用空间。
   做法：把内容区变纵向 flex 容器、卡片 flex:1，卡片内部只让 textarea 伸展，
   其余（记录到/字数、语音行、记录按钮）维持原高。
   min-height 同时写在 textarea 的内联样式里：万一 CSS 没加载或是旧版本，
   输入框也不会塌回全局默认的 90px（曾经因为这个把高度"改小了"）。 */
.quick-inline textarea {
  flex: 1 1 auto;
  min-height: 180px;
  margin: 10px 0;
  font-size: 17px;
}

/* 注意：下面这些都必须限定在 .content 上。
   pageClass 同时也会挂在 <body> 上，如果写成 body.quick-shell{display:flex}，
   body 变成 flex 列，.content 的 auto 外边距会把它在交叉轴上挤成一条窄列。 */
.content.quick-shell {
  display: flex;
  flex-direction: column;
}
.content.quick-shell .card.quick-inline {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.content.quick-shell .card.quick-inline > .row,
.content.quick-shell .card.quick-inline > .btn { flex: 0 0 auto; }
.content.quick-shell .card.quick-inline > textarea { flex: 1 1 auto; }

/* 只有小屏（没有左侧边栏、有底部 Tab）才把内容区撑到整屏，输入框才是"最高高度"；
   桌面端不设容器最小高度，保持固定高度，免得出现一个巨大的空白输入框 */
@media (max-width: 1023px) {
  .content.quick-shell {
    min-height: calc(100vh - 52px);      /* 52px = topbar 高度 */
    /* 再减去键盘高度：弹键盘时内容区变矮，卡片底部的按钮才不会被键盘挡住 */
    min-height: calc(100dvh - 52px - var(--kb, 0px));
  }
}

/* 快捷记录里的发货表单（选中「发货」时出现）。
   字段名和输入框同一行、尽量紧凑；地址框压到最低高度，标题不用下拉就能看到 */
.ship-quick { margin: 10px 0; }
.ship-quick > .btn { margin-bottom: 10px; }

.ship-quick .ship-line {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.ship-quick .ship-label {
  flex: 0 0 auto;
  white-space: nowrap;      /* 字段名不换行，空间不够时挤输入框而不是折行 */
  font-size: 13px;
  color: var(--text-2);
}
.ship-quick .ship-line > input,
.ship-quick .ship-line > textarea {
  flex: 1 1 0;
  min-width: 0;
  margin: 0;
}

/* 收件人 / 电话：同一行里并排两个字段 */
.ship-quick .ship-pair { display: flex; gap: 10px; margin-bottom: 8px; }
.ship-quick .ship-pair > .ship-line { flex: 1 1 0; min-width: 0; margin-bottom: 0; }

/* 地址框：高度已压到最低，不允许拖动放大（ID 选择器，压过 .quick-form/.quick-inline 的 textarea 规则） */
.ship-quick #shipAddr {
  height: 32px;
  min-height: 32px;
  padding: 5px 10px;
  line-height: 20px;
  font-size: 14px;
  resize: none;
}

.quick-footer {
  position: fixed;
  left: 0; right: 0;
  /* 默认贴底；弹键盘时由 --kb 顶到键盘上方（iOS 不改布局视口，fixed 底栏会被键盘盖住） */
  bottom: var(--kb, 0px);
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--border);
}

.quick-footer .inner {
  max-width: 656px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* ---------- 录音按钮（快捷记录页 / 收件箱「＋记录」共用） ---------- */
#recordBtn {
  /* 固定占满整行，长度**写死**：
     不给它 flex-grow —— 否则旁边一旦冒出别的东西（提示文字、状态）就会被挤窄；
     录音读秒、草稿提示、转写中都不改变它的长度，拇指按在哪就一直在哪。 */
  flex: 0 0 auto;
  width: 100%;
  /* 文字变长也不换行，高度同样不变 */
  white-space: nowrap;
  /* 虽然带了 btn-sm，但录音是触摸目标，按手机端 44px 的下限来 */
  min-height: 44px;
  font-size: 15px;
  /* 手机上按住容易触发文字选中和长按菜单，全部关掉 */
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
/* 草稿提示是独立一行，空的时候完全不占高度 */
#draftHint { flex: 0 0 auto; }
#draftHint:empty { display: none; }
#recordBtn.rec-live {
  border-color: var(--danger);
  color: var(--danger);
}

/* ---------- 快捷记录页的次级工具（清空 / 复制） ---------- */
/* 低频操作，降级成纯文字按钮，一左一右守在大圆麦克风两侧；没内容时置灰 */
.quick-mic-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 48px;
  flex: 0 0 auto;
}
/* 行内麦克风不需要自动外边距（居中交给 justify-content） */
.quick-mic-row > #recordBtn.quick-mic { margin: 0; }

.btn-text {
  appearance: none;
  background: none;
  border: none;
  padding: 0 4px;
  min-height: 44px;
  font-family: inherit;
  font-size: 14px;
  color: var(--primary);
  cursor: pointer;
}
.btn-text:disabled { color: var(--text-2); opacity: .55; pointer-events: none; }

/* ---------- 快捷记录页的大圆麦克风 ---------- */
/* 录音是核心输入方式，做成大圆键放在拇指区；录音中整颗变红显示秒数、
   转写中显示短文案，所以这两种状态下字号要缩小才放得下。
   （按钮文案按 .quick-mic 判切换，见 partials/quick_script.php） */
#recordBtn.quick-mic {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  min-height: 64px;
  margin: 0 auto;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 28px;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: var(--shadow);
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
#recordBtn.quick-mic:active { opacity: .8; }
#recordBtn.quick-mic.rec-live {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
  font-size: 13px;
}
#recordBtn.quick-mic:disabled { font-size: 13px; opacity: .6; }
/* 外壳版（管理后台里的「快捷」页）卡片内要上下留白；底部固定栏那边由 gap 负责 */
.content.quick-shell .card.quick-inline > .quick-mic-row { flex: 0 0 auto; margin: 14px 0; }

/* ---------- 收件箱双栏（桌面端增强，手机端零影响） ---------- */

/* 手机：勾选框不显示、整张卡片就是链接，点击区域与改造前一致 */
.card.item { padding: 0; }
.card.item .item-body { display: block; color: inherit; padding: 14px; }
.pick { display: none; }

/* 右栏预览与多选操作条只在桌面端出现 */
.inbox-detail { display: none; }
.batchbar     { display: none; }

/* 嵌入预览（inbox_item.php?embed=1）：只收起边栏和顶栏，正文与操作按钮都保留 ——
   这样在右侧预览窗里就能直接确认/编辑条目，不必再打开完整页。
   注意别再把 .btn-group / .actionbar 隐藏掉，否则预览又变回只读。 */
.embed .topbar,
.embed .sidebar { display: none; }
.embed .content { margin-left: 0; padding: 12px; max-width: none; }
.embed .content.no-tabbar { padding-bottom: 12px; }
/* 预览窗里没有左侧边栏，底部操作栏不需要再让位 */
.embed .actionbar { left: 0; }

@media (min-width: 1024px) {
  /* 收件箱双栏（列表 + 预览）不设上限，用满边栏右边的全部宽度，
     这样 1920 这类大屏上右侧预览窗才真的变宽 */
  .content.inbox-page { max-width: none; }

  .inbox-layout {
    display: grid;
    grid-template-columns: minmax(0, 400px) minmax(0, 1fr);
    gap: 14px;
    align-items: start;
  }

  /* 列表项：勾选框 + 内容 */
  .card.item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 14px;
  }
  .card.item.active {
    border-color: var(--primary);
    box-shadow: 0 0 0 2px rgba(47, 111, 237, .18);
  }
  .card.item .item-body { flex: 1; min-width: 0; padding: 0; }
  .card.item .item-body:hover { color: var(--primary); }

  .pick {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 24px;
    height: 24px;
    margin-top: 2px;
    cursor: pointer;
  }
  .pick input { width: 18px; height: 18px; min-height: 0; margin: 0; cursor: pointer; }

  /* 多选操作条 */
  .batchbar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    margin-bottom: 10px;
    background: var(--surface);
    border: 1px solid var(--primary);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
  }
  .batchbar .batch-count { flex: 1; font-size: 14px; }
  .batchbar .batch-all   { font-size: 14px; white-space: nowrap; }

  /* 右侧只读预览 */
  .inbox-detail { display: block; position: sticky; top: 64px; }

  .detail-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
  }
  .detail-bar .btn { margin-left: auto; }

  .detail-body {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    overflow: hidden;
  }
  .detail-body iframe {
    display: none;
    width: 100%;
    height: calc(100vh - 190px);
    min-height: 420px;
    border: 0;
  }
}

/* ---------- 事务页（手机单栏 / 桌面双栏） ---------- */

.task-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}
.task-toolbar .chips { margin: 0; }

.task-filter {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}
/* 搜索框 / 搜索按钮 / 排序下拉必须挤在同一行：搜索框可以压短，按钮和下拉不缩 */
.task-search { flex: 0 1 170px; width: auto; min-width: 0; }
.task-sort   { flex: 0 0 auto; width: auto; }
/* 搜索按钮跟搜索框/下拉框同高，排一排才齐 */
.task-search-btn { flex: 0 0 auto; min-height: 44px; }

/* 行内可点的小标签：点一下弹面板就地改状态 / 优先级 / 截止时间 / 动作类型 */
.task-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }

.tag {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 0 12px;
  font-size: 13px;
  font-family: inherit;
  color: var(--text-2);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
}
.tag:hover { border-color: var(--primary); color: var(--primary); }
.tag.pr-high,
.tag.due-over { color: var(--danger); border-color: rgba(220, 53, 69, .35); }
.tag.pr-medium { color: var(--warn); border-color: rgba(217, 119, 6, .35); }
.tag.st-done   { color: var(--success); border-color: rgba(22, 163, 74, .35); }
.tag.st-doing  { color: var(--primary); border-color: rgba(47, 111, 237, .35); }
.tag.st-cancelled { text-decoration: line-through; }

/* 点标签后弹出的选择面板（JS 动态插到 body 下） */
.tagmenu {
  position: absolute;
  z-index: 60;
  min-width: 132px;
  padding: 4px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 26px rgba(0, 0, 0, .16);
}
.tagmenu button {
  display: block;
  width: 100%;
  min-height: 40px;
  padding: 0 12px;
  font-size: 15px;
  font-family: inherit;
  text-align: left;
  color: var(--text);
  background: none;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
}
.tagmenu button:hover,
.tagmenu button.active { background: var(--surface-2); color: var(--primary); }
.tagmenu-datetime { width: 100%; }
.tagmenu-clear { margin-top: 2px; color: var(--danger); }

/* 右栏与双栏布局只在桌面端出现 */
.task-detail { display: none; }

.card.task-item { padding: 12px 14px; }
.card.task-item .task-body { display: block; color: inherit; }
.card.task-item .task-head { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.card.task-item .task-text { white-space: pre-wrap; word-break: break-word; }
.card.task-item .task-meta { margin-top: 4px; }

/* 条目标题：列表卡片的主行（详情页的条目标题也用它）。
   标题为空、或标题只是正文开头时不会渲染这一行，所以不会出现"标题=正文"的重复。 */
.task-title { font-weight: 600; word-break: break-word; }

/* 标题下面的正文预览：最多两行，超出省略，比正文行更小更淡 */
.task-sub {
  margin-top: 2px;
  font-size: 13px;
  color: var(--text-2);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
}

/* ---------- 人物记录：置顶标记 + 折叠全文 ---------- */
.rec-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}
.rec-pin-btn { margin-left: auto; }
.rec-pin-flag {
  display: inline-flex;
  align-items: center;
  font-size: 12px;
  line-height: 1;
  color: var(--primary);
  border: 1px solid var(--primary);
  border-radius: 999px;
  padding: 3px 8px;
}
.rec-pin-flag[hidden] { display: none; }
.card.task-item.is-pinned { border-color: var(--primary); }

.rec-full {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed var(--border);
}
.rec-full-text { white-space: pre-wrap; word-break: break-word; }

@media (max-width: 1023px) {
  /* 手机上也让搜索框 / 搜索按钮 / 排序下拉保持一行：搜索框压短，其余不缩 */
  .task-filter { margin-left: 0; width: 100%; }
  .task-search { flex: 1 1 auto; min-width: 0; }
}

@media (min-width: 1024px) {
  /* 「左列表 + 右详情」页（事务 / 笔记 / 开发 / 吃 / 人物）：和收件箱一样用满边栏右边的全部宽度，
     大屏上右栏（编辑表单）才够宽、右边不留下大片空白。
     左右比例交给下面的 clamp —— 左列表随屏宽变化（360 ~ 720px），其余全给右详情，
     这样既不会像原来那样永远只有 400px，也不会让右栏把空间吃光。 */
  .content.task-page { max-width: none; }

  .task-layout {
    display: grid;
    grid-template-columns: clamp(360px, 32%, 720px) minmax(0, 1fr);
    gap: 14px;
    align-items: start;
  }
  /* 电脑端搜索框给足宽度，别是个 170px 的小条孤零零挤在右边 */
  .task-search { flex: 0 1 300px; }
  .card.task-item { cursor: pointer; }
  .card.task-item:hover { border-color: var(--primary); }
  .card.task-item.active {
    border-color: var(--primary);
    box-shadow: 0 0 0 2px rgba(47, 111, 237, .18);
  }
  .task-detail { display: block; position: sticky; top: 64px; }

  /* 「吃」列表页：左侧可点行的悬停 / 选中态，和开发页的卡片选中呼应 */
  .list-row.pane-row { cursor: pointer; }
  .list-row.pane-row:hover { background: rgba(47, 111, 237, .06); }
  .list-row.pane-row.active {
    background: rgba(47, 111, 237, .10);
    box-shadow: inset 3px 0 0 var(--primary);
  }
}

/* 人物页上半部分（资料 / 快速记一条 / 事项）：整页铺满会让快速记录的多行框和
   「记下来」按钮拉成 1700px 宽的一条，很难用。这里给个和普通页面一致的宽度上限；
   下面「人物记录」的双栏仍然用满整屏。 */
.person-top { max-width: 1280px; }

/* ---------- 菜谱（吃） ---------- */

/* 桌面端侧边栏底部的「设置」：靠 margin-top:auto 顶到最下面。
   它只在 .sidebar 里（手机端整条侧边栏隐藏），所以不用再写媒体查询。 */
.sidebar-foot {
  margin-top: auto;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

/* 菜谱「做法」的渲染结果。
   只做两件事：**加粗** 变成真加粗（由 PHP 输出 <strong>），换行和缩进靠 pre-wrap 原样保留。
   为什么不做成 <ol>/<ul>：xlsx 里的编号（1. 2.、-）本来就在正文里，
   硬解析会把续行的缩进和空行吃掉，反而更难读。 */
.md-body {
  white-space: pre-wrap;
  word-break: break-word;
  line-height: 1.7;
}

.md-body strong { font-weight: 600; }

/* 「吃」的图标是内联 SVG（字体里没有"碗筷"这种字形，用汉字又和旁边的 ▣ ¥ ✓ 不是一路）。
   把图标格改成 flex 居中：inline SVG 默认按基线对齐，会把这一格顶高、
   和其他 Tab 的字体图标错位；side 里再把它压到 18px，和旁边 18px 的字号对齐。 */
.tabbar a .ico,
.tabbar button .ico,
.sidebar .nav-item .ico {
  display: flex;
  align-items: center;
  justify-content: center;
}

.tabbar a .ico svg,
.tabbar button .ico svg,
.sidebar .nav-item .ico svg { display: block; }

.sidebar .nav-item .ico svg { width: 18px; height: 18px; }

/* ---------- 「更多」二级菜单 ---------- */
.more-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.more-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 84px;
  padding: 10px 6px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
  color: var(--text);
  font-size: 13px;
}

.more-item .ico {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  line-height: 1;
}

.more-item .ico svg { width: 22px; height: 22px; }

.more-item.active { border-color: var(--primary); color: var(--primary); }

/* ---------- 弹窗（收件箱「＋记录」等共用） ---------- */
body.modal-open { overflow: hidden; }

.modal {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: flex-end;   /* 手机：从底部弹起的抽屉 */
  justify-content: center;
}

.modal-mask {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .45);
}

.modal-sheet {
  position: relative;
  width: 100%;
  max-width: 680px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-radius: 16px 16px 0 0;
  padding: 14px 14px calc(14px + env(safe-area-inset-bottom));
  box-shadow: 0 -2px 16px rgba(0, 0, 0, .18);
  animation: modal-in .18s ease-out;
}

@keyframes modal-in {
  from { transform: translateY(12px); opacity: .6; }
  to   { transform: translateY(0);    opacity: 1; }
}

.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
  flex: 0 0 auto;
}

.modal-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

.modal-body textarea {
  width: 100%;
  min-height: 140px;
  font-size: 17px;
}

.modal-foot {
  flex: 0 0 auto;
  padding-top: 10px;
}

/* 自定义二次确认（confirmActBig）：正文保留换行，按钮加大防误触 */
.confirm-msg { white-space: pre-line; line-height: 1.7; }
.confirm-actions { display: flex; gap: 10px; }
.confirm-actions .btn { flex: 1; }
.btn-lg { min-height: 52px; padding: 0 16px; font-size: 17px; }

/* 桌面端改成居中浮层，不要贴着屏幕底部 */
@media (min-width: 1024px) {
  .modal { align-items: center; padding: 24px; }
  .modal-sheet {
    border-radius: 16px;
    max-width: 560px;
    max-height: 80vh;
    padding: 18px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, .28);
  }
}

/* ---------- 助手（对话） ---------- */

/* 助手页没有底部 Tab，底部只有固定的对话操作区（输入区 + 返回/录音/发送） */
.content.assistant-page {
  padding-bottom: calc(var(--assistant-composer-h) + 16px + env(safe-area-inset-bottom));
}

.msg-list { display: flex; flex-direction: column; gap: 12px; }

.msg { display: flex; }
.msg.user { justify-content: flex-end; }

.msg .bubble {
  max-width: 84%;
  padding: 10px 12px;
  border-radius: 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
}

.msg .bubble-text { white-space: pre-wrap; word-break: break-word; }

/* 正文里的轻量 Markdown（加粗 / 列表 / 行内代码）渲染结果 */
.bubble-text .rich-p { margin: 0 0 8px; }
.bubble-text .rich-p:last-child { margin-bottom: 0; }

.bubble-text .rich-h { font-weight: 600; margin: 10px 0 4px; }
.bubble-text .rich-h:first-child { margin-top: 0; }

.bubble-text ul,
.bubble-text ol { margin: 4px 0 8px; padding-left: 20px; }
.bubble-text ul:last-child,
.bubble-text ol:last-child { margin-bottom: 0; }
.bubble-text li { margin: 2px 0; }

.bubble-text strong { font-weight: 600; }

.bubble-text code {
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--surface-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 14px;
}

/* 正文里的条目编号（#12）：只有编号本身可点，点一下在页内弹层打开编辑 */
.bubble-text .entry-link {
  color: var(--primary);
  text-decoration: none;
  background: rgba(47, 111, 237, .10);
  border-radius: 6px;
  padding: 0 4px;
  margin: 0 -2px;
}
.bubble-text .entry-link:active { background: rgba(47, 111, 237, .20); }

/* 正文里的菜名：点一下在同一个弹层里编辑菜谱（用绿色区分于蓝色的 #条目） */
.bubble-text .recipe-link {
  color: var(--success);
  text-decoration: none;
  background: rgba(22, 163, 74, .10);
  border-radius: 6px;
  padding: 0 4px;
  margin: 0 -2px;
}
.bubble-text .recipe-link:active { background: rgba(22, 163, 74, .20); }

/* 助手页内的条目编辑抽屉（iframe，保存后回到对话） */
.modal-sheet.editor-sheet {
  padding: 0;
  height: 90vh;
  max-height: 90vh;
  overflow: hidden;
}
.editor-sheet .modal-head {
  margin: 0;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.editor-frame-wrap { flex: 1 1 auto; min-height: 0; }
.editor-frame-wrap iframe { width: 100%; height: 100%; border: 0; display: block; }

.msg.user .bubble {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-text);
  border-top-right-radius: 4px;
}

.msg.assistant .bubble { border-top-left-radius: 4px; }

/* 待确认动作卡片 */
.action-card {
  margin-top: 10px;
  padding: 10px;
  border: 1px dashed var(--primary);
  border-radius: 10px;
  background: rgba(47, 111, 237, .07);
  font-size: 15px;
  white-space: normal;   /* 气泡正文是 pre-wrap，卡片里要恢复正常换行 */
}

.action-card .action-title { word-break: break-word; }
.action-card .action-ops { display: flex; gap: 8px; margin-top: 8px; }
.action-card .action-ops .btn { flex: 1; min-width: 0; }

/* 「改条目」卡片里的变更清单 */
.action-card .action-changes { margin: 6px 0 0; padding-left: 18px; list-style: disc; }
.action-card .action-changes li { margin: 5px 0; }
.action-card .action-name { font-weight: 600; word-break: break-word; }
.action-card .action-change { font-size: 13px; color: var(--text-2); }

.action-card.resolved {
  border-style: solid;
  border-color: var(--border);
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 13px;
}

/* 底部对话操作区：上面一行输入区，下面一行「返回 / 录音 / 发送」 */
.assistant-composer {
  position: fixed;
  left: 0; right: 0;
  bottom: 0;
  z-index: 30;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--border);
}

/* 输入区：文本框（或快捷按钮）在左、切换图标在右 */
.assistant-composer .composer-input {
  max-width: 680px;
  margin: 0 auto 8px;
  display: flex;
  align-items: flex-end;
  gap: 8px;
}

.assistant-composer textarea {
  flex: 1;
  /* flex 项默认 min-width:auto，会被内容顶宽，这里必须显式归零 */
  min-width: 0;
  min-height: 44px;
  max-height: 140px;
  margin: 0;
  resize: none;
  font-size: 16px;
  line-height: 1.4;
  padding: 10px 12px;
}

/* 快捷按钮那排：几个按钮一律排在一行里。
   不用横向滚动：滚动条是隐藏的，溢出时用户看不出"还能往右滑"，
   会以为少了一个按钮。这里改成自动收窄 + 省略号，保证都看得见。 */
.assistant-composer .quick-chips {
  flex: 1;
  min-width: 0;
  display: flex;
  gap: 6px;
}

/* .chip 默认 36px；这排是要点着用的，按「触摸目标 ≥44px」的规则加高。
   字号和内边距也调小了些：390px 的屏上几个按钮要平分输入区宽度，
   4 个汉字得完整放得下（实测 14px 字号 + 14px 内边距在 375px 的屏上会差几像素）。
   用 block 而不是 .chip 自带的 inline-flex：inline-flex 上 text-overflow 不生效。 */
.assistant-composer .quick-btn {
  flex: 0 1 auto;
  min-width: 0;
  min-height: 44px;
  padding: 0 10px;
  font-size: 13px;
  display: block;
  line-height: 42px;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 输入区右侧的「快捷 / 文本框」切换按钮：图标态固定 44×44。
   快捷模式下显示键盘图标（点了去打字），文本框模式下显示闪电图标（点了回快捷）。 */
.assistant-composer .composer-toggle {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}
.assistant-composer .composer-toggle:active { background: var(--surface-2); }
.assistant-composer .composer-toggle .toggle-ico-bolt { display: none; }
.assistant-composer.mode-type .composer-toggle .toggle-ico-bolt { display: block; }
.assistant-composer.mode-type .composer-toggle .toggle-ico-key { display: none; }

/* 快捷按钮 / 文本框 互斥显示（只在配了快捷提问、存在切换按钮时生效）。
   .mode-type 表示切到了文本框模式；默认是快捷模式。 */
.assistant-composer.has-shortcuts .quick-chips { display: flex; }
.assistant-composer.has-shortcuts textarea { display: none; }
.assistant-composer.has-shortcuts.mode-type .quick-chips { display: none; }
.assistant-composer.has-shortcuts.mode-type textarea { display: block; }

/* 操作行：左返回、中录音、右发送，三等分让录音正好落在中间 */
.assistant-composer .composer-actions {
  max-width: 680px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
}
.assistant-composer .composer-actions .btn { flex: 1 1 0; min-width: 0; }

/* 中间的语音按钮：图标态高度固定 44，录音中变红并显示读秒。
   左右内边距与 .btn 保持一致 —— 三个按钮用 flex:1 1 0，padding 不同会导致中间那个偏窄。 */
.assistant-composer .asr-btn {
  height: 44px;
  padding: 0 16px;
  font-size: 18px;
  line-height: 1;
  /* 手机上按住容易触发文字选中和长按菜单，全部关掉 */
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
.assistant-composer .asr-btn.rec-live {
  border-color: var(--danger);
  color: var(--danger);
}

/* 等回答的时候快捷按钮不可点，避免连点发出两轮 */
.assistant-composer .quick-chips.is-busy .quick-btn {
  opacity: .5;
  pointer-events: none;
}

/* 记忆列表 */
.mem-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}

.mem-item:last-child { border-bottom: 0; }
.mem-item .mem-text { flex: 1; min-width: 0; word-break: break-word; font-size: 15px; }
.mem-item .mem-ops { display: flex; gap: 6px; flex: 0 0 auto; }

.field-label { display: block; font-size: 13px; color: var(--text-2); margin: 10px 0 4px; }

@media (min-width: 1024px) {
  .assistant-composer { left: var(--sidebar-w); }
  .assistant-composer .composer-input { max-width: 900px; }
  .assistant-composer .composer-actions { max-width: 900px; }
  .content.assistant-page { padding-bottom: calc(var(--assistant-composer-h) + 16px); }
}

/* ---------- 快递 ---------- */
.ship-item { padding: 12px 14px; }
.ship-item .ship-main { display: block; color: inherit; word-break: break-word; }
.ship-item .task-tags { margin-top: 8px; }

/* 状态文字 / 标签的着色（发货这套状态） */
.ship-status.st-doing { color: var(--warn); }
.ship-status.st-done { color: var(--success); }
.ship-status.st-cancelled { color: var(--text-2); text-decoration: line-through; }
.ship-item .tag.st-doing { color: var(--warn); border-color: rgba(217, 119, 6, .35); }
.ship-item .tag.st-cancelled { color: var(--text-2); text-decoration: line-through; }

.ship-due-over { color: var(--danger); }

/* 单号用等宽字体：一眼能看清位数，也方便核对 */
.ship-no { font-family: ui-monospace, Menlo, Consolas, monospace; letter-spacing: .5px; }

/* 创建日期：显示在标题左边 */
.ship-date {
  display: inline-block;
  margin-right: 6px;
  font-size: 12px;
  font-weight: 400;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

/* 就地填单号的小表单：默认收起，点「填单号」展开 */
.ship-form {
  margin-top: 10px;
  padding: 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
}

/* 条形码：白底黑条是刻意的（扫码要高对比），不跟随明暗主题 */
.ship-barcode {
  margin-top: 10px;
  padding: 10px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 10px;
  text-align: center;
  overflow-x: auto;
}
.ship-barcode svg { max-width: 100%; height: auto; }
.ship-barcode .small { margin-top: 6px; color: #666; }

/* 输入框 + 扫码按钮并排（按钮不跟着输入框一起拉宽） */
.input-row { display: flex; gap: 8px; }
.input-row > input { flex: 1 1 auto; min-width: 0; }
.input-row > .btn { flex: 0 0 auto; }

/* 扫码取景框：黑底 + 中间一个引导矩形 */
.scan-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  background: #000;
  border-radius: 12px;
  overflow: hidden;
}
.scan-stage video { display: block; width: 100%; height: 100%; object-fit: cover; }
.scan-frame {
  position: absolute;
  left: 6%;
  right: 6%;
  top: 28%;
  height: 44%;
  border: 2px solid rgba(255, 255, 255, .9);
  border-radius: 8px;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, .35);
  pointer-events: none;
}

/* ---------- 快捷记录：类型芯片 ---------- */
.quick-type-chips { margin-bottom: 10px; }
.quick-type-chips .chip { min-height: 34px; padding: 0 12px; }

/* AI 识别结果只是"提示性高亮"，不代表已选中（选中态只有用户点了才有） */
.quick-type-chips .chip.ai-hit {
  border-color: var(--success);
  color: var(--success);
  box-shadow: 0 0 0 2px rgba(22, 163, 74, .16);
}

/* ---------- 小助手（气泡 + 弹窗） ---------- */
.modal-sheet.assistant-sheet {
  /* 比默认抽屉高一些，底部再让出手机的安全区（否则最底下的输入区会被小白条盖住） */
  height: 88vh;
  max-height: 88vh;
  padding: 0 0 env(safe-area-inset-bottom);
  overflow: hidden;
}
.assistant-sheet .modal-head {
  margin: 0;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.assistant-frame-wrap { flex: 1 1 auto; min-height: 0; overflow: hidden; }
.assistant-frame-wrap iframe { width: 100%; height: 100%; border: 0; display: block; }

/* 嵌进弹窗后没有左侧边栏了，底部操作行不用再让位 */
.embed .assistant-composer { left: 0; }

/* 小气泡（录音钮）：比「助手」小一号，落在它上面 */
.mini-fab {
  position: fixed;
  right: 18px;
  bottom: calc(var(--tabbar-h) + 82px + env(safe-area-inset-bottom));
  z-index: 25;
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--surface);
  color: var(--primary);
  border: 1px solid var(--primary);
  box-shadow: 0 4px 14px rgba(47, 111, 237, .22);
  font-size: 20px;
  line-height: 1;
  text-decoration: none;
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
  transition: transform .12s ease;
}
.mini-fab:active { transform: scale(.94); }
/* 录音中：变红（asr_script 会加 rec-live） */
.mini-fab.rec-live { border-color: var(--danger); color: var(--danger); }

/* 没有底部 Tab 的页面（条目详情）：整页只有这一个小按钮，按底部操作栏的高度抬起来 */
.mini-fab-raised { bottom: calc(88px + env(safe-area-inset-bottom)); }

/* 录音结果先落在这个看不见的输入框上，再转交给弹窗 */
.mini-asr-input {
  position: absolute;
  left: -9999px;
  top: 0;
  width: 1px;
  height: 1px;
  opacity: 0;
}

/* 桌面端有左侧边栏，两个悬浮钮都藏掉 */
@media (min-width: 1024px) {
  .mini-fab { display: none; }
}

/* 嵌在右栏预览里时不要悬浮钮（那是给整页用的） */
.embed .mini-fab { display: none; }
.embed .assistant-fab { display: none; }

