/* Layout: phone-first single column (customer side ≤ 440px); the shop side widens to 1080px and the calendar is one column per staff member. */
:root{
  --bg:#f3f2ee; --surface:#ffffff; --surface-2:#eae8e2; --line:#dedbd3; --fg:#1d1b18; --muted:#6c675f; --faint:#a39e95;
  --brand:#3d5a4c; --brand-ink:#ffffff; --accent:var(--brand);
  --ok:#2a7a4b; --warn:#a9640a; --danger:#b3261e; --danger-soft:#fbe9e7;
  --font-body:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Helvetica Neue","Noto Sans SC","Microsoft YaHei",sans-serif;
  --font-display:var(--font-body);   /* phase 17: one font family everywhere (the serif display font is gone, as DESIGN.md says) */
  --radius:14px; --shadow:0 1px 2px rgba(20,15,10,.05),0 10px 28px -14px rgba(20,15,10,.22);
  --demo-h:44px;
}
@media (prefers-color-scheme:dark){ :root:not([data-theme="light"]){
  --bg:#141412; --surface:#1e1d1a; --surface-2:#2a2825; --line:#35332e; --fg:#ece8e1; --muted:#a39d93; --faint:#6e6a63;
  --accent:color-mix(in srgb,var(--brand) 55%,#fff); --danger:#ef7b73; --danger-soft:#3a1f1d; --ok:#6cc08b; --warn:#e2a24a; color-scheme:dark } }
:root[data-theme="dark"]{
  --bg:#141412; --surface:#1e1d1a; --surface-2:#2a2825; --line:#35332e; --fg:#ece8e1; --muted:#a39d93; --faint:#6e6a63;
  --accent:color-mix(in srgb,var(--brand) 55%,#fff); --danger:#ef7b73; --danger-soft:#3a1f1d; --ok:#6cc08b; --warn:#e2a24a; color-scheme:dark }
:root{ --brand-soft:color-mix(in srgb,var(--brand) 10%,var(--surface)); --brand-line:color-mix(in srgb,var(--brand) 35%,var(--line)); }

*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{background:var(--bg);color:var(--fg);font-family:var(--font-body);font-size:15px;line-height:1.45;-webkit-font-smoothing:antialiased;-webkit-tap-highlight-color:transparent}
[hidden]{display:none!important}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer;border:0;background:none;padding:0}
button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
h1,h2,h3{margin:0;font-weight:600;text-wrap:balance}
p{margin:0}
a{color:var(--accent)}
.num{font-variant-numeric:tabular-nums}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* Demo bar */
.demobar{position:sticky;top:env(safe-area-inset-top,0px);z-index:40;height:var(--demo-h);background:#1d1b18;color:#ece8e1;display:flex;align-items:center;gap:8px;padding:0 10px;overflow-x:auto;scrollbar-width:none;border-bottom:1px solid #2e2b27}
:root[data-theme="dark"] .demobar,:root:not([data-theme="light"]) .demobar{background:#0e0d0c}
.demobar::-webkit-scrollbar{display:none}
.demobar .lbl{font-size:11px;letter-spacing:.08em;color:#a39d93;white-space:nowrap;flex:none}
.demobar .lbl b{color:#f4c05a;font-weight:600}
.demobar .pills{display:flex;gap:4px;flex:none;background:#2a2825;padding:3px;border-radius:999px}
.demobar .pill{padding:5px 9px;border-radius:999px;font-size:13px;color:#cfcac2;white-space:nowrap;min-height:28px}
.demobar .pill.on{background:#ece8e1;color:#1d1b18;font-weight:600}
.demobar .sp{flex:1}
.demobar .ib{flex:none;font-size:12px;color:#cfcac2;padding:6px 8px;border-radius:8px;white-space:nowrap;min-height:32px;display:inline-flex;align-items:center;gap:4px}
.demobar .ib:hover{background:#2a2825}

/* Shared */
.wrap{max-width:440px;margin:0 auto;padding:0 16px 48px}
.wrap-wide{max-width:1080px;margin:0 auto;padding:0 16px 48px}
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:48px;padding:0 20px;border-radius:12px;font-weight:600;font-size:16px;background:var(--brand);color:var(--brand-ink);width:100%;transition:filter .15s}
.btn:hover{filter:brightness(1.06)}
.btn:disabled{opacity:.45;cursor:not-allowed}
.btn.sec{background:var(--surface);color:var(--fg);border:1px solid var(--line)}
.btn.ghost{background:transparent;color:var(--accent)}
.btn.danger{background:var(--danger-soft);color:var(--danger)}
.btn.sm{min-height:38px;font-size:14px;padding:0 14px;width:auto;border-radius:10px}
.row{display:flex;align-items:center;gap:10px}
.col{display:flex;flex-direction:column;gap:10px}
.gap8{gap:8px}.gap16{gap:16px}
.muted{color:var(--muted)}.faint{color:var(--faint)}.small{font-size:13px}.xs{font-size:12px}
.eyebrow{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);font-weight:600}
.chip{display:inline-flex;align-items:center;padding:2px 9px;border-radius:999px;font-size:12px;font-weight:600;background:var(--surface-2);color:var(--muted);white-space:nowrap}
.chip.ok{background:color-mix(in srgb,var(--ok) 14%,var(--surface));color:var(--ok)}
.chip.warn{background:color-mix(in srgb,var(--warn) 14%,var(--surface));color:var(--warn)}
.chip.bad{background:var(--danger-soft);color:var(--danger)}
.chip.brand{background:var(--brand-soft);color:var(--accent)}
.field{display:flex;flex-direction:column;gap:6px}
.field label{font-size:13px;font-weight:600;color:var(--muted)}
.input{width:100%;min-height:48px;padding:10px 14px;border:1px solid var(--line);border-radius:12px;background:var(--surface);font-size:16px}
textarea.input{min-height:72px;resize:vertical;line-height:1.4}
.input.err{border-color:var(--danger)}
select.input{appearance:none;background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),linear-gradient(135deg,var(--muted) 50%,transparent 50%);background-position:calc(100% - 20px) 50%,calc(100% - 15px) 50%;background-size:5px 5px;background-repeat:no-repeat;padding-right:36px}
input[type="color"].input{padding:4px;height:48px;width:72px}
.errmsg{color:var(--danger);font-size:13px}
.note{background:var(--brand-soft);border:1px solid var(--brand-line);border-radius:12px;padding:12px 14px;font-size:13px;color:var(--fg)}
.note.warn{background:color-mix(in srgb,var(--warn) 10%,var(--surface));border-color:color-mix(in srgb,var(--warn) 40%,var(--line))}
.hr{height:1px;background:var(--line);margin:4px 0}
.avatar{width:44px;height:44px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-weight:700;color:#fff;background:var(--stc,var(--brand));font-size:16px;flex:none;letter-spacing:.02em}
.avatar.lg{width:64px;height:64px;font-size:22px}
.avatar.sm{width:28px;height:28px;font-size:11px}
.logo{width:48px;height:48px;border-radius:12px;background:var(--brand);color:#fff;display:inline-flex;align-items:center;justify-content:center;font-family:var(--font-display);font-size:20px;flex:none;overflow:hidden}
.logo img{width:100%;height:100%;object-fit:cover}
.logo.lg{width:84px;height:84px;font-size:34px;border-radius:20px}
.empty{color:var(--muted);text-align:center;padding:20px 10px;font-size:14px}
.toast{position:fixed;left:50%;bottom:calc(24px + env(safe-area-inset-bottom,0px));transform:translateX(-50%);background:#1d1b18;color:#ece8e1;padding:10px 16px;border-radius:12px;font-size:14px;z-index:60;max-width:calc(100% - 32px);box-shadow:var(--shadow);opacity:0;transition:opacity .2s;pointer-events:none}
.toast.show{opacity:1}
.toast.bad{background:var(--danger);color:#fff}
.tabs{display:flex;gap:4px;background:var(--surface-2);padding:4px;border-radius:12px;overflow-x:auto;scrollbar-width:none}
.tabs::-webkit-scrollbar{display:none}
.tab{flex:1;min-height:38px;padding:0 8px;border-radius:9px;font-size:14px;font-weight:600;color:var(--muted);white-space:nowrap}
.tab.on{background:var(--surface);color:var(--fg);box-shadow:0 1px 2px rgba(0,0,0,.08)}
.list{display:flex;flex-direction:column}
.list>.item{display:flex;align-items:center;gap:12px;padding:14px 0;border-top:1px solid var(--line);min-height:56px}
.list>.item:first-child{border-top:0}
.item.tap{cursor:pointer}
.item .grow{flex:1;min-width:0}
.item .ttl{font-weight:600}
.item .sub{color:var(--muted);font-size:13px}
.chev{color:var(--faint);flex:none}
.kv{display:grid;grid-template-columns:5.5em 1fr;gap:6px 12px;font-size:14px}
.kv dt{color:var(--muted);margin:0}
.kv dd{margin:0;font-weight:500}
.sec-title{font-family:var(--font-display);font-size:19px;margin:22px 0 10px}
.sec-title.first{margin-top:14px}
.cat-h{font-size:12px;letter-spacing:.1em;color:var(--muted);font-weight:600;margin:18px 0 6px;text-transform:uppercase}
.check{display:flex;align-items:center;gap:10px;min-height:40px;font-size:14px}
.check input{width:20px;height:20px;accent-color:var(--brand);margin:0}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:10px}
@media (min-width:720px){.grid3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;align-items:start}}
details.adv{border:1px solid var(--line);border-radius:12px;padding:0 14px}
details.adv summary{cursor:pointer;padding:12px 0;font-weight:600;color:var(--muted);font-size:14px}
details.adv .col{padding-bottom:14px}
.chips{display:flex;gap:8px;overflow-x:auto;scrollbar-width:none;padding:2px 2px 10px;margin:0 -2px}
.chips::-webkit-scrollbar{display:none}
.chipbtn{flex:none;display:inline-flex;align-items:center;gap:8px;min-height:42px;padding:0 14px 0 6px;border-radius:999px;border:1px solid var(--line);background:var(--surface);font-weight:600;font-size:14px}
.chipbtn.sel{background:var(--brand);color:var(--brand-ink);border-color:var(--brand)}
.chipbtn .avatar{width:30px;height:30px;font-size:11px}
.chipbtn.any{padding-left:14px}
.statusrow{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.statusrow button{min-height:44px;border:1px solid var(--line);border-radius:10px;font-size:13px;font-weight:600;background:var(--surface);color:var(--muted)}
.statusrow button.on{background:var(--fg);color:var(--bg);border-color:var(--fg)}
.statusrow button.on.ns{background:var(--danger);border-color:var(--danger);color:#fff}

/* Date strip + slots */
.strip{display:flex;gap:8px;overflow-x:auto;padding:4px 2px 8px;scrollbar-width:none;margin:0 -2px}
.strip::-webkit-scrollbar{display:none}
.day{flex:none;width:58px;min-height:72px;border-radius:12px;border:1px solid var(--line);background:var(--surface);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;position:relative}
.day .dw{font-size:11px;color:var(--muted)}
.day .dn{font-size:18px;font-weight:700;font-variant-numeric:tabular-nums;line-height:1.1}
.day .dm{font-size:11px;color:var(--muted)}
.day.sel{background:var(--brand);border-color:var(--brand);color:var(--brand-ink)}
.day.sel .dw,.day.sel .dm{color:color-mix(in srgb,var(--brand-ink) 80%,transparent)}
.day.closed{opacity:.45}
.day .cnt{position:absolute;top:-6px;right:-6px;min-width:18px;height:18px;border-radius:9px;background:var(--accent);color:var(--brand-ink);font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;padding:0 5px;border:2px solid var(--bg)}
.day.sel .cnt{background:var(--brand-ink);color:var(--brand)}
.slot-grp{margin-top:12px}
.slot-lbl{font-size:12px;color:var(--muted);margin-bottom:8px;font-weight:600}
.slots{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.slot{min-height:44px;border-radius:10px;border:1px solid var(--line);background:var(--surface);font-weight:600;font-variant-numeric:tabular-nums;font-size:15px}
.slot.sel{background:var(--brand);color:var(--brand-ink);border-color:var(--brand)}

/* Customer */
.c-head{display:flex;align-items:center;gap:12px;padding:18px 0 14px}
.c-head .grow{flex:1;min-width:0}
.shop-name{font-family:var(--font-display);font-size:20px;line-height:1.2}
.shop-sub{font-size:12px;color:var(--muted);margin-top:2px}
.langbtn{border:1px solid var(--line);border-radius:999px;padding:6px 12px;font-size:13px;font-weight:600;min-height:34px;color:var(--muted);flex:none}
.steps{display:flex;align-items:center;gap:0;margin:4px 0 14px}
.steps .s{flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;font-size:11px;color:var(--faint);position:relative}
.steps .s i{width:8px;height:8px;border-radius:50%;background:var(--line);display:block}
.steps .s.done i,.steps .s.on i{background:var(--brand)}
.steps .s.on{color:var(--accent);font-weight:600}
.steps .s.done{color:var(--muted)}
.banner{display:flex;align-items:center;gap:12px;background:var(--brand-soft);border:1px solid var(--brand-line);border-radius:var(--radius);padding:12px 14px;width:100%;text-align:left;margin-bottom:6px}
.banner .grow{flex:1;min-width:0}
.banner b{display:block;font-size:14px}
.banner span{font-size:13px;color:var(--muted)}
.svc{display:flex;align-items:center;gap:12px;padding:14px 0;border-top:1px solid var(--line);cursor:pointer;min-height:64px;text-align:left;width:100%}
.svc:first-child{border-top:0}
.svc .grow{flex:1;min-width:0}
.svc .n{font-weight:600;font-size:16px}
.svc .d{color:var(--muted);font-size:13px;margin-top:2px}
.svc .p{font-weight:700;font-size:16px;font-variant-numeric:tabular-nums;text-align:right;flex:none}
.svc .t{color:var(--muted);font-size:12px;text-align:right;flex:none;display:block;font-weight:400}
.svc .tick{width:24px;height:24px;border-radius:50%;border:1.5px solid var(--line);flex:none;display:flex;align-items:center;justify-content:center;font-size:14px;color:transparent}
.svc.sel .tick{background:var(--brand);border-color:var(--brand);color:var(--brand-ink)}
.svc.sel .n{color:var(--accent)}
.selbar{position:sticky;bottom:0;padding:10px 0 calc(12px + env(safe-area-inset-bottom,0px));background:linear-gradient(to top,var(--bg) 75%,transparent);margin-top:12px}
.selbar .btn{justify-content:space-between;padding:0 18px}
.selbar .btn small{font-weight:500;font-size:13px;opacity:.85}
.summary{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:16px;display:flex;flex-direction:column;gap:12px}
.summary .big{font-family:var(--font-display);font-size:22px;line-height:1.25}
.items{display:flex;flex-direction:column;gap:6px;font-size:14px}
.items div{display:flex;justify-content:space-between;gap:10px}
.items .tot{border-top:1px solid var(--line);padding-top:6px;font-weight:700}
.success{text-align:center;padding:26px 0 10px}
.success .tick{width:64px;height:64px;border-radius:50%;background:color-mix(in srgb,var(--ok) 14%,var(--surface));color:var(--ok);display:inline-flex;align-items:center;justify-content:center;font-size:30px;margin-bottom:12px}
.success h2{font-family:var(--font-display);font-size:24px}
.sms{background:var(--surface-2);border-radius:16px 16px 16px 4px;padding:12px 14px;font-size:14px;line-height:1.5;white-space:pre-wrap;word-break:break-word}
.sms-wrap{display:flex;flex-direction:column;gap:6px}
.sms-wrap .from{font-size:12px;color:var(--muted)}
.bk-status{display:flex;justify-content:space-between;align-items:center}
.sticky-cta{position:sticky;bottom:0;padding:12px 0 calc(12px + env(safe-area-inset-bottom,0px));background:linear-gradient(to top,var(--bg) 70%,transparent);margin-top:12px}

/* Poster */
.poster{background:var(--surface);border:1px solid var(--line);border-radius:20px;padding:36px 24px;text-align:center;box-shadow:var(--shadow);max-width:420px;margin:20px auto 0;display:flex;flex-direction:column;align-items:center;gap:14px}
.poster .name{font-family:var(--font-display);font-size:28px;line-height:1.2}
.poster .nameEn{font-size:14px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
.poster .qr{background:#fff;padding:14px;border-radius:14px;border:1px solid var(--line);display:inline-block}
.poster .qr img,.poster .qr canvas{display:block;width:220px;height:220px;max-width:100%}
.poster .scan{font-size:20px;font-weight:700;margin-top:4px}
.poster .scan small{display:block;font-size:13px;font-weight:500;color:var(--muted);letter-spacing:.08em;margin-top:2px}
.poster .addr{font-size:13px;color:var(--muted)}
.poster .rule{width:40px;height:3px;background:var(--brand);border-radius:2px}

/* Shop */
@media (max-width:560px){.cal-col .ch small{display:none}}
.s-head{display:flex;align-items:center;gap:12px;padding:16px 0 12px}
.s-head .grow{flex:1;min-width:0}
.s-head .tt{font-family:var(--font-display);font-size:19px}
.toolbar{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:14px 0 8px}
.toolbar h2{font-family:var(--font-display);font-size:18px}
.toolbar .row{gap:6px}
.cal{display:flex;border:1px solid var(--line);border-radius:12px;overflow:hidden;background:var(--surface);margin-top:8px}
.cal-gutter{width:44px;flex:none;border-right:1px solid var(--line);position:relative;background:var(--surface)}
.cal-gutter .gh{height:48px;border-bottom:1px solid var(--line)}
.cal-gutter .hl{position:absolute;left:0;right:6px;text-align:right;font-size:11px;color:var(--muted);transform:translateY(-7px);font-variant-numeric:tabular-nums}
.cal-cols{display:flex;flex:1;min-width:0;overflow-x:auto}
.cal-col{flex:1 1 0;min-width:94px;border-right:1px solid var(--line)}
.cal-col:last-child{border-right:0}
.cal-col .ch{height:48px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:6px;padding:0 8px;font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden}
.cal-col .ch small{font-weight:400;color:var(--muted);font-size:11px}
.cal-body{position:relative;background:repeating-linear-gradient(to bottom,var(--line) 0 1px,transparent 1px 64px);cursor:copy}
.cal-off{position:absolute;left:0;right:0;background:repeating-linear-gradient(135deg,var(--surface-2) 0 6px,color-mix(in srgb,var(--surface-2) 60%,var(--surface)) 6px 12px);cursor:default}
.cal-break{position:absolute;left:0;right:0;background:repeating-linear-gradient(135deg,transparent 0 5px,color-mix(in srgb,var(--line) 70%,transparent) 5px 6px)}
.cal-block{position:absolute;left:3px;right:3px;border-radius:7px;background:repeating-linear-gradient(135deg,var(--surface-2) 0 6px,var(--line) 6px 8px);border:1px dashed var(--faint);font-size:11px;color:var(--muted);padding:4px 6px;text-align:left;overflow:hidden;cursor:pointer}
.cal-block b{display:block;color:var(--fg)}
.cal-bk{position:absolute;left:3px;right:3px;border-radius:7px;padding:3px 6px;font-size:11px;line-height:1.25;overflow:hidden;border-left:3px solid var(--stc);background:color-mix(in srgb,var(--stc) 18%,var(--surface));cursor:pointer;text-align:left;color:var(--fg);box-shadow:0 0 0 1px var(--surface)}
.cal-bk.nested{left:38%;box-shadow:0 2px 8px rgba(0,0,0,.18)}
.cal-bk>b,.cal-bk>span,.cal-bk>.st{position:relative;z-index:1}
.cal-bk>b,.cal-bk>span:not(.st){white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}
.cal-bk b{display:block;font-size:11.5px}
.cal-bk .t{color:var(--muted);font-variant-numeric:tabular-nums}
.cal-bk .st{position:absolute;top:3px;right:5px;font-size:11px;font-weight:700}
.cal-bk.completed{opacity:.6}
.cal-bk.noshow{background:var(--danger-soft);border-left-color:var(--danger);text-decoration:line-through;color:var(--muted)}
.cal-bk.noshow .st{color:var(--danger)}

.cal-proc{position:absolute;left:0;right:0;background:repeating-linear-gradient(135deg,transparent 0 4px,color-mix(in srgb,var(--surface) 70%,transparent) 4px 8px);border-top:1px dashed var(--stc);border-bottom:1px dashed var(--stc);opacity:.9;pointer-events:none}
.cal-now{position:absolute;left:0;right:0;height:2px;background:var(--danger);z-index:2;pointer-events:none}
.cal-now::before{content:"";position:absolute;left:-1px;top:-3px;width:8px;height:8px;border-radius:50%;background:var(--danger)}
.legend{display:flex;gap:12px;flex-wrap:wrap;font-size:12px;color:var(--muted);margin-top:8px}
.legend i{display:inline-block;width:14px;height:10px;border-radius:3px;vertical-align:-1px;margin-right:4px}
.msg{padding:14px 0;border-top:1px solid var(--line)}
.msg:first-child{border-top:0}
.msg .hd{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12px;color:var(--muted);margin-bottom:8px}
.msg .body{background:var(--surface-2);border-radius:12px;padding:10px 12px;font-size:13px;white-space:pre-wrap;word-break:break-word;line-height:1.5}
.msg .body+.body{margin-top:6px}
.hours-row{display:grid;grid-template-columns:3.2em 1fr;gap:6px 10px;align-items:center;font-size:14px;padding:6px 0;border-top:1px solid var(--line)}
.hours-row:first-child{border-top:0}
.hours-row .off{color:var(--faint)}
.hours-edit{display:grid;grid-template-columns:auto auto 1fr auto 1fr;gap:6px;align-items:center;padding:8px 0;border-top:1px solid var(--line);font-size:13px}
.hours-edit .check{white-space:nowrap;gap:6px}
.hours-edit select.input{min-height:40px;padding:6px 26px 6px 8px;font-size:14px;border-radius:8px}
.hours-edit .brk{grid-column:2/-1;display:grid;grid-template-columns:auto 1fr auto 1fr;gap:6px;align-items:center;color:var(--muted)}
.tagrow{display:flex;flex-wrap:wrap;gap:6px}
.tag{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:999px;background:var(--surface-2);font-size:13px}
.tag button{font-size:14px;color:var(--muted);line-height:1}
.filters{display:flex;gap:6px;overflow-x:auto;scrollbar-width:none;padding-bottom:4px}
.filters::-webkit-scrollbar{display:none}
.fchip{flex:none;padding:6px 12px;border-radius:999px;border:1px solid var(--line);font-size:13px;color:var(--muted);min-height:34px;background:var(--surface)}
.fchip.on{background:var(--fg);color:var(--bg);border-color:var(--fg)}
.staff-pick{display:grid;gap:12px}
.staffcard{display:flex;align-items:center;gap:14px;padding:14px;border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);width:100%;text-align:left;min-height:72px}
.staffcard .n{font-weight:600;font-size:16px}
.staffcard .r{color:var(--muted);font-size:13px}
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.stats div{background:var(--surface-2);border-radius:10px;padding:8px 6px;text-align:center}
.stats b{display:block;font-size:18px;font-variant-numeric:tabular-nums}
.stats span{font-size:11px;color:var(--muted)}
.clientnote{background:color-mix(in srgb,var(--warn) 9%,var(--surface));border:1px solid color-mix(in srgb,var(--warn) 35%,var(--line));border-radius:12px;padding:10px 12px;font-size:13px;display:flex;flex-direction:column;gap:4px}
.clientnote b{font-size:12px;color:var(--warn)}

/* Sheet / dialog */
.sheet-wrap{position:fixed;inset:0;z-index:50;display:flex;align-items:flex-end;justify-content:center}
.sheet-bg{position:absolute;inset:0;background:rgba(10,8,6,.45)}
.sheet{position:relative;background:var(--surface);width:100%;max-width:560px;max-height:calc(100% - var(--demo-h) - 12px);border-radius:20px 20px 0 0;display:flex;flex-direction:column;box-shadow:0 -10px 40px rgba(0,0,0,.25);animation:up .2s ease-out}
@keyframes up{from{transform:translateY(24px);opacity:.6}to{transform:none;opacity:1}}
.sheet-handle{width:40px;height:4px;border-radius:2px;background:var(--line);margin:10px auto 0;flex:none}
.sheet-body{overflow-y:auto;padding:12px 18px calc(20px + env(safe-area-inset-bottom,0px));display:flex;flex-direction:column;gap:14px}
.sheet-body>*{flex:none}
.sheet-body h3{font-family:var(--font-display);font-size:19px}
.sheet-x{position:absolute;right:8px;top:6px;width:44px;height:44px;border-radius:50%;background:var(--surface-2);color:var(--muted);font-size:16px;display:flex;align-items:center;justify-content:center}
@media (min-width:720px){.sheet-wrap{align-items:center;padding:20px}.sheet{border-radius:20px;max-height:calc(100% - 40px)}}
.dlg-wrap{position:fixed;inset:0;z-index:55;display:flex;align-items:center;justify-content:center;padding:20px}
.dlg{position:relative;background:var(--surface);border-radius:18px;padding:22px 20px 18px;max-width:360px;width:100%;box-shadow:var(--shadow);display:flex;flex-direction:column;gap:12px}
.dlg h3{font-size:18px}
.dlg .acts{display:flex;gap:10px;margin-top:6px}
.dlg .acts .btn{flex:1}

/* ===== v3: desktop shop layout, week view, tiles, drag, avatars, poster, script panel, pricing ===== */
.avatar svg{width:100%;height:100%;display:block;border-radius:50%}
.avatar.img{background:transparent;overflow:hidden;padding:0}
.tiles{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin:10px 0 4px}
.tiles div{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:10px 12px}
.tiles b{display:block;font-size:20px;font-variant-numeric:tabular-nums;line-height:1.2}
.tiles span{font-size:12px;color:var(--muted)}
.tiles small{font-size:11px;color:var(--ok);font-weight:600}
.viewtog{display:inline-flex;background:var(--surface-2);padding:3px;border-radius:9px;gap:2px}
.viewtog button{padding:5px 12px;border-radius:7px;font-size:13px;font-weight:600;color:var(--muted);min-height:32px}
.viewtog button.on{background:var(--surface);color:var(--fg);box-shadow:0 1px 2px rgba(0,0,0,.08)}
.shop{display:block}
.sidenav{display:none}
.wk-col{flex:1 1 0;min-width:120px;border-right:1px solid var(--line);position:relative}
.wk-col:last-child{border-right:0}
.wk-col .ch{height:48px;border-bottom:1px solid var(--line);display:flex;flex-direction:column;align-items:center;justify-content:center;font-size:12px;font-weight:600;cursor:pointer;line-height:1.15}
.wk-col .ch small{font-weight:400;color:var(--muted);font-size:11px}
.wk-col .ch.today{color:var(--accent)}
.wk-col .ch.closed{color:var(--faint)}
.wk-bk{position:absolute;border-radius:5px;border-left:3px solid var(--stc);background:color-mix(in srgb,var(--stc) 22%,var(--surface));font-size:10px;line-height:1.2;padding:2px 3px;overflow:hidden;cursor:pointer;text-align:left;color:var(--fg);box-shadow:0 0 0 1px var(--surface)}
.wk-bk b{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wk-bk.noshow{text-decoration:line-through;opacity:.6}
.wk-bk.completed{opacity:.6}
.wk-blk{position:absolute;border-radius:5px;background:repeating-linear-gradient(135deg,var(--surface-2) 0 5px,var(--line) 5px 7px);border:1px dashed var(--faint);font-size:10px;color:var(--muted);padding:2px 3px;overflow:hidden}
.script-fab{position:fixed;right:14px;bottom:calc(14px + env(safe-area-inset-bottom,0px));z-index:45;background:#1d1b18;color:#f4c05a;border:1px solid #3a362f;border-radius:999px;min-height:40px;padding:0 14px;font-size:13px;font-weight:700;box-shadow:var(--shadow);display:inline-flex;align-items:center;gap:6px}
.script{position:fixed;right:14px;bottom:calc(62px + env(safe-area-inset-bottom,0px));z-index:46;width:min(360px,calc(100% - 28px));background:#1d1b18;color:#ece8e1;border:1px solid #3a362f;border-radius:16px;padding:14px;box-shadow:0 20px 50px rgba(0,0,0,.4);display:flex;flex-direction:column;gap:8px;font-size:13px}
.script h4{margin:0;font-size:13px;color:#f4c05a;letter-spacing:.06em}
.script .step{display:flex;align-items:center;gap:8px;padding:6px 0;border-top:1px solid #2e2b27}
.script .step span{flex:1;min-width:0}
.script .step i{font-style:normal;width:20px;height:20px;border-radius:50%;background:#2a2825;display:inline-flex;align-items:center;justify-content:center;font-size:11px;color:#a39d93;flex:none}
.script .step button{background:#2a2825;color:#ece8e1;border-radius:8px;padding:5px 10px;font-size:12px;min-height:30px;white-space:nowrap}
.script .step button:hover{background:#3a362f}
.script .foot{display:flex;gap:6px;margin-top:4px}
.script .foot button{flex:1;background:#f4c05a;color:#1d1b18;border-radius:8px;min-height:34px;font-weight:700;font-size:12px}
.script .foot button.sec{background:#2a2825;color:#ece8e1}
.demobar .ib.on{background:#f4c05a;color:#1d1b18;font-weight:700}
.poster-a4{background:#fff;color:#1d1b18;width:100%;max-width:420px;aspect-ratio:210/297;margin:16px auto 0;border:1px solid var(--line);box-shadow:var(--shadow);display:flex;flex-direction:column;align-items:center;justify-content:space-between;padding:7% 8%;text-align:center}
.poster-a4 .band{width:100%;height:10px;background:var(--brand);border-radius:6px}
.poster-a4 .name{font-family:var(--font-display);font-size:clamp(22px,7vw,34px);line-height:1.15;margin-top:8px}
.poster-a4 .nameEn{font-size:12px;letter-spacing:.2em;text-transform:uppercase;color:#6c675f;margin-top:4px}
.poster-a4 .qr{padding:10px;border:2px solid var(--brand);border-radius:14px;display:inline-block}
.poster-a4 .qr img,.poster-a4 .qr canvas{display:block;width:min(240px,52vw);height:auto;max-width:100%}
.poster-a4 .scan{font-size:clamp(20px,6vw,30px);font-weight:800;color:var(--brand);letter-spacing:.04em}
.poster-a4 .scan small{display:block;font-size:12px;letter-spacing:.2em;color:#6c675f;font-weight:600;margin-top:2px}
.poster-a4 .hours{font-size:11px;color:#1d1b18;display:grid;grid-template-columns:1fr 1fr;gap:2px 16px;text-align:left;width:100%}
.poster-a4 .addr{font-size:11px;color:#6c675f}
.swatches{display:flex;gap:8px;flex-wrap:wrap}
.swatch{display:inline-flex;align-items:center;gap:6px;padding:6px 10px 6px 6px;border-radius:999px;border:1px solid var(--line);background:var(--surface);font-size:13px;min-height:36px}
.swatch i{width:22px;height:22px;border-radius:50%;display:inline-block}
.swatch.on{border-color:var(--fg);box-shadow:0 0 0 1px var(--fg)}
.price-hero{background:var(--brand);color:var(--brand-ink);border-radius:20px;padding:22px 20px;display:flex;flex-direction:column;gap:6px}
.price-hero .big{font-family:var(--font-display);font-size:38px;line-height:1;font-variant-numeric:tabular-nums}
.price-hero .big small{font-size:14px;font-family:var(--font-body);opacity:.85}
.price-hero .vs{font-size:13px;opacity:.9}
.compare{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.compare .col-c{background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:14px;display:flex;flex-direction:column;gap:8px}
.compare h4{margin:0;font-size:13px;color:var(--muted);letter-spacing:.06em;text-transform:uppercase}
.compare .amt{font-size:24px;font-weight:700;font-variant-numeric:tabular-nums}
.compare ul{margin:0;padding-left:18px;font-size:13px;color:var(--muted);display:flex;flex-direction:column;gap:4px}
.compare .col-c.ours{border-color:var(--brand-line);background:var(--brand-soft)}
.compare .col-c.ours .amt{color:var(--accent)}
.plan{display:flex;flex-direction:column;gap:6px;padding:14px;border:1px solid var(--line);border-radius:14px;background:var(--surface)}
.plan.rec{border-color:var(--brand);box-shadow:0 0 0 2px var(--brand-soft)}
.plan .pn{font-weight:700;display:flex;justify-content:space-between;align-items:baseline}
.plan .pn b{font-size:22px;font-variant-numeric:tabular-nums}
.plan .pn b small{font-size:12px;color:var(--muted);font-weight:500}
.plan ul{margin:0;padding-left:18px;font-size:13px;color:var(--muted);display:flex;flex-direction:column;gap:3px}
@media (min-width:720px){.tiles{grid-template-columns:repeat(4,1fr)}.compare{grid-template-columns:1fr 1fr}}
@media (min-width:900px){
  .shop{display:grid;grid-template-columns:200px minmax(0,1fr);gap:28px;align-items:start}
  .sidenav{display:flex;flex-direction:column;gap:4px;position:sticky;top:calc(var(--demo-h) + 16px)}
  .sidenav .brand{display:flex;align-items:center;gap:10px;padding:8px 6px 14px}
  .sidenav .brand .tt{font-family:var(--font-display);font-size:17px;line-height:1.2}
  .sidenav button.nav{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;font-size:14px;font-weight:600;color:var(--muted);text-align:left;width:100%}
  .sidenav button.nav.on{background:var(--surface);color:var(--fg);box-shadow:0 1px 2px rgba(0,0,0,.06)}
  .sidenav button.nav:hover{color:var(--fg)}
  .sidenav .mini{font-size:11px;color:var(--faint);padding:14px 12px 0}
  .shop>.content>.s-head,.shop>.content>.tabs{display:none}
  .wrap-wide{padding-top:16px}
  .sheet-wrap{justify-content:flex-end;align-items:stretch;padding:0}
  .sheet{max-width:460px;border-radius:0;max-height:none;height:100%;animation:slide .2s ease-out}
  @keyframes slide{from{transform:translateX(30px);opacity:.6}to{transform:none;opacity:1}}
  .sheet-handle{display:none}
  .sheet-body{padding-top:48px}
  .cal-col{min-width:120px}
}
@media print{.demobar,.script-fab,.script,.poster-tools,.poster-note{display:none!important}body{background:#fff}.poster-a4{box-shadow:none;border:0;max-width:none;width:100%;height:100vh;margin:0}}

/* ===== v4: sign-in, 安全 tab, step-up, PIN pad ===== */
.login{padding:18px 16px;margin-top:8px}
.login h2{font-family:var(--font-display);font-size:22px}
.code-input{font-size:24px;letter-spacing:.35em;text-align:center;font-variant-numeric:tabular-nums}
.who{display:inline-flex;align-items:center;gap:6px;flex:none}
.sidenav-lang{margin:2px 0 10px}  /* phase 15: the wide layout has no top bar, so its 中 / EN pill sits under the shop name */
.banner.warn{background:color-mix(in srgb,var(--warn) 10%,var(--surface));border-color:color-mix(in srgb,var(--warn) 40%,var(--line))}
.banner.warn b{color:var(--warn)}
.pw-meter{display:flex;align-items:center;gap:8px;min-height:18px}
.pw-meter i{display:block;height:6px;width:72px;border-radius:3px;background:var(--surface-2);position:relative;overflow:hidden;flex:none}
.pw-meter i::after{content:"";position:absolute;inset:0;width:0;background:var(--danger);transition:width .2s}
.pw-meter.l1 i::after{width:25%}.pw-meter.l2 i::after{width:50%;background:var(--warn)}.pw-meter.l3 i::after{width:75%;background:var(--ok)}.pw-meter.l4 i::after{width:100%;background:var(--ok)}
.codes{display:grid;grid-template-columns:1fr 1fr;gap:8px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:15px;letter-spacing:.06em;user-select:all}
.codes div{background:var(--surface-2);border-radius:10px;padding:10px;text-align:center}
.qr.otp{display:inline-block;background:#fff;padding:10px;border-radius:12px;border:1px solid var(--line);margin:10px 0 6px}
.qr.otp img,.qr.otp canvas{display:block;width:200px;height:200px;max-width:100%}
code.secret{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:14px;letter-spacing:.08em;user-select:all;word-break:break-all;color:var(--fg)}
.pinpad{display:flex;flex-direction:column;align-items:center;gap:8px;padding:22px 18px;margin-top:10px;text-align:center}
.pinpad .n{font-family:var(--font-display);font-size:22px;margin-top:4px}
.pinpad .dots{display:flex;gap:14px;margin:12px 0 4px}
.pinpad .dots i{width:16px;height:16px;border-radius:50%;border:2px solid var(--line);display:block}
.pinpad .dots i.on{background:var(--brand);border-color:var(--brand)}
.pinpad .dots.shake{animation:shake .3s}
@keyframes shake{0%,100%{transform:none}25%{transform:translateX(-6px)}75%{transform:translateX(6px)}}
.pinpad .keys{display:grid;grid-template-columns:repeat(3,76px);gap:10px;margin-top:10px}
.pinpad .keys button{height:64px;border-radius:50%;background:var(--surface-2);font-size:24px;font-weight:600;font-variant-numeric:tabular-nums}
.pinpad .keys button.txt{background:transparent;font-size:15px;color:var(--muted)}
.pinpad .keys button:disabled{opacity:.4}
.script .viewtog.dark{background:#2a2825;min-width:0;flex:0 1 auto;flex-wrap:wrap;justify-content:flex-end}
.script h4{white-space:nowrap;flex:none}
.script>.row{min-width:0;max-width:100%}
.script .viewtog.dark button{white-space:nowrap;flex:none} /* five script tabs at 375 px: whole pills wrap onto a second row, labels never break mid-word */
.script .viewtog.dark button{color:#a39d93;min-height:26px;padding:3px 9px;font-size:11px}
.script .viewtog.dark button.on{background:#f4c05a;color:#1d1b18;box-shadow:none}
.script .creds{background:#2a2825;border-radius:10px;padding:10px;font-size:12px;display:flex;flex-direction:column;gap:6px;line-height:1.5}
.script .creds code{background:#1d1b18;color:#f4c05a;border-radius:5px;padding:1px 5px;font-size:12px;user-select:all}
@media (min-width:900px){.who .muted{display:none}}

/* ===== v5: packages and follow-up ===== */
:root{--on-danger:#fff}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--on-danger:#1d1b18}}
:root[data-theme="dark"]{--on-danger:#1d1b18}
.badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;margin-left:5px;border-radius:999px;background:var(--danger);color:var(--on-danger);font-size:11px;font-weight:700;line-height:1;vertical-align:1px}
.tiles .hot b{color:var(--danger)}
.fu-banner{display:flex;align-items:center;gap:12px;width:100%;text-align:left;margin:4px 0 6px;padding:12px 14px;border-radius:12px;background:color-mix(in srgb,var(--warn) 10%,var(--surface));border:1px solid color-mix(in srgb,var(--warn) 40%,var(--line));color:var(--fg);min-height:56px}
.fu-banner .ic{font-size:20px;flex:none}
.fu-banner .grow{flex:1;min-width:0}
.fu-sec{display:flex;align-items:center;gap:8px;font-family:var(--font-display);font-size:17px;margin:20px 0 8px}
.fu-sec .n{font-family:var(--font-body);font-size:12px;font-weight:700;color:var(--muted);background:var(--surface-2);border-radius:999px;padding:1px 8px}
.fu-row{align-items:flex-start}
.fu-row .avatar{margin-top:2px}
.fu-row .ttl{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.fu-row .why{font-size:13px;margin-top:2px}
.fu-row .st{font-size:12px;color:var(--muted);margin-top:2px}
.fu-row .acts{flex:none;align-self:center}
.fu-row .acts .btn{white-space:nowrap}
details.fu-more{background:var(--surface)}
details.fu-more .list{padding-bottom:4px}
.pbar{height:6px;border-radius:999px;background:var(--surface-2);overflow:hidden;margin:6px 0 4px}
.pbar i{display:block;height:100%;background:var(--brand);border-radius:999px}
.script-box{background:var(--surface-2);border-radius:12px;padding:12px 14px;font-size:14px;line-height:1.6}
.fu-results{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.fu-results .btn{font-size:14px;min-height:52px;padding:6px 10px;line-height:1.3}
a.btn{text-decoration:none}
.fu-row .sub .num{white-space:nowrap}

/* phase 01: rooms, add-ons, client notes */
.cal-col .ch .rm-ic{font-size:14px}
.cal-body.room{cursor:default}
.room-row{display:grid;grid-template-columns:1.2fr 1fr auto auto;gap:6px;align-items:center;padding:6px 0;border-top:1px solid var(--line)}
.room-row .input{min-height:40px;padding:6px 10px;font-size:14px;border-radius:8px}
.patch-add{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:8px}
.patch-add .input{min-height:40px;padding:6px 10px;font-size:14px;border-radius:8px}
.patch-add .btn{grid-column:1/-1}
@media (min-width:720px){.patch-add{grid-template-columns:auto 1fr auto 1fr auto}.patch-add .btn{grid-column:auto}}
.banner.note-next{margin:0;cursor:default}
.banner.note-next .ic{font-size:20px;flex:none}
.svc .cut{display:inline-block;margin-top:3px;font-size:11px;color:var(--warn);font-weight:600}
.card.addons .svc .n{font-size:15px}
.toolbar{flex-wrap:wrap}
.toolbar .viewtog button,.toolbar .btn{white-space:nowrap}

/* phase 15: the 中 / EN pill, always in the header (shop, staff, customer, sign-in) */
.langpill{display:inline-flex;align-items:center;flex:none;min-height:36px;padding:0 4px;border:1px solid var(--line);border-radius:999px;background:var(--card);color:var(--muted);font-size:13px;font-weight:600;line-height:1;cursor:pointer;gap:0}
.langpill span{padding:6px 8px;border-radius:999px}
.langpill span.on{background:var(--brand);color:#fff}
.langpill:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
/* phase 15: the header at phone width with the pill in it — the title keeps its line, who-is-signed-in hides, the buttons shrink */
.s-head .tt{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.s-head .grow .small{white-space:nowrap}
@media (max-width:640px){.who .muted{display:none}.who .btn.ghost.sm{padding:0 8px}.langpill{min-height:32px}.langpill span{padding:5px 7px}}

/* ---------- phase 23 (b): Plan & billing (ui-x-billing.js) ---------- */
/* the bar under the shell's top header: one line, its button at the end; wraps on a narrow phone instead of clipping */
.bill-bar{display:flex;align-items:center;flex-wrap:wrap;gap:8px 12px;margin:8px 0 10px;padding:9px 12px 9px 14px;border-radius:12px;font-size:14px;font-weight:600;
  border:1px solid color-mix(in srgb,var(--warn) 40%,var(--line));background:color-mix(in srgb,var(--warn) 10%,var(--surface));color:var(--fg)}
.bill-bar .grow{flex:1 1 auto;min-width:0}
.bill-bar .btn{flex:none;min-height:36px}
.bill-bar.bad{border-color:color-mix(in srgb,var(--danger) 45%,var(--line));background:var(--danger-soft);color:var(--danger)}
.bill-bar.bad .btn{background:var(--danger);color:var(--on-danger,#fff)}
@media (min-width:768px){.bill-bar{margin-top:0}}

/* the Plan card */
.bill-eyebrow{margin:2px 0 6px}
.bill-head .grow{font-size:15px}
.bill-head .chip{margin-left:auto}
.bill-acts{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.bill-acts .btn{flex:1 1 160px;min-height:46px}
@media (min-width:768px){.bill-acts .btn{flex:0 0 auto;min-width:180px}}

/* the Choose plan sheet */
.bill-iv{display:flex;width:100%;margin:4px 0 14px}
.bill-iv button{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:40px}
.bill-price{display:flex;align-items:baseline;gap:10px;margin:0 0 10px}
.bill-price b{font-size:28px;font-family:var(--font-display)}
.bill-setup{border-bottom:0;padding:14px 0 6px}
.bill-consent{align-items:flex-start;padding:10px 0 14px;line-height:1.4}
.bill-consent input{flex:none;margin-top:1px}
.bill-pay{width:100%;min-height:52px}

/* the booking page of a paused shop */
.bill-closed{display:flex;flex-direction:column;align-items:center;gap:14px;padding:28px 18px;text-align:center;font-size:17px}
.bill-closed .btn{min-width:220px}

/* ---------- phase 23 (C): select rows and act on them (ui-x-bulk.js), for Clients and Services ----------
   The box is the app's checkbox (ui-x-menu.css A5: 22 px, 6 px corners, the brand fill and a white tick) drawn on a button with
   role=checkbox, inside a 44 px target. On a computer it shows on a row's hover and on every row once one is ticked; on a phone
   only after Select. The bar floats at the bottom of the list's column (ui-x-bulk.js places it), above a phone's tab bar. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.bk-box{flex:none;display:inline-grid;place-items:center;width:44px;height:44px;min-height:0;margin:0;padding:0;border:0;background:none;cursor:pointer;-webkit-tap-highlight-color:transparent}
.bk-box::before{content:"";width:22px;height:22px;box-sizing:border-box;border-radius:6px;border:2px solid var(--muted);background:var(--surface);display:block}
.bk-box[aria-checked="true"]::before,.bk-box[aria-checked="mixed"]::before{background:var(--brand);border-color:var(--brand)}
.bk-box::after{content:"";position:absolute;width:6px;height:11px;border:solid var(--brand-ink);border-width:0 2.5px 2.5px 0;transform:translateY(-1px) rotate(45deg);opacity:0}
.bk-box{position:relative}
.bk-box[aria-checked="true"]::after{opacity:1}
.bk-box[aria-checked="mixed"]::after{width:10px;height:0;border-width:0 0 2.5px 0;transform:none;opacity:1}
.bk-box:focus-visible{outline:2px solid var(--accent);outline-offset:-4px;border-radius:10px}
/* where the boxes show: always on a group or a header; on a row, on hover (a mouse) or once one is ticked, or in a phone's Select */
/* a mouse: faded out until the row is hovered (still there for the Tab key, and shown when it has focus) */
@media (hover:hover) and (pointer:fine) and (min-width:760px){
  .bk-row .bk-box,.bk-hov{opacity:0;transition:opacity .1s}
  .bk-row:hover .bk-box,.bk-row .bk-box:focus-visible,.bk-any .bk-row .bk-box,body.bk-on .bk-row .bk-box,.bk-hov:hover,.bk-hov:focus-visible,.bk-any .bk-hov,body.bk-on .bk-hov{opacity:1}
}
.bk-row.bk-sel{background:var(--brand-soft)}
.bk-mode{display:none}
/* a touch screen (a phone, an iPad): no hover, so the boxes come with Select */
@media (hover:none),(pointer:coarse),(max-width:759px){
  .bk-mode{display:inline-flex}
  .bk-row .bk-box,.bk-hov,.bk-touchsel{display:none}
  body.bk-on .bk-row .bk-box,.bk-any .bk-row .bk-box,body.bk-on .bk-hov,.bk-any .bk-hov,body.bk-on .bk-touchsel{display:inline-grid}
}
/* "All 80 on screen selected · Select all 10,517" */
.bk-banner{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:4px 10px;margin:8px 0 0;padding:8px 12px;border-radius:12px;background:var(--brand-soft);font-size:14px;font-weight:600;text-align:center}
.bk-banner[hidden]{display:none}
.bk-banner .lnk,.bk-toast .bk-undo{background:none;border:0;padding:0 4px;min-height:36px;font:inherit;font-weight:700;color:var(--accent);cursor:pointer}
/* the bar */
.bk-bar{position:fixed;z-index:40;display:flex;align-items:center;gap:8px;padding:8px 8px 8px 16px;border-radius:16px;background:var(--surface);border:1px solid var(--line);box-shadow:0 10px 30px rgba(16,19,24,.18)}
.bk-bar[hidden]{display:none}
.bk-cnt{white-space:nowrap;font-size:15px}
.bk-acts{display:flex;align-items:center;gap:6px;margin-left:auto;overflow-x:auto;scrollbar-width:none;min-width:0}
.bk-acts::-webkit-scrollbar{display:none}
.bk-acts .btn{flex:none;white-space:nowrap;min-height:40px}
.bk-acts .btn .n{font-weight:500;opacity:.75;margin-left:4px}
.bk-acts .btn.danger{background:var(--danger-soft);color:var(--danger)}
.bk-x{flex:none;width:44px;height:44px;border:0;border-radius:12px;background:none;color:var(--muted);font-size:18px;cursor:pointer}
.bk-x:hover{background:var(--surface-2)}
/* (the page's bottom padding is the bar's own height: ui-x-bulk.js bkPlace) */
@media (max-width:640px){
  /* a phone: the count and ✕ on top, every action below, wrapping rather than hidden off the edge */
  .bk-bar{flex-wrap:wrap;padding:8px 6px 8px 14px;row-gap:6px}
  .bk-cnt{order:1;flex:1 1 auto}
  .bk-x{order:2}
  .bk-acts{order:3;flex:1 0 100%;margin-left:0;flex-wrap:wrap;overflow:visible}
  .bk-acts .btn{flex:1 1 auto}
}
/* Undo, above the bar */
.bk-toast{position:fixed;left:50%;transform:translateX(-50%);bottom:24px;z-index:61;display:flex;align-items:center;gap:10px;max-width:calc(100% - 32px);padding:6px 8px 6px 16px;border-radius:12px;background:#1d1b18;color:#ece8e1;font-size:14px;box-shadow:var(--shadow)}
.bk-toast[hidden]{display:none}
.bk-toast .bk-undo{color:#f4c05a}
/* a count on a filter chip: plain, not the red badge (a count is not an alarm) */
.chipbtn .bk-n{font-weight:600;color:var(--muted);font-variant-numeric:tabular-nums}
.chipbtn.sel .bk-n{color:inherit;opacity:.8}
/* the drag grip (Quotebot .dg): a button, so it takes focus and the arrow keys; never moves the page on a phone (touch-action) */
.bk-grip{flex:none;display:grid;place-items:center;width:32px;min-height:44px;padding:0;border:0;background:none;color:var(--muted);cursor:grab;touch-action:none;font-size:16px;letter-spacing:-2px}
.bk-grip:hover{color:var(--fg)}
.bk-dglist{position:relative;isolation:isolate}
.bk-dr.dragging{position:relative;z-index:5;cursor:grabbing;background:var(--surface);box-shadow:0 8px 24px rgba(20,24,31,.16),0 0 0 1px var(--line)}
.dragging-list .bk-dr:not(.dragging){transition:transform .14s ease}
@media (prefers-reduced-motion:reduce){.dragging-list .bk-dr{transition:none!important}}
/* a menu under a chip (Tags ▾): placed by its list, over the page */
.bk-pop{position:fixed;z-index:35;top:calc(100% + 6px);right:0;min-width:200px;max-width:min(320px,calc(100vw - 32px));max-height:min(60vh,420px);overflow:auto;padding:6px;border-radius:14px;background:var(--surface);border:1px solid var(--line);box-shadow:0 12px 32px rgba(16,19,24,.18)}
.bk-pop button{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:0 12px;border:0;border-radius:10px;background:none;color:var(--fg);font:inherit;font-size:15px;text-align:left;cursor:pointer}
.bk-pop button:hover,.bk-pop button.on{background:var(--surface-2)}
.bk-pop button .bk-n{margin-left:auto;color:var(--muted);font-variant-numeric:tabular-nums}

/* ---------- phase 24, Part C: a calendar you can trust ----------
   The five status colours (DESIGN.md's status tokens: light / dark), the blocked-after tail, the colour toggle's legend,
   the no-show tile, 再约一次, the policy row. */
:root{--c24-ok:#1b6f3f;--c24-wait:#8f5300;--c24-call:#b3261e;--c24-done:#64605a;--c24-cancel:#64605a}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]){--c24-ok:#6cc08b;--c24-wait:#e2a24a;--c24-call:#ef7b73;--c24-done:#a39d93;--c24-cancel:#a39d93}}
:root[data-theme=dark]{--c24-ok:#6cc08b;--c24-wait:#e2a24a;--c24-call:#ef7b73;--c24-done:#a39d93;--c24-cancel:#a39d93}

/* blocked after: a denser hatch than a processing gap, no dashed rails (the client is gone; the room is being reset) */
.cal-bk .cal-tail{position:absolute;left:0;right:0;pointer-events:auto;background:repeating-linear-gradient(135deg,transparent 0 3px,color-mix(in srgb,var(--stc) 45%,transparent) 3px 5px);border-top:1px solid color-mix(in srgb,var(--stc) 60%,transparent);opacity:.9}
.cal-bk .cal-tail::before{content:"";position:absolute;inset:0;background:color-mix(in srgb,var(--surface) 55%,transparent)}

/* the ⋯ menu's colour toggle and legend */
.c24-color{margin-bottom:6px}
.c24-legend .c24-sw{flex:none;width:18px;height:14px;border-radius:4px;border-left:3px solid var(--stc);background:color-mix(in srgb,var(--stc) 22%,var(--surface));box-shadow:0 0 0 1px var(--line)}

/* 再约一次 on a history row (a 44 px target on a phone) and on the done screen */
.cc-visits .c24-again{flex:none;margin-left:6px;min-height:36px;padding:0 10px;white-space:nowrap}
@media (max-width:600px){.cc-visits .c24-again{min-height:44px}}
.c24-again-done{align-self:stretch}

/* the policy row on the booking card; the line in the late-cancel sheet */
.c24-pol{color:var(--ok)}
.c24-pol-line{display:block;color:var(--ok);margin-top:2px}
.cc-tiles .c24-ns b{color:var(--danger)}

/* phase 20 (B): the booking page's categories first (ui-x-catalog.js) */
.cust-q{margin:0 0 10px;min-height:44px}
.cust-cats{display:grid;grid-template-columns:1fr;gap:8px}
@media (min-width:560px){.cust-cats{grid-template-columns:1fr 1fr}}
.cust-cat{display:grid;grid-template-columns:1fr auto;grid-template-rows:auto auto;align-items:center;column-gap:10px;min-height:64px;padding:10px 16px;border:1px solid var(--line);border-radius:14px;background:var(--card);color:var(--fg);text-align:left}
.cust-cat b{font-size:16px}
.cust-cat .chev{grid-row:1/3;grid-column:2}
.cust-cat.on{border-color:var(--brand);box-shadow:inset 0 0 0 1px var(--brand)}
.cust-back{margin:0 0 6px}
/* phase 22 (C, Martin's 20): Services › Edit categories. Body-size type everywhere (16 px: iOS does not zoom a 16 px field);
   the new-name box takes the row, Add is compact beside it; rows are one grid — name · count · ↑ · ↓ · ⋯/✕ — so every arrow sits
   at the same x, each control a 44 px target. */
#sheet-body .cat-add{display:flex;gap:8px;margin:4px 0 14px}
#sheet-body .cat-add .input{flex:1 1 auto;min-width:0;min-height:48px;font-size:16px}
#sheet-body .cat-add .btn{flex:none;width:auto;min-height:48px;padding:0 20px}
#sheet-body .cat-list .cat-row{display:grid;grid-template-columns:minmax(0,1fr) 72px 44px 44px 44px;align-items:center;gap:0;min-height:56px;padding:0 4px 0 0}
#sheet-body .cat-list .cat-open{display:flex;flex-direction:column;justify-content:center;min-height:56px;padding:6px 14px;font-size:16px;text-align:left;min-width:0}
#sheet-body .cat-list .cat-open b,#sheet-body .cat-list .cat-open span{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#sheet-body .cat-list .cat-open b{font-weight:600}
#sheet-body .cat-list .cat-open span{font-size:13px}
#sheet-body .cat-list .cat-ren{margin:6px 8px;min-height:44px;font-size:16px}
#sheet-body .cat-list .cat-n{font-size:14px;color:var(--muted);text-align:right;padding-right:8px;white-space:nowrap}
#sheet-body .cat-list .cat-ic{display:grid;place-items:center;width:44px;height:44px;padding:0;border:0;border-radius:10px;background:none;color:var(--fg);font-size:18px;line-height:1;cursor:pointer}
#sheet-body .cat-list .cat-ic:hover:not(:disabled){background:var(--surface-2)}
#sheet-body .cat-list .cat-ic:disabled{opacity:.25;cursor:default}
#sheet-body .cat-list .cat-x{color:var(--danger)}

/* ---------- phase 20 (16): the 短信 tab, Messenger on a computer (ui-x-chat.js) ----------
   A card the height of the window: the conversations (340 px) | the open conversation. On a phone the list, then the conversation
   full screen. Bubbles as Messenger draws them: ours on the right in the shop colour, theirs on the left in grey, a run of bubbles
   from one side shares its inner corners, a centred time between groups, the state under our last text only. */
body.on-msg .app-main{max-width:none}
.ib-page{display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr);background:var(--surface);border:1px solid var(--line);border-radius:14px;overflow:hidden;min-height:320px}
@media (min-width:768px){.ib-page{grid-template-columns:300px minmax(0,1fr)}}
@media (min-width:1280px){.ib-page{grid-template-columns:360px minmax(0,1fr)}}
.ib-list{display:flex;flex-direction:column;min-height:0;min-width:0}
@media (min-width:768px){.ib-list{border-right:1px solid var(--line)}}
.ib-search{padding:12px 12px 4px}
.ib-search .input{border-radius:999px;background:var(--surface-2);border-color:transparent;min-height:40px}
.ib-f{display:flex;gap:8px;padding:6px 12px 8px}   /* phase 20 QA (14): the chips every other filter row uses */
.ib-f .chipbtn{gap:6px}
.ib-f .nav-n{position:static}
.ib-rows{flex:1;min-height:0;overflow-y:auto;padding:0 6px 10px}
.ib-row{display:flex;align-items:center;gap:12px;width:100%;min-height:68px;padding:8px 10px;border-radius:10px;text-align:left;color:var(--fg)}
.ib-row:hover{background:var(--surface-2)}
.ib-row.on{background:color-mix(in srgb,var(--brand-soft) 70%,var(--surface))}
.ib-av{width:48px;height:48px;font-size:18px;background:color-mix(in srgb,var(--fg) 64%,var(--surface));color:var(--surface)}
.ib-row .nm{display:block;font-weight:600;font-size:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ib-row .last{display:block;font-size:13px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:2px}
.ib-row.unread .nm,.ib-row.unread .last{font-weight:750;color:var(--fg)}
.ib-row .side{flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:6px;align-self:flex-start;padding-top:6px}
.ib-row .tm{font-size:12px;color:var(--muted);white-space:nowrap;font-variant-numeric:tabular-nums}
.ib-dot{width:10px;height:10px;border-radius:50%;background:var(--accent)}
.ib-th{display:flex;flex-direction:column;min-height:0;min-width:0}
.ib-none{align-items:center;justify-content:center}
.ib-th-h{display:flex;align-items:center;gap:10px;min-height:64px;padding:8px 12px;border-bottom:1px solid var(--line)}
.ib-th-h .ib-av{width:40px;height:40px;font-size:16px}
.ib-th-h .grow{display:flex;flex-direction:column;min-width:0}
.ib-name{font-weight:700;font-size:16px;color:var(--fg);background:none;border:0;padding:0;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.ib-name:hover{color:var(--accent)}
.ib-ic{flex:none;width:40px;height:40px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;color:var(--accent)}
.ib-ic:hover{background:var(--surface-2)}
.ib-back{color:var(--fg)}
@media (min-width:768px){.ib-back{display:none}}
.ib-msgs{flex:1;min-height:0;overflow-y:auto;padding:8px 16px 12px;display:flex;flex-direction:column}
.ib-sep{align-self:center;font-size:12px;color:var(--muted);margin:14px 0 6px;font-variant-numeric:tabular-nums}
.ib-b{display:flex;flex-direction:column;max-width:min(72%,560px);margin-top:2px}
.ib-b.head{margin-top:8px}
.ib-b.out{align-self:flex-end;align-items:flex-end}
.ib-b.in{align-self:flex-start;align-items:flex-start}
.ib-b .txt-bubble{max-width:100%;border-radius:18px;padding:8px 13px;font-size:15px}
.ib-b .txt-bubble.in{background:var(--surface-2);border:0}
.ib-b.out:not(.head) .txt-bubble{border-top-right-radius:5px}
.ib-b.out:not(.tail) .txt-bubble{border-bottom-right-radius:5px}
.ib-b.out.tail .txt-bubble{border-bottom-right-radius:18px}
.ib-b.in:not(.head) .txt-bubble{border-top-left-radius:5px}
.ib-b.in:not(.tail) .txt-bubble{border-bottom-left-radius:5px}
.ib-b.in.tail .txt-bubble{border-bottom-left-radius:18px}
.ib-st{font-size:11.5px;color:var(--muted);padding:3px 4px 0}
.chat-st.ok{color:var(--ok)}
.chat-st.bad{color:var(--danger);font-weight:600}
.ib-comp{display:flex;align-items:flex-end;gap:6px;padding:10px 12px calc(10px + env(safe-area-inset-bottom,0px));border-top:1px solid var(--line)}
.ib-comp textarea{flex:1;resize:none;min-height:42px;max-height:140px;line-height:1.35;border-radius:21px;background:var(--surface-2);border-color:transparent;padding:10px 14px}
.ib-note{padding:12px 16px;border-top:1px solid var(--line)}
/* a phone: the list, or the conversation full screen */
@media (max-width:767px){
  .ib-page{border:0;border-radius:0;background:transparent;margin:0 -16px;min-height:0}
  .ib-page.has-th .ib-list{display:none}
  .ib-page.has-th{background:var(--surface)}
  .ib-page.has-th{margin-top:0}
  .ib-b{max-width:82%}
}
/* ---------- phase 18 (B12): search everywhere ---------- */
.side-sr{color:var(--muted)}
.sr-btn{display:inline-flex;align-items:center;gap:8px}
#sr-pal{position:fixed;inset:0;z-index:60}
#sr-pal .sr-bg{position:absolute;inset:0;background:rgba(0,0,0,.35)}
.sr-box{position:relative;margin:8vh auto 0;width:min(620px,94vw);max-height:76vh;display:flex;flex-direction:column;background:var(--surface);border-radius:16px;box-shadow:0 24px 60px rgba(0,0,0,.35);overflow:hidden}
.sr-in{display:flex;align-items:center;gap:10px;padding:12px 14px;border-bottom:1px solid var(--line)}
.sr-in .input{border:0;box-shadow:none;font-size:17px;min-height:44px;flex:1}
.sr-in kbd{font-size:11px;color:var(--muted);border:1px solid var(--line);border-radius:6px;padding:2px 6px}
.sr-list{overflow:auto;padding:6px 8px 12px}
.sr-tip{padding:12px 10px}
.sr-g{font-size:12px;font-weight:700;color:var(--muted);padding:10px 10px 4px}
.sr-r{display:flex;align-items:center;gap:10px;width:100%;min-height:52px;padding:6px 10px;border-radius:10px;text-align:left;color:var(--fg)}
.sr-r b{display:block;font-size:15px}
.sr-r span span{display:block;font-size:13px;color:var(--muted)}
.sr-r.on,.sr-r:hover{background:var(--brand-soft)}
@media (max-width:640px){.sr-box{margin:0;width:100vw;max-height:100vh;height:100%;border-radius:0}}
.ib-row>.grow,.ib-th-h>.grow,.sr-r>.grow,.sd-bar>.grow,.bp-link>.grow,.switch-row>.grow,.rf-row>.grow{flex:1 1 auto;min-width:0}
/* phase 20 review (6): on a phone every control is at least 44 px (Apple's minimum touch target) */
@media (max-width:767px){.ib-search .input{min-height:44px}.ib-ic{width:44px;height:44px}.ib-comp textarea{min-height:44px}}

/* phase 21 (Part D): the ClickSend credit beside the title */
.chat-credit{font-size:12px;color:var(--muted);white-space:nowrap;font-variant-numeric:tabular-nums}
.chat-credit.low{color:var(--danger,#c0392b);font-weight:600}

/* checkout and the client profile (phase 04): 结账 sheet, receipts, balances on chips and rows, late-cancel choice */
.co-lines{display:flex;flex-direction:column;gap:6px;font-size:14px;background:var(--surface-2);border-radius:12px;padding:12px 14px}
.co-lines>div{display:flex;justify-content:space-between;gap:10px}
.co-lines>div.bonus{color:var(--ok);font-size:13px}
.co-lines .tot{border-top:1px solid var(--line);padding-top:8px;font-weight:700;font-size:16px}
.co-lines .btn.ghost{margin:-2px 0}
.co-prod{display:grid;grid-template-columns:1.4fr 1fr auto;gap:6px;align-items:center}
.co-prod .input{min-height:40px;padding:6px 10px;font-size:14px;border-radius:8px}
.co-tenders{display:flex;flex-direction:column;gap:6px}
.co-tender{display:grid;grid-template-columns:minmax(0,1fr) 124px 32px;align-items:center;column-gap:10px;padding:10px 6px 10px 14px;border:1px solid var(--line);border-radius:12px;background:var(--surface)}
.co-tender.package,.co-tender.stored{background:var(--brand-soft);border-color:var(--brand-line)}
.co-tender.owing{background:var(--danger-soft);border-color:color-mix(in srgb,var(--danger) 35%,var(--line))}
.co-tender .grow{min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:4px}
.co-tender .lbl{font-size:15px;font-weight:600;line-height:1.3;overflow-wrap:anywhere}
.co-tender .grow>.small{font-size:12.5px;line-height:1.3}
.co-tender select.input{min-height:36px;padding:4px 28px 4px 10px;font-size:14px;border-radius:8px;width:auto;max-width:100%}
.co-x{color:var(--muted);font-size:14px;width:32px;height:32px;border-radius:50%;flex:none;display:inline-flex;align-items:center;justify-content:center}
.co-x:hover{background:var(--surface-2)}
.co-remain{font-size:14px;color:var(--warn);padding:4px 0}
.co-remain.bad{color:var(--danger)}
.co-pills{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-top:4px}
.co-pill{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;min-height:48px;padding:6px 8px;border:1px solid var(--line);border-radius:12px;background:var(--surface);font-weight:600;font-size:14px;color:var(--fg)}
.co-pill small{font-size:11px;font-weight:500;color:var(--muted)}
.co-pill.on{background:var(--brand);color:var(--brand-ink);border-color:var(--brand)}
.co-pill.on small{color:color-mix(in srgb,var(--brand-ink) 80%,transparent)}
.co-pill.off{opacity:.45}
/* phase 20 (20): the top-up presets: equal tiles filling the row, amount over bonus, centred; the chosen one marked */
.co-presets{display:grid;grid-template-columns:repeat(var(--n,2),minmax(0,1fr));gap:8px}
.co-preset{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;min-height:68px;padding:8px;border:1px solid var(--line);border-radius:12px;background:var(--surface);color:var(--fg);text-align:center}
.co-preset b{font-size:19px;font-weight:700;line-height:1.2}
.co-preset small{font-size:12.5px;font-weight:500;color:var(--muted);line-height:1.2}
.co-preset.on{border-color:var(--brand);box-shadow:inset 0 0 0 1px var(--brand);background:var(--brand-soft)}
.co-preset.on small{color:var(--brand)}
.co-preset .ck{position:absolute;top:6px;right:8px;font-style:normal;font-size:12px;font-weight:800;line-height:1;color:var(--brand)}
/* phase 20 (21): one money field everywhere: the $ inside the box, the figure on tabular digits; .r right-aligns it in a list */
.money{position:relative;display:block;min-width:0}
.money>.cur{position:absolute;left:12px;top:50%;transform:translateY(-50%);font-size:16px;line-height:1;font-weight:600;color:var(--muted);pointer-events:none;font-variant-numeric:tabular-nums}
.money>input.input{width:100%;padding-left:28px;font-variant-numeric:tabular-nums}
.money.r>input.input,.co-tender .money>input.input{text-align:right;padding-right:12px}
.co-tender .money>input.input,.co-tender .money>.co-fixed{min-height:44px;height:44px;font-size:16px;border-radius:10px}
.money>.co-fixed{display:flex;align-items:center;justify-content:flex-end;padding:0 12px 0 28px;border:1px solid transparent;font-weight:600;background:color-mix(in srgb,var(--surface) 60%,transparent)}
.co-big{min-height:56px;font-size:17px;line-height:1.25;padding:8px 16px;text-align:center}
.co-receipt{border:1px dashed var(--line);border-radius:12px;padding:14px 16px;font-size:13px;display:flex;flex-direction:column;gap:10px;background:var(--surface)}
.co-receipt .hd{display:flex;flex-direction:column;gap:2px;text-align:center}
.co-receipt .hd b{font-family:var(--font-display);font-size:17px}
.co-receipt .meta{display:flex;justify-content:space-between;gap:8px;color:var(--muted)}
.co-receipt .lines{display:flex;flex-direction:column;gap:4px;border-top:1px dashed var(--line);padding-top:8px}
.co-receipt .lines>div{display:flex;justify-content:space-between;gap:10px}
.co-receipt .lines .tot{font-weight:700;font-size:15px;border-top:1px solid var(--line);padding-top:6px;margin-top:2px}
.co-receipt .foot{text-align:center;color:var(--muted);border-top:1px dashed var(--line);padding-top:8px}
.co-receipt.void{text-decoration:line-through;opacity:.6}
/* profile */
.co-prof{display:flex;flex-direction:column;gap:10px;background:var(--surface-2);border-radius:14px;padding:14px}
.co-name{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:15px}
.co-name>b{font-size:18px;font-family:var(--font-display)}
.co-bal{display:grid;grid-template-columns:1fr 1fr;gap:8px 14px}
.co-bal>div{display:flex;flex-direction:column;gap:8px;min-width:0}
.co-bal>div>div{display:flex;flex-direction:column;gap:1px}
.co-bal span{font-size:11px;color:var(--muted);letter-spacing:.04em}
.co-bal b{font-size:18px;line-height:1.2}
.co-bal b.small{font-size:13px}
.co-bal small{font-size:11px;color:var(--muted)}
.co-bal .owing b{color:var(--danger)}
.co-bal .dim{opacity:.55}
.co-exp.amber{color:var(--warn);font-weight:600}
.co-exp.grey{color:var(--faint)}
.co-next{font-size:13px;background:color-mix(in srgb,var(--warn) 10%,var(--surface));border:1px solid color-mix(in srgb,var(--warn) 40%,var(--line));border-radius:10px;padding:8px 10px}
.co-acts{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}
.co-acts .btn{min-height:44px;font-size:14px;padding:0 6px}
.co-acts .btn:first-child{grid-column:1/-1}
@media (min-width:720px){.co-acts{grid-template-columns:repeat(5,1fr)}.co-acts .btn:first-child{grid-column:auto}}
.co-tabs{margin-top:2px}
.co-ledger .co-sale.void .ttl,.co-ledger .co-sale.void .sub:not(.co-void),.co-ledger .co-sale.void>b{text-decoration:line-through;opacity:.6}
.co-ledger .co-void{color:var(--danger)}
.co-owe{color:var(--danger);font-weight:600}
.co-pkg{padding:12px 14px;display:flex;flex-direction:column;gap:4px}
.co-uses{display:flex;flex-direction:column;gap:2px;font-size:12px;color:var(--muted);margin-top:4px;padding-left:8px;border-left:2px solid var(--line)}
.co-rowbal{margin-top:2px}
.co-right{display:flex;flex-direction:column;align-items:flex-end;gap:1px;flex:none;font-size:12px;color:var(--muted)}
.co-right b{font-size:14px;color:var(--fg)}
/* calendar chip: the one balance line, bottom right */
.cal-bk .co-chipbal{position:absolute;right:4px;bottom:3px;z-index:2;font-size:9.5px;font-weight:700;line-height:14px;padding:0 5px;border-radius:999px;background:var(--surface);color:var(--muted);box-shadow:0 0 0 1px var(--line);white-space:nowrap}
.cal-bk .co-chipbal.owing{background:var(--danger);color:#fff;box-shadow:none}
.cal-bk .co-chipbal.pkg{background:var(--brand);color:var(--brand-ink);box-shadow:none}
/* late cancel */
.co-late{display:flex;flex-direction:column;gap:6px;padding:12px 14px;border-radius:12px;background:color-mix(in srgb,var(--warn) 10%,var(--surface));border:1px solid color-mix(in srgb,var(--warn) 40%,var(--line))}
.co-late-acts{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-top:4px}
.co-late-acts .btn{flex-direction:column;gap:0;min-height:54px;font-size:14px;padding:6px 4px;line-height:1.2}
.co-late-acts .btn small{font-size:11px;font-weight:500;opacity:.8}
.co-latelist{margin:4px 0 6px;padding:12px 14px;border-radius:12px;background:color-mix(in srgb,var(--warn) 10%,var(--surface));border:1px solid color-mix(in srgb,var(--warn) 40%,var(--line))}
.co-latelist .item{display:flex;align-items:center;gap:10px;flex-wrap:wrap;border-top:1px solid var(--line)}
.co-latelist .item:first-of-type{border-top:0}
.co-latelist .acts{display:flex;gap:6px;flex-wrap:wrap;width:100%;margin-top:4px}
.co-latelist .acts .btn{flex:1 1 auto}
@media (min-width:720px){.co-latelist .acts{width:auto;margin-top:0}}
/* 折扣 (phase 12) */
.co-lines .discount b{color:var(--ok)}
.co-disc{display:flex;flex-direction:column;gap:6px;padding:10px;border:1px dashed var(--line);border-radius:12px}
.co-disc-tag{background:color-mix(in srgb,var(--ok) 14%,var(--surface-2))}
/* phase 21 (Part E, 18): "not checked out" on a calendar chip: amber, the same pill as the balance line */
.cal-bk .co-nco{flex:none;margin-left:auto;align-self:center;font-size:9.5px;font-weight:700;line-height:14px;padding:0 5px;border-radius:999px;background:var(--surface);color:var(--warn);box-shadow:0 0 0 1px var(--warn);white-space:nowrap}
.cal-bk .co-nco+.co-chipbal{margin-left:4px}
.gc .cal-bk.short .co-nco{display:none}
@container (max-width:110px){#gc-cal .cal-bk .co-nco{display:none}}
/* phase 21 (Part E, 11): the receipt send block */
.co-send .co-pill:disabled{opacity:.45}
.co-send-row .co-sent{color:var(--ok);white-space:nowrap}

/* ---------- phase 18 (B14): the booking page on a phone (320, 375, 430 wide) ----------
   The shop: "the scaling and positioning of the times and the buttons are all over the place". Times in an even grid (4 a row
   from 340 px, 3 below), every target 48 px; one primary button pinned at the bottom; nothing wider than the screen. */
.wrap{overflow-x:clip}
.c-head .shop-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.shop-sub{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.slots{grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
.slot{min-height:48px;font-size:16px;padding:0}
@media (max-width:339px){.slots{grid-template-columns:repeat(3,minmax(0,1fr))}}
.slot-grp{margin-top:14px}
.strip .day{width:60px;min-height:76px}
.chips[data-key^="chips-c-staff"]{flex-wrap:wrap;overflow:visible}
.chips[data-key^="chips-c-staff"] .chipbtn{min-height:48px}
.svc{min-height:56px}
.sticky-cta,.selbar{z-index:5}
.sticky-cta .btn,.selbar .btn{min-height:52px}
.sec-title + .muted.small{overflow-wrap:anywhere}
/* B15: the done screen — booked, the text will ask them to confirm; no tick */
.success.booked{padding:30px 0 14px}
.success.booked h2{font-size:26px}
/* B16: the booking's mobile, typed again before a change or a cancel */
.my-verify{margin-top:14px}
.my-cancel{padding:18px 16px;display:flex;flex-direction:column;gap:12px}
.my-cancel h3{font-size:18px}
.my-act{text-align:center}
@media (max-width:359px){.my-acts{grid-template-columns:repeat(2,minmax(0,1fr))}}
.my-pkgs{padding:14px 16px}
/* ---------- phase 21 (C): the client profile — chips under the name, ✎ Edit, the grouped edit sheet ---------- */
.cc-prof .co-name .cl-edit{margin-left:auto;flex:none;min-height:36px}
/* a phone: the name and Edit on one line, the mobile under them (Edit never sits alone on a line) */
@media (max-width:599px){.cc-prof .co-name .cl-edit{order:2}.cc-prof .co-name>.num{order:3;flex-basis:100%}}
.cl-chips{display:flex;flex-direction:column;align-items:flex-start;gap:4px}
.cl-blocked{display:inline-flex;align-items:center;gap:6px;padding:2px 10px;border-radius:999px;background:var(--danger);color:#fff;font-size:13px;font-weight:700;white-space:nowrap}
.cl-blocked small{font-weight:500;opacity:.9;white-space:normal}
.ta-item .cl-blocked{font-size:11px;padding:0 7px;vertical-align:1px}
.cl-alert{padding:6px 10px;border-radius:8px;background:color-mix(in srgb,#f0a020 18%,var(--surface));color:var(--fg);font-size:14px;font-weight:600;overflow-wrap:anywhere}
.cl-allergy{color:var(--danger);font-size:14px;font-weight:600}
.cl-ed-h{margin:0 48px 12px 0;font-size:20px;font-family:var(--font-display);overflow-wrap:anywhere}
.cl-ed{gap:10px}
.cl-grp{border:1px solid var(--line);border-radius:12px;padding:0 14px}
.cl-grp>summary{min-height:48px;display:flex;align-items:center;font-weight:700;cursor:pointer;list-style:none}
.cl-grp>summary::-webkit-details-marker{display:none}
.cl-grp>summary::after{content:'›';margin-left:auto;color:var(--muted);transition:transform .15s}
.cl-grp[open]>summary::after{transform:rotate(90deg)}
.cl-grp>.col{gap:12px;padding-bottom:14px}
.cl-grp .grid2{gap:10px}
.btn.ghost.cl-del{color:var(--danger);align-self:flex-start}
.cl-grp .grid2>*{min-width:0}
.cl-grp .grid2 .input{min-width:0;width:100%}
.cl-details .kv{margin-top:8px}
/* phase 22 (C): the record no. small next to a name; "No mobile"; Shares mobile with X; the Merge sheet */
.cl-rec{font-size:12px;font-weight:600;color:var(--muted);letter-spacing:.01em;margin-left:6px;white-space:nowrap}
.co-name .cl-rec{align-self:center}
.cl-nomob{color:var(--muted);font-style:normal}
.cl-share{margin:2px 0 6px}
.cl-share .cl-link{font-weight:600}
.cl-row .cl-mg{flex:none;margin-right:10px;align-self:center}
/* phase 23 (D): the merge sheet became the review (ui-x-dups.css); the card's "also 0433 … · Make main"; the type-ahead's last 3 digits */
.cl-also{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:2px 0 6px}
.cl-also .num,.cl-also span{font-variant-numeric:tabular-nums}
.cl-also .lnk{background:none;border:0;padding:0;min-height:44px;color:var(--accent);font-weight:600;font-size:14px;cursor:pointer}
.ta-item .ta-last3{font-weight:800;color:var(--fg);text-decoration:underline;text-underline-offset:2px}
.ta-item .cl-rec{margin-left:4px}
.cl-row .cl-money{min-width:88px}

/* two-way confirmations (phase 02): badges, bell, call list, link-page button, SMS log demo controls */
.ackb{display:inline-flex;align-items:center;gap:3px;padding:1px 8px;border-radius:999px;font-size:11px;font-weight:700;background:var(--surface-2);color:var(--muted);white-space:nowrap;line-height:18px}
.ackb.ok{background:color-mix(in srgb,var(--ok) 14%,var(--surface));color:var(--ok)}
.ackb.bad{background:var(--danger-soft);color:var(--danger)}
.ackb.warn{background:color-mix(in srgb,var(--warn) 14%,var(--surface));color:var(--warn)}
.ackb.brand{background:var(--brand-soft);color:var(--accent)}
.cal-bk .ack{position:absolute;top:3px;right:4px;z-index:2;width:16px;height:16px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:800;background:var(--surface);color:var(--muted);box-shadow:0 0 0 1px var(--line)}
.cal-bk .ack.ok{background:var(--ok);color:#fff;box-shadow:none}
.cal-bk .ack.bad{background:var(--danger);color:#fff;box-shadow:none}
.cal-bk .ack.warn{background:var(--warn);color:#fff;box-shadow:none}
.cal-bk .ack.brand{background:var(--brand);color:var(--brand-ink);box-shadow:none}
.bell{position:relative;font-size:18px;min-width:36px;min-height:36px;border-radius:10px;display:inline-flex;align-items:center;justify-content:center}
.bell:hover{background:var(--surface-2)}
.bell .badge{position:absolute;top:-2px;right:-4px;margin:0}
.cf-notice .ic{width:30px;height:30px;border-radius:50%;flex:none;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;background:var(--surface-2);color:var(--muted)}
.cf-notice .ic.confirmed{background:color-mix(in srgb,var(--ok) 14%,var(--surface));color:var(--ok)}
.cf-notice .ic.cancelled,.cf-notice .ic.failed{background:var(--danger-soft);color:var(--danger)}
.cf-notice .ic.rescheduled{background:var(--brand-soft);color:var(--accent)}
.cf-notice.unread .ttl{font-weight:700}
.cf-notice .ttl{font-weight:500;font-size:14px}
.cf-call{margin:4px 0 6px;padding:12px 14px;border-radius:12px;background:var(--danger-soft);border:1px solid color-mix(in srgb,var(--danger) 35%,var(--line))}
.cf-call .list{margin-top:6px}
.cf-call .item{flex-wrap:wrap}
.cf-call .acts{display:flex;gap:6px;flex-wrap:wrap;width:100%;margin-top:6px}
.cf-call .acts .btn{flex:1 1 auto;min-height:38px}
.cf-sec{padding:12px 14px;border-radius:12px;background:var(--surface-2)}
.cf-big{font-size:18px;min-height:58px}
.cf-done{background:color-mix(in srgb,var(--ok) 14%,var(--surface));color:var(--ok);border-radius:12px;padding:16px;text-align:center;font-weight:700;font-size:18px}
.cf-done small{display:block;font-weight:400;font-size:13px;margin-top:4px;color:var(--fg)}
.msg .body.other{opacity:.55;font-size:12px}
.msg.in .body{background:var(--brand-soft)}
.msg .seg{font-weight:600}
.msg .seg.many{color:var(--warn)}
.cf-demo{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:8px;font-size:12px;color:var(--muted)}
.cf-demo button{border:1px solid var(--line);border-radius:8px;padding:0 10px;font-size:12px;font-weight:600;background:var(--surface);min-height:30px;color:var(--fg)}
.cf-demo button.y{color:var(--ok)}
.cf-demo button.n{color:var(--danger)}
.cf-demo input{min-height:30px;font-size:12px;padding:0 8px;border:1px solid var(--line);border-radius:8px;background:var(--surface);width:120px}
.cf-inbox{display:grid;grid-template-columns:1fr 1fr auto;gap:6px;align-items:end}
@media (max-width:480px){.cf-inbox{grid-template-columns:1fr 1fr}.cf-inbox .btn{grid-column:1/-1}}
/* phase 20 (18): the booking sheet's confirmation is one line with at most one action */
.cf-line{display:flex;align-items:center;gap:10px;min-height:40px;padding:6px 12px;border-radius:12px;background:var(--surface-2);line-height:1.35}
.cf-line .grow{min-width:0}
.cf-line .btn{flex:none}
.cf-line .cf-ok{color:var(--ok);font-weight:700}
.cf-line .cf-bad{color:var(--danger);font-weight:700}
.cf-line .cf-wait{color:var(--warn);font-weight:700}
/* phase 20 (11): the booking page's code step and "for someone else" */
.c-other{align-self:flex-start;padding:4px 0;color:var(--accent)}
.c-code{display:flex;flex-direction:column;gap:10px;padding:16px}
.c-code label{font-size:15px;line-height:1.4}
.c-code-in{font-size:28px;letter-spacing:.4em;text-align:center;font-variant-numeric:tabular-nums;padding-left:.4em}
.c-code-more{justify-content:space-between;gap:12px}
.c-code-more .lnk[disabled]{color:var(--muted);cursor:default;text-decoration:none}
/* phase 20 (12): add to calendar, three ways in */
.my-cal .btn{width:100%;min-height:48px}
/* the 84 px rail: logo + bell fill the row, so the unread badge stays inside the bell (a two-digit count overflowed by 2 px) */
.app-shell.rail .side-brand .bell .badge{right:0}

/* ---------- phase 17: 概览 / Dashboard (ui-x-dash.js): big numbers, few words, one simple chart ---------- */
.dash-toolbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.dash-toolbar h2{flex:1}
.dash-range{margin:-4px 0 12px}
.dash-tiles{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:14px}
.dash-tile{background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:12px 14px;display:flex;flex-direction:column;gap:4px;min-width:0}
.dash-l{font-size:13px;font-weight:600;color:var(--muted)}
.dash-big{font-size:28px;line-height:1.1;font-weight:750;letter-spacing:-.02em;color:var(--fg);display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dash-big small{font-size:14px;font-weight:600;color:var(--muted)}
.dash-tile .rp-num{text-align:left;padding:0;min-height:0}
.dash-s{font-size:12.5px;color:var(--muted)}
.dash-d{font-size:12.5px;font-weight:600}
.dash-d.up{color:var(--st-ok,#1b6f3f)}.dash-d.down{color:var(--st-call,#b3261e)}.dash-d.flat{color:var(--muted)}
.dash-cols{display:grid;gap:14px}
.dash-col{display:flex;flex-direction:column;gap:14px;min-width:0}
.dash-card{background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:6px 14px 8px}
.dash-h{display:flex;align-items:center;justify-content:space-between;font-size:var(--t-section,17px);font-weight:700;padding:8px 0 6px}
.dash-h .lnk{font-size:13px;font-weight:600;color:var(--accent);padding:0}
.dash-row{display:flex;align-items:center;gap:10px;width:100%;min-height:48px;padding:6px 0;border-top:1px solid var(--line);text-align:left;font-size:14.5px}
.dash-row:first-of-type{border-top:0}
.dash-row .grow{display:flex;flex-direction:column;min-width:0}
.dash-row .ttl{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dash-row>b.num{min-width:46px;font-size:15px}
.dash-row .chev{color:var(--faint)}
.dash-row .gc-st{flex:none;display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 4px;border-radius:999px;font-style:normal;font-size:10.5px;font-weight:800;color:var(--stk);background:color-mix(in srgb,var(--stk) 16%,var(--surface));box-shadow:0 0 0 1px color-mix(in srgb,var(--stk) 45%,transparent)}
.dash-row.static{cursor:default}
.dash-rank{width:20px;color:var(--muted);font-weight:700;font-variant-numeric:tabular-nums}
.dash-amt{min-width:64px;text-align:right}
.dash-row .rp-num{padding:0 4px;min-height:32px}
.dash-empty{color:var(--muted);font-size:14px;padding:8px 0 10px}
.dash-todo .banner,.dash-todo .card{margin:6px 0}
.dash-bars{display:flex;align-items:flex-end;gap:3px;height:130px;padding:6px 0 2px}
.dash-bar{flex:1 1 0;min-width:0;height:100%;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;gap:3px}
.dash-bar i{display:block;width:100%;max-width:34px;min-height:2px;border-radius:4px 4px 1px 1px;background:color-mix(in srgb,var(--accent) 70%,var(--surface))}
.dash-bar.today i{background:var(--accent)}
.dash-bar.future i{background:var(--line)}
.dash-bar span{font-size:10.5px;color:var(--muted);font-variant-numeric:tabular-nums;line-height:1}
.dash-bars.month .dash-bar span{font-size:9px}
.dash-bars.month .dash-bar:nth-child(odd):not(.today) span{visibility:hidden}
.dash-more{align-self:flex-start}
@media (min-width:720px){.dash-tiles{grid-template-columns:repeat(4,1fr)}}
@media (min-width:1100px){.dash-cols{grid-template-columns:minmax(0,1.25fr) minmax(0,1fr)}}

/* ---------- phase 23 (D): the duplicates review, its Undo toast, Clients' "n possible duplicates" line, the card's merges ---------- */
.drv-on body{overflow:hidden}
.drv{position:fixed;inset:0;z-index:52;display:flex;flex-direction:column;background:var(--bg);color:var(--fg);outline:none}
.drv-h{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:10px 16px;padding-top:calc(10px + env(safe-area-inset-top,0px));background:var(--surface);border-bottom:1px solid var(--line)}
.drv-h h2{font-family:var(--font-display);font-size:20px;margin:0}
.drv-n{color:var(--muted);font-size:14px;white-space:nowrap}
.drv-x{flex:none;width:44px;height:44px;border-radius:50%;background:var(--surface-2);color:var(--muted);font-size:16px;display:flex;align-items:center;justify-content:center}
.drv-h .drv-all{margin-left:auto;min-height:44px}
.drv-prog{display:inline-flex;align-items:center;color:var(--muted);font-size:14px}
.drv-wait{padding:24px 16px}
.drv-body{flex:1;min-height:0;display:grid;grid-template-columns:minmax(0,1fr)}
.drv-list{display:none}
@media (min-width:900px){
  .drv-body{grid-template-columns:300px minmax(0,1fr)}
  .drv-list{display:flex;flex-direction:column;overflow-y:auto;border-right:1px solid var(--line);background:var(--surface);padding:6px 0}
}
.drv-li{display:flex;align-items:center;gap:8px;min-height:44px;padding:8px 16px;text-align:left;font-size:14px;color:var(--fg);background:none;border:0;cursor:pointer}
.drv-li .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.drv-li:hover{background:var(--surface-2)}
.drv-li.on{background:var(--brand-soft);font-weight:700}
.drv-li.is-merged,.drv-li.is-not{opacity:.45;text-decoration:line-through}
.drv-li.is-skip{color:var(--muted)}
.drv-pair{overflow-y:auto;padding:16px 16px calc(16px + env(safe-area-inset-bottom,0px));display:flex;flex-direction:column;gap:14px;width:100%;max-width:760px;margin:0 auto}
.drv-pair>*{flex:none}
.drv-pair.drv-in{animation:drv-in .22s ease-out}
@keyframes drv-in{from{transform:translateX(28px);opacity:0}to{transform:none;opacity:1}}
.drv-tier:empty{display:none}
/* the two side by side: a label column and one column per record; what differs is tinted */
.drv-cmp{display:grid;grid-template-columns:minmax(72px,auto) minmax(0,1fr) minmax(0,1fr);border:1px solid var(--line);border-radius:14px;overflow:hidden;background:var(--surface)}
.drv-cmp>*{padding:10px 12px;border-top:1px solid var(--line);min-width:0;overflow-wrap:anywhere;font-size:15px}
.drv-cmp>:nth-child(-n+3){border-top:0}
.drv-cmp .k{color:var(--muted);font-size:13px;align-self:center}
.drv-cmp .v{align-self:center}
.drv-cmp .v.nw{white-space:nowrap;overflow-wrap:normal}
.drv-cmp .d{background:color-mix(in srgb,var(--warn) 13%,var(--surface))}
.drv-cmp .faint{color:var(--faint)}
.drv-c{display:flex;flex-direction:column;align-items:flex-start;gap:4px;min-height:56px;text-align:left;font-size:16px;color:var(--fg);background:none;border:0;cursor:pointer}
.drv-c.on{box-shadow:inset 0 -3px 0 var(--brand)}
.drv-c b{overflow-wrap:anywhere}
@media (max-width:599px){
  .drv-cmp{grid-template-columns:minmax(56px,auto) minmax(0,1fr) minmax(0,1fr)}
  .drv-cmp>*{padding:9px 8px;font-size:14px}
  .drv-cmp .k{font-size:12px}
  .drv-c{font-size:15px}
  .drv-pair{padding:12px 12px calc(12px + env(safe-area-inset-bottom,0px))}
}
/* Texts go to: the two mobiles, one chosen */
.drv-tx{border:1px solid var(--line);border-radius:14px;padding:6px 14px 8px;background:var(--surface);margin:0}
.drv-tx legend{padding:0 4px;font-size:13px;font-weight:700;color:var(--muted)}
.drv-opt{display:flex;align-items:center;gap:10px;min-height:48px;cursor:pointer;flex-wrap:wrap}
.drv-opt input{width:20px;height:20px;accent-color:var(--brand);flex:none}
.drv-opt .num{font-size:16px;font-weight:600}
.drv-acts{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.35fr) auto;gap:8px;position:sticky;bottom:0;padding:10px 0 2px;background:linear-gradient(to bottom,transparent,var(--bg) 30%)}
.drv-acts .btn{min-height:52px;display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:0 10px;white-space:nowrap}
.drv-acts .btn.ghost{padding:0 14px}
.drv-acts kbd{display:none;font:600 11px/1 var(--font-body);padding:3px 6px;border-radius:6px;border:1px solid currentColor;opacity:.55}
@media (min-width:900px) and (hover:hover){.drv-acts kbd{display:inline-block}}
.drv-done{display:flex;flex-direction:column;align-items:center;gap:14px;padding:48px 16px;text-align:center}
.drv-done b{font-family:var(--font-display);font-size:22px}
.drv-done .btn{min-width:220px}
/* the Undo toast (above the review and the sheet) */
.drv-undo{position:fixed;left:50%;bottom:calc(24px + env(safe-area-inset-bottom,0px));transform:translate(-50%,12px);z-index:61;display:flex;align-items:center;gap:16px;padding:6px 8px 6px 16px;border-radius:12px;background:#1d1b18;color:#ece8e1;font-size:14px;box-shadow:var(--shadow);opacity:0;pointer-events:none;transition:opacity .2s,transform .2s;max-width:calc(100% - 32px)}
.drv-undo.show{opacity:1;transform:translate(-50%,0);pointer-events:auto}
.drv-undo .lnk{min-height:40px;padding:0 10px;background:none;border:0;color:#f3c77a;font-weight:700;font-size:14px;cursor:pointer}
/* Clients: n possible duplicates · Review */
.dup-line{display:flex;align-items:center;gap:12px;margin:2px 0 10px;padding:6px 6px 6px 14px;border:1px solid color-mix(in srgb,var(--warn) 35%,var(--line));border-radius:12px;background:color-mix(in srgb,var(--warn) 8%,var(--surface));font-size:14px}
.dup-line span{flex:1;min-width:0}
.dup-line .btn{flex:none}
/* the kept client's card: Merged with X · date · Undo */
.cl-merged{display:flex;flex-direction:column;gap:2px}
.cl-mg-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.cl-mg-row .lnk{background:none;border:0;padding:0;min-height:44px;color:var(--accent);font-weight:600;font-size:14px;cursor:pointer}

/* phase 20 (B): the file picker (ui-x-filepick.js) — a drop zone that is a <label for>, with a real Choose file button */
.fp-input{position:absolute;width:1px;height:1px;opacity:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.fp-drop{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;min-height:168px;margin-top:4px;padding:20px;border:2px dashed var(--line);border-radius:16px;background:var(--surface);color:var(--fg);cursor:pointer;text-align:center;-webkit-tap-highlight-color:transparent}
.fp-drop:hover,.fp-drop.over{border-color:var(--brand)}
.fp-drop.over{background:var(--brand-soft)}
.fp-drop.busy{opacity:.6;pointer-events:none}
.fp-drop .ic{font-size:30px;line-height:1}
.fp-drop .fp-btn{margin-top:6px;pointer-events:none}
.fp-input:focus-visible+.fp-drop{outline:2px solid var(--brand);outline-offset:2px}

/* ---------- phase 16: the 日历 tab, modelled on Google Calendar (src/ui-x-gcal.js) ---------- */
/* the bar: 今天 ‹ › title on the left, the views and the two actions on the right; two rows on a phone */
.gc-head{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;margin-bottom:8px}
.gc-nav{display:flex;align-items:center;gap:4px;min-width:0;flex:1 1 auto}
.gc-today{min-height:36px;padding:6px 14px;border-radius:999px;font-weight:600}
.gc-today.here{color:var(--accent)}
.gc-arrow{width:36px;height:36px;border-radius:50%;font-size:22px;line-height:1;display:inline-flex;align-items:center;justify-content:center;color:var(--fg)}
.gc-arrow:hover{background:var(--surface-2)}
.gc-title{font-size:17px;margin-left:6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;font-variant-numeric:tabular-nums}
.gc-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.gc-tools .grow{flex:1}
.gc-tools .btn{white-space:nowrap}
@media (max-width:560px){.gc-tools{flex:1 1 100%}.gc-title{font-size:15px}}
.gc-sum{justify-content:space-between;margin-top:4px;align-items:center}

/* the grid: hour lines, a fainter half-hour line, no cell borders inside a column */
.gc{user-select:none;-webkit-user-select:none;-webkit-touch-callout:none}
.gc .cal-body{background:
  repeating-linear-gradient(to bottom,var(--line) 0 1px,transparent 1px var(--gc-hr,64px)),
  repeating-linear-gradient(to bottom,transparent 0 calc(var(--gc-hr,64px)/2),color-mix(in srgb,var(--line) 45%,transparent) calc(var(--gc-hr,64px)/2) calc(var(--gc-hr,64px)/2 + 1px),transparent calc(var(--gc-hr,64px)/2 + 1px) var(--gc-hr,64px));
  cursor:cell;touch-action:pan-x pan-y}
.gc-week{--gc-hr:48px}
.gc .cal-off,.gc .cal-break{pointer-events:none}
.gc .cal-col.wk{min-width:0;flex:1 1 0}
.gc-3day .cal-col.wk{min-width:96px}
.gc .cal-col.wk .ch{flex-direction:column;justify-content:center;gap:0;line-height:1.1;cursor:pointer;padding:0 2px}
.gc .cal-col.wk .ch .dw{font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase}
.gc .cal-col.wk .ch .dn{font-size:18px;font-weight:600;width:30px;height:26px;display:flex;align-items:center;justify-content:center;border-radius:999px}
.gc .cal-col.wk.today .ch .dw{color:var(--danger)}
.gc .cal-col.wk.today .ch .dn{background:var(--danger);color:#fff}
.gc .cal-col.wk.closed .ch{color:var(--faint)}
.gc .cal-col.wk .ch small{font-size:10px;color:var(--muted);min-height:12px}
@media (max-width:560px){.gc-week .cal-col.wk .ch .dn{font-size:15px;width:24px;height:22px}.gc-week .cal-gutter{width:36px}.gc-week .cal-gutter .hl{font-size:10px}}

/* the blocks: the staff colour, rounded, a hairline between neighbours, compact text */
.gc .cal-bk{right:auto;border-radius:6px;border-left:3px solid var(--stc);background:color-mix(in srgb,var(--stc) 22%,var(--surface));box-shadow:0 0 0 1px var(--surface);padding:2px 5px;line-height:1.25;touch-action:pan-x pan-y;transition:box-shadow .15s ease-out,opacity .15s ease-out}
.gc .cal-bk>b{font-size:12px;font-weight:650}
.gc .cal-bk>span:not(.st){font-size:11px}
.gc .cal-bk.short{display:flex;align-items:baseline;gap:4px;padding-top:1px;padding-bottom:0}
.gc .cal-bk.short>span.sv{display:none}   /* phase 17: a short block keeps the name line (it used to hide every line but the time) */
.gc .cal-bk.short>b,.gc .cal-bk.short>.t{display:inline;white-space:nowrap}
.gc .cal-bk.compact{padding:1px 3px;font-size:10px;line-height:1.15;border-left-width:2px;display:block}
.gc .cal-bk.compact>b{font-size:10px;display:inline;font-weight:600}
.gc .cal-bk.compact>.t{display:inline;font-size:10px}
.gc .cal-bk.gc-mv{cursor:grab}
.gc .cal-bk:hover{box-shadow:0 0 0 1px var(--surface),0 2px 6px rgba(0,0,0,.14);z-index:3}
/* the bottom edge: a 10 px strip (16 px on touch) that drags the length; on a touch screen the grip shows */
.gc-rs{position:absolute;left:0;right:0;bottom:0;height:10px;cursor:ns-resize;touch-action:none;z-index:2}
.gc-rs::after{content:"";position:absolute;left:50%;bottom:3px;width:18px;height:3px;margin-left:-9px;border-radius:2px;background:var(--stc);opacity:0;transition:opacity .15s}
.gc .cal-bk:hover .gc-rs::after{opacity:.7}
@media (pointer:coarse){.gc-rs{height:14px}.gc-rs::after{opacity:.35;width:14px;height:2px;margin-left:-7px;bottom:1px}}
.gc .cal-bk.nested{z-index:2;box-shadow:0 0 0 1px var(--surface),0 2px 8px rgba(0,0,0,.18)}
/* lifted: the block stays where it was, faded; the ghost shows where it lands */
.gc .cal-bk.gc-lifted{opacity:.4;box-shadow:none}
body.gc-dragging,body.gc-dragging *{cursor:grabbing!important}
.gc-ghost{position:absolute;left:2px;right:2px;z-index:6;border-radius:6px;pointer-events:none;padding:3px 6px;font-size:11px;line-height:1.25;overflow:hidden;
  background:color-mix(in srgb,var(--stc) 40%,var(--surface));border-left:3px solid var(--stc);box-shadow:0 6px 18px rgba(0,0,0,.25);color:var(--fg)}
.gc-ghost b{display:block;font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gc-ghost span{display:block;font-weight:700;font-variant-numeric:tabular-nums}
.gc-ghost.same{opacity:.75}
.gc-ghost.bad{background:color-mix(in srgb,var(--danger) 16%,var(--surface));border-left-color:var(--danger);outline:2px dashed var(--danger);outline-offset:-2px}
.gc-ghost.bad span{color:var(--danger);white-space:normal}
.gc-ghost.new{background:color-mix(in srgb,var(--accent) 22%,var(--surface));border-left-color:var(--accent);box-shadow:0 2px 8px rgba(0,0,0,.16)}

/* now: a red line and dot across today's column */
.gc .cal-now{height:2px;z-index:4}
.gc .cal-now::before{left:0;top:-4px;width:10px;height:10px}   /* phase 21: inside the column (its edge clipped half of it) */
.gc .cal-now:not(.first)::before{display:none}   /* phase 21: one dot for the whole day, not one per staff column */

/* ‹ › and the swipe slide the page in from that side */
.gc-in-r .cal-cols{animation:gc-in-r .18s ease-out}
.gc-in-l .cal-cols{animation:gc-in-l .18s ease-out}
@keyframes gc-in-r{from{transform:translateX(24px);opacity:.4}to{transform:none;opacity:1}}
@keyframes gc-in-l{from{transform:translateX(-24px);opacity:.4}to{transform:none;opacity:1}}
@media (prefers-reduced-motion:reduce){.gc-in-r .cal-cols,.gc-in-l .cal-cols{animation:none}.gc .cal-bk{transition:none}}

/* the undo bar: what happened + 撤销, 6 s, bottom centre */
#gc-bar{position:fixed;left:50%;bottom:calc(20px + env(safe-area-inset-bottom,0px));transform:translate(-50%,16px);opacity:0;pointer-events:none;z-index:61;
  display:flex;align-items:center;gap:12px;min-width:min(340px,calc(100% - 32px));max-width:calc(100% - 32px);padding:10px 8px 10px 16px;border-radius:12px;
  background:#1d1b18;color:#ece8e1;box-shadow:0 8px 24px rgba(0,0,0,.3);overflow:hidden;transition:opacity .2s ease-out,transform .2s ease-out}
#gc-bar.show{opacity:1;transform:translate(-50%,0);pointer-events:auto}
#gc-bar .grow{flex:1;min-width:0}
#gc-bar b{display:block;font-size:14px;font-weight:600}
#gc-bar small{display:block;font-size:12px;color:#b9b2a7}
#gc-bar button{flex:none;min-height:40px;padding:0 14px;border-radius:9px;font-weight:700;font-size:14px;color:#f4c05a}
#gc-bar button:hover{background:rgba(255,255,255,.08)}
#gc-bar .gc-timer{position:absolute;left:0;bottom:0;height:2px;background:#f4c05a;width:100%;transform-origin:left}
#gc-bar.show .gc-timer{animation:gc-timer var(--gc-bar-ms,6s) linear forwards}   /* phase 24 (C): no-show keeps its undo 10 s */
@keyframes gc-timer{to{transform:scaleX(0)}}
@media (prefers-color-scheme:dark){#gc-bar{background:#3a3733}}

/* ---------- phase 17 (item 4): the status glyph has its own place ----------
   The block: [staff-colour edge] name ……… ● / service / time (balance). The glyph sits at the end of the name line, in the status
   colour (DESIGN.md: one meaning per colour, always with its glyph), so it never covers the name; the old absolute badge is gone. */
:root{--st-ok:#1b6f3f;--st-wait:#8f5300;--st-call:#b3261e;--st-busy:#2457a8;--st-done:#64605a}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--st-ok:#6cc08b;--st-wait:#e2a24a;--st-call:#ef7b73;--st-busy:#8ab8ee;--st-done:#a39d93}}
:root[data-theme="dark"]{--st-ok:#6cc08b;--st-wait:#e2a24a;--st-call:#ef7b73;--st-busy:#8ab8ee;--st-done:#a39d93}
.gc .cal-bk>span.nm{display:flex;align-items:center;gap:4px;min-width:0;overflow:hidden}
.gc .cal-bk .nm>b{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:650;display:block}
.gc .cal-bk .nm>.t{flex:none}
.gc .cal-bk .gc-st{position:static;width:auto;flex:none;display:inline-flex;align-items:center;justify-content:center;min-width:19px;height:18px;padding:0 4px;border-radius:999px;font-style:normal;font-size:11.5px;font-weight:800;line-height:1;letter-spacing:-.04em;
  color:var(--stk);background:color-mix(in srgb,var(--stk) 16%,var(--surface));box-shadow:0 0 0 1px color-mix(in srgb,var(--stk) 45%,transparent)}
.gc-st.st-sent{--stk:var(--st-done)}.gc-st.st-none{--stk:var(--line)}.gc-st.st-ok{--stk:var(--st-ok)}.gc-st.st-wait{--stk:var(--st-wait)}.gc-st.st-call{--stk:var(--st-call)}.gc-st.st-busy{--stk:var(--st-busy)}.gc-st.st-done{--stk:var(--st-done)}
.gc .cal-bk .sv .mk{font-size:9px;opacity:.85}
.gc .cal-bk>span.t{display:flex;align-items:center;gap:4px}
.gc .cal-bk>span.t .co-chipbal{position:static;margin-left:auto;flex:none}
.gc .cal-bk.short>span.nm{display:inline-flex;flex:0 1 auto}
.gc .cal-bk.short>span.sv{display:none}
.gc .cal-bk.short>span.t{display:inline-flex}
.gc .cal-bk.short .co-chipbal{display:none}
.gc .cal-bk.compact>span.nm{display:flex}
.gc .cal-bk.compact .nm>b{font-size:10px;font-weight:600}
.gc .cal-bk.compact .gc-st{min-width:15px;height:15px;font-size:9.5px;padding:0 3px}
.gc .cal-bk.noshow .nm>b{text-decoration:line-through}

/* ---------- phase 17 (item 7): the month grid ---------- */
.gm{background:var(--surface);border:1px solid var(--line);border-radius:12px;overflow:hidden;margin-top:10px}
.gm-head,.gm-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr))}
.gm-dow{font-size:12px;font-weight:600;color:var(--muted);text-align:center;padding:6px 0;border-bottom:1px solid var(--line)}
.gm-day{min-height:118px;border-right:1px solid var(--line);border-bottom:1px solid var(--line);padding:3px 3px 4px;display:flex;flex-direction:column;gap:2px;min-width:0;cursor:pointer;position:relative}
.gm-day:nth-child(7n){border-right:0}
.gm-day.out{background:color-mix(in srgb,var(--surface-2) 45%,var(--surface))}
.gm-day.out .gm-num{color:var(--faint)}
.gm-day.closed{background-image:repeating-linear-gradient(135deg,transparent 0 6px,color-mix(in srgb,var(--line) 45%,transparent) 6px 7px)}
.gm-num{align-self:center;min-width:28px;height:28px;border-radius:999px;font-size:13px;font-weight:600;display:inline-flex;align-items:center;justify-content:center;font-variant-numeric:tabular-nums}
.gm-num:hover{background:var(--surface-2)}
.gm-day.today .gm-num{background:var(--danger);color:#fff}
.gm-ev{display:flex;align-items:center;gap:4px;min-width:0;width:100%;text-align:left;font-size:11.5px;line-height:1.25;padding:2px 4px;border-radius:5px;touch-action:pan-y}
.gm-ev:hover{background:var(--surface-2)}
.gm-ev .gm-dot{flex:none;width:7px;height:7px;border-radius:50%;background:var(--stc)}
.gm-ev .t{flex:none;color:var(--muted);font-variant-numeric:tabular-nums}
.gm-ev b{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}
.gm-ev .gc-st{position:static;width:auto;flex:none;min-width:16px;height:15px;font-size:9.5px;padding:0 3px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;font-style:normal;font-weight:800;
  color:var(--stk);background:color-mix(in srgb,var(--stk) 16%,var(--surface));box-shadow:0 0 0 1px color-mix(in srgb,var(--stk) 45%,transparent)}
.gm-ev.noshow b{text-decoration:line-through;color:var(--muted)}
.gm-ev.completed{opacity:.7}
.gm-ev.gc-mv{cursor:grab}
.gm-ev.gc-lifted{opacity:.35}
.gm-more{font-size:11.5px;font-weight:600;color:var(--muted);text-align:left;padding:1px 4px;border-radius:5px}
.gm-more:hover{background:var(--surface-2);color:var(--fg)}
.gm-day.gm-drop{box-shadow:inset 0 0 0 2px var(--accent)}
.gm-day.gm-bad{box-shadow:inset 0 0 0 2px var(--danger)}
.gm-day.gm-bad::after{content:attr(data-why);position:absolute;left:2px;right:2px;bottom:2px;font-size:10px;color:var(--danger);background:var(--surface);border-radius:4px;padding:1px 3px;z-index:2}
/* phones: a narrower cell shows the dot and the name; the week button gives way to month (Day · 3 days · Month) */
@media (max-width:600px){
  .gm-day{min-height:76px;padding:2px 1px}
  .gm-ev{padding:1px 2px;font-size:10px;gap:2px}
  .gm-ev .t,.gm-ev .gc-st{display:none}
  .gm-more{font-size:10px;padding:0 2px}
  .gc-views [data-view="week"]{display:none}
}
/* phase 17: the client's signals on a block */
.gc-sig{flex:none;font-style:normal;font-size:9.5px;font-weight:800;line-height:15px;height:15px;padding:0 4px;border-radius:999px;color:#fff;font-variant-numeric:tabular-nums}
.gc-sig.late{background:var(--st-wait)}
.gc-sig.move{background:var(--st-busy)}
.gm-ev .gc-sig{font-size:8px;line-height:12px;height:12px;padding:0 3px}

/* ---------- phase 22 (B1): a card is whole lines, one marker, nothing on top of the name ----------
   (#gc-cal.gc … outranks the older #gc-cal rules in ui-x-wide.css and the absolute balance pill in ui-x-checkout.css) */
#gc-cal.gc .cal-bk>span.nm{overflow:hidden;gap:calc(4px*var(--gc-fs,1))}
#gc-cal.gc .cal-bk .nm>b{flex:1 1 auto}
#gc-cal.gc .cal-bk .nm>.gc-st,#gc-cal.gc .cal-bk .nm>.gc-sig{flex:none;margin-left:auto}
#gc-cal.gc .cal-bk>span.t{display:flex;align-items:center;gap:calc(4px*var(--gc-fs,1));overflow:hidden;white-space:nowrap}
#gc-cal.gc .cal-bk>span.t .tt{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums}
#gc-cal.gc .cal-bk>span.t .gc-x{flex:none;font-size:calc(10px*var(--gc-fs,1));line-height:1}
#gc-cal.gc .cal-bk>span.t>.gc-xs{flex:none;margin-left:auto;display:inline-flex;align-items:center;gap:2px}
#gc-cal.gc .cal-bk .co-chipbal.gc-bal{position:static;flex:none;margin-left:auto;display:inline-flex;align-items:center;gap:2px;padding:0;background:none;box-shadow:none;border-radius:0;--bal-c:var(--fg);
  font-size:calc(10.5px*var(--gc-fs,1));font-weight:600;line-height:1;color:var(--fg);font-variant-numeric:tabular-nums}
#gc-cal.gc .cal-bk>span.t>.gc-xs~.gc-bal{margin-left:4px}
#gc-cal.gc .cal-bk .gc-bal.owing{color:var(--st-call)}
#gc-cal.gc .cal-bk .gc-bal.pkg{color:var(--st-busy)}
.gc-bal-ic{width:calc(12px*var(--gc-fs,1));height:calc(11px*var(--gc-fs,1));flex:none}
/* the not-checked-out marker: a small amber dot in the marker's place (it was a wide "Not checked out" pill) */
#gc-cal.gc .cal-bk .gc-st.co-nco,.gc-legend .gc-st.co-nco,.gm .gc-st.co-nco,.gc-pop .gc-st.co-nco{display:inline-flex;padding:0;font-size:inherit;color:var(--st-wait);background:color-mix(in srgb,var(--st-wait) 16%,var(--surface));box-shadow:0 0 0 1px color-mix(in srgb,var(--st-wait) 45%,transparent)}
.gc-st.co-nco .gc-mk{color:var(--st-wait)}
/* paid: a solid green ✓ (the outlined grey ✓ is "text delivered") */
.gc-st.st-paid{--stk:var(--st-ok)}
#gc-cal.gc .cal-bk .gc-st.st-paid,.gm .gc-st.st-paid,.gc-legend .gc-st.st-paid,.gc-pop .gc-st.st-paid{background:var(--st-ok);color:var(--surface);box-shadow:none}
/* a narrow card: the balance and the extras go (they are on hover and in the sheet) */
@container (max-width:170px){#gc-cal.gc .cal-bk>span.t>.co-chipbal.gc-bal,#gc-cal.gc .cal-bk>span.t>.gc-xs{display:none}}
#gc-cal.gc .cal-bk>span.t .tt{flex:none}

/* ---------- phase 22 (B2): the month fills the window, Google's way ---------- */
.gm{display:flex;flex-direction:column;margin-top:6px}
.gm .gm-head{flex:none}
.gm .gm-grid{flex:1 1 auto;min-height:0}
.gm .gm-day{min-height:0;overflow:hidden;padding:4px 4px 3px;gap:2px}
.gm .gm-num{flex:none;min-width:calc(26px*var(--gm-fs,1));height:calc(26px*var(--gm-fs,1));font-size:calc(12.5px*var(--gm-fs,1));margin-bottom:2px}
.gm .gm-ev{flex:none;height:calc(18px*var(--gm-fs,1));font-size:calc(11.5px*var(--gm-fs,1));padding:0 4px}
.gm .gm-more{flex:none;height:calc(18px*var(--gm-fs,1));font-size:calc(11.5px*var(--gm-fs,1));padding:0 4px;line-height:1}
.gm .gm-dow{font-size:calc(11.5px*var(--gm-fs,1));text-transform:uppercase;letter-spacing:.02em}
.gm .gm-day.sel:not(.today) .gm-num{box-shadow:inset 0 0 0 1.5px var(--line)}
.gm .gm-day.out{background:color-mix(in srgb,var(--surface-2) 35%,var(--surface))}
.gm .gm-day.out .gm-ev{opacity:.6}
.gm .gm-ev .gc-st{margin-left:auto}
/* a phone: dots, the whole day is the button */
.gm.gm-ph .gm-day{padding:2px 1px;align-items:center}
.gm.gm-ph .gm-num{min-width:24px;height:24px;font-size:12px;margin-bottom:1px}
.gm-dots{display:flex;flex-wrap:wrap;justify-content:center;gap:3px;padding:0 3px;max-width:100%}
.gm-dots i{width:6px;height:6px;border-radius:50%;background:var(--stc)}
.gm-dots b{font-size:9.5px;font-weight:700;color:var(--muted);line-height:6px}

/* ---------- phase 22: Google's small cards (#gc-pop) ---------- */
.gc-pop{position:fixed;z-index:70;min-width:220px;max-width:min(340px,calc(100vw - 16px));max-height:min(70vh,520px);overflow:auto;padding:10px;border-radius:14px;
  background:var(--surface);color:var(--fg);box-shadow:0 0 0 1px var(--line),0 12px 32px rgba(0,0,0,.28);animation:gc-pop .12s ease-out}
@keyframes gc-pop{from{opacity:0;transform:scale(.97)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.gc-pop{animation:none}}
.gc-pop-h{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.gc-pop-h .dw{font-size:11.5px;font-weight:700;color:var(--muted);text-transform:uppercase}
.gc-pop-x{margin-left:auto;width:32px;height:32px;min-height:32px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;color:var(--muted)}
.gc-pop-x:hover{background:var(--surface-2)}
.gm-num.big{min-width:40px;height:40px;border-radius:50%;font-size:20px;font-weight:600;display:inline-flex;align-items:center;justify-content:center}
.gm-num.big:hover{background:var(--surface-2)}
.gm-num.big.today{background:var(--danger);color:var(--on-danger,#fff)}
.gc-pop-day{width:260px}
.gc-pop-list{display:flex;flex-direction:column;gap:2px}
.gc-pop-list .gm-ev{height:28px;font-size:13px;padding:0 6px}
#sheet-body .gc-pop-list .gm-ev{height:44px;font-size:15px}
#sheet-body .gc-pop-h .gm-num.big{min-width:44px;height:44px}
.gc-pop-list .gm-ev .gc-st{margin-left:auto}
/* the Create menu */
.gc-pop-menu{min-width:180px;padding:6px}
.gc-menu-list{display:flex;flex-direction:column}
.gc-menu-list button{text-align:left;min-height:40px;padding:0 12px;border-radius:8px;font-size:14px;font-weight:500}
.gc-menu-list button:hover,.gc-menu-list button:focus-visible{background:var(--surface-2)}
/* the split + Book ▾ */
.gc-create{display:inline-flex;align-items:stretch;gap:1px}
.gc-create .gc-new{border-radius:999px 0 0 999px}
.gc-create .gc-caret{border-radius:0 999px 999px 0;width:34px;min-width:34px;padding:0;display:inline-flex;align-items:center;justify-content:center}
/* the quick create */
.gc-pop-qc{width:320px}
.gc-qc-when{font-size:13px;min-width:0}
.gc-qc-when b{font-size:15px;margin-right:4px}
.gc-qc{display:flex;flex-direction:column;gap:8px}
.gc-qc-who{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.gc-qc .input{min-height:40px;font-size:15px}
.gc-qc-sug{display:flex;flex-direction:column}
.gc-qc-sug:empty{display:none}
.gc-qc-hit{display:flex;justify-content:space-between;gap:8px;min-height:34px;padding:0 8px;border-radius:8px;font-size:13.5px;text-align:left;align-items:center}
.gc-qc-hit:hover{background:var(--surface-2)}
.gc-qc-hit span{color:var(--muted)}
.gc-qc-acts{display:flex;justify-content:flex-end;gap:8px}
.gc-qc-ph{opacity:.9;pointer-events:none}

/* ---------- phase 22 (B3): the left rail and its mini month ---------- */
.gc-2col{display:grid;grid-template-columns:216px minmax(0,1fr);gap:20px;align-items:start}
.gc-rail{position:sticky;top:12px;padding-top:4px}
.mm-h{display:flex;align-items:center;gap:2px;margin:0 0 6px 6px}
.mm-h b{flex:1;font-size:14px;font-weight:600}
.mm-arrow{width:30px;height:30px;min-height:30px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center}
.mm-arrow .nav-ic{width:18px;height:18px}
.mm-arrow:hover{background:var(--surface-2)}
.mm-g{display:grid;grid-template-columns:repeat(7,1fr);row-gap:2px;text-align:center}
.mm-w{font-size:10.5px;font-weight:600;color:var(--muted);line-height:22px}
.mm-d{position:relative;height:28px;min-height:28px;width:28px;justify-self:center;border-radius:50%;font-size:11.5px;font-weight:500;font-variant-numeric:tabular-nums;display:inline-flex;align-items:center;justify-content:center;padding:0}
.mm-d:hover span{background:var(--surface-2)}.mm-d.today:hover span{background:var(--danger)}
.mm-d.out{color:var(--faint)}
.mm-d.sel{background:color-mix(in srgb,var(--accent) 18%,transparent);font-weight:700;width:100%;border-radius:0}
.mm-d.sel.sa{border-radius:14px 0 0 14px}.mm-d.sel.sz{border-radius:0 14px 14px 0}.mm-d.sel.sa.sz{border-radius:14px}
.mm-d span{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:50%}
.mm-d.today span{background:var(--danger);color:var(--on-danger,#fff);font-weight:700}
.mm-d.has::after{content:"";position:absolute;bottom:2px;left:50%;width:4px;height:4px;margin-left:-2px;border-radius:50%;background:var(--accent)}
.mm-d.today.has::after{background:var(--on-danger,#fff)}

/* ---------- phase 22 (B3): column heads, Google's way — small weekday, big date, today circled; the count is a number ---------- */
#gc-cal .cal-col.wk .ch{height:auto;min-height:calc(56px*var(--gc-fs,1));padding:4px 2px}
#gc-cal .cal-col.wk .ch .dw{font-size:calc(11px*var(--gc-fs,1));letter-spacing:.02em}
#gc-cal .cal-col.wk .ch .dn{font-size:calc(22px*var(--gc-fs,1));font-weight:500;width:calc(36px*var(--gc-fs,1));height:calc(36px*var(--gc-fs,1));border-radius:50%}
#gc-cal .cal-col.wk .ch:hover .dn{background:var(--surface-2)}
#gc-cal .cal-col.wk.today .ch .dn{background:var(--danger);color:var(--on-danger,#fff)}
#gc-cal .cal-gutter .gh{height:auto;min-height:calc(56px*var(--gc-fs,1))}
.gc-week #gc-cols .ch,.gc-3day #gc-cols .ch{box-sizing:border-box}
#gc-cal .cal-col .ch .gc-n{margin-left:auto;flex:none;min-width:22px;height:20px;padding:0 6px;border-radius:999px;background:var(--surface-2);color:var(--muted);font-size:calc(11.5px*var(--gc-fs,1));font-weight:700;display:inline-flex;align-items:center;justify-content:center;font-variant-numeric:tabular-nums}
@media (max-width:600px){#gc-cal .cal-col.wk .ch .dn{font-size:17px;width:28px;height:28px}#gc-cal .cal-col.wk .ch{min-height:50px}#gc-cal .cal-gutter .gh{min-height:50px}}
#gc-cal.gc .cal-bk .co-chipbal.gc-bal{align-self:center}
#gc-cal.gc .cal-bk .nm>.gc-gift{flex:none;margin-left:auto;font-size:calc(10px*var(--gc-fs,1));line-height:1;white-space:nowrap}
.gc-leg-row>.gc-st.co-nco{margin-left:0}
.gc-pop-list .gm-ev .t,#sheet-body .gc-pop-list .gm-ev .t{display:inline}.gc-pop-list .gm-ev .gc-st,#sheet-body .gc-pop-list .gm-ev .gc-st{display:inline-flex}

/* import from Fresha / Excel (phase 06): kind picker, step strip, column mapping, dry-run tiles, lists */
.im-steps{display:flex;gap:4px;margin:4px 0 10px;flex-wrap:wrap}
.im-steps span{font-size:11px;font-weight:700;padding:2px 9px;border-radius:999px;background:var(--surface-2);color:var(--muted)}
.im-steps span.cur{background:var(--brand);color:var(--brand-ink)}
.im-steps span.done{background:color-mix(in srgb,var(--ok) 14%,var(--surface));color:var(--ok)}
.im-kinds{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.im-kind{display:flex;flex-direction:column;align-items:flex-start;gap:2px;text-align:left;padding:10px 12px;border:1px solid var(--line);border-radius:12px;background:var(--surface);color:var(--fg);min-height:44px}
.im-kind .ic{font-size:20px}
.im-kind b{font-size:14px}
.im-kind small{font-size:11px;color:var(--muted);line-height:1.35}
.im-kind.on{border-color:var(--brand);background:var(--brand-soft)}
.im-file{display:flex;flex-direction:column;gap:8px;margin-top:10px}
.im-file .btn{cursor:pointer}
.im-cols{display:flex;flex-direction:column;gap:6px}
.im-col{display:flex;align-items:center;gap:8px;padding:8px 10px;border:1px solid var(--line);border-radius:10px;background:var(--surface)}
.im-col .ttl{font-size:13px;font-weight:600}
.im-col .sub{font-size:11px;color:var(--muted)}
.im-col select{width:150px;flex:none}
.im-col.unknown{border-color:color-mix(in srgb,var(--warn) 50%,var(--line));background:color-mix(in srgb,var(--warn) 7%,var(--surface))}
.im-stats{margin:8px 0}
.im-list .item{min-height:0;padding:8px 0}
.im-locs{display:flex;flex-direction:column;gap:4px}
.im-card{display:flex;align-items:center;gap:8px;margin-top:6px}
.im-card select{width:170px;flex:none}
.im-newtpl{padding:12px 14px;margin-top:8px;display:flex;flex-direction:column;gap:8px}
.im-rooms{display:flex;flex-wrap:wrap;gap:4px 10px;width:100%;margin-top:4px}
.im-rooms .check{font-size:12px;min-height:0}
.im-sec{padding:12px 14px;border-radius:12px;background:var(--surface-2)}
.linkbtn{background:none;border:0;padding:0;color:var(--accent);font-size:inherit;text-decoration:underline;cursor:pointer}
@media (max-width:480px){.im-col{flex-wrap:wrap}.im-col select{width:100%}.im-card{flex-wrap:wrap}.im-card select{width:100%}}

/* phase 22 (A5, A8): one importer look (ui-x-importer.js) — the client import's design, shared by the services import */
.sheet:has(.imx-steps){width:100%;max-width:min(1240px,calc(100vw - 24px))}
.imx-steps{display:flex;align-items:center;gap:6px;list-style:none;margin:0;padding:0;font-size:13px;color:var(--faint)}
.imx-steps li.cur{color:var(--fg);font-weight:700}
.imx-steps li.done{color:var(--muted)}
.imx-title{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;min-width:0}
.imx-title .small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}
.imx-chips{display:flex;flex-wrap:wrap;gap:8px}
.imx-chip{display:inline-flex;align-items:center;min-height:44px;border:1px solid var(--line);border-radius:999px;background:var(--surface);padding:0 4px 0 2px}
.imx-chip.sel{border-color:var(--brand);background:var(--brand-soft)}
.imx-chip.info{border-style:dashed}
.imx-chip.off .imx-lbl{color:var(--muted)}
.imx-chip.warn .imx-lbl b{color:var(--warn)}
.imx-lbl{display:inline-flex;align-items:center;gap:6px;min-height:42px;padding:0 12px 0 10px;background:none;border:0;color:var(--fg);font-weight:600;font-size:14px;white-space:nowrap;cursor:pointer}
.imx-chip:has(.imx-tick) .imx-lbl{padding-left:2px}
.imx-lbl b{font-weight:700}
.imx-tick{flex:none;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;background:none;border:0;padding:0;cursor:pointer;color:var(--brand-ink)}
.imx-tick i{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:6px;border:2px solid var(--line);background:var(--surface);font-style:normal;font-size:14px;font-weight:800;line-height:1}
.imx-tick.on i{background:var(--brand);border-color:var(--brand);color:var(--brand-ink)}
.imx-tick.ro{cursor:default;opacity:.55}
.imx-tick:focus-visible{outline:2px solid var(--brand);outline-offset:-4px;border-radius:10px}
.imx-tools{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
.imx-tools input[type=search]{flex:1 1 220px;max-width:340px;min-height:44px}
.imx-tools .grow{flex:1}
.imx-since{display:inline-flex;align-items:center;gap:6px}
.imx-since select{min-height:44px;width:auto}
.imx-table{position:relative;border:1px solid var(--line);border-radius:12px;overflow:hidden;background:var(--surface)}
.imx-tr{display:grid;grid-template-columns:var(--imx-cols);column-gap:10px;align-items:center;height:44px;padding:0 10px 0 2px;border-bottom:1px solid var(--line);box-sizing:border-box}
.imx-th{height:38px;font-size:12px;font-weight:600;color:var(--muted);background:var(--surface-2)}
.imx-th>span{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;padding:0 7px}
.imx-body{position:relative;max-height:clamp(320px,calc(100dvh - 400px),2400px);overflow-y:auto;overflow-anchor:none;overscroll-behavior:contain}
.imx-win{position:absolute;top:0;left:0;right:0}
.imx-win>.imx-tr{position:absolute;left:0;right:0}
.imx-td{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;padding:5px 6px;border:1px solid transparent;border-radius:7px;line-height:1.35}
.imx-td[contenteditable=true]:hover{border-color:var(--line)}
.imx-td:focus{outline:0;border-color:var(--brand);background:var(--card);text-overflow:clip}
.imx-td.b{font-weight:600}
.imx-td.num,.imx-lbl .num{font-variant-numeric:tabular-nums}
.imx-td.bad{color:var(--danger)}
.imx-td.shared{color:var(--muted)}
.imx-th .c-blk{color:var(--muted)}
.imx-td.rec{color:var(--muted);font-size:13px}
.c-st{display:flex;padding:0 6px}
.c-st .chip{max-width:100%;overflow:hidden;text-overflow:ellipsis}
.imx-tr.off>.imx-td{opacity:.5}
.imx-ghost{background:linear-gradient(90deg,transparent,var(--surface-2) 30%,transparent 70%)}
.imx-table .empty{padding:18px;text-align:center}
.imx-foot{position:sticky;bottom:calc(-20px - env(safe-area-inset-bottom,0px));z-index:3;display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;margin:0 -18px -20px;padding:10px 18px calc(12px + env(safe-area-inset-bottom,0px));background:var(--surface);border-top:1px solid var(--line)}
.imx-foot .row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.imx-foot .btn{min-height:44px}
.linkbtn{background:none;border:0;padding:0 2px;color:var(--accent);font-weight:600;font-size:inherit;cursor:pointer;text-decoration:underline;text-underline-offset:2px}
/* a phone: one card per row, the same fields in the same order (tick · status · name / mobile · email / record · notes) */
@media (max-width:760px){
  .imx-th{display:none}
  .imx-tr{height:118px;grid-template-columns:40px auto minmax(0,1fr) minmax(0,1fr);grid-template-rows:38px 36px 36px;grid-template-areas:"tick st name x" ". phone phone email" ". rec rec notes";column-gap:6px;row-gap:0;padding:4px 8px 4px 0;align-items:center}
  .imx-tr>.imx-tick{grid-area:tick}.imx-tr>.c-st{grid-area:st;padding:0}.imx-tr>.c-name{grid-area:name}.imx-tr>.c-phone{grid-area:phone}.imx-tr>.c-email{grid-area:email}
  .imx-tr>.c-recordNo{grid-area:rec}.imx-tr>.c-notes{grid-area:notes}.imx-tr>.c-bal,.imx-tr>.c-blk{grid-area:x;justify-self:end}.imx-tr>.c-blk:empty{display:none}
  .imx-tr>.c-name{grid-column:name-start/x-end}
  .imx-body{max-height:max(300px,calc(100dvh - 330px))}
  .imx-tools input[type=search]{max-width:none;flex-basis:100%}
  .imx-chips{flex-wrap:nowrap;overflow-x:auto;margin:0 -18px;padding:0 18px 2px;scrollbar-width:none}
  .imx-chips::-webkit-scrollbar{display:none}
  .imx-chip{flex:none}
  .imx-tools .grow{display:none}
  .imx-since>span{display:none}
  .imx-since select{max-width:132px}
  .imx-tools .btn.ghost{padding:0 8px}
}
/* the services import: its cells are inputs */
.svi-r .imx-td{padding:0;overflow:visible;border:0}
.svi-r .input{width:100%;min-height:36px;padding:4px 8px;font-size:14px}
.svi-r .input.num{font-variant-numeric:tabular-nums;text-align:right}
.svi-r .input.guess{border-style:dashed;font-style:italic}
.svi-r .input.err{border-color:var(--danger)}
.imx-tools .svi-bulkcat{width:180px;min-height:44px}
@media (max-width:760px){
  .svi-r{grid-template-areas:"tick st cat cat cat" ". name name name name" ". nameEn nameEn dur price"}
  .svi-r>.c-cat{grid-area:cat}.svi-r>.c-name{grid-area:name}.svi-r>.c-nameEn{grid-area:nameEn}.svi-r>.c-dur{grid-area:dur}.svi-r>.c-price{grid-area:price}
  .svi-r{grid-template-columns:40px auto minmax(0,1fr) 72px 80px}
  .svi-r .input{font-size:16px}
  .imx-tools .svi-bulkcat{flex:1 1 0;width:auto;min-width:0}
}
.imx-dl{width:44px;min-height:44px;padding:0;font-size:18px}

/* ---------- phase 20 review (8): less text — the booking page's opening hours fold under their title ---------- */
.c-hours>summary{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;min-height:24px}
.c-hours>summary::-webkit-details-marker{display:none}
.c-hours>summary::after{content:"";width:8px;height:8px;border-right:1.6px solid currentColor;border-bottom:1.6px solid currentColor;transform:rotate(45deg) translate(-2px,-2px);opacity:.7}
.c-hours[open]>summary::after{transform:rotate(-135deg)}
.svc .tick svg{display:block}

/* phase 24: a link never breaks across lines (at 768 the second one wrapped mid-link and its box lay over the first) */
.sec-links a{display:inline-block}

/* ---------- phase 18 (B11): Services as a menu — categories in a column on the left (a chip row on a phone), search, staff ---------- */
.menu-toolbar{gap:8px;flex-wrap:wrap}
.menu{display:grid;grid-template-columns:minmax(0,1fr);gap:12px}
.menu-main,.menu-cats{min-width:0}
.menu-cats{display:flex;gap:8px;overflow-x:auto;scrollbar-width:none;padding:2px 0 6px}
.menu-cats::-webkit-scrollbar{display:none}
.menu-cat{flex:none;display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:0 14px;border-radius:999px;border:1px solid var(--line);background:var(--surface);font-weight:600;font-size:14px;color:var(--fg);white-space:nowrap}
.menu-cat .cnt{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums}
.menu-cat.on{background:var(--brand);border-color:var(--brand);color:var(--brand-ink)}
.menu-cat.on .cnt{color:var(--brand-ink)}
.menu-tools{display:flex;flex-direction:column;gap:8px;margin-bottom:10px}
.menu-tools input[type=search]{min-height:44px}
.menu-staff{padding-bottom:2px}
.menu-staff .chipbtn{min-height:40px}
.menu-sec{margin-bottom:14px}
.menu-h{font-size:13px;font-weight:700;color:var(--muted);margin:4px 2px 6px}
.menu-card{padding:0;overflow:hidden}
.menu-row{display:flex;align-items:center;gap:12px;width:100%;min-height:60px;padding:10px 16px;border-bottom:1px solid var(--line);text-align:left;color:var(--fg)}
.menu-row:last-child{border-bottom:0}
.menu-row:hover{background:var(--surface-2)}
.menu-row .n{display:block;font-weight:650;font-size:15px}
.menu-row .sub{display:block;font-size:13px;color:var(--muted);margin-top:2px}
.menu-row .p{font-weight:700;font-size:15px}
.menu-row.off .n{color:var(--muted)}
@media (min-width:760px){
  .menu{grid-template-columns:200px minmax(0,1fr);align-items:start}
  .menu-cats{flex-direction:column;overflow:visible;position:sticky;top:12px;padding:0}
  .menu-cat{border-radius:10px;border-color:transparent;background:transparent;min-height:42px;padding:0 12px}
  .menu-cat:hover{background:var(--surface-2)}
  .menu-cat.on{background:var(--brand-soft);color:var(--accent);border-color:transparent}
  .menu-cat.on .cnt{color:var(--accent)}
  .menu-tools{flex-direction:row;align-items:center;flex-wrap:wrap}
  .menu-tools input[type=search]{max-width:300px}
}
/* the editor: staff as avatars to tap, the online switch */
.staff-togs{display:flex;flex-wrap:wrap;gap:8px}
.staff-tog{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:0 14px 0 6px;border-radius:999px;border:1px solid var(--line);background:var(--surface);font-weight:600;cursor:pointer}
.staff-tog input{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none}
.staff-tog:has(input:checked){background:var(--brand-soft);border-color:var(--brand);color:var(--accent)}
.staff-tog:has(input:checked)::after{content:"✓";font-weight:800}
.staff-tog:has(input:focus-visible){outline:2px solid var(--accent);outline-offset:2px}
.switch-row{display:flex;align-items:center;gap:12px;min-height:52px;padding:4px 0;font-weight:600;cursor:pointer}
/* A5: one checkbox and one switch everywhere (the shop's screenshot had small native boxes next to large ones) */
input[type=checkbox]:not(.switch):not([role=switch]):not([hidden]){-webkit-appearance:none;appearance:none;flex:none;width:22px;height:22px;margin:0;border-radius:6px;border:2px solid var(--muted);background:var(--surface);display:inline-grid;place-content:center;cursor:pointer;vertical-align:middle}
input[type=checkbox]:not(.switch):not([role=switch]):checked{background:var(--brand);border-color:var(--brand)}
input[type=checkbox]:not(.switch):not([role=switch]):checked::before{content:"";width:6px;height:11px;border:solid var(--brand-ink);border-width:0 2.5px 2.5px 0;transform:translateY(-1px) rotate(45deg)}
input[type=checkbox]:not(.switch):not([role=switch]):disabled{opacity:.45;cursor:not-allowed}
input.switch,input[type=checkbox][role=switch]{-webkit-appearance:none;appearance:none;flex:none;width:50px;height:30px;margin:0;border-radius:999px;background:var(--line);position:relative;cursor:pointer;transition:background .15s}
input.switch::before,input[type=checkbox][role=switch]::before{content:"";position:absolute;top:3px;left:3px;width:24px;height:24px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.25);transition:transform .15s}
input.switch:checked,input[type=checkbox][role=switch]:checked{background:var(--brand)}
input.switch:checked::before,input[type=checkbox][role=switch]:checked::before{transform:translateX(20px)}
.check{display:flex;align-items:center;gap:10px;min-height:44px}
/* one short helper line where a screen needs one (DESIGN.md rule 11); the ⓘ is gone */
.hint{font-size:13px;color:var(--muted);margin:4px 0 0}
/* A3: the import sheet */
.svi-table{display:flex;flex-direction:column;gap:6px;margin:10px 0;max-height:60vh;overflow:auto}
.svi-tr{display:grid;grid-template-columns:28px minmax(80px,1fr) minmax(110px,1.6fr) minmax(110px,1.6fr) 70px 80px 58px;gap:6px;align-items:center}
.svi-th{font-size:12px;font-weight:700;color:var(--muted);position:sticky;top:0;background:var(--surface);z-index:1;padding:4px 0}
.svi-tr .input{min-height:38px;padding:6px 8px;font-size:14px}
.svi-tr.off .input{opacity:.5}
.svi-notes{grid-column:2/-1;font-size:12px;color:var(--warn);margin-top:-2px}
.svi-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;position:sticky;bottom:0;background:var(--surface);padding-top:8px}
@media (max-width:700px){.svi-tr{grid-template-columns:28px 1fr 1fr;}.svi-th{display:none}.svi-tr>span:nth-child(n+5){grid-column:auto}.svi-tr{padding:8px 0;border-bottom:1px solid var(--line)}}
.sheet-wrap .sheet:has(.svi-table){max-width:min(1040px,96vw);width:100%}
/* B13: "what you typed last time is back · Discard" */
.sd-bar{display:flex;align-items:center;gap:10px;padding:8px 12px;margin:6px 0 12px;border-radius:10px;background:var(--brand-soft);font-size:13px;font-weight:600}
.sd-bar .lnk{color:var(--danger);font-weight:700;background:none;border:0;min-height:32px}
.menu-row>.grow{flex:1 1 auto;min-width:0}
input.switch:disabled,input[type=checkbox][role=switch]:disabled{opacity:.45;cursor:not-allowed}
/* phase 20 (B): a long menu folds each category to one row with its count; the Categories sheet */
.menu-h .cnt{font-weight:600;margin-left:4px}
.menu-fold{display:flex;align-items:center;gap:10px;width:100%;min-height:52px;padding:0 16px;border:1px solid var(--line);border-radius:14px;background:var(--card);color:var(--fg);font-weight:650;font-size:15px;text-align:left}
.menu-fold .cnt{color:var(--muted);font-size:13px}
.menu-fold .chev{transition:transform .15s}
.menu-fold.on{border-radius:14px 14px 0 0;border-bottom-color:transparent}
.menu-fold.on .chev{transform:rotate(90deg)}
.menu-fold.on+.menu-card{border-top-left-radius:0;border-top-right-radius:0}
.menu-sec:has(.menu-fold){margin-bottom:8px}
.cat-list{padding:0;overflow:hidden}
.cat-row{display:flex;align-items:center;gap:4px;min-height:52px;padding:0 8px 0 0;border-bottom:1px solid var(--line)}
.cat-row:last-child{border-bottom:0}
.cat-open{display:block;min-height:52px;padding:8px 16px;text-align:left;color:var(--fg);background:none;border:0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cat-row .btn{min-width:40px}
/* phase 20 (B): the import preview grouped by category, with a search, a selection and one bar to set the category of many rows */
.svi-tools{display:flex;gap:8px;align-items:center;margin-top:8px}
.svi-tools input[type=search]{max-width:320px;min-height:40px}
.svi-bulk{display:flex;flex-wrap:wrap;align-items:center;gap:8px;position:sticky;top:0;z-index:2;margin:8px 0;padding:8px 10px;border-radius:12px;background:var(--brand-soft)}
.svi-bulk .input{width:180px;min-height:38px}
.svi-group{display:flex;flex-direction:column;gap:6px;padding-bottom:6px;border-bottom:1px solid var(--line)}
.svi-gh{display:flex;align-items:center;gap:8px;min-height:44px;position:sticky;top:30px;background:var(--surface);z-index:1}
.svi-gname{display:flex;align-items:center;gap:6px;min-height:44px;text-align:left;background:none;border:0;color:var(--fg);padding:0}
.svi-gname .chev{margin-left:auto;transition:transform .15s}
.svi-gname .chev.on{transform:rotate(90deg)}
.svi-tr.sel .input{border-color:var(--brand)}
.svi-tr .input.guess{border-style:dashed;font-style:italic}
.menu-cat-edit{color:var(--muted);font-weight:600}
/* ---------- phase 23 (C, Martin's 8 and 9): Services — the header like Clients', a box per row, a category's own box, the grip ----------
   A row is now [grip][box][the row's button]: the button keeps the whole row's tap (and its .menu-row look); the line under it
   moves to the wrapper. */
.menu-toolbar>.row{flex-wrap:nowrap}
@media (max-width:430px){.menu-toolbar>.row{gap:4px}.menu-toolbar>.row .btn{padding:0 10px;min-width:44px}}   /* three buttons in a 288 px column (a 320 phone): */
@media (max-width:399px){.menu-toolbar>.row .btn .l-short{font-size:18px;line-height:1;padding:0 4px}}   /* + New service is "＋" on the narrowest phones (zlayout .l-short)… */
@media (min-width:360px) and (max-width:399px){.menu-toolbar>.row .btn .l-long{display:inline}.menu-toolbar>.row .btn .l-short{display:none}}   /* …from 360 px the words fit */
.menu-li{display:flex;align-items:center;border-bottom:1px solid var(--line);background:var(--surface)}
.menu-li:last-child{border-bottom:0}
.menu-li>.menu-row{border-bottom:0;flex:1 1 auto;min-width:0;padding-left:6px}
.menu-li>.bk-box{margin-left:4px}
.menu-li>.bk-grip{margin-left:2px}
.menu-li>.bk-grip+.bk-box{margin-left:-6px}
.menu-li.bk-sel,.menu-li.bk-sel>.menu-row{background:var(--brand-soft)}
.menu-h{display:flex;align-items:center;gap:2px}
.menu-h>.bk-box{margin:-10px -4px -10px -10px}
.menu-gh{display:flex;align-items:center;gap:4px}
.menu-gh>.menu-fold{flex:1 1 auto;min-width:0}
@media (hover:hover) and (pointer:fine) and (min-width:760px){.menu-gh:hover>.bk-box,.menu-h:hover>.bk-box{opacity:1}}   /* a category's box: .bk-hov (ui-x-bulk.css) */
.menu-search{display:flex;align-items:center;gap:4px;min-width:0}
.menu-search>.input{flex:1 1 auto;min-width:0}
.menu-search>.bk-head{margin-left:-10px}
.menu-selrow{flex-direction:row!important;align-items:center}
/* Retired */
.svr-row{cursor:default}
.svr-row:hover{background:none}
.svr-one{flex:none;margin-right:12px}
/* the bulk sheets */
.svb-mode{display:inline-flex}
.svb-prev{margin:4px 0 14px;min-height:20px}
.svb-samples{display:flex;flex-direction:column;gap:4px;margin-top:8px;padding:8px 12px;border-radius:12px;background:var(--surface-2);font-size:14px}
.svb-s{display:flex;align-items:center;gap:10px}
.svb-s .grow{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.staff-tog input[type=radio]{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none}
.staff-tog:has(input[type=radio]:checked){background:var(--brand-soft);border-color:var(--brand);color:var(--accent)}

/* ---------- phase 17: the navigation (ui-x-nav.js) ----------
   Phone: the page, a slim top bar (logo · name · bell · 中/EN) and a bottom bar of five. ≥ 900 px: a 232 px sidebar, the page beside it. */
.app-shell{min-height:100vh}
.app-main{max-width:1180px;margin:0 auto;padding:0 16px calc(84px + env(safe-area-inset-bottom))}
.app-top{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:10px;padding:10px 0;margin-bottom:6px;background:color-mix(in srgb,var(--bg) 92%,transparent);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
.app-top .logo{width:34px;height:34px;border-radius:9px;font-size:16px}
.app-top .tt{font-weight:700;font-size:16px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.nav-ic{width:22px;height:22px;flex:none}
.side-nav{display:none}
.bot-bar{position:fixed;left:0;right:0;bottom:0;z-index:30;display:grid;grid-template-columns:repeat(5,1fr);background:color-mix(in srgb,var(--surface) 94%,transparent);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-top:1px solid var(--line);padding:4px 4px calc(4px + env(safe-area-inset-bottom))}
.bot-item{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;min-height:52px;border-radius:10px;color:var(--muted);font-size:11px;font-weight:600}
.bot-item.on{color:var(--accent)}
.bot-item .nav-n,.bot-item .nav-dot{position:absolute;top:3px;left:calc(50% + 7px)}
.nav-n{min-width:18px;height:18px;padding:0 5px;border-radius:999px;background:var(--danger);color:#fff;font-size:11px;font-weight:700;line-height:18px;text-align:center;font-variant-numeric:tabular-nums}
.nav-dot{width:9px;height:9px;border-radius:50%;background:var(--warn);box-shadow:0 0 0 2px var(--surface)}
/* the "More" page: iOS grouped list */
.ios-group{background:var(--surface);border:1px solid var(--line);border-radius:14px;overflow:hidden;margin:0 0 16px}
.ios-row{display:flex;align-items:center;gap:12px;width:100%;min-height:52px;padding:8px 16px;border-bottom:1px solid var(--line);text-align:left;font-size:15px;color:var(--fg);text-decoration:none;position:relative}
.ios-row:last-child{border-bottom:0}
.ios-row.static{cursor:default}
.ios-row .nav-ic{color:var(--muted)}
.ios-row .chev{color:var(--faint);font-size:18px}
.ios-row.danger{color:var(--danger);justify-content:center}
.ios-row .nav-n,.ios-row .nav-dot{position:static}
button.ios-row:active,a.ios-row:active{background:var(--surface-2)}
/* the old shell, if anything still draws it */
.shop>.content>.tabs{display:none}
body.no-bar .app-top{top:0}
@media (min-width:768px){   /* phase 19: the bottom bar ends at 768 px (ui-x-zlayout.css) */
  .app-shell{display:grid;grid-template-columns:232px minmax(0,1fr)}
  .side-nav{display:flex;flex-direction:column;gap:6px;position:sticky;top:0;height:100vh;overflow:auto;padding:16px 12px;border-right:1px solid var(--line);background:var(--surface)}
  .side-brand{display:flex;align-items:center;gap:10px;padding:2px 6px 10px}
  .side-brand .logo{width:38px;height:38px;border-radius:10px;font-size:17px}
  .side-brand .tt{font-weight:700;font-size:15px;line-height:1.25;overflow:hidden;text-overflow:ellipsis}
  .side-group{display:flex;flex-direction:column;gap:2px;padding:6px 0;border-top:1px solid var(--line)}
  .side-item{display:flex;align-items:center;gap:12px;padding:0 12px;min-height:44px;border-radius:10px;font-size:14.5px;font-weight:600;color:var(--muted);text-align:left;width:100%;position:relative}
  .side-item:hover{background:var(--surface-2);color:var(--fg)}
  .side-item.on{background:var(--brand-soft);color:var(--accent)}
  .side-item .nav-l{flex:1}
  .side-foot{margin-top:auto;display:flex;flex-direction:column;gap:10px;padding:12px 6px 4px;border-top:1px solid var(--line)}
  .side-foot .langpill{align-self:flex-start}
  .side-acc{display:flex;flex-direction:column;font-size:13px}
  .side-links{display:flex;flex-wrap:wrap;gap:4px 14px}
  .side-links .lnk{font-size:13px;color:var(--muted);text-decoration:none;font-weight:600;padding:0}
  .side-links .lnk:hover{color:var(--fg)}
  .app-main{padding:20px 28px 48px;max-width:1240px;margin:0}
  .app-top,.bot-bar{display:none}
}

/* ---------- phase 22 (Part D): the booking page (hours, steps in words, perks, a code) and personal offers ---------- */

/* the opening hours, always shown under the shop's name: groups on one or two lines, today's bold */
.c-hours2{font-size:13px;line-height:1.5;color:var(--muted);margin:-8px 0 12px;display:flex;flex-wrap:wrap;align-items:baseline;column-gap:0;row-gap:2px}
.c-hours2 .ch-g{white-space:nowrap}
.c-hours2 .ch-g.now{color:var(--fg);font-weight:650}
.c-hours2 .ch-g.off .num{color:var(--faint)}
.c-hours2 .ch-g.now.off .num{color:var(--muted)}
.c-hours2 .sep{margin:0 7px;color:var(--faint)}

/* the steps in words: one line at 375 px; the current one bold, a done one goes back */
.steps.words{display:flex;align-items:center;justify-content:flex-start;gap:2px;margin:0 0 12px;white-space:nowrap;overflow:hidden;min-height:44px;border-bottom:1px solid var(--line)}
.steps.words .s{flex:none;display:inline-flex;align-items:center;flex-direction:row;gap:0;font-size:15px;color:var(--faint);font-weight:500;position:static;min-height:44px;padding:0 2px}
.steps.words .s.on{color:var(--fg);font-weight:700}
.steps.words .s.done{color:var(--accent);font-weight:600;background:none;border:0;cursor:pointer;padding:0 4px;min-width:44px;justify-content:center}
.steps.words .s.done:hover{text-decoration:underline}
.steps.words .sep{color:var(--faint);font-size:15px;padding:0 4px}

/* under the services: a known client's balance / sessions, and Have a code? */
.c-perks{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:6px 14px;margin:-6px 0 8px;font-size:14px;color:var(--muted)}
.c-perks .c-bal{display:flex;align-items:center;gap:0;flex-wrap:wrap}
.c-perks .c-bal b{color:var(--fg)}
.c-perks .sep{margin:0 7px;color:var(--faint)}
.c-perks .lnk{color:var(--accent);font-weight:600;font-size:14px;min-height:44px;background:none;border:0;padding:0;cursor:pointer;margin-left:auto}
.c-perks .c-code-row{display:flex;gap:8px;flex:1 1 220px;max-width:340px;margin-left:auto}
.c-perks .c-code-row .input{flex:1;min-width:0;font-size:16px;text-transform:uppercase;letter-spacing:.04em;min-height:44px}
.c-perks .c-code-row .btn{flex:none;min-height:44px}
.c-perks .errmsg{flex-basis:100%;text-align:right}
.c-where{margin-top:14px;display:flex;flex-direction:column;align-items:center;gap:0;text-align:center}
.c-where a{min-height:44px;display:inline-flex;align-items:center}
.c-where a{color:inherit}

/* prices with an offer: the struck one, then the price after it */
s.was{color:var(--faint);font-weight:400;font-size:13px;margin-right:2px;text-decoration-thickness:1px}
.svc .p s.was{display:block;line-height:1.1}
.off-tag{font-size:13px;font-weight:600;color:var(--ok);white-space:nowrap}
.c-offer-note{margin-top:8px;font-size:14px;color:var(--ok);font-weight:600}
.c-offer-note b{margin-left:4px}

/* the offer banner on the booking page (ui-x-promolink.js): one line, a ✓, an ✕ for a typed code */
.pl-banner span.grow{display:block;line-height:1.4}
.pl-banner span.grow>*{margin-right:6px}
.pl-banner .pl-ok{color:var(--ok);font-weight:800}
.pl-banner .pl-x{flex:none;min-width:44px;min-height:44px;margin:-10px -10px -10px 0;background:none;border:0;color:var(--muted);font-size:16px;cursor:pointer;border-radius:10px}

/* the client card: the 🎁 chip and Give offer */
.of-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:6px 0 2px}
.of-row .of-chip{font-size:13px;min-height:32px;cursor:pointer;border:0}
.of-row .of-chip.used{cursor:default;color:var(--muted);background:var(--surface-2)}
.of-row .of-give{min-height:32px;font-size:13px;padding:0 12px}
/* the Give offer sheet */
.of-form{display:flex;flex-direction:column;gap:14px}
.of-val{display:flex;align-items:center;gap:10px}
.of-val .viewtog button{min-width:48px;min-height:44px;font-size:16px;font-weight:700}
.of-val .input{width:110px;font-size:18px;font-weight:700;min-height:44px;text-align:right}
.of-val .of-prev{font-size:15px;font-weight:700;color:var(--ok)}
.of-svcs{display:flex;flex-wrap:wrap;gap:6px;max-height:180px;overflow:auto;padding:2px 0}
.of-svcs .chipbtn{min-height:36px;font-size:14px}
.of-form .input[type=date]{max-width:220px;font-size:16px}

/* checkout: the code field sits above the manual discount */
.co-prod.co-code{grid-template-columns:1fr auto;margin-top:8px}
.co-prod.co-code .input{text-transform:uppercase;letter-spacing:.04em;font-size:16px}
/* the promotions list: code · Copy link · used n× · −$given */
.rt-code{display:flex;flex-wrap:wrap;align-items:center;gap:4px 12px;margin-top:2px}
.rt-code b{letter-spacing:.04em}
.rt-code .lnk{color:var(--accent);font-weight:600;background:none;border:0;padding:0;min-height:32px;cursor:pointer}
@media (max-width:767px){.rt-code .lnk,.of-row .of-chip,.of-row .of-give{min-height:44px}}
/* checkout: the discount is one line in the items, its ✕ on the line */
.co-lines .discount b{display:inline-flex;align-items:center;gap:2px}
.co-lines .co-line-x{min-width:32px;min-height:32px;margin:-8px -10px -8px 0;background:none;border:0;color:var(--muted);font-size:14px;cursor:pointer;border-radius:8px}
@media (max-width:767px){.co-lines .co-line-x{min-width:44px;min-height:44px;margin:-12px -12px -12px 0}}

/* ---------- phase 20 (10, 5): the poster, three lines, centred (ui-x-poster.js) ---------- */
.poster-page{max-width:520px;margin:0 auto;display:flex;flex-direction:column;align-items:center}
.poster-tools{display:flex;justify-content:center;margin-top:16px;width:100%}
.poster3{width:100%;max-width:420px;margin:16px auto 0;gap:22px;justify-content:center}
.poster3 .name{font-family:var(--font-display);font-size:30px;line-height:1.2;text-align:center}
.poster3 .name small{display:block;font-family:inherit;font-size:13px;letter-spacing:.16em;text-transform:uppercase;color:var(--muted);margin-top:4px}
.poster3 .scan{font-size:24px;font-weight:800;margin:0;text-align:center}
.poster3 .scan small{display:block;font-size:13px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);margin-top:4px}
.poster-a4.poster3{justify-content:space-around;max-width:460px}
.poster-a4.poster3 .name{color:#1d1b18;font-size:clamp(26px,8vw,40px)}
.poster-a4.poster3 .name small{color:#6c675f}
.poster-a4.poster3 .scan{color:var(--brand);font-size:clamp(24px,7vw,34px)}
.poster-a4.poster3 .scan small{color:#6c675f}
.poster-foot{display:flex;justify-content:center;margin-top:12px}
@media print{.poster-foot{display:none!important}}

/* phase 15 step 5: 客人 › 导入 (ui-x-quick-import.js). Phase 22 (A): the table, chips and footer are the shared importer pieces (ui-x-importer.css) */
.qi-tiles{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.qi-tile{display:flex;flex-direction:column;align-items:flex-start;gap:4px;min-height:72px;padding:12px 14px;border-radius:14px;border:1px solid var(--line);background:var(--surface);color:var(--fg);text-align:left;cursor:pointer}
.qi-tile:hover{border-color:var(--brand)}
.qi-unknown{display:flex;flex-direction:column;gap:8px}
.qi-unk{padding:10px 12px;border:1px solid var(--line);border-radius:12px;background:var(--surface)}
.qi-unk .hd{display:block;font-weight:600;margin-bottom:6px}
.qi-why{font-size:13px}
.qi-why .brand-ink{color:var(--accent);font-weight:600}
.c-blk{text-align:center;color:var(--danger);font-weight:700}
.c-blk i{display:none;font-style:normal;margin-left:4px}
.qi-r.st-merged .c-name{color:var(--muted)}
.qi-progress{height:10px;border-radius:999px;background:var(--surface-2);overflow:hidden;margin:16px 0 8px}
.qi-progress i{display:block;height:100%;background:var(--brand);transition:width .25s ease-out}
@media (max-width:760px){.qi-tiles{grid-template-columns:1fr}.c-blk i{display:inline}}

/* ===== phase 05: dashboard tiles, 报表 tab, client segments, print view ===== */
.rp-dash{display:grid;grid-template-columns:1fr;gap:8px;margin:10px 0 4px}
.rp-tile{background:var(--surface);border:1px solid var(--line);border-radius:12px;overflow:hidden}
.rp-tile-h{display:flex;align-items:center;gap:10px;padding:10px 12px;cursor:pointer;min-height:44px}
.rp-tile-h .eyebrow{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rp-tile-h b{font-size:17px;white-space:nowrap}
.rp-caret{color:var(--faint);transition:transform .15s;font-size:18px;line-height:1}
.rp-tile.open .rp-caret{transform:rotate(90deg)}
.rp-tile-b{display:none;padding:0 12px 10px;border-top:1px solid var(--line)}
.rp-tile.open .rp-tile-b{display:block}
@media (min-width:720px){.rp-dash{grid-template-columns:1fr 1fr;gap:10px}.rp-tile-b{display:block}.rp-caret{display:none}.rp-tile-h{cursor:default}}
.rp-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:5px 0;font-size:14px;border-top:1px solid color-mix(in srgb,var(--line) 55%,transparent)}
.rp-row:first-child,.rp-sub+.rp-row,.rp-staff:first-child>.rp-row:first-child{border-top:0}
.rp-row .l{flex:1;min-width:0;display:flex;flex-direction:column}
.rp-row .l small{color:var(--muted);font-size:11px;font-weight:400}
.rp-row.total{font-weight:700;border-top:1px solid var(--line);margin-top:2px;padding-top:7px}
.rp-row.total .rp-num{font-weight:700}
.rp-pair{display:flex;gap:6px;align-items:center;flex-wrap:wrap;justify-content:flex-end}
.rp-num{font-weight:600;color:var(--accent);padding:2px 6px;margin:-2px -6px;border-radius:8px;white-space:nowrap;text-align:right}
.rp-num:not(:disabled):hover{background:var(--brand-soft)}
.rp-num:disabled{color:var(--fg);opacity:.8;cursor:default}
.rp-num em{font-style:normal;font-size:12px;font-weight:600}
.rp-num em.up{color:var(--ok)}.rp-num em.down{color:var(--danger)}
.rp-sub{font-size:11px;color:var(--muted);letter-spacing:.06em;margin:10px 0 2px;font-weight:600}
.rp-sub.first{margin-top:4px}
.rp-dot{display:inline-block;width:9px;height:9px;border-radius:50%;margin-right:6px;vertical-align:middle}
.rp-next{display:flex;flex-direction:column;margin:4px 0 2px}
.rp-next-row{display:flex;gap:8px;align-items:center;padding:6px 0;text-align:left;font-size:13px;width:100%;border-top:1px solid color-mix(in srgb,var(--line) 55%,transparent)}
.rp-next-row:first-child{border-top:0}
.rp-next-row .num{font-weight:700;width:3.2em;flex:none}
.rp-next-row .grow{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* 报表 tab — phase 20 (Part D): one page, top to bottom: period · four numbers · takings by day · method / staff / service */
.rp-ranges{justify-content:space-between;flex-wrap:wrap;gap:6px 12px;margin-bottom:12px}
.rp-ranges .viewtog{flex-wrap:wrap}
.rp-custom{margin-bottom:12px}
.rp-print-head{display:none}
.rp-kpis{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-bottom:12px}
@media (min-width:900px){.rp-kpis{grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}}
.rp-kpi{background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:12px 14px;display:flex;flex-direction:column;gap:2px;min-width:0}
.rp-def{position:relative;align-self:flex-start;font-size:13px;font-weight:600;color:var(--muted);text-decoration:underline dotted color-mix(in srgb,var(--muted) 60%,transparent);text-underline-offset:3px;padding:0;min-height:0;text-align:left}
.rp-def.open::after,.rp-def:hover::after,.rp-def:focus-visible::after,.rp-def:focus::after{content:attr(data-tip);position:absolute;left:0;top:calc(100% + 6px);z-index:30;width:max-content;max-width:min(260px,70vw);padding:8px 10px;border-radius:8px;background:var(--fg);color:var(--bg);font-size:12.5px;font-weight:500;line-height:1.4;text-decoration:none;white-space:normal;box-shadow:0 4px 14px rgba(0,0,0,.18)}
.rp-kpi:nth-child(2n) .rp-def::after{left:auto;right:-60px}
@media (min-width:900px){.rp-kpi:nth-child(2n) .rp-def::after{left:0;right:auto}}
.rp-kv{min-width:0}
.rp-kv .rp-num{display:inline-block;margin:0;padding:0;font-size:26px;font-weight:700;line-height:1.25;color:var(--fg);font-variant-numeric:normal;text-align:left}
.rp-kv .rp-num:not(:disabled):hover{background:none;color:var(--accent)}
.rp-ks{font-size:12.5px;line-height:1.35;min-height:17px;overflow-wrap:anywhere}
.rp-delta{font-weight:700;font-variant-numeric:tabular-nums}
.rp-delta.up{color:var(--ok)}.rp-delta.down{color:var(--danger)}
.rp-sec{padding:14px 16px 12px;margin-bottom:12px}
.rp-h{font-size:15px;font-weight:700;margin:0 0 8px}
.rp-h2{font-size:12px;font-weight:600;color:var(--muted);margin:12px 0 2px}
/* the chart: hairline grid, columns ≤ 24 px wide with a 4 px rounded top, a tooltip per column */
.rp-chart{position:relative;height:180px;margin:20px 0 4px}
.rp-grid-l{position:absolute;inset:0}
.rp-gl{position:absolute;left:0;right:0;border-top:1px solid var(--line);height:0}
.rp-gl em{position:absolute;left:0;bottom:2px;font-style:normal;font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums;line-height:1}
.rp-cols{position:absolute;left:44px;right:0;top:0;bottom:0;display:grid;grid-template-columns:repeat(var(--n),minmax(0,1fr));column-gap:2px;align-items:end}
.rp-col{position:relative;height:100%;min-height:0;padding:0;display:flex;align-items:flex-end;justify-content:center;background:none;border-radius:4px}
.rp-col i{display:block;width:min(24px,100%);min-height:0;background:var(--accent);border-radius:4px 4px 0 0}
.rp-col:not(:disabled):hover i,.rp-col:focus-visible i{opacity:.75}
.rp-col:hover::after,.rp-col:focus-visible::after{content:attr(data-tip);position:absolute;bottom:calc(100% + 4px);left:50%;transform:translateX(-50%);z-index:30;white-space:nowrap;padding:6px 8px;border-radius:8px;background:var(--fg);color:var(--bg);font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;pointer-events:none}
.rp-col.l:hover::after,.rp-col.l:focus-visible::after{left:0;transform:none}
.rp-col.r:hover::after,.rp-col.r:focus-visible::after{left:auto;right:0;transform:none}
.rp-col:disabled{cursor:default}
.rp-col::before{content:'';position:absolute;inset:0 -1px}
.rp-xs{display:grid;grid-template-columns:repeat(var(--n),minmax(0,1fr));column-gap:2px;margin-left:44px;font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums;line-height:16px;min-height:16px}
.rp-xs span{text-align:center;white-space:nowrap;overflow:visible;min-width:0}
/* the three tables */
.rp-cols2{display:grid;grid-template-columns:minmax(0,1fr);gap:0 14px;align-items:stretch}
@media (min-width:1100px){.rp-cols2{grid-template-columns:repeat(2,minmax(0,1fr))}.rp-cols2>.rp-sec:last-child{grid-column:1/-1}}
.rp-tw{overflow-x:auto}
.rp-t{width:100%;border-collapse:collapse;font-size:14px}
.rp-t th{text-align:left;font-weight:600;color:var(--muted);font-size:12.5px;padding:0 6px 6px 0;border-bottom:1px solid var(--line)}
.rp-t th.n,.rp-t td.n{text-align:right;padding-right:0;padding-left:10px}
.rp-t th button{font:inherit;color:inherit;padding:4px 0;min-height:32px;display:inline-flex;align-items:center;gap:3px}
.rp-t th button i{font-style:normal;width:.8em;display:inline-block}
.rp-t th[aria-sort="ascending"] button,.rp-t th[aria-sort="descending"] button{color:var(--fg)}
.rp-t td{padding:8px 6px 8px 0;border-bottom:1px solid color-mix(in srgb,var(--line) 55%,transparent);vertical-align:middle;overflow-wrap:normal;word-break:normal}
.rp-t th{white-space:normal;vertical-align:bottom}
.rp-t th button{text-align:inherit;justify-content:inherit}
@media (max-width:480px){.rp-t{font-size:13px}.rp-t th{font-size:11.5px}.rp-t th.n,.rp-t td.n{padding-left:6px}.rp-t td .rp-num{margin:-2px 0 -2px -4px;padding:2px 0 2px 4px}}
.rp-t td.n{white-space:nowrap}
.rp-t td .rp-num{margin:-2px 0 -2px -6px;padding:2px 0 2px 6px;font-weight:600}   /* nothing past the right edge: the table scrolls, so it would be clipped */
.rp-t tr.sub td:first-child{color:var(--muted);padding-left:12px}
.rp-t tfoot td{font-weight:700;border-bottom:0;border-top:1px solid var(--fg);padding-top:9px}
.rp-not{margin-top:4px}
.rp-not .rp-row{font-size:14px}
/* client segments */
.rp-segs{margin-top:10px}
.rp-segs .chips{padding-bottom:6px}
.rp-segs.on ~ #client-list{display:none}
.rp-seg-bar{justify-content:space-between;flex-wrap:wrap;gap:6px;margin:4px 0 8px}
/* print: only the report, on white */
@media print{
  html.rp-print .demobar,html.rp-print .sidenav,html.rp-print .tabs,html.rp-print .s-head,html.rp-print #script-root,html.rp-print .rp-toolbar,html.rp-print .rp-ranges,html.rp-print .rp-custom,html.rp-print #sheet,html.rp-print #toast,html.rp-print #dlg,html.rp-print .rp-foot{display:none!important}
  html.rp-print{--bg:#fff;--surface:#fff;--surface-2:#f2f2f2;--line:#ccc;--fg:#000;--muted:#444;--faint:#888;--accent:#000;--shadow:none}
  html.rp-print body{background:#fff;color:#000;padding:0}
  html.rp-print main{padding:0}
  html.rp-print .shop{display:block}
  html.rp-print .content{padding:0}
  html.rp-print .rp-print-head{display:block;margin:0 0 10px}
  html.rp-print .rp-print-head h1{font-size:18px;margin:0}
  html.rp-print .rp-print-head p{margin:2px 0 0;font-size:12px;color:#444}
  html.rp-print .rp-kpis{grid-template-columns:repeat(4,1fr)}
  html.rp-print .rp-cols2{grid-template-columns:1fr 1fr}
  html.rp-print .rp-def{text-decoration:none}
  html.rp-print .rp-col i{background:#000}
  html.rp-print .rp-sec,html.rp-print .rp-kpi{break-inside:avoid;border:1px solid #ccc;box-shadow:none}
  html.rp-print .rp-num{color:#000}
}

/* ---------- phase 24 (Part E): products, vouchers, the retail reports (ui-x-retail.js) ---------- */
.rl-lowdot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--warn);margin-left:6px;vertical-align:1px}
.menu-cat.on .rl-lowdot{background:var(--brand-ink)}
.rl-row .rl-low,.rl-low{font-size:11px;vertical-align:2px;margin-left:4px}
.rl-row.off .n{color:var(--muted)}
.rl-foot{margin:10px 2px 0}
.rl-ro{background:var(--surface-2);display:flex;align-items:center}
.rl-adj{gap:10px}
.rl-take{align-items:flex-end;gap:8px}
.rl-take .field{margin:0}
.rl-moves .item{padding:8px 0;min-height:44px}
.rl-moves .rl-neg{color:var(--danger)}
.rl-moves .rl-pos{color:var(--ok)}
.rl-imp td,.rl-imp th{font-size:13px}
.rl-imp tr.off td{opacity:.45}
.rl-imp input[type=checkbox]{width:22px;height:22px;margin:11px}   /* a 44 px hit area on a phone */
/* the checkout */
.co-prod.ta-host{position:relative}
.co-prod #rl-ta{left:0;right:0}
.co-tender.voucher .lbl{color:var(--accent)}
.rl-vcode{margin-top:6px}
.rl-sell-link{margin-top:-2px}
/* selling a voucher: the code big enough to read across a counter */
.rl-vcard{padding:14px 16px;display:flex;flex-direction:column;gap:4px;text-align:center}
.rl-code{font-size:30px;letter-spacing:.14em;font-weight:800;font-variant-numeric:tabular-nums;padding:6px 0}
/* the card */
.rl-refunded{font-size:11px;margin-right:6px}
.rl-pkrf{color:var(--danger)}
/* the liability table: a name opens the card, with a 44 px hit area on every width */
.rl-liab .cl-link{display:inline-flex;align-items:center;min-height:44px;padding:0 4px;margin:-8px 0}
/* 概览 */
.rl-dash-st{flex:none;margin-left:6px;white-space:nowrap}
@media (max-width:479px){.rl-dash-st{display:none}}
/* 报表: the more-reports grid and the totals rows */
.rl-more-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}
.rl-more-btn{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-height:72px;padding:10px 12px;border:1px solid var(--line);border-radius:12px;background:var(--surface);text-align:left;color:var(--fg)}
.rl-more-btn b{font-size:15px}
.rl-more-btn span{font-size:14px;color:var(--fg)}
.rl-more-btn small{font-size:11.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.rl-def{margin:-4px 0 8px}
.rl-tot{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:10px 14px;margin:4px 0 10px}
.rl-tot>div{display:flex;flex-direction:column;gap:1px;min-width:0}
.rl-tot span{font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rl-tot b{font-size:18px}
.rl-tot small{font-size:11px;color:var(--muted)}
.rl-tot .all b{color:var(--accent)}
.rl-tot .bad b{color:var(--danger)}
.rl-qnav{align-items:center;gap:8px}
.rl-qnav .btn{min-width:44px}
.rl-tenders .item{padding:8px 0;min-height:44px}
.rl-vrow .acts{display:flex;gap:4px;flex-wrap:wrap}
.rl-vrow .ttl.num{letter-spacing:.06em}
/* the booking page: the package line under a price */
.c-pkg-use{display:block;font-size:12px;color:var(--accent);font-weight:600;margin-top:2px}
.c-pkg-note{margin-top:8px;font-size:13px}
/* printing the GST page: the sheet alone, black on white */
@media print{
  html.rl-print #app,html.rl-print #toast,html.rl-print #dlg,html.rl-print .rl-qnav,html.rl-print .rl-print-btn,html.rl-print #sheet .sheet-bg,html.rl-print #sheet .x{display:none!important}
  html.rl-print{--bg:#fff;--surface:#fff;--surface-2:#f2f2f2;--line:#ccc;--fg:#000;--muted:#444;--accent:#000;--shadow:none}
  html.rl-print body{background:#fff;color:#000}
  html.rl-print #sheet{position:static;display:block;height:auto;max-height:none;width:auto;max-width:none;box-shadow:none;border:0;border-radius:0;padding:0;overflow:visible}
  html.rl-print #sheet-body{overflow:visible;max-height:none;height:auto;padding:0}
  html.rl-print .rl-print-head{display:block;margin:0 0 10px}
}

/* phase 12: 跟进 (久未到店, 疗程), 活动, consent at 结账 */
.rt-consent{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:10px 12px;border:1px dashed var(--line);border-radius:12px;margin:2px 0 6px}
.rt-consent .check{margin:0;min-height:0}
.rt-consent .input.sm{width:auto;min-width:120px;padding:6px 10px;font-size:14px}
.rt-consent-how{margin-top:-6px}
.rt-consent-line{margin:4px 0 8px}
.rt-row .why{font-size:13px;margin-top:2px}
.rt-preview{padding:14px 16px;border:1px solid var(--brand);display:flex;flex-direction:column;gap:10px}
.rt-preview .tiles{margin:0}
.rt-offer{padding:10px 12px;border:1px solid var(--line);border-radius:12px;gap:10px}
.rt-offer[hidden]{display:none}

/* phase 22 (integration): a promotion's date range stays on one line */
.rt-range{white-space:nowrap;font-variant-numeric:tabular-nums}

/* phase 20 (B): the client list from the server — fixed-height rows placed by position (ui-x-roster.js), so only what is on
   screen is in the page; the filters and the actions for a filtered set */
#cl-q{margin-top:4px}
.cl-tools{justify-content:space-between}
.cl-filters{margin-top:10px}
.cl-bulk{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:10px;padding:8px 12px;border-radius:12px;background:var(--brand-soft);font-weight:600}
.cl-vlist{position:relative;padding:0;margin-top:10px;overflow:hidden;min-height:72px}
.cl-vlist>.cl-row{position:absolute;left:0;right:0;height:72px;box-sizing:border-box;margin:0;padding:0 16px;display:flex;align-items:center;gap:12px;border-bottom:1px solid var(--line);min-height:0}
.cl-vlist>.cl-row .grow{min-width:0}
.cl-vlist>.cl-row .ttl{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cl-vlist>.cl-row .sub{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cl-vlist .cl-ghost::before{content:"";display:block;height:14px;width:40%;border-radius:7px;background:var(--surface-2)}
.cl-vlist>.empty,.cl-vlist>.cl-wait{padding:16px}
/* phase 23 (C): the row's box sits before the name (ui-x-bulk.css draws it); the header box, the Deleted link, the Deleted view */
.cl-vlist>.cl-row{padding-left:4px}
.cl-vlist>.cl-row .bk-box{margin-right:-4px}
.cl-tools{display:flex;align-items:center;justify-content:flex-start;gap:8px;flex-wrap:wrap}
.cl-tools .bk-head{margin-left:-2px}
.cl-dellink{background:none;border:0;min-height:44px;padding:0 4px;font:inherit;font-size:14px;color:var(--muted);text-decoration:underline;text-underline-offset:3px;cursor:pointer;white-space:nowrap}
.cld-list{padding:0;margin-top:10px}
.cld-row{display:flex;align-items:center;gap:8px;min-height:64px;padding:0 12px 0 4px;border-bottom:1px solid var(--line);margin:0}
.cld-row:last-of-type{border-bottom:0}
.cld-row .grow{min-width:0}
.cld-row .ttl,.cld-row .sub{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cld-more{display:block;margin:8px auto}
@media (max-width:759px){
  .cl-tools>.viewtog{order:-1;flex:1 0 100%}
}

/* ---------- phase 17: Settings — one readable column, iOS grouped lists (ui-x-settings.js) ---------- */
.set-col{max-width:640px;display:flex;flex-direction:column;gap:14px}
.set-col>.ios-group{margin:0}
.set-val{color:var(--muted);font-size:14px;text-align:right;max-width:55%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-flex;align-items:center;gap:6px}
.set-nudge{display:flex;align-items:center;gap:12px;width:100%;text-align:left;padding:12px 16px;border-radius:14px;border:1px solid color-mix(in srgb,var(--warn) 45%,var(--line));background:color-mix(in srgb,var(--warn) 9%,var(--surface))}
.set-nudge .grow{display:flex;flex-direction:column}
.set-nav{margin:0 0 4px}
.set-nav .lnk{font-size:15px;font-weight:600;color:var(--accent);padding:6px 0;min-height:36px}
.set-form{padding:4px 16px}
.set-field{display:flex;flex-direction:column;gap:6px;padding:12px 0;border-bottom:1px solid var(--line)}
.set-field:last-child{border-bottom:0}
.set-field>label{font-size:14px;font-weight:600;color:var(--fg);display:flex;align-items:center;gap:6px}
.set-field .swatches{display:flex;flex-wrap:wrap;gap:8px}
.swatch.custom{display:inline-flex;align-items:center;gap:6px;cursor:pointer}
.swatch.custom input[type=color]{width:28px;height:28px;border:0;padding:0;background:none;border-radius:50%}
/* opening hours: a row per day, the two times fit (no more "1▾" / "09:(") */
.set-hours{padding:4px 12px}
.set-hrow{display:grid;grid-template-columns:minmax(76px,auto) minmax(92px,1fr) auto minmax(92px,1fr);align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--line)}
.set-hrow:last-child{border-bottom:0}
.set-hrow .check{min-height:44px;font-weight:600}
.set-hrow select.input{min-width:0;width:100%;padding-right:28px;font-variant-numeric:tabular-nums;min-height:44px}
.set-hrow .set-closed{display:none;grid-column:2/-1}
.set-hrow.off select,.set-hrow.off>span.muted:not(.set-closed){display:none}
.set-hrow.off .set-closed{display:block}
/* the cards other features add keep working, but in one column and without their own wide grids */
.set-page .grid3{grid-template-columns:1fr!important}
.set-page .card{margin:0}
.set-page .sec-title{margin:6px 0 2px;font-size:var(--t-section,17px)}
.set-page .eyebrow{font-size:14px;color:var(--fg)}
.set-page .room-row{display:grid;grid-template-columns:1fr 1fr auto auto;gap:8px;align-items:center}
.set-link{border:1px solid var(--line);border-radius:14px;background:var(--surface)}
.set-dock{position:sticky;bottom:calc(76px + env(safe-area-inset-bottom));padding:8px 0;background:linear-gradient(transparent,var(--bg) 35%)}
.set-dock .btn{width:100%;min-height:52px}
@media (min-width:768px){.set-dock{bottom:0}.set-dock .btn{max-width:320px}}
.ios-row>.grow{flex:1 1 auto;min-width:0;text-align:left}
.set-form>.field,.set-form>.grid2,.set-form>label.check{padding:10px 0;border-bottom:1px solid var(--line);margin:0}
.set-form>.field>label{font-size:14px;font-weight:600}
.set-form>.field:last-child,.set-form>label.check:last-child{border-bottom:0}
.set-form>.info,.set-form>button.info{margin:-2px 0 6px}
.set-tog{display:flex;align-items:center;gap:12px;padding:12px 0;border-bottom:1px solid var(--line);cursor:pointer}
.set-tog:last-child{border-bottom:0}
.set-tog .grow{display:flex;flex-direction:column;gap:2px}
.set-tog small{color:var(--muted);font-size:12.5px}
/* phase 18: the toggle is the one switch (ui-x-menu.css input[role=switch]); nothing of its own here */
.set-cost{margin-left:auto}

/* ---------- phase 23 (a): the setup checklist on 概览 / Dashboard (ui-x-setup.js) ----------
   One card above the numbers: the title and n/7, a thin progress bar, then iOS-style rows. A done row is a green ✓ and grey
   words; a row to do is an empty circle, its name and either › or its one or two buttons (↑ 导入 like Clients' header). */
.su-card{background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:12px 14px 6px;margin:0 0 14px;box-shadow:var(--shadow)}
.su-head{display:flex;align-items:center;gap:10px;min-height:32px}
.su-head b{font-size:17px;flex:1}
.su-n{font-size:15px;font-weight:700;color:var(--muted)}
.su-bar{height:6px;border-radius:3px;background:var(--surface-2);overflow:hidden;margin:8px 0 4px}
.su-bar i{display:block;height:100%;border-radius:3px;background:var(--ok);transition:width .25s ease-out}
.su-list{display:flex;flex-direction:column}
.su-row{display:flex;align-items:center;gap:12px;width:100%;min-height:52px;padding:6px 0;border-bottom:1px solid var(--line);text-align:left;font-size:15px;color:var(--fg)}
.su-row:last-child{border-bottom:0}
button.su-row{cursor:pointer}
button.su-row:hover .grow{color:var(--accent)}
.su-row .grow{flex:1;min-width:0}
.su-row .btn.sm{flex:none;gap:4px}
.su-row .btn.sm .nav-ic{width:16px;height:16px}
.su-row.done{color:var(--muted)}
.su-mark{display:inline-grid;place-items:center;width:24px;height:24px;border-radius:50%;border:2px solid var(--line);flex:none;font-size:14px;font-weight:700}
.su-mark.ok{background:var(--ok);border-color:var(--ok);color:var(--surface)}
.su-card .sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
@media (min-width:1024px){.su-card{padding:14px 18px 8px}.su-list{display:grid;grid-template-columns:1fr 1fr;column-gap:28px}.su-row:nth-last-child(2):nth-child(odd){border-bottom:0}}

/* phase 17: the sign-in forms add no box of their own */
.sec-form{display:contents}
/* a field with unsaved typing (kept across a redraw) */
.input.draft{box-shadow:0 0 0 2px color-mix(in srgb,var(--brand) 35%,transparent)}

/* ---------- phase 17 (item 3): one font, one type scale ----------
   title = a page's or a sheet's name · section = a group inside it · body · caption. The same in Chinese and English;
   bold, not a different typeface, carries the hierarchy. */
:root{--t-title:24px;--t-section:17px;--t-body:15px;--t-caption:13px}
@media (min-width:900px){:root{--t-title:26px;--t-section:18px}}
.toolbar h2,.login h2,.success h2{font-size:var(--t-title);font-weight:700;letter-spacing:-.01em;line-height:1.2}
.sheet-body h3{font-size:calc(var(--t-title) - 4px);font-weight:700;line-height:1.25}
.sec-title,.fu-sec{font-size:var(--t-section);font-weight:700;letter-spacing:0}
.s-head .tt,.sidenav .brand .tt,.shop-name{font-weight:700;letter-spacing:-.005em}
.summary .big,.pinpad .n{font-weight:700}
.eyebrow{font-size:var(--t-caption);letter-spacing:.02em;text-transform:none;font-weight:600}
.co-receipt .hd b,.co-name>b{font-family:var(--font-body);font-weight:700}
/* phase 17 (item 6): a client's name is a link to the profile wherever it shows */
.cl-link{color:inherit;font:inherit;font-weight:inherit;text-decoration:underline;text-decoration-color:color-mix(in srgb,currentColor 35%,transparent);text-underline-offset:3px;padding:0;min-height:0;display:inline}
.cl-link:hover{color:var(--accent);text-decoration-color:currentColor}
/* ---------- phase 17 (items 6, 18): the client list's money column, the sort, the type-ahead ---------- */
.cl-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:10px 0 0}
.cl-row .cl-money{display:flex;flex-direction:column;align-items:flex-end;gap:2px;flex:none;text-align:right}
.cl-row .cl-money b{font-size:15px}
.chip.xs{font-size:10.5px;padding:0 6px;min-height:18px}
.ta-host{position:relative}
.ta-list{position:absolute;left:0;right:0;top:100%;z-index:40;margin-top:4px;background:var(--surface);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow);overflow:hidden;max-height:320px;overflow-y:auto}
.ta-item{display:grid;grid-template-columns:1fr auto;gap:0 10px;width:100%;text-align:left;padding:9px 12px;min-height:48px;border-bottom:1px solid var(--line)}
.ta-item:last-child{border-bottom:0}
.ta-item b{font-weight:600}
.ta-item .num{color:var(--muted);font-size:13px}
.ta-item small{grid-column:1/-1;color:var(--muted);font-size:12px}
.ta-item.on,.ta-item:hover{background:var(--brand-soft)}
.ta-pick{font-size:14px;padding:4px 0}
.ta-warn{color:var(--danger);font-size:13px;font-weight:600;margin-top:2px}
.ta-note{margin-top:2px}
@media (min-width:900px){.ta-host .ta-list{min-width:320px}}
/* ---------- phase 17 (item 20): the client's link page ---------- */
.my-acts{display:grid;grid-template-columns:repeat(auto-fit,minmax(72px,1fr));gap:8px}
.my-act{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;min-height:64px;border-radius:14px;background:var(--surface);border:1px solid var(--line);font-size:13px;font-weight:600;color:var(--fg);text-decoration:none}
.my-act .ic{font-size:20px;line-height:1}
.my-late{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.my-late .chipbtn{min-height:40px}
.my-late.done{padding:10px 14px;border-radius:12px;background:color-mix(in srgb,var(--st-wait,#8f5300) 12%,var(--surface));color:var(--st-wait,#8f5300);font-weight:600}
.my-shop{padding:12px 16px}
.my-signin,.my-lookup{margin-top:16px;background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:12px 16px}
.my-signin summary,.my-lookup summary{font-weight:600;cursor:pointer}
.my-signin .row{margin-top:10px;gap:8px}
.cf-done{padding:12px 16px;border-radius:14px;background:color-mix(in srgb,var(--st-ok,#1b6f3f) 12%,var(--surface));color:var(--st-ok,#1b6f3f);font-weight:700;text-align:center}
.lnk{background:none;border:0;padding:0;color:var(--accent);font-weight:600;cursor:pointer}

/* phase 25 (a): the demo shop's booking page (ui-x-site-demo.js) */
.sd-bar{display:flex;align-items:center;gap:10px;margin:0 0 12px;padding:8px 8px 8px 14px;border-radius:14px;background:var(--surface-2,#eae8e2);color:var(--fg);font-size:14px;line-height:1.35}
.sd-dot{width:8px;height:8px;border-radius:50%;background:var(--brand,#3d5a4c);flex:none}
.sd-go{display:inline-flex;align-items:center;min-height:44px;padding:0 14px;border-radius:999px;background:var(--brand-strong,#2b4337);color:#fff;font-weight:650;text-decoration:none;white-space:nowrap}
.sd-done{display:grid;gap:12px;justify-items:center;text-align:center;padding:28px 8px 12px}
.sd-done h2{font-size:24px;margin:4px 0 0}
.sd-done .btn{width:100%;max-width:360px}
.sd-tick{display:grid;place-items:center;width:64px;height:64px;border-radius:50%;background:var(--surface-2,#eae8e2);color:var(--brand,#3d5a4c);font-size:30px;font-weight:700}

/* ---------- phase 19: the staff app (ui-x-staffapp.js) ----------
   The shell is the shop's (ui-x-nav.css): bottom bar on a phone, sidebar from 900 px. Big type for a glance between clients;
   the allergy line is always red and never behind a tap. */
.bot-bar.n4{grid-template-columns:repeat(4,1fr)}
.st-app .app-main{max-width:980px}
body.on-cal .st-app .app-main{max-width:none}
.st-day-head{display:flex;align-items:flex-start;gap:12px;margin:6px 0 10px}
.st-hi{font-size:22px;font-weight:700;line-height:1.2}
.st-date{color:var(--muted);font-size:14px;margin-top:2px}
.st-shift{display:inline-block;margin-top:8px;padding:4px 10px;border-radius:999px;background:var(--surface-2);color:var(--muted);font-weight:600;font-size:14px}
.st-shift.on{background:var(--brand-soft);color:var(--accent)}
.st-count{flex:none;display:flex;flex-direction:column;align-items:center;min-width:64px;padding:8px 10px;border-radius:14px;background:var(--surface);border:1px solid var(--line)}
.st-count b{font-size:26px;line-height:1;font-variant-numeric:tabular-nums}
.st-count span{font-size:12px;color:var(--muted);margin-top:4px;white-space:nowrap}
.st-dnav{display:flex;align-items:center;gap:8px;margin:0 0 12px}
.st-dnav .ib{width:40px;height:40px;border-radius:10px;border:1px solid var(--line);background:var(--surface);font-size:20px}
.st-dnav .btn.here{background:var(--brand-soft);color:var(--accent)}
.st-next{display:block;width:100%;text-align:left;padding:14px 16px;margin:0 0 14px;border-radius:16px;border:1px solid var(--brand-line);background:var(--brand-soft);color:var(--fg)}
.st-next.now{border-color:var(--accent)}
.st-next .eyebrow{color:var(--accent)}
.st-next-row{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin:4px 0 2px}
.st-next-t{font-size:24px;font-variant-numeric:tabular-nums}
.st-next-n{font-size:20px}
.st-next-in{margin-left:auto;font-weight:600;color:var(--accent);white-space:nowrap}
.st-list{display:flex;flex-direction:column;gap:8px}
.st-bk{display:flex;gap:12px;width:100%;text-align:left;padding:12px 14px;border-radius:14px;border:1px solid var(--line);background:var(--surface);color:var(--fg)}
.st-bk:active{background:var(--surface-2)}
.st-bk.cancelled{opacity:.6}
.st-bk.cancelled .st-nm b{text-decoration:line-through}
.st-time{flex:none;width:52px;display:flex;flex-direction:column;font-variant-numeric:tabular-nums}
.st-time b{font-size:17px}
.st-time span{color:var(--muted);font-size:13px}
.st-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}
.st-nm{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.st-nm b{font-size:17px}
.st-sv{font-size:14px}
.st-line{font-size:14px;color:var(--fg);overflow-wrap:anywhere}
.st-line .lbl{color:var(--muted);font-weight:600;margin-right:6px}
.st-allergy{font-size:14px;color:var(--danger);background:var(--danger-soft);border-radius:8px;padding:4px 8px;overflow-wrap:anywhere}
.st-allergy b{margin-right:6px}
.st-mk{display:inline-flex;align-items:center;padding:1px 8px;border-radius:999px;font-size:12px;font-weight:700;white-space:nowrap;background:var(--surface-2);color:var(--muted)}
.st-mk.new{background:color-mix(in srgb,var(--ok) 14%,var(--surface));color:var(--ok)}
.st-mk.req{background:var(--brand-soft);color:var(--accent)}
.st-mk.pkg{background:var(--surface-2);color:var(--fg)}
.st-mk.late,.st-mk.wait{background:color-mix(in srgb,var(--warn) 16%,var(--surface));color:var(--warn)}
.st-mk.chg{background:var(--accent);color:var(--brand-ink)}
.st-free{font-size:13px;color:var(--muted);text-align:center;padding:2px 0;border-left:2px dashed var(--line);margin-left:26px}
.st-block{padding:10px 14px;border-radius:12px;background:var(--surface-2);color:var(--muted);font-size:14px}
.st-empty,.st-done{padding:16px;margin:0 0 12px;display:flex;flex-direction:column;gap:6px}
.st-week{display:flex;align-items:baseline;justify-content:space-between;padding:12px 16px;margin:0 0 10px}
.st-week b{font-size:20px}
.st-hours{display:flex;flex-direction:column;gap:6px}
.st-hrow{display:grid;grid-template-columns:minmax(0,11em) minmax(0,1fr) auto;align-items:center;gap:10px;width:100%;text-align:left;padding:12px 14px;border-radius:12px;border:1px solid var(--line);background:var(--surface);color:var(--fg);font-size:15px}
.st-hrow.today{border-color:var(--accent)}
.st-hrow.off{background:var(--surface-2);color:var(--muted)}
.st-hd{font-weight:600}
.st-hs{display:flex;flex-wrap:wrap;gap:4px 8px;align-items:center;font-variant-numeric:tabular-nums}
.st-hn{color:var(--muted);font-size:13px;white-space:nowrap}
@media (max-width:560px){.st-hrow{grid-template-columns:1fr auto}.st-hs{grid-column:1 / -1;grid-row:2}}
/* the booking and client card */
.st-sheet-when{color:var(--muted);margin:2px 0 8px}
.st-sheet-marks{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:6px}
.st-sheet-sec{display:flex;flex-direction:column;gap:6px;padding:12px 0;border-top:1px solid var(--line)}
.st-note{display:flex;flex-direction:column;gap:4px;padding:10px 12px;border-radius:12px;background:var(--surface-2);margin-top:6px}
.st-note-b{white-space:pre-wrap;overflow-wrap:anywhere;font-size:14px}
.st-note-new{display:flex;flex-direction:column;gap:6px}
.st-note-new textarea{width:100%;min-height:84px;padding:10px 12px;border-radius:12px;border:1px solid var(--line);background:var(--surface);color:var(--fg);font:inherit;font-size:16px}
/* her column on the shared calendar */
.st-app .cal-col.mine .ch{color:var(--accent);font-weight:700;box-shadow:inset 0 -3px 0 var(--accent)}
.st-app .cal-bk:not(.mine){opacity:.82}
/* the signed-out page */
.st-login .sp-empty input{width:100%;min-height:44px;padding:10px 12px;border-radius:10px;border:1px solid var(--line);background:var(--surface);color:var(--fg);font-size:16px}
.st-login .sp-empty label{font-weight:600;font-size:14px}
.st-login .sp-empty .btn{min-height:44px}

/* phase 20 (A): the Staff tab — the list, the card, the add sheet; the PIN pad's Forgot PIN (ui-x-staffs.js, ui-x-staffpin.js) */
.sf-q{margin:0 0 12px;max-width:420px}
.sf-row{gap:12px}
.sf-row .grow{min-width:0}
.sf-row .ttl,.sf-mail{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sf-right{display:flex;flex-direction:column;align-items:flex-end;gap:4px;flex:none;text-align:right}
.sf-chips{display:flex;gap:4px;flex-wrap:wrap;justify-content:flex-end}
.sf-chips:empty{display:none}
.faint{color:var(--faint)}
.sf-foot{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-top:14px;padding:0 4px}

.sf-head{display:flex;align-items:center;gap:12px;margin:0 36px 6px 0}
.sf-head .grow{min-width:0}
.sf-head h3{margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sf-head .sf-chips{flex-direction:column;align-items:flex-end}
.sf-sec{border-top:1px solid var(--line);padding:14px 0 6px}
.sf-add .field:first-child{margin-top:4px}
.sf-lbl{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);font-weight:600;margin-bottom:10px;flex:none}
.sf-fold{padding:0}
.sf-fold>summary{display:flex;align-items:center;gap:12px;min-height:52px;cursor:pointer;list-style:none}
.sf-fold>summary::-webkit-details-marker{display:none}
.sf-fold>summary .sf-lbl{margin:0}
.sf-fold>summary::after{content:'';flex:none;width:8px;height:8px;border-right:2px solid var(--faint);border-bottom:2px solid var(--faint);transform:rotate(45deg);margin:-4px 4px 0 0;transition:transform .15s}
.sf-fold[open]>summary::after{transform:rotate(225deg);margin-top:4px}
.sf-sum{flex:1;min-width:0;text-align:right;color:var(--fg);font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sf-body{padding:0 0 12px}
.sf-svc-all{gap:8px;margin:0 0 6px}
.sf-svc-q{margin:0 0 8px}
.sf-cat .cat-h{margin:8px 0 2px}
.sf-line{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-height:44px;margin:0 0 6px}
.sf-line .grow{flex:1 1 auto;min-width:0}   /* the buttons sit at the right edge */
.sf-btns{display:flex;gap:8px;flex:none}
.sf-cols{gap:8px}
.sf-col{position:relative;padding:3px;min-height:auto;cursor:pointer}
.sf-col input{position:absolute;opacity:0;width:1px;height:1px}
.sf-col i{width:26px;height:26px}
.sf-col:has(input:checked){border-color:var(--fg);box-shadow:0 0 0 1px var(--fg)}
.sf-col:focus-within{outline:2px solid var(--brand);outline-offset:2px}
.sf-save{width:100%;margin-top:14px}
.sf-secline .lnk{font-size:15px}

/* the PIN pad: the reason under a new PIN, Forgot PIN */
.pn-why{min-height:18px;font-size:13px}
.pinpad .pn-forgot{margin-top:6px}
.pinpad .pn-lock{max-width:300px}
.pn-fg .sec-form,.pn-fg .col{width:100%;max-width:320px;text-align:left}
.pn-fg .btn{width:100%}

/* the icon rail (768–1279 px): the bell's unread badge sits inside the 32 px bell, so the brand block never overflows
   (found by walk-layout19-api once a PIN lock put an unread line in the bell; the layout system is ui-x-zlayout.css) */
.app-shell.rail .side-brand .bell .badge{right:-1px;top:-3px}

/* phase 21 (A): the figure + colour picker, the invite panel (link, Copy link / Text it, Resend) */
.sf-figs{display:flex;gap:10px;margin:0 0 10px}
.sf-fig{position:relative;display:inline-flex;padding:3px;border:2px solid transparent;border-radius:50%;cursor:pointer;min-height:auto}
.sf-fig input{position:absolute;opacity:0;width:1px;height:1px}
.sf-fig .avatar{width:48px;height:48px}
.sf-fig:has(input:checked){border-color:var(--fg)}
.sf-fig:focus-within{outline:2px solid var(--brand);outline-offset:2px}
.sf-inv{display:flex;flex-direction:column;gap:10px;margin:4px 0 8px}
.sf-inv-st{display:flex;gap:6px;flex-wrap:wrap}
.sf-err{color:var(--bad,#b3261e)}
.sf-link{font-size:13px;color:var(--muted)}
.sf-inv-btns{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.sf-inv-btns .btn{min-height:48px;font-size:16px}
.sf-inv-more{justify-content:flex-start}
.sf-row .sf-err{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* phase 22 (C, Martin's 12): the icon picker — a live preview, then figures, skin and hair in rows of pictures (no words) */
.sf-avp{display:flex;gap:16px;align-items:flex-start;margin:0 0 10px}
.sf-avbig{width:72px;height:72px;flex:none;border-radius:50%;overflow:hidden}
.sf-avbig svg{width:100%;height:100%;display:block}
.sf-avrows{display:flex;flex-direction:column;gap:6px;min-width:0;flex:1}
.sf-avrow{display:flex;flex-wrap:wrap;gap:2px}
.sf-avrow.off{opacity:.3;pointer-events:none}
.sf-av,.sf-sw{display:grid;place-items:center;width:44px;height:44px;padding:0;border:0;border-radius:50%;background:none;cursor:pointer}
.sf-av .avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;box-shadow:0 0 0 2px transparent}
.sf-av .avatar svg{width:100%;height:100%;display:block}
.sf-av.on .avatar{box-shadow:0 0 0 2px var(--surface),0 0 0 4px var(--fg)}
.sf-sw i{display:block;width:26px;height:26px;border-radius:50%;box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--fg) 22%,transparent)}
.sf-sw.on i{box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--fg) 22%,transparent),0 0 0 2px var(--surface),0 0 0 4px var(--fg)}
.sf-av:focus-visible,.sf-sw:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
@media (max-width:420px){.sf-avp{flex-direction:column;align-items:center}.sf-avrows{width:100%}.sf-avrow{justify-content:center}}
.sf-avfigs .sf-av[data-g="m"][data-s="short"]{margin-left:8px}

/* phase 24 (D): the 起 / from mark before a service's price on the booking page, and the importer's Team / from cells */
.svc-from{font-size:12px;font-weight:500;color:var(--muted);margin-right:1px}
.imx-td.c-team{color:var(--muted);font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.imx-td.c-team.miss{color:var(--warn)}
/* the from toggle: a 44 px tap target drawing a 32 px pill (phone rule: 44 hit area, the row stays 36 tall) */
.svi-from{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;padding:0;border:0;background:transparent;color:var(--muted);font-size:12px;font-weight:600;cursor:pointer}
.svi-from i{display:inline-flex;align-items:center;height:32px;padding:0 10px;border-radius:999px;border:1px solid var(--line);background:var(--surface);font-style:normal}
.svi-from.on i{border-color:var(--brand);background:var(--brand-soft);color:var(--accent)}
/* a phone: the card gets the from toggle beside the name and the Team beside the minutes */
@media (max-width:760px){
  .svi-r{grid-template-columns:40px auto minmax(0,1fr) 64px 64px 72px;grid-template-areas:"tick st cat cat cat cat" ". name name name name from" ". nameEn nameEn team dur price"}
  .svi-r>.c-from{grid-area:from;justify-self:end}.svi-r>.c-team{grid-area:team}
  .svi-r .svi-from i{height:30px;padding:0 8px}
}
/* the picker's button reads 试传 / Test upload (two characters in Chinese): keep it a visible, tappable button */
.fp-drop .fp-btn{min-width:96px;min-height:36px;justify-content:center}

/* ---------- phase 18 (A1, B4): the Booking page button and sheet; "booked as" ---------- */
.bp-btn{display:inline-flex;align-items:center;gap:8px}
.top-bp{width:40px;height:40px;justify-content:center;border-radius:10px;color:var(--accent);flex:none}
.top-bp .nav-l{display:none}
.top-bp:active{background:var(--surface-2)}
.side-bp{color:var(--accent)!important;border:1px solid var(--brand-line);margin:0 0 6px}
.dash-bp{margin-left:auto}
.dash-bp .nav-ic{width:18px;height:18px}
.bp-link{display:flex;align-items:center;gap:8px;padding:12px 14px;border-radius:12px;background:var(--surface-2);font-size:15px;font-weight:600;word-break:break-all;margin:6px 0 14px}
.bp-qr{display:flex;justify-content:center;padding:14px;background:#fff;border-radius:14px;border:1px solid var(--line);width:max-content;margin:0 auto 16px}
.bp-qr img,.bp-qr canvas{display:block;width:200px;height:200px}
.bp-acts{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.bp-acts .btn{width:100%}
.bp-acts .btn.ghost{grid-column:1/-1}
/* B6: the legend in the calendar's ⋯ menu */
.gc-legend{display:grid;gap:8px;margin:6px 0 4px}
.gc-leg-row{display:flex;align-items:center;gap:10px;font-size:14px}
.gc-leg-row .gc-st{min-width:26px;height:22px;font-size:13px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;font-style:normal;font-weight:800;
  color:var(--stk);background:color-mix(in srgb,var(--stk) 16%,var(--surface));box-shadow:0 0 0 1px color-mix(in srgb,var(--stk) 45%,transparent)}
/* B3: why a staff column cannot take bookings */
.gc .ch .why{color:var(--danger);font-weight:600}
/* B17: the promotion link */
.pl-box{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:12px 14px;margin:12px 0;border-radius:12px;border:1px solid var(--brand-line);background:var(--brand-soft)}
.pl-box .grow{display:flex;flex-direction:column;gap:2px;min-width:200px}
.pl-box .pl-url{margin:4px 0 0;font-size:13px;padding:6px 10px;background:var(--surface)}
.pl-qr{background:#fff;padding:8px;border-radius:10px}
.pl-qr img,.pl-qr canvas{width:120px;height:120px;display:block}
.pl-banner{display:flex;align-items:center;gap:10px;padding:12px 14px;margin:4px 0 12px;border-radius:14px;background:color-mix(in srgb,var(--ok) 12%,var(--surface));border:1px solid color-mix(in srgb,var(--ok) 35%,var(--line))}
.pl-banner .grow{display:flex;flex-direction:column;gap:2px;min-width:0}
.pl-tag{flex:none;font-weight:800;color:var(--ok);font-size:15px}
/* B18: her phone, in the staff editor */
.sp-box{padding:12px 14px;border:1px solid var(--line);border-radius:12px;margin:8px 0 14px}
.sp-link{display:flex;flex-direction:column;gap:8px;margin-top:10px}
.sp-link .bp-link{margin:0}
.rf-row{margin-top:8px;display:flex;justify-content:flex-end}
/* /app/staff on a browser that is not set up */
.sp-empty{padding:20px 18px;display:flex;flex-direction:column;gap:14px;margin-top:8px}
.sp-empty h2{font-size:20px}
.sp-way{display:flex;flex-direction:column;gap:6px;padding:12px 14px;border:1px solid var(--line);border-radius:12px}
.sp-way p{color:var(--muted);font-size:14px}

/* phase 15: 💬 one-tap texts, the chat thread, the Test SMS card */
.txt-who{display:flex;align-items:center;gap:10px;padding:4px 0}
.txt-chips{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.txt-chip{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:4px;min-height:64px;padding:10px 14px;border-radius:14px;border:1px solid var(--line);background:var(--surface);color:var(--fg);text-align:left;cursor:pointer}
.txt-chip .l{font-weight:700;font-size:15px}
.txt-chip .s{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums}
.txt-chip .s.why{color:var(--warn)}
.txt-chip.off{opacity:.55;cursor:not-allowed}
.txt-chip:not(.off):hover{border-color:var(--brand)}
.txt-bubble{max-width:86%;padding:10px 14px;border-radius:18px;font-size:15px;line-height:1.4;white-space:pre-wrap;word-break:break-word}
.txt-bubble.out{background:var(--brand);color:var(--brand-ink,#fff);border-bottom-right-radius:6px;align-self:flex-end}
.txt-bubble.in{background:var(--surface);border:1px solid var(--line);border-bottom-left-radius:6px;align-self:flex-start}
.txt-bubble.preview{max-width:100%;align-self:stretch}
.txt-thread{display:flex;flex-direction:column;gap:10px;max-height:420px;overflow-y:auto;padding:6px 0}
.txt-row{display:flex;flex-direction:column;gap:2px}
.txt-row.out{align-items:flex-end}
.txt-row.in{align-items:flex-start}
.txt-meta{font-size:11px;color:var(--muted);padding:0 6px;font-variant-numeric:tabular-nums}
.txt-tick{font-weight:700}
.txt-tick.ok{color:var(--ok)}
.txt-tick.bad{color:var(--danger)}
.txt-thread-head{display:flex;align-items:center;gap:8px;margin-bottom:4px}
.txt-thread-head h4{margin:0;font-size:15px}
.txt-reply{display:flex;gap:8px;margin-top:10px}
.txt-reply .input{flex:1;min-height:44px}
.txt-card{padding:14px 16px}
.txt-custom{width:100%;min-height:96px;font:inherit;resize:vertical}
.txt-inline{min-height:32px;padding:0 6px;font-size:14px}
.txt-missing{margin:6px 0 4px 18px;padding:0;font-size:13px}
.txt-missing code{font-size:12px}
@media (min-width:900px){.txt-chips{grid-template-columns:1fr 1fr 1fr}}
/* phase 15 step 3: the ⓘ that holds the explanation (ui-x-less.js) */
.ib.info{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;padding:0 6px;border-radius:999px;border:0;background:transparent;color:var(--muted);font-size:16px;line-height:1;cursor:pointer;vertical-align:middle}
.ib.info:hover{color:var(--accent)}
.help-line{display:flex;align-items:center;gap:4px;color:var(--muted);font-size:13px;margin:0}
/* phase 20 (19): the 中 / EN switch beside the client's name */
.txt-who .txt-lang{flex:none}
.txt-lang button{min-width:44px;min-height:36px;font-weight:700}
@media (max-width:767px){.txt-lang button{min-height:44px}}
/* phase 20 review (8): the preview keeps its height when 中 / EN rewrites it (the English text is longer; the sheet jumped ~40 px) */
.txt-bubble.preview{min-height:7.6em}

/* phase 23 (E): the "Texts are paused" bar on the Calendar and Texts (ui-x-textstate.js): one thin line, calm amber, no button */
.txs-bar{display:flex;align-items:center;gap:8px;min-height:32px;padding:6px 12px;margin:8px 0 2px;border-radius:var(--radius);
  background:color-mix(in srgb,var(--warn) 10%,var(--surface));border:1px solid color-mix(in srgb,var(--warn) 35%,var(--line));
  color:var(--fg);font-size:13px;line-height:1.3}
.txs-bar .nav-ic{width:16px;height:16px;flex:none;color:var(--warn)}
.txs-bar span{min-width:0}

/* ---------- phase 18 (A2): the Appearance switch ---------- */
.theme-seg button{display:inline-flex;align-items:center;gap:4px;white-space:nowrap}
.theme-tog{display:inline-flex;align-items:center;gap:6px;min-height:36px;padding:0 12px;border-radius:999px;border:1px solid var(--line);background:var(--surface);color:var(--fg);font-size:13px;font-weight:600}
.theme-tog .g{font-size:15px;line-height:1}
.theme-tog.icon{width:40px;justify-content:center;padding:0}
.theme-tog.icon .nav-l{display:none}
.set-theme{flex-wrap:wrap;gap:8px}
@media (max-width:420px){.ios-row.static .theme-seg button{padding:0 9px}}
/* AA contrast in both themes (walk-theme-api checks every visible text): faint text is never fainter than 4.5:1, badges on the
   danger colour use its ink, the client avatars sit on the page's own grey, the selected day reads its labels in the brand ink */
:root{--faint:#6f6a62}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--faint:#9a958c}}
:root[data-theme="dark"]{--faint:#9a958c}
.chev,.ios-row .chev,.dash-row .chev{color:var(--muted)}
.nav-n,.badge{color:var(--on-danger,#fff)}
.gc .cal-col.wk.today .ch .dn,.gm-day.today .gm-num{color:var(--on-danger,#fff)}
.avatar[style*="var(--muted)"]{background:var(--surface-2);color:var(--fg);box-shadow:inset 0 0 0 1px var(--line)}
.day.sel .dw,.day.sel .dm{color:var(--brand-ink)}
.day .cnt{background:var(--brand);color:var(--brand-ink)}
.day.sel .cnt{background:var(--brand-ink);color:var(--brand)}
.gc .cal-bk>span.t,.gc .cal-bk .nm>.t{color:color-mix(in srgb,var(--fg) 85%,transparent)}
:root{--ok:#226b40;--warn:#8a5207}
/* the running-late / wants-to-move signals: dark text on their colour in both themes (white on amber was 2.2:1 in dark) */
.gc-sig.late,.gc-sig.move{color:#1d1b18}
:root:not([data-theme="dark"]) .gc-sig.late{background:#e9b04f}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .gc-sig.late{background:var(--st-wait)}}

/* phase 20, Part C: the desk's text switch, the checkout's "come back" chips, Settings › Texts */
.tx-switch{margin:4px 0}
.co-recall{display:flex;flex-direction:column;gap:6px;margin:4px 0 10px}
.co-recall .lbl{font-size:13px;font-weight:600;color:var(--muted)}
.co-recall .chips{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:6px}
.co-recall .chipbtn{min-height:40px;justify-content:center;text-align:center;padding:0 4px;white-space:nowrap}
.tx-list .tx-row{padding:10px 0;border-bottom:1px solid var(--line)}
.tx-list .tx-row:last-child{border-bottom:0}
.tx-list .set-tog small{display:block;font-weight:400;color:var(--muted);font-size:12px;margin-top:2px}
.tx-words{display:flex;flex-direction:column;gap:4px;margin-top:6px}
.tx-words p{margin:0;padding:6px 10px;border-radius:12px;background:var(--surface-2);font-size:12px;line-height:1.45;color:var(--fg);overflow-wrap:anywhere}
.tx-words p[lang="en"]{color:var(--muted)}

/* ---------- phase 18 (A4): the calendar on the shop's widescreen monitor ----------
   The calendar takes the full width on a wide screen and the rows fill the height (ui-x-gcal.js gcPpm); text scales with the width
   and the zoom (--gc-fs).
   Phase 19 (Part D): the 72 px rail that appeared on the calendar only (≥ 1400 px) and the bigger 日历 icon are gone: the shell is
   chosen by the width alone (ui-x-zlayout.css), so nothing jumps when you leave the calendar. */
body.on-cal .app-main{max-width:none}
/* the zoom − / + */
.gc-zoom button{min-width:36px}
.gc-zoom button:disabled{opacity:.35}
/* the staff filter: All / Amy / Vicky … */
.gc-staff{margin:2px 0 6px;padding-bottom:4px}
.gc-staff .chipbtn{min-height:38px}
.gc-staff .chipbtn .avatar{width:26px;height:26px}
/* scaled text in the grid (1 at 1500 px wide, up to 1.4 at 2100 px and more; times √zoom) */
#gc-cal .cal-bk .nm>b,#gc-cal .cal-bk>b{font-size:calc(12px*var(--gc-fs,1))}
#gc-cal .cal-bk>span.sv,#gc-cal .cal-bk>span.t,#gc-cal .cal-bk .nm>.t{font-size:calc(11px*var(--gc-fs,1))}
#gc-cal .cal-bk.compact .nm>b{font-size:calc(11px*var(--gc-fs,1))}
#gc-cal .cal-bk .gc-st{height:calc(18px*var(--gc-fs,1));min-width:calc(19px*var(--gc-fs,1));font-size:calc(11.5px*var(--gc-fs,1))}
#gc-cal .cal-col .ch{height:calc(48px*var(--gc-fs,1));font-size:calc(13px*var(--gc-fs,1))}
#gc-cal .cal-col .ch small{font-size:calc(11px*var(--gc-fs,1))}
#gc-cal .cal-gutter .gh{height:calc(48px*var(--gc-fs,1))}
#gc-cal .cal-gutter .hl{font-size:calc(11px*var(--gc-fs,1))}
#gc-cal .cal-col .ch .avatar.sm{width:calc(28px*var(--gc-fs,1));height:calc(28px*var(--gc-fs,1))}
#gc-cal .cal-bk{padding:calc(2px*var(--gc-fs,1)) calc(6px*var(--gc-fs,1))}
/* B5 ("their names are moving, not fixed in position"): while a block is dragged or stretched only the ghost carries the name, at
   the same place and size as on the block (top-left, pinned); the lifted original keeps its place with no text; nothing beside it
   moves until the drop */
.gc .cal-bk{display:flex;flex-direction:column;justify-content:flex-start}
.gc .cal-bk.short{flex-direction:row}
.gc .cal-bk.gc-lifted>*:not(.gc-rs){visibility:hidden}
.gc-ghost{padding:calc(2px*var(--gc-fs,1)) calc(6px*var(--gc-fs,1));display:flex;flex-direction:column;justify-content:flex-start}
.gc-ghost b{font-size:calc(12px*var(--gc-fs,1))}
.gc-ghost span{font-size:calc(11px*var(--gc-fs,1))}
/* ---------- phase 20 (15, 27): blocks that never squeeze, marks that never clip ----------
   Martin: "the text is all squeezed", "the ticks don't show properly". The block holds whole lines only (ui-x-gcal.js gcLines picks
   1, 2 or 3+ lines from its height): each line is exactly one line-height, nothing shrinks, so lines can no longer be pressed on top
   of each other. The status pill is no taller than the name line and the name line does not clip it. */
#gc-cal .cal-bk{--lh:calc(15px*var(--gc-fs,1));display:flex;flex-direction:column;justify-content:flex-start;overflow:hidden;line-height:var(--lh);padding:calc(2px*var(--gc-fs,1)) calc(6px*var(--gc-fs,1)) 0}
#gc-cal .cal-bk.compact{--lh:calc(14px*var(--gc-fs,1));padding:calc(1px*var(--gc-fs,1)) calc(4px*var(--gc-fs,1)) 0}
#gc-cal .cal-bk>span{flex:none;display:flex;align-items:center;min-height:0;height:var(--lh);line-height:var(--lh);min-width:0}
#gc-cal .cal-bk>span.nm{gap:4px;overflow:visible}
#gc-cal .cal-bk .nm>b{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;line-height:var(--lh)}
#gc-cal .cal-bk.short{flex-direction:column}
#gc-cal .cal-bk.short>span.nm{display:flex;width:100%}
#gc-cal .cal-bk.short .nm>b .t{font-weight:500;font-size:inherit}
#gc-cal .cal-bk>span.sv{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:var(--sv-l,1);height:auto;max-height:calc(var(--lh)*var(--sv-l,1));white-space:normal;overflow:hidden;overflow-wrap:anywhere}
#gc-cal .cal-bk.compact .nm>b,#gc-cal .cal-bk.compact>span.t,#gc-cal .cal-bk.compact>span.sv{font-size:calc(11px*var(--gc-fs,1))}
#gc-cal .cal-bk>span.t .co-chipbal{position:static;margin-left:auto;flex:none;line-height:calc(13px*var(--gc-fs,1))}
#gc-cal .cal-bk .gc-st,#gc-cal .cal-bk .gc-sig{flex:none;height:calc(14px*var(--gc-fs,1));min-width:calc(16px*var(--gc-fs,1));padding:0 calc(2px*var(--gc-fs,1));font-size:calc(11px*var(--gc-fs,1));line-height:1;display:inline-flex;align-items:center;justify-content:center;gap:1px;border-radius:999px;overflow:visible}
#gc-cal .cal-bk .gc-st.wide{min-width:calc(21px*var(--gc-fs,1))}
#gc-cal .cal-bk.compact .gc-st,#gc-cal .cal-bk.compact .gc-sig{height:calc(12.5px*var(--gc-fs,1));min-width:calc(14px*var(--gc-fs,1))}
.gc-mk{display:block;flex:none;width:11px;height:10px;overflow:visible}
#gc-cal .gc-mk{width:calc(11px*var(--gc-fs,1));height:calc(10px*var(--gc-fs,1))}
.gc-st.wide .gc-mk{width:14px}
#gc-cal .gc-st.wide .gc-mk{width:calc(14px*var(--gc-fs,1))}
.gc-sig .gc-mk{width:9px;height:9px}
#gc-cal .gc-sig .gc-mk{width:calc(9px*var(--gc-fs,1));height:calc(9px*var(--gc-fs,1))}
/* the same pill elsewhere (month, the legend, the Dashboard): one size, the glyph centred */
.gc-st{display:inline-flex;align-items:center;justify-content:center;font-style:normal}
.gm-ev .gc-st,.gc-legend .gc-st,.dash-row .gc-st{height:16px;min-width:18px;padding:0 3px;border-radius:999px;overflow:visible}
.gm-ev .gc-st.wide,.gc-legend .gc-st.wide,.dash-row .gc-st.wide{min-width:22px}
/* a narrow block (a phone column, two bookings side by side in a week): the name, then the start; the service is on hover and one tap away */
#gc-cal .cal-bk{container-type:inline-size}
@container (max-width:110px){#gc-cal .cal-bk>span.sv,#gc-cal .cal-bk .te,#gc-cal .cal-bk .co-chipbal{display:none}}
.gc-vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.gc-st{position:relative}
#gc-cal .cal-bk>span.t{gap:0}
#gc-cal .cal-bk>span.t .co-chipbal{margin-left:auto}
#gc-cal .cal-bk.short .co-chipbal{display:none}
#gc-cal .cal-bk.short .nm>b .t{color:inherit}
#gc-cal .cal-bk .nm>.mk{flex:none;font-size:calc(10px*var(--gc-fs,1));line-height:1}
/* the status pill shares its colour classes (st-done …) with the staff app's empty-state boxes (ui-x-staffapp.css .st-done): a pill
   never takes their padding, margin or column layout */
.gc-st.st-done{margin:0;flex-direction:row;gap:0}
.cc-st.st-done{margin:0;flex-direction:row;gap:4px;padding:0 9px}
#gc-cal .cal-bk .gc-st.st-done{padding:0 calc(2px*var(--gc-fs,1))}
.gm-ev .gc-st.st-done,.gc-legend .gc-st.st-done,.dash-row .gc-st.st-done{padding:0 3px}
/* a very narrow block (three bookings side by side in a week): the mark loses its pill and keeps the glyph; a sliver keeps the name only */
@container (max-width:72px){#gc-cal .cal-bk .gc-st{min-width:0;padding:0;background:none;box-shadow:none}#gc-cal .cal-bk>span.nm{gap:2px}#gc-cal .cal-bk .nm>.mk,#gc-cal .cal-bk .gc-sig{display:none}}
/* phase 20 review (3): a sliver (a phone's week column) keeps the status as a 6 px dot in its colour, never nothing */
@container (max-width:40px){#gc-cal .cal-bk .gc-st{width:6px;min-width:6px;height:6px;padding:0;border-radius:50%;background:var(--stk);box-shadow:none}#gc-cal .cal-bk .gc-st .gc-mk{display:none}}
/* ---------- phase 20 review ----------
   (4) the grid: at most 640 px a column, from the left edge under the head (ui-x-gcal.js gcGridHTML) */
/* (9) the calendar ends at the window's bottom: no page padding under it on a computer (the phone keeps room for its bottom bar) */
@media (min-width:768px){body.on-cal .app-main{padding-bottom:8px}}
/* (11) a finished visit: the fill and the stripe fade, the text keeps its contrast (opacity .6 dimmed it to ~3:1 in dark) */
#gc-cal .cal-bk.completed{opacity:1;background:color-mix(in srgb,var(--stc) 8%,var(--surface));border-left-color:color-mix(in srgb,var(--stc) 45%,var(--surface))}
/* (3) the bookings that do not fit a crowded lane: "+N", one tap lists them */
#gc-cal .gc-more{position:absolute;z-index:1;border-radius:6px;background:var(--surface-2);box-shadow:0 0 0 1px var(--line);color:var(--fg);font-weight:700;font-size:calc(12px*var(--gc-fs,1));line-height:1;display:flex;align-items:flex-start;justify-content:center;padding-top:calc(3px*var(--gc-fs,1));font-variant-numeric:tabular-nums;cursor:pointer}
#gc-cal .gc-more:hover{background:var(--line)}
/* (12) one pill style for every mark: the running-late and wants-to-move signals are tinted pills like the others */
.gc-sig.late,.gc-sig.move,:root:not([data-theme="dark"]) .gc-sig.late.late{color:var(--stk);background:color-mix(in srgb,var(--stk) 16%,var(--surface));box-shadow:0 0 0 1px color-mix(in srgb,var(--stk) 45%,transparent)}
.gc-sig.late{--stk:var(--st-wait)}.gc-sig.move{--stk:var(--st-busy)}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .gc-sig.late.late{background:color-mix(in srgb,var(--stk) 16%,var(--surface))}}
/* (12) the legend: the marks in a column of one width, so every label starts at the same place */
.gc-leg-row>.gc-st,.gc-leg-row>.gc-sig{width:30px;min-width:30px;height:22px;padding:0;flex:none;border-radius:999px;display:inline-flex;align-items:center;justify-content:center}
.gc-leg-row .gc-mk{width:13px;height:12px}.gc-leg-row .gc-st.wide .gc-mk{width:17px}

/* ---------- phase 20 (17): the client card, with less on it (ui-x-zcard.js) ---------- */
.cc-prof{gap:12px}
.cc-prof .co-name{padding-right:48px}   /* phase 20 review (5): the name never runs under the sheet's × */
.cc-prof .co-name h3{margin:0;font-size:22px;font-family:var(--font-display);line-height:1.2;min-width:0;overflow-wrap:anywhere}
.cc-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(118px,1fr));gap:10px 14px}
.cc-tiles>div{display:flex;flex-direction:column;gap:1px;min-width:0}
.cc-tiles span{font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cc-tiles b{font-size:17px;line-height:1.25}
.cc-tiles small{font-size:11px;color:var(--muted)}
.cc-tiles .owing b{color:var(--danger)}
/* one row of actions: the main ones share the row, ⋯ keeps its size */
.cc-acts{display:flex;gap:8px;align-items:stretch}
.cc-acts>.btn{flex:1 1 0;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-height:44px;padding:0 10px}
.cc-more{position:relative;flex:none}
.cc-more>summary{list-style:none;width:44px;min-width:44px;height:100%;min-height:44px;padding:0;display:inline-flex;align-items:center;justify-content:center;cursor:pointer}
.cc-more>summary::-webkit-details-marker{display:none}
.cc-menu{position:absolute;right:0;top:calc(100% + 6px);z-index:5;min-width:180px;display:flex;flex-direction:column;padding:6px;background:var(--surface);border:1px solid var(--line);border-radius:12px;box-shadow:0 12px 32px rgba(0,0,0,.18)}
.cc-menu button{text-align:left;min-height:44px;padding:0 12px;border-radius:8px;font-size:15px;color:var(--fg);white-space:nowrap}
.cc-menu button:hover{background:var(--surface-2)}
/* one status per visit: the calendar's mark and one word, in the status colour */
.cc-st{flex:none;display:inline-flex;justify-content:flex-start;min-width:84px;margin:0;flex-direction:row;align-items:center;gap:4px;height:24px;padding:0 9px;border-radius:999px;font-size:12px;font-weight:700;white-space:nowrap;
  color:var(--stk);background:color-mix(in srgb,var(--stk) 13%,var(--surface))}
.cc-st.st-ok{--stk:var(--st-ok)}.cc-st.st-sent,.cc-st.st-done{--stk:var(--st-done)}.cc-st.st-wait{--stk:var(--st-wait)}.cc-st.st-call{--stk:var(--st-call)}
.cc-st .gc-mk{width:12px;height:11px}
.cc-st .gc-mk.mk-ok{width:15px}
.cc-visits .item{gap:10px}
.cc-visits .item>.cc-st{display:inline-flex;flex-direction:row;align-items:center}
.cc-tiles>div.dim{opacity:.55}
.cc-menu button:disabled{opacity:.45;cursor:default;background:none}
.cc-st.st-none{--stk:var(--muted)}
.cc-mk0{display:block;flex:none;width:12px;height:11px}
.cc-st .gc-mk.mk-ok+*,.cc-st .gc-mk{flex:none}
.co-next{display:flex;align-items:flex-start;gap:6px}
.cc-ic{flex:none;width:16px;height:15px;margin-top:2px;color:var(--muted)}

/* ---------- phase 19 (Part D): one navigation system, chosen by the width only ----------
   Martin: "make sure it scales well! the items are always all over the place, especially the tabs and icons".
   The measured faults (walk-layout19-api) came from the shell changing with the tab (a rail on the calendar only), three
   breakpoints for one menu, icons of four sizes (an emoji bell, text glyphs ‹ › − + ⋯ ◐), bars that wrap differently per view, and
   labels that wrap. The rules, in one place (this sheet sorts after every ui-x sheet on purpose):
     < 768 px      phone: the top bar and the bottom bar (five places, or four in the staff app)
     768–1279 px   tablet / small laptop: an 84 px rail on every tab, the icon over a one-line label
     ≥ 1280 px     the 232 px sidebar on every tab, or the rail when the person collapses it (remembered; every tab alike)
   One icon set (.nav-ic, stroked SVG) at one size; a label never wraps (it shortens with … and keeps its title); a bar keeps one
   height; the calendar's head has the same parts in the same places in every view; only the list of places scrolls, the footer
   (language, appearance, the account) stays in view. */
:root{--nav-ic:22px;--ctl-h:36px;--rail-w:84px}
/* phase 24 (b): a button that cannot act yet is greyed with aria-disabled (not disabled), so a tap still answers with the reason */
.btn[aria-disabled="true"],button[aria-disabled="true"]{opacity:.45;cursor:not-allowed}
.rt-acts .btn{flex:1 1 0;min-width:0;padding-inline:10px}   /* a promotion's Save draft · Preview & send share the row on a phone */
.co-use-go{min-height:22px;padding:0 4px}
@media (max-width:767px){#sheet .co-use-go{min-height:44px;min-width:44px;margin-block:-11px}}   /* the › to a booking in a package's uses: the target grows, the line does not */
.nav-ic{width:var(--nav-ic);height:var(--nav-ic);flex:none}
.nav-gap{display:inline-block}
.nav-l,.viewtog button,.chipbtn,.gc-today,.toolbar .btn,.gc-head .btn{white-space:nowrap}
/* controls in a bar: one height, never squeezed */
.toolbar .btn.sm,.toolbar .viewtog button,.gc-head .btn.sm,.gc-head .viewtog button{min-height:var(--ctl-h);height:var(--ctl-h)}
.gc-head .ib,.gc-arrow,.gc-menu{width:var(--ctl-h);height:var(--ctl-h);min-width:var(--ctl-h);flex:none;display:inline-flex;align-items:center;justify-content:center;border-radius:50%;padding:0;color:var(--fg)}
.gc-head .ib:hover{background:var(--surface-2)}
.gc-zoom button,.gc-cols button{display:inline-flex;align-items:center;justify-content:center}
.gc-cols button:disabled{opacity:.45;cursor:default}
.bell{min-width:var(--ctl-h);min-height:var(--ctl-h);font-size:inherit;color:var(--fg)}
.theme-seg button{display:inline-flex;align-items:center;gap:6px}
.theme-seg .nav-ic,.theme-tog .nav-ic{--nav-ic:18px}
/* the page's header: the same top and at least the same height on every tab, the calendar included */
.toolbar{margin:14px 0 8px;min-height:44px}
.gc-head{margin:14px 0 8px}
/* ---- the calendar head: two fixed rows until there is room for one ---- */
.gc-head{display:flex;flex-direction:column;align-items:stretch;gap:8px}
.gc-nav{display:flex;align-items:center;gap:4px;min-width:0;max-width:100%;flex:none}
.gc-today{flex:none}
.gc-title{flex:1 1 0;width:0;min-width:0}   /* takes what is left and shortens with … (the whole title is its title attribute) */
.gc-tools{display:flex;align-items:center;gap:8px;flex-wrap:nowrap;min-width:0;max-width:100%}
.gc-tools .grow{flex:1 1 auto}
.gc-new-ph{margin-left:auto;width:var(--ctl-h);min-width:0;padding:0;justify-content:center;flex:none}
.gc-mid,.gc-wide{display:none}
.gc-menu-tools{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-top:8px}
@media (min-width:768px){.gc-mid{display:inline-flex}.gc-new-ph{display:none}}
@media (min-width:1024px){.gc-wide{display:inline-flex}}
@media (min-width:1366px){.gc-head{flex-direction:row;align-items:center;gap:12px}.gc-nav{flex:1 1 0}.gc-tools{flex:none}}
/* chip rows that scroll say so: the last chip fades at the edge */
.chips{padding-right:24px}
.rp-ranges .viewtog{flex-wrap:nowrap;overflow-x:auto;max-width:100%}
/* phase 20 QA (5): only when the row overflows (ui-x-qa20.js sets .ovf) */
.chips.ovf,.rp-ranges .viewtog.ovf{-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent)}
/* ---- phone ---- */
/* the page header on a phone: the title on its own line (as iOS does), the page's actions in one row under it, the same on
   every tab; a page without actions keeps one line */
@media (max-width:599px){
  .toolbar{flex-wrap:wrap;row-gap:8px}
  .toolbar>h2{flex:1 0 100%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .toolbar>:not(h2){flex:none}
  .toolbar>.grow{display:none}
  .toolbar>.row{flex-wrap:nowrap}
  .dash-toolbar .dash-bp{display:none}   /* the booking page is in the top bar */
}
.bot-item{min-height:56px;min-width:0}
.bot-item .nav-l{max-width:100%;overflow:hidden;text-overflow:ellipsis}
@media (max-width:599px){
  .theme-seg .t-l{display:none}       /* the three icons, each with its name for a screen reader (aria-pressed) */
  .theme-seg button{padding:0 12px}
  button.ios-row:has(.set-val:not(:empty)){display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:12px;row-gap:2px;min-height:62px}
  button.ios-row:has(.set-val:not(:empty)) .set-val{grid-column:1;grid-row:2;max-width:none;height:20px;line-height:20px;text-align:left;justify-content:flex-start}
  button.ios-row:has(.set-val:not(:empty)) .set-val .nav-dot{flex:none}
  button.ios-row:has(.set-val:not(:empty)) .chev{grid-column:2;grid-row:1 / 3;align-self:center}
}
.ios-row .grow{min-width:0;overflow:hidden;text-overflow:ellipsis}
.ios-row{min-height:52px;padding-top:6px;padding-bottom:6px}
.ios-row .theme-seg{padding:2px}
.ios-row .theme-seg button{height:34px;min-height:34px}
.ios-row .langpill{height:var(--ctl-h);min-height:var(--ctl-h)}
.ios-row .theme-seg{flex:none}
.ios-row.ios-ctl .grow{flex:1 1 auto}
.l-short{display:none}
@media (max-width:399px){.l-long{display:none}.l-short{display:inline}}
/* ---- the rail and the sidebar ---- */
@media (min-width:768px){
  .side-nav{padding-bottom:0;overflow-y:auto;overflow-x:hidden}
  .side-foot{position:sticky;bottom:0;background:var(--surface);padding-bottom:12px;z-index:1}
  .bp-btn,.sr-btn{gap:12px}
}
/* the rail: 768–1279 px always, and on a wide screen when the person collapses the menu (remembered on the device, every tab
   alike: the calendar gets the room without anything jumping when you change tabs). ui-x-nav.js navRail() sets .rail. */
@media (min-width:768px){
  .app-shell.rail{grid-template-columns:var(--rail-w) minmax(0,1fr)}
  .app-shell.rail .side-nav{padding:10px 6px 0;gap:2px}
  .app-shell.rail .side-brand{justify-content:center;padding:2px 0 8px;gap:2px}
  .app-shell.rail .side-brand .logo{width:32px;height:32px;font-size:14px;flex:none}
  .app-shell.rail .side-brand .bell{min-width:32px;width:32px;flex:none}
  .app-shell.rail .side-brand .bell .badge{right:-1px;top:-3px;min-width:16px;padding:0 4px;font-size:10px}   /* phase 20: a two-digit count stays inside the rail (it stuck out 2 px) */
  .app-shell.rail .side-brand .grow{display:none}
  .app-shell.rail .side-group{gap:2px;padding:4px 0}
  .app-shell.rail .side-item{flex-direction:column;justify-content:center;gap:3px;min-height:56px;padding:6px 2px;text-align:center}
  .app-shell.rail .side-item .nav-l{flex:none;font-size:11px;line-height:1.2;max-width:100%;overflow:hidden;text-overflow:ellipsis}
  .app-shell.rail .side-item .nav-n,.app-shell.rail .side-item .nav-dot{position:absolute;top:4px;right:8px}
  .app-shell.rail .side-bp{border:0!important;margin:0}
  .app-shell.rail .side-foot{align-items:center;gap:8px;padding:8px 0 12px}
  .app-shell.rail .side-foot .row{justify-content:center}
  .app-shell.rail .side-foot .langpill span,.app-shell.rail .side-foot .langpill a{padding:4px 7px}
  .app-shell.rail .side-foot .theme-tog{display:none}   /* on the rail, Appearance is in Settings (one control per line, nothing standing on end) */
  .app-shell.rail .side-acc{align-items:center;text-align:center;max-width:100%}
  .app-shell.rail .side-acc b{font-size:12px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .app-shell.rail .side-acc .muted{display:none}
  .app-shell.rail .side-links{flex-direction:column;align-items:center;gap:2px}
  .app-shell.rail .side-links .lnk{font-size:11px;white-space:nowrap}
  .app-shell.rail .app-main{padding:12px 20px 40px}
}
.nav-rail-tog{display:none}
@media (min-width:1280px){.nav-rail-tog{display:inline-flex}}
@media (min-width:1280px){.app-main{padding:16px 28px 48px}}

/* ---------- phase 20 QA (Martin: "check all the scaling and positioning of the tabs") ----------
   (1) above: a Settings row has a second line only when it has something to say (the summaries left the rows in phase 20). */
/* (3) on a phone every control is at least 44 × 44 px (Apple's minimum touch target). The first rule has no weight (:where), so
   anything already taller keeps its size; the second lifts the controls that were set smaller. The calendar's blocks are the grid. */
@media (max-width:767px){
  :root{--ctl-h:44px}
  :where(#app,#sheet) :where(button,a.btn,summary,select):not(:where(.cal *,.gm *)){min-height:44px}
  #app .btn,#sheet .btn,#app .viewtog button,#sheet .viewtog button,#app .chipbtn,#sheet .chipbtn,#app .tab,#sheet .tab,.langpill,
  #app .theme-seg button,#sheet .theme-seg button,#app .ios-row .theme-seg button{min-height:44px}
  #app .viewtog button,#sheet .viewtog button,#app .ib,#sheet .ib,.bell,#app .lnk,#sheet .lnk,#app .cl-link,#sheet .cl-link,
  #app .theme-seg button,#sheet .theme-seg button,[data-act="co-tender-del"],.top-bp,[data-act="theme-cycle"]{min-height:44px;min-width:44px}
  #app .rp-t th button,#app .rp-num{min-height:44px;min-width:44px;margin-block:-6px}   /* a report's sort headers and figures: the target grows, the table barely */
  #app .ios-row.static{padding-top:3.5px;padding-bottom:3.5px}   /* 44 + 7 + the 1 px line = the 52 px of every row */
  #app .ios-row .theme-seg{padding:0}
  #app .viewtog button,#sheet .viewtog button{flex-shrink:0}
  #app .cl-link,#sheet .cl-link{margin-block:-12px}   /* a name inside a line of text: the target grows, the line does not */
  #app .ios-row .theme-seg button{height:44px}
  #app label.check,#sheet label.check{min-height:44px;align-items:center}
  #app a[href]:not(.btn):not(.ios-row):not(.bot-item):not(.side-item),#sheet a[href]:not(.btn):not(.ios-row){display:inline-flex;align-items:center;justify-content:center;min-height:44px;min-width:44px}
  #app .rp-def,#sheet .rp-def{min-height:44px;min-width:44px;margin-block:-12px}   /* a term in a report label: the target grows, the line does not */
  #app .rp-kpi .rp-def{margin-block:-10px 0}
  #app .swatches .swatch{min-height:44px}   /* phase 24 (b): the brand colour swatches */
  #app .room-row [data-act="room-del"]{min-width:44px}   /* phase 24 (b): in a KPI card the term sits over the card's own padding, not over the figure under it */
}
.ib-f.chips{margin:0}
@media (max-width:359px){#app .ios-row{padding-left:12px;padding-right:12px;gap:8px}}   /* 320 px: "Appearance" beside three 44 px buttons */
/* (2) the rail fits an iPad held sideways: labels at 10 px (iOS's tab-bar size); the account, the poster, the staff app,
   appearance and sign-out are one tap on the shop's logo (they took four lines under the places); short windows get 44 px places */
.bp-short{display:none}
.side-logo{flex:none;display:inline-flex;padding:0;border-radius:10px}
.side-me-row{display:flex;align-items:center;gap:6px}
.nav-rail-tog .nav-ic{width:16px;height:16px}
@media (min-width:1280px){.nav-rail-tog{align-items:center;gap:6px;min-height:28px}}
@media (min-width:768px){
  .app-shell.rail .side-acc,.app-shell.rail .side-links{display:none}
  .app-shell.rail .side-item .nav-l{font-size:10px}
  /* (4) the booking page's place is not a second "selected" item */
  .app-shell.rail .side-bp:not(.on){color:var(--muted)!important}
  .app-shell.rail .side-bp .bp-full{display:none}
  .app-shell.rail .side-bp .bp-short{display:inline}
}
@media (min-width:768px) and (max-height:900px){
  .app-shell.rail .side-item{min-height:44px;padding:2px;gap:2px}
  .app-shell.rail .side-group{padding:2px 0}
  .app-shell.rail .side-brand{padding-bottom:4px}
  .app-shell.rail .side-foot{padding:6px 0 8px}
}
/* the full menu on a window up to 900 px tall: the poster / staff app / sign-out links live under the logo (as on the rail) */
@media (min-width:768px) and (max-height:900px){.side-links{display:none}}
/* an iPad held sideways in a browser (~700 px tall): the language moves into the logo's sheet so every place shows */
@media (min-width:768px) and (max-height:760px){.app-shell.rail .side-foot>.row{display:none}}
/* (6) dark: the selected segment is lighter than its track (it was darker); the bottom bar's place has a pill behind its icon */
:root[data-theme="dark"] .viewtog button.on{background:color-mix(in srgb,var(--fg) 20%,var(--surface-2));color:var(--fg)}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .viewtog button.on{background:color-mix(in srgb,var(--fg) 20%,var(--surface-2));color:var(--fg)}}
.bot-item.on{font-weight:700}
.bot-item.on::before{content:"";position:absolute;top:5px;left:50%;width:56px;height:30px;margin-left:-28px;border-radius:15px;background:var(--brand-soft);z-index:-1}
/* (7) on a wide screen a page's header spans the window like the calendar's (its actions end where the calendar's do); what is
   under it stays a readable 1,240 px column */
@media (min-width:768px){
  .app-main{max-width:none}
  body:not(.on-cal):not(.on-msg) .app-main>*:not(.app-top){max-width:var(--page-max)}
}
/* phase 22 (C, Martin's 8): one page column. A page's header and its actions sit on the same column as what is under it (on a
   2,000 px screen the Services and Clients buttons sat ~900 px right of their content); the column is at most 1,200 px, from the
   same left edge on every tab. The calendar and Texts keep the whole width (their head spans it, as before). */
:root{--page-max:1200px}
/* (8) the staff app's top bar: the name takes the room, 中 / EN at the right edge as in the shop app */
.app-top>.grow{flex:1 1 auto}
/* (9) drawn icons inside buttons */
.btn>.nav-ic:not(:only-child){width:18px;height:18px;margin-right:6px}
/* (11) the booking sheet: the status row in the brand colour like every selected chip; the client line breaks between its parts */
.statusrow button.on{background:var(--brand);color:var(--brand-ink);border-color:var(--brand)}
.bk-cl{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:4px 12px}
.bk-cl .nw,.bk-cl .btn{white-space:nowrap}
.bk-cl .btn{flex:none}
/* (12) a block narrower than 180 px leaves out the stored-value chip (it covered the name) */
@container (max-width:180px){#gc-cal .cal-bk .co-chipbal{display:none}}
/* (13) the staff list: the hours line up with the name */
.sf-row:has(.sf-mail) .sf-right{align-self:stretch;justify-content:flex-start;padding-top:1px}
/* (16) the public page: ‹ Back on the column's edge; in dark the chosen service's name as bright as the others */
button[data-act="c-back"].btn.ghost{padding-left:0}
:root[data-theme="dark"] .svc.sel .n{color:var(--fg)}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .svc.sel .n{color:var(--fg)}}
/* a phone held sideways (≥ 768 px): nothing under the notch */
@media (min-width:768px){.app-shell{padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px)}}
@media (max-width:767px){.app-main{padding-left:max(16px,env(safe-area-inset-left,0px));padding-right:max(16px,env(safe-area-inset-right,0px))}}
/* the staff app's day: its date is the page title */
.st-day-title{margin-bottom:4px}
/* a header's spacer pushes its actions to the column's right edge (Services had "Import" floating mid-header) */
.toolbar>.grow{flex:1 1 auto;min-width:0}

/* api.css — the few rules the API build adds on top of the prototype's sheet (src/api.js). */
/* the demo bar becomes a slim side switch (shop ↔ staff) on the shop and staff sides, and is gone on the customer page */
.demobar.api{height:36px;justify-content:flex-end;gap:6px}
.demobar.api .lbl b{color:#ece8e1}
.demobar[hidden]{display:none!important}
body.no-bar{--demo-h:0px}
.api-loading{padding:14px 0;color:var(--muted);font-size:13px;text-align:center}
.api-loading::before{content:'';display:inline-block;width:12px;height:12px;border:2px solid var(--line);border-top-color:var(--accent);border-radius:50%;margin-right:8px;vertical-align:-2px;animation:api-spin .8s linear infinite}
@keyframes api-spin{to{transform:rotate(360deg)}}
.api-offline{position:fixed;left:0;right:0;bottom:0;z-index:60;background:var(--danger);color:#fff;font-size:13px;text-align:center;padding:6px}
