.setvo-brand{display:inline-flex;align-items:center;gap:10px;font-size:30px;font-weight:750;letter-spacing:-1.5px;color:inherit;line-height:1.1;vertical-align:middle}.setvo-brand img{display:block;max-width:180px;height:36px;object-fit:contain}.setvo-brand.small-brand{font-size:24px}.brand-period{color:#c4f66a}.setvo-brand-icon{width:31px;height:30px;display:flex;align-items:center;gap:3px;transform:rotate(-18deg)}.setvo-brand-icon i{background:#c4f66a;width:7px;border-radius:3px;height:19px}.setvo-brand-icon i:nth-child(2){height:30px}.setvo-brand-icon i:nth-child(3){height:24px}
body.setvo-marketing{background:#0b0d0c!important}.setvo-landing{--lime:#c4f66a;--ink:#0b0d0c;--dim:#959d95;background:var(--ink);color:#f2f4ee;font-family:Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;font-size:16px;line-height:1.5;overflow:hidden;min-height:100vh}.setvo-landing *{box-sizing:border-box}.setvo-landing button{font:inherit;cursor:pointer}.setvo-landing a{color:inherit;text-decoration:none}.setvo-landing button:focus-visible,.setvo-landing a:focus-visible,.setvo-landing summary:focus-visible{outline:2px solid var(--lime);outline-offset:5px}.setvo-landing h1,.setvo-landing h2,.setvo-landing h3,.setvo-landing p{margin:0}.setvo-landing em{font-style:normal;color:var(--lime)}.landing-nav,.landing-hero,.landing-section,.landing-privacy,.landing-faq,.landing-footer,.landing-principles{width:min(1160px,calc(100% - 80px));margin:auto}.landing-nav{height:108px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #242824}.landing-nav nav{display:flex;gap:36px}.landing-nav nav button,.landing-link,.footer-links button{background:none;border:0;color:#c0c8bf;padding:10px 0}.landing-nav nav button:hover,.landing-link:hover{color:var(--lime)}.landing-btn{background:var(--lime);color:#172010;border:1px solid var(--lime);border-radius:12px;padding:17px 24px;display:inline-flex;align-items:center;justify-content:center;gap:30px;font-weight:650!important;font-size:16px;transition:transform .2s,background .2s}.landing-btn:hover{background:#d8ff9a;transform:translateY(-2px)}.landing-btn.small{padding:12px 18px;border-radius:10px;font-size:14px;gap:20px}.landing-btn span{font-size:22px;line-height:1}.landing-hero{min-height:740px;padding-top:86px;padding-bottom:90px;display:grid;grid-template-columns:1.05fr 1fr;align-items:center;gap:40px}.landing-eyebrow{font-size:11px;letter-spacing:2px;font-weight:650;color:var(--lime);display:flex;align-items:center;gap:9px;margin-bottom:24px}.landing-eyebrow>span{width:6px;height:6px;background:var(--lime);border-radius:50%;box-shadow:0 0 16px #c4f66675}.hero-copy h1{font-size:clamp(54px,6.4vw,89px);letter-spacing:-5px;line-height:1.02;font-weight:720}.hero-lead{max-width:438px;font-size:18px;line-height:1.75;color:#9da69c;margin-top:27px!important}.hero-actions{display:flex;align-items:center;gap:27px;margin-top:33px}.landing-link{display:inline-flex;align-items:center;gap:16px;font-size:14px;font-weight:600}.hero-footnote{font-size:12px;color:#7e897d;margin-top:18px!important}.hero-tags{display:flex;gap:18px;margin-top:44px;color:#b5bfb2;font-size:11px}.hero-tags span:before{content:'\2713';color:var(--lime);margin-right:6px}.hero-visual{position:relative;display:flex;justify-content:center;align-items:center;min-height:560px}.hero-orbit{position:absolute;width:470px;height:470px;border:1px solid #27301f;border-radius:50%;pointer-events:none}.orbit-one{transform:rotate(-22deg) scaleX(1.12);border-color:#263221;background:radial-gradient(ellipse,#c4f66a0c,transparent 65%)}.orbit-two{width:370px;height:370px;border-style:dashed;border-color:#303a28;transform:rotate(28deg) scaleX(1.35)}.preview-phone{background:#101411;width:286px;border:1px solid #4b5346;border-radius:38px;padding:19px 18px 9px;z-index:1;transform:rotate(7deg);box-shadow:0 0 0 5px #161b16,0 0 0 6px #292f26,0 32px 70px #0009}.phone-status{display:flex;justify-content:space-between;font-size:11px;color:#d1d9cc;margin:0 6px 26px}.phone-heading{display:flex;flex-direction:column;gap:6px}.phone-overline{font-size:8px;color:#8a9687;letter-spacing:1.5px}.phone-heading strong{font-size:30px;letter-spacing:-1.4px}.phone-dot{display:inline-block;width:8px;height:8px;background:var(--lime);border-radius:50%;margin-left:10px}.phone-subtitle{font-size:10px;color:#7d8c79}.phone-metrics{display:grid;grid-template-columns:repeat(3,1fr);margin:23px 0;padding:12px 0;background:#192018;border-radius:10px}.phone-metrics div{display:flex;flex-direction:column;align-items:center;gap:2px}.phone-metrics div+div{border-left:1px solid #2a3426}.phone-metrics b{font-size:17px;letter-spacing:-.5px}.phone-metrics b>span{font-size:11px;color:#84917c}.phone-metrics div>span{font-size:7px;color:#889582;letter-spacing:1px}.preview-exercise{display:flex;gap:11px;align-items:center}.preview-exercise>div:last-child{display:flex;flex-direction:column;gap:4px}.preview-exercise small{font-size:7px;color:#9aa991;letter-spacing:1px}.preview-exercise strong{font-size:14px}.preview-exercise span{font-size:8px;color:#899780}.preview-lift-icon{width:41px;height:44px;background:#23321d;border-radius:10px;display:flex;justify-content:center;align-items:center;gap:3px;transform:rotate(-3deg)}.preview-lift-icon i{width:6px;height:22px;background:var(--lime);border-radius:2px}.preview-lift-icon i:nth-child(2){width:12px;height:5px}.preview-sets{margin:18px 0}.preview-sets>div{display:grid;grid-template-columns:.65fr 1fr 1fr .65fr;align-items:center;text-align:center;gap:10px;font-size:11px;min-height:38px;border-bottom:1px solid #252d21}.preview-sets .sets-heading{font-size:8px;color:#819177;min-height:23px;border:0;letter-spacing:1px}.set-complete b{color:#cedbc4}.set-check{background:#273a20;color:#bde87e;border-radius:5px;height:24px;display:flex;justify-content:center;align-items:center}.set-current{background:#1a2315;border-radius:5px}.set-current b{color:var(--lime)}.set-current .set-check{background:#c4f66a;color:#172010}.preview-rest{display:flex;gap:12px;align-items:center;background:#1b2416;padding:13px 10px;border-radius:10px;border:1px solid #314024}.rest-ring{border:2px solid var(--lime);border-left-color:#485c33;border-radius:50%;width:37px;height:37px;display:grid;place-items:center;font-size:13px;color:var(--lime)}.preview-rest div{display:flex;flex-direction:column;gap:3px}.preview-rest strong{font-size:11px}.preview-rest div span{font-size:8px;color:#88957d}.phone-bottom{display:flex;justify-content:space-around;margin:22px 0 15px;font-size:8px;color:#6a7762}.phone-active{color:var(--lime)}.home-indicator{height:3px;width:76px;background:#8b9483;border-radius:5px;margin:0 auto}.preview-badge{position:absolute;z-index:3;bottom:58px;left:-8px;background:#e1ead6;border:1px solid #f2f6eb;color:#182211;border-radius:13px;padding:14px 18px;display:flex;gap:12px;align-items:center;box-shadow:0 12px 40px #0004;transform:rotate(-4deg)}.preview-badge>span{width:35px;height:35px;background:#c2dda3;border-radius:10px;display:grid;place-items:center;font-size:27px}.preview-badge div{display:flex;flex-direction:column;gap:3px}.preview-badge strong{font-size:12px}.preview-badge small{font-size:9px;color:#5b6c4e}.visual-caption{position:absolute;top:6px;right:-3px;font-size:8px;letter-spacing:1.2px;line-height:1.9;color:#a6b299;transform:rotate(7deg)}.visual-caption span{font-size:10px;color:#627059;letter-spacing:0}.preview-disclaimer{position:absolute;bottom:-17px;right:10px;font-size:8px;color:#67745b;letter-spacing:1.5px;display:none;}.landing-principles{border-top:1px solid #2c3229;border-bottom:1px solid #2c3229;display:grid;grid-template-columns:repeat(3,1fr);padding:27px 0;gap:20px}.landing-principles div{display:flex;gap:18px;align-items:center;color:#c3cabe;font-size:13px}.landing-principles b{font-size:10px;color:#6f805c;font-weight:500}.landing-section{padding:108px 0}.section-intro{display:flex;justify-content:space-between;gap:40px;align-items:flex-end;margin-bottom:38px}.section-intro h2,.landing-privacy h2,.landing-install h2{font-size:48px;line-height:1.15;letter-spacing:-2px;font-weight:650}.section-intro h2 span{color:#7f8b76}.section-intro>p{max-width:320px;color:#8e9a85;font-size:14px;line-height:1.8}.feature-grid{display:grid;grid-template-columns:1.15fr 1fr 1fr;gap:17px}.feature-card{background:#141914;border:1px solid #2a3227;border-radius:18px;padding:29px 26px;min-height:310px;position:relative;overflow:hidden}.feature-number{font-size:9px;letter-spacing:1.8px;color:#92a57b}.feature-card h3{font-size:23px;line-height:1.2;letter-spacing:-.8px;margin-top:24px}.feature-card p{font-size:13px;line-height:1.8;color:#89977f;margin-top:13px}.mini-week{display:flex;justify-content:space-between;gap:6px;margin-top:35px}.mini-week>span{background:#1b2218;border-radius:7px;min-width:26px;width:12%;height:44px;display:flex;align-items:center;flex-direction:column;justify-content:center;gap:6px;font-size:9px;color:#75876a}.mini-week .active-day{background:#344a23;color:#d4edb2}.mini-week i{width:3px;height:3px;background:currentColor;border-radius:50%}.mini-numbers{display:flex;gap:24px;justify-content:center;align-items:center;margin-top:26px}.mini-numbers b{font-size:38px;line-height:1;font-weight:500;color:#d2e3bb;letter-spacing:-1px}.mini-numbers small{font-size:8px;color:#819b6a;display:block;text-align:center;letter-spacing:1px;margin-top:8px}.mini-numbers>span{color:#566d43}.mini-bars{height:84px;display:flex;align-items:flex-end;gap:10px;margin-top:20px;padding:0 10px}.mini-bars i{flex:1;background:#2d4020;border-radius:4px 4px 0 0;max-width:30px}.mini-bars i:last-child{background:var(--lime)}.landing-privacy{display:grid;grid-template-columns:.85fr 1fr;align-items:center;gap:90px;border-top:1px solid #2a3227;padding:92px 70px 100px}.privacy-emblem{height:250px;display:grid;place-items:center;position:relative;background:radial-gradient(ellipse,#bfdc6930,transparent 65%)}.privacy-emblem:before,.privacy-emblem:after{content:'';position:absolute;width:205px;height:205px;border:1px solid #344329;border-radius:50%}.privacy-emblem:after{width:155px;height:155px;border-style:dashed;transform:rotate(14deg)}.privacy-emblem>span{font-size:55px;color:var(--lime);border:2px solid #75904f;border-radius:18px 18px 40px 40px;width:86px;height:100px;text-align:center;box-shadow:0 0 60px #8dad5820}.landing-privacy p{margin-top:20px;color:#a1ae94;font-size:15px;line-height:1.85}.landing-privacy .privacy-small{font-size:12px;color:#7d8c70}.landing-privacy .landing-link{margin-top:15px;color:var(--lime)}.landing-install{text-align:center;background:#151c10;border-top:1px solid #2f3f20;border-bottom:1px solid #2f3f20;padding:80px 24px}.landing-install .landing-eyebrow{justify-content:center}.landing-install h2{font-size:65px;letter-spacing:-3px}.landing-install>p{max-width:475px;margin:22px auto 0;color:#98a789;font-size:15px;line-height:1.8}.landing-install .setvo-install-compact{display:flex;justify-content:center;color:#c4f66a}.landing-install .btn{color:#14200c;background:var(--lime);border-radius:12px;min-height:52px;padding:0 30px}.landing-install .install-fine{font-size:11px;max-width:330px;color:#7e936b}.landing-faq{max-width:780px;padding:90px 0}.landing-faq h2{font-size:34px;letter-spacing:-1px;margin-bottom:30px}.landing-faq details{border-bottom:1px solid #2d3527}.landing-faq summary{list-style:none;cursor:pointer;padding:21px 0;display:flex;align-items:center;justify-content:space-between;font-size:15px;gap:15px}.landing-faq summary::-webkit-details-marker{display:none}.landing-faq summary>span{color:var(--lime);font-size:21px;font-weight:300}.landing-faq details[open] summary>span{transform:rotate(45deg)}.landing-faq details p{font-size:14px;color:#91a082;line-height:1.8;padding:0 25px 22px 0}.landing-footer{border-top:1px solid #2c3326;padding:44px 0 35px;display:flex;justify-content:space-between;gap:30px}.landing-footer p{font-size:12px;color:#7e8c71;margin-top:17px}.landing-footer>div:last-child{text-align:right;display:flex;flex-direction:column;align-items:flex-end;gap:18px}.landing-footer>div:last-child>a{font-size:15px;color:#c6d6b5}.footer-links{display:flex;align-items:center;gap:20px;font-size:11px;color:#899a7a}.footer-links button{font-size:11px;padding:0}.landing-footer small{font-size:10px;color:#6d7c60}.landing-skip{position:fixed;left:20px;top:-100px;background:var(--lime);color:#13200b!important;padding:12px;z-index:100}.landing-skip:focus{top:10px}.setvo-ad{border:1px solid var(--separator);border-radius:15px;padding:12px 15px;margin:0 0 18px;background:var(--surface-1)}.setvo-ad>small{font-size:9px;letter-spacing:1.5px;opacity:.55;display:block;margin-bottom:8px}.setvo-ad a,.setvo-ad>div{display:flex;flex-direction:column;gap:8px;color:inherit;text-decoration:none}.setvo-ad img{width:100%;max-height:220px;object-fit:contain;border-radius:8px}.setvo-ad strong{font-size:17px}.setvo-ad a>span{font-size:13px;opacity:.8}.setvo-ad a>b{font-size:12px;color:var(--acc)}.site-field{display:flex;flex-direction:column;gap:6px;margin-bottom:13px;font-size:13px}.site-field input,.site-field textarea{width:100%;min-width:0;padding:11px 12px;border:1px solid var(--separator);border-radius:9px;background:var(--surface-2);color:var(--label-1);font:inherit;font-size:16px}.site-field textarea{min-height:76px;resize:vertical}.brand-upload-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.brand-upload{border:1px solid var(--separator);border-radius:12px;padding:13px;min-width:0}.brand-upload-preview{height:65px;display:flex;align-items:center;justify-content:center;border-radius:7px;background:#e6e9e3;margin:10px 0}.brand-upload-preview.dark{background:#11170e}.brand-upload-preview img{max-width:100%;max-height:55px;object-fit:contain}.brand-upload input{font-size:12px;max-width:100%}.storage-metrics{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin:15px 0}.storage-metrics div{background:var(--surface-2);border-radius:10px;padding:12px;text-align:center}.storage-metrics b{font-size:23px;display:block}.storage-metrics span{font-size:11px;opacity:.65}.setvo-mode-note{border:1px solid var(--separator);background:var(--surface-2);border-radius:12px;padding:15px;margin-bottom:18px;font-size:13px;line-height:1.7}.setvo-mode-note p{margin:0 0 8px}.setvo-admin-login{max-width:450px;padding:50px 20px;margin:auto}.setvo-admin-login .setvo-brand{margin-bottom:30px}.setvo-boot{min-height:70vh;display:grid;place-items:center}
@media(min-width:1400px){.landing-hero{min-height:780px}.hero-visual{transform:scale(1.05)}}
@media(max-width:1000px){.landing-nav,.landing-hero,.landing-section,.landing-privacy,.landing-faq,.landing-footer,.landing-principles{width:calc(100% - 48px)}.landing-hero{gap:20px;padding-top:70px}.hero-copy h1{font-size:64px;letter-spacing:-3.5px}.hero-tags{flex-wrap:wrap;gap:10px}.hero-visual{transform:scale(.88);transform-origin:center right}.hero-lead{font-size:16px}.feature-card{padding:23px 20px}.feature-card h3{font-size:21px}.landing-privacy{padding:70px 30px;gap:35px}}
@media(max-width:700px){.landing-nav,.landing-hero,.landing-section,.landing-privacy,.landing-faq,.landing-footer,.landing-principles{width:calc(100% - 40px)}.landing-nav{height:85px}.landing-nav nav{display:none}.landing-nav .setvo-brand{font-size:27px}.landing-nav .landing-btn.small{padding:10px 13px;font-size:12px;gap:14px}.landing-hero{grid-template-columns:1fr;padding-top:56px;padding-bottom:55px;gap:40px;min-height:0}.hero-copy h1{font-size:clamp(52px,13.8vw,75px);letter-spacing:-3.5px}.landing-eyebrow{font-size:9px;letter-spacing:1.6px;margin-bottom:21px}.hero-lead{font-size:16px;line-height:1.75;margin-top:23px!important;max-width:410px}.hero-actions{gap:24px;margin-top:26px}.landing-btn{padding:15px 20px;font-size:14px;gap:25px}.hero-footnote{font-size:11px}.hero-tags{margin-top:26px;font-size:10px;gap:15px}.hero-visual{transform:none;min-height:540px;margin:0 auto;width:min(100%,390px)}.preview-phone{width:258px;padding:17px 16px 8px;border-radius:32px;transform:rotate(5deg)}.hero-orbit{width:320px;height:320px}.orbit-two{width:260px;height:260px}.phone-status{margin-bottom:20px}.phone-heading strong{font-size:28px}.phone-metrics{margin:19px 0}.preview-badge{left:-4px;bottom:42px;padding:12px 13px}.preview-badge strong{font-size:11px}.visual-caption{right:-3px;top:2px;font-size:7px}.preview-disclaimer{bottom:0;right:0;font-size:7px;display:none;}.landing-principles{gap:15px;padding:23px 0}.landing-principles div{flex-direction:column;gap:8px;align-items:flex-start;font-size:11px;line-height:1.6}.landing-principles b{font-size:9px}.landing-section{padding:62px 0}.section-intro{display:block;margin-bottom:26px}.section-intro h2,.landing-privacy h2{font-size:36px;letter-spacing:-1.5px}.section-intro>p{font-size:13px;margin-top:20px}.feature-grid{grid-template-columns:1fr;gap:12px}.feature-card{min-height:230px;padding:25px}.feature-card h3{margin-top:15px;font-size:23px}.feature-card p{max-width:280px}.mini-week{max-width:320px;margin-top:24px}.mini-numbers{justify-content:flex-start;margin-left:15px}.mini-bars{max-width:280px;padding:0;height:60px}.landing-privacy{grid-template-columns:1fr;padding:25px 0 60px;gap:20px}.privacy-emblem{height:200px;max-width:250px;width:100%;margin:auto}.privacy-emblem:before{width:170px;height:170px}.privacy-emblem:after{width:135px;height:135px}.landing-privacy p{font-size:14px}.landing-install{padding:65px 24px}.landing-install h2{font-size:48px;letter-spacing:-2px}.landing-install>p{font-size:14px}.landing-faq{padding:60px 0}.landing-faq h2{font-size:29px}.landing-faq summary{font-size:14px;padding:20px 0}.landing-faq details p{font-size:13px}.landing-footer{padding:35px 0 30px;flex-direction:column;gap:35px}.landing-footer>div:last-child{align-items:flex-start;text-align:left;gap:16px}.brand-upload-grid{grid-template-columns:1fr}.storage-metrics{grid-template-columns:1fr 1fr}.brand-upload input{font-size:14px}}
@media(prefers-reduced-motion:reduce){.setvo-landing *{scroll-behavior:auto!important;transition:none!important;animation:none!important}}

/* Admin dashboard — operator-facing, English-only. Sits on top of the app's tokens; nothing
   here is used outside views/Admin.jsx and views/AdminCoach.jsx. The page is looked at maybe
   twice a year, so every card says what it is for in a sentence and every state is a word, not
   a colour to decode. */

.adm-intro{color:var(--label-2);font-size:14px;line-height:1.45;margin:-6px 0 16px}

/* one sentence under a card heading that says what the card is for */
.adm-lead{color:var(--label-2);font-size:13px;line-height:1.45;margin:2px 0 12px}

/* status pill: a word and a colour, never a paragraph */
.adm-pill{
  display:inline-flex;align-items:center;gap:6px;padding:3px 10px;border-radius:999px;
  font-size:12.5px;font-weight:600;letter-spacing:-.004em;line-height:1.5;white-space:nowrap;
  background:var(--surface-2);color:var(--label-2)
}
.adm-pill::before{content:'';width:7px;height:7px;border-radius:50%;background:currentColor;flex:none}
.adm-pill.ok{background:color-mix(in srgb,var(--green) 16%,transparent);color:var(--green)}
.adm-pill.warn{background:color-mix(in srgb,var(--yellow) 18%,transparent);color:var(--yellow)}
.adm-pill.bad{background:color-mix(in srgb,var(--red) 16%,transparent);color:var(--red)}
.adm-pill.acc{background:var(--acc-soft);color:var(--acc)}

/* the one-line "what state is this in" under the card title */
.adm-status{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:14px;color:var(--label-2);margin:4px 0 14px;line-height:1.4}

/* numbered setup steps: a <details> per step, so a finished step folds away */
.adm-step{border-top:var(--hair) solid var(--sep);padding:2px 0}
.adm-step:first-of-type{border-top:0}
.adm-step>summary{
  list-style:none;cursor:pointer;display:flex;align-items:center;gap:12px;min-height:50px;padding:6px 0;
  -webkit-tap-highlight-color:transparent
}
.adm-step>summary::-webkit-details-marker{display:none}
.adm-step>summary:active{opacity:.7}
.adm-num{
  width:26px;height:26px;border-radius:50%;flex:none;display:grid;place-items:center;
  font-size:13px;font-weight:700;background:var(--surface-3);color:var(--label)
}
.adm-step.done .adm-num{background:var(--acc);color:var(--on-acc)}
.adm-step.todo .adm-num{background:var(--surface-3);color:var(--label-2)}
.adm-step-t{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.adm-step-t b{font-size:16px;font-weight:600;letter-spacing:-.012em;line-height:1.25}
.adm-step-t span{font-size:13px;color:var(--label-2);line-height:1.3}
.adm-step>summary .chev{color:var(--label-3);font-size:14px;transition:transform .18s ease;flex:none}
.adm-step[open]>summary .chev{transform:rotate(90deg)}
.adm-step-b{padding:2px 0 14px 38px}
@media (max-width:380px){.adm-step-b{padding-left:0}}

/* a dim explainer that reads like a sentence, not a footnote */
.adm-hint{font-size:13px;color:var(--label-2);line-height:1.45;margin:6px 0 10px}
.adm-hint code{font-size:12px;background:var(--surface-2);padding:1px 5px;border-radius:5px}

/* provider chips grouped under a small heading */
.adm-group{margin:0 0 12px}
.adm-group-t{font-size:11.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--label-3);margin:0 0 7px}
.adm-chips{display:flex;flex-wrap:wrap;gap:8px}
.adm-chips .chip{min-height:38px;display:inline-flex;align-items:center;gap:7px}
.adm-chip-key{
  font-size:10.5px;font-weight:700;letter-spacing:.02em;padding:1px 6px;border-radius:999px;
  background:var(--acc-soft);color:var(--acc)
}
.chip.on .adm-chip-key{background:rgba(0,0,0,.18);color:inherit}

/* label + control pairs inside a step */
.adm-field{display:flex;flex-direction:column;gap:6px;margin:0 0 10px}
.adm-field>label{font-size:13px;font-weight:600;color:var(--label-2)}
/* Inside a card the app's default field colour is the card's own colour, so the box was
   invisible and the placeholder floated in space. One shade up, and a size that is readable
   without iOS zooming into it. */
.adm-field .field{width:100%;background:var(--surface-2);font-size:16px;min-height:44px}
.adm-select{
  width:100%;min-height:44px;padding:10px 38px 10px 12px;border-radius:var(--r);border:0;
  background:var(--surface-2);color:var(--label);font-size:15px;appearance:none;-webkit-appearance:none;
  background-image:linear-gradient(45deg,transparent 50%,var(--label-2) 50%),linear-gradient(135deg,var(--label-2) 50%,transparent 50%);
  background-position:calc(100% - 20px) 50%,calc(100% - 14px) 50%;background-size:6px 6px;background-repeat:no-repeat
}
.adm-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:6px}
.adm-actions .btn{min-height:44px}

/* inline result box under the Test button */
.adm-result{
  margin-top:10px;padding:10px 12px;border-radius:var(--r);font-size:13.5px;line-height:1.45;
  background:var(--surface-2);color:var(--label)
}
.adm-result.ok{background:color-mix(in srgb,var(--green) 14%,transparent)}
.adm-result.bad{background:color-mix(in srgb,var(--red) 14%,transparent)}
.adm-result b{display:block;margin-bottom:2px}

/* advanced / activity folds */
.adm-fold{border-top:var(--hair) solid var(--sep);margin-top:4px}
.adm-fold>summary{
  list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:10px;
  min-height:48px;padding:6px 0;font-size:15px;font-weight:600;letter-spacing:-.012em
}
.adm-fold>summary::-webkit-details-marker{display:none}
.adm-fold>summary .chev{color:var(--label-3);font-size:14px;transition:transform .18s ease}
.adm-fold[open]>summary .chev{transform:rotate(90deg)}
.adm-fold-b{padding:0 0 12px}

.adm-kv{display:flex;justify-content:space-between;gap:12px;padding:9px 0;border-bottom:var(--hair) solid var(--sep);font-size:14px}
.adm-kv:last-child{border-bottom:0}
.adm-kv .k{color:var(--label-2);flex:none}
.adm-kv .v{text-align:right;min-width:0;overflow-wrap:anywhere}
/* the two daily-limit numbers: a real field, not the browser's white default box */
.adm-kv .v input{
  width:84px;min-height:40px;padding:6px 10px;text-align:right;font-size:16px;font-weight:600;
  border:0;border-radius:10px;background:var(--surface-2);color:var(--label);outline:none;
  -moz-appearance:textfield;appearance:textfield
}
.adm-kv .v input::-webkit-outer-spin-button,.adm-kv .v input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.adm-kv .v input:focus{box-shadow:inset 0 0 0 2px var(--acc)}

.adm-log{display:flex;flex-direction:column}
.adm-log-row{display:flex;justify-content:space-between;gap:10px;padding:8px 0;border-bottom:var(--hair) solid var(--sep);font-size:13.5px}
.adm-log-row:last-child{border-bottom:0}
.adm-log-row .when{color:var(--label-3);font-size:12px;flex:none}

/* users list rows with a copy affordance for invite codes */
.adm-code{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-weight:600;letter-spacing:.08em;
  background:var(--surface-2);padding:4px 9px;border-radius:8px;font-size:14px
}
.adm-iconbtn{width:44px;height:44px;border-radius:12px;font-size:17px}
.adm-empty{color:var(--label-3);font-size:13.5px;padding:10px 2px}

/* ---------- the Coach before setup: a pitch, not a form ---------- */
.adm-hero{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:6px 2px 2px}
.adm-hero-av{
  width:52px;height:52px;border-radius:16px;display:grid;place-items:center;font-size:26px;
  background:linear-gradient(135deg,var(--acc),color-mix(in srgb,var(--acc) 55%,var(--teal)));
  color:var(--on-acc);margin-bottom:8px;box-shadow:0 8px 24px -8px color-mix(in srgb,var(--acc) 55%,transparent)
}
.adm-hero h2{margin:0 0 4px;font-size:22px;letter-spacing:-.022em}
.adm-hero p{margin:0 0 14px;font-size:14px;line-height:1.5;color:var(--label-2)}
.adm-hero-feats{display:grid;gap:10px;margin-bottom:18px}
.adm-hero-feats>div{display:flex;gap:11px;align-items:flex-start}
.adm-hero-feats .icn{color:var(--acc);font-size:18px;flex:none;margin-top:2px}
.adm-hero-feats span{font-size:13.5px;line-height:1.45;color:var(--label-2)}
.adm-hero-feats b{color:var(--label);font-weight:600}
.adm-hero .btn{width:100%}

/* ---------- setup progress ---------- */
.adm-progress{height:5px;border-radius:99px;background:var(--surface-2);overflow:hidden;margin:0 0 10px}
.adm-progress i{display:block;height:100%;border-radius:99px;background:var(--acc);transition:width var(--med) var(--ease)}

/* ---------- provider chips: clearly idle vs. clearly chosen ---------- */
.adm-chips .chip{
  background:var(--surface-2);border:1.5px solid transparent;color:var(--label);
  font-weight:500;text-transform:none
}
.adm-chips .chip.on{background:var(--acc-soft);border-color:var(--acc);color:var(--acc);font-weight:600}
.adm-chips .chip:active{transform:scale(.97)}

/* a finished step's summary reads as a receipt, not a control */
.adm-step.done>summary .adm-step-t span{color:var(--acc)}

/* ============================================================================
   Setvo — design system
   ----------------------------------------------------------------------------
   Rebuilt around four rules, each aimed at a specific "generated" tell in the
   previous sheet:

   1. ONE TYPE SCALE, MOSTLY REGULAR WEIGHT. The old sheet set font-weight 700/800
      on nearly every element, which flattens hierarchy — when everything shouts,
      position is the only cue left. Here weight carries meaning: 600 for a title,
      400 for its content, and size does the rest.
   2. A NEUTRAL SURFACE RAMP. Cards are near-neutral greys a few points apart, not
      saturated blue-greys. Colour is spent only on the accent and on status.
   3. HAIRLINES, NOT BORDERS. Separators are sub-pixel and inset past the icon
      rail, so a list reads as one object instead of a stack of outlined boxes.
   4. MOTION THAT ACKNOWLEDGES, NOT ANIMATES. Presses scale ~2%, transitions run
      140–220ms on an ease-out curve. Nothing bounces or slides for decoration.
   ========================================================================== */

/* ---------------------------------------------------------------- tokens -- */
:root {
  /* surfaces — dark is the default */
  --bg:        #000000;
  --bg-el:     #0e0e10;   /* elevated backdrop (sheets, bars) */
  --surface:   #1c1c1e;   /* card / grouped-list fill */
  --surface-2: #2c2c2e;   /* pressed + nested fill */
  --surface-3: #3a3a3c;   /* controls (segmented track, switch off) */

  /* text */
  --label:     #ffffff;
  --label-2:   rgba(235,235,245,.60);
  --label-3:   rgba(235,235,245,.32);
  --label-4:   rgba(235,235,245,.18);

  /* lines */
  --sep:       rgba(84,84,88,.60);
  --sep-op:    rgba(84,84,88,.34);   /* for edges sitting over blur */
  --hair:      .5px;

  /* system palette (iOS dark values) */
  --blue:#0a84ff; --green:#30d158; --red:#ff453a; --orange:#ff9f0a;
  --yellow:#ffd60a; --teal:#40c8e0; --indigo:#5e5ce6; --pink:#ff375f;
  --purple:#bf5af2; --mint:#63e6e2; --brown:#ac8e68; --grey:#8e8e93;

  /* accent (per-account, synced) */
  --acc:  var(--green);
  --acc-2:#248a3d;
  --on-acc:#000000;
  --acc-soft: color-mix(in srgb, var(--acc) 16%, transparent);
  --acc-line: color-mix(in srgb, var(--acc) 38%, transparent);

  /* geometry */
  --r-sm:8px; --r:12px; --r-lg:16px; --r-xl:22px; --r-card:14px;
  --pad:16px;
  --icon-stroke:1.7;

  /* motion */
  --ease:cubic-bezier(.32,.72,0,1);
  --fast:140ms; --med:220ms;

  --sab:env(safe-area-inset-bottom,0px);
  --sat:env(safe-area-inset-top,0px);
}

:root[data-theme="light"] {
  --bg:        #f2f2f7;
  --bg-el:     #f7f7fa;
  --surface:   #ffffff;
  --surface-2: #ececef;
  --surface-3: #e3e3e8;

  --label:     #000000;
  --label-2:   rgba(60,60,67,.60);
  --label-3:   rgba(60,60,67,.30);
  --label-4:   rgba(60,60,67,.16);

  --sep:       rgba(60,60,67,.29);
  --sep-op:    rgba(60,60,67,.20);

  --blue:#007aff; --green:#34c759; --red:#ff3b30; --orange:#ff9500;
  --yellow:#ffcc00; --teal:#30b0c7; --indigo:#5856d6; --pink:#ff2d55;
  --purple:#af52de; --mint:#00c7be; --brown:#a2845e; --grey:#8e8e93;
  --acc-2:#248a3d;
  --on-acc:#ffffff;
}

/* accents — Apple's system colours, so a recolour never looks off-system */
:root[data-accent="lime"]  { --acc:var(--green);  --acc-2:#248a3d; --on-acc:#000 }
:root[data-accent="sky"]   { --acc:var(--blue);   --acc-2:#0060df; --on-acc:#fff }
:root[data-accent="orange"]{ --acc:var(--orange); --acc-2:#c76b00; --on-acc:#000 }
:root[data-accent="violet"]{ --acc:var(--purple); --acc-2:#8944ab; --on-acc:#fff }
:root[data-accent="pink"]  { --acc:var(--pink);   --acc-2:#d70036; --on-acc:#fff }
:root[data-accent="red"]   { --acc:var(--red);    --acc-2:#d70015; --on-acc:#fff }
:root[data-accent="teal"]  { --acc:var(--teal);   --acc-2:#0071a4; --on-acc:#000 }
:root[data-accent="gold"]  { --acc:var(--yellow); --acc-2:#b25000; --on-acc:#000 }
/* Label colour on a filled accent button is picked per accent by measured contrast,
   not by taste. Button text is 17px/600, so the AA bar is 3:1 (large text). White on
   the light-theme green is 2.22:1 and on teal 2.57:1 — both fail, and green is the
   DEFAULT accent, so every primary button in light mode was failing. Black scores
   9.46 / 8.16 there. Blue, purple, pink and red keep white (3.5–4.1:1), which both
   passes and matches the platform convention. */
:root[data-theme="light"][data-accent="lime"],
:root[data-theme="light"][data-accent="teal"]  { --on-acc:#000 }
:root[data-theme="light"][data-accent="sky"],
:root[data-theme="light"][data-accent="violet"],
:root[data-theme="light"][data-accent="pink"],
:root[data-theme="light"][data-accent="red"]   { --on-acc:#fff }

/* ---------------------------------------------------------------- reset -- */
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html{
  font-size:16px;background:var(--bg);overscroll-behavior:none;overflow-x:clip;
  -webkit-text-size-adjust:100%;
}
body{
  background:var(--bg);color:var(--label);
  font-family:-apple-system,BlinkMacSystemFont,'SF Pro Text','SF Pro Display','Segoe UI',Roboto,system-ui,sans-serif;
  font-size:17px;line-height:1.29;letter-spacing:-.01em;
  min-height:100vh;min-height:100dvh;overscroll-behavior-y:none;overflow-x:clip;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  touch-action:manipulation;
  font-variant-numeric:tabular-nums;
}
button{font:inherit;color:inherit;background:none;border:none;cursor:pointer;letter-spacing:inherit}
input,select,textarea{font:inherit;color:var(--label);letter-spacing:inherit}
img{max-width:100%}
a{color:var(--acc);text-decoration:none}
:focus{outline:none}
:focus-visible{outline:2.5px solid var(--acc);outline-offset:2px;border-radius:6px}
button,.chip,.tile,.item,.wday,.cal-d,.swatch,.hm-c,.lrow,.seg button,.stp button,.sld
{-webkit-user-select:none;user-select:none}

/* icons inherit colour and optical size from their context */
.icn{
  width:1em;height:1em;flex:none;display:block;
  fill:none;stroke:currentColor;stroke-width:var(--icon-stroke);
  stroke-linecap:round;stroke-linejoin:round;
}

@media (prefers-reduced-motion: reduce){*{animation:none!important;transition:none!important}}

/* ------------------------------------------------------------ type scale -- */
.t-large  {font-size:34px;line-height:1.06;font-weight:700;letter-spacing:-.028em}
.t-title  {font-size:28px;line-height:1.12;font-weight:700;letter-spacing:-.024em}
.t-title2 {font-size:22px;line-height:1.18;font-weight:700;letter-spacing:-.021em}
.t-head   {font-size:17px;line-height:1.29;font-weight:600;letter-spacing:-.012em}
.t-body   {font-size:17px;line-height:1.29;font-weight:400;letter-spacing:-.012em}
.t-callout{font-size:16px;line-height:1.31;font-weight:400;letter-spacing:-.009em}
.t-sub    {font-size:15px;line-height:1.33;font-weight:400;letter-spacing:-.006em}
.t-foot   {font-size:13px;line-height:1.38;font-weight:400;letter-spacing:-.001em}
.t-cap    {font-size:12px;line-height:1.33;font-weight:400;letter-spacing:0}

.muted{color:var(--label-2)} .dim{color:var(--label-3)}
.small{font-size:13px;line-height:1.38}
.accent{color:var(--acc)}
.capitalize{text-transform:capitalize}
/* exercise names and body-part/equipment terms arrive lowercase from the dataset,
   so tags and chips capitalise by default. Anything that is a unit or a sentence opts
   back out — blanket-capitalising turned "60 kg" into "60 Kg" and a whole hint into
   Title Case. The compound selectors are needed: .tag/.chip come later in this file
   and would otherwise win on source order. */
.nocap,.tag.nocap,.chip.nocap{text-transform:none}

/* ---------------------------------------------------------------- layout -- */
#app{
  padding:calc(var(--sat) + 8px) var(--pad) calc(88px + var(--sab));
  max-width:560px;margin:0 auto;
}
/* Keep the last workout controls clear of the mobile overlays without adding a second
   screenful of blank scroll space. The stacked rest timer needs the larger reserve. */
body.resting #app{padding-bottom:calc(206px + var(--sab))}
.workout-end-spacer{height:0}
@keyframes viewfade{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
#app.vfade{animation:viewfade var(--med) var(--ease)}

/* sync banner: one line for a signed-in user whose changes are not on the server yet */
.sync-banner{
  display:flex;align-items:center;gap:9px;width:100%;text-align:left;
  margin:0 0 12px;padding:9px 12px;border-radius:var(--r);
  background:color-mix(in srgb,var(--yellow) 16%,var(--surface));color:var(--label);font-size:13px;line-height:1.35;
}
.sync-banner.off{background:color-mix(in srgb,var(--label-3) 18%,var(--surface))}
.sync-banner .icn,.sync-banner svg{flex:none;font-size:16px;color:var(--label-2)}
/* large title, the way a nav bar does it */
.hdr{display:flex;align-items:flex-end;justify-content:space-between;gap:12px;margin:8px 0 18px}
/* The title block gives way, the button on the right never does: a flex item will not shrink
   below its longest word, so "Упражнения" at 34px or "Hi Bartholomew_Jones" used to push the
   gear / "By muscle" past the screen edge. Two things follow from letting it shrink. Below 420px
   — every phone width we test — the title drops a step to 30px, because the 95 to 125px the
   Library button leaves the Polish and Russian titles is less than half of "Ćwiczenia" or
   "Упражнения" at 34px and they came apart into three lines; at 30px all 14 packs take two at
   most. And a word that still does not fit is broken with overflow-wrap:break-word, which moves
   the whole word to the next line first and breaks it only if it does not fit there either —
   `anywhere` broke "Bartholomew_Jones" mid-word even at 412px, where a line of its own was
   waiting for it. hyphens:auto goes with them: the hyphen costs a character's worth of width in
   a box this tight, and that is what turned "Упражнения" into "Упра / жнен / ия". */
.hdr>div{min-width:0}
.hdr>.btn{flex:none}
.hdr h1{font-size:34px;line-height:1.06;font-weight:700;letter-spacing:-.028em;overflow-wrap:break-word}
@media (max-width:420px){.hdr h1{font-size:30px}}
.hdr .sub{color:var(--label-2);font-size:15px;letter-spacing:-.006em;margin-top:4px}

.iconbtn{
  width:36px;height:36px;border-radius:50%;flex:none;
  background:var(--surface);color:var(--label);
  display:flex;align-items:center;justify-content:center;font-size:18px;
  transition:background var(--fast),transform var(--fast);
}
.iconbtn:active{background:var(--surface-2);transform:scale(.92)}
/* invisible hit-area extension: these look right at their size but fall short of a
   finger-sized target, so the pseudo element widens what the tap lands on without
   changing the painted box. Segmented buttons sit flush against each other, so they
   only grow vertically or the neighbour would steal the edge of the tap. */
.iconbtn,.chip,.seg button,.helpbtn{position:relative}
.iconbtn::before,.chip::before,.seg button::before,.helpbtn::before{content:'';position:absolute;inset:-6px}
.seg button::before{inset:-6px 0}
.iconbtn.on-ss{background:var(--acc-soft);color:var(--acc)}
.iconbtn:disabled{opacity:.32}

h4.sec{
  font-size:13px;font-weight:400;letter-spacing:-.004em;color:var(--label-2);
  text-transform:none;margin:22px 0 8px;padding:0 4px;
}
.card h2{
  font-size:13px;font-weight:400;letter-spacing:-.004em;color:var(--label-2);
  text-transform:none;margin:0 0 12px;
}
.divider{height:var(--hair);background:var(--sep);margin:14px 0;border:0}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.row{display:flex;align-items:center;gap:12px}
.row.between{justify-content:space-between}
/* The body-weight card header (Home and Stats): title on the left, Goal + Log on the right. In
   German the title and the two buttons ("Ziel", "+ Eintragen") outgrow a 320px card by about
   55px, so the button pair may drop to a second line — still flush right, hence the auto margin. */
.bw-head{flex-wrap:wrap;row-gap:8px}
.bw-head>.row{margin-left:auto}

/* ----------------------------------------------------------------- card -- */
.card{
  background:var(--surface);border-radius:var(--r-card);
  padding:16px;margin-bottom:12px;
}
.card .big{font-size:30px;font-weight:600;letter-spacing:-.026em;line-height:1.1}

/* ------------------------------------------------------ inset group list -- */
.sect{margin-bottom:22px}
.sect-t{
  font-size:13px;font-weight:400;color:var(--label-2);
  letter-spacing:-.004em;padding:0 4px 7px;display:block;
}
.sect-b{background:var(--surface);border-radius:var(--r-card);overflow:hidden}
.sect-f{font-size:13px;color:var(--label-2);padding:7px 4px 0;line-height:1.38}

.lrow{
  display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  padding:11px 14px;min-height:46px;position:relative;color:var(--label);
  background:none;
}
/* hairline starts after the icon rail so the list reads as one object */
.lrow+.lrow::before{
  content:'';position:absolute;left:14px;right:0;top:0;height:var(--hair);background:var(--sep);
}
.lrow:has(.lrow-i)+.lrow:has(.lrow-i)::before{left:55px}
.lrow.tap:active{background:var(--surface-2)}
.lrow-i{
  width:29px;height:29px;border-radius:7px;flex:none;font-size:18px;
  display:flex;align-items:center;justify-content:center;
  background:var(--tint,var(--acc));color:#fff;
}
/* The title column never shrinks below its own longest word. With a basis of 0 and min-width:0 it
   only got what a capped value left over, and on a 320px phone "Progression" (96px) was painted over
   by "Linear progression" in a 37px box; min-width:auto — the flex default — is exactly the floor
   that case wants. A fixed 104px floor fixed that row and starved the rest: the backfill sheet's Date
   and Start-time rows have nothing but the title to give, so the floor shoved their fixed-width
   .timef off a 320px screen, and a short title like "Routine" (63px) took 104px away from the value
   beside it until "Freies Training" ellipsised. Asking only for the longest word takes nothing a row
   did not already owe the title. .lrow-t does not ellipsise on purpose — long settings titles wrap
   onto a second line — and the value next to it shrinks and ellipsises instead (below). */
.lrow-m{flex:1;min-width:auto;display:flex;flex-direction:column;gap:1px}
.lrow-t{font-size:17px;letter-spacing:-.012em;line-height:1.25}
.lrow-s{font-size:13px;color:var(--label-2);line-height:1.3}
/* flex:none would let a long value ("Follow the routine (Linear progression)") run straight
   through the title next to it, since the title's column only holds out for its longest word.
   Letting the value shrink and ellipsise instead keeps the two out of each other's way.
   The cap is max-width, not flex-basis: .lrow-m is flex:1, so its basis is 0 and it absorbs
   none of the shrink — a long value would otherwise take the whole row and squeeze the title
   to 21px. A basis of 45% fixes that but reserves the space even for "3", costing the title
   141px on the rows that need it most. A cap does neither. */
.lrow-v{color:var(--label-2);font-size:17px;letter-spacing:-.012em;flex:0 1 auto;max-width:55%;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:right}
.lrow-c{color:var(--label);font-size:15px;flex:none;--icon-stroke:2.4}
.lrow-k{color:var(--acc);font-size:17px;flex:none;--icon-stroke:2.4}
.lrow.danger,.lrow.danger .lrow-t{color:var(--red)}
/* The Stats exercise name gets its own line so long names cannot run into the title.
   Two columns only — label/value on the left, chevron on the right — so this is for rows
   WITHOUT an icon. `.lrow-i` is not placed here; on a row that has one it would auto-place
   into the grid and push the layout around. Give it a leading column before using this
   anywhere else. */
.lrow.lrow-stack-value{
  display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-rows:auto auto;
}
.lrow.lrow-stack-value .lrow-m{grid-column:1;grid-row:1}
.lrow.lrow-stack-value .lrow-v{grid-column:1;grid-row:2;width:100%;max-width:none;text-align:left}
.lrow.lrow-stack-value .lrow-c{grid-column:2;grid-row:1 / span 2;align-self:center}
/* an (i) before a row's control: painted small and dim so the control stays the loud thing,
   but with a finger-sized target like everything else — the padding is the hit area and the
   vertical negative margin keeps it from making the row taller. The horizontal ones pull the
   hit area back under the row's own 12px gap instead of adding to it. */
.helpbtn{
  color:var(--label-3);font-size:16px;background:none;line-height:0;flex:none;
  margin:-11px -2px -11px -4px;padding:11px 4px;
}
.helpbtn:active{color:var(--label)}

/* -------------------------------------------------------------- buttons -- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;width:100%;
  padding:14px 18px;border-radius:var(--r);font-size:17px;font-weight:600;
  letter-spacing:-.012em;background:var(--surface-2);color:var(--label);
  transition:transform var(--fast) var(--ease),background var(--fast),opacity var(--fast);
}
.btn .icn{font-size:19px}
.btn:active{transform:scale(.975)}
.btn.primary{background:var(--acc);color:var(--on-acc)}
.btn.primary:active{background:var(--acc-2)}
.btn.tinted{background:var(--acc-soft);color:var(--acc)}
.btn.danger{background:color-mix(in srgb,var(--red) 15%,transparent);color:var(--red)}
.btn.ghost,.btn.plain{background:none;color:var(--acc);font-weight:400}
.btn.ghost:active,.btn.plain:active{background:var(--surface-2)}
.btn.sm{padding:8px 14px;width:auto;font-size:15px;border-radius:var(--r-sm);gap:5px}
.btn.sm .icn{font-size:16px}
.btn.xs{padding:5px 10px;width:auto;font-size:13px;border-radius:7px;gap:4px}
.btn:disabled{opacity:.32;pointer-events:none}

/* ----------------------------------------------------------- tab bar ----- */
/* Nearly opaque, and deliberately so. At the old 72% the page read straight through the bar
   and the labels had to compete with whatever was scrolling behind them — nobody needs to read
   the content under a navigation bar. 94% keeps a hint of movement behind the glass without
   letting text through. The blur is also down from 24px to 10px: this is a fixed element, so
   the WebView recomposites the blurred region on every scroll frame, and on Android that is
   the single most expensive thing on the screen. See @supports below for the no-blur case. */
#tabbar{
  position:fixed;left:0;right:0;bottom:0;z-index:50;
  display:flex;justify-content:space-around;align-items:flex-end;
  padding:7px 6px calc(6px + var(--sab));
  background:color-mix(in srgb,var(--bg-el) 94%,transparent);
  -webkit-backdrop-filter:saturate(180%) blur(10px);backdrop-filter:saturate(180%) blur(10px);
  border-top:var(--hair) solid var(--sep-op);
}
:root[data-theme="light"] #tabbar{background:rgba(249,249,251,.94)}
#tabbar button{
  flex:1;display:flex;flex-direction:column;align-items:center;gap:3px;
  color:var(--label-3);font-size:10px;font-weight:500;letter-spacing:.005em;padding-top:3px;
  transition:color var(--fast);
}
/* The inactive tint is semi-transparent, so wherever two strokes cross inside an
   icon (the calendar's hangers over its frame, the divider's caps on its sides)
   the alpha doubled up and the icon read as a stack of loose layers. Carrying the
   fade on the <svg> instead of in the stroke colour flattens the icon first and
   fades it as one shape — and it does that for every icon, not just this one. */
#tabbar button .icn{font-size:25px;--icon-stroke:1.65;color:var(--label)}
#tabbar button.on{color:var(--acc)}
#tabbar button.on .icn{--icon-stroke:2;color:inherit;opacity:1}
#tabbar button.start{margin-top:-24px}
#tabbar button.start .cir{
  width:52px;height:52px;border-radius:50%;background:var(--acc);color:var(--on-acc);
  display:flex;align-items:center;justify-content:center;position:relative;
  box-shadow:0 6px 18px -4px color-mix(in srgb,var(--acc) 55%,transparent);
  transition:transform var(--fast) var(--ease);
}
#tabbar button.start:active .cir{transform:scale(.93)}
#tabbar button.start .cir .icn{font-size:26px;--icon-stroke:2;color:inherit;opacity:1}
#tabbar button.start span{color:var(--acc);font-weight:600}
/* `.cir` is itself a <span>, so the label rules above and below reach it too and
   outrank the `.cir` block — which is how the running state ended up painting an
   orange play glyph onto an orange disc. Both states restate their own colour.
   The disc is orange in either theme, so its glyph is black, not `--on-acc`. */
#tabbar button.start .cir{color:var(--on-acc)}
#tabbar button.start.rec .cir{background:var(--orange);color:#000;box-shadow:0 6px 18px -4px color-mix(in srgb,var(--orange) 55%,transparent)}
#tabbar button.start.rec span{color:var(--orange)}
#tabbar button.start.rec .cir::after{
  content:'';position:absolute;inset:0;border-radius:50%;
  border:2px solid var(--orange);animation:ping 1.9s var(--ease) infinite;
}
@keyframes ping{0%{transform:scale(1);opacity:.7}100%{transform:scale(1.45);opacity:0}}

/* NOTE on every backdrop-filter pair in this file: the -webkit- line comes first and the
   standard property last, which is the order a prefixed/standard pair wants — whichever is
   written last wins in the cascade, and that should be the standard name.

   Where backdrop-filter is genuinely unsupported there is no glass either — only the alpha,
   and the page shows through unblurred, which is the worst of both. Older Android WebViews
   never had it, and "reduce transparency" accessibility settings drop it. Those surfaces go
   fully opaque instead. Keep this in sync with the rules above. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  #tabbar{background:var(--bg-el)}
  :root[data-theme="light"] #tabbar{background:#f9f9fb}
  #timer{background:var(--surface)}
  #toast{background:var(--surface-2)}
}

/* ------------------------------------------------------------ week strip -- */
.week{display:flex;justify-content:space-between;gap:4px}
.wday{
  flex:1;text-align:center;padding:8px 2px 9px;border-radius:10px;
  background:none;border:none;transition:background var(--fast);
}
.wday .lbl{font-size:11px;color:var(--label-3);font-weight:500;text-transform:uppercase;letter-spacing:.03em}
.wday .num{font-size:17px;font-weight:400;margin:4px 0;letter-spacing:-.012em}
.wday .dot{width:5px;height:5px;border-radius:50%;background:transparent;margin:0 auto}
.wday .dot.plan{background:var(--label-3)}
.wday .dot.ovr{background:var(--orange)}
.wday .dot.done{background:var(--acc)}
.wday:active{background:var(--surface-2)}
.wday.today .num{
  background:var(--acc);color:var(--on-acc);font-weight:600;
  width:31px;height:31px;border-radius:50%;display:flex;align-items:center;
  justify-content:center;margin:2px auto;
}

/* ----------------------------------------------------------------- list -- */
.list{display:flex;flex-direction:column;gap:8px}
.item{
  display:flex;align-items:center;gap:12px;background:var(--surface);
  border-radius:var(--r-card);padding:10px 12px;min-height:60px;
  transition:background var(--fast);text-align:left;width:100%;
}
.item:active{background:var(--surface-2)}
.routine-list{position:relative}
.routine-drag-row{touch-action:pan-y;-webkit-touch-callout:none;position:relative;transition:transform var(--fast) var(--ease)}
.routine-list.is-reordering{user-select:none;-webkit-user-select:none}
.routine-list.is-reordering .routine-drag-row{transition:none}
.routine-drag-row.is-dragging{z-index:2;pointer-events:none}
.routine-drag-row.is-dragging .item{box-shadow:0 10px 28px rgba(0,0,0,.22);background:var(--surface-2)}
.routine-drop-indicator{
  position:absolute;left:6px;right:6px;height:3px;border-radius:99px;
  background:var(--acc);transform:translateY(-50%);pointer-events:none;z-index:3;
}
.thumb{width:50px;height:50px;border-radius:9px;object-fit:cover;background:#fff;flex:none}
/* exercise pictures are decoration inside tappable rows/cards: no save-image callout on
   a long press and no drag ghost when a scroll starts on the picture */
.thumb,.exmedia img{-webkit-touch-callout:none;-webkit-user-drag:none;user-select:none;-webkit-user-select:none}
.thumb-x{
  display:flex;align-items:center;justify-content:center;font-size:21px;
  background:var(--surface-2);color:var(--label-2);
}
.item .tt{font-size:16px;font-weight:400;line-height:1.25;letter-spacing:-.009em}
.item .ss{color:var(--label-2);font-size:13px;margin-top:2px}
.item .grow{flex:1;min-width:0}
.chev{color:var(--label);flex:none;font-size:15px;--icon-stroke:2.4}
.tag{
  display:inline-flex;align-items:center;gap:3px;background:var(--surface-2);
  color:var(--label-2);border-radius:6px;padding:3px 7px;font-size:12px;
  font-weight:500;text-transform:capitalize;
}
.tag.acc{background:var(--acc-soft);color:var(--acc)}
/* favourite marker (issue #6): a small yellow star glued to the exercise name — distinct from
   the accent "chosen" tag at the row's end, which means "already in a routine or the log" */
.fav-star{color:var(--yellow);font-size:12px;display:inline-block;margin-right:5px;vertical-align:-1px}
.fav-btn{margin-top:-4px}
.fav-btn.on{color:var(--yellow)}

/* ---------------------------------------------------------------- chips -- */
.chips{
  display:flex;gap:7px;overflow-x:auto;padding:4px 4px 6px;   /* room for a chip's focus outline inside a sheet (#162) */
  scrollbar-width:none;
}
.chips::-webkit-scrollbar{display:none}
/* horizontal strips: keep a sideways overscroll from chaining to the page and leave a
   margin when a chip is scrolled into view. The chip row also claims the horizontal axis
   (touch-action:pan-x): on a phone a slightly diagonal swipe along the chips used to hand
   the gesture to the page, which scrolled down instead. The row is 32px tall, so losing a
   vertical scroll that happens to start on it costs nothing; the ~130px heatmap wrap keeps
   both axes, there the trade-off goes the other way. The chips contain both axes: once a
   strip is at its end, a diagonal drag must not chain into the page either. */
.chips,.hm-wrap{overscroll-behavior-x:contain;scroll-padding-inline:16px}
.chips{touch-action:pan-x;overscroll-behavior:contain}
/* The chip hit-area (.chip::before, inset:-6px) must not poke out of the strip vertically:
   overflow-x:auto makes overflow-y auto as well, and that 6px of positioned overflow gave
   the 32px row a 36px scroll height — a diagonal swipe, wheel or drag then scrolled the
   whole row up by 4px and left it there. Vertical slop is clipped by the strip anyway. */
.chips .chip::before{top:0;bottom:0}
.chip{
  flex:none;padding:6px 13px;border-radius:99px;background:var(--surface);
  font-size:14px;font-weight:400;color:var(--label);text-transform:capitalize;
  letter-spacing:-.006em;transition:background var(--fast),color var(--fast);
}
.chip:active{background:var(--surface-2)}
.chip.on{background:var(--acc);color:var(--on-acc);font-weight:500}
.chip.on .dim{color:color-mix(in srgb,var(--on-acc) 62%,transparent)}
/* On a phone these rows scroll by swipe. On a pointer device lib/hchips.js lets you
   click-drag anywhere on the row to pull it along; a grab cursor on rows that actually
   overflow (data-xscroll, set by hchips.js on hover) is the hint. */
@media (hover:hover) and (pointer:fine){
  .chips[data-xscroll]{cursor:grab}
}
/* while a drag is in flight: no text selection, grabbing cursor everywhere (the `*` rule
   outweighs button{cursor:pointer} so it holds even over a chip) */
body.chips-dragging{cursor:grabbing;user-select:none;-webkit-user-select:none}
body.chips-dragging *{cursor:inherit}

/* =========================== CONTROLS ==================================== */

/* --- text field --- */
.field,.input{
  width:100%;background:var(--surface);border:none;border-radius:var(--r);
  padding:13px 15px;font-size:17px;letter-spacing:-.012em;outline:none;
  transition:box-shadow var(--fast);
}
.field::placeholder,.input::placeholder{color:var(--label-3)}
.field:focus,.input:focus{box-shadow:inset 0 0 0 2px var(--acc)}
.field.area,textarea.input{min-height:92px;resize:vertical;line-height:1.42}
.exnote{
  background:var(--surface);border-radius:var(--r);padding:13px 15px;
  line-height:1.45;white-space:pre-wrap;font-size:15px;margin-bottom:10px;color:var(--label-2);
}

/* --- search field --- */
.searchf{position:relative;display:flex;align-items:center}
.searchf .lead{
  position:absolute;left:11px;font-size:16px;color:var(--label-3);
  pointer-events:none;--icon-stroke:2.1;z-index:1;
}
.searchf .field{padding-left:35px;padding-right:36px;background:var(--surface-2);border-radius:10px}
:root[data-theme="light"] .searchf .field{background:rgba(118,118,128,.12)}
.searchf .clear{
  position:absolute;right:8px;width:22px;height:22px;border-radius:50%;
  background:var(--label-3);color:var(--bg);display:flex;align-items:center;
  justify-content:center;font-size:11px;--icon-stroke:3;
}
/* legacy .search wrapper */
.search{position:relative}
.search .input{padding-left:35px;background:var(--surface-2);border-radius:10px}
:root[data-theme="light"] .search .input{background:rgba(118,118,128,.12)}
.search>svg{
  position:absolute;left:11px;top:50%;transform:translateY(-50%);z-index:1;
  width:16px;height:16px;stroke:var(--label-3);fill:none;stroke-width:2.1;stroke-linecap:round;
}

/* --- switch --- */
.sw{
  width:51px;height:31px;border-radius:99px;background:var(--surface-3);
  flex:none;padding:2px;display:flex;align-items:center;
  transition:background var(--med) var(--ease);
}
.sw .knob{
  width:27px;height:27px;border-radius:50%;background:#fff;
  box-shadow:0 3px 8px rgba(0,0,0,.15),0 1px 1px rgba(0,0,0,.16);
  transition:transform var(--med) var(--ease),width var(--fast) var(--ease);
}
.sw.on{background:var(--acc)}
.sw.on .knob{transform:translateX(20px)}
.sw:active .knob{width:31px}
.sw.on:active .knob{transform:translateX(16px)}
.sw:disabled{opacity:.4}

/* --- segmented control --- */
/* flex, not grid: an absolutely-positioned child of a GRID container is placed
   into a grid area, so the sliding thumb resolved top/bottom against the wrong
   box and overflowed the track. A flex container leaves abspos children on the
   padding box, which is what the thumb needs. */
.seg{
  position:relative;display:flex;
  background:var(--surface-3);border-radius:9px;padding:2px;isolation:isolate;
}
.seg>button{flex:1 1 0;min-width:0}
:root[data-theme="light"] .seg{background:rgba(118,118,128,.12)}
.seg-sel{
  position:absolute;z-index:0;top:2px;bottom:2px;left:2px;
  width:calc((100% - 4px)/var(--n));
  transform:translateX(calc(100% * var(--i)));
  background:var(--surface);border-radius:7px;
  box-shadow:0 3px 8px rgba(0,0,0,.12),0 1px 1px rgba(0,0,0,.06);
  transition:transform var(--med) var(--ease);
}
:root[data-theme="light"] .seg-sel{background:#fff}
.seg button{
  position:relative;z-index:1;padding:6px 8px;font-size:14px;font-weight:500;
  letter-spacing:-.006em;color:var(--label);display:flex;align-items:center;
  justify-content:center;gap:5px;min-height:30px;transition:opacity var(--fast);
}
.seg button .icn{font-size:16px}
.seg button:not(.on){color:var(--label-2);font-weight:400}
.seg button:active{opacity:.5}
/* sitting in a list row: shrink to content instead of filling the row. The control never
   shrinks below its labels, so a row whose title and control do not both fit — most translated
   packs at 390px: "Übungs-Animationen" against "Voll · Klein · Aus" — wraps the control onto its
   own line under the title instead of painting it over the title. */
.seg-inline{flex:none;min-width:132px;max-width:100%;margin-left:auto}
.lrow:has(.seg-inline){flex-wrap:wrap}
.lrow:has(.seg-inline) .lrow-m{min-width:min(150px,100%)}
.seg-range{margin-bottom:10px}
.seg-inline button{padding:5px 10px;font-size:13px;min-height:28px}
.seg-inline button .icn{font-size:14px}

/* native time input, restyled to sit in a row like a value label */
.timef{
  background:var(--surface-2);border:none;border-radius:8px;padding:6px 10px;
  font-size:16px;color:var(--label);outline:none;font-variant-numeric:tabular-nums;
}
/* A date or time field is as wide as the browser draws it and will not give way, and neither will
   the title beside it once that is down to its longest word: the Polish "Godzina rozpoczęcia" plus
   the clock leaves a 320px row 17px short, and the field then hangs over the edge of the card with
   its picker icon. Such a row wraps the field onto a line of its own under the title instead, still
   flush right — the same way a row carrying an inline segmented control does. */
.lrow:has(.timef){flex-wrap:wrap}
.lrow>.timef{margin-left:auto}
.timef::-webkit-calendar-picker-indicator{filter:invert(.5)}
:root[data-theme="light"] .timef::-webkit-calendar-picker-indicator{filter:none}

/* --- stepper --- */
.stp-w{display:flex;flex-direction:column;gap:6px;min-width:0}
.stp-l{font-size:13px;color:var(--label-2);text-align:center}
.stp{
  display:flex;align-items:center;background:var(--surface-2);
  border-radius:10px;overflow:hidden;min-width:0;
}
.stp button{
  width:40px;height:44px;flex:none;color:var(--label);font-size:16px;
  display:flex;align-items:center;justify-content:center;
  transition:background var(--fast);--icon-stroke:2.2;
}
.stp button:active{background:var(--surface-3)}
.stp .val{
  flex:1;min-width:0;display:flex;align-items:baseline;justify-content:center;gap:3px;padding:0 2px;
  align-self:stretch;
}
.stp .val i{font-style:normal;font-size:12px;color:var(--label-2);flex:none}
.stp .num{
  width:100%;min-width:0;text-align:center;background:none;border:none;outline:none;
  font-size:17px;font-weight:500;letter-spacing:-.012em;padding:0;
  -moz-appearance:textfield;appearance:textfield;
  /* the field is the whole height of the stepper, not just its 18px text line, so a tap
     anywhere between the two buttons focuses it */
  height:100%;min-height:40px;cursor:text;
}
.stp .num::-webkit-inner-spin-button{display:none}
.stp.invalid{box-shadow:inset 0 0 0 1px var(--red)}

/* --- slider --- */
.sld{position:relative;height:32px;display:flex;align-items:center;cursor:pointer;touch-action:none}
.sld-track{
  position:absolute;left:0;right:0;height:6px;border-radius:99px;
  background:var(--surface-3);overflow:hidden;
}
.sld-fill{display:block;height:100%;background:var(--acc);border-radius:99px}
.sld-knob{
  position:absolute;width:26px;height:26px;border-radius:50%;background:#fff;
  transform:translateX(-50%);
  box-shadow:0 4px 10px rgba(0,0,0,.22),0 1px 2px rgba(0,0,0,.16);
  transition:transform var(--fast) var(--ease);
}
.sld.dragging .sld-knob{transform:translateX(-50%) scale(1.14)}

/* --- checkbox --- */
.chk,.ck{
  width:30px;height:30px;border-radius:50%;flex:none;position:relative;
  display:flex;align-items:center;justify-content:center;
  background:none;box-shadow:inset 0 0 0 1.8px var(--label-4);color:transparent;
  transition:background var(--fast),box-shadow var(--fast),color var(--fast),transform var(--fast);
}
.chk .icn{font-size:16px;--icon-stroke:2.6}
/* 30px is the right look next to a stepper but a poor target: extend the tap area to 44px
   without painting it; the left side stays shorter so the stepper's + button keeps its edge */
.chk::before,.ck::before{content:'';position:absolute;inset:-7px -7px -7px -4px}
.chk.on{background:var(--acc);box-shadow:none;color:var(--on-acc)}
.chk:active,.ck:active{transform:scale(.9)}
.ck svg{
  width:16px;height:16px;stroke:transparent;fill:none;stroke-width:2.6;
  stroke-linecap:round;stroke-linejoin:round;transition:stroke var(--fast);
}
.ck.on{background:var(--acc);box-shadow:none}
.ck.on svg{stroke:var(--on-acc)}

/* ------------------------------------------------------------- workout --- */
/* Workout header. In list mode it is pinned: pulled up over #app's top padding so it sits flush
   with the screen edge from the first pixel, and given the page's own ground plus a light blur so
   the rows scrolling underneath read as underneath. */
.whdr.stick{
  position:sticky;top:0;z-index:20;
  margin:calc(-1 * (var(--sat) + 8px)) calc(-1 * var(--pad)) 6px;
  padding:calc(var(--sat) + 8px) var(--pad) 0;
  background:color-mix(in srgb,var(--bg) 94%,transparent);
  -webkit-backdrop-filter:saturate(180%) blur(10px);backdrop-filter:saturate(180%) blur(10px);
}
.whdr.stick .hdr{margin-bottom:12px}
.whdr.stick .wprog{margin-bottom:10px}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .whdr.stick{background:var(--bg)}
}
.wprog{height:4px;background:var(--surface-2);border-radius:99px;overflow:hidden;margin-bottom:16px}
.wprog i{display:block;height:100%;background:var(--acc);border-radius:99px;transition:width var(--med) var(--ease)}
.exmedia{position:relative;border-radius:var(--r-lg);overflow:hidden;background:#fff;margin-bottom:12px}
.exmedia img{width:100%;height:320px;object-fit:contain;display:block}
.exmedia .gifhint,.exmedia .giftoggle{
  position:absolute;bottom:9px;display:inline-flex;align-items:center;gap:4px;
  background:rgba(0,0,0,.45);color:#fff;border-radius:99px;padding:5px 11px;
  font-size:12px;font-weight:500;
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
}
.exmedia .gifhint{right:9px}
.exmedia .giftoggle{left:9px}
.exmedia .gifhint .icn,.exmedia .giftoggle .icn{font-size:13px}
/* superset: both exercises are on screen together, so the animations have to give way —
   at 180px you had to scroll a full screen between two exercises done back-to-back */
.exmedia.compact img{height:120px}
.exmedia.mini img{height:84px}
/* both the animation and the still failed to load: a neutral tile instead of the browser's
   broken-image glyph; same heights as the picture so the card does not jump. tap retries. */
.exmedia.broken{background:var(--surface-2)}
.exmedia-x{width:100%;height:320px;display:flex;align-items:center;justify-content:center;color:var(--label-3);font-size:34px}
.exmedia.compact .exmedia-x{height:120px}
.exmedia.mini .exmedia-x{height:84px}

.sethead{
  display:flex;align-items:center;gap:8px;padding:0 0 6px;
  font-size:11px;color:var(--label-3);font-weight:500;text-transform:uppercase;letter-spacing:.045em;
}
.sethead .n-sp{width:24px;flex:none}
.sethead .w-sp{flex:1.4;text-align:center}
.sethead .r-sp{flex:1;text-align:center}
.sethead .eff-sp{text-align:center}
.sethead .ck-sp{width:30px;flex:none}
.setrow{display:flex;align-items:center;gap:8px;padding:7px 0;position:relative}
.setrow+.setrow::before{
  content:'';position:absolute;left:32px;right:0;top:0;height:var(--hair);background:var(--sep);
}
.setph{margin:8px 0 2px;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--dim);display:flex;align-items:center;gap:10px}
.setph::after{content:'';flex:1;height:1px;background:var(--sep)}
.setsep{height:1px;background:var(--sep);margin:9px 0}
/* the per-side wrapper carries its own .n (the set number in front of the L/R rows) */
.setrow .n,.setrow-side>.n{
  width:24px;height:24px;border-radius:50%;background:var(--surface-2);color:var(--label-2);
  display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;flex:none;
  position:relative;padding:0;border:0;font-family:inherit;cursor:pointer;
  transition:background var(--fast),color var(--fast);
}
.setrow .stp.w{flex:1.4;min-width:0}
.setrow .stp.r{flex:1;min-width:0}
/* The number outranks the buttons in every set row, not only the ones with an effort column
   that #235 covered: a 320 px phone left 0–6 px for the reps number and showed 102.5 as "102",
   and the cardio row's 10.5 km/h read "10" at 368 px (QA C2, C21, C24). The field reserves the
   widest value it shows at its font — "227.5" kg, "100" reps or "10.5" km/h (`--num`, incl.
   the field's 4 px padding and 2 px against font rounding) — and the two buttons give up width
   first, down to an 18 px floor, before anything is clipped. The cell itself is never narrower
   than number + two floors, so the row's flex hands a starving cell width from the others
   instead of clipping its buttons. */
.setrow .stp button{width:32px;height:40px}
/* Only the weight/reps buttons: `.effcell-stp` is a `.stp` too, and its value is a `<button>`,
   so a rule on `.setrow .stp button` would outrank `.effcell-stp .val` and stop the value from
   filling the cell (it bunched left with dead space next to it at desktop widths). */
.setrow .stp.w button,.setrow .stp.r button{flex:0 1 auto;min-width:var(--btn-floor)}
.setrow .stp.w,.sethead .w-sp{--num:48px}
.setrow .stp.r,.sethead .r-sp{--num:39px}
.setrow .stp.w,.setrow .stp.r,.sethead .w-sp,.sethead .r-sp{--btn-floor:18px;min-width:calc(var(--num) + 2*var(--btn-floor))}
/* no buttons (Workout controls → steppers off): the number alone is the floor. The header
   carries the same `plain` so its columns freeze where the cells do. */
.setrow .stp.plain,.sethead.plain .w-sp,.sethead.plain .r-sp{--btn-floor:0px}
.setrow .stp.w .val,.setrow .stp.r .val{min-width:var(--num)}
/* A timed hold logs the seconds in the first column and the load in the second, so the two
   columns swap roles: the load carries "227.5" and needs the wider reserve and the bigger share,
   the seconds column "120". Without the swap the load input was 35 px for a 41.7 px "102.5" at
   368 and 412 px — "102.5 kg" read "102.!" — while the seconds column sat on 67 px for "120". */
.setrow.timed .stp.w,.sethead.timed .w-sp{flex:1;--num:39px}
.setrow.timed .stp.r,.sethead.timed .r-sp{flex:1.4;--num:48px}
/* The effort column is a single tap-to-pick button, not a stepper. It is a direct flex child
   of the row (like the .stp cells), carrying its own column width via flex. `align-self` and
   a fixed height stop the row from stretching it taller than the weight/reps cells; it is NOT
   inside `.stp`, so the stepper's 32px fixed button width (which wrapped "RIR") never applies. */
/* flex-basis:0 so the button's width comes from its flex share, not its text, and the column
   never jumps between an empty "RIR" and a logged "2". The unrated state uses `.is-empty`, not
   the generic `.empty` (which is a full-page empty-state with 44px padding — sharing that name
   inflated the cell to ~90px). */
.setrow .effcell,.sethead .eff-sp{flex:.8 1 0;min-width:0}
/* The whole effort column — empty cell, logged cell and header label alike, so the row does not
   jump when a rating is added and the label does not drift — never goes below what the logged
   stepper needs at its floor: 28 px value + two 16 px buttons + the 1.5 px borders. The row's
   flex hands the difference back to weight and reps, whose own buttons shrink for it. */
.setrow .effcell,.setrow .effcell-stp,.setrow.eff3 .effcell-stp,.sethead .eff-sp{min-width:64px}
.effcell{
  box-sizing:border-box;height:44px;border-radius:10px;
  background:var(--surface-2);border:1.5px solid transparent;
  color:var(--label);font-size:15px;font-weight:600;letter-spacing:-.01em;
  font-variant-numeric:tabular-nums;white-space:nowrap;line-height:1;
  display:flex;align-items:center;justify-content:center;
  transition:background var(--fast),transform var(--fast),border-color var(--fast);
}
.effcell:active{transform:scale(.94)}
.effcell.is-empty{color:var(--label-2);font-weight:500;font-size:12px;letter-spacing:.02em}
/* a logged rating becomes a −/value/+ stepper, tinted by its effort band: the band colour
   fills the cell at low opacity (set inline via color-mix), borders it, and colours the value.
   the +/− buttons step 0.5 on the profile's scale; the value opens the picker. it carries the
   same column flex as the plain .effcell so the row does not jump when a rating is added. */
.setrow .effcell-stp,.setrow.eff3 .effcell-stp{
  height:44px;border-radius:10px;border:1.5px solid transparent;
  transition:background var(--fast),border-color var(--fast);
}
.effcell-stp button{color:inherit}
.effcell-stp>button[aria-label="Decrease"],
.effcell-stp>button[aria-label="Increase"]{width:26px;height:44px;font-size:15px;opacity:.85;flex:0 1 auto;min-width:16px}
/* the value is the tap target for the picker, so it keeps a 28 px finger's width for "8.5" and
   the −/+ shrink first — on a 368 px phone it had collapsed to 4 px under its own digits, and a
   tap on the number stepped the rating instead of opening the picker (QA C22) */
.effcell-stp .val{
  flex:1;min-width:28px;display:flex;align-items:center;justify-content:center;
  font-size:15px;font-weight:600;letter-spacing:-.01em;
  font-variant-numeric:tabular-nums;line-height:1;align-self:stretch;color:inherit;
}
.effcell-stp .val:active{background:var(--surface-3)}
/* the effort cell needs less room now (one short value, no +/- buttons), so weight/reps keep
   more of the row on narrow phones than they did when three steppers had to share it */
.setrow .effcell-stp,.setrow.eff3 .effcell-stp{flex:.8 1 0}
.setrow.eff3 .effcell-stp{flex:.7 1 0}
.setrow.eff3,.sethead.eff3{gap:6px}
.setrow.eff3 .stp.w,.sethead.eff3 .w-sp{flex:1.4}
.setrow.eff3 .stp.r,.sethead.eff3 .r-sp{flex:1.1}
.setrow.eff3 .effcell,.sethead.eff3 .eff-sp{flex:.7 1 0}
.setrow.eff3 .stp.w button,.setrow.eff3 .stp.r button{width:26px}
.setrow.eff3 .stp .num{font-size:14px}
/* the same reserved widths as a plain row's, at the smaller font */
.setrow.eff3 .stp.w,.sethead.eff3 .w-sp{--num:41px}
.setrow.eff3 .stp.r,.sethead.eff3 .r-sp{--num:30px}
.setrow.eff3 .effcell-stp>button[aria-label="Decrease"],
.setrow.eff3 .effcell-stp>button[aria-label="Increase"]{width:22px}
.setrow.eff3 .effcell-stp .val{font-size:14px}
/* effort quick picker sheet: colour-coded preset buttons, hardest (purple) first */
/* effort picker: the ⋯-menu list with the value in the icon square, tinted per band; the
   exact-value row carries the same stepper as the logged cell in the set row. */
.effpick.menu-list .menu-item .effpick-n{
  background:var(--bc);color:#fff;font-size:13px;font-weight:700;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;
}
.effpick .menu-item.on{background:color-mix(in srgb,var(--bc) 14%,var(--surface))}
.effpick .menu-on.is-on{color:var(--bc)}
.effpick .effpick-free{padding-right:8px}
.effpick .effpick-free .stp{flex:none;width:148px}
.effpick .effpick-free .stp .num{font-size:17px;font-weight:600}
.effpick .effpick-free .stp .num::placeholder{color:var(--label-3);font-weight:500}
.setrow.done .n{background:var(--acc);color:var(--on-acc)}
.setrow.done{opacity:.45}

/* one-sided (unilateral) sets (issue #60): the set number sits beside a two-row L/R stack, each
   side its own weight/reps/effort + done tick. The two inner rows reuse .setrow so their columns
   line up with the header exactly like a straight set — only the leading .n circle is replaced by
   a small L/R badge of the same width. */
.setrow-side{display:flex;align-items:center;gap:8px;padding:4px 0;position:relative}
.setrow-side+.setrow-side::before{content:'';position:absolute;left:32px;right:0;top:0;height:var(--hair);background:var(--sep)}
.setrow-side>.n{align-self:center}
.setrow-side .side-rows{flex:1;min-width:0;display:flex;flex-direction:column}
/* inner side rows: no leading number circle (the badge takes its place), no top hairline between
   the two sides of the same set — they read as one unit. */
.setrow-side .setrow.side{padding:4px 0}
.setrow-side .setrow.side+.setrow.side::before{display:none}
.sidetag{
  width:24px;height:24px;border-radius:8px;background:var(--surface-2);color:var(--label-3);
  display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;flex:none;
}
/* A one-sided row with an effort column is the tightest line in the app: set number, L/R badge,
   two steppers, effort, tick. On a narrow phone the reps stepper's two buttons took all of its
   width and the number between them was gone (issue #235, 368 px). The number outranks the
   buttons here: slimmer buttons, tighter gaps, and reps gets the same share as the weight. */
.setrow-side .setrow.side.eff3{gap:4px}
.setrow-side .setrow.side.eff3 .stp.r{flex:1.4}
.setrow-side .setrow.side.eff3 .effcell,.setrow-side .setrow.side.eff3 .effcell-stp{flex:.6 1 0}
.setrow-side .setrow.side.eff3 .stp.w button,.setrow-side .setrow.side.eff3 .stp.r button{width:20px}
/* The header is laid out like a straight row, but in front of an L/R row's weight cell sit the
   set number, its gap AND the side badge, so over per-side rows the labels stood 17–23 px left
   of their cells (QA C5). `.per-side` (set by Workout.jsx) widens the number slot by the badge
   and takes the badge's gap as its own, so header and rows share one column track; with an
   effort column it also mirrors the side rows' own shares (reps 1.4, effort .6). */
.sethead.per-side .n-sp{width:56px}
.sethead.per-side.eff3{gap:4px}
.sethead.per-side.eff3 .r-sp{flex:1.4}
.sethead.per-side.eff3 .eff-sp{flex:.6 1 0}
@media (max-width:400px){
  /* the same squeeze on a plain row, where the list view's own inset costs the last pixels */
  .setrow.eff3 .stp.w button,.setrow.eff3 .stp.r button{width:21px}
  .setrow.eff3 .stp.r,.sethead.eff3 .r-sp{flex:1.25}
  .setrow-side{gap:5px}
  /* and on every L/R row, with or without an effort column — the default profile (no effort,
     buttons on) lost the per-side reps number the same way at 320 and 368 px (QA C2, C3) */
  .setrow-side .setrow.side{gap:4px}
  .setrow-side .setrow.side .sidetag{width:20px}
  .setrow-side .setrow.side .stp .num{font-size:14px}
  .setrow-side .setrow.side .stp.w,.sethead.per-side .w-sp{--num:41px}
  .setrow-side .setrow.side .stp.r,.sethead.per-side .r-sp{--num:30px}
  .setrow-side .side-rows .setrow.side .stp.w button,.setrow-side .side-rows .setrow.side .stp.r button{width:18px}
  /* number 24 + gap 5 + badge 20; the row's 4 px gap is the header's too */
  .sethead.per-side{gap:4px}
  .sethead.per-side .n-sp{width:49px}
}
/* The effort column steps down twice on the way to a narrow screen, not once. Its −/+ are gone
   below 360 px (see the 359 px query), and from 366 px an L/R row carries them at full size in a
   sets card two insets deep — in a list unit, or in a superset card. In between it could do
   neither: the 64 px the pill needs for a 28 px value and two 16 px button floors left the row
   6, 5, 4, 3, 2 and 1 px wider than its card's content box at 360–365 px, so its done tick sat
   in the card's side padding. The −/+ give way there too, to a 12 px floor — they are what the
   cell sheds first, a pixel further down they go altogether — and the row keeps everything that
   carries meaning: the rating stays a 28 px tap target, the weight and reps columns keep their
   numbers, their buttons and their floors, and the header keeps its single line ("WEIGHT (KG)"
   has 1.5 px to spare in a 77 px column and would wrap if the weight column paid instead).
   An L/R row in a superset in the list view has no −/+ to shrink below 430 px; the rule for it
   below is more specific and keeps the cell at 34 px. */
@media (min-width:360px) and (max-width:365px){
  .setrow.side .effcell,.setrow.side .effcell-stp,.sethead.per-side .eff-sp{min-width:56px}
  .setrow.side .effcell-stp>button[aria-label="Decrease"],
  .setrow.side .effcell-stp>button[aria-label="Increase"]{min-width:12px}
}
/* An L/R row with an effort column inside a superset in the list view sits behind three insets
   (unit, superset card, sets card): at 412 px the row is 260 px wide, and with the logged
   effort's −/+ its cells want 277 (badge, tick and gaps, weight 77, reps 66, effort 64). The
   −/+ give way; the value stays, still opens the picker on tap, and the picker's exact row steps
   in halves as before. The header's effort slot follows the cell's floor.
   Only while the row is that narrow — the insets are fixed, so it is 1 px short at 428 px and
   fits from 430 px up, where it keeps the −/+ like the plain row above it. The 34 px floor
   belongs to the same query: on its own it clips the cell by 27 px. */
@media (max-width:429px){
  .wl-unit .ss-card .setrow.side .effcell-stp>button[aria-label="Decrease"],
  .wl-unit .ss-card .setrow.side .effcell-stp>button[aria-label="Increase"]{display:none}
  .wl-unit .ss-card .setrow.side .effcell,.wl-unit .ss-card .setrow.side .effcell-stp,.wl-unit .ss-card .sethead.per-side .eff-sp{min-width:34px}
}
/* Below 360 px a row with an effort column cannot hold three numbers and six buttons: with the
   set number, tick and gaps gone a card leaves ~178 px, and 102.5 / 12 / 8.5 at their floors need
   ~197. The effort −/+ give way there on every row — the value stays (26 px for "8.5" plus the
   border), still opens the picker on tap, and the picker's exact row steps in halves as before;
   weight and reps keep their buttons. */
@media (max-width:359px){
  .setrow .effcell-stp>button[aria-label="Decrease"],.setrow .effcell-stp>button[aria-label="Increase"]{display:none}
  .setrow .effcell,.setrow .effcell-stp,.setrow.eff3 .effcell-stp,.sethead .eff-sp,
  .wl-unit .ss-card .setrow.side .effcell,.wl-unit .ss-card .setrow.side .effcell-stp,.wl-unit .ss-card .sethead.per-side .eff-sp{min-width:29px}
  .setrow .effcell-stp .val{min-width:26px}
  /* an L/R row with an effort column is still over by 14 px in a card at 320 px (badge 20, 77 + 66 +
     29 for the three cells, tick 30, four gaps): one notch further there — 16 px button floors
     and a 13 px number — and it fits with two pixels to spare. Not with the buttons off (`plain`),
     where the number alone is the floor. */
  .setrow-side .setrow.side.eff3 .stp.w:not(.plain),.setrow-side .setrow.side.eff3 .stp.r:not(.plain),.sethead.per-side.eff3:not(.plain) .w-sp,.sethead.per-side.eff3:not(.plain) .r-sp{--btn-floor:16px}
  .setrow-side .setrow.side.eff3 .stp .num{font-size:13px}
  .setrow-side .setrow.side.eff3 .stp.w,.sethead.per-side.eff3 .w-sp{--num:38px}
  .setrow-side .setrow.side.eff3 .stp.r,.sethead.per-side.eff3 .r-sp{--num:28px}
  /* A weighted timed hold has one control more than a straight row (the play button before the
     tick) and was 15 px over at 320 px with the full-size floors: seconds ("120") and the load
     ("102.5") at the 14 px size and 16 px button floors, as an effort row does. */
  .setrow.timed .stp .num{font-size:14px}
  .setrow.timed .stp.w,.sethead.timed .w-sp{--num:30px}
  .setrow.timed .stp.r,.sethead.timed .r-sp{--num:41px}
  .setrow.timed .stp.w:not(.plain),.setrow.timed .stp.r:not(.plain),.sethead.timed:not(.plain) .w-sp,.sethead.timed:not(.plain) .r-sp{--btn-floor:16px}
}
.setrow.side.done .sidetag{background:var(--acc);color:var(--on-acc)}
.setrow.side.done{opacity:.45}

/* drop-set drops / rest-pause bursts riding on a work row, editable like the row itself
   (issue: drop-sets & rest-pause) */
.subrow{display:flex;align-items:center;gap:6px;padding:3px 0 3px 32px}
/* Under an L/R row the set number already sits outside the .side-rows box, so the indent that
   tucks a straight row's drops under its number would be paid twice — at 320 px both number
   fields of a per-side drop collapsed to 0 px (QA C3). The label starts under the badge instead. */
.setrow-side .side-rows .subrow{padding-left:0}
.subrow .subn{font-size:11px;color:var(--label-3);flex:none;width:46px}
/* the number outranks the buttons here as in the row above: room for "227.5" (a drop's weight)
   or "100" (the second mini is always reps) at 13 px, and the buttons shrink to 16 px first */
.subrow .stp.mini{flex:1;--num:38px;min-width:calc(var(--num) + 32px)}
.subrow .stp.mini+.stp.mini{--num:28px}
.subrow .stp.mini button{width:26px;height:30px;flex:0 1 auto;min-width:16px}
.subrow .stp.mini .val{min-width:var(--num)}
.subrow .stp.mini .num{font-size:13px;min-height:30px}
.subrow .iconbtn{width:26px;height:26px;font-size:11px;flex:none}
/* label 46, two minis at their floors 70 + 60, the ✕ and three gaps: 252 px with the indent — the
   whole row at 320 px. The label starts under the number circle's inner edge there instead. */
@media (max-width:359px){
  .subrow{padding-left:24px}
}
/* The number is the set's menu (drop / burst / remove); a 24px circle needs a finger-sized hit area. */
.setrow .n::before{content:'';position:absolute;inset:-10px}
/* No +/- buttons: the number field takes the whole cell and is the tap target. */
.stp.plain{grid-template-columns:1fr}
.stp.plain .val{width:100%}
.stp.plain .num{width:100%;text-align:center}
/* --- menu sheet (the workout's "more" menus) --- */
.menu-list .menu-item{min-height:52px;padding:8px 12px}
.menu-list .menu-item .lrow-i{width:32px;height:32px;font-size:16px;background:var(--surface-2);color:var(--label)}
.menu-list .menu-item.danger .tt,.menu-list .menu-item.danger .lrow-i{color:var(--red)}
.menu-list .menu-item.disabled{opacity:.4;pointer-events:none}
.menu-on{color:transparent;font-size:16px;flex:none}
.menu-on.is-on{color:var(--acc)}
.setextra{display:flex;flex-wrap:wrap;gap:6px;margin:2px 0 8px 32px}
.setextra .chip.add{display:inline-flex;align-items:center;gap:4px;color:var(--acc)}
.setextra .chip.add svg{width:13px;height:13px}
.setextra .chip.add:disabled{opacity:.35}
/* why the next target is what it is (issue #17) */
.progline{
  width:100%;display:flex;align-items:flex-start;gap:7px;margin:6px 0 2px;padding:0;
  text-align:left;font-size:13px;line-height:1.38;color:var(--acc);
}
.progline.warn{color:var(--yellow)}
.progline svg{flex:none;margin-top:2px}

/* start a timed set (issue #16) — sits where you'd otherwise reach for the checkbox */
.setrow .setgo{
  width:30px;height:30px;border-radius:50%;flex:none;
  display:flex;align-items:center;justify-content:center;
  background:var(--surface-2);color:var(--acc);font-size:14px;
  transition:background var(--fast),opacity var(--fast);
}
.setrow .setgo:disabled{opacity:.3;cursor:default}
.setrow .setgo:not(:disabled):active{background:var(--surface-3)}
/* exercise-config sheet: three steppers side by side on narrow phones */
.cfgrow{gap:8px}
.cfgrow>div{flex:1;min-width:0}
.cfgrow .stp button{width:30px}
.cfgrow .stp-l{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* The double-progression row holds four (Step / Reps from / Reps up to / Deload 1RM). Each stepper
   already spends 64px on its two buttons, so four abreast left the input 1px at 320 and 13px at
   368 — "1.25" showed as "1.2", "90" as "9(". Below 480px the row wraps into two pairs instead;
   from there up four abreast still leaves the input 40px or more. The basis is half the row minus
   half the gap, so each line takes exactly two. */
@media (max-width:479px){
  .cfgrow.cfgrow-4{flex-wrap:wrap}
  .cfgrow.cfgrow-4>div{flex-basis:calc(50% - 4px)}
}

/* --- rest timer --- */
#timer{
  position:fixed;left:12px;right:12px;bottom:calc(88px + var(--sab));z-index:60;
  /* nearly opaque: the set rows underneath were reading through the old 82% and made the
     clock hard to pick out mid-set. The blur stays, so it still sits above the page. */
  background:color-mix(in srgb,var(--surface) 97%,transparent);
  -webkit-backdrop-filter:saturate(180%) blur(10px);backdrop-filter:saturate(180%) blur(10px);
  border-radius:var(--r-lg);padding:12px 14px;
  display:flex;align-items:center;gap:12px;
  box-shadow:0 12px 34px -8px rgba(0,0,0,.55);
  animation:slideup var(--med) var(--ease);
}
@keyframes slideup{from{transform:translateY(16px);opacity:0}to{transform:none;opacity:1}}
#timer .t{font-size:26px;font-weight:600;letter-spacing:-.026em;font-variant-numeric:tabular-nums;min-width:66px}
#timer .bar{flex:1;height:4px;background:var(--surface-3);border-radius:99px;overflow:hidden}
#timer .bar i{display:block;height:100%;background:var(--acc);transition:width 1s linear}
/* rest variant: −15/+15/Skip and the clock won't share one line on a phone, so the clock and
   bar take the top row and the controls take their own. The work timer keeps a single row —
   it only ever has two buttons. */
#timer.rest{flex-direction:column;align-items:stretch;gap:10px}
#timer.rest .head{display:flex;align-items:center;gap:12px}
#timer.rest .acts{display:flex;align-items:center;gap:8px}
#timer.rest .acts .btn{padding-top:11px;padding-bottom:11px}   /* sweaty hands, mid-set */
#timer.rest .acts .skip{margin-left:auto;min-width:84px}
/* work timer (issue #16): the same bar doing the opposite job — outlined and tinted so a
   glance tells "you are holding this" apart from "you are recovering". */
#timer.working{border:var(--hair) solid var(--acc)}
#timer.working .t{color:var(--acc)}
#timer.working .grow{flex:1;min-width:0}
#timer.working .lbl{
  font-size:12px;color:var(--label-2);margin-bottom:5px;text-transform:capitalize;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* ---------------------------------------------------------------- modal -- */
#modal-root{position:fixed;inset:0;z-index:100;display:none}
#modal-root.open{display:block}
.mback{
  position:absolute;inset:0;background:rgba(0,0,0,.4);
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);
  touch-action:none;overscroll-behavior:none;
}
.sheet{
  position:absolute;left:0;right:0;bottom:0;background:var(--bg-el);
  border-radius:var(--r-xl) var(--r-xl) 0 0;
  padding:8px 18px calc(20px + var(--sab));
  /* A tall sheet stops short of the status bar / Dynamic Island: every cap carries the top
     safe-area inset, which the layout viewport does not (viewport-fit=cover). */
  max-height:90vh;max-height:min(90vh,calc(100dvh - var(--sat) - 8px));
  overflow-y:auto;scroll-padding-bottom:calc(20px + var(--sab));
  animation:sheetup .34s var(--ease);
  overscroll-behavior:contain;touch-action:pan-y;will-change:transform;
}
.sheet:has(.picker-search){
  bottom:var(--picker-keyboard-bottom,0px);
  /* with the keyboard up the sheet is capped by the visual viewport — which still starts
     under the notch, hence the inset here too */
  max-height:min(90vh,calc(100dvh - var(--sat) - 8px),calc(var(--picker-visual-height,100vh) - var(--sat) - 8px));
}
:root[data-theme="light"] .sheet{background:var(--bg)}
@keyframes sheetup{from{transform:translateY(100%)}to{transform:none}}
.sheet .grab{width:36px;height:5px;border-radius:99px;background:var(--label-4);margin:6px auto 14px}
.sheet h3{font-size:20px;font-weight:600;letter-spacing:-.021em;margin-bottom:14px}
.picker-search{
  position:sticky;top:0;z-index:2;margin-bottom:0;padding-bottom:10px;
  background:var(--bg-el);
}
:root[data-theme="light"] .picker-search{background:var(--bg)}
.center{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:min(84vw,300px);background:var(--bg-el);border-radius:var(--r-lg);padding:20px;
  max-height:calc(100dvh - 2*var(--sat) - 24px);overflow-y:auto;
  box-shadow:0 20px 60px -12px rgba(0,0,0,.5);
  animation:pop .28s var(--ease);
}
:root[data-theme="light"] .center{background:#fff}
@keyframes pop{from{transform:translate(-50%,-50%) scale(.94);opacity:0}to{transform:translate(-50%,-50%) scale(1);opacity:1}}

/* --- RIR/RPE conversion table (effort help sheet) ---
   The two scales only click when you see them side by side, so the numbers get fixed-width
   tabular columns you can read straight down, and the words take whatever is left. Built out
   of the same grouped-list parts as the rest of the app (surface fill, inset hairlines) rather
   than a real <table>, so it inherits the card look and wraps properly on a narrow phone. */
.efftbl{background:var(--surface);border-radius:var(--r-lg);overflow:hidden;margin:14px 0 12px}
.efftbl .r{display:flex;align-items:center;gap:10px;padding:10px 14px;position:relative}
.efftbl .r+.r::before{
  content:'';position:absolute;left:14px;right:0;top:0;height:var(--hair);background:var(--sep);
}
.efftbl .n{
  width:36px;flex:none;text-align:center;font-size:17px;font-weight:600;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums;
}
.efftbl .f{flex:1;min-width:0;font-size:15px;color:var(--label-2);line-height:1.3}
/* the header names the columns without competing with them */
.efftbl .hd{background:var(--surface-2);padding-top:8px;padding-bottom:8px}
.efftbl .hd .n,.efftbl .hd .f{
  font-size:11px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;
  color:var(--label-3);
}
/* the row a working set usually lands on — the anchor the others are read against */
.efftbl .r.on{background:var(--acc-soft)}
.efftbl .r.on .n{color:var(--acc)}
.efftbl .r.on .f{color:var(--label)}

/* --- glyph picker (replaces the emoji grid) --- */
.glyph-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:9px}
.glyph-cell{
  aspect-ratio:1;border-radius:13px;background:var(--surface);
  display:flex;align-items:center;justify-content:center;font-size:24px;
  color:var(--label);transition:background var(--fast),color var(--fast),transform var(--fast);
}
.glyph-cell:active{transform:scale(.92)}
.glyph-cell.on{background:var(--acc);color:var(--on-acc)}

/* --- big weight readout --- */
.bwstep{display:flex;align-items:center;justify-content:center;gap:18px;margin:14px 0 6px}
.bw-pm{
  width:46px;height:46px;border-radius:50%;background:var(--surface);flex:none;
  color:var(--label);display:flex;align-items:center;justify-content:center;font-size:19px;
  transition:background var(--fast),transform var(--fast);--icon-stroke:2.2;
}
.bw-pm:active{background:var(--surface-2);transform:scale(.92)}
.bw-read{
  font-size:52px;font-weight:600;letter-spacing:-.035em;min-width:158px;text-align:center;
  font-variant-numeric:tabular-nums;line-height:1;
}
.bw-read .u{font-size:19px;color:var(--label-2);font-weight:400;letter-spacing:-.01em}
.bw-read .num{
  display:inline-block;vertical-align:baseline;background:none;border:none;outline:none;
  padding:0;margin:0;color:inherit;font:inherit;letter-spacing:inherit;
  font-variant-numeric:tabular-nums;text-align:center;cursor:text;
  -moz-appearance:textfield;appearance:textfield;
}
.bwin{display:flex;align-items:baseline;justify-content:center;gap:7px;margin:16px 0}
.bwin input{
  width:150px;background:none;border:none;outline:none;text-align:right;
  font-size:52px;font-weight:600;letter-spacing:-.035em;color:var(--label);
}
.bwin span{color:var(--label-2);font-size:19px}

/* --------------------------------------------------------------- charts -- */
.chart{width:100%;overflow:hidden}
.chart svg{display:block;width:100%;height:auto}
.chart-i{position:relative;touch-action:pan-y}
/* left/top are written by LineChart after measuring the label, so it can never be
   pushed under the `.chart` clip at either edge — hence no offset here. */
.ctip{
  position:absolute;left:0;top:0;background:var(--surface-2);
  border-radius:8px;padding:4px 10px;font-size:12px;font-weight:500;white-space:nowrap;
  max-width:calc(100% - 8px);overflow:hidden;text-overflow:ellipsis;
  pointer-events:none;box-shadow:0 6px 18px -4px rgba(0,0,0,.4);
}

/* --- activity heatmap --- */
.hm-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;padding-bottom:2px}
.hm-wrap::-webkit-scrollbar{display:none}
.hm-months{display:flex;margin-left:28px;margin-bottom:5px}
.hm-months span{flex:none;width:14px;font-size:11px;color:var(--label-3);white-space:nowrap;overflow:visible}
.hm-body{display:flex}
.hm-days{display:flex;flex-direction:column;gap:3px;flex:none;width:28px}
.hm-days span{height:11px;font-size:10px;color:var(--label-2);line-height:11px}
.hm-grid{display:flex;gap:3px}
.hm-col{display:flex;flex-direction:column;gap:3px}
.hm-c{width:11px;height:11px;border-radius:3px;background:var(--surface-2);flex:none}
.hm-c.l1{background:color-mix(in srgb,var(--acc) 30%,var(--surface-2))}
.hm-c.l2{background:color-mix(in srgb,var(--acc) 55%,var(--surface-2))}
.hm-c.l3{background:color-mix(in srgb,var(--acc) 78%,var(--surface-2))}
.hm-c.l4{background:var(--acc)}
.hm-c.today{box-shadow:0 0 0 1.5px var(--acc)}
.hm-c.future{opacity:.3}
.hm-legend{
  display:flex;align-items:center;gap:4px;justify-content:flex-end;margin-top:9px;
  font-size:11px;color:var(--label-3);
}
.hm-legend .hm-c{width:10px;height:10px}

/* --- muscle map --- */
/* Reuses the .hm-c level ramp above, so one accent scale means one thing app-wide. */
/* An untrained muscle is derived from the text colour rather than a fixed surface, so
   the body keeps the same contrast in both themes — pinned to --surface-2 it was all
   but invisible on a white card. */
.bodymap{
  display:flex;gap:6px;justify-content:center;align-items:flex-start;
  --bm-base:color-mix(in srgb,var(--label) 11%,var(--surface));
}
.bm-v{flex:1;min-width:0;height:auto;max-height:min(46vh,340px)}
.bm-ph{height:200px}                       /* holds the space while the geometry loads */
.bm-sil{fill:color-mix(in srgb,var(--label) 18%,var(--surface))}
.bm-m{fill:var(--bm-base);transition:fill var(--med) var(--ease)}
.bm-m.l1{fill:color-mix(in srgb,var(--acc) 32%,var(--bm-base))}
.bm-m.l2{fill:color-mix(in srgb,var(--acc) 56%,var(--bm-base))}
.bm-m.l3{fill:color-mix(in srgb,var(--acc) 78%,var(--bm-base))}
.bm-m.l4{fill:var(--acc)}
/* Fatigue view: attention ramp - fatigued muscles highlighted (owner tweak 2026-08-06) */
.hm-fatigue .bm-m.l4{fill:var(--red)}
.hm-fatigue .bm-m.l3{fill:var(--orange)}
.hm-fatigue .bm-m.l2{fill:var(--yellow)}
.hm-fatigue .bm-m.l1{fill:color-mix(in srgb,var(--yellow) 32%,var(--bm-base))}
.hm-fatigue .hm-c.l4{background:var(--red)}
.hm-fatigue .hm-c.l3{background:var(--orange)}
.hm-fatigue .hm-c.l2{background:var(--yellow)}
/* Strength view: top band pops gold (owner tweak 2026-08-06) */
.hm-strength .bm-m.l4{fill:var(--yellow);filter:drop-shadow(0 0 1.5px var(--yellow))}
.hm-strength .hm-c.l4{background:var(--yellow)}

.bm-m.sel{stroke:var(--label);stroke-width:7}
.bodymap.tappable .bm-m{cursor:pointer}
.bodymap.tappable .bm-m:focus-visible{outline:none;stroke:var(--label);stroke-width:7;filter:drop-shadow(0 0 2px var(--surface))}
/* A hairline in the surface colour separates neighbouring muscles; the artwork has no
   outline path of its own, so without this the body reads as one flat blob. */
.bm-v path{stroke:var(--surface);stroke-width:2.5;stroke-linejoin:round}

.mrow{display:flex;align-items:center;gap:9px;padding:5px 0}
.mrow .nm{flex:1;min-width:0;font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mrow .bar{width:74px;height:5px;border-radius:3px;background:var(--surface-2);flex:none;overflow:hidden}
.mrow .bar i{display:block;height:100%;background:var(--acc);border-radius:3px}
.mrow .v{font-size:12px;color:var(--label-2);min-width:52px;text-align:right;flex:none}
/* A headline number inside a card — tile weight without a tile around it, for the pair of
   readings at the top of the effort card. */
.stat-v{font-size:26px;font-weight:600;letter-spacing:-.026em;line-height:1.1}
.mchips{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}
.mchip{font-size:12px;padding:4px 9px;border-radius:99px;background:var(--surface-2);color:var(--label-2)}
.mchip.miss{background:color-mix(in srgb,var(--orange) 16%,transparent);color:var(--orange)}

/* --- stat tiles --- */
.tiles{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:12px}
.tile{background:var(--surface);border-radius:var(--r-card);padding:14px}
.tile .l{
  color:var(--label-2);font-size:13px;font-weight:400;letter-spacing:-.004em;
  text-transform:none;display:flex;align-items:center;gap:5px;
}
.tile .l .icn{font-size:14px;color:var(--label)}
.tile .v{font-size:26px;font-weight:600;letter-spacing:-.026em;margin-top:5px;line-height:1.1}
.tile.tappable:active{background:var(--surface-2)}

/* --- PR badge --- */
.pr{
  display:inline-flex;align-items:center;gap:4px;
  background:color-mix(in srgb,var(--yellow) 18%,transparent);color:var(--yellow);
  border-radius:6px;padding:3px 8px;font-size:12px;font-weight:500;
}
.pr .icn{font-size:13px}

/* --- toast --- */
#toast{
  position:fixed;left:50%;transform:translateX(-50%) translateY(6px);
  bottom:calc(96px + var(--sab));z-index:200;
  background:color-mix(in srgb,var(--surface-2) 88%,transparent);
  -webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px);
  border-radius:99px;padding:11px 20px;font-size:15px;font-weight:500;
  box-shadow:0 10px 30px -6px rgba(0,0,0,.5);
  opacity:0;pointer-events:none;transition:opacity var(--med),transform var(--med) var(--ease);
  max-width:88vw;text-align:center;
}
#toast.show{opacity:1;transform:translateX(-50%) translateY(0)}

/* ---------------------------------------------------------------- misc --- */
.empty{text-align:center;color:var(--label-2);padding:44px 20px;font-size:15px;line-height:1.45}
.empty .ico{font-size:34px;color:var(--label-2);margin-bottom:12px;display:flex;justify-content:center}
.steps-list{
  padding-left:18px;color:var(--label-2);font-size:15px;line-height:1.5;
  display:flex;flex-direction:column;gap:9px;
}
.steps-list::marker{color:var(--label-3)}

/* --- month calendar --- */
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:5px;margin-top:10px}
.cal-h{text-align:center;font-size:11px;color:var(--label-3);font-weight:500;text-transform:uppercase;padding:2px 0}
.cal-d{
  aspect-ratio:1;border-radius:10px;background:var(--surface);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  font-weight:400;font-size:15px;color:var(--label);transition:background var(--fast);
}
.cal-d:active{background:var(--surface-2)}
.cal-d.has{background:var(--acc-soft);color:var(--acc)}
.cal-d.today{box-shadow:inset 0 0 0 1.8px var(--acc)}
.cal-d i{width:5px;height:5px;border-radius:50%;background:transparent}
.cal-d i.done{background:var(--acc)}
.cal-d i.plan{background:var(--label-3)}
.cal-d i.ovr{background:var(--orange)}
.cal-legend{display:flex;gap:14px;justify-content:center;margin-top:12px;font-size:12px;color:var(--label-3)}
.cal-legend i{display:inline-block;width:6px;height:6px;border-radius:50%;margin-right:5px}

/* --- accent swatches --- */
.swatches{display:flex;gap:12px;flex-wrap:wrap}
.swatch{width:32px;height:32px;border-radius:50%;flex:none;position:relative;transition:transform var(--fast)}
.swatch:active{transform:scale(.9)}
.swatch.on::after{content:'';position:absolute;inset:-4px;border-radius:50%;box-shadow:0 0 0 2px var(--label)}

/* --- supersets --- */
.ss-label{
  font-size:12px;font-weight:600;letter-spacing:-.004em;text-transform:none;
  color:var(--acc);margin:8px 0 5px 4px;display:flex;align-items:center;gap:5px;
}
.ss-label .icn{font-size:13px}
.item.in-ss{box-shadow:inset 3px 0 0 var(--acc)}
.ss-card{
  border-radius:var(--r-lg);padding:14px;
  background:var(--surface);box-shadow:inset 0 0 0 1.5px var(--acc-line);
}
.workout-swipe-surface{touch-action:pan-y}
/* A superset nests a card inside the page's own gutter, so its inset is paid twice. On a
   narrow phone that left the weight and reps steppers too tight to show a three-digit
   number — reported as "the reps textbox becomes too small when superset on mobile". The
   card only gives up its own padding; the rows inside keep their spacing.
   The give-back runs to 404 px rather than 400, because it may not end before the full insets
   fit: at 401 px they snapped back to 16 + 14 + 14 per side and took 48 px off the row while the
   screen had gained one, so a plain row with an effort column in a superset in the list view —
   285 px of cells in a 281 px card — was 4, 3, 2 and 1 px wider than its card's content box at
   401–404 px and its done tick sat in the card's side padding. 405 px is the width where those
   285 px and the three full insets first add up to the screen, so that is where it ends. */
@media (max-width:404px){
  .ss-card{padding:10px 8px}
  /* The sets card nested in a superset card or a list unit pays a second inset, and in a superset
     in the list view a third; with an L/R row's set number, badge, two steppers, effort and tick
     it is the line that decides whether the numbers fit. 8 px each, and the superset card inside
     a unit keeps 4 (none below 360), so every set row has the same 256 px at 320 as in a plain
     card, and 296–304 at 368. */
  .wl-unit .card,.ss-card .card{padding-left:8px;padding-right:8px}
  .wl-unit .ss-card{padding-left:4px;padding-right:4px}
}
@media (max-width:359px){
  .wl-unit .ss-card{padding-left:0;padding-right:0}
}
.ss-hd{
  font-size:12px;font-weight:600;color:var(--acc);margin-bottom:12px;
  text-align:center;display:flex;align-items:center;justify-content:center;gap:5px;
}
.ss-ex{position:relative}
.ss-amp{text-align:center;font-size:15px;font-weight:600;color:var(--acc);margin:14px 0 8px}

/* --- workout list view: every unit stacked, the current one outlined --- */
/* minmax(0, …): a grid's default `auto` track is at least as wide as its widest content, so a set
   row whose cells have floors (see .setrow .stp) would widen the whole unit past the screen and
   push the ticks off it. Capped, a row that does not fit overflows its own card instead. */
.workout-list{display:grid;grid-template-columns:minmax(0,1fr);gap:14px}
.wl-unit{
  border-radius:var(--r-lg);padding:14px 14px 4px;
  background:var(--surface-2);
}
/* scrolled to when the list opens (#224): clear the sticky header above it. Workout.jsx
   measures the header (--whdr-h on .workout-list, safe area included) because it grows when
   the session name wraps; the fallback is the height of a one-line header. */
.wl-unit{scroll-margin-top:calc(var(--whdr-h, var(--sat) + 80px) + 16px)}
.wl-unit.cur{box-shadow:inset 0 0 0 1.5px var(--acc-line)}
.wl-hd{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:10px}
/* part of the give-back above — one edge for all three insets of a row in the list view */
@media (max-width:404px){
  .wl-unit{padding:10px 8px 2px}
}

/* --- home: today's session row --- */
.today-row{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-top:12px;padding:12px 14px;border-radius:var(--r);background:var(--surface-2);
  transition:background var(--fast);width:100%;text-align:left;cursor:pointer;
}
.today-row:active{background:var(--surface-3)}
.today-row .lbl2{font-size:11px;font-weight:500;letter-spacing:.03em;text-transform:uppercase;color:var(--label-3)}
.today-row .ttl{
  font-weight:500;font-size:17px;line-height:1.25;text-transform:capitalize;
  letter-spacing:-.012em;margin-top:2px;
  /* two lines before the ellipsis: "Leg Day — in progress" grows past one line in hu/tr/th/pt-BR */
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;
}

/* Only where a pointer really hovers — on a phone :hover sticks to the row after the tap.
   Lighter than :active, which goes all the way to --surface-3, so the two stay distinct. */
@media (hover:hover){
  .today-row:hover{background:color-mix(in srgb,var(--surface-2),var(--surface-3) 60%)}
  :root[data-theme="light"] .today-row:hover{background:color-mix(in srgb,var(--surface-2),var(--surface-3) 85%)}
}

/* --------------------------------------------------- desktop (≥1000px) --- */
.cols{display:block}
@media (min-width:1000px){
  #app{max-width:1080px;padding-top:32px;padding-bottom:calc(128px + var(--sab))}
  body.resting #app{padding-bottom:calc(250px + var(--sab))}
  .workout-end-spacer{height:40px}
  .cols{display:grid;grid-template-columns:1fr 1fr;gap:14px;align-items:start}
  .cols>*{min-width:0}
  #app .list{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  #modal-root .list,.narrow .list{display:flex;flex-direction:column}
  .narrow{max-width:640px;margin:0 auto}
  .tiles{grid-template-columns:repeat(4,1fr)}
  .cols .tiles,.center .tiles{grid-template-columns:1fr 1fr}   /* a 300px dialog has no room for four */
  #tabbar{
    left:50%;right:auto;bottom:16px;transform:translateX(-50%);width:520px;
    border:var(--hair) solid var(--sep-op);border-radius:var(--r-xl);
    padding:7px 10px 9px;box-shadow:0 12px 40px -10px rgba(0,0,0,.5);
  }
  #tabbar button.start{margin-top:-26px}
  .sheet{left:50%;right:auto;margin-left:-320px;width:640px;border-radius:var(--r-xl) var(--r-xl) 0 0}
  .center{width:340px}
  #timer{left:50%;right:auto;margin-left:-260px;width:520px;bottom:112px}
  /* 520px fits the clock, the bar and all three controls on one line again */
  #timer.rest{flex-direction:row;align-items:center;gap:14px}
  #timer.rest .head{flex:1;min-width:0}
  .exmedia img{height:380px}
  .hm-wrap{display:flex;flex-direction:column;align-items:center}
}

/* ------------------------------------------------------- gym check-in -- */
/* Mobile-only feature (views/CheckIn.jsx): saved membership codes shown as QR, swiped
   through horizontally. The rail is a scroll-snap track — one card per viewport, no JS
   carousel — with a trailing "+" card to add another. */
.ci-rail{
  display:flex;gap:14px;overflow-x:auto;scroll-snap-type:x mandatory;
  -webkit-overflow-scrolling:touch;scrollbar-width:none;
  padding:4px 0 8px;margin:0 -16px;padding-left:16px;padding-right:16px;
}
.ci-rail::-webkit-scrollbar{display:none}
.ci-card{
  scroll-snap-align:center;flex:0 0 100%;box-sizing:border-box;
  background:var(--surface);border-radius:var(--r-xl);padding:22px 18px;
  display:flex;flex-direction:column;align-items:center;gap:14px;
  transition:transform var(--fast),box-shadow var(--fast),opacity var(--fast);
}
/* header row: edit — title — trash. The two icon buttons are equal fixed widths so the title,
   flexed between them, stays optically centered on the card no matter how long it is. */
.ci-card-hd{display:flex;align-items:center;gap:8px;width:100%}
.ci-card-btn{width:30px;height:30px;font-size:14px;flex:none}
.ci-card .ci-label{flex:1;min-width:0;font-size:19px;font-weight:600;letter-spacing:-.014em;text-align:center;overflow-wrap:anywhere}
.ci-card .ci-value{font-size:14px;color:var(--label-2);word-break:break-all;text-align:center;font-variant-numeric:tabular-nums}
/* reorder row under a card (only shown with >1 card): ◀ position ▶ to nudge the card one slot
   along the rail. A plain, reliable control — no drag gesture to fight the horizontal scroll. */
.ci-reorder{display:flex;align-items:center;justify-content:center;gap:14px;margin-top:2px}
.ci-reorder .ci-pos{font-size:13px;color:var(--label-2);font-variant-numeric:tabular-nums;min-width:44px;text-align:center}
.ci-reorder .iconbtn:disabled{opacity:.3;pointer-events:none}
/* The QR itself: lean-qr paints 1 module per pixel, so scale it up with the browser's
   nearest-neighbour so every module stays a crisp square instead of a blurred blob. White
   quiet-zone padding is baked in by the renderer; the plate underneath just frames it. */
.ci-qr-plate{background:#fff;border-radius:var(--r-lg);padding:16px}
.qr-canvas{display:block;image-rendering:pixelated;image-rendering:crisp-edges;transition:opacity var(--fast)}
/* the trailing add card — a big + on a dashed outline, same footprint as a real card */
.ci-add{
  scroll-snap-align:center;flex:0 0 100%;box-sizing:border-box;
  min-height:280px;border-radius:var(--r-xl);
  border:2px dashed var(--surface-3);background:none;color:var(--label-2);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;
}
.ci-add:active{background:var(--surface);transform:scale(.99)}
.ci-add .icn{font-size:40px;--icon-stroke:1.8}
.ci-add .ci-add-t{font-size:16px;font-weight:500}
/* dots under the rail — which card you're on. Purely a hint; the rail itself is the control. */
.ci-dots{display:flex;justify-content:center;gap:7px;margin-top:4px}
.ci-dot{width:7px;height:7px;border-radius:50%;background:var(--surface-3);transition:background var(--fast),transform var(--fast)}
.ci-dot.on{background:var(--acc);transform:scale(1.15)}
/* browser camera sheet (components/CameraScan.jsx): the video fills a portrait plate, a dashed
   square in the middle says "put the code here" — decoding reads the whole frame regardless. */
.cam-wrap{position:relative;width:100%;aspect-ratio:3/4;max-height:58vh;border-radius:var(--r-lg);overflow:hidden;background:#000}
.cam-wrap video{width:100%;height:100%;object-fit:cover;display:block}
.cam-frame{position:absolute;inset:0;margin:auto;width:62%;aspect-ratio:1;border:2px dashed rgba(255,255,255,.75);border-radius:14px;pointer-events:none}
/* ------------------------------------------------- the Coach entry on Plan -- */
.coach-cta{
  display:flex;align-items:center;gap:13px;width:100%;text-align:left;
  margin-bottom:12px;padding:14px 16px;border-radius:var(--r-card);
  background:linear-gradient(135deg,var(--acc-soft),color-mix(in srgb,var(--acc) 6%,var(--surface)));
  border:1px solid color-mix(in srgb,var(--acc) 35%,transparent);
  transition:transform var(--fast),filter var(--fast)
}
.coach-cta:active{transform:scale(.985);filter:brightness(1.06)}
.coach-cta-av{
  width:42px;height:42px;border-radius:13px;flex:none;display:grid;place-items:center;font-size:21px;
  background:var(--acc);color:var(--on-acc);box-shadow:0 6px 18px -6px color-mix(in srgb,var(--acc) 60%,transparent)
}
.coach-cta-t{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.coach-cta-t b{font-size:17px;font-weight:600;letter-spacing:-.015em;color:var(--label)}
.coach-cta-t span{font-size:13px;color:var(--label-2);line-height:1.35}
.coach-cta-chev{color:var(--acc);font-size:15px;flex:none}

/* Setvo personal-site identity and accessible account forms. */
.setvo-login{max-width:420px;padding-top:clamp(28px,7vh,80px);padding-bottom:70px;text-align:center}
.setvo-wordmark{display:flex;align-items:center;justify-content:center;gap:12px;color:var(--acc);font-size:44px;font-weight:800;letter-spacing:-1.5px}
.setvo-wordmark>span{color:var(--label-1)}
.setvo-label{display:block;font-size:13px;font-weight:600;margin:12px 0;color:var(--label-2)}
.setvo-label .input{display:block;width:100%;margin-top:6px;min-height:46px}
.setvo-text-button{border:0;padding:8px;background:none;color:var(--acc);font:inherit;font-size:13px;cursor:pointer}
.setvo-error{border:1px solid var(--red);border-radius:10px;padding:12px;margin:12px 0;font-size:13px;color:var(--red)}
:focus-visible{outline:2px solid var(--acc);outline-offset:3px}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}

/* Setvo installed-app touch behavior. Browser/OS accessibility overrides still apply. */
html, body { touch-action: pan-x pan-y; overscroll-behavior-x: none; }
@media (pointer: coarse) {
  input:not([type="checkbox"]):not([type="radio"]), textarea, select { font-size: 16px !important; }
  button, a, [role="button"] { touch-action: manipulation; }
}
.setvo-contact a { display: inline-block; padding: 10px 14px; }

/* Setvo official S + dumbbell brand mark */
.setvo-brand-icon{
  width: 31px !important;
  height: 31px !important;
  display: inline-block !important;
  flex: 0 0 31px;
  background: url('../branding/setvo-brand-mark.svg') center/contain no-repeat !important;
  transform: none !important;
}

.setvo-brand-icon i{
  display: none !important;
}

/* Hide the old wireframe elements inside the phone bezel */
.preview-phone > :not(.phone-status):not(.home-indicator) {
  display: none !important;
}

/* Style the phone bezel and use flex column ordering */
.preview-phone {
  display: flex !important;
  flex-direction: column !important;
  background: #000000 !important;
  padding: 14px 10px 8px !important;
  border-color: #38383a !important;
  box-shadow: 0 0 0 5px #121214, 0 0 0 6px #2c2c2e, 0 32px 70px #000c !important;
}

/* 1. Keep status bar (9:41 & dots) at the very top */
.preview-phone .phone-status {
  order: 1 !important;
  margin: 2px 12px 8px !important;
  color: #ffffff !important;
}

/* 2. Place screenshot in the middle from the branding folder */
.preview-phone::before {
  content: "";
  order: 2 !important;
  display: block;
  width: 100%;
  aspect-ratio: 1170 / 2532;
  background: url("../branding/home-hero.png") top center / cover no-repeat;
  border-radius: 16px 16px 24px 24px;
  margin-bottom: 8px;
}

/* 3. Keep the home indicator bar at the very bottom */
.preview-phone .home-indicator {
  order: 3 !important;
  margin: 0 auto !important;
}