:root {
  --primary: #f97316;
  --primary-dark: #ea580c;
  --primary-soft: #fff4ed;
  --primary-border: #ffe0cc;
  --bg: #fff8f3;
  --card: #ffffff;
  --text: #3b2c24;
  --muted: #907668;
  --border: #f2e2d6;
  --success: #16a34a;
  --danger: #dc2626;
  --shadow-sm: 0 1px 3px rgba(59, 44, 36, 0.06);
  --shadow: 0 4px 16px rgba(249, 115, 22, 0.10);
  --shadow-lg: 0 8px 28px rgba(249, 115, 22, 0.16);
  --radius: 14px;

  /* ---------- 布局令牌 ----------
     把「所有可压缩的尺寸」集中成变量。视口不够高时，只需在下面的
     高度媒体查询里改这几个值，整页会等比收紧，不必逐个组件去改。 */
  --pad-app: 14px;      /* 页面四周留白 */
  --pad-panel: 16px;    /* 面板内边距 */
  --pad-card: 12px;     /* 统计卡内边距 */
  --num-size: 26px;     /* 统计数字字号 */
  --gap: 12px;          /* 区块之间的间距 */
  --row-pad: 8px;       /* 表格行的上下内边距 */
  --cell-font: 13.5px;  /* 表格字号 */
  --ctrl-pad: 11px;     /* 输入框 / 按钮的上下内边距 */
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", "Microsoft YaHei", sans-serif;
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  line-height: 1.5;
}

.hidden { display: none !important; }

/* ---------- 口令门 ---------- */
.login {
  max-width: 360px;
  height: 100vh;
  height: 100dvh;
  margin: 0 auto;
  padding: 80px 20px 40px;
  text-align: center;
  overflow-y: auto;   /* 横屏等极矮视口下仍可滚动，不至于够不到按钮 */
}
.login h1 {
  font-size: 24px;
  font-weight: 700;
  color: var(--primary-dark);
  margin-bottom: 28px;
  letter-spacing: 1px;
}
.login input {
  width: 100%;
  padding: 14px 16px;
  margin-bottom: 14px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  font-size: 16px;
  background: var(--card);
  transition: border-color .2s, box-shadow .2s;
}
.login input:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 4px rgba(249, 115, 22, .13);
}
.login button { width: 100%; }

/* ---------- 按钮 ---------- */
button {
  padding: var(--ctrl-pad) 24px;
  border: none;
  border-radius: var(--radius);
  background: linear-gradient(135deg, #fb923c 0%, #f97316 100%);
  color: #fff;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: filter .2s, transform .06s, box-shadow .2s;
}
button:hover {
  filter: brightness(1.05);
  box-shadow: var(--shadow-lg);
}
button:active { transform: translateY(1px); }

.err { color: var(--danger); margin-top: 8px; font-size: 14px; min-height: 20px; }

/* ---------- 主界面 ----------
   整页锁定为「一个视口高」，内部用 flex 纵向分配空间：
   统计卡 / 标签页 固定高度，面板吃掉剩余高度。
   这样页面本身永远不会出现整页滚动条。 */
.app {
  max-width: 720px;
  height: 100vh;                /* 老浏览器兜底 */
  height: 100dvh;               /* dvh = 动态视口高，手机地址栏伸缩时自动跟随 */
  margin: 0 auto;
  padding: var(--pad-app) 16px calc(var(--pad-app) + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  overflow: hidden;
}

/* 顶部统计 */
.stats { display: flex; gap: 12px; flex: 0 0 auto; }
.stat-card {
  flex: 1;
  background: linear-gradient(135deg, #fff6ef 0%, #ffeadb 100%);
  border: 1px solid var(--primary-border);
  border-radius: var(--radius);
  padding: var(--pad-card) 14px;
  text-align: center;
  font-size: 13px;
  color: var(--muted);
  box-shadow: var(--shadow-sm);
}
.stat-card .num {
  font-size: var(--num-size);
  font-weight: 800;
  color: var(--primary-dark);
  margin-top: 2px;
  letter-spacing: .5px;
  line-height: 1.2;
}

/* 标签页 */
.tabs { display: flex; gap: 10px; flex: 0 0 auto; }
.tab {
  flex: 1;
  padding: var(--ctrl-pad) 12px;
  background: #fff;
  color: var(--muted);
  border: 1px solid var(--border);
  font-size: 15px;
  font-weight: 600;
  box-shadow: none;
}
.tab:hover { filter: none; box-shadow: var(--shadow-sm); }
.tab.active {
  background: linear-gradient(135deg, #fb923c 0%, #f97316 100%);
  color: #fff;
  border-color: transparent;
  box-shadow: var(--shadow);
}

/* 面板 */
.panel {
  flex: 0 1 auto;      /* 默认按内容高；空间不足时可被压缩 */
  min-height: 0;       /* 关键：允许 flex 子项真正收缩，内部滚动才会生效 */
  display: flex;
  flex-direction: column;
  background: var(--card);
  border-radius: var(--radius);
  padding: var(--pad-panel);
  box-shadow: var(--shadow-sm);
  border: 1px solid #f7ece3;
  overflow: hidden;
}
/* 查询面板：吃掉剩余的全部高度，交给内部的结果列表去分配 */
#query { flex: 1 1 auto; }
/* 新增面板：表单比面板高时（如手机键盘弹起）整体可滚 */
#add { overflow-y: auto; }

/* 面板里的普通元素不参与压缩，保证按钮、提示始终可见 */
#add > * { flex: 0 0 auto; }
#query > *:not(.table-wrap) { flex: 0 0 auto; }

.panel label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  margin: 0 0 5px;
}
.req { color: var(--danger); margin-right: 3px; font-weight: 700; }

.panel input, .panel select {
  width: 100%;
  padding: var(--ctrl-pad) 14px;
  margin-bottom: var(--gap);
  border: 1.5px solid var(--border);
  border-radius: 12px;
  font-size: 16px;      /* 16px 是 iOS 的临界值：小于它，聚焦时 Safari 会自动放大整个页面 */
  background: #fffdfb;
  color: var(--text);
  transition: border-color .2s, box-shadow .2s, background .2s;
}
.panel input:focus, .panel select:focus {
  outline: none;
  background: #fff;
  border-color: var(--primary);
  box-shadow: 0 0 0 4px rgba(249, 115, 22, .13);
}
.panel button { width: 100%; margin-top: 2px; }

.msg { margin-top: 6px; font-size: 14px; font-weight: 600; min-height: 20px; }
.msg b { color: var(--primary-dark); }

/* 查询 */
.query-bar { display: flex; gap: 10px; }
.query-bar input { flex: 1; margin-bottom: 0; }
.query-bar button { width: auto; margin-top: 0; white-space: nowrap; padding: var(--ctrl-pad) 20px; }
.hint {
  margin-top: 6px;
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.45;
}
.hint b { color: var(--primary-dark); font-weight: 700; }

/* ---------- 结果表格 ----------
   .table-wrap 是「剩余空间的容器」：吃掉查询面板里所有剩下的高度。
   表格内容超出时，只在这里滚动 —— 上方的统计、输入框、提示都不会被顶走。 */
.table-wrap {
  flex: 1 1 auto;
  min-height: 0;
  margin-top: var(--gap);
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}
table { width: 100%; min-width: 560px; border-collapse: collapse; }
th, td {
  padding: var(--row-pad) 10px;
  text-align: left;
  font-size: var(--cell-font);
  border-bottom: 1px solid #f7ece3;
  white-space: nowrap;
}
th {
  position: sticky;     /* 列表滚动时表头固定在顶部 */
  top: 0;
  z-index: 2;
  background: var(--primary-soft);
  color: var(--primary-dark);
  font-weight: 700;
  font-size: 12.5px;
  box-shadow: inset 0 -1px 0 var(--primary-border);
}
tbody tr:nth-child(even) { background: #fffdfb; }
tbody tr:hover { background: var(--primary-soft); }
td { color: #4a3a30; }
#resultInfo { margin-top: 6px; text-align: center; font-size: 12.5px; }

/* ---------- 高度自适应：视口越矮，整体收紧越多 ----------
   顺序有讲究 —— 后面的查询会覆盖前面的，所以按「从宽松到严格」排列。
   目标是让 10 条记录在尽量多的设备上都能一屏放下。 */
@media (max-height: 860px) {
  :root {
    --pad-app: 12px;
    --gap: 10px;
    --row-pad: 7px;
    --pad-card: 10px;
    --num-size: 23px;
  }
  .hint-long { display: none; }   /* 矮屏先砍掉说明文字的长尾 */
}
@media (max-height: 760px) {
  :root {
    --pad-app: 10px;
    --gap: 8px;
    --row-pad: 5px;
    --pad-card: 8px;
    --num-size: 20px;
    --ctrl-pad: 10px;
  }
}

/* ---------- 窄屏（手机）：表格重排成两行卡片，彻底消除横向滚动 ----------
   同一段 HTML，不改渲染结构，只用 CSS 把 6 个单元格重新排布：
     第 1 行：手机号（加粗）  姓名（加粗）
     第 2 行：卡号  编号  额度（右对齐）  开卡时间（右对齐，仅到日）
   把手机号提到第一行并加粗，是因为查询时店员最先要核对的就是它；
   卡号排在第二行首位（等宽字体，视觉更醒目），编号随后。 */
@media (max-width: 700px) {
  :root {
    --pad-app: 10px;
    --pad-panel: 10px;
    --gap: 8px;
    --pad-card: 8px;
    --num-size: 20px;
    --row-pad: 4px;
    --ctrl-pad: 10px;
  }
  .app { padding: var(--pad-app) 10px calc(var(--pad-app) + env(safe-area-inset-bottom, 0px)); }
  .login { padding-top: 48px; }
  .hint-long { display: none; }

  .table-wrap { overflow-x: hidden; }
  table { min-width: 0; }
  thead { display: none; }        /* 表头去掉：每条记录自带两行，字段位置固定 */

  tbody tr {
    display: grid;
    /* 列宽分配：两行共用 4 列，但语义不同 ——
       第 1 行（手机号+姓名）：手机号按内容取宽（auto），姓名吃掉剩余空间（1fr）；
       第 2 行（卡号+编号+额度+时间）：卡号 = 编号的两倍（2fr : 1fr），
       额度和时间仍按内容取宽（auto），保持不变。
       所以用 4 列「auto 1fr auto auto」作骨架，第一行第 1 列按内容、第 2 列弹性；
       第二行第 1、2 列需改成 2:1，靠下面对 grid-area 的 min/max 收紧实现。 */
    /* 列宽：第 1 列 = 第 2 列的两倍（2fr : 1fr），第 3、4 列按内容取宽（auto）不变。
       这一比例同时作用于两行：
         第 1 行  手机号(2fr) : 姓名(1fr)
         第 2 行  卡号(2fr)   : 编号(1fr)  额度(auto) 时间(auto) */
    grid-template-columns: 2fr 1fr auto auto;
    grid-template-areas:
      "phone name .  ."
      "cardno code  bal  time";
    align-items: center;
    gap: 1px 8px;
    padding: var(--row-pad) 10px;
    border-bottom: 1px solid #f7ece3;
  }
  tbody tr:nth-child(even) { background: #fffdfb; }
  tbody tr:hover { background: #fffdfb; }

  tbody td {
    border: 0;
    padding: 0;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.25;
  }

  /* 第 1 行：手机号 + 姓名 —— 查询时最先核对的两项，加粗放大 */
  tbody td:nth-child(4) { grid-area: name;  font-weight: 700; font-size: 13.5px; }
  tbody td:nth-child(5) { grid-area: phone; font-weight: 700; font-size: 13.5px; }

  /* 第 2 行：卡号 / 编号 / 额度 / 时间 —— 次要信息，回到 12px */
  tbody td:nth-child(1) { grid-area: code;   font-size: 12px; color: var(--muted); }
  tbody td:nth-child(2) {
    grid-area: cardno;
    font-size: 12px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;   /* 卡号等宽，数字对得齐 */
    letter-spacing: .3px;
    /* 关键：给卡号列一个最小宽度。
       姓名跨了「卡号/额度/时间」三列，它的宽度需求会挤占这个弹性列 ——
       实测 320px 宽时列只剩 78.5px，而 12 位卡号需要约 83px，会被省略号吃掉。
       卡号是核对实体卡的唯一依据，宁可从姓名那边借空间，也不能让卡号不全。 */
    min-width: 90px;
  }
  tbody td:nth-child(3) { grid-area: bal;  text-align: right; font-size: 12px; font-weight: 700; color: var(--primary-dark); }
  tbody td:nth-child(6) { grid-area: time; text-align: right; font-size: 12px; color: var(--muted); }

  /* 手机端开卡时间只显示到日：.t-clock 是"时:分"那段，桌面端仍完整显示 */
  tbody td:nth-child(6) .t-clock { display: none; }

  /* 「无结果」「查询失败」这类 colspan 整行提示：占满整行并居中
     （必须排在上面 nth-child 规则之后，否则会被 grid-area 抢占） */
  tbody td[colspan] { grid-area: auto; grid-column: 1 / -1; text-align: center; }
}

/* ---------- 极矮视口（约 640px 高的老设备 / 笔记本内容区）----------
   放在最后，因为它要覆盖上面所有档位 —— CSS 变量同优先级时「后定义者胜」。
   到这个尺寸，一屏放 10 条已经很勉强，把非关键信息让位给结果列表。 */
@media (max-height: 700px) {
  :root {
    --pad-app: 8px;
    --pad-panel: 10px;
    --pad-card: 7px;
    --num-size: 18px;
    --gap: 6px;
    --row-pad: 2px;
    --cell-font: 12px;
    --ctrl-pad: 9px;
  }
  th, td { line-height: 1.2; }
  .stat-card { font-size: 12px; }
  .msg { min-height: 18px; }
  #qHint { display: none; }       /* 输入框本身就能看到位数，优先把高度留给结果 */
  /* 只隐藏查询框上方那段静态说明（注意别连 #resultInfo 一起藏掉 ——
     它没有自己的 display，会被这条规则连带隐藏）。空查询时下方仍会提示
     「未输入手机号码，显示最近的 10 条」，信息不丢。 */
  .hint-static { display: none; }
}

/* 手机 + 矮屏（如 360×640）：第一行的加粗信息也收回到 12px，
   把高度让给结果列表。必须同时限定 max-width，否则会波及矮屏的桌面端
   （桌面端是普通表格，没有"第一行"的概念）。 */
@media (max-width: 700px) and (max-height: 700px) {
  tbody td:nth-child(4),
  tbody td:nth-child(5) { font-size: 12px; }
}

/* 超窄屏（≤359px，如 iPhone SE 一代 320px）：
   两行里要塞下「手机号 + 姓名」和「编号 + 卡号 + 额度 + 日期」，物理上很紧 ——
   实测 320px 只有 258px 可用，全部完整显示需要约 270px。因此这一档：
     · 字号压到 11px、列间距收到 2px，把空间挤出来；
     · 给手机号、卡号各设最小宽度，谁都不能被省略号吃掉
       （手机号是查询依据、卡号是核对实体卡的依据）；
     · 代价是姓名可能被截断 —— 它是最不关键的信息，优先让位。
   这一档不承诺一屏放下 10 条，结果列表内部可滚动，但上述关键信息必须完整。 */
@media (max-width: 359px) {
  tbody tr { column-gap: 2px; }
  tbody td:not([colspan]) { font-size: 11px; }
  tbody td:nth-child(2) { min-width: 84px; }   /* 卡号：12 位完整 */
  tbody td:nth-child(5) { min-width: 81px; }   /* 手机号：11 位完整 */
}
