/* Meiyan concept B, laid out like laseraway.com (2026-10-08). Loaded AFTER site.css on /b/ pages only.
   A's content, data and booking; LaserAway's shapes: wide page, big rounded cards (34px), pill buttons with a soft glow,
   a geometric sans (Outfit), small letter-spaced serif labels, soft colour washes, a dark footer with a big wordmark.
   Meiyan's teal stands in for LaserAway's pink. Home page markup: theme_l.py. */
/* Outfit (SIL Open Font License), self-hosted as fixed weights: Google serves one variable file whose default is
   weight 100, and the WebKit check drew every weight that thin. assets/fonts/outfit-{300,400,500,600}.woff2 */
@font-face{font-family:"Outfit";font-style:normal;font-weight:300;font-display:swap;src:url(fonts/outfit-300.woff2) format("woff2")}
@font-face{font-family:"Outfit";font-style:normal;font-weight:400;font-display:swap;src:url(fonts/outfit-400.woff2) format("woff2")}
@font-face{font-family:"Outfit";font-style:normal;font-weight:500;font-display:swap;src:url(fonts/outfit-500.woff2) format("woff2")}
@font-face{font-family:"Outfit";font-style:normal;font-weight:600;font-display:swap;src:url(fonts/outfit-600.woff2) format("woff2")}
:root{
  --sans:"Outfit","Noto Sans SC",system-ui,-apple-system,"Segoe UI",sans-serif;
  --head:"Outfit","Noto Sans SC",system-ui,sans-serif;
  --serif:"Cormorant Garamond","Noto Serif SC",Georgia,serif;
  --ink:#2a2a2a; --muted:#6b7280; --line:#e7e9ea; --soft:#f4fbfb; --tint:#e1f7f7; --pill:#cff3f2;
  /* her blue (Yumi's logo file, brand/BRAND.md): fills are #6ADAD8 with ink #221916 on top; her gradient stays
     around that blue. Deep teal #1F6F6B is for TEXT on white only, never a fill (Ruben 2026-10-08: "needs to be her blue") */
  --blue:#6adad8; --blue-2:#52cfcc; --blue-l:#93e8e6; --on-blue:#221916;
  /* 2026-10-09, Ruben picked "A · Pearl" (blue-gradient-options-2026-10-09.png): her blue with a soft pearly shine.
     Was linear-gradient(90deg,#8ce6e4 0%,#6adad8 55%,#5fd5d3 100%). */
  --grad:linear-gradient(100deg,#c6f4f2 0%,#93e6e4 30%,#6adad8 62%,#82d6e2 100%);
  --grad-card:radial-gradient(70% 80% at 15% 0%,rgba(255,255,255,.75) 0,rgba(255,255,255,0) 60%),linear-gradient(150deg,#b4efed 0%,#6adad8 55%,#7fd0e0 100%);
  --glow:0 12px 30px -12px rgba(82,207,204,.75);
  --r:24px; --R:34px; --wrap:1440px;
}
body{background:
  radial-gradient(720px 900px at -8% 1100px,rgba(106,218,216,.16) 0,rgba(106,218,216,0) 70%),
  radial-gradient(760px 900px at 108% 2700px,#eef9f8 0,rgba(238,249,248,0) 70%),
  #fff;font-size:16.5px;color:var(--ink)}
.wrap{padding:0 34px}
h1,h2,h3{font-family:var(--head);font-weight:400;letter-spacing:-.015em}
h2{font-size:clamp(30px,3.3vw,48px);line-height:1.12}
h3{font-weight:400}
section{padding:56px 0}
section+section{border-top:0}
.sec-top{align-items:center;margin-bottom:28px}
.muted{color:var(--muted)}
.note{background:rgba(227,245,244,.7)}

/* buttons: LaserAway's glowing gradient pills, in Meiyan teal */
.btn{height:52px;padding:0 28px;font:500 15.5px/1 var(--sans);letter-spacing:.005em;border-radius:999px;transition:transform .15s,box-shadow .15s,background .15s}
.btn-primary,nav.main a.btn{background:var(--grad);color:var(--on-blue);box-shadow:var(--glow);border:0}
.btn-primary:hover,nav.main a.btn:hover{background:var(--grad);transform:translateY(-1px);box-shadow:0 16px 34px -10px rgba(82,207,204,.85)}
.btn-primary:disabled{opacity:.45;box-shadow:none;cursor:default;transform:none}
.btn-ghost{background:#fff;border:1px solid #cfd8d7;color:var(--ink)}
.btn-white{background:#fff;color:var(--on-blue);border:0}
.btn-white:hover{background:#f2fbfb}
.btn-glass{background:rgba(255,255,255,.16);border:1px solid rgba(255,255,255,.7);color:#fff;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.btn-glass:hover{background:rgba(255,255,255,.26)}
.btn-sm{height:42px;padding:0 20px;font-size:14.5px}
.link{color:#1f6f6b}

/* top bar: soft tint, offer left, quick links right */
.topbar{background:linear-gradient(90deg,#eefbfb,#e4f6f8);color:var(--ink);font-size:13px}
.topbar .wrap{justify-content:flex-start;gap:26px;padding-top:9px;padding-bottom:9px}
.topbar a{color:var(--ink);font-weight:400}
.topbar .tb-offer{margin-right:auto}
/* 2026-10-11 (theme helper B2b): the desktop strip read "NEW HERE? $50 OFF YOUR FIRST BOTOX" in letter-spaced capitals (the
   10-08 look) while phones already read "New here? $50 off your first Botox". Ruben's standing rule for B (high-end = light
   type, normal case) and the handoff ask "Desktop offer strip: UPPERCASE to normal case": computers now match phones, same
   13px, same 38px strip; the pinned strip + header (job 30) is unchanged. Was: text-transform:uppercase;letter-spacing:.04em */
.topbar .tb-offer:before{content:"✦";color:var(--blue-2);margin-right:8px}
.topbar .tb-offer u{text-transform:none;letter-spacing:0;text-underline-offset:3px}
.topbar .tb-x:hover,.topbar .tb-tel:hover{color:#1f6f6b}
@media (max-width:860px){.topbar .tb-x,.topbar .tb-tel{display:none}.topbar .wrap{justify-content:flex-start;padding-top:12px;padding-bottom:12px}}

/* header: logo left, quiet links, a glowing Book pill */
header.site{background:rgba(255,255,255,.94);border-bottom:0}
header.site .wrap{height:84px}
nav.main{gap:30px;font-size:15px}
nav.main a{color:var(--ink)}
nav.main a:hover,nav.main a[aria-current]{color:#1f6f6b}
nav.main a.btn{height:42px;padding:0 22px}
.menu-btn{border:1.5px solid var(--ink);border-radius:12px;width:40px;height:40px;display:none;align-items:center;justify-content:center}
.menu-btn svg{width:20px;height:20px}
@media (max-width:860px){
  header.site .wrap{height:72px}
  .menu-btn{display:flex}
  nav.main{inset:72px 0 auto 0}
}

/* ---------- home: hero = two rounded cards ---------- */
.lh{padding:14px 0 30px}
.lh-in{display:grid;grid-template-columns:1fr 1fr;grid-template-areas:"media pick";gap:20px 22px}  /* 2026-10-11 job 37: no "award" row (the bar is gone) */
.lh-media{grid-area:media;position:relative;border-radius:var(--R);overflow:hidden;min-height:620px;background:#cfe3e2;isolation:isolate;-webkit-mask-image:-webkit-radial-gradient(white,black);transform:translateZ(0)}
.lh-media video,.lh-ph img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.lh-ph{display:contents}
.lh-media:after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(10,22,21,.55) 0%,rgba(10,22,21,.18) 45%,rgba(10,22,21,.05) 62%,rgba(10,22,21,.45) 100%);pointer-events:none}
.lh-words{position:relative;z-index:1;padding:42px 40px;color:#fff;max-width:600px}
.lh-words h1{font-size:clamp(40px,4.4vw,66px);line-height:1.04;font-weight:400;letter-spacing:-.025em;margin:0 0 16px;text-shadow:0 2px 24px rgba(0,0,0,.18)}
.lh-sub{font-size:18px;line-height:1.5;margin:0 0 26px;max-width:30em;opacity:.95}

.lh-pick{grid-area:pick;border:1px solid #dfe5e5;border-radius:var(--R);padding:40px 34px 30px;display:flex;flex-direction:column;background:#fff;min-height:620px}
.lp-h{font-size:clamp(24px,2vw,28px);margin:0 0 24px;letter-spacing:-.01em}
.lp-step{flex:1}
.lp-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.lp-grid[hidden]{display:none}
.lp-opt{display:flex;align-items:center;gap:12px;min-height:74px;padding:12px 14px;border:1.5px solid #e1e6e6;border-radius:14px;background:#fff;font:400 15px/1.3 var(--sans);color:var(--ink);text-align:left;cursor:pointer;transition:border-color .15s,background .15s}
.lp-opt:hover{border-color:var(--blue-l)}
.lp-opt.on{border-color:var(--blue);background:#effbfb;box-shadow:0 0 0 1px var(--blue) inset}
.lp-opt .ph{flex:none;width:44px;height:44px;border-radius:50%;background:var(--tint) center/cover no-repeat}
.lp-opt small{display:block;color:var(--muted);font-size:13px;margin-top:3px}
.lp-q-ph{display:flex;align-items:center;justify-content:center;color:#1f6f6b;font-size:20px}
.lp-foot{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin-top:26px}
.lp-lbl{display:block;font-size:13px;font-weight:500;margin-bottom:8px}
.lp-bar{display:block;width:100px;height:6px;border-radius:9px;background:#e9eeee;overflow:hidden}
.lp-bar i{display:block;height:100%;width:12%;background:var(--grad);border-radius:9px;transition:width .3s}
.st2 .lp-bar i{width:100%}
.lp-btns{display:flex;gap:10px}

/* ---------- swipe rows of tall cards ---------- */
.lr-nav{display:flex;gap:10px}
.lr-b{width:46px;height:46px;border-radius:50%;border:0;background:var(--grad);color:var(--on-blue);font-size:26px;line-height:1;cursor:pointer;box-shadow:var(--glow);display:flex;align-items:center;justify-content:center;padding:0 0 3px}
.lr-rail{display:grid;grid-auto-flow:column;grid-auto-columns:calc((100% - 80px) / 5.15);gap:20px;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;padding:4px 2px 18px}
.lr-rail::-webkit-scrollbar{display:none}
.lr-rail>*{scroll-snap-align:start}
.l-more{margin:6px 0 0;text-align:center}

.lc{display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;padding:36px 18px 32px;border:1px solid var(--line);border-radius:var(--R);background:#fff;text-decoration:none;color:var(--ink);transition:box-shadow .2s,transform .2s}
.lc:hover{box-shadow:0 18px 40px -24px rgba(0,0,0,.25);transform:translateY(-2px)}
.lc-ph{width:104px;height:104px;border-radius:50%;background:var(--tint) center/cover no-repeat;margin-bottom:18px}
.lc b{font-weight:400;font-size:20px;line-height:1.25}
/* 2026-10-10 (night, later), Ruben: "I want this copy to be treatment name first and then what it helps with there".
   b = the treatment name now, small = what it helps with: a plain normal-case line like the offer cards' (.lo small),
   no longer letter-spaced serif caps (was: font:500 14px/1.3 var(--serif);text-transform:uppercase;letter-spacing:.2em;color:#7c7f84) */
.lc small{display:block;font-size:15px;line-height:1.4;color:#5f6368;text-wrap:balance}
.lc em{font-style:normal;color:#1f6f6b;font-size:15px;margin-top:8px}

.lres{margin:0;border:1px solid var(--line);border-radius:var(--R);overflow:hidden;background:#fff}
.lres img{width:100%;aspect-ratio:1/1;object-fit:contain;background:#f4f7f7;cursor:zoom-in}
.lres figcaption{display:flex;justify-content:space-between;align-items:baseline;gap:10px;padding:16px 20px 18px}
.lres figcaption b{font-weight:400;font-size:17px}
.lres figcaption .link{font-size:14px;white-space:nowrap}
.lres-rail{grid-auto-columns:calc((100% - 60px) / 4.1)}
.res-note{margin-top:10px;font-size:14px}

/* centred heading block */
.l-center{text-align:center;max-width:820px;margin:0 auto 36px}
.l-center h2{margin:0 0 10px}
.lc-sub{font-size:clamp(17px,1.5vw,21px);color:var(--muted);margin:0 0 24px}
.l-note{display:table;margin:-18px auto 30px}

/* reviews: full-width photo banner with a quote, then cards */
.l-quote-sec{padding-top:40px;padding-bottom:20px}
.l-banner{position:relative;border-radius:var(--R);overflow:hidden;min-height:560px;background:#c9d3d2 center/cover no-repeat;display:flex;align-items:center;justify-content:center;text-align:center}
.l-banner:before{content:"";position:absolute;inset:0;background:rgba(18,26,25,.42)}
.lb-in{position:relative;width:100%;max-width:820px;min-height:240px;padding:40px 28px 60px;color:#fff;display:grid}
.lq{grid-area:1/1;margin:0;opacity:0;transition:opacity .6s;align-self:center}
.lq.on{opacity:1}
.lq p{font-size:clamp(21px,2.2vw,30px);line-height:1.35;margin:0 0 16px}
.lq cite{font:500 14px/1 var(--serif);font-style:normal;text-transform:uppercase;letter-spacing:.24em}
.l-dots{position:absolute;left:0;right:0;bottom:22px;display:flex;justify-content:center;gap:8px}
.ld{width:10px;height:10px;border-radius:50%;border:1.5px solid #fff;background:transparent;padding:0;cursor:pointer}
.ld.on{background:#fff}
.l-rev .l-center{margin-bottom:28px}
.l-rev-top{justify-content:flex-end;margin-bottom:16px}
.lrv{margin:0;display:flex;flex-direction:column;align-items:center;text-align:center;gap:12px;padding:32px 22px 28px;border:1px solid var(--line);border-radius:var(--R);background:#fff}
.lrv-av{width:56px;height:56px;border-radius:50%;background:var(--tint);color:#1f6f6b;display:flex;align-items:center;justify-content:center;font-size:22px}
.lrv .rv-stars{color:var(--blue-2);letter-spacing:2px;font-size:14px}
.lrv blockquote{margin:0;font-size:16.5px;line-height:1.55}
.lrv figcaption{font-size:13.5px;color:var(--muted);margin-top:auto}

/* first visit: photo cards */
.ls-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}
.ls{border:1px solid var(--line);border-radius:var(--R);overflow:hidden;background:#fff;box-shadow:0 10px 30px -26px rgba(0,0,0,.4)}
.ls img{width:100%;aspect-ratio:4/3;object-fit:cover}
.ls div{padding:24px 22px 28px;text-align:center}
.ls h3{font-size:22px;margin:0 0 8px}
.ls p{color:var(--muted);margin:0;font-size:15.5px}

/* offers */
.lo-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.lo{border:1px solid var(--line);border-radius:var(--R);overflow:hidden;background:#fff}
.lo-ph{display:block;aspect-ratio:16/10;background:var(--tint) center/cover no-repeat}
.lo-b{padding:24px 26px 28px}
.lo h3{font-size:22px;margin:0 0 4px}
.lo small{display:block;font-size:15px;line-height:1.4;color:#5f6368}  /* 2026-10-10: now the payoff line under the name, normal case (was an uppercase label) */
.lo-p{margin:14px 0 18px}
.lo-p b{font-weight:500;font-size:24px;color:#1f6f6b}
.lo-p s{color:var(--muted);font-size:14.5px;margin-left:6px}

/* the pair of feature cards (dark + teal) */
.l-pair{display:grid;grid-template-columns:1fr 1fr;gap:22px}
.lf{position:relative;border-radius:var(--R);overflow:hidden;min-height:380px;padding:56px 44px;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;text-decoration:none;color:#fff;isolation:isolate}
.lf h2{font-size:clamp(34px,3.6vw,54px);margin:0 0 12px;color:inherit}
.lf p{font-size:18px;max-width:26em;margin:0 0 26px;opacity:.92}
.lf-dark{background:linear-gradient(rgba(38,38,38,.86),rgba(38,38,38,.9)),var(--ph,none) center/cover no-repeat,#363636}
.lf-teal{color:var(--on-blue);background:var(--grad-card)}
.lf .btn{pointer-events:none}
.lf:hover .btn-primary{transform:translateY(-1px)}
.l-pair-sec .note{margin-top:14px}

/* step inside: full-width video banner + photos */
.l-vid{position:relative;border-radius:var(--R);overflow:hidden;min-height:560px;display:flex;align-items:flex-end;justify-content:center;text-align:center;isolation:isolate;-webkit-mask-image:-webkit-radial-gradient(white,black);transform:translateZ(0)}
.l-vid video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:-2}
.l-vid:after{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(180deg,rgba(0,0,0,0) 35%,rgba(0,0,0,.55) 100%)}
.lv-in{color:#fff;padding:40px 28px 48px;max-width:640px}
.lv-in h2{color:#fff;margin:0 0 10px}
.lv-in p{font-size:18px;margin:0 0 22px}
.l-gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:20px}
.l-gallery img{width:100%;height:280px;object-fit:cover;border-radius:var(--r)}

/* prices: LaserAway's "All Services" card */
.l-svc{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);gap:34px;border:1px solid #dfe5e5;border-radius:var(--R);padding:36px;background:#fff}
.lsv-list h3{font-size:clamp(28px,2.4vw,36px);margin:0 0 22px}
.lsv-list{display:flex;flex-direction:column;gap:10px}
.pt-tab.lsv{display:flex;align-items:center;gap:18px;height:auto;width:100%;padding:16px 20px;border:1px solid #edf0f0;border-radius:12px;background:#fff;text-align:left;color:var(--ink);font:400 16px/1.3 var(--sans)}
.pt-tab.lsv:hover{border-color:var(--blue-l)}
.pt-tab.lsv[aria-pressed=true]{border:1.5px solid var(--blue);background:#effbfb;color:var(--ink);box-shadow:0 0 0 1px var(--blue) inset}
.lsv .ph{flex:none;width:58px;height:58px;border-radius:50%;background:var(--tint) center/cover no-repeat}
.lsv b{display:block;font-weight:400;font-size:19px}
.lsv small{color:var(--muted);font-size:14px}
.lsv-pane{border-radius:var(--r);background:var(--soft);padding:8px 26px;max-height:560px;overflow:auto;align-self:start}
.lsv-pane .pt-row{border-bottom-color:#dfeceb}
.lsv-pane .pt-row:last-child{border-bottom:0}
.pt-help{text-align:center;margin-top:22px}

/* visit: dark card + map card */
.lf-static{align-items:stretch;text-align:left;justify-content:flex-start}
.lf-static h2{font-size:clamp(30px,3vw,44px)}
.lf-static p{font-size:16px;opacity:.9}
.lf-static a{color:#fff}
.lf-static .btn-primary{pointer-events:auto}
.lf-static .btn{pointer-events:auto}
.lf-static .open-now{color:var(--blue);margin:0 0 6px}
.lf-static .hours td{border-bottom-color:rgba(255,255,255,.14);color:#e9eded}
.lf-static .hours td:last-child{color:#c9d1d0}
.lf-static .hours tr.today td{color:#fff}
.l-map{padding:0;background:#e9eeee}
.l-map iframe{position:absolute;inset:0;width:100%;height:100%;border:0}

/* questions */
.l-faq .faq{max-width:1180px;margin:0 auto}
.l-faq .faq details:first-child{border-top:0}
.l-faq .faq summary{font-weight:400;font-size:clamp(17px,1.6vw,22px);padding:22px 0}
.l-faq .faq summary:after{color:var(--ink)}
.l-faq .faq details p{font-size:16.5px}
.l-still{text-align:center;font-size:19px;margin:34px 0 0}

/* closing card */
.l-close{border-radius:var(--R);padding:76px 28px;text-align:center;background:radial-gradient(80% 120% at 50% 0%,rgba(106,218,216,.28) 0,#f5fcfc 55%,#fff 100%);border:1px solid rgba(106,218,216,.45)}
.l-close h2{margin:0 0 26px}
.l-close .cta-row{justify-content:center}

/* footer: dark, letter-spaced serif headings, a big wordmark at the bottom */
footer.site{background:#2f2f2f;color:#d8dcdc;padding-bottom:0;overflow:hidden}
footer.site h4{font:400 17px/1.3 var(--sans);text-transform:none;letter-spacing:0;color:#fff;margin-bottom:16px}
/* 2026-10-11 (theme helper B2b): the footer's headings ("Meiyan Med Spa 美妍", "Treatments", "More" / 美妍医美, 项目, 更多)
   were letter-spaced serif capitals, flagged by the last two theme helpers ("B's footer headings are still letter-spaced
   serif caps on every page") against Ruben's rule that high-end = light type, normal case. Now B's normal heading style:
   Outfit 400 (Noto Sans SC 400 on Chinese pages), normal case, no tracking, white on the dark footer, a size above the
   14.5px links under them. The MEIYAN / DUKE MEDICAL CLINIC lockup above them is the logo and keeps its spacing.
   Was: font:500 15px/1 var(--serif);text-transform:uppercase;letter-spacing:.24em;margin-bottom:18px */
footer.site a{color:#e7eaea}
footer.site .big{border-bottom-color:rgba(255,255,255,.12)}
footer.site .big img{filter:brightness(0) invert(1)}
footer.site .big b{color:#fff}
footer.site .big span{color:var(--blue)}
footer.site .fine{color:#a9afaf}
.l-mark{font:500 clamp(90px,23vw,360px)/.78 var(--serif);letter-spacing:.04em;color:rgba(255,255,255,.09);text-align:center;white-space:nowrap;margin:36px 0 -0.06em;user-select:none;pointer-events:none}

/* inner pages: LaserAway's rounded cards and soft tint */
.p-hero h1,.pg-hero h1,.t-hero h1{font-weight:400}
.chip{border-color:rgba(106,218,216,.6)}
.chip.on{background:var(--grad);border-color:transparent;color:var(--on-blue)}
/* 2026-10-10, Ruben: categories on one line on desktop ("make sure that the categories are in one line and don't double
   line here on desktop, both English and Chinese"). site.css sets the treatments filter pills to 15.5px / 10px 18px with
   an 8px gap, so the English row (1246px) was wider than B's 1212px column and "Vitamin shots" dropped to a 2nd line.
   Desktop only (phone <=760 and tablet 761-860 untouched): less side padding, a smaller gap, a touch smaller text.
   English fits on one line from 1119px wide (~1136 with a Windows scrollbar); Chinese from 861px. Below 1119 the
   English row cannot fit at 14px+ text, so it still wraps there. Same look: teal hairline, dark selected pill. */
@media (min-width:861px){
  .theme-l #goalFilters{gap:6px}
  .theme-l #goalFilters .chip{font-size:14px;padding:10px 12px;white-space:nowrap}
}
@media (min-width:1280px){
  .theme-l #goalFilters .chip{font-size:15px;padding:10px 14px}
}
.cta-strip{background:transparent}
.cta-strip .wrap{border-radius:var(--R);padding:64px 28px;background:radial-gradient(80% 120% at 50% 0%,rgba(106,218,216,.28) 0,#f5fcfc 55%,#fff 100%);border:1px solid rgba(106,218,216,.45);text-align:center}
.cta-strip .cta-row{justify-content:center}

/* ---------- tablet + phone ---------- */
@media (max-width:1100px){
  .lr-rail{grid-auto-columns:calc((100% - 40px) / 3.2)}
  .lres-rail{grid-auto-columns:calc((100% - 40px) / 3.1)}
  .ls-grid{grid-template-columns:1fr 1fr}
  .lp-grid{grid-template-columns:1fr 1fr}
}
@media (max-width:860px){
  .wrap{padding:0 20px}  /* A's phone gutter: A's swipe rows bleed by exactly 20px */
  .lh{padding-top:4px}
  .lh-in{grid-template-columns:1fr;grid-template-areas:"media" "pick";gap:16px}
  .lh-media{min-height:0;aspect-ratio:9/15.5;max-height:640px;display:flex;align-items:flex-end;justify-content:center;text-align:center}
  .lh-media:after{background:linear-gradient(180deg,rgba(10,22,21,0) 30%,rgba(10,22,21,.2) 50%,rgba(10,22,21,.7) 100%)}
  .lh-words{padding:26px 20px 30px}
  .lh-words h1{font-size:clamp(32px,8.6vw,42px);margin-bottom:12px}
  .lh-sub{font-size:16px;margin-bottom:20px}
  .lh-words .cta-row{flex-direction:column;align-items:stretch}
  .lh-words .btn{height:56px;font-size:16.5px}
  .lh-pick{min-height:0;padding:26px 16px 18px;border-radius:28px}
  .lp-grid{grid-template-columns:1fr;gap:10px}
  .lp-opt{min-height:68px}
  .lp-foot{position:sticky;bottom:0}
  section{padding:40px 0}
  .lr-rail{grid-auto-columns:76%;gap:14px}
  .lres-rail{grid-auto-columns:84%}
  .lr-nav{display:none}
  .lc{padding:28px 16px}
  .ls-grid,.lo-grid{grid-template-columns:1fr;gap:16px}
  .l-pair{grid-template-columns:1fr;gap:16px}
  .lf{min-height:320px;padding:44px 22px;border-radius:28px}
  .l-map{min-height:340px}
  .l-banner{min-height:440px;border-radius:28px}
  .l-vid{min-height:520px;border-radius:28px}
  .l-gallery{grid-template-columns:1fr 1fr;gap:12px}
  .l-gallery img{height:160px}
  .l-gallery img:first-child{grid-column:span 2;height:220px}
  .l-svc{grid-template-columns:1fr;padding:22px 16px;gap:18px;border-radius:28px}
  .pt-tab.lsv{padding:12px 14px;gap:14px}
  .lsv .ph{width:46px;height:46px}
  .lsv b{font-size:17px}
  .lsv-pane{max-height:none;padding:4px 16px}
  .l-close{padding:52px 18px;border-radius:28px}
  .l-close .cta-row{flex-direction:column;align-items:stretch}
  .l-center{margin-bottom:26px}
  .cta-strip .wrap{border-radius:28px;margin:0 20px;padding:44px 18px}
}
@media (max-width:760px){
  footer.site{padding-bottom:calc(24px + env(safe-area-inset-bottom))}
  .l-mark{margin-bottom:0}
  .sec-top .link{display:inline}
}
html[lang=zh-CN] h1,html[lang=zh-CN] h2{letter-spacing:0}

/* fixes after the first look (2026-10-08) */
.lp-back[hidden]{display:none}
.lp-goals .lp-opt{flex-direction:column;align-items:flex-start;justify-content:flex-start;gap:12px;min-height:158px;padding:16px 16px 18px;font-size:16px}
.lp-goals .lp-opt .ph{width:64px;height:64px}
footer.site .cols a,footer.site .cols div>a,footer.site a{color:#e7eaea}
footer.site a:hover{color:var(--blue)}
@media (max-width:860px){
  .lp-foot{position:static}
  .lp-goals .lp-opt{flex-direction:row;align-items:center;min-height:72px;gap:12px;padding:12px 14px;font-size:15px}
  .lp-goals .lp-opt .ph{width:48px;height:48px}
  .topbar .tb-offer{text-transform:none;letter-spacing:0;font-size:13px}
}

/* 2026-10-08: offers first in the picker, full-width tile on top */
.lp-goals .lp-opt.lp-deal{grid-column:1/-1;flex-direction:row;align-items:center;min-height:84px;background:linear-gradient(90deg,rgba(106,218,216,.26),rgba(106,218,216,.06));border-color:rgba(106,218,216,.7)}
.lp-goals .lp-opt.lp-deal.on{border-color:var(--blue)}
.lp-goals .lp-opt.lp-deal .ph{width:56px;height:56px}
.lp-goals .lp-opt.lp-deal>span:last-child{font-size:17px}
.lp-sale{color:#1f6f6b;font-weight:600}
.lp-opt s{color:#9aa1a1;margin-left:4px}
@media (min-width:861px){.lp-goals .lp-opt{min-height:140px}}

/* 2026-10-08, Ruben: "remove the book now tab at the bottom that's always there" -> B has no fixed phone booking bar.
   Booking stays one tap away in the header (Book pill / menu) and in every section. A keeps its bar. */
.theme-l .mbar{display:none!important}
@media (max-width:760px){.theme-l .demo-ribbon{bottom:12px}}

/* 2026-10-08, Ruben's iPhone screenshot (Chinese B): "Make sure the Chinese hero padding is good".
   1) On phones wider than ~400px the box hit max-height:640px and aspect-ratio then shrank its WIDTH, so the box sat
      off-centre with a wider right gutter. Now it is always full width; only the height is capped.
   2) The Chinese headline ran to 3 lines (one phrase each); Ruben's rule is 2 lines. Sized so two phrases fit a line. */
@media (max-width:860px){
  .lh-media{aspect-ratio:auto;width:100%;height:min(calc((100vw - 40px) * 1.72), 680px)}
  html[lang=zh-CN] .lh-words{padding:24px 22px 28px}
  html[lang=zh-CN] .lh-words h1{font-size:min(34px, calc((100vw - 96px) / 10.3));line-height:1.25;margin-bottom:12px}
  html[lang=zh-CN] .lh-sub{font-size:15px;line-height:1.6}
}
@media (min-width:861px){
  html[lang=zh-CN] .lh-words{max-width:640px}
  html[lang=zh-CN] .lh-words h1{font-size:clamp(34px,3.3vw,52px);line-height:1.2}
}

/* B's full-screen offer in her blue: soft wash of #6ADAD8 behind, button = her blue gradient with ink text (above). */
.theme-l .of .op-card.of-screen{background:radial-gradient(900px 520px at 50% -10%,rgba(106,218,216,.32) 0,rgba(106,218,216,0) 70%),radial-gradient(700px 500px at 100% 100%,#f6ecea 0,rgba(246,236,234,0) 70%),#fbfaf8}
.theme-l .of-arch{background:var(--tint)}
.theme-l .lf-dark .btn-primary{color:var(--on-blue)}
.lp-h[hidden]{display:none}
.lp-step .lp-sub{margin:-14px 0 20px;color:var(--muted,#6b7280);font-size:15px;line-height:1.45}
/* picker buttons never break mid-word (Chinese 返回 / 下一步 were splitting), and on phones the A/B switcher sits
   bottom-LEFT so it never covers the picker's Next button or the main buttons (all right-aligned or full width). */
.lp-btns .btn{white-space:nowrap}
.lp-foot{flex-wrap:wrap}
@media (max-width:860px){
  .lp-btns .btn{height:48px;padding:0 20px}
  .lp-lbl{font-size:12.5px}
  .theme-l .demo-ribbon{right:auto;left:10px;bottom:10px;font-size:10.5px}
}

/* ---------- 2026-10-08: the bell + offers panel (LaserAway's notification button), B only ---------- */
.l-bell{position:relative;width:40px;height:40px;display:inline-flex;align-items:center;justify-content:center;border:1.5px solid var(--blue);border-radius:12px;background:#fff;color:var(--on-blue);cursor:pointer;padding:0;flex:none}
.l-bell:hover{background:#effbfb}
.l-dot{position:absolute;top:-4px;right:-4px;width:11px;height:11px;border-radius:50%;background:var(--blue);border:2px solid #fff;box-shadow:0 0 0 1px rgba(34,25,22,.12)}
html.deals-seen .l-dot{display:none}
nav.main .l-bell{margin-left:2px}
.head-right{gap:8px}
@media (max-width:860px){nav.main .l-bell{display:none}}
/* 2026-10-10, Ruben: "Make the Chinese button more in theme." The 中文 / EN switch was site.css's grey pill; on B it is
   now the bell's box (teal 1.5px border, 12px corners, white, ink text, the same pale-teal hover and tap), a little
   wider for the words and one width in both languages, so the bell and menu do not shift when you switch. */
.theme-l .lang{box-sizing:border-box;width:56px;height:40px;padding:0;flex:none;border:1.5px solid var(--blue);border-radius:12px;background:#fff;color:var(--on-blue)!important;font:400 14px/1 var(--sans);letter-spacing:0}
.theme-l .lang[lang=en]{letter-spacing:.03em;text-indent:.03em}  /* "EN": a touch of air, still centred */
.theme-l .lang:hover{border-color:var(--blue);background:#effbfb}
@media (prefers-reduced-motion:no-preference){  /* motion-l.css's tap on the bell */
  .theme-l .lang{transition:scale .45s var(--mo-press),background-color .2s,border-color .2s}
  .theme-l .lang:active{scale:.96;transition:scale .1s ease-out,background-color .2s}
}
/* 2026-10-11: the panel's width, slide, shadow and dim are tokens, because the phone menu opens the same way (Ruben: "Can
   the menu open like the notication thing does?"; "menu like the bell" block below). One source for both panels. */
:root{--ld-w:min(440px,100%);--ld-slide:.35s cubic-bezier(.2,.8,.2,1);--ld-fade:.3s;--ld-shadow:-20px 0 60px -30px rgba(0,0,0,.4);--ld-dim:rgba(34,25,22,.35)}
.l-deals{position:fixed;inset:0;z-index:95}
.l-deals[hidden]{display:none}
.ld-back{position:absolute;inset:0;background:var(--ld-dim);opacity:0;transition:opacity var(--ld-fade)}
.ld-panel{position:absolute;top:0;right:0;bottom:0;width:var(--ld-w);background:#fbfaf8;overflow-y:auto;overscroll-behavior:contain;transform:translateX(100%);transition:transform var(--ld-slide);box-shadow:var(--ld-shadow)}
.l-deals.in .ld-back{opacity:1}
.l-deals.in .ld-panel{transform:none}
.ld-head{position:sticky;top:0;z-index:1;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:18px 20px;background:rgba(251,250,248,.95);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.ld-head h2{font-size:22px;margin:0}
.ld-x{width:40px;height:40px;border-radius:50%;border:1px solid var(--line);background:#fff;display:grid;place-items:center;cursor:pointer;color:var(--ink)}
.ld-list{display:flex;flex-direction:column;gap:16px;padding:16px 20px}
.ld-card{background:#fff;border:1px solid var(--line);border-radius:28px;overflow:hidden}
.ld-card img{width:100%;aspect-ratio:16/9;object-fit:cover;object-position:50% 35%}
.ld-b{padding:22px 22px 24px;text-align:center}
.ld-b h3{font-size:24px;margin:0 0 6px}
.ld-sub{margin:0 0 18px;font-size:14px;letter-spacing:.08em;text-transform:uppercase;color:#1f6f6b}
.ld-sub b{font-size:20px;letter-spacing:0;font-weight:600}
.ld-sub s{color:var(--muted);text-transform:none;letter-spacing:0;margin-left:4px}
.ld-b .btn{width:100%;height:52px}
.ld-fine{margin:12px 0 0;font-size:12.5px;color:var(--muted)}
.ld-b .note{margin-top:10px}
.ld-foot{text-align:center;padding:4px 20px 28px;margin:0}
@media (prefers-reduced-motion:reduce){.ld-panel,.ld-back{transition:none}}

/* ---------- 2026-10-08, Ruben: "The website looks tiny on my large screen". B was designed at 1440px and simply stopped
   growing past it (content capped at 1440, text in fixed px), so on 1920/2560 monitors it sat small in the middle.
   Above 1600px the whole page now scales up in steps (CSS zoom keeps the exact 1440 layout, only bigger), roughly
   viewport / 1440, capped at 1.8x for ultra-wide screens. Media queries still use the real screen width. ---------- */
@media (min-width:1600px){body.theme-l{zoom:1.1}}
@media (min-width:1760px){body.theme-l{zoom:1.2}}
@media (min-width:1900px){body.theme-l{zoom:1.3}}
@media (min-width:2100px){body.theme-l{zoom:1.45}}
@media (min-width:2400px){body.theme-l{zoom:1.6}}
@media (min-width:2700px){body.theme-l{zoom:1.8}}
/* short-but-wide screens (e.g. 1920x900 browser windows): keep the hero inside the first screen */
@media (min-width:1600px) and (max-height:1000px){body.theme-l{zoom:1.12}}
@media (min-width:2100px) and (max-height:1250px){body.theme-l{zoom:1.3}}

/* hero line on ONE line on computers (2026-10-08); phones may wrap */
@media (min-width:1100px){.lh-words{max-width:none}.lh-sub{max-width:none;white-space:nowrap;font-size:17px}}
.lh-sub{white-space:nowrap}

/* hero leads with an offer + ONE button (2026-10-08, LaserAway pattern) */
.lh-claim{min-width:220px}
.lh-fine{margin:14px 0 0;font-size:13px;opacity:.9}
/* 2026-10-10: on computers the two small lines sit on the lobby's white wall (2.3-3:1). A soft ink halo, like the h1's,
   lifts them from the first frame. Phones keep their darker bottom wash and no halo. */
@media (min-width:861px){.lh-sub,.lh-fine{text-shadow:0 1px 2px rgba(10,22,21,.3),0 0 16px rgba(10,22,21,.42)}}
@media (max-width:860px){.lh-words .cta-row{flex-direction:column;align-items:stretch}.lh-fine{font-size:12.5px}}
/* 2026-10-08 (night): the h1 opens with the business name, sentence case, then the offer as the big second beat */
/* 2026-10-11: the name line's size + weight moved to the "hero helper" block at the end (job 36: a quiet kicker now). */

/* ---------- 2026-10-08, Ruben: "This opens the booking page. Can we have a booking widget here instead of opening another
   page". After a treatment is picked, the card shows step 3 = B's booking flow (book-embed.html, the same wizard as
   book.html without header/footer) in a frame that grows with its content. ---------- */
.lp-book[hidden]{display:none}
.lp-change{background:none;border:0;padding:0 0 14px;font:500 14.5px var(--sans);color:#1f6f6b;cursor:pointer}
.lp-frame{display:block;width:100%;border:0;min-height:420px;background:transparent}
.lp-foot[hidden]{display:none}
.lh-pick.st3{min-height:0}
body.embed{background:transparent}
.embed .wrap.book-wrap{display:block;max-width:none;padding:0}
.embed .summary{display:none}
.embed .nav-row{position:static;padding:0;margin-top:22px;border:0;background:none}
.embed .step h2{font-size:24px}
.progress div.done i,.progress div.cur i{background:var(--blue)}

/* ---------- 2026-10-08, Ruben: the picker + booking "needs to look like it's one widget, not two stapled together".
   The card owns the ONE progress bar, step label ("Step 3 of 6 · Day & time") and Back/Next row for all six steps.
   The booking frame draws none of its own (no progress, no step count, no "You are booking" bar, no button row);
   the chosen treatment is a small chip at the top of the card. Inside the frame, options, days and times use the
   card's own look: 14px corners, her blue outline + pale blue fill when picked, her blue fill with ink text for the
   picked day and time. Those picked-state rules apply to B's book.html too (they were deep-teal fills). ---------- */
.lp-chip{display:flex;align-items:center;gap:10px;align-self:flex-start;max-width:100%;margin:0 0 18px;padding:6px 6px 6px 16px;border-radius:999px;background:#effbfb;border:1px solid var(--blue-l);font-size:14.5px;color:var(--on-blue)}
.lp-chip[hidden]{display:none}
.lp-chip-t{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}
.lp-chip-x{flex:none;height:32px;padding:0 14px;border-radius:999px;border:1px solid var(--blue);background:#fff;font:500 13.5px var(--sans);color:var(--on-blue);cursor:pointer}
.lp-chip-x:hover{background:#effbfb}
.lp-bar{width:140px}
.st2 .lp-bar i{width:auto}
.lh-pick.st3 .lp-foot{margin-top:18px;padding-top:18px;border-top:1px solid #eef1f1}
.embed .progress,.embed .step-count,.embed .prefill,.embed .nav-row{display:none!important}
.embed .step h2{font-size:clamp(24px,2vw,28px);letter-spacing:-.01em;margin:0 0 8px}
.embed .panel{border:0;padding:0;background:none;border-radius:0}
.embed .hint,.embed .muted{font-size:14.5px}
.theme-l .opt,.theme-l .pick,.theme-l .goal,.theme-l .consult-card{border:1.5px solid #e1e6e6;border-radius:14px}
.theme-l .opt[aria-pressed=true],.theme-l .pick[aria-pressed=true],.theme-l .goal[aria-pressed=true],.theme-l .consult-card[aria-pressed=true]{border:1.5px solid var(--blue);background:#effbfb;box-shadow:0 0 0 1px var(--blue) inset}
.theme-l .pick[aria-pressed=true] i,.theme-l .goal[aria-pressed=true] i{background:var(--blue);border-color:var(--blue)}
.theme-l .goal[aria-pressed=true] i:after,.theme-l .pick[aria-pressed=true] i:after{border-color:var(--on-blue)}
.theme-l .cal button,.theme-l .slots button{border-radius:12px}
.theme-l .cal button.sel,.theme-l .slots button.sel{background:var(--blue);border-color:var(--blue);color:var(--on-blue);font-weight:500}
.theme-l .field input,.theme-l .field select,.theme-l .field textarea{border-radius:12px}
.lh-pick.st3 .lp-frame{min-height:0}

/* ---------- 2026-10-08, Ruben: "Make the testimonial widget swipeable". The banner quotes are a scroll-snap row (touch +
   trackpad), not a cross-fade; the review cards get dots on phones. ---------- */
.lb-in{display:block}
.lb-track{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch;outline:0;cursor:grab}
.lb-track:active{cursor:grabbing}
.lb-track::-webkit-scrollbar{display:none}
.lb-track .lq{flex:0 0 100%;scroll-snap-align:center;scroll-snap-stop:always;opacity:1;padding:0 6px;box-sizing:border-box;transition:none}
.lb-track:focus-visible{box-shadow:0 0 0 2px rgba(255,255,255,.7);border-radius:12px}
.ld{width:12px;height:12px}
.lr-dots{display:none}
@media (max-width:860px){
  .lr-dots{display:flex;justify-content:center;gap:7px;margin-top:4px}
  .lr-dots i{width:7px;height:7px;border-radius:50%;background:#d5dddd;transition:background .2s,width .2s}
  .lr-dots i.on{width:20px;border-radius:9px;background:var(--blue)}
}

/* picker step 2 shows the treatment's real name first (Ruben 2026-10-08), then the plain line, then the price */
.lp-tn{display:block;font-weight:500;font-size:15.5px;line-height:1.25}
.lp-opt small.lp-td{margin-top:2px}
.lp-opt small.lp-tp{margin-top:4px;color:#1f6f6b;font-weight:500}

/* reviewer's own Google picture (2026-10-08); same 56px circle as the initial */
.lrv-pic{object-fit:cover;background:var(--tint);border:1px solid var(--line)}

/* results squares: blurred copy of the photo behind it fills the empty bands (Ruben 2026-10-08: "so it looks nice") */
.lres-ph{position:relative;display:block;aspect-ratio:1/1;overflow:hidden;background:#f4f7f7;isolation:isolate}
.lres-bg{position:absolute;inset:-12%;background:center/cover no-repeat;filter:blur(22px) saturate(1.05) brightness(1.04);transform:translateZ(0)}
.lres-bg:after{content:"";position:absolute;inset:0;background:rgba(255,255,255,.18)}
.lres-ph img{position:relative;z-index:1;display:block;width:100%;height:100%;aspect-ratio:auto;object-fit:contain;background:transparent}

/* ---------- B's offer pop-up, v2 (2026-10-08 night). Layout from the NakedMD round (thin X top-left, wordmark, big
   bold amount, a question, three buttons); look from B itself (Ruben: "too nude", Meiyan is "more of a girly clinic
   aesthetic"): white with a wash of her blue from the top and a little pale blush low left, like B's closing "Book"
   block; her logo mark; B's glowing pills in her blue gradient with ink text. The offer is claimed inside the pop-up:
   offer -> form -> done (.of2-s screens, site.js). ---------- */
.theme-l .of2 .op-card.of-screen{justify-content:center;background:
  radial-gradient(75% 52% at 50% -6%,rgba(106,218,216,.40) 0,rgba(106,218,216,.12) 55%,rgba(106,218,216,0) 78%),
  radial-gradient(60% 46% at -4% 104%,rgba(248,215,224,.75) 0,rgba(248,215,224,0) 72%),
  radial-gradient(52% 40% at 104% 98%,rgba(147,232,230,.30) 0,rgba(147,232,230,0) 70%),#fff}
.of2 .of-body{position:relative;z-index:1;margin:auto 0;padding:76px 0 36px;max-width:440px}
/* the X stays put while the form scrolls under it: a soft white disc keeps it clear of the wordmark */
.of2 .op-x{left:14px;right:auto;top:14px;z-index:3;background:rgba(255,255,255,.72);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border:0;box-shadow:none;color:#4f5a5e;width:48px;height:48px}
.of2 .op-x:hover{color:#221916;background:#fff}
.of2-brand{display:flex;flex-direction:column;align-items:center;margin-bottom:30px;color:#221916}
.of2-brand img{width:38px;height:auto;margin-bottom:12px}
.of2-brand b{font:400 28px/1 var(--head);letter-spacing:.32em;margin-right:-.32em}
.of2-brand span{font:400 14px/1 var(--sans);letter-spacing:.3em;margin:8px -.3em 0 0;color:#3d3633}
.of2-brand em{font-style:normal;font:500 9.5px/1 var(--sans);letter-spacing:.34em;margin:9px -.34em 0 0;color:#4f5a5e}
.of2-s{display:flex;flex-direction:column;align-items:center;width:100%}
.of2-s[hidden]{display:none}
/* 2026-10-08 (late), Ruben: "doesn't feel high-end enough ... the weight of the font". Was: 600-weight uppercase
   GET / $50 OFF at 108px and glowing gradient pills, which read as a sale banner. Now: one light line in normal case,
   more air, and quiet hairline pills (her blue fills them on hover / tap) so the offer reads like a spa, not a coupon. */
.of2-title{margin:0;color:#221916;font-family:var(--head);line-height:1}
.of2-get,.of2-amt{display:inline-block;font:300 clamp(50px,11.5vw,76px)/1 var(--head);letter-spacing:-.03em}
.of2-amt{font-weight:400}
.of2-get{margin-right:.22em}
.of2-sub{font:300 clamp(18px,4.4vw,21px)/1.35 var(--sans);color:#3d3633;letter-spacing:.005em;margin:18px 0 34px}
.of2-ask{font:400 15px/1.55 var(--sans);color:#4f5a5e;margin:0 0 18px}
.of2-picks{display:flex;flex-direction:column;gap:10px;width:100%;max-width:330px}
.of-pick{display:flex;align-items:center;justify-content:center;width:100%;height:52px;padding:0 22px;border:1px solid #6adad8;border-radius:999px;background:#6adad8;color:var(--on-blue);box-shadow:none;font:400 15.5px/1 var(--sans);letter-spacing:.01em;text-decoration:none;cursor:pointer;transition:background-color .2s,border-color .2s,color .2s,transform .15s}
.of-pick:hover{background:#5fd5d3;border-color:#5fd5d3}
.of2 .of2-picks .of-pick{background:rgba(255,255,255,.62);border-color:rgba(34,25,22,.16);color:#221916}
.of2 .of2-picks .of-pick:hover{background:#6adad8;border-color:#6adad8;color:#221916}
.of2-unsure{margin-top:20px;font-size:14px;color:#221916;text-decoration:underline;text-decoration-color:rgba(34,25,22,.35);text-decoration-thickness:1px;text-underline-offset:4px}
.of2 .of-no{margin-top:6px;font-size:13.5px;color:#6b7378}
.of2 .of-fine{color:#6b7378;margin-top:14px}
html[lang=zh-CN] .of2-get,html[lang=zh-CN] .of2-amt{display:block;margin:0;letter-spacing:.02em;font-weight:400}
html[lang=zh-CN] .of2-sub{font-weight:400}  /* Noto Sans SC is loaded at 400 + 500 only: 300 fell back to a thin system font */
html[lang=zh-CN] .of2-get{font-size:clamp(30px,6.4vw,40px);margin-bottom:10px}
html[lang=zh-CN] .of2-amt{font-size:clamp(50px,11vw,72px);letter-spacing:0}
html[lang=zh-CN] .of-pick{letter-spacing:.08em}
/* form + done screens */
.of2-h{font:500 clamp(28px,6vw,36px)/1.15 var(--head);letter-spacing:-.015em;color:#221916;margin:0 0 8px;outline:none}
.of2-lead{font-size:16px;line-height:1.5;color:#3d3633;margin:0 0 20px}
.of2-form{max-width:380px;text-align:left}
.of2-form .of2-h,.of2-form .of2-lead{text-align:center;align-self:center}
.of2-f{width:100%;margin:0 0 14px;display:flex;flex-direction:column;gap:6px}
.of2-f label{font:500 14px/1.3 var(--sans);color:#221916}
.of2-f input,.of2-f select{width:100%;height:52px;padding:0 16px;border:1.5px solid #c9dfdf;border-radius:14px;background:#fff;font:400 16px/1.2 var(--sans);color:#221916;-webkit-appearance:none;appearance:none;box-shadow:0 1px 0 rgba(34,25,22,.03);scroll-margin:96px 0 120px}
.of2-f select{padding-right:44px;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23221916' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") right 16px center/14px no-repeat}
.of2-f input:focus,.of2-f select:focus{outline:none;border-color:var(--blue-2);box-shadow:0 0 0 4px rgba(106,218,216,.32)}
.of2-err{display:none;font-size:13.5px;color:#a63a31}
.of2-f.bad input{border-color:#a63a31}
.of2-f.bad .of2-err{display:block}
.of2-go{margin-top:6px}
.of2-go[disabled]{opacity:.7;cursor:progress;transform:none}
.of2-msg{margin:10px 0 0;font-size:14.5px;line-height:1.45;color:#a63a31;text-align:center;align-self:center}
.of2-msg:empty{display:none}
.of2-small{margin:12px 0 0;font-size:13px;color:#5f6670;text-align:center;align-self:center}
.of2-form .of2-back{align-self:center}
.of2-done{max-width:400px}
.of2-next{list-style:none;margin:4px 0 22px;padding:0;width:100%;text-align:left;border-top:1px solid rgba(34,25,22,.1)}
.of2-next li{padding:13px 2px;border-bottom:1px solid rgba(34,25,22,.1);font-size:15.5px;line-height:1.45;color:#2f2a28}
.of2-next b{font-weight:500;color:#221916;overflow-wrap:anywhere}
@media (max-width:640px){.of2 .of-body{padding:70px 0 28px}.of2-brand{margin-bottom:24px}.of2-brand img{width:32px;margin-bottom:10px}}
@media (max-height:760px){.of2 .of-body{padding-top:58px}.of2-brand{margin-bottom:18px}.of2-sub{margin-bottom:24px}}
.of2 .of-pick:focus{outline:none}
.of2 .of-pick:focus-visible{box-shadow:0 0 0 3px #fff,0 0 0 5px rgba(34,25,22,.45)}

/* ---------- 2026-10-08 (night), Ruben: "make the form stay one size throughout the form completion, specifically the
   widget form. On both desktop and mobile." The home picker card is ONE fixed height from "Step 1 of 6" to the done
   screen: computers 620px (the video card beside it, unchanged), phones min(640px, small screen height - 92px) so the
   whole card and its Back/Next row fit under the 72px header with the browser bars showing (svh never changes while
   the bars hide or the keyboard opens, so the card never resizes). The chip and the step label + buttons stay put; a
   long step scrolls inside its own box (steps 1-2: .lp-step; steps 3-6: <main> inside the frame, which is now a fixed
   size too and no longer grows). A soft fade at the bottom shows while more is below. ---------- */
.lh-pick,.lh-pick.st3{height:620px;min-height:0}
.lp-chip,.lp-foot{flex:none}
.lp-step{position:relative;flex:1 1 0;min-height:0;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;
  scrollbar-width:thin;scrollbar-color:#cfe6e5 transparent;padding:4px;margin:-4px}
.lp-step::after,body.embed main::after{content:"";position:-webkit-sticky;position:sticky;bottom:0;display:block;height:34px;margin-top:-34px;
  background:linear-gradient(rgba(255,255,255,0),#fff 90%);pointer-events:none;opacity:0;transition:opacity .2s}
.lp-step.lp-more::after,body.embed main.lp-more::after{opacity:1}  /* not "more": site.css .more{display:none} hid the step, which then fitted, so it flickered (fixed 2026-10-09) */
.lp-step.lp-book{overflow:hidden;padding:0;margin:0}
.lp-step.lp-book::after{content:none}
.lp-frame,.lh-pick.st3 .lp-frame{position:absolute;inset:0;width:100%;height:100%;min-height:0}
@media (max-width:860px){
  .lh-pick,.lh-pick.st3{height:640px;height:min(640px,max(440px,calc(100svh - 92px)))}
  /* phones: goal rows a little tighter (68px tall, were 74) so all six goals show in the fixed card without scrolling */
  .lp-step .lp-h{margin-bottom:18px}
  .lp-goals{gap:8px}
  .lp-goals .lp-opt{min-height:64px;padding:9px 14px}
}
/* inside the frame: the page never scrolls, <main> does (one scroll box, no sideways scroll) */
html.embed-root,html.embed-root body.embed{height:100%;overflow:hidden;margin:0}
body.embed main{height:100%;box-sizing:border-box;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;
  scrollbar-width:thin;scrollbar-color:#cfe6e5 transparent;padding:3px 3px 0}
body.embed .done-box{padding-bottom:0}
/* 320px phones: Chrome gives text boxes a ~250px minimum width, wider than the box, which scrolled it sideways */
body.embed .field{min-width:0}
body.embed .field input,body.embed .field select,body.embed .field textarea{width:100%;min-width:0;box-sizing:border-box}
/* 2026-10-08 (night) legal pass, before/after captions (CA B&P 651): the procedure named plainly + "Results may vary."
   on every result card (home .lres, treatment pages and ig.html .res.ba). Markup: theme_l.l_results, build.results_grid. */
.lres figcaption{flex-direction:column;align-items:flex-start;gap:8px}
.lres figcaption .ba-t{display:flex;flex-direction:column;gap:3px;min-width:0}
.ba-rmv{display:block;font-size:13px;line-height:1.35;color:var(--muted);font-weight:400}
.res.ba .ba-cap{margin-top:10px;display:flex;flex-direction:column;gap:3px}
.res.ba .ba-cap b{font-weight:500;font-size:15px;line-height:1.3}
.res.ba .ba-cap a{margin-top:4px;font-size:14px;font-weight:400;color:var(--ink);text-decoration:underline;text-underline-offset:3px}
/* 2026-10-09 (night): pages with many before/afters show 6, then "See all N results" (build.results_grid, no JS) */
.res-all{margin-top:18px}
.res-all>summary{display:inline-flex;align-items:center;gap:8px;list-style:none;cursor:pointer;padding:10px 20px;border:1px solid var(--line,#d9e9e8);border-radius:999px;font-size:14.5px;color:var(--ink);background:#fff}
.res-all>summary::-webkit-details-marker{display:none}
.res-all>summary::after{content:"";width:7px;height:7px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:translateY(-2px) rotate(45deg)}
.res-all[open]>summary{display:none}
.res-all>.results{margin-top:0}
/* 2026-10-08 (night) legal pass: "photo coming soon" tiles (img/ph/, photo_soon.py) in thumbnails too small for words show
   the camera alone (soon-icon). Bigger slots keep the tile with its line of text. */
.lp-opt .ph[style*="img/ph/soon-"],.lc-ph[style*="img/ph/soon-"],.pick .th[style*="img/ph/soon-"]{background-image:url(../img/ph/soon-icon.webp)!important}
.ig-t img[src*="img/ph/soon-"]{content:url(../img/ph/soon-icon.webp)}
/* 2026-10-08 (late), Ruben: (1) the booking page's Back/Continue row sat flush on the footer. ".wrap{padding:0 34px}"
   above (and the 20px phone gutter) reset .book-wrap's top/bottom padding from site.css; put it back, B only.
   (2) the hours card, rebuilt below. */
body:not(.embed) .wrap.book-wrap{padding-top:40px;padding-bottom:100px}
@media (max-width:760px){body:not(.embed) .wrap.book-wrap{padding-top:20px;padding-bottom:140px}}
/* hours card v2 (Ruben: "no picture... sleek and modern, go with our theme"): one white card like the price menu,
   hairline rows, teal only for the open dot and today's row, the map in a rounded inner panel. */
.lvc{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);gap:34px;border:1px solid var(--line);border-radius:var(--R);padding:36px;background:#fff}
.lvc-info{padding:12px 12px 8px}
.lvc h2{font-size:clamp(30px,3vw,44px);margin:0 0 10px}
.lvc .open-now{display:flex;align-items:center;gap:8px;margin:0 0 22px;font-size:15px;font-weight:400;color:#1f6f6b}
.lvc .open-now:before{content:"";width:8px;height:8px;border-radius:50%;background:var(--blue);box-shadow:0 0 0 4px var(--tint);flex:none}
.lvc .open-now.closed{color:var(--muted)}
.lvc .open-now.closed:before{background:#c4cbcb;box-shadow:0 0 0 4px #f1f3f3}
.lvc .open-now:empty{display:none}
.lvc .hours{margin:0 0 28px;font-size:16px}
.lvc .hours td{padding:12px 0;border-bottom:1px solid var(--line);color:var(--ink)}
.lvc .hours td:last-child{color:var(--muted)}
.lvc .hours tr:last-child td{border-bottom:0}
.lvc .hours tr.today td{background:var(--soft);color:#1f6f6b;font-weight:500;border-bottom-color:transparent}
.lvc .hours tr.today td:first-child{padding-left:14px;border-radius:12px 0 0 12px}
.lvc .hours tr.today td:last-child{padding-right:14px;border-radius:0 12px 12px 0}
.lvc-addr{display:flex;flex-direction:column;gap:4px;margin:0 0 28px;font-size:16px}
.lvc-addr b{font-weight:500;font-size:18px;color:var(--ink)}
.lvc-addr span{color:var(--muted)}
.lvc-addr a{color:#1f6f6b;text-decoration:underline;text-underline-offset:3px;align-self:flex-start}
.lvc .cta-row{margin:0}
.lvc-map{position:relative;min-height:420px;border-radius:var(--r);overflow:hidden;background:var(--soft);isolation:isolate;-webkit-mask-image:-webkit-radial-gradient(white,black)}
.lvc-map iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
@media (max-width:860px){
  .lvc{grid-template-columns:1fr;gap:22px;padding:22px;border-radius:28px}
  .lvc-info{padding:6px 4px 0}
  .lvc-map{min-height:300px;border-radius:18px}
}

/* 2026-10-08 (late), Ruben on the home pair cards + membership plans: "too flat, needs a little pizzazz", on theme.
   No photos. Depth from her own palette: a blush + aqua satin card, a deeper teal gradient with a soft light,
   an oversized faint Meiyan mark cropped off the corner, a teal glow under the teal cards, a lift on hover. */
.lf{min-height:440px;transition:transform .25s ease,box-shadow .25s ease}
.lf-satin,.lf-teal,.theme-l .mp{position:relative;overflow:hidden;isolation:isolate}
.lf-satin{color:var(--ink);border:1px solid rgba(106,218,216,.28);
  background:radial-gradient(70% 90% at 0% 0%,#fde9ee 0,rgba(253,233,238,0) 70%),radial-gradient(80% 100% at 100% 100%,#d4f5f4 0,rgba(212,245,244,0) 70%),linear-gradient(160deg,#fff 0,#f7fcfc 100%);
  box-shadow:0 30px 60px -40px rgba(31,111,107,.35),inset 0 1px 0 #fff}
.lf-satin p{opacity:1;color:#4b5563}
.lf-teal{background:var(--grad-card);
  box-shadow:0 34px 60px -34px rgba(76,205,202,.85),inset 0 1px 0 rgba(255,255,255,.6)}
.lf-satin:after,.lf-teal:after,.theme-l .mp-vip:after{content:"";position:absolute;z-index:-1;pointer-events:none;right:-6%;bottom:-18%;width:52%;aspect-ratio:453/435;background:url(../img/mark-teal-lg.webp) center/contain no-repeat;opacity:.22;transform:rotate(-8deg)}
.lf-teal:after,.theme-l .mp-vip:after{background-image:url(../img/mark-white-lg.webp);opacity:.3}
@media (hover:hover){.lf-satin:hover,.lf-teal:hover{transform:translateY(-4px)}
  .lf-satin:hover{box-shadow:0 40px 70px -40px rgba(31,111,107,.45),inset 0 1px 0 #fff}
  .lf-teal:hover{box-shadow:0 44px 70px -34px rgba(76,205,202,.95),inset 0 1px 0 rgba(255,255,255,.6)}}

/* membership plans (B only; A's .mp stays as is) */
.theme-l .mp{border-radius:var(--R);padding:40px 38px 34px;border-color:rgba(106,218,216,.3);
  background:radial-gradient(90% 60% at 100% 0%,#fdecf0 0,rgba(253,236,240,0) 65%),linear-gradient(180deg,#fff 0,#f6fcfc 100%);
  box-shadow:0 30px 60px -42px rgba(31,111,107,.4),inset 0 1px 0 #fff}
.theme-l .mp-top b{font-size:34px;letter-spacing:-.02em}
.theme-l .mp li{padding:12px 0 12px 34px;border-top-color:rgba(31,111,107,.1)}
.theme-l .mp li:before{left:0;top:13px;width:22px;height:22px;border:0;border-radius:50%;transform:none;opacity:1;
  background:var(--tint) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231f6f6b' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 12.5l4 4 8-9'/%3E%3C/svg%3E") center/13px no-repeat}
.theme-l .mp-vip{border-color:transparent;color:var(--on-blue);
  background:var(--grad-card);
  box-shadow:0 40px 70px -36px rgba(76,205,202,.9),inset 0 1px 0 rgba(255,255,255,.6)}
.theme-l .mp-vip:after{right:-14%;bottom:-12%;width:62%}
.theme-l .mp-vip li{border-top-color:rgba(34,25,22,.12)}
.theme-l .mp-vip li:before{background-color:rgba(255,255,255,.75)}
@media (min-width:861px){.theme-l .mp-vip{transform:translateY(-12px)}}
/* B's membership is ONE paid plan now (Ruben 2026-10-08): a single centred card, no lift */
.theme-l .mps-one{grid-template-columns:1fr;max-width:540px}
.theme-l .mps-one .mp-vip{transform:none}

/* B's offer pop-up, slides (2026-10-09, Ruben from his iPhone): six concerns -> first name -> email -> mobile ->
   gift-card thank-you. Picked concern stays highlighted on Back; the chip above the form says what was picked. */
.of2 .of2-picks .of-pick.on{background:#6adad8;border-color:#6adad8;color:#221916}
.of2-chip{display:flex;align-items:center;justify-content:center;gap:10px;margin:0 0 22px;font:400 14px/1.3 var(--sans);color:#221916;align-self:center}
.of2-cat{padding:6px 14px;border-radius:999px;background:#eef8f7;border:1px solid #c9dfdf}
.of2-change{background:none;border:0;padding:4px 2px;font:inherit;color:#221916;text-decoration:underline;text-decoration-color:rgba(34,25,22,.35);text-underline-offset:4px;cursor:pointer}
.of2-p{width:100%;display:flex;flex-direction:column;align-items:stretch}
.of2-p[hidden]{display:none}
.of2-p .of2-h{margin-bottom:22px}
.of2-p .of2-lead{margin-top:-12px}
.of2.is-form .of-body{margin:0 0 auto}  /* name / email / mobile slides start at the top so the logo stays put */
.of2-ask2{display:none}
.of2-vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.of2-p .of2-f input{height:56px;font-size:17px;text-align:center}
.of2-p .of2-f input::placeholder{color:#8a9599}
.of2-p .of2-go{margin-top:4px}
/* Back: a clear outlined pill on every slide (Ruben: "make the back button easier to see") */
.of2-back{display:inline-flex;align-items:center;justify-content:center;gap:8px;width:100%;height:50px;margin-top:12px;border:1.5px solid rgba(34,25,22,.24);border-radius:999px;background:rgba(255,255,255,.78);font:500 15px/1 var(--sans);color:#221916;cursor:pointer;transition:background-color .2s,border-color .2s}
.of2-back:hover{background:#fff;border-color:rgba(34,25,22,.45)}
.of2-back:focus-visible{outline:none;box-shadow:0 0 0 3px #fff,0 0 0 5px rgba(34,25,22,.45)}
/* slide 1 = the offer + one button; slide 2 = the concerns */
.of2 .of2-start{max-width:330px;margin-top:4px}
.of2-goals .of2-h{text-align:center;margin-bottom:20px}
.of2-goals .of2-back{max-width:330px}
/* the concerns slide: all six fit; a little tighter on phones */
@media (max-width:640px){
  .of2 .of-body{padding-top:62px}
  .of2-brand{margin-bottom:20px}
  .of2-brand img{width:32px;margin-bottom:9px}
  .of2-brand b{font-size:24px}
  .of2-sub{margin:12px 0 20px}
  .of2-ask{margin-bottom:14px}
  .of2-ask1{display:none}
  .of2-ask2{display:inline}
  .of2-picks{gap:8px}
  .of2 .of2-picks .of-pick{height:47px}
  .of2-unsure{margin-top:16px}
}
/* thank-you: the gift card lands with a shine, confetti bursts from behind it (site.js) */
.of2.is-done .of2-brand,.of2.is-done .of-fine{display:none}
.of2-done{position:relative}
.of2-confetti{position:fixed;inset:0;width:100%;height:100%;pointer-events:none;z-index:4}
.of2-gift{position:relative;width:min(300px,82vw);aspect-ratio:1.6;margin:0 0 28px;padding:20px 22px;border-radius:22px;display:flex;flex-direction:column;justify-content:space-between;align-items:flex-start;text-align:left;color:#221916;overflow:hidden;
  background:var(--grad-card);
  box-shadow:0 22px 48px rgba(31,111,107,.24),0 2px 0 rgba(255,255,255,.6) inset,0 0 0 1px rgba(255,255,255,.45) inset;
  animation:of2-gift-in .95s cubic-bezier(.2,1.35,.38,1) both}
.of2-gift::before{content:"";position:absolute;top:-40%;bottom:-40%;left:-60%;width:42%;background:linear-gradient(100deg,rgba(255,255,255,0),rgba(255,255,255,.8),rgba(255,255,255,0));transform:skewX(-18deg);animation:of2-shine 1.5s .75s ease-out both}
.of2-gift::after{content:"";position:absolute;right:-34px;top:50%;width:68px;height:68px;margin-top:-34px;border-radius:50%;background:rgba(255,255,255,.28)}
.of2-gift img{width:30px;height:auto;position:relative}
.of2-gift div{display:flex;flex-direction:column;position:relative}
.of2-gift-amt{font:400 64px/1 var(--head);letter-spacing:-.03em}
.of2-gift-off{font:500 14px/1.3 var(--sans);margin-top:4px}
.of2-gift-for{position:relative;font:500 11.5px/1 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:rgba(34,25,22,.7)}
.of2-gift-for b{font-weight:600;color:#221916;letter-spacing:.08em}
.of2-done .of2-h{animation:of2-up .6s .45s both}
.of2-done .of2-lead,.of2-done .of2-book,.of2-done .of2-close{animation:of2-up .6s .6s both}
@keyframes of2-gift-in{0%{opacity:0;transform:translateY(28px) scale(.7) rotate(-7deg)}100%{opacity:1;transform:none}}
@keyframes of2-shine{0%{left:-60%}100%{left:135%}}
@keyframes of2-up{0%{opacity:0;transform:translateY(12px)}100%{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.of2-gift,.of2-gift::before,.of2-done .of2-h,.of2-done .of2-lead,.of2-done .of2-book,.of2-done .of2-close{animation:none}}

/* booking details: required fields show a small teal star (2026-10-09, Ruben: "Make the necessary elements required";
   first name, last name, mobile and email already blocked Continue when empty, they just did not look required) */
.theme-l .field:has(> input[required]) > label::after{content:"*";margin-left:3px;color:#1f6f6b;font-weight:500}

/* booking confirmation (2026-10-09, Ruben: "make this confirmation a lil more magical too"): an appointment card in the
   pop-up gift card's look lands with the same shine, the drawn check sits on its corner, confetti bursts from behind it
   and the rest rises in after (book.js finish() builds the card, B only) */
.theme-l .bk-card{position:relative;width:min(340px,100%);margin:6px 0 30px;padding:20px 22px 18px;border-radius:22px;color:#221916;overflow:hidden;
  display:flex;flex-direction:column;gap:14px;text-align:left;
  background:var(--grad-card);
  box-shadow:0 22px 48px rgba(31,111,107,.24),0 2px 0 rgba(255,255,255,.6) inset,0 0 0 1px rgba(255,255,255,.45) inset}
.theme-l .bk-card::before{content:"";position:absolute;top:-40%;bottom:-40%;left:-60%;width:42%;pointer-events:none;
  background:linear-gradient(100deg,rgba(255,255,255,0),rgba(255,255,255,.8),rgba(255,255,255,0));transform:skewX(-18deg)}
.theme-l .bk-card::after{content:"";position:absolute;left:-17px;bottom:40px;width:34px;height:34px;border-radius:50%;background:rgba(255,255,255,.3)}
.theme-l .bk-top{position:relative;display:flex;align-items:center;gap:8px;font:500 11.5px/1 var(--sans);letter-spacing:.16em}
.theme-l .bk-top img{width:24px;height:auto}
.theme-l .bk-when{position:relative}
.theme-l .bk-date{display:block;font:400 32px/1.08 var(--head);letter-spacing:-.02em}
.theme-l .bk-time{display:block;font:400 17px/1.3 var(--sans);margin-top:6px}
.theme-l .bk-what{position:relative;font:500 14px/1.4 var(--sans);color:rgba(34,25,22,.78)}
.theme-l .bk-foot{position:relative;display:flex;justify-content:space-between;align-items:center;gap:10px;padding-top:12px;border-top:1px dashed rgba(34,25,22,.28)}
.theme-l .bk-for{font:500 11.5px/1.3 var(--sans);letter-spacing:.14em;text-transform:uppercase;color:rgba(34,25,22,.7)}
.theme-l .bk-for b{font-weight:600;color:#221916;letter-spacing:.08em}
.theme-l .bk-off{font:500 13px/1 var(--sans);padding:7px 11px;border-radius:999px;background:rgba(255,255,255,.6);white-space:nowrap}
.theme-l .bk-card .mo-check{position:absolute;top:14px;right:14px;width:40px;height:40px;margin:0}
.theme-l .bk-card .mo-check circle{fill:#fff;stroke:#fff}
.theme-l .bk-confetti{position:fixed;inset:0;width:100%;height:100%;pointer-events:none;z-index:60}
.theme-l .step.on .bk-card{animation:of2-gift-in .95s cubic-bezier(.2,1.35,.38,1) both}
.theme-l .step.on .bk-card::before{animation:of2-shine 1.5s .75s ease-out both}
.theme-l .step.on .bk-card .mo-check{animation:moPopIn .5s .7s cubic-bezier(.34,1.3,.64,1) both}
.theme-l .step.on .bk-card .mo-check path{animation:moDraw .42s .95s cubic-bezier(.22,1,.36,1) both}
.theme-l .step.on .has-card > h2{animation:of2-up .6s .45s both}
.theme-l .step.on .has-card > .lead,.theme-l .step.on .has-card > .next-list{animation:of2-up .6s .6s both}
.theme-l .step.on .has-card > .cta-row,.theme-l .step.on .has-card > .note{animation:of2-up .6s .75s both}
@media (prefers-reduced-motion:reduce){.theme-l .step.on .bk-card,.theme-l .step.on .bk-card::before,.theme-l .step.on .bk-card .mo-check,
  .theme-l .step.on .bk-card .mo-check path,.theme-l .step.on .has-card > *{animation:none}}

/* the "warp" between a $50 button and the booking page (2026-10-09, Ruben: "go straight to the cart with the discount
   applied ... have the transition ... be a little magical too"; site.js). The gift card's teal opens as a circle from
   the button, "$50 off / Added to your booking" rises in with one shine, the page changes, and on the booking page the
   same screen closes into the offer pill, which pops. Light type, no glow (high-end = light). */
/* 2026-10-09 (later), Ruben: "the animation from the discount to the booking page [is] a little glitchy ... it just needs
   to be smooth". Was a clip-path circle (redrawn by the phone every frame) plus a shine that moved by `left` (layout
   every frame), and the closing half started while the booking page was still loading. Now the circle is its own
   round layer that only SCALES (the graphics chip does it, smooth even while the page is busy), sized in site.js to
   just cover the screen from its centre, and the shine only translates. The words fade out BEFORE the page changes,
   so the booking page only needs the plain teal screen (no font swap mid-animation) to close into the offer pill. */
.warp{position:fixed;inset:0;z-index:2000;display:flex;align-items:center;justify-content:center;color:#221916;pointer-events:none;overflow:hidden;contain:strict}
/* 2026-10-10 (night, later), Ruben: a shorter "Claim my $50" animation, about half as long, same look. Every duration
   and delay in the warp is about halved (circle .62s -> .32s, close .56s -> .30s, words, shine, sparkles, butterfly and
   the pill's pop too); site.js GROW / SHRINK carry the two circle times for Safari's edge bands. Was (bak-2026-10-10-quick):
   amt .45s/.7s at .26s, sub .4s/.6s at .4s, shine 1s at .45s, leave .2s/.3s, pill pop .6s + shine .9s at .25s. */
.warp-c{position:absolute;left:var(--wx,50vw);top:var(--wy,50vh);width:calc(var(--wr,150vmax) * 2);height:calc(var(--wr,150vmax) * 2);
  margin:calc(var(--wr,150vmax) * -1) 0 0 calc(var(--wr,150vmax) * -1);border-radius:50%;
  background:var(--grad-card);
  transform:scale(.001);will-change:transform;backface-visibility:hidden;transition:transform .32s cubic-bezier(.65,0,.35,1)}
.warp.go .warp-c{transform:scale(1)}
.warp.out .warp-c{transform:scale(.001);transition:transform .3s cubic-bezier(.65,0,.35,1)}
.warp.stay .warp-c{transition:none}
.warp::after{content:"";position:absolute;top:-20%;bottom:-20%;left:0;width:38vw;background:linear-gradient(100deg,rgba(255,255,255,0),rgba(255,255,255,.5),rgba(255,255,255,0));transform:translateX(-160%) skewX(-18deg);will-change:transform}
.warp.go:not(.stay)::after{animation:warp-shine .5s .2s cubic-bezier(.4,0,.2,1) both}
@keyframes warp-shine{from{transform:translateX(-160%) skewX(-18deg)}to{transform:translateX(330%) skewX(-18deg)}}
.warp-t{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;gap:10px;text-align:center}
.warp-amt{font:300 clamp(56px,14vw,96px)/1 var(--head);letter-spacing:-.03em;opacity:0;transform:translateY(14px) scale(.96);transition:opacity .22s .1s,transform .36s .1s cubic-bezier(.22,1,.36,1)}
.warp-sub{font:400 15px/1.3 var(--sans);letter-spacing:.06em;opacity:0;transform:translateY(8px);transition:opacity .2s .16s,transform .3s .16s cubic-bezier(.22,1,.36,1)}
.warp.go .warp-amt,.warp.go .warp-sub{opacity:1;transform:none}
.warp.go.leave .warp-amt,.warp.go.leave .warp-sub{opacity:0;transform:translateY(-6px);transition:opacity .1s,transform .15s ease-in}
.theme-l .pf-offer.pf-pop{position:relative;overflow:hidden;animation:pfPop .4s cubic-bezier(.34,1.56,.64,1) both}
.theme-l .pf-offer.pf-pop::after{content:"";position:absolute;top:-30%;bottom:-30%;left:-60%;width:45%;background:linear-gradient(100deg,rgba(255,255,255,0),rgba(255,255,255,.85),rgba(255,255,255,0));transform:skewX(-18deg);animation:of2-shine .5s .12s ease-out both}
@keyframes pfPop{0%{transform:scale(.6);opacity:0}100%{transform:none;opacity:1}}
/* the $250 rule: until the picks reach it, the pill is a quieter hint ("Add $171 in injectables for $50 off") */
.theme-l .pf-offer.pf-wait{background:#f2f7f7;color:#3d5654;font-weight:400}
@media (prefers-reduced-motion:reduce){.warp{display:none}.theme-l .pf-offer.pf-pop,.theme-l .pf-offer.pf-pop::after{animation:none}}

/* ---------- the $50 offer, smoothed (2026-10-09 night, later). Ruben: "making the claim my 50 dollar animation smoother
   i just don't want it to stutter also i noticed that in one frame it covers the ... lower safari bar ... smooth
   especially on iphone mobile but really everywhere". Measured in WebKit + Chromium (390x844 and 1440x900, EN + ZH)
   before changing anything (*.bak-2026-10-09-smoothoffer):
   - the full-screen offer slid up 16px on a phone (grew from 101.5% on a computer), so in its first and last frames it
     hung 4-6px past the bottom of the screen, into the iPhone's bottom bar; it was a fade inside a second fade; its X
     blurred the page behind it (backdrop-filter, re-drawn every frame of the fade); and a 300 ms timer hid it while its
     0.4-0.5 s fade was still running (a cut, not an ending).
   - opening it took the page's scrollbar away: on a Windows computer everything behind shifted 15px during the fade.
   - iPhone Safari 26 colours its top and bottom bars from the full-width pinned box at the middle of each edge (WebKit
     fixedContainerEdges): white the moment the offer was un-hidden (still see-through), and on the booking page teal for
     ~0.8 s after the circle had already left the bottom. site.js: sfShield / cross / nudge.
   Now: the offer screen sits exactly on the screen and only fades (its contents still rise in: motion-l.css 7). */
.theme-l .offer-pop.of{opacity:1;transition:none}
.theme-l .offer-pop.of:not(.in){pointer-events:none}   /* while it fades out nothing under the finger is blocked */
.theme-l .of .op-card.of-screen{transform:none;opacity:0;transition:opacity .4s cubic-bezier(.22,1,.36,1)}
.theme-l .of.in .op-card.of-screen{opacity:1}
.theme-l .of.op-anim .op-card.of-screen{will-change:opacity}   /* its own layer only while it fades (site.js) */
.theme-l .of2 .op-x{-webkit-backdrop-filter:none;backdrop-filter:none;background:rgba(255,255,255,.88);top:calc(14px + env(safe-area-inset-top,0px))}
.theme-l .of2 .of-body{padding-bottom:calc(36px + env(safe-area-inset-bottom,0px))}
@media (max-width:640px){.theme-l .of2 .of-body{padding-bottom:calc(28px + env(safe-area-inset-bottom,0px))}}
@media (prefers-reduced-motion:reduce){.theme-l .of .op-card.of-screen{transition:none}}
html.pop-open{scrollbar-gutter:stable}   /* the page keeps its scrollbar's space while it is locked: nothing shifts */
/* the shields (site.js sfShield): see-through, untouchable, on the two points iPhone Safari reads its bar colour from */
.sf-shield{position:fixed;top:0;left:50%;width:24px;height:16px;margin-left:-12px;z-index:2147483647;pointer-events:none}
.sf-shield.sf-b{top:auto;bottom:0}
/* the warp: its own box is invisible to that probe (only the circle, words, shine and sparkles show). Two bands at the
   top and bottom edge paint nothing (background-clip:text, no text) but carry the teal the circle shows there; site.js
   switches each one on when the circle reaches that edge and off when it leaves it, so Safari's bar matches the screen.
   The circle also carries a mid teal under its (opaque) gradient, in case Safari looks between two switches. On the
   booking page the circle shrinks towards the pill (--wox/--woy, site.js land). The moving pieces are layers from the
   first frame (the warp only exists while it plays), so the first moving frame has nothing left to draw. */
.warp{visibility:hidden}
.warp>*,.warp::after{visibility:visible}
.warp-c{background-color:#7bdcdb;transform-origin:var(--wox,50%) var(--woy,50%)}
.warp-e{display:none;position:fixed;left:0;right:0;height:14px;z-index:2001;color:transparent;-webkit-background-clip:text;background-clip:text;pointer-events:none}
.warp-e.on{display:block}
.warp-et{top:0;background-color:#a3eae8}      /* defaults = the booking page's centred circle (site.js sets them on the way out) */
.warp-eb{bottom:0;background-color:#75d5dc}
@media (min-aspect-ratio:1/1){.warp-et{background-color:#88e3e1}.warp-eb{background-color:#6fd7da}}
.warp-amt,.warp-sub,.warp-s,.warp-bf{will-change:transform,opacity}
/* the booking pill's shine moved by `left` (a layout on every frame, while the booking page is still busy); now it slides */
@media (prefers-reduced-motion:no-preference){
  .theme-l .pf-offer.pf-pop::after{left:0;transform:translateX(-133.3%) skewX(-18deg);animation-name:pf-shine}
  @keyframes pf-shine{from{transform:translateX(-133.3%) skewX(-18deg)}to{transform:translateX(300%) skewX(-18deg)}}
}

/* B's booking page, 2026-10-09: treatments under category tabs (book.js step 9), Botox first. The tabs scroll
   sideways inside the form on a phone; a number on a tab = treatments picked there. */
.bk-cats{display:flex;gap:8px;margin:20px 0 18px;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding:2px}
.bk-cats::-webkit-scrollbar{display:none}
.bk-cat{flex:none;align-items:center;gap:8px;font:500 15px/1 var(--sans);cursor:pointer;white-space:nowrap}
.bk-n{display:inline-grid;place-items:center;min-width:20px;height:20px;padding:0 6px;border-radius:999px;background:var(--ink);color:#fff;font-size:12px}
.bk-cat.on .bk-n{background:#fff;color:var(--on-blue)}
#catList .pick{margin-bottom:10px}

/* Small beauty details (2026-10-09, Ruben: "beauty aspirational in some of the small details such as animations and
   graphics", light, not heavy). Thin white sparkles and a satin sheen, no glow, all transform/opacity only (smooth on a
   phone), all off for reduced motion:
   - the hero "Claim my $50" button: its ✦ twinkles, and a satin sheen crosses it every few seconds
   - the top bar's ✦ twinkles
   - the $50 warp: a few tiny ✦ sparkle around "$50 off" (site.js adds them)
   - booking: picking a treatment pops a tiny ✦ off its check (book.js marks the one just picked) */
@media (prefers-reduced-motion:no-preference){
  .theme-l .lh-claim{position:relative;overflow:hidden;isolation:isolate}
  .theme-l .lh-claim::after{content:"";position:absolute;top:-30%;bottom:-30%;left:0;width:34%;z-index:-1;pointer-events:none;
    background:linear-gradient(100deg,rgba(255,255,255,0),rgba(255,255,255,.6),rgba(255,255,255,0));transform:translateX(-200%) skewX(-18deg);
    animation:bd-satin 6s 2.2s cubic-bezier(.4,0,.2,1) infinite}
  @keyframes bd-satin{0%,74%{transform:translateX(-200%) skewX(-18deg)}100%{transform:translateX(420%) skewX(-18deg)}}
  /* 2026-10-10 (night, later), Ruben: the star on "Claim my $50" twinkles faster, 3.2s -> 1.8s (the only Claim
     button that carries one; the top bar's ✦ before "Claim it" keeps 3.6s) */
  .theme-l .lh-claim span[aria-hidden]{display:inline-block;animation:bd-twinkle 1.8s ease-in-out infinite}
  .topbar .tb-offer:before{display:inline-block;animation:bd-twinkle 3.6s .8s ease-in-out infinite}
  @keyframes bd-twinkle{0%,100%{transform:scale(1) rotate(0deg);opacity:1}45%{transform:scale(.62) rotate(40deg);opacity:.5}}
  .warp-s{position:absolute;z-index:1;left:50%;top:50%;color:#fff;line-height:1;opacity:0;pointer-events:none;
    transform:translate(var(--sx),var(--sy)) scale(.3)}
  .warp.go .warp-s{animation:bd-spark .65s var(--sd) cubic-bezier(.22,1,.36,1) both}   /* 1.25s -> .65s, 2026-10-10 night, later */
  .warp.go.leave .warp-s{animation:none;opacity:0;transition:opacity .1s}
  @keyframes bd-spark{0%{opacity:0;transform:translate(var(--sx),var(--sy)) scale(.3) rotate(0)}
    40%{opacity:.95;transform:translate(var(--sx),calc(var(--sy) - 6px)) scale(1) rotate(45deg)}
    100%{opacity:0;transform:translate(var(--sx),calc(var(--sy) - 16px)) scale(.55) rotate(90deg)}}
  .theme-l .pick i{position:relative}
  .theme-l .pick.bd-pop i::before{content:"✦";position:absolute;right:-9px;top:-11px;font-size:12px;color:var(--blue-2);pointer-events:none;
    animation:bd-tick .8s cubic-bezier(.22,1,.36,1) both}
  @keyframes bd-tick{0%{opacity:0;transform:scale(.2) rotate(0)}45%{opacity:1;transform:scale(1.15) rotate(40deg)}100%{opacity:0;transform:scale(.8) rotate(80deg) translateY(-4px)}}
}

/* Lowkey sparkles and hearts (2026-10-09 evening, Ruben: "don't make it more girl with colors or fonts ... by graphic
   elements like sparkles or hearts but lowkey"). Her teal and white only, thin outlines, small, slow:
   - a thin outline sparkle beside each home section heading, twinkling slowly
   - three tiny white sparkles in the hero video's top corner
   - a small outline heart after each review's "Google"
   - hearts mixed into the booking confetti (book.js burst) */
.theme-l .sec-top h2::after,.theme-l .l-center h2::after{content:"";display:inline-block;width:20px;height:20px;
  margin-left:6px;vertical-align:.5em;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1.5c.5 5.6 4.9 10 10.5 10.5-5.6.5-10 4.9-10.5 10.5C11.5 16.9 7.1 12.5 1.5 12 7.1 11.5 11.5 7.1 12 1.5z' fill='none' stroke='%2352cfcc' stroke-width='1.8' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat}
.lh-spk{position:absolute;top:22px;right:24px;width:64px;height:58px;z-index:2;pointer-events:none}
.lh-spk i{position:absolute;display:block;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1.5c.5 5.6 4.9 10 10.5 10.5-5.6.5-10 4.9-10.5 10.5C11.5 16.9 7.1 12.5 1.5 12 7.1 11.5 11.5 7.1 12 1.5z' fill='%23fff'/%3E%3C/svg%3E") center/contain no-repeat;opacity:.85}
.lh-spk i:nth-child(1){width:18px;height:18px;right:0;top:8px}
.lh-spk i:nth-child(2){width:10px;height:10px;right:26px;top:0}
.lh-spk i:nth-child(3){width:8px;height:8px;right:22px;top:34px}
.lrv-h{display:inline-block;width:12px;height:12px;margin-left:6px;vertical-align:-1px;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 20.3s-7.8-4.7-7.8-10.2a4.4 4.4 0 0 1 7.8-2.8 4.4 4.4 0 0 1 7.8 2.8c0 5.5-7.8 10.2-7.8 10.2z' fill='none' stroke='%2352cfcc' stroke-width='1.6' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat}
@media (prefers-reduced-motion:no-preference){
  .theme-l .sec-top h2::after,.theme-l .l-center h2::after{animation:bd-glint 4.2s ease-in-out infinite}
  @keyframes bd-glint{0%,100%{transform:scale(1) rotate(0deg);opacity:1}45%{transform:scale(.8) rotate(30deg);opacity:.6}}
  .lh-spk i{animation:bd-twinkle 3.4s ease-in-out infinite}
  .lh-spk i:nth-child(2){animation-delay:1.1s}
  .lh-spk i:nth-child(3){animation-delay:2.2s}
}

/* Lowkey butterflies (2026-10-09, Ruben: "Can we add butterfly details on the website? Lowkey"): her clinic's blue
   butterflies, drawn as the same thin outline as the sparkles. A small white one in the hero corner and one in the $50
   warp; two section headings (reviews, first visit) carry a butterfly instead of the sparkle. Wings flutter now and
   then (each wing scales from the body); reduced motion = still. */
.bfly{display:block;overflow:visible}
.bfly path{fill:none;stroke:currentColor;stroke-width:1.15;stroke-linejoin:round;stroke-linecap:round}
.bfly .bw-l,.bfly .bw-r{transform-origin:12px 12px}
.lh-bf{position:absolute;width:24px;height:24px;right:40px;top:28px;color:#fff;opacity:.9}
.warp-bf{position:absolute;z-index:1;left:50%;top:50%;width:30px;height:30px;color:#fff;opacity:0;transform:translate(-150px,-120px)}
.theme-l .l-rev h2::after,.theme-l .l-first h2::after{width:24px;height:24px;vertical-align:.35em;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2352cfcc' stroke-width='1.25' stroke-linejoin='round' stroke-linecap='round'%3E%3Cpath d='M12 11.5C10.2 6.6 5.6 3.6 3.4 5.2C1.5 6.6 3.6 11.4 12 12.2Z'/%3E%3Cpath d='M12 12.6C6.6 12.6 4.4 15.8 5.7 17.8C7.1 19.8 10.4 17.4 12 13.6Z'/%3E%3Cpath d='M12 11.5C13.8 6.6 18.4 3.6 20.6 5.2C22.5 6.6 20.4 11.4 12 12.2Z'/%3E%3Cpath d='M12 12.6C17.4 12.6 19.6 15.8 18.3 17.8C16.9 19.8 13.6 17.4 12 13.6Z'/%3E%3Cpath d='M12 9v8.6M12 9C11.6 7.4 10.9 6.4 10.2 5.8M12 9C12.4 7.4 13.1 6.4 13.8 5.8'/%3E%3C/svg%3E")}
@media (prefers-reduced-motion:no-preference){
  /* 2026-10-10, Ruben: "make that butterfly animation slightly faster": flap 3.4s -> 2.4s, drift 6s -> 4.5s.
     Later the same night: "way faster": flap 2.4s -> 1.1s, drift 4.5s -> 2.6s (thank-you butterfly too). */
  .bfly .bw-l,.bfly .bw-r{animation:bf-flap 1.1s ease-in-out infinite}
  @keyframes bf-flap{0%,58%,100%{transform:scaleX(1)}66%{transform:scaleX(.42)}74%{transform:scaleX(1)}82%{transform:scaleX(.6)}90%{transform:scaleX(1)}}
  .lh-bf{animation:bf-bob 2.6s ease-in-out infinite}
  @keyframes bf-bob{0%,100%{translate:0 0}50%{translate:-4px -5px}}
  .theme-l .l-rev h2::after,.theme-l .l-first h2::after{animation:bf-bob 2.6s ease-in-out infinite}
  .warp.go .warp-bf{animation:bf-up .7s .15s cubic-bezier(.22,1,.36,1) both}   /* 1.4s at .3s -> .7s at .15s with the shorter warp, 2026-10-10 night, later */
  .warp.go .warp-bf .bw-l,.warp.go .warp-bf .bw-r{animation:bf-flap-fast .5s ease-in-out infinite}
  @keyframes bf-flap-fast{0%,100%{transform:scaleX(1)}50%{transform:scaleX(.4)}}
  @keyframes bf-up{0%{opacity:0;transform:translate(-150px,-90px) rotate(-8deg)}35%{opacity:.95}100%{opacity:.9;transform:translate(-128px,-150px) rotate(6deg)}}
  .warp.go.leave .warp-bf{animation:bf-out .12s ease-in both}
  @keyframes bf-out{from{opacity:.9;transform:translate(-128px,-150px) rotate(6deg)}to{opacity:0;transform:translate(-124px,-164px) rotate(6deg)}}
}

/* ---------- B's booking page as a full-screen app (2026-10-09, Ruben, after LaserAway's form): "remove the discount
   banner on the top of the header once they get to the form", "remove the menu and notification button just the logo
   and translation button", "make the steps bar smaller", "the only thing that's scrollable is the section with the
   options. Not the entire page". The page is exactly one screen tall (html.bk-app-root / body.bk-app, build.py APP):
   header, offer pill, step bar, question and the button row stay put; only a step's .bk-scroll (its options) scrolls.
   One-question slides (name / email / mobile, book.js LEAD) have nothing to scroll. ---------- */
html.bk-app-root{height:100%;overflow:hidden}
body.bk-app{height:100%;height:100dvh;overflow:hidden;display:flex;flex-direction:column;margin:0}
.bk-app .topbar,.bk-app .l-bell,.bk-app .menu-btn,.bk-app nav.main,.bk-app footer.site,.bk-app .mbar{display:none!important}
.bk-app header.site{flex:none;position:relative}
.bk-app header.site .wrap{height:64px}
.bk-app .head-right{display:flex;align-items:center}  /* on a computer too: the menu row is gone, 中文/EN stays */
.bk-app main{flex:1;min-height:0;display:flex;flex-direction:column}
body.bk-app .wrap.book-wrap{flex:1;min-height:0;width:100%;box-sizing:border-box;padding-top:6px;padding-bottom:0;align-items:stretch;grid-template-rows:minmax(0,1fr)}
.bk-app .book-wrap>div{display:flex;flex-direction:column;min-height:0}
.bk-app #bookForm{flex:1;min-height:0;display:flex;flex-direction:column}
.bk-app .step.on{flex:1;min-height:0;display:flex;flex-direction:column;overflow-y:auto;-webkit-overflow-scrolling:touch}
.bk-app .step.on:has(.bk-scroll){overflow:hidden}
.bk-app .step>*{flex:none}
.bk-app .bk-scroll{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  margin:0 -8px;padding:2px 8px 18px;
  -webkit-mask-image:linear-gradient(#000 calc(100% - 26px),transparent);mask-image:linear-gradient(#000 calc(100% - 26px),transparent)}
.bk-app .bk-scroll .opts{margin-top:4px!important}
.bk-app .step h2{font-size:clamp(25px,2.6vw,32px);font-weight:400;letter-spacing:-.01em;margin:0 0 6px}
.bk-app .step .hint{font-size:15.5px;margin:0 0 14px}
.bk-app .bk-cats{flex:none;margin-bottom:12px}
.bk-app .nav-row{flex:none;position:static;margin:0;padding:12px 0 calc(12px + env(safe-area-inset-bottom));border-top:0;background:transparent}
.bk-app .bk-toast{flex:none;margin:8px 0 0!important}
/* the step bar: one small line, "Step 1 of 4 · Treatment" on the left and a thin bar beside it (was a full-width bar
   with a line of text under it) */
.bk-app .bk-head{flex:none;display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;column-gap:14px;margin:4px 0 16px}
.bk-app .bk-head .prefill{grid-column:1/-1;grid-row:1;background:none;padding:0;margin:0 0 10px;font-size:14.5px}
.bk-app .bk-head .prefill .pf-offer{margin-right:6px}
.bk-app .bk-head .step-count{display:block;grid-column:1;grid-row:2;margin:0;font-size:13px;white-space:nowrap}
.bk-app .bk-head .progress{grid-column:2;grid-row:2;margin:0;gap:4px}
.bk-app .bk-head .progress i{height:3px}
/* one question per slide */
.bk-app .bk-one{margin-top:8px}
.bk-app .bk-one .field input{height:56px;font-size:18px;padding:0 16px;width:100%;box-sizing:border-box}
.theme-l .bk-fine{font-size:12.5px;line-height:1.5;color:var(--muted);margin:14px 0 0;max-width:520px}  /* book.html and the home card */
/* the request-sent screen scrolls on its own if a short phone needs it */
.bk-app .step[data-step="6"].on{padding-bottom:24px}
/* computer: the summary stays on the right and scrolls by itself if it is ever taller than the screen */
.bk-app .summary{position:static;align-self:start;max-height:100%;overflow-y:auto;padding-top:6px}
/* the concept tag sits up in the header, clear of the options and the Back button */
.bk-app .demo-ribbon{top:calc(18px + env(safe-area-inset-top));bottom:auto;left:50%;right:auto;transform:translateX(-50%)}
@media (max-width:760px){
  .bk-app header.site .wrap{height:58px}
  .bk-app .step h2{font-size:24px}
  .bk-app .nav-row .btn{height:52px}
  .bk-app .demo-ribbon{top:calc(15px + env(safe-area-inset-top));bottom:auto;left:auto;right:86px;opacity:.75}  /* in the header gap, between the logo and 中文 */
}
.bk-app .bk-head .progress span{display:none}  /* the bar alone; the words are in "Step 1 of 4 · Treatment" */
.bk-app .bk-one,.bk-app .step[data-step="10"] .bk-one{max-width:560px}

/* the step bar glides (2026-10-09, Ruben: "Make the progress bar smooth"): book.html = one track, its fill eases to the
   next step (book.js LEAD); the home card's bar gets the same easing */
.bk-app .bk-head .progress .bk-track{flex:1;height:4px;border-radius:9px;background:#e9eeee;overflow:hidden}
.bk-app .bk-head .progress .bk-track i{display:block;width:0;height:100%;border-radius:9px;background:var(--grad);transition:width .7s cubic-bezier(.22,1,.36,1)}
.lp-bar i{transition:width .7s cubic-bezier(.22,1,.36,1)}
@media (prefers-reduced-motion:reduce){.bk-app .bk-head .progress .bk-track i,.lp-bar i{transition:none}}

/* thank-you (2026-10-09, Ruben: "I don't like the end thank you page why a card lol? It should be on brand"): no card,
   no confetti. Her mark in a soft pearl circle, a thin teal butterfly and two sparkles (the site's own lowkey details),
   a light heading, one line on who reaches out, hairline rows, one pill. Centred, calm, light type. */
.ty{text-align:center;max-width:500px;margin:0 auto;padding:clamp(12px,5vh,48px) 0 24px}
.ty-mark{position:relative;width:96px;height:96px;margin:0 auto 26px;border-radius:50%;display:grid;place-items:center;
  background:radial-gradient(circle at 35% 30%,#fff,#e4f8f7 60%,#d2f2f1);box-shadow:0 0 0 1px #d6f1f0,0 18px 40px -22px rgba(82,207,204,.55)}
.ty-mark img{width:46px;height:auto}
.ty-bf{position:absolute;width:26px;height:26px;right:-18px;top:-8px;color:#52cfcc}
.ty-mark i{position:absolute;display:block;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1.5c.5 5.6 4.9 10 10.5 10.5-5.6.5-10 4.9-10.5 10.5C11.5 16.9 7.1 12.5 1.5 12 7.1 11.5 11.5 7.1 12 1.5z' fill='none' stroke='%2352cfcc' stroke-width='1.8' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat}
.ty-mark i:nth-of-type(1){width:14px;height:14px;left:-16px;top:26px}
.ty-mark i:nth-of-type(2){width:9px;height:9px;right:-4px;bottom:6px}
.ty h2{font-weight:300;font-size:clamp(30px,3.6vw,40px);letter-spacing:-.015em;line-height:1.15;margin:0 0 12px}
.bk-app .ty h2{font-weight:300;font-size:clamp(30px,3.6vw,40px)}
.ty .ty-lead{font-size:17px;line-height:1.6;color:var(--muted);margin:0 auto 28px;max-width:430px}
.ty .ty-lead b{color:var(--ink);font-weight:500;white-space:nowrap}
.ty-rows{margin:0 0 22px;border-top:1px solid var(--line);text-align:left}
.ty-rows div{display:flex;justify-content:space-between;align-items:baseline;gap:18px;padding:14px 2px;border-bottom:1px solid var(--line);font-size:15px}
.ty-rows dt{color:var(--muted);flex:none}
.ty-rows dd{margin:0;text-align:right;color:var(--ink)}
.ty-rows .pf-offer{margin:0}
.ty .ty-q{font-size:15px;color:var(--muted);margin:0 0 24px}
.ty .cta-row{justify-content:center;margin:0}
.ty .cta-row .btn{min-width:220px}
.ty .note{margin-top:20px;font-size:13px}
@media (max-width:760px){.ty .cta-row{display:flex}.ty .cta-row .btn{width:100%}}
@media (prefers-reduced-motion:no-preference){
  .step.on .ty-mark{animation:ty-in .8s cubic-bezier(.22,1.2,.36,1) both}
  .step.on .ty>:not(.ty-mark){animation:of2-up .7s both}
  .step.on .ty>h2{animation-delay:.25s}
  .step.on .ty>.ty-lead{animation-delay:.38s}
  .step.on .ty>.ty-rows{animation-delay:.5s}
  .step.on .ty>.ty-q,.step.on .ty>.cta-row,.step.on .ty>.note{animation-delay:.62s}
  .ty-mark i{animation:bd-twinkle 3.4s ease-in-out infinite}
  .ty-mark i:nth-of-type(2){animation-delay:1.3s}
  .ty-bf{animation:bf-bob 2.6s ease-in-out infinite}
  @keyframes ty-in{from{opacity:0;transform:scale(.7)}to{opacity:1;transform:none}}
}
.ty .mo-check{display:none}  /* motion-l.js adds a drawn check to every done box; the mark circle is the check here */
.bk-app .book-wrap:has(.step[data-step="6"].on){grid-template-columns:minmax(0,1fr)}  /* thank-you: no summary beside it */
.bk-app .book-wrap:has(.step[data-step="6"].on) .summary{display:none}
.ty-bf{width:30px;height:30px;right:-24px;top:-12px}
.ty-bf path{stroke-width:1.3}
.ty .nw{white-space:nowrap}
/* 2026-10-09, Ruben (iPhone screenshot): the mobile box's teal focus ring was cut off left and right. The step is its own
   scroll box, which clips anything past its edge; give it 8px of room each side (and the home card's box 3px more) */
.bk-app .step.on{margin-left:-8px;margin-right:-8px;padding-left:8px;padding-right:8px}
body.embed .bk-one{padding:0 3px}

/* 2026-10-09, Ruben ("Go" + "the pricing is not final it may change at time of visit"): the thank-you's price note and
   its "pick a time yourself" box; B's calendar step (returning clients, or after the request) inside the app */
.ty .ty-price{font-size:13px;line-height:1.5;color:var(--muted);margin:-8px 0 22px}
.ty-pick{margin:0 0 22px;padding:18px 18px 20px;border:1px solid var(--line);border-radius:20px}
.ty-pick[hidden]{display:none}
.ty-pick p{margin:0 0 12px;font-size:15.5px;color:var(--ink)}
.ty-pick .btn{min-width:200px}
.bk-app .bk-cal{border:0;padding:0;background:none}
.theme-l .reassure li+li{margin-top:4px}
.bk-app .nav-row .btn{white-space:nowrap}

/* the quiz's thank-you (home card, 2026-10-09: "the quiz should have thank you ... improve it"): the same page, sized
   for the card's fixed box so the whole thing shows with little or no scrolling */
body.embed .ty{padding:4px 0 8px;max-width:none}
body.embed .ty-mark{width:72px;height:72px;margin-bottom:14px}
body.embed .ty-mark img{width:36px}
body.embed .ty-bf{width:24px;height:24px;right:-18px;top:-8px}
body.embed .ty h2{font-size:clamp(24px,2.4vw,30px);margin-bottom:8px}
body.embed .ty .ty-lead{font-size:15.5px;line-height:1.55;margin-bottom:18px}
body.embed .ty-rows{margin-bottom:14px}
body.embed .ty-rows div{padding:10px 2px;font-size:14px}
body.embed .ty .ty-price{margin:-4px 0 16px;font-size:12.5px}
body.embed .ty-pick{padding:14px 14px 16px;margin-bottom:16px}
body.embed .ty .ty-q{font-size:14px;margin-bottom:16px}
/* 2026-10-09: a treatment hero that is a whole before/after photo (lip filler): show all of it, never crop the halves */
/* 2026-10-09 (night): every B&A hero takes its own shape (--ar from build.BA_SIZE); tall ones are capped on phones */
.t-photo.t-photo-ba{position:relative;aspect-ratio:var(--ar,1284/877);align-self:center}
.t-photo.t-photo-ba img{object-fit:contain;object-position:center}
.t-ba-cap{position:absolute;left:12px;bottom:12px;padding:5px 11px;border-radius:999px;background:rgba(255,255,255,.88);color:var(--ink);font-size:12.5px;letter-spacing:.01em}
@media (max-width:760px){.t-photo.t-photo-ba{aspect-ratio:var(--ar,1284/877);max-height:68svh;width:auto;margin-left:auto;margin-right:auto;border-radius:14px}}
/* 2026-10-09 (Ruben, desktop: "it won't let me scroll"): the wide-screen zoom (zoom 1.1-1.8 from 1600px) made the one-screen
   booking app 100dvh x zoom tall, so its bottom (the end of the list + Back/Continue) sat below the window, and the page itself
   cannot scroll. The booking app keeps zoom 1 so it is exactly one window tall at every width. */
body.theme-l.bk-app{zoom:1}
/* 2026-10-09: stock photo tag (motion-l.js) */
.stk{position:absolute;left:10px;bottom:10px;z-index:2;padding:3px 9px;border-radius:999px;background:rgba(255,255,255,.88);color:#4b5563;font-size:11px;font-weight:400;line-height:1.35;letter-spacing:.02em;pointer-events:none;white-space:nowrap;text-transform:none}
.stk.stk-s{left:auto;right:-3px;bottom:-3px;width:15px;height:15px;padding:0;display:grid;place-items:center;font-size:12px;line-height:1;box-shadow:0 0 0 1px var(--line)}
/* 2026-10-09 (later): the quiz questions about the person (text-only answers, one column) + Botox-only offer form */
.lp-grid.lp-1col{display:grid;grid-template-columns:1fr;gap:10px}
.lp-opt.lp-txt{min-height:58px;font-size:16px}
.bk-cats[hidden]{display:none!important}
/* 2026-10-09: on a phone the Concept ribbon sat on the quiz card's Back button; hide it while the quiz is past its first step */
@media (max-width:860px){body:has(#lpick.st2) .demo-ribbon,body:has(#lpick.st3) .demo-ribbon{display:none}}
/* 2026-10-09: .showing{display:flex} beat [hidden], so "Showing treatments for: / See all" showed on the All view too, where See all did nothing */
.showing[hidden]{display:none!important}
/* 2026-10-09: the $50 Botox form hides its price total (book.js); .sum-total{display:flex} beat [hidden] */
.sum-total[hidden]{display:none!important}
/* 2026-10-09: small floating Book button on the home page (motion-l.js). Bottom-right; the Concept ribbon is bottom-left on phones and bottom-right on computers, so it sits above it there */
.l-fab{position:fixed;right:16px;bottom:calc(16px + env(safe-area-inset-bottom));z-index:65;display:inline-flex;align-items:center;justify-content:center;height:44px;padding:0 22px;border-radius:999px;background:var(--grad);color:var(--ink);font:500 15px/1 var(--sans);letter-spacing:.01em;text-decoration:none;box-shadow:0 10px 24px -12px rgba(0,0,0,.45),0 0 0 1px rgba(255,255,255,.6) inset;opacity:0;transform:translateY(14px);pointer-events:none;transition:opacity .25s ease,transform .25s ease}
.l-fab.on{opacity:1;transform:none;pointer-events:auto}
@media (min-width:861px){.l-fab{bottom:60px;right:16px}}
@media (prefers-reduced-motion:reduce){.l-fab{transition:none}}
/* 2026-10-09: About facts are three on B ("Every price listed online" removed): three across; on a phone the third spans the row */
.theme-l .ab-facts{grid-template-columns:repeat(3,1fr)}
@media (max-width:760px){.theme-l .ab-facts{grid-template-columns:1fr 1fr}.theme-l .ab-facts div:nth-child(3){grid-column:1/-1;border-left:0;padding-left:0}}
/* 2026-10-09 (Ruben: "desktop doesn't need a floating book button. Since it already has one in the header"): phones only */
@media (min-width:861px){.l-fab{display:none!important}}
/* ---------- highlight textures (2026-10-09 night, Ruben: "anyway we can somehow involve these textures? in small
   details?"). The five round covers on her live Instagram highlights (img/texture/, texture_l.py, SOURCES.md there):
   gel swirl = GUESTS, pale silk = PRICES, shimmer = LASER, teal satin = SKIN, whipped cream = VISIT US. They are
   ~250 px originals, so only small circles, never behind body text, no new colours:
   1. Most booked: a thin texture ring around each round photo, in her highlight row's order, card by card
   2. review cards with no Google picture: the GUESTS gel swirl behind the initial (soft white veil over it)
   3. thank-you: her mark sits on the pale silk instead of the plain pearl circle
   4. footer: five tiny highlight circles after "Instagram", like her profile's highlight row
   Tried and dropped: satin inside the booking check circle (28 px: the folds hid the tick). ---------- */
.theme-l .lc-ph{position:relative}
.theme-l .lc-ph::after{content:"";position:absolute;inset:-7px;border-radius:50%;pointer-events:none;
  background:url(../img/texture/gel.webp) center/112% no-repeat;
  -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 3px),#000 calc(100% - 2.5px));
  mask:radial-gradient(farthest-side,transparent calc(100% - 3px),#000 calc(100% - 2.5px))}
.theme-l .lc:nth-child(5n+2) .lc-ph::after{background-image:url(../img/texture/silk.webp)}
.theme-l .lc:nth-child(5n+3) .lc-ph::after{background-image:url(../img/texture/shimmer.webp)}
.theme-l .lc:nth-child(5n+4) .lc-ph::after{background-image:url(../img/texture/satin.webp)}
.theme-l .lc:nth-child(5n+5) .lc-ph::after{background-image:url(../img/texture/cream.webp)}
.theme-l .lrv-av:not(.lrv-pic){background:url(../img/texture/gel.webp) center/112% no-repeat;color:#1f6f6b;
  box-shadow:inset 0 0 0 28px rgba(255,255,255,.42);text-shadow:0 0 8px #fff}
.ty-mark{background:radial-gradient(circle at 50% 50%,rgba(255,255,255,.6),rgba(255,255,255,0) 62%),#e4f8f7 url(../img/texture/silk.webp) center/104% no-repeat}
.theme-l footer.site a[href*="instagram.com"]::after{content:"";display:inline-block;width:86px;height:14px;margin-left:10px;vertical-align:-2px;
  background:url(../img/texture/gel.webp) 0 0/14px 14px no-repeat,url(../img/texture/silk.webp) 18px 0/14px 14px no-repeat,
    url(../img/texture/shimmer.webp) 36px 0/14px 14px no-repeat,url(../img/texture/satin.webp) 54px 0/14px 14px no-repeat,
    url(../img/texture/cream.webp) 72px 0/14px 14px no-repeat}
.theme-l footer.site a[href*="instagram.com"]{white-space:nowrap}
@media (max-width:760px){  /* the phone footer column is ~170 px: smaller dots so the row stays beside "Instagram" */
  .theme-l footer.site a[href*="instagram.com"]::after{width:71px;height:11px;margin-left:7px;vertical-align:-1px;
    background-size:11px 11px;background-position:0 0,15px 0,30px 0,45px 0,60px 0}}
@media (max-width:359px){.theme-l footer.site a[href*="instagram.com"]::after{display:none}}  /* 320 px: no room beside it */

/* ---------- Pop-up butterflies (2026-10-09, Ruben: "Can we have the pop-up open with butterflies? Like a slight little
   animation there?"). Three small thin-line butterflies in her teal drift up from behind the offer and fade, once, as
   the pop-up opens (build.py offer_popup_full). Lowkey: outline only, no new colours. Reduced motion = none. ---------- */
.of2-bfs{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.of2-bf{position:absolute;opacity:0;color:#52cfcc}
.of2-bf:nth-child(1){width:32px;height:32px;left:calc(50% - 190px);top:46%}
.of2-bf:nth-child(2){width:26px;height:26px;left:calc(50% + 160px);top:54%;color:#6adad8}
.of2-bf:nth-child(3){width:20px;height:20px;left:calc(50% - 110px);top:66%;color:#6adad8}
@media (max-width:640px){.of2-bf:nth-child(1){left:8%}.of2-bf:nth-child(2){left:auto;right:9%}.of2-bf:nth-child(3){left:22%}}
@media (prefers-reduced-motion:no-preference){
  .of2.in .of2-bf:nth-child(1){animation:of2-fly1 3s .25s cubic-bezier(.22,1,.36,1) both}
  .of2.in .of2-bf:nth-child(2){animation:of2-fly2 3.2s .45s cubic-bezier(.22,1,.36,1) both}
  .of2.in .of2-bf:nth-child(3){animation:of2-fly3 2.8s .7s cubic-bezier(.22,1,.36,1) both}
  .of2.in .of2-bf .bw-l,.of2.in .of2-bf .bw-r{animation:bf-flap-fast .55s ease-in-out infinite}
  @keyframes of2-fly1{0%{opacity:0;transform:translate(0,0) rotate(-6deg)}20%{opacity:.9}70%{opacity:.75}100%{opacity:0;transform:translate(-36px,-230px) rotate(-14deg)}}
  @keyframes of2-fly2{0%{opacity:0;transform:translate(0,0) rotate(8deg)}22%{opacity:.85}70%{opacity:.7}100%{opacity:0;transform:translate(42px,-260px) rotate(16deg)}}
  @keyframes of2-fly3{0%{opacity:0;transform:translate(0,0) rotate(0)}25%{opacity:.8}70%{opacity:.6}100%{opacity:0;transform:translate(-14px,-200px) rotate(-8deg)}}
}
@media (prefers-reduced-motion:reduce){.of2-bfs{display:none}}

/* ---------- Big monitors (2026-10-09, Ruben: "it's a little too wide on large screens ... on some small monitor it
   looks decent"). The 10-08 zoom steps (above) made the 1440 layout fill the whole width of a wide monitor. Now the
   content stops at 1280 and the zoom steps are gentler, so a wide screen gets white space on both sides instead of
   a page stretched edge to edge. Up to 1440 nothing changes. ---------- */
.theme-l{--wrap:1280px}
.theme-l .wrap{max-width:var(--wrap);margin-left:auto;margin-right:auto}
@media (min-width:1600px){body.theme-l{zoom:1.05}}
@media (min-width:1760px){body.theme-l{zoom:1.1}}
@media (min-width:1900px){body.theme-l{zoom:1.15}}
@media (min-width:2100px){body.theme-l{zoom:1.25}}
@media (min-width:2400px){body.theme-l{zoom:1.35}}
@media (min-width:2700px){body.theme-l{zoom:1.5}}
@media (min-width:1600px) and (max-height:1000px){body.theme-l{zoom:1.05}}
@media (min-width:2100px) and (max-height:1250px){body.theme-l{zoom:1.2}}

/* ---------- Treatment pages, top (2026-10-09, Ruben: "fix the margins ... the top treatment slash TOX is obviously
   not spaced enough", "make this whole graphical interface look a little cleaner ... clean and clear. Nice and
   easy"). The crumb line lost its top space to ".wrap{padding:0 34px}" (same weight, later), so it sat on the header.
   Now: the crumb has room; the photo is a calm square that no longer towers over the words, so the title no longer
   floats in empty space; one clear column of words (title, name, one line, two buttons); the facts sit in a quiet
   row of four under a hairline. ---------- */
.theme-l .wrap.crumbs{padding-top:30px;font-size:13.5px;letter-spacing:.01em}
.theme-l .crumbs a{color:var(--muted)}
.theme-l .crumbs a:last-child{color:var(--ink)}
.theme-l .t-hero{padding:34px 0 80px}
.theme-l .t-grid{grid-template-columns:minmax(0,1fr) minmax(0,.86fr);gap:clamp(48px,6vw,96px);align-items:center}
.theme-l .t-photo:not(.t-photo-ba){aspect-ratio:1/1;border-radius:var(--r)}
.theme-l .t-photo-ba{border-radius:var(--r)}
.theme-l .t-hero h1{font-size:clamp(40px,4.4vw,62px);line-height:1.04}
.theme-l .t-hero h1 small{margin-top:16px;font-size:20px}
.theme-l .t-hero .lead{max-width:30em;margin:22px 0 32px;font-size:18px;line-height:1.55}
.theme-l .t-hero .facts{margin-top:52px;padding-top:26px;grid-template-columns:repeat(4,auto);justify-content:space-between;gap:20px 32px}
.theme-l .t-hero .facts small{font-size:13px;margin-bottom:6px}
.theme-l .t-hero .facts b{font-size:17px;font-weight:500;white-space:nowrap}  /* "about 4-6 months" on one line */
@media (max-width:1240px){.theme-l .t-hero .facts{grid-template-columns:1fr 1fr;justify-content:stretch}.theme-l .t-hero .facts b{white-space:normal}}
@media (max-width:760px){  /* phones keep the full-width photo on top (site.css) */
  .theme-l .wrap.crumbs{padding-top:18px}
  .theme-l .t-hero{padding:18px 0 40px}
  .theme-l .t-grid{grid-template-columns:1fr;gap:24px}
  .theme-l .t-photo:not(.t-photo-ba){aspect-ratio:16/10;border-radius:0}
  .theme-l .t-hero h1 small{margin-top:12px;font-size:18px}
  .theme-l .t-hero .lead{font-size:16.5px;margin:16px 0 24px}
  .theme-l .t-hero .facts{margin-top:30px}
}

/* 2026-10-10 Ruben: "making the treatment and prices list a grid list". treatments.html, B only (build.py adds .tc-grid
   on B and puts the no-page entries in as .tc-short tiles). Same words, links and prices as the old two-wide cards.
   Columns: 4 from 1200 px, 3 from 900, 2 below (phones too: two short tiles per row = about four treatments a screen,
   where the old full-width card showed one). Tiles in a row are one height; price + buttons sit on one line across. */
.tc-list.tc-grid{grid-template-columns:repeat(4,minmax(0,1fr));gap:18px}
.tc-grid .tc{position:relative;padding:0 0 18px;border:1px solid var(--line);border-radius:18px;background:#fff;transition:border-color .2s}
.tc-grid .tc:hover{border-color:rgba(106,218,216,.7)}
.tc-grid .tc-ph{aspect-ratio:4/3;margin-bottom:14px}
.tc-grid .tc-top{display:contents}  /* name and price become their own rows, so the price can sit just above the buttons */
.tc-grid .tc h3,.tc-grid .tc-price{margin-left:18px;margin-right:18px}
.tc-grid .tc>*:not(.tc-ph){margin-left:18px;margin-right:18px}
.tc-grid .tc h3{order:1;font-size:19px;font-weight:400;line-height:1.3;margin-bottom:4px}
.tc-grid .tc h3 a:after{content:"";position:absolute;inset:0;z-index:1;border-radius:inherit}  /* the whole tile opens the page */
.tc-grid .tc-name{order:2;margin-top:0;margin-bottom:10px;font-size:14.5px;line-height:1.4}
.tc-grid .tc-name b{font-weight:400}
.tc-grid .tc-what{order:3;font-size:15px;line-height:1.5;margin-bottom:10px}
.tc-grid .tc-facts{order:4;flex-direction:column;gap:2px;font-size:13.5px;margin-bottom:14px}
.tc-grid .tc-price{order:5;margin-top:auto;margin-bottom:12px;padding-top:12px;border-top:1px solid var(--line);font-size:16px;font-weight:500;white-space:normal}
.tc-grid .tc-btns{order:6;position:relative;z-index:2;gap:8px;margin-top:0}  /* site.css gives it margin-top:auto too; one auto (the price's) keeps prices level */
.tc-grid .tc-btns .btn{min-width:0;height:44px;padding:0 10px;font-size:14.5px;font-weight:400;box-shadow:none}
.tc-grid .tc-btns .btn-ghost{border:1px solid var(--line)}
@media (max-width:1199px){.tc-list.tc-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:899px){.tc-list.tc-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}}
@media (max-width:600px){  /* phones: two per row, photo + name + what it does + price + Book; the rest is on the page */
  .tc-list.tc-grid{gap:10px}
  .tc-grid .tc{padding-bottom:12px;border-radius:14px}
  .tc-grid .tc-ph{margin-bottom:10px}
  .tc-grid .tc h3,.tc-grid .tc-price,.tc-grid .tc>*:not(.tc-ph){margin-left:12px;margin-right:12px}
  .tc-grid .tc h3{font-size:16px;line-height:1.3}
  .tc-grid .tc-name{font-size:13px;margin-bottom:8px}
  .tc-grid .tc-what,.tc-grid .tc-facts{display:none}
  .tc-grid .tc-price{font-size:15px;padding-top:10px;margin-bottom:10px}
  .tc-grid .tc-btns .btn-ghost{display:none}
  .tc-grid .tc-btns .btn{font-size:14.5px}
}
/* Home "All treatments" price card, same request: the chosen category's price lines as a two-wide grid of small tiles
   (each still the same link, name, treatment and price, sale price struck through as before). */
.lsv-pane{padding:16px}
.lsv-pane .pt-pane:not([hidden]){display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
.lsv-pane .pt-row,.lsv-pane .pt-row:last-child{flex-direction:column;align-items:stretch;justify-content:flex-start;gap:10px;min-height:44px;padding:14px 16px;border:1px solid #dfeceb;border-radius:14px;background:#fff;transition:border-color .2s}
.lsv-pane .pt-row:hover{border-color:var(--blue-l)}
.lsv-pane .pt-n{display:block;font-weight:400;line-height:1.3}  /* block, not site.css's flex column: Chinese pieces must flow as words */
.lsv-pane .pt-n small{display:block}
.lsv-pane .pt-n small{margin-top:3px;line-height:1.35}
.lsv-pane .pt-p{margin-top:auto}
/* Chinese names in both grids come in phrase pieces (build.zh_wrap): a piece moves to the next line whole; one wider than
   its tile still wraps inside (no nowrap, no word-break:keep-all, which stops iPhone Safari wrapping Chinese at all) */
.zb{display:inline-block;max-width:100%;text-wrap:pretty}  /* pretty: a piece that must wrap inside avoids a one-character last line */
@media (max-width:760px){
  .lsv-pane{padding:10px}
  .lsv-pane .pt-pane:not([hidden]){gap:8px}
  .lsv-pane .pt-row,.lsv-pane .pt-row:last-child{padding:12px}
  .lsv-pane .pt-n{font-size:15px}
  .lsv-pane .pt-p{font-size:15px}
  .lsv-pane .pt-p s{font-size:13px;margin-right:6px}
}
/* 2026-10-10 hero = light studio shot of the Botox box (theme_l .lh-studio): dark words straight on the image, no dark
   shade, no text shadows; sparkles + butterfly in brand teal so they show on the pale backdrop. */
.lh-studio{background:#eef7f8}
.lh-studio:after{display:none}
.lh-studio .lh-words{color:#221916}
.lh-studio .lh-words h1,.lh-studio .lh-sub,.lh-studio .lh-fine{text-shadow:none}
.lh-studio .lh-sub{opacity:1;color:#3d3633}
.lh-studio .lh-fine{opacity:1;color:#5d5653}
.lh-studio .lh-spk i{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1.5c.5 5.6 4.9 10 10.5 10.5-5.6.5-10 4.9-10.5 10.5C11.5 16.9 7.1 12.5 1.5 12 7.1 11.5 11.5 7.1 12 1.5z' fill='%236ADAD8'/%3E%3C/svg%3E")}
.lh-studio .lh-bf{color:#6ADAD8;opacity:1}
.lh-ph img{cursor:default}  /* 2026-10-10: the hero photo does not enlarge (site.js skips .lh) */
/* 2026-10-10 "Offer terms" link under each first-visit fine print (build.terms_link) + the offer-terms.html list */
.lh-terms,.of-terms,.ld-terms,.ig-terms{margin:6px 0 0;font-size:13px;line-height:1.4}
.lh-terms a,.of-terms a,.ld-terms a,.ig-terms a{color:inherit;text-decoration:underline;text-underline-offset:3px}
.ig-terms{display:block}
.lh-studio .lh-terms{color:#5d5653}
.ot-sec{padding:8px 0 56px}
.ot-list{max-width:640px;margin:0 0 24px;padding-left:1.4em;font-size:17px;line-height:1.6}
.ot-list li{padding:8px 0;border-bottom:1px solid var(--line)}
.ot-q{margin:0 0 22px;color:var(--muted)}
.ot-q a{color:var(--ink)}
/* 2026-10-10 (night) About "Our story": Yumi's 25th-anniversary group photo (11 people, build.page_about) is shown whole at
   its own 3:2 instead of the 4:5 crop (site.css), so nobody at either end is cut off. */
.ab-story-img img[src*="/anniv-25-group.webp"]{aspect-ratio:3/2;object-position:50% 50%}
/* 2026-10-10 (night) viewer caption (B; A keeps site.css). Ruben: "these text previews look good". Before: caption and
   counter on one line (the "1 / 12" split across two), the page readable through the 92% backdrop under the white caption,
   the caption over the photo and close to the arrows. Now: a solid dark backdrop (nothing behind shows); photo, then the caption one
   item per line (name, "Results may vary." smaller and muted, the treatment link, the counter on its own line that never
   splits), then on phones the arrows in a row under it. site.js fit() gives the photo the height that is left. */
body.theme-l .lb{background:#0a0d0d;flex-direction:column;gap:16px;padding:60px 88px 28px}
body.theme-l .lb[hidden],body.theme-l .lb button[hidden]{display:none}
body.theme-l .lb img{flex:0 0 auto;max-width:100%;max-height:calc(100vh - 220px);max-height:calc(100dvh - 220px)}
body.theme-l .lb button{background:rgba(255,255,255,.1)}
body.theme-l .lb .lb-cap{position:static;flex:0 0 auto;display:flex;flex-direction:column;align-items:center;gap:3px;max-width:34em;margin:0;padding:0;
  text-align:center;color:#fff;font:400 16px/1.35 var(--sans);letter-spacing:0}
body.theme-l .lb .lb-cap span,body.theme-l .lb .lb-cap a{margin:0;opacity:1}
body.theme-l .lb .lb-cap .lb-rmv{font-size:13px;line-height:1.4;color:rgba(255,255,255,.6)}
body.theme-l .lb .lb-cap .lb-go{margin-top:7px;color:#6ADAD8;font-weight:400;font-size:14.5px;text-decoration:none}
body.theme-l .lb .lb-cap .lb-ct{margin-top:8px;font-size:12.5px;line-height:1.2;color:rgba(255,255,255,.5);white-space:nowrap;letter-spacing:.06em;font-variant-numeric:tabular-nums}
@media (max-width:760px){
  body.theme-l .lb{display:grid;grid-template-columns:1fr 1fr;align-content:center;justify-items:center;row-gap:16px;column-gap:18px;
    padding:64px 16px calc(16px + env(safe-area-inset-bottom))}
  body.theme-l .lb img{grid-column:1/-1;grid-row:1;max-height:calc(100vh - 300px);max-height:calc(100dvh - 300px)}
  body.theme-l .lb .lb-cap{grid-column:1/-1;grid-row:2;max-width:100%;font-size:15.5px}
  body.theme-l .lb .lb-p,body.theme-l .lb .lb-n{position:static;grid-row:3;top:auto;bottom:auto;transform:none}
  body.theme-l .lb .lb-p{grid-column:1;justify-self:end}
  body.theme-l .lb .lb-n{grid-column:2;justify-self:start}
}
/* ---------- 2026-10-10 (night, later): three small fixes (B only; A has none of these classes) ---------- */
/* "Your first visit" cards: Ruben, "These images dont have to be tappable" (site.js skips .l-first in the photo viewer) */
.l-first .ls img{cursor:default}
/* The Google reviews pill: Ruben, "can you give the star a very subtle movement". A slow, quiet twinkle every ~5 s: a
   small lift in size with a slight tilt and a soft glow of her teal, then still again. Quieter than the Claim star (1.8 s,
   scale .62 + 40deg). Transform and glow only, so "4.6 from 100 Google reviews" beside it never moves. Still for
   reduced motion. */
/* 2026-10-11 (hero helper, job 37): the pill is gone; the same twinkle now lives on the hero's rating line (.lh-rate). */
.lh-rate .hp-star{display:inline-block;transform-origin:50% 55%}
@media (prefers-reduced-motion:no-preference){
  .lh-rate .hp-star{animation:la-star 5s 1.2s ease-in-out infinite}
  @keyframes la-star{0%,64%,100%{transform:none;text-shadow:none}
    76%{transform:scale(1.16) rotate(-10deg);text-shadow:0 0 7px rgba(106,218,216,.7)}
    88%{transform:scale(.97) rotate(3deg);text-shadow:0 0 2px rgba(106,218,216,.25)}}
}
/* Offers panel (the bell): Ruben's phone screenshot, the "Stock photo" tag sat at the bottom-left of the whole Neck TOX
   card, on top of "Smoother neck & jawline · Price confirmed at your visit.", and the Claim button's glow crowded that
   line. The photo now has its own box (.ld-ph, theme_l.deals_panel), so motion-l.js puts the tag on the photo's corner as
   everywhere else; the fine print sits 20px under the button (was 12px). */
.ld-ph{display:block;position:relative}
.ld-fine{margin-top:20px}
/* Offer cards, Masseter TOX: Yumi, "这个价格改成$499，原价$599 50unit". What the price buys sits beside it ("· 50 units"),
   quieter than the price, in the same deep teal (theme_l.l_units, copy_l.UNITS); never uppercase in the panel. */
.lo-u{font-size:15px;font-weight:400;color:#1f6f6b;margin-left:2px;white-space:nowrap}
.ld-sub .lo-u{font-size:14px;text-transform:none;letter-spacing:0}
/* ---------- 2026-10-10 (night, later): Treatments page top + Chinese names kept whole (B only; A has no .theme-l) ----------
   Handoff item 9 (Ruben): the line under "Treatments and prices" on ONE line from 360 px phones up ("What each one does,
   and what it costs." / 每个项目的作用和价格。, build.page_treatments), and "trim spacing a little so the grid starts
   higher": less space above the title, under the line and above the first group. .p-hero is only on treatments.html. */
.theme-l .p-hero{padding:44px 0 16px}
.theme-l .p-hero h1{margin-bottom:.32em}
.theme-l .p-hero .lead{margin:0;max-width:none}
.theme-l .p-hero .filters{margin-top:22px}
.theme-l #tgroups>.tgroup:first-child{padding-top:28px}
@media (max-width:760px){
  .theme-l .p-hero{padding:24px 0 4px}
  .theme-l .p-hero .filters{margin-top:14px}
  .theme-l #tgroups>.tgroup:first-child{padding-top:24px}
}
/* ---------- 2026-10-10 (night, later), job 23: treatment page headers name first (B only; A has no .theme-l) ----------
   Ruben (phone screenshot of the Meiyan Nose header): "make sure that it is treatment name first". The h1 is the name, its
   small teal line the other names (build.l_title / l_alt_names), then the hero sentence. Sculptra and B12 & NAD+ keep their
   payoff as a short plain line under the names (build.L_KEEP_PAY), quieter than the title, then the hero sentence close under it. */
.theme-l .t-hero .t-pay{margin:20px 0 0;font-size:20px;line-height:1.4;color:var(--ink)}
.theme-l .t-hero .t-pay+.lead{margin-top:8px}
@media (max-width:760px){.theme-l .t-hero .t-pay{margin-top:14px;font-size:18px}.theme-l .t-hero .t-pay+.lead{margin-top:6px}}
/* ---------- 2026-10-10 (night, later), job 11: B's phone menu (☰). B only: A's menu is site.css + site.js's plain toggle. ----------
   Ruben (phone screenshot of the open menu): "make sure this menu fits our theme/aesthetic". Before: links in a heavy 500
   weight (site.css nav.main a{font:500 24px}), the current page in dark green, grey hairlines, the phone number as a big
   link, half the screen empty white under the Book pill, and a ☰ button with a black border beside the teal 中文 / bell
   boxes. Now: the ☰ is the bell's box (her blue 1.5px hairline, 12px corners) and turns into an X while open; the menu
   fills the screen under the header on her soft wash, light links (Outfit 300; Chinese 400) on blue hairlines, a tiny
   ✦ beside the page you are on, Book (the one Pearl pill) and Call as B's pills, then a quiet foot: the small butterfly,
   today's hours and the address (theme_l.menu_parts). Fades in (none for reduced motion); the page behind is locked;
   a link tap, Escape, the bell or a wider screen closes it (site.js). Computers: the header nav is unchanged. */
.theme-l .menu-btn{box-sizing:border-box;padding:0;border:1.5px solid var(--blue);border-radius:12px;background:#fff;color:var(--on-blue);cursor:pointer}
.theme-l .menu-btn:hover,.theme-l .menu-btn[aria-expanded=true]{background:#effbfb}
.theme-l .menu-btn svg{width:22px;height:22px;overflow:visible}
.theme-l .menu-btn .mb-1{transform-origin:12px 9px}
.theme-l .menu-btn .mb-2{transform-origin:12px 15px}
.theme-l .menu-btn[aria-expanded=true] .mb-1{transform:translateY(3px) rotate(45deg)}
.theme-l .menu-btn[aria-expanded=true] .mb-2{transform:translateY(-3px) rotate(-45deg)}
.theme-l .nav-foot,.theme-l .nav-call{display:none}
@media (prefers-reduced-motion:no-preference){
  .theme-l .menu-btn{transition:scale .45s var(--mo-press),background-color .2s}
  .theme-l .menu-btn:active{scale:.96;transition:scale .1s ease-out,background-color .2s}
  .theme-l .menu-btn svg path{transition:transform .32s cubic-bezier(.22,1,.36,1)}
}
@media (max-width:860px){
  .theme-l nav.main{display:flex;flex-direction:column;align-items:stretch;gap:0;
    inset:100% 0 auto 0;height:calc(100vh - var(--mt,117px));height:calc(100dvh - var(--mt,117px));
    padding:4px 24px calc(20px + env(safe-area-inset-bottom,0px));overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
    border:0;border-top:1px solid rgba(106,218,216,.28);
    background:radial-gradient(120% 50% at 100% 100%,rgba(106,218,216,.16) 0,rgba(106,218,216,0) 70%),radial-gradient(90% 40% at 0% 0%,#eef9f8 0,rgba(238,249,248,0) 75%),#fff;
    visibility:hidden;opacity:0;transform:translateY(-8px);pointer-events:none;
    transition:opacity .2s ease,transform .2s ease,visibility 0s linear .2s}
  .theme-l nav.main.open{visibility:visible;opacity:1;transform:none;pointer-events:auto;
    transition:opacity .32s cubic-bezier(.22,1,.36,1),transform .32s cubic-bezier(.22,1,.36,1),visibility 0s}
  .theme-l nav.main>*{flex-shrink:0}  /* a short screen scrolls the menu; nothing in it is squeezed */
  .theme-l nav.main>a:not(.btn):not(.lang):not(.nav-tel){display:flex;align-items:center;gap:12px;padding:14px 2px;border-bottom:1px solid rgba(106,218,216,.3);
    font:300 25px/1.2 var(--head);letter-spacing:-.01em;color:var(--ink)}
  html[lang=zh-CN] .theme-l nav.main>a:not(.btn):not(.lang):not(.nav-tel){font-weight:400;font-size:22px;letter-spacing:.02em}
  /* the page you are on: a tiny outline sparkle in her blue (the home headings' ✦), the words stay ink */
  .theme-l nav.main>a[aria-current]::after{content:"";flex:none;width:15px;height:15px;
    background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1.5c.5 5.6 4.9 10 10.5 10.5-5.6.5-10 4.9-10.5 10.5C11.5 16.9 7.1 12.5 1.5 12 7.1 11.5 11.5 7.1 12 1.5z' fill='none' stroke='%2352cfcc' stroke-width='1.8' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat}
  .theme-l nav.main a.btn{order:2;margin-top:22px;height:52px;padding:0 22px;font-size:16px}
  .theme-l nav.main a.nav-tel{order:3;display:flex;align-items:center;justify-content:center;height:52px;margin-top:10px;padding:0 22px;
    border:1px solid rgba(106,218,216,.75);border-radius:999px;background:rgba(255,255,255,.75);font:400 16px/1 var(--sans);letter-spacing:.005em;color:var(--ink)}
  .theme-l .nav-call{display:inline;white-space:pre}
  .theme-l .nav-foot{order:4;display:flex;flex-direction:column;align-items:center;gap:4px;margin-top:auto;padding-top:18px;text-align:center;font-size:14px;line-height:1.45;color:var(--muted)}
  .theme-l .nav-foot .bfly{width:24px;height:24px;color:#52cfcc;margin-bottom:2px}
  .theme-l .nav-foot .bfly path{stroke-width:1.2}
  .theme-l .nav-foot p{margin:0}
  .theme-l .nav-today{font-size:15px;color:var(--ink)}
  .theme-l .nav-today[hidden]{display:none}
  html.menu-open{overflow:hidden}  /* <html> only, never <body> too: that made <body> the scroll box and the sticky header jumped away */
  html.menu-open .l-fab{opacity:0!important;pointer-events:none!important}
}
/* short phones (iPhone SE and the like): a little tighter, no butterfly, so the whole menu still fits one screen */
@media (max-width:860px) and (max-height:620px){
  .theme-l nav.main>a:not(.btn):not(.lang):not(.nav-tel){padding-top:11px;padding-bottom:11px;font-size:23px}
  html[lang=zh-CN] .theme-l nav.main>a:not(.btn):not(.lang):not(.nav-tel){font-size:21px}
  .theme-l nav.main a.btn{margin-top:16px}
  .theme-l .nav-foot{padding-top:14px}
  .theme-l .nav-foot .bfly{display:none}
}
@media (max-width:860px) and (prefers-reduced-motion:no-preference){
  .theme-l nav.main>a[aria-current]::after{animation:bd-glint 4.2s ease-in-out infinite}
}
@media (max-width:860px) and (prefers-reduced-motion:reduce){
  .theme-l nav.main,.theme-l nav.main.open{transition:none;transform:none}
}

/* ---------- 2026-10-10 (night, later), job 24: the treatment page template reads as B (B only; A has no .theme-l). ----------
   Ruben (phone screenshot of a treatment page): "can we make sure this page/template for the treatments aligns with our
   theme". What still came from A and looked like another site, and what it is now:
   - a flat mint band behind the crumbs + header  -> white with B's soft teal wash (as the home page's own washes)
   - the names under the title in letter-spaced teal SERIF -> B's sans, normal spacing (the cards dropped serif tonight)
   - the facts as white mini boxes on mint (phone) and 500-weight values -> one hairline list (phone) / a quiet row of
     four (computer), values in 400
   - small 22px section headings in a document layout -> B's heading scale, light, and the home headings' lowkey ✦ on
     "What it is" and "Questions" only (build.page_treatment .t-spk)
   - black bullet lists, numbered steps with bold lead-ins -> hairline-divided lists; each step's name on its own line
   - results as bare photos with bold captions -> B's rounded hairline result cards (as the home "Real results")
   - review stars in gold -> her blue (as the home review cards); B's card radius
   - the price as bare rows -> B's soft price panel (the home "All treatments" pane)
   - before / after care as two bare lists -> two B hairline cards
   - questions in 500 weight -> B's FAQ (the home Questions block)
   - "Related" as a row of teal payoff links -> B's treatment cards (home "Most booked": name first)
   - the closing Book card ran edge to edge on phones and past the content column on computers -> aligned (all B pages)
   - section hairlines between every block -> space, as on the home page (the lists carry the hairlines now) */
.theme-l .crumbs-band{position:relative;background:transparent}
.theme-l .crumbs-band::before{content:"";position:absolute;left:0;right:0;top:0;height:min(1000px,150vh);z-index:-1;pointer-events:none;
  background:radial-gradient(55% 50% at 100% 0%,rgba(106,218,216,.16) 0,rgba(106,218,216,0) 72%),radial-gradient(60% 55% at 0% 8%,#eef9f8 0,rgba(238,249,248,0) 72%)}
.theme-l .t-hero{background:transparent}
.theme-l .t-hero h1 small{font:400 19px/1.4 var(--sans);letter-spacing:0;color:#1f6f6b}
.theme-l .t-photo:not(.t-photo-ba),.theme-l .t-photo-ba{border-radius:var(--R)}
.theme-l .t-hero .facts{border-top:1px solid var(--line)}
.theme-l .t-hero .facts small{color:var(--muted)}
.theme-l .t-hero .facts b{font-weight:400;font-size:18px}
/* sections */
.theme-l .t-sec{padding:44px 0}
.theme-l .t-sec+.t-sec{border-top:0}
.theme-l .t-sec.split>h2{font-size:clamp(26px,2.3vw,32px);font-weight:400;letter-spacing:-.015em;line-height:1.15}
html[lang=zh-CN] .theme-l .t-sec.split>h2{letter-spacing:.01em}
.theme-l .t-sec h2.t-spk::after{content:"";display:inline-block;width:18px;height:18px;margin-left:6px;vertical-align:.45em;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1.5c.5 5.6 4.9 10 10.5 10.5-5.6.5-10 4.9-10.5 10.5C11.5 16.9 7.1 12.5 1.5 12 7.1 11.5 11.5 7.1 12 1.5z' fill='none' stroke='%2352cfcc' stroke-width='1.8' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat}
@media (prefers-reduced-motion:no-preference){.theme-l .t-sec h2.t-spk::after{animation:bd-glint 4.2s ease-in-out infinite}}
.theme-l .t-sec p.body{font-size:17.5px;line-height:1.65;max-width:36em}
/* lists: hairline rows, no bullets */
.theme-l .t-sec .plain{list-style:none;margin:0;padding:0}
.theme-l .t-sec .plain li{margin:0;padding:13px 2px;border-top:1px solid var(--line);font-size:16.5px;line-height:1.5}
.theme-l .t-sec .plain li:last-child{border-bottom:1px solid var(--line)}
.theme-l .t-steps li{display:flex;flex-direction:column;gap:3px;padding:16px 2px}
.theme-l .t-steps b{font-weight:400;font-size:18px;line-height:1.35;color:var(--ink)}
.theme-l .t-steps span{color:var(--muted);font-size:16px;line-height:1.55}
/* results: B's result cards */
.theme-l .t-sec .results{gap:16px}
.theme-l .t-sec .res.ba{border:1px solid var(--line);border-radius:var(--R);overflow:hidden;background:#fff}
.theme-l .t-sec .res.ba img{border-radius:0;background:#f4f7f7}
.theme-l .t-sec .res.ba .ba-cap{margin:0;padding:14px 20px 18px}
.theme-l .t-sec .res.ba .ba-cap b{font-weight:400;font-size:16px}
/* reviews */
.theme-l .t-sec .rv{border-radius:var(--R);padding:26px 28px 24px}
.theme-l .t-sec .rv-stars{color:var(--blue-2)}
.theme-l .t-sec .rv blockquote{font-size:17px}
/* price: the home price pane */
.theme-l .t-sec .price{background:var(--soft);border-radius:var(--r);padding:4px 24px}
.theme-l .t-sec .price .row{padding:16px 0;border-bottom:1px solid #dfeceb;font-size:16.5px}
.theme-l .t-sec .price .row:first-child{border-top:0}
.theme-l .t-sec .price .row:last-child{border-bottom:0}
.theme-l .t-sec .price .row b{font-weight:400;font-size:17.5px;white-space:nowrap}
.theme-l .t-sec .price .row s{white-space:nowrap}
/* before / after care: two hairline cards */
.theme-l .t-sec .care{gap:16px}
.theme-l .t-sec .care>div{border:1px solid var(--line);border-radius:var(--r);padding:24px 26px 14px;background:#fff}
.theme-l .t-sec .care h3{font-size:19px;font-weight:400;margin:0 0 6px}
.theme-l .t-sec .care .plain li:first-child{border-top:0}
.theme-l .t-sec .care .plain li:last-child{border-bottom:0}
/* questions: the home Questions block */
.theme-l .t-sec .faq details:first-child{border-top:1px solid var(--line)}
.theme-l .t-sec .faq summary{font-weight:400;font-size:18px;padding:20px 0}
.theme-l .t-sec .faq summary:after{color:var(--ink)}
.theme-l .t-sec .faq details p{font-size:16.5px;line-height:1.6}
/* related: B's treatment cards (home "Most booked") */
.theme-l .t-rels{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}
.theme-l .t-rels a.lc{display:flex;margin:0;padding:30px 18px 26px}  /* site.css .related a{display:inline-block} */
.theme-l .t-rels .lc-ph{display:block;flex:none}
.theme-l .t-rels .lc-t{display:flex;flex-direction:column;align-items:center;gap:6px}
.theme-l .t-rels .lc-ph{width:88px;height:88px;margin-bottom:14px}
.theme-l .t-rels .lc b{font-size:19px}
/* the closing Book card lines up with the page's content column (was 68px wider on computers, edge to edge on phones) */
.theme-l .cta-strip .wrap{box-sizing:border-box;width:calc(100% - 68px);max-width:calc(var(--wrap) - 68px)}
@media (max-width:860px){.theme-l .cta-strip .wrap{width:calc(100% - 40px);margin-left:20px;margin-right:20px}}
@media (max-width:1240px){.theme-l .t-rels{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:760px){
  .theme-l .t-photo:not(.t-photo-ba){margin:0;border-radius:28px}
  .theme-l .t-photo.t-photo-ba{border-radius:28px}
  .theme-l .t-hero h1 small{font-size:17.5px}
  /* the facts as one hairline list: label left, value right (as the booking thank-you's rows) */
  .theme-l .t-hero .facts{display:block;margin-top:30px;padding-top:0;border-top:1px solid var(--line)}
  .theme-l .t-hero .facts div{display:flex;justify-content:space-between;align-items:baseline;gap:16px;padding:13px 2px;background:none;border-radius:0;border-bottom:1px solid var(--line)}
  .theme-l .t-hero .facts small{margin:0;font-size:14.5px;flex:none}
  .theme-l .t-hero .facts b{font-size:16.5px;text-align:right;white-space:normal}
  .theme-l .t-sec{padding:30px 0}
  .theme-l .t-sec.split{gap:14px}
  .theme-l .t-sec.split>h2{font-size:26px}
  .theme-l .t-sec .results{gap:10px}
  .theme-l .t-sec .res.ba{border-radius:20px}
  .theme-l .t-sec .res.ba .ba-cap{padding:10px 12px 12px}
  .theme-l .t-sec .res.ba .ba-cap b{font-size:14.5px}
  .theme-l .t-sec .rv{border-radius:28px;padding:22px 22px 20px}
  .theme-l .t-sec .price{padding:2px 18px}
  .theme-l .t-sec .care>div{border-radius:20px;padding:20px 20px 10px}
  .theme-l .t-sec .faq summary{font-size:17px;padding:18px 0}
  /* related on a phone: compact rows (round photo left, words right), so two or three fit one screen */
  .theme-l .t-rels{grid-template-columns:1fr;gap:10px}
  .theme-l .t-rels a.lc{flex-direction:row;align-items:center;text-align:left;gap:16px;padding:14px 18px 14px 14px;border-radius:24px}
  .theme-l .t-rels .lc-t{align-items:flex-start;gap:2px}
  .theme-l .t-rels .lc-ph{width:64px;height:64px;margin:0 0 0 4px;flex:none}
  .theme-l .t-rels .lc-ph::after{inset:-5px}
  .theme-l .t-rels .lc b{font-size:17px}
  .theme-l .t-rels .lc small{font-size:14px}
  .theme-l .t-rels .lc em{font-size:14px;margin-top:4px}
}

/* ---------- 2026-10-10 (night, later), job 25: home "This month's offers" cards behave like the treatment tiles. ----------
   Ruben: "this should behave like the treatment cards where you click on the image and it takes you to the learn more,
   but book this offer goes straight to frame". The photo and the name open the treatment's page (the name's link covers
   the card, as .tc-grid's does); "Book this offer" sits above that link and opens booking with the treatment ticked.
   Hover: the hairline turns her blue (as the tiles); keyboard focus rings the whole card. The bell panel's offer cards
   work the same way (theme_l.deals_panel .ld-t). */
.lo,.ld-t{position:relative;transition:border-color .2s}
.lo h3 a,.ld-t h3 a{color:inherit;text-decoration:none}
.lo h3 a::after,.ld-t h3 a::after{content:"";position:absolute;inset:0;z-index:1;border-radius:inherit}
.lo .btn,.ld-t .btn{position:relative;z-index:2}
.lo:hover,.ld-t:hover{border-color:rgba(106,218,216,.7)}
.lo h3 a:focus-visible,.ld-t h3 a:focus-visible{outline:none}
.lo h3 a:focus-visible::after,.ld-t h3 a:focus-visible::after{box-shadow:inset 0 0 0 2px var(--blue-2)}
.lo-ph{position:relative}

/* ---------- 2026-10-10 (night, later), job 30: the offer strip is pinned WITH the header (B only; A has no .l-pin). ----------
   Ruben (desktop screenshot of the strip "New here? $50 off your first Botox · Claim it" above the header): "I want the
   offer to stay, dont want it to move when we scroll the way it does rn". Before: only header.site was sticky, so the
   strip scrolled away and the header slid up into its place. Now build.layout wraps strip + header in ONE sticky block
   (.l-pin): nothing moves, at the top or scrolled. Its height is fixed per screen (--pin) so anchors, the treatments page
   chips and the phone menu all know where it ends.
   iPhone Safari 26 colours the strip behind the clock from a full-width pinned box at the middle of the top edge (WebKit
   fixedContainerEdges, memory ios26-safari-web-limits): the walk up from the strip meets a real background-color first
   (#eefbfb, the strip's own pale teal, so the clock strip and the offer strip are one colour) and no backdrop-filter on the
   way (the header's blur is gone: it sits on the pin's own solid background, there is nothing behind it to blur). The
   strip is one solid colour now (was a #eefbfb -> #e4f6f8 sideways gradient), so its whole top edge matches the clock
   strip with no seam. Phones: a slim one-line strip (32px, was 44.8px) and a 64px header (was 72px): pinned block 96px. */
:root{--tb:38px;--hh:84px;--pin:122px}
@media (max-width:860px){:root{--tb:32px;--hh:64px;--pin:96px}}
.l-pin{position:-webkit-sticky;position:sticky;top:0;z-index:50;background-color:#eefbfb}
.l-pin header.site{position:relative;top:auto;background:#fff;-webkit-backdrop-filter:none;backdrop-filter:none}
header.site .wrap{height:var(--hh)}            /* .bk-app header.site .wrap (64 / 58px) is more specific and keeps its own */
.topbar{background:#eefbfb}
.topbar .wrap{height:var(--tb);padding-top:0;padding-bottom:0;align-items:stretch;flex-wrap:nowrap}
.topbar .wrap>a{line-height:var(--tb);white-space:nowrap}   /* flex items: the whole strip height is each link's tap area */
.topbar .tb-offer{min-width:0;overflow:hidden;text-overflow:ellipsis}
@media (max-width:860px){.topbar .wrap{padding-top:0;padding-bottom:0}.topbar .tb-offer{font-size:13px}}
@media (max-width:349px){.topbar .tb-offer{font-size:12.5px}.topbar .tb-offer:before{margin-right:6px}}
/* anchors (#prices, the treatments page groups, ...) and a link reached with the keyboard land under the pinned block,
   not behind it. On the targets only, not as html scroll-padding: that made the browser scroll the page whenever
   something INSIDE the pinned block (a header link, the menu button) got focus, since it sits in the padded band. */
body.theme-l:not(.embed):not(.bk-app) main [id],body.theme-l:not(.embed):not(.bk-app) main :focus{scroll-margin-top:calc(var(--pin) + 12px)}
@media (max-width:760px){.theme-l .filters{top:var(--pin)}}
/* the phone menu: the header no longer carries a backdrop-filter, which was the box its fixed menu was placed in (inset
   100% = under the header). It is placed on the screen now, from where the header ends (site.js sets --mt at open). */
@media (max-width:860px){
  .theme-l nav.main{inset:var(--mt,var(--pin)) 0 auto 0;height:calc(100vh - var(--mt,var(--pin)));height:calc(100dvh - var(--mt,var(--pin)))}
}
/* the booking page (book.html, a one-screen app) hides the strip and keeps its own header, as before */
.bk-app .l-pin{display:contents}
/* the offer pop-up and the bell panel lock the page with overflow on <html> AND <body> (site.css). Two hidden overflows
   make <body> its own scroll box, and a pinned block inside it jumps to the top of the page (off screen on a scrolled
   page; it showed behind the bell panel's dimmed backdrop). B keeps the lock on <html> only, as the phone menu does. */
html.pop-open body{overflow:visible}

/* ---------- 2026-10-10 (night, later): the logo on small phones (B only). ----------
   Found by the menu helper: at 360px the logo wrapped ("美 / 妍" stacked, "DUKE MEDICAL / CLINIC" on two lines; at 375px
   too) and at 320px the 中文 box sat on top of 美妍. Below 384px the logo steps down a little (smaller letters, a touch less
   letter-spacing, smaller gaps), and below 350px once more (the 中文/EN box 46px wide). It never wraps (nowrap), from
   320px up, EN + ZH, menu open or closed. 384px and up: unchanged. */
.brand .bt b,.brand .bt small,.brand .bt em{white-space:nowrap}
@media (max-width:383px){
  header.site .wrap{gap:12px}
  .brand{gap:8px}
  .brand img{height:27px}
  .brand b{font-size:14px;letter-spacing:.18em}
  .brand small{font-size:12px}
  .brand .bt>span{gap:6px}
  .brand em{font-size:8px;letter-spacing:.17em}
  .head-right{gap:6px}
}
@media (max-width:349px){
  .brand{gap:7px}
  .brand img{height:25px}
  .brand b{font-size:13px;letter-spacing:.15em}
  .brand small{font-size:11.5px}
  .brand .bt>span{gap:5px}
  .brand em{font-size:7.2px;letter-spacing:.13em}
  .theme-l .lang{width:46px}
}

/* ---------- 2026-10-10 (night, later), job 27: a smaller Google reviews pill (B home, under the hero). ----------
   Ruben (phone screenshot): "can you make the rating a lil smaller takes too much space". Phones: two tight lines (was
   76px tall: 14px/18px padding, 16px + 14px type) -> less padding and a little smaller type. Computers: one line, a bit
   slimmer too. The star's slow twinkle is unchanged. */
/* 2026-10-11 (hero helper, job 37): Ruben, "there should be a way of displaying the rating without an ugly bar like we have
   now that takes up that whole bar's space". The pill's rules are gone with it; see the "hero helper" block at the end. */

/* ======================================================================================================================
   2026-10-11, theme helper B2a (handoff rows 35, 26; row 28 lives in site.js only). B only (A never loads this file).
   ====================================================================================================================== */

/* ---------- job 35: on phones the strip + header block slides away on the way down and back on the way up. ----------
   Ruben (2026-10-10, ~11 PM): "can you make the header move as you scroll, including the offer banner, on mobile", then
   "make sure slide-back version". Phones only (860px and under); computers keep job 30's pinned block exactly. The block
   (.l-pin: still one sticky box with its solid #eefbfb for Safari, no backdrop-filter) moves by transform only, so nothing
   on the page moves or reflows. site.js adds html.pin-up after 10px of scrolling down and removes it after 6px back up;
   always shown at the top and while the menu, bell panel, pop-up or photo viewer is open (html.pin-snap = at once, no
   slide). No transform at all while shown: the phone menu (position:fixed, inside the header) must be placed on the
   screen, and a transform would make the block its containing box. Reduced motion: no slide, it just shows or hides.
   The treatments page's sticky category chips (phones under 761px) sit under the block and follow it (top 96px -> 0);
   a sticky box's top never moves anything else on the page. Anchors keep job 30's scroll-margin (block + 12px). */
@media (max-width:860px){
  body.theme-l:not(.bk-app):not(.embed) .l-pin{transition:transform .24s cubic-bezier(.22,.61,.36,1)}
  html.pin-up body.theme-l:not(.bk-app):not(.embed) .l-pin{transform:translate3d(0,-100%,0)}
  html.pin-snap body.theme-l:not(.bk-app):not(.embed) .l-pin{transition:none}   /* as specific as the line above it, + html */
}
@media (max-width:760px){
  body.theme-l .filters{transition:top .24s cubic-bezier(.22,.61,.36,1)}
  html.pin-up body.theme-l .filters{top:0}
  html.pin-snap body.theme-l .filters{transition:none}
}
@media (prefers-reduced-motion:reduce){body.theme-l .l-pin,body.theme-l .filters{transition:none!important}}

/* ---------- job 26: no scroll bar on the home quiz card when everything fits (computers). ----------
   Ruben (desktop screenshot of the card, step 1 of 6, a thin scroll bar at the right): "i dont think we need to scroll
   this quiz on desktop ... everything fits there". Cause, measured (Chromium with real scroll bars + WebKit, 1280x720,
   1366x768, 1440x900, 1920x1080): the card is a fixed 620px (713 with the 1.15 wide-screen zoom) and on English pages its
   six goal tiles ran 3-6px past their box (the two-line names "Face shape, lips & nose" / "Spots & uneven tone" make a
   row ~189px tall), so the browser drew a scroll bar for a few pixels; with the wide-screen zoom, WebKit's rounding put
   steps 2-3 (and ZH step 1) 1px over; and the thank-you inside the card's frame ran 29px (EN) / 16px (ZH) over. Now: the
   tiles are 2px tighter top and bottom and between photo and words (12px of room per card, both rows); a box that is over
   by no more than its own padding (the rounding) shows no scroll bar (.lp-fit, set by the card's fade() and book.js
   more()); the thank-you's "Prefer to pick a time yourself?" sits beside its button inside the card on computers (the
   frame is ~560px wide there; phones' frame is under 480px and keep the stacked box). A step that really is taller than
   the card (the calendar's times, a narrow window, phones) still scrolls inside it, with its fade, as before. */
.lp-step.lp-fit,body.embed main.lp-fit{overflow-y:hidden}
@media (min-width:861px){.lp-goals .lp-opt{gap:10px;padding:14px 16px 16px}}
@media (min-width:480px){
  body.embed .ty-pick:not([hidden]){display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 12px 12px 20px;text-align:left}
  body.embed .ty-pick p{margin:0}
  body.embed .ty-pick .btn{min-width:0;flex:none}
}

/* ======================================================================================================================
   2026-10-11, theme helper B2b: job 29 (the booking page at the site's own scale on computers), footer headings and the
   desktop offer strip in normal case (those two are edited in place above, at the strip and footer rules). B only.
   ====================================================================================================================== */

/* ---------- job 29: book.html (body.bk-app) at the site's own scale on computers (861px and wider). ----------
   Ruben (desktop screenshot of book.html, Masseter picked): "on desktop, the booking pages look smaller than the rest of
   the site". Measured before (WebKit + Chromium, 1280x720 to 1920x1080): every other B page grows with the screen from
   1600px (the wide-screen zoom above, 1.05-1.5), but the booking app was held at zoom 1 (10-09, so its one-screen layout
   would not run past the window), so at 1920x1080 the rest of the site was 15% bigger: logo 34.5px vs 30px, a 1472px
   column vs 1280px. At every size its own type was also a step under the site's: step line 13px, question 32px, line
   under it 15.5px, category pills 40px tall (the treatments page's are 46px), names 17.5px (treatment tiles 19px),
   summary rows 15px and total 20px, a 64px header (84px on every other page).
   Now: (1) from 1600px the booking app takes the same zoom steps as every other B page and divides its own height by that
   zoom (--bkz), so it is still exactly one window tall: the page never scrolls, only the list does, and Continue/Back
   stay on screen. (2) On every computer: the 84px header of the other pages where the screen is 800px+ tall (the logo is
   the same 30px mark either way), 15px step line, 40px question, 17px line under it, 46px pills, 20px names with 88px
   photos, 16px lines under them, a summary card with 16.5px rows and a 26px total, wider one-question slides and
   thank-you, bigger calendar days. The list column keeps the site's own width (the 1280px wrap of every page, less the
   summary), and grows with the zoom from 1600px (824px -> 948px at 1920x1080). Buttons were already the site's (52px, 15.5px). Phones (860px and under) unchanged. */
@media (min-width:1600px){body.theme-l.bk-app{zoom:1.05;--bkz:1.05}}
@media (min-width:1760px){body.theme-l.bk-app{zoom:1.1;--bkz:1.1}}
@media (min-width:1900px){body.theme-l.bk-app{zoom:1.15;--bkz:1.15}}
@media (min-width:2100px){body.theme-l.bk-app{zoom:1.25;--bkz:1.25}}
@media (min-width:2400px){body.theme-l.bk-app{zoom:1.35;--bkz:1.35}}
@media (min-width:2700px){body.theme-l.bk-app{zoom:1.5;--bkz:1.5}}
@media (min-width:1600px) and (max-height:1000px){body.theme-l.bk-app{zoom:1.05;--bkz:1.05}}
@media (min-width:2100px) and (max-height:1250px){body.theme-l.bk-app{zoom:1.2;--bkz:1.2}}
@media (min-width:861px){
  body.theme-l.bk-app{height:calc(100vh / var(--bkz,1));height:calc(100dvh / var(--bkz,1))}
  .bk-app .bk-head{margin:6px 0 20px;column-gap:16px}
  .bk-app .bk-head .prefill{font-size:15.5px;margin-bottom:14px}
  .bk-app .bk-head .step-count{font-size:15px}
  .bk-app .bk-head .progress .bk-track{height:5px}
  .bk-app .step h2{font-size:40px;line-height:1.15;margin-bottom:10px}
  .bk-app .step .hint{font-size:17px;margin-bottom:18px}
  .bk-app .bk-cats{gap:10px;margin:22px 0 16px}
  .bk-app .bk-cat{height:46px;padding:0 20px;font-size:15.5px}
  .bk-app .bk-n{min-width:22px;height:22px;font-size:12.5px}
  .bk-app #catList .pick,.bk-app .pick{margin-bottom:12px}
  .bk-app .pick{min-height:80px;padding:16px 20px;border-radius:18px}
  .bk-app .pick.has-th{grid-template-columns:88px minmax(0,1fr) 30px;column-gap:18px;padding:12px 20px 12px 12px}
  .bk-app .pick .th{width:88px;height:88px;border-radius:14px}
  .bk-app .pick b,.bk-app .pick.has-th b,html[lang=zh-CN] .bk-app .pick b{font-size:20px}
  .bk-app .pick small,.bk-app .pick.has-th small{font-size:16px}
  .bk-app .pick em,.bk-app .pick.has-th em{font-size:16px}
  .bk-app .pick i{width:30px;height:30px}
  .bk-app .opt{padding:20px 22px;border-radius:18px}
  .bk-app .opt b{font-size:20px}
  .bk-app .opt small{font-size:16px}
  .bk-app .consult-card{padding:20px 22px;border-radius:18px}
  .bk-app .consult-card b,html[lang=zh-CN] .bk-app .consult-card b{font-size:20px}
  .bk-app .consult-card small{font-size:16px}
  .bk-app .or{font-size:15.5px}
  .bk-app .summary .panel{padding:28px 28px 26px;border-radius:28px}
  .bk-app .summary h3{font-size:22px;margin-bottom:12px}
  .bk-app #sumList li{font-size:16.5px;padding:11px 0}
  .bk-app .sum-meta{font-size:15.5px}
  .bk-app .sum-total span{font-size:17px}
  .bk-app #sumTotal{font-size:26px}
  .bk-app .reassure{font-size:14.5px}
  .bk-app .bk-one,.bk-app .step[data-step="10"] .bk-one{max-width:640px}
  .bk-app .bk-one .field label{font-size:15.5px}
  .bk-app .bk-one .field input{height:60px;font-size:19px}
  .bk-app .bk-fine{font-size:13.5px;max-width:640px}
  .bk-app .q>.ql{font-size:16.5px}
  .bk-app .cal-head b{font-size:18px}
  .bk-app .cal-head button{width:40px;height:40px}
  .bk-app .cal .dow{font-size:13.5px}
  .bk-app .cal button,.bk-app .slots button{height:46px;font-size:16px}
  /* thank-you: wider (600px, the lead line and the address fit in fewer lines), and "Prefer to pick a time yourself?"
     beside its button, as in the home card's frame (job 26), so it is shorter and fits the window */
  .bk-app .step[data-step="6"].on{padding-bottom:8px}
  .bk-app .ty{max-width:600px;padding:clamp(8px,2vh,24px) 0 8px}
  .bk-app .ty-mark{width:88px;height:88px;margin-bottom:16px}
  .bk-app .ty-mark img{width:42px}
  .bk-app .ty .ty-lead{font-size:18px;max-width:520px;margin-bottom:24px}
  .bk-app .ty-rows div{font-size:16px;padding:11px 2px}
  .bk-app .ty .ty-q{font-size:16px}
  .bk-app .ty-pick:not([hidden]){display:flex;align-items:center;justify-content:space-between;gap:16px;padding:14px 14px 14px 24px;text-align:left}
  .bk-app .ty-pick p{margin:0;font-size:16px}
  .bk-app .ty-pick .btn{min-width:0;flex:none}
}
@media (min-width:861px) and (min-height:800px){
  .bk-app header.site .wrap{height:var(--hh)}  /* 84px, as on every other page */
}
/* shorter computer screens (under 800px tall, e.g. 1280x720, 1366x768): the same type, a little less air, so the list
   still shows two and a half rows and the thank-you fits */
@media (min-width:861px) and (max-height:799px){
  .bk-app .bk-head{margin:2px 0 14px}
  .bk-app .bk-head .prefill{margin-bottom:10px}
  .bk-app .step h2{font-size:36px;margin-bottom:6px}
  .bk-app .step .hint{margin-bottom:12px}
  .bk-app .bk-cats{margin:14px 0 12px}
  .bk-app .pick.has-th{grid-template-columns:80px minmax(0,1fr) 30px;padding-top:10px;padding-bottom:10px}
  .bk-app .pick .th{width:80px;height:80px}
  .bk-app #catList .pick,.bk-app .pick{margin-bottom:10px}
  .bk-app .nav-row{padding-top:10px;padding-bottom:10px}
  .bk-app .ty{padding-top:2px}
  .bk-app .ty-mark{width:64px;height:64px;margin-bottom:12px}
  .bk-app .ty-mark img{width:32px}
  .bk-app .ty-bf{width:24px;height:24px;right:-18px;top:-8px}
  .bk-app .ty h2{font-size:34px;margin-bottom:6px}
  .bk-app .ty .ty-lead{font-size:17px;line-height:1.5;margin-bottom:14px}
  .bk-app .ty-rows{margin-bottom:10px}
  .bk-app .ty-rows div{padding:7px 2px}
  .bk-app .ty .ty-price{margin:-2px 0 10px}
  .bk-app .ty-pick:not([hidden]){margin-bottom:12px;padding-top:8px;padding-bottom:8px}
  .bk-app .ty .ty-q{margin-bottom:12px}
  .bk-app .ty .note{margin-top:10px}
}
/* job 29, found while testing narrow computer windows (761-960px, e.g. a 900x700 window or a landscape tablet): the
   booking grid drops to one column there, so the summary card sat UNDER the form inside the one-screen app and squeezed
   the step to a sliver (before tonight too: the list showed none of its rows, the question was cut off). As on phones:
   no summary card, and the total ("1 chosen · $499") sits between Back and Continue. */
@media (min-width:761px) and (max-width:960px){
  .bk-app .summary{display:none}
  .bk-app .nav-sum{display:block}
}

/* ======================================================================================================================
   2026-10-11, hero helper (handoff rows 36 + 37). B's home hero only (A never loads this file).
   36. Ruben: "the hero hierarchy of the text, make sure it looks good please, something's off". The name line was 500
       weight at 0.44em (28px at 1440) over a 400 headline and ended in a comma, so the eye went to it first. Now one
       order that only steps down: quiet kicker (deep teal, 400, 15-17px) -> big LIGHT headline (Outfit 300; Chinese
       stays Noto Sans SC 400, B has no lighter Chinese face) -> sub (18px) -> Claim pill (unchanged) -> fine print (13px)
       -> Offer terms (12.5px, where B2a/B2b left it, under the fine print).
   37. Ruben: "there should be a way of displaying the rating without an ugly bar like we have now that takes up that
       whole bar's space". The rating is one small line beside the Claim pill on computers, centred under it on phones:
       her blue star (the same slow twinkle), deep-teal words on a hairline of her blue, opens Google like the bar did.
   ====================================================================================================================== */
.lh-words h1 .lh-name{display:block;font-size:clamp(15px,1.15vw,17px);font-weight:400;line-height:1.45;letter-spacing:.01em;color:#1F6F6B;margin:0 0 18px}
html[lang=zh-CN] .lh-words h1 .lh-name{letter-spacing:.04em;line-height:1.5}
.lh-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
.lh-studio .lh-words h1{font-weight:300;letter-spacing:-.02em}
html[lang=zh-CN] .lh-studio .lh-words h1{font-weight:400;letter-spacing:0}
.lh-studio .lh-words h1 .lh-name{letter-spacing:.01em}
html[lang=zh-CN] .lh-studio .lh-words h1 .lh-name{letter-spacing:.04em}
.lh-rate{display:inline-flex;align-items:center;gap:7px;font-size:14.5px;line-height:1.3;font-weight:400;color:#1F6F6B;text-decoration:none;white-space:nowrap;padding:6px 0}
.lh-rate .hp-star{color:#6ADAD8;font-size:15px;line-height:1}
.lh-rate b{font-weight:500}
/* the dot between the score and the count: Outfit's small dot with even room on both sides (Chinese pages drew a wide
   full-width dot with two wide spaces) */
.lh-dot{font-family:"Outfit",sans-serif;white-space:pre;letter-spacing:.06em}
.lh-rate-t{text-decoration:underline;text-decoration-thickness:1px;text-decoration-color:#6ADAD8;text-underline-offset:5px}
.lh-rate:hover .lh-rate-t,.lh-rate:focus-visible .lh-rate-t{text-decoration-color:#1F6F6B}
.lh-fine{margin-top:16px}
.lh-terms{font-size:12.5px;margin-top:4px}
@media (min-width:861px){
  .lh-words .cta-row{align-items:center;gap:12px 22px}
  .lh-words .lh-sub{font-size:18px;margin-bottom:28px}
  html[lang=zh-CN] .lh-words .lh-sub{font-size:17px}
  .lh-words h1{margin-bottom:18px}
}
@media (max-width:860px){
  .lh-words h1 .lh-name{font-size:14px;margin-bottom:10px;text-wrap:balance}
  html[lang=zh-CN] .lh-words h1 .lh-name{font-size:13.5px;margin-bottom:8px}
  .lh-words .cta-row{gap:10px}
  .lh-words .cta-row .lh-rate{align-self:center;font-size:13.5px;padding:2px 0}
  .lh-rate .hp-star{font-size:14px}
  .lh-fine{margin-top:10px}
}
/* Small phones (350px and under, e.g. 320x568). Found while measuring job 36: here the one-line sub and fine print were
   wider than the card and were cut at both edges (already so before this job), and the two-line kicker would sit on the
   Botox box. Now the two small lines wrap (balanced), the type steps down a little (headline 28px, sub 15px, pill 52px),
   and the card is a bit taller (2.04 x its width) so the words sit under the box. The Claim pill stays on the first
   screen (bottom ~545 of 568). */
@media (max-width:350px){
  .lh-media{height:calc((100vw - 40px) * 2.04)}
  .lh-words{padding-left:14px;padding-right:14px}
  .lh-sub,.lh-fine{white-space:normal;text-wrap:balance}
  .lh-words h1{font-size:28px}
  .lh-words .lh-sub{font-size:15px;margin-bottom:16px}
  .lh-words .btn{height:52px}
  .lh-fine{font-size:12px;line-height:1.4}
}
/* Narrow computers / landscape tablets (861-1199px): the card is too narrow for the rating beside the pill, so it sits
   under it; the kicker and fine print wrap short (balanced) so neither runs into the butterfly or the Botox box. */
@media (min-width:861px) and (max-width:1199px){
  .lh-words h1 .lh-name{max-width:19em;text-wrap:balance}
  .lh-words .lh-sub{margin-bottom:22px}
  .lh-words .cta-row{gap:8px 22px}
  .lh-fine{max-width:17em;text-wrap:balance;margin-top:12px}
}
/* 2026-10-11 (rating placement). Ruben, circling the rating on the desktop hero: "fix the placement, it doesnt look like it
   fits". Beside the pill it floated off to the right and its end ran into the top of the Botox box. Computers (861px+): the
   rating is its own small line between the sub and the Claim pill, left-aligned with the words (theme_l puts it first in
   the row), so it never reaches the box. The sub's gap shrinks by the same amount, so the card does not grow.
   Phones keep what they had (it sat well there): centred under the pill (order:1). */
@media (min-width:861px){
  .lh-words .cta-row{flex-direction:column;align-items:flex-start;gap:14px}
  .lh-words .cta-row .lh-rate{padding:0}
  .lh-words .lh-sub{margin-bottom:16px}
  html[lang=zh-CN] .lh-words .lh-sub{margin-bottom:16px}
}
@media (max-width:860px){
  .lh-words .cta-row .lh-rate{order:1}
}
/* 2026-10-11 pop-up helper (job 5), from the 10-10 WIP patch. Ruben 2026-10-10: "can we make the pop up show twice?" The
   pop-up's SECOND showing (build.offer_mini; when it shows: site.js "second showing"): a small white card with a hairline
   of her blue #6ADAD8 that slides up at the bottom. Not modal: no dimming, the page still scrolls. Light type, normal case,
   a hairline button with deep-teal words (#1F6F6B, text on white only), one tiny sparkle. No new colours or fonts.
   Phones (860px and under): across the bottom, 89% of the screen wide (5.5vw each side, 16px at least): never 90%+ wide,
   so iPhone Safari 26 never takes it for a pinned bar and never tints its own bottom bar white (WebKit fixedContainerEdges:
   a pinned box 90%+ wide with a background at the middle of the edge, 4px in; the card also stops 14px + the safe area
   above the edge). The strip + header block (job 35) is at the top, so the two never meet. Computers: bottom right, 380px.
   Above the pinned block (50) and the floating Book button (65); under the offers panel (95), the pop-up (100), the
   photo viewer (200) and the warp (2000). While any of those, the phone menu or the home card's booking frame is open,
   or a $50 Claim button is under it, it steps aside (.off, set by site.js; the three rules below the card are the same
   thing without waiting for the script). Reduced motion: no slide, no fade. */
.of-mini{position:fixed;z-index:70;left:calc(max(16px,5.5vw) + env(safe-area-inset-left));right:calc(max(16px,5.5vw) + env(safe-area-inset-right));
  bottom:calc(14px + env(safe-area-inset-bottom));box-sizing:border-box;display:grid;grid-template-columns:minmax(0,1fr) auto;
  grid-template-areas:"t t" "l go";align-items:center;column-gap:12px;row-gap:8px;padding:13px 12px 14px 18px;
  background:#fff;border:1px solid #6ADAD8;border-radius:22px;color:var(--ink);font-family:var(--sans);text-align:left;
  box-shadow:0 18px 40px -24px rgba(31,111,107,.45),0 4px 14px -10px rgba(34,25,22,.16);touch-action:none;
  opacity:0;visibility:hidden;transform:translate3d(0,calc(100% + 24px + env(safe-area-inset-bottom)),0);
  transition:transform .45s cubic-bezier(.2,.8,.2,1),opacity .3s ease,visibility 0s linear .45s}
.of-mini[hidden]{display:none}
.of-mini.in{opacity:1;visibility:visible;transform:none;transition:transform .45s cubic-bezier(.2,.8,.2,1),opacity .3s ease,visibility 0s}
.of-mini.in.off{opacity:0;visibility:hidden;pointer-events:none;transition:opacity .2s ease,visibility 0s linear .2s}
.of-mini-t{grid-area:t;margin:0;padding:1px 34px 0 0;font-size:17px;font-weight:400;line-height:1.25;letter-spacing:0;color:var(--ink);align-self:center;min-width:0}
.of-mini-spk{display:inline-block;width:10px;height:10px;margin:0 0 8px 6px;vertical-align:middle;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1.5c.5 5.6 4.9 10 10.5 10.5-5.6.5-10 4.9-10.5 10.5C11.5 16.9 7.1 12.5 1.5 12 7.1 11.5 11.5 7.1 12 1.5z' fill='%236ADAD8'/%3E%3C/svg%3E") center/contain no-repeat}
.of-mini-l{grid-area:l;margin:0;font-size:13.5px;font-weight:400;line-height:1.4;color:var(--muted);min-width:0;text-wrap:balance}
.theme-l .of-mini-go{grid-area:go;justify-self:end;align-self:end;display:inline-flex;align-items:center;justify-content:center;height:40px;padding:0 18px;
  margin:0;border:1px solid #6ADAD8;border-radius:999px;background:#fff;color:#1F6F6B;font:400 14.5px/1 var(--sans);letter-spacing:.01em;
  text-decoration:none;white-space:nowrap;transition:background-color .15s}
.theme-l .of-mini-go:hover,.theme-l .of-mini-go:focus-visible{background:var(--soft)}
.of-mini-x{position:absolute;top:3px;right:5px;display:flex;align-items:center;justify-content:center;width:40px;height:40px;margin:0;
  padding:0;border:0;border-radius:50%;background:transparent;color:var(--ink);cursor:pointer}
.of-mini-x:hover{background:var(--soft)}
.of-mini-x:focus-visible,.theme-l .of-mini-go:focus-visible{outline:2px solid #1F6F6B;outline-offset:2px}
@media (min-width:861px){.of-mini{left:auto;right:24px;bottom:24px;width:380px}}
@media (max-width:350px){.of-mini{padding-left:14px;column-gap:10px}.of-mini-t{font-size:16px}.of-mini-l{font-size:13px}.theme-l .of-mini-go{padding:0 14px;font-size:14px}}
html.mini-open .l-fab.on{opacity:0;transform:translateY(14px);pointer-events:none;visibility:hidden;transition:opacity .25s ease,transform .25s ease,visibility 0s linear .25s}
html.pop-open .of-mini,html.menu-open .of-mini,body.lb-open .of-mini{visibility:hidden;pointer-events:none}
html:has(#lpick.st3) .of-mini{visibility:hidden;pointer-events:none}  /* own rule: a browser without :has() drops only this one */
@media (prefers-reduced-motion:reduce){.of-mini,.of-mini.in,.of-mini.in.off,html.mini-open .l-fab.on{transition:none}}

/* ---------- 2026-10-11: the phone menu (☰) opens like the bell's offers panel (B only; A has no .theme-l). ----------
   Ruben: "Can the menu open like the notication thing does?" The bell's panel slides in from the right edge over a dimmed
   page (full screen height, min(440px, screen) wide, square corners, a soft shadow on its left edge, .35s), with a head
   row (title, round close cross) and closes on the cross, a tap on the dimmed page or Escape. The menu now does exactly
   that, with the same tokens (--ld-*), the same head (.ld-head / .ld-x) and the same dim (.ld-back): theme_l.menu_shell.
   Before it faded down (.32s, 8px) from under the header and the header stayed visible above it. Kept: everything inside
   (links, Call, Book, 中文/EN, the foot), its wash and hairlines (job 11), html.menu-open (the lock on <html> only, the
   pinned block's snap, the second offer card stepping aside, the home Book pill hiding). Computers: no ☰; unchanged. */
.theme-l .nav-head,.theme-l .nav-back{display:none}
@media (max-width:860px){
  .theme-l .nav-back{display:block;position:fixed;z-index:1;visibility:hidden;transition:opacity var(--ld-fade),visibility 0s linear .35s}
  html.menu-open .theme-l .nav-back{opacity:1;visibility:visible;transition:opacity var(--ld-fade),visibility 0s}
  .theme-l nav.main{inset:0 0 0 auto;width:var(--ld-w);height:auto;z-index:2;padding-top:0;border-top:0;box-shadow:var(--ld-shadow);
    opacity:1;transform:translateX(100%);visibility:hidden;pointer-events:none;
    transition:transform var(--ld-slide),visibility 0s linear .35s}
  .theme-l nav.main.open{opacity:1;transform:none;visibility:visible;pointer-events:auto;transition:transform var(--ld-slide),visibility 0s}
  .theme-l .nav-head{display:flex;margin:0 -24px 4px}   /* the bell panel's head, edge to edge over the menu's 24px sides */
}
@media (max-width:860px) and (prefers-reduced-motion:reduce){   /* as the bell: no slide, no fade */
  .theme-l nav.main,.theme-l nav.main.open,.theme-l .nav-back,html.menu-open .theme-l .nav-back{transition:none}
}

/* 2026-10-13 Laser Hair Removal price table (build.page_treatment, data_l.LHR_TABLE): the same soft .price card and
   hairline rows, two price columns (1 session, package of 6); the new-client price sits under its area in deep teal text. */
.theme-l .t-sec .price .lhr-p{display:flex;gap:12px;flex:none;text-align:right}
.theme-l .t-sec .price .lhr-p>*{width:86px;white-space:nowrap}
.theme-l .t-sec .price .lhr-h{font-size:13px;color:var(--muted);padding:14px 0 10px}
.theme-l .t-sec .price .lhr-h .lhr-p>*{white-space:normal}
.theme-l .t-sec .price .lhr-new{display:block;margin-top:3px;font-size:14px;color:#1F6F6B}
@media (max-width:420px){.theme-l .t-sec .price .lhr-p{gap:8px}.theme-l .t-sec .price .lhr-p>*{width:68px}
  .theme-l .t-sec .price .row:not(.lhr-h){font-size:15.5px}.theme-l .t-sec .price .lhr-p b{font-size:16px}}

/* 2026-10-13, Ruben (iPhone screenshot, "make this thank you screen fit on one page instead of scrolling"): on a phone the
   thank-you is one screen. Smaller mark and heading, tighter lead and rows, "Prefer to pick a time yourself?" beside its
   button (as on a computer), less space between the parts. Sizes shrink with the screen height (vh) so short phones fit too. */
@media (max-width:860px){
  .bk-app .step[data-step="6"].on{padding-bottom:4px}
  .bk-app .ty{padding:clamp(0px,1vh,10px) 0 4px}
  .bk-app .ty-mark{width:clamp(52px,8vh,72px);height:clamp(52px,8vh,72px);margin-bottom:clamp(8px,1.6vh,14px)}
  .bk-app .ty-mark img{width:clamp(26px,4vh,34px)}
  .bk-app .ty-bf{width:22px;height:22px;right:-17px;top:-8px}
  .bk-app .ty-mark i:nth-of-type(1){width:11px;height:11px;left:-14px;top:18px}
  .bk-app .ty h2{font-size:clamp(26px,4vh,32px);margin-bottom:6px}
  .bk-app .ty .ty-lead{font-size:15.5px;line-height:1.5;margin-bottom:clamp(10px,2vh,18px)}
  .bk-app .ty-rows{margin-bottom:8px}
  .bk-app .ty-rows div{padding:clamp(6px,1.1vh,10px) 2px;font-size:14.5px;line-height:1.4}
  .bk-app .ty .ty-price{font-size:12.5px;margin:0 0 clamp(8px,1.6vh,14px)}
  .bk-app .ty-pick:not([hidden]){display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 8px 8px 16px;margin-bottom:clamp(8px,1.6vh,14px);text-align:left;border-radius:16px}
  .bk-app .ty-pick p{margin:0;font-size:14.5px;line-height:1.35}
  .bk-app .ty-pick .btn{min-width:0;flex:none;height:42px;padding:0 18px;font-size:14.5px}
  .bk-app .ty .ty-q{font-size:14px;margin:0 0 clamp(8px,1.6vh,14px)}
  .bk-app .ty .cta-row{margin-top:0}
}
/* very short phones (iPhone SE with Safari's bars, ~570px): the mark circle steps aside so the words still fit one screen */
@media (max-width:860px) and (max-height:620px){
  .bk-app .ty-mark{display:none}
  .bk-app .ty h2{font-size:25px;margin-bottom:4px}
  .bk-app .ty .ty-lead{font-size:14.5px;margin-bottom:8px}
  .bk-app .ty-rows div{padding:5px 2px;font-size:14px}
  .bk-app .ty .ty-price{margin-bottom:8px}
  .bk-app .ty-pick:not([hidden]),.bk-app .ty .ty-q{margin-bottom:8px}
  .bk-app .ty .cta-row .btn{height:46px}
  .bk-app .ty{padding-top:0}
  .bk-app .ty .ty-lead{line-height:1.4}
  .bk-app .ty-rows div{padding:4px 2px;line-height:1.3}
}
.ty .note:empty{display:none}  /* 2026-10-13: the empty "not sent" note drew a small blank pill under Back to home */

/* 2026-10-21 (Ruben 3A): the optional "Anything you want to ask first?" box under the mobile number (book.html + the
   home card). 16px+ type so iPhone Safari does not zoom in; it may grow taller by hand, never wider. */
.theme-l .bk-ask{margin-top:6px}
.theme-l .bk-ask label .muted{font-weight:400}
.theme-l .bk-ask textarea{width:100%;box-sizing:border-box;height:92px;min-height:76px;max-height:220px;font-size:17px;line-height:1.45;padding:12px 16px;resize:vertical}
.theme-l .bk-ask textarea::placeholder{color:#9aa3a1}
@media (min-width:1100px){.bk-app .bk-ask textarea{font-size:18px}}
