/* The accent carries white text on the header bar AND is used as link text on
   white (.dl, .tab.on), so it has to clear 4.5:1 against both. This pink is
   5.9:1 — a pastel one reads prettier on the header and makes 下载当前视图
   unreadable, which is why the shade is this deep. --a/--b are untouched: they
   mean grade A and grade B, not decoration. */
:root{--bg:#faf7f8;--card:#fff;--line:#ebe3e7;--ink:#1f2328;--mut:#6b6266;
--accent:#c2185b;--a:#ff8080;--b:#ffcc80;--warn:#b3261e}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);
font:15px/1.6 -apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif}
header{background:var(--accent);color:#fff;padding:.7rem 1rem;display:flex;
align-items:center;gap:1rem;flex-wrap:wrap}
header a{color:#fff;text-decoration:none;opacity:.9;padding:.25rem .55rem;
border-radius:6px}
header a:hover{opacity:1;text-decoration:underline}
/* Current page. Not colour alone: the underline keeps it legible for anyone
   who can't distinguish the tint against the header bar. */
header a.on{opacity:1;background:rgba(255,255,255,.22);font-weight:600;
box-shadow:inset 0 -2px 0 #fff;text-decoration:none}
header a.on:hover{text-decoration:none}
header .sp{margin-left:auto;font-size:.85rem;opacity:.85}
main{max-width:1100px;margin:1.2rem auto;padding:0 1rem}
.card{background:var(--card);border:1px solid var(--line);border-radius:10px;
padding:1.1rem;margin-bottom:1.1rem}
h1{font-size:1.3rem;margin:.2rem 0 1rem}h2{font-size:1.05rem;margin:0 0 .8rem}
table{width:100%;border-collapse:collapse;font-size:.9rem}
th,td{text-align:left;padding:.45rem .5rem;border-bottom:1px solid var(--line);
vertical-align:top}
th{color:var(--mut);font-weight:600;white-space:nowrap}
label{display:block;margin:.6rem 0 .2rem;font-size:.85rem;color:var(--mut)}
input,select,textarea{width:100%;padding:.5rem;border:1px solid var(--line);
border-radius:6px;font:inherit;background:#fff}
textarea{min-height:70px;resize:vertical}
button{background:var(--accent);color:#fff;border:0;border-radius:6px;
padding:.55rem 1.1rem;font:inherit;cursor:pointer}
button:hover{filter:brightness(1.08)}
button.sec{background:#efe7eb;color:var(--ink)}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:.8rem}
.msg{padding:.6rem .8rem;border-radius:6px;margin-bottom:.8rem}
/* An error and a note are now both pale pinks, so the error keeps a
   deliberately stronger border — 未保存 must not read as ordinary chatter. */
.err{background:#fdeae8;color:var(--warn);border:1px solid #eeb0aa}
/* 保存被拒时圈出出错的那一格 —— 见 _form_error.html。padding 是为了让一整组
   checkbox 被框住时不贴着边框。 */
.field-err{outline:2px solid var(--warn);outline-offset:3px;border-radius:4px;
  padding:.2rem;scroll-margin:5rem}
.note{background:#fdf1f6;border:1px solid #f0d8e4;color:#7c3357}
/* AI 辅助录入填过的格子。要的是"这几处是机器填的，看一眼"，不是"这几处错了"
   —— 所以是一条淡色的边，不是 .field-err 那种红框。勾选组标在 <label> 上，
   日期标在看得见的那个框上（提交的 hidden 根本没有样子可标）。 */
.ai-filled{background:#fff8e6;box-shadow:0 0 0 2px #f3dfae;border-radius:4px}
label.ai-filled{padding:0 .25rem;margin-left:-.25rem}
.pill{display:inline-block;padding:.1rem .5rem;border-radius:99px;font-size:.78rem}
.g-A{background:var(--a)}.g-B{background:var(--b)}.g-C{background:#eceff1}
.g-D{background:#d9d9d9}
pre{background:#11151a;color:#d7dde3;padding:.8rem;border-radius:8px;
overflow:auto;max-height:380px;font-size:.82rem;line-height:1.5;white-space:pre-wrap}
.mut{color:var(--mut);font-size:.85rem}
/* .mut 兼着两件事：调淡颜色 + 缩小字号。整格用它的时候（录入者、分级依据、
   时间那几列）只想要前者 —— 缩小字号的结果是同一行里 录入者/分级依据 是
   13.6px，邻座是 14.4px，一张表两种字号。只夹整格：格子里内嵌的
   <span class="mut">（"80% 4/5" 那个 4/5）本来就该比主数字小。 */
table td.mut,table th.mut{font-size:inherit}
ul.files{list-style:none;padding:0;margin:0}
ul.files li{padding:.3rem 0;border-bottom:1px solid var(--line)}
/* ICP/公安备案 numbers are legally required on every page and must link out. */
footer{max-width:1100px;margin:0 auto 1.4rem;padding:0 1rem;text-align:center;
color:var(--mut);font-size:.78rem}
footer a{color:var(--mut);text-decoration:none}
footer a:hover{text-decoration:underline}

/* ---- Wide-table treatment, shared by every table on the site ------------
   Wrap the table in .scroller, put a .hbar right after it, give free-text
   cells class="cell" with the text in a <span>. The JS at the bottom of the
   page wires the rest up. Written once here rather than per template: the
   first version of this lived only in 总览, and every other table on the
   site grew a different, worse answer to the same problem. */

/* Any wide table scrolls inside its own box; the page itself must never
   scroll sideways, or the header and nav drift off screen with it. */
.scroller,div[style*="overflow-x"]{max-width:100%}
/* Horizontal only. The height stays auto so the page keeps scrolling the
   rows as one document -- overflow-y:hidden clips nothing here, it only
   stops the browser adding a second, vertical scrollbar. */
.scroller{overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;
overscroll-behavior-x:contain}
/* The real bar sits at the bottom of a long table, which is nowhere near
   where you are reading. Hide it and drive the table from a proxy bar that
   sticks to the bottom of the viewport instead. */
.scroller{scrollbar-width:none}
.scroller::-webkit-scrollbar{display:none}
.hbar{position:sticky;bottom:0;z-index:5;overflow-x:auto;overflow-y:hidden;
height:14px;margin-top:2px;background:var(--card);border-top:1px solid var(--line)}
.hbar>div{height:1px}
.hbar::-webkit-scrollbar{height:12px}
.hbar::-webkit-scrollbar-thumb{background:#b6bfc8;border-radius:6px}
.hbar::-webkit-scrollbar-thumb:hover{background:#9aa5b1}
.hbar::-webkit-scrollbar-track{background:#eef1f4;border-radius:6px}
/* One line per cell keeps every row the same height, which is what makes a
   wide table scannable. The full text is still in the DOM -- clipped, never
   truncated -- so hover (title) and tap-to-expand both have something to
   show. */
/* 这句一直没起作用：auto 布局下 max-width 加在 td 上，浏览器**不认**，列宽照
   内容算。留着是给下一个人看的路标 —— 真正管宽度的是下面 .fixed 那一段。 */
table.rows td.cell>span{display:block;white-space:nowrap;overflow:hidden;
text-overflow:ellipsis}
table.rows tr.open td.cell>span{white-space:pre-wrap;overflow:visible}
/* ---- 定宽列 -------------------------------------------------------------
   一个 40 字的昵称本来能把那一列顶到 600px，把 第一次咨询记录 挤到只剩一点：
   最该读的那一列，被最不该占地方的那一格挤掉。列宽从此由 <col> 说了算。

   table-layout:fixed 要配 width:min-content 才真的照声明走：width:auto 和
   max-content 仍按内容算（昵称列实测 563px），width:100% 会把声明的宽度按比
   例放大（176 → 294）。min-content 下表格正好是各列之和，横向滚动交给
   .scroller —— 这张表本来就比一屏宽。

   每一列都必须在 colgroup 里有一格：fixed 布局下没被指定宽度的列去分"剩下
   的空间"，而 min-content 下剩下的空间是 0，那一列会直接塌成看不见。铅笔、
   灯泡、等级 这些也因此在 views.CHROME_WIDTHS 里点了名。 */
table.rows.fixed{table-layout:fixed;width:min-content}
/* 列不多、加起来还没一屏宽的表（待并入的手工录入线索）用 .fill：宽度照声明
   走，剩下的空间**全给最后一列** —— 那一列在 colgroup 里不写宽度就行。
   不这么做的话，min-content 会让这张六列的表缩在左边、右边空一大片。
   注意不能只把 width 改成 100% 而所有列都指定：那样浏览器会把声明的宽度按
   比例一起放大（量过：176 → 294），等于没定宽。 */
table.rows.fixed.fill{width:100%}
/* 表头允许折行：这样 第一次咨询教练 七个字也能待在 6rem 的列里，宽度按格子里
   的内容定，不被列名绑架。数据格仍是一行——一行一高才扫得动。 */
table.rows.fixed th{white-space:normal;overflow-wrap:anywhere}
/* 这几个数是量出来的，不是拍的。定宽自然会比原来宽（原来大部分列被挤到
   74px，是"挤得下"不是"读得了"），所以挑的是总宽只多两成、而最左边那十列
   仍然一屏放得下的那一档：前十列合计 948px < 一屏 1031px —— 比改之前
   （长值在场时 985px）还宽松一点。再宽一档总宽就到 4300+，第一屏就摆不下
   刚排到最左边的那几列了，那等于把上一版排序的收益吐回去。 */
/* w-name 是 5rem 而不是 4.5：四个字的列名（跟踪教练、线索归属）正好在 5rem
   里排得下一行，4.5rem 会把它们折成两行，把整个表头拉高一截。七个字的
   第一次咨询教练 仍然折两行 —— 那是有意的，列宽该由格子里的人名定，不该由
   列名定。 */
table.rows.fixed col.w-icon{width:2.4rem}
table.rows.fixed col.w-bulb{width:3rem}
table.rows.fixed col.w-flag{width:4rem}
table.rows.fixed col.w-name{width:5rem}
table.rows.fixed col.w-date{width:5.5rem}
table.rows.fixed col.w-id{width:7rem}
table.rows.fixed col.w-mid{width:7.5rem}
table.rows.fixed col.w-multi{width:6.5rem}
table.rows.fixed col.w-long{width:11rem}
/* 展开那一行看全文时，定宽反而碍事：这一行的格子改成按内容折行。 */
table.rows.fixed tr.open td.cell>span{white-space:pre-wrap;overflow:visible;
overflow-wrap:anywhere}
table.rows tbody tr{cursor:pointer}
table.rows tr.open{background:#fbf2f6}
/* Icon-only control: the label lives in aria-label/title, and it needs a
   visible focus ring since there is no text to underline. Works on a link or
   a button — a row's 修改 and 删除 sit side by side and have to read as one
   pair of controls, not a link next to a filled button. */
.icon{display:inline-flex;padding:.2rem;border-radius:5px;color:var(--mut);
line-height:0}
.icon:hover{background:#f8eef3;color:var(--accent)}
.icon:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* Undo the filled-button look. Every one of these beats the plain `button`
   rules on specificity, including the full-width mobile override below. */
button.icon{background:none;border:0;width:auto;cursor:pointer}
button.icon:hover{filter:none}
/* Destructive: red on hover rather than the accent pink, so 删除 does not
   look like one more way to open the row. */
.icon.danger:hover{background:#fdeae8;color:var(--warn)}

/* 重点跟进的灯泡，挨着铅笔单独一列。没亮时是淡淡的描边（在那儿，但不抢戏），
   亮起来是填实的琥珀色 —— 和 B 级那个浅橙药丸隔了一列，不会看混。
   从不只靠颜色：亮/灭是形状上的差别（填充 vs 空心），列头还写着「重点」。 */
.icon.bulb{color:#d9cbd3}
.icon.bulb:hover{color:#c8901f;background:#fdf6e6}
.icon.bulb.on{color:#c8901f;--bulb-fill:#f7d270}
.icon.bulb.on:hover{color:#a8770f;background:#fdf6e6}
/* 亮着的灯要真的"发光"：两层 drop-shadow，近处一圈实的、远处一圈散的，
   模仿灯泡本身的光晕。只加在亮着的图标上，灭的那些保持安静。 */
.icon.bulb.on svg{filter:drop-shadow(0 0 1.5px rgba(233,169,32,.95))
 drop-shadow(0 0 5px rgba(247,210,112,.75))}
/* 刚点亮的那一下：光晕从强到常态收一次，告诉你"这一下生效了" —— 就地切换没有
   页面刷新，不给点反馈的话人会怀疑自己有没有点到。 */
@keyframes bulb-lit{
  0%{filter:drop-shadow(0 0 0 rgba(233,169,32,0));transform:scale(.8)}
  45%{filter:drop-shadow(0 0 3px rgba(233,169,32,1))
      drop-shadow(0 0 12px rgba(247,210,112,.95));transform:scale(1.18)}
  100%{filter:drop-shadow(0 0 1.5px rgba(233,169,32,.95))
       drop-shadow(0 0 5px rgba(247,210,112,.75));transform:scale(1)}
}
.icon.bulb.lit svg{animation:bulb-lit .45s ease-out}
.icon.bulb.busy{opacity:.5}
@media (prefers-reduced-motion:reduce){
  .icon.bulb.lit svg{animation:none}
}

/* ---- 会员资料：档位与进度 ---------------------------------------------------
   档位牌上写的就是金额。原来这里有四种金属渐变配 白银/黄金/铂金/钻石，全撤了：
   金额本身已经是档位，一层译名加一套颜色，只是让人多记两遍同一件事。 */
.lv{display:inline-flex;align-items:center;gap:.3rem;padding:.15rem .55rem;
border-radius:99px;font-size:.78rem;font-weight:600;letter-spacing:.02em;
font-variant-numeric:tabular-nums;background:#f3eef1;color:#5c4b54;
border:1px solid var(--line)}

/* 进度条的三个色系。颜色回答的是"这条说的是哪一类事"，不是"这是第几条"：
     钱   —— 支付进度：金（#ffdb51）
     时间 —— 会员期限：爱马仕橙（#f37021，Pantone 1448 C）
     交付 —— 学习进度 / 起步陪跑 / 资深陪跑 / 高级课程：品牌粉
   **四条交付共用一个色是有意的。** 这一页上真正要读的是交付和时间之间的
   **差**（服务期走了 80%，起步陪跑才 30%）；给每条交付各配一个色，等于把要比
   的两组东西打散成七种颜色，差反而读不出来了。模块名就写在左边，颜色再说一遍
   也是白说。归色在 main.py 的 BAR_TONES。

   金这一条要额外撑一下：#ffdb51 太亮，和 #efe9ec 的空槽只差 1.13:1 的对比度
   （非文字元素的下限是 3:1），直接铺上去，付了一半的条看着像一条没付的空条。
   所以左端起一段深金，再给填充部分描一圈 1px 的暗金边 —— 读的是**边界**，不
   是亮度差。改色时这两样得跟着改，只换 background 会把条读没。 */
.bar{position:relative;height:9px;border-radius:99px;background:#efe9ec;
overflow:hidden;margin:.2rem 0}
.bar>i{display:block;height:100%;border-radius:99px}
.bar-time>i{background:linear-gradient(90deg,#f9a03f,#f37021)}
.bar-done>i{background:linear-gradient(90deg,#f06292,var(--accent))}
.bar-money>i{background:linear-gradient(90deg,#ffc72c,#ffdb51);
box-shadow:inset 0 0 0 1px rgba(140,92,0,.5)}
/* 第一列放得下四个字：模块名是 支付进度/会员期限/学习进度/起步陪跑 这一类，
   2.4rem 是「时间」「进度」两个字时代的宽度，四个字会折行。 */
.bar-row{display:grid;grid-template-columns:4.2rem 1fr auto;gap:.5rem;
align-items:center;font-size:.8rem;color:var(--mut);margin:.15rem 0}
.bar-row b{font-variant-numeric:tabular-nums;color:var(--ink);font-weight:600}

/* 会员级别阶梯。格子标的是**金额** —— 白银/黄金/铂金/钻石 那套叫法不用了，
   金额本身就是档位，也不用记哪个词排在哪个词前面。
   **只亮一格**（见 members.ladder_for）：一条报名记录只有一个金额，亮成一排
   读起来像"她买过这几档"，还得回头数格子才知道她是哪一档。
   亮的那格是品牌粉，不跟支付那条的金走。级别不是一条进度 —— 它没有"走到哪
   了"，它是一个已经定下来的事实，长得也和进度条不一样（一排格子，不是一条
   填充）。抬头第一行用品牌色，剩下的颜色才好各自说各自的事。
   教练班和合伙人还没有定义，画成斜纹占位：看得见位置，但明显不是"她到了这一
   档"。 */
.ladder{display:flex;gap:2px;border-radius:99px;overflow:hidden}
.ladder>i{flex:1;text-align:center;font-style:normal;font-size:.7rem;
line-height:1.5rem;background:#efe9ec;color:var(--mut);white-space:nowrap}
.ladder>i.on{background:linear-gradient(90deg,#f06292,var(--accent));
color:#fff;font-weight:600}
.ladder>i.pending{background:repeating-linear-gradient(45deg,#f6f2f4,
#f6f2f4 4px,#ece5e9 4px,#ece5e9 8px);color:#b3a8ae}

/* 报名信息里改不了的字段。长得像一行字而不是一个灰输入框：禁用的输入框看起来
   像"暂时不能填"，而这是"这一格不归你填"，两回事。 */
.ro{padding:.45rem 0;color:var(--ink)}

/* 核对状态。三种状态得长得不一样：待核对是"还没人看过"，值变了是"看过但
   底下的数改了" —— 后者正是财务要回头再看一眼的那一批，混进灰色里就找不着了。 */
.ckrow{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;
margin:.05rem 0 .45rem 4.7rem;font-size:.74rem}
.ckrow form{margin:0}
.ckrow button{padding:.12rem .5rem;font-size:.72rem;width:auto}
.ck.ok{color:#1f7a4d}
.ck.stale{color:var(--warn)}
.ck.none{color:var(--mut)}

/* 收款流水。缩进对齐核对那一行（4.7rem = 模块名那一列 + 间距），因为它说的是
   上面那条支付进度，不是一段独立的内容。
   窄：一笔收款只有 日期/金额/备注/谁记的 四样，撑满整卡宽度反而要横着扫。 */
.paylog{margin:0 0 .7rem 4.7rem}
.payacts{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap;
margin:0 0 .35rem}
.payacts form{margin:0}
.payacts button.sec{width:auto;padding:.15rem .55rem;font-size:.74rem}
.payacts .backfill button{padding:.3rem .6rem}
.payacts .backfill input[name=amount]{width:6.5rem}
.paytab{width:auto;min-width:26rem;max-width:100%;font-size:.78rem}
.paytab td{padding:.2rem .55rem .2rem 0;border-bottom:1px solid var(--line)}
/* 金额右对齐、等宽数字：一列钱是用来竖着加的，对不齐就得一个个读。 */
.paytab td.amt{text-align:right;font-variant-numeric:tabular-nums;
font-weight:600;color:var(--ink);white-space:nowrap}
.paytab tr.void td.amt{font-weight:400}
/* 撤销那一列宽度按内容走，别把「已撤销」三个字挤成两行。**不要用 width:1%**
   那个老写法：Chrome 会把它反推成"表格至少要有 内容宽/1% 那么宽"，整张表就
   被撑满整张卡片，四列钱横着散开，加都加不起来。 */
.paytab td.act{text-align:right;white-space:nowrap;padding-right:0}

/* 公告弹窗。盖住整页而不是浮在角上：角落里那张卡片试过一版，第一眼没人看见 ——
   而这条要说的事值得挡一下路。
   .modal[hidden] 必须显式写出来：display:flex 会盖掉 hidden 自带的 display:none，
   于是 JS 还没跑起来那一瞬间弹窗会闪一下。 */
.modal{position:fixed;inset:0;z-index:100;display:flex;align-items:center;
justify-content:center;padding:1.5rem;background:rgba(31,35,40,.55)}
.modal[hidden]{display:none}
.sheet{background:var(--card);border-radius:16px;padding:1.8rem 1.9rem;
max-width:30rem;width:100%;box-shadow:0 18px 50px rgba(31,35,40,.3);
max-height:90vh;overflow:auto}
.sheet h2{margin:0 0 .8rem;font-size:1.35rem}
.sheet p{margin:0 0 .8rem;font-size:1rem;line-height:1.7}
.acts{display:flex;gap:.7rem;align-items:center;flex-wrap:wrap;margin-top:1.3rem}
.acts .go{display:inline-block;background:var(--accent);color:#fff;
padding:.6rem 1.4rem;border-radius:8px;font-weight:600;text-decoration:none;
font-size:1rem}
.acts .go:hover{filter:brightness(1.08)}
.acts .later{width:auto;padding:.6rem 1rem;background:none;border:0;
color:var(--mut);font-size:.9rem;cursor:pointer}
.acts .later:hover{color:var(--ink);text-decoration:underline}

/* 暂停的那一段。灰掉而不是缩小或加边框：她还是会员，卡片上每一个字都还成立，
   只是这周不用排课。grayscale 把等级色和进度条的粉一起洗掉 —— 只调 opacity
   会让整段看起来像"还在加载"。 */
.psec{margin-top:1.6rem}
.psec>h2{font-size:.95rem;color:var(--mut);margin:0 0 .2rem;font-weight:600}
.paused{filter:grayscale(1);opacity:.7}
.paused:hover,.paused:focus-within{opacity:.92}

/* 落后提示。不是装饰：这是会员资料页唯一一个"现在该有人去做点什么"的信号。 */
.lag{display:inline-block;padding:.12rem .5rem;border-radius:6px;
background:#fdeae8;color:var(--warn);border:1px solid #eeb0aa;font-size:.78rem}

.mcards{display:grid;gap:.8rem;
grid-template-columns:repeat(auto-fill,minmax(272px,1fr))}
/* 整张卡片就是链接（见 members.html 里的注释），所以要先把 <a> 的默认蓝色
   下划线关掉，再靠 hover/focus 和底部的 .cta 把"这能点"说清楚。 */
.mcard{background:var(--card);border:1px solid var(--line);border-radius:12px;
padding:.85rem .9rem;display:flex;flex-direction:column;gap:.35rem;
text-decoration:none;color:inherit}
.mcard:hover{border-color:#e0c4d3;box-shadow:0 2px 10px rgba(194,24,91,.07)}
.mcard:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.mcard .who{font-weight:600;font-size:1rem}
.mcard .meta{font-size:.82rem;color:var(--mut)}
.mcard .top{display:flex;align-items:center;justify-content:space-between;
gap:.5rem}
/* 新用户不知道点卡片能改进度，所以把去处直接写在卡片底部，不指望她自己发现
   名字能点。margin-top:auto 把它钉在卡片底边，卡片高矮不一也对齐。 */
.mcard .cta{margin-top:auto;padding-top:.3rem;color:var(--accent);
font-size:.82rem;font-weight:600}
.mcard:hover .cta{text-decoration:underline}

/* .dl 一直没有专门的规则，全靠浏览器默认的蓝色下划线撑着 —— 能用但和页面
   其它地方的粉色品牌色不搭，重点行动（新增会员）混在一堆提示文字链接里
   也不够显眼。这里先给它一个和品牌一致、明确带下划线的样子；真正需要「像
   按钮」的入口（新增会员）另外用 .btn-add。 */
.dl{color:var(--accent);text-decoration:underline}
.dl:hover{color:#8f1345}

/* 「新增会员」是这页唯一的主动作，得长得像按钮，不能和一堆说明性文字链接
   混在一起，不然新用户扫一眼找不到从哪儿开始。 */
.btn-add{display:inline-flex;align-items:center;background:var(--accent);
color:#fff;padding:.4rem .8rem;border-radius:6px;text-decoration:none;
font-size:.85rem;font-weight:600}
.btn-add:hover{filter:brightness(1.08)}

/* 卡片/列表切换：做成分段控件（segmented control）的样子——选中的一格填色，
   两格本身带边框像"能点的按钮"，而不是原来那种"卡片 · 列表"纯文字，容易被
   当成静态标签看过去。 */
.viewtabs{display:inline-flex;border:1px solid var(--line);border-radius:99px;
padding:2px;background:#fff}
.viewtabs a{padding:.25rem .75rem;border-radius:99px;text-decoration:none;
color:var(--mut);font-size:.85rem}
.viewtabs a:hover{color:var(--ink)}
.viewtabs a.on{background:var(--accent);color:#fff;font-weight:600}

/* 汇总条：每一格都是一个筛选器，所以它们必须看起来可以点。 */
.tally{display:flex;flex-wrap:wrap;gap:.4rem}
.tally a{display:inline-flex;align-items:center;gap:.35rem;padding:.3rem .7rem;
border:1px solid var(--line);border-radius:99px;text-decoration:none;
color:var(--ink);font-size:.85rem;background:#fff}
.tally a:hover{border-color:var(--accent);color:var(--accent)}
.tally a.on{border-color:var(--accent);background:#fdf1f6;color:var(--accent);
font-weight:600}
.tally a b{font-variant-numeric:tabular-nums}
.tally a.alert{border-color:#eeb0aa;color:var(--warn);background:#fdeae8}

/* 服务清单。一组一块，组名是海报上那一行（起步教练/资深教练/…）。 */
.chk{border-top:1px solid var(--line);padding:.5rem 0}
.chk:first-child{border-top:0}
.chk h3{font-size:.85rem;color:var(--mut);margin:0 0 .4rem;font-weight:600}
/* 一行一项服务。四列：勾选框 / 做什么 / 走到哪 / 补记。勾选框在最前面，和海报
   上那一列 ✅ 是同一个位置。 */
.chk .item{display:grid;grid-template-columns:auto 1fr auto auto;gap:.6rem;
align-items:center;padding:.35rem 0;border-top:1px dashed #f1e8ed}
.chk .item:first-of-type{border-top:0}
/* 勾完之后带锚点跳回来。留出上边距，让那一行落在视线中段而不是贴着窗口顶边 ——
   贴顶的话看不见它上面是哪一组，等于还是迷路。:target 那一下淡粉色是告诉你
   "刚才点的是这一行"。 */
.chk .item{scroll-margin-top:35vh}
.chk .item:target{background:#fdf1f6;border-radius:6px;
box-shadow:0 0 0 6px #fdf1f6}
.card[id]{scroll-margin-top:1rem}
.chk .item.done .what{color:var(--mut)}
.tickf{margin:0;display:flex}
/* 长得像勾选框的按钮：它要一眼就能认出来是"可以点的方框"，而不是又一个粉色
   按钮 —— 一行里有十几个粉色按钮时，眼睛就不知道该看哪儿了。 */
button.tick{width:20px;height:20px;padding:0;border-radius:5px;background:#fff;
border:1.5px solid #d9cbd3;color:#fff;font-size:.8rem;line-height:1;
display:flex;align-items:center;justify-content:center;cursor:pointer}
button.tick:hover{border-color:var(--accent);filter:none}
button.tick.on{background:var(--accent);border-color:var(--accent)}
button.tick.part{border-color:var(--accent);color:var(--accent);
background:#fdf1f6;font-weight:700}
button.tick:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.chk h3{display:flex;align-items:center;gap:.5rem}
/* 组一级的完成度：清单十四行，先看哪一段落下了，再往里翻。 */
.gbar{flex:0 0 72px;height:5px;border-radius:99px;background:#efe9ec;overflow:hidden}
.gbar>i{display:block;height:100%;background:var(--accent);border-radius:99px}
/* 一格一次。24 个小格比一个「3/24」更快让人知道走到哪了，而且不用读数字。 */
.pips{display:flex;flex-wrap:wrap;gap:2px;align-items:center;max-width:15rem;
justify-content:flex-end}
.pip{width:11px;height:11px;border-radius:2px;background:#e8dfe4;
box-shadow:inset 0 0 0 1px rgba(0,0,0,.04);padding:0;border:0}
.pip.on{background:var(--accent)}
/* 亮着的格子是按钮：点它撤掉那一次。悬停时缩一下并露出红边，好让"这个能点、
   而且点了会拿掉东西"在按下之前就看得出来。 */
button.pip{cursor:pointer}
button.pip:hover{background:var(--warn);transform:scale(.85)}
button.pip:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.more{margin:0}
.more summary{font-size:.8rem;cursor:pointer;white-space:nowrap;color:var(--mut)}
.backfill{display:flex;gap:.3rem;margin-top:.3rem}
.backfill input[type=date]{width:9.5rem}

/* 日期：自带的日历。浮层挂在 body 上（position:fixed），因为表格那一列在一个
   overflow:auto 的容器里 —— 挂在输入框旁边会被裁掉半个日历。 */
.datebox{width:11rem}
.cal{position:fixed;z-index:60;display:none;width:16.5rem;padding:.5rem;
background:var(--card);border:1px solid var(--line);border-radius:10px;
box-shadow:0 8px 28px rgba(0,0,0,.14)}
.cal .hd{display:flex;align-items:center;justify-content:space-between;gap:.3rem}
.cal .hd b{font-size:.95rem}
.cal button{font:inherit;background:none;border:0;color:var(--ink);cursor:pointer;
border-radius:6px;padding:.3rem .5rem}
.cal button:hover{background:var(--bg)}
.cal .g{display:grid;grid-template-columns:repeat(7,1fr);margin-top:.3rem;
text-align:center}
.cal .g span{color:var(--mut);font-size:.75rem;padding:.25rem 0}
.cal .g button{padding:.35rem 0}
.cal .g button.off{color:var(--mut);opacity:.5}
/* 选中那天不只靠颜色：加粗一并留着，浏览器的强制深色模式会把 accent 改掉。 */
.cal .g button.on{background:var(--accent);color:#fff;font-weight:600}
.cal .g button.now{box-shadow:inset 0 0 0 1px var(--accent)}
.cal .ft{display:flex;justify-content:space-between;margin-top:.35rem;
padding-top:.35rem;border-top:1px solid var(--line)}
.backfill input[name=note]{width:8rem}
.backfill button{width:auto;padding:.35rem .7rem}
.acts button.sec{width:auto;padding:.32rem .7rem;white-space:nowrap}
.chk .n{font-variant-numeric:tabular-nums;font-size:.85rem;color:var(--mut)}
.chk .n.full{color:#1b7a4b;font-weight:600}
.chk .dim{color:var(--mut);font-size:.8rem}
.void{text-decoration:line-through;color:var(--mut)}

@media (max-width:640px){
  header{gap:.5rem;padding:.6rem .7rem;font-size:.92rem}
  header a{padding:.2rem .45rem}
  header .sp{margin-left:0;width:100%;order:9;font-size:.8rem}
  main{margin:.8rem auto;padding:0 .7rem}
  .card{padding:.8rem;border-radius:8px}
  h1{font-size:1.15rem}
  table{font-size:.84rem}
  th,td{padding:.4rem .35rem}
  /* Full-width tap targets: a 44px-tall control is the usual floor for a
     finger, and these are the two things staff actually press. */
  button{width:100%;padding:.7rem 1rem}
  input,select,textarea{font-size:16px}  /* under 16px iOS zooms on focus */
  /* 收款流水在手机上不缩进、不留最小宽度：4.7rem 的缩进加 26rem 的表，
     在 390px 的屏幕上会把整页顶出一条横向滚动条 —— 这一页从来不该横着滚。 */
  .paylog{margin-left:0}
  .paytab{min-width:0}
  .payacts .backfill{flex-wrap:wrap}
  .payacts .backfill input[name=amount],
  .payacts .backfill input[name=note]{width:auto;flex:1}
}
