/** Shopify CDN: Minification failed

Line 1094:0 Unexpected "}"

**/
@import url("https://fonts.googleapis.com/css2?family=Jost:ital,wght@0,400;0,500;0,600;1,400&display=swap");
/* PDP v3 — Touch 2 alternate template. Namespaced: only applies inside .pdp-v3 wrappers.
   Source of truth: touch2-pdp-v3_mockup.html. Do not edit Mode core files for v3 work. */
.pdp-v3{
  --ink:#181713; --ink2:#45423b; --mut:#6a665c; --line:#e7e1d4;
  --bg:#ffffff; --cream:#F4F3F4; --cream2:#F4F3F4; --gold:#a9802d; --gold-lt:#f7f0dc;
  --green:#1e7b45; --red:#b0472e; --amber:#b06a12; --radius:10px;
  --max:1180px;
}.pdp-v3 *{box-sizing:border-box;margin:0;padding:0}.pdp-v3 h1, .pdp-v3 h2, .pdp-v3 h3, .pdp-v3 h4, .pdp-v3 h5, .pdp-v3 p, .pdp-v3 a, .pdp-v3 li, .pdp-v3 th, .pdp-v3 td, .pdp-v3 summary, .pdp-v3 button, .pdp-v3 input, .pdp-v3 select, .pdp-v3 textarea{font-family:inherit;text-transform:none;letter-spacing:normal}.pdp-v3 h1, .pdp-v3 h2, .pdp-v3 h3{color:var(--ink)}.pdp-v3{font-family:"Jost","Lato",-apple-system,"Segoe UI",Helvetica,Arial,sans-serif;color:var(--ink);background:var(--bg);line-height:1.5;-webkit-font-smoothing:antialiased}.pdp-v3 img{max-width:100%;display:block}.pdp-v3 .wrap{max-width:var(--max);margin:0 auto;padding:0 20px}.pdp-v3 .eyebrow{font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:var(--mut);font-weight:600}.pdp-v3 h2{font-size:clamp(30px,3.2vw,46px);line-height:1.12;letter-spacing:-.02em;font-weight:600}.pdp-v3 h3{font-size:17px;font-weight:600;letter-spacing:-.01em}.pdp-v3 .sec{padding:72px 0;border-top:1px solid var(--line)}.pdp-v3 .sec.cream{background:var(--cream)}.pdp-v3 .center{text-align:center}.pdp-v3 .lede{font-size:16px;color:var(--ink2);max-width:640px}.pdp-v3 .center .lede{margin-left:auto;margin-right:auto}

/* ANNOUNCEMENT + NAV */.pdp-v3 .announce{background:#141310;color:#fff;font-size:12.5px;text-align:center;padding:9px 16px;letter-spacing:.02em}.pdp-v3 .announce b{color:#f0d488}.pdp-v3 .topnav{border-bottom:1px solid var(--line);position:sticky;top:0;background:rgba(255,255,255,.97);backdrop-filter:blur(8px);z-index:60}.pdp-v3 .topnav .wrap{display:flex;align-items:center;gap:28px;height:56px}.pdp-v3 .logo{font-weight:600;letter-spacing:.22em;font-size:15px}.pdp-v3 .subnav{display:flex;gap:22px;margin-left:auto;font-size:12.5px;font-weight:500;letter-spacing:.04em;text-transform:uppercase;overflow-x:auto}.pdp-v3 .subnav a{color:var(--ink2);text-decoration:none;white-space:nowrap;padding:4px 0;border-bottom:2px solid transparent}.pdp-v3 .subnav a:hover{color:var(--ink);border-color:var(--ink)}

/* HERO */.pdp-v3 .hero{padding:34px 0 44px}.pdp-v3 .hero-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:52px;align-items:start}.pdp-v3 .gallery{position:sticky;top:74px}.pdp-v3 .shot{flex-direction:column;gap:5px;background:var(--cream);border:1px solid var(--line);border-radius:var(--radius);aspect-ratio:1/1;display:flex;align-items:center;justify-content:center;color:#a9a294;font-size:13px;text-align:center;padding:24px}.pdp-v3 .thumbs{display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin-top:8px}.pdp-v3 .thumbs .shot{flex-direction:row;aspect-ratio:1/1;font-size:10px;border-radius:6px;padding:6px}.pdp-v3 .stars{color:#a9802d;letter-spacing:1px;font-size:13px}.pdp-v3 .rating-row{display:flex;align-items:center;gap:9px;flex-wrap:wrap;font-size:12.5px;color:var(--mut);margin-bottom:12px}.pdp-v3 .rating-row b{color:var(--ink)}.pdp-v3 .badge-1{background:#141310;color:#fff;font-size:10.5px;font-weight:600;letter-spacing:.1em;padding:3px 8px;border-radius:3px;text-transform:uppercase}.pdp-v3 h1{font-size:15px;font-weight:500;letter-spacing:.02em;color:var(--mut);text-transform:uppercase}.pdp-v3 .promise{font-size:clamp(34px,3.6vw,52px);line-height:1.06;letter-spacing:-.03em;font-weight:600;margin:8px 0 12px}.pdp-v3 .promise em{font-style:normal;color:var(--gold)}.pdp-v3 .subpromise{font-size:16px;color:var(--ink2);margin-bottom:20px}.pdp-v3 .chips{display:grid;grid-template-columns:repeat(4,1fr);gap:0;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;margin-bottom:24px}.pdp-v3 .chip{padding:12px 10px;text-align:center;border-right:1px solid var(--line)}.pdp-v3 .chip:last-child{border-right:0}.pdp-v3 .chip b{display:block;font-size:14px;font-weight:600;letter-spacing:-.01em}.pdp-v3 .chip span{font-size:12px;color:var(--mut);line-height:1.3;display:block;margin-top:2px}

/* VALUE STACK */.pdp-v3 .stack{border:1.5px solid var(--ink);border-radius:var(--radius);overflow:hidden}.pdp-v3 .stack-hd{background:#141310;color:#fff;padding:11px 16px;font-size:11.5px;letter-spacing:.16em;text-transform:uppercase;font-weight:600;display:flex;justify-content:space-between;align-items:center}.pdp-v3 .stack-hd span{color:#f0d488;letter-spacing:.04em;text-transform:none;font-size:12px}.pdp-v3 .stack-body{padding:6px 16px}.pdp-v3 .li{display:flex;justify-content:space-between;align-items:baseline;gap:12px;padding:9px 0;border-bottom:1px solid #ede7da;font-size:14px}.pdp-v3 .li:last-child{border-bottom:0}.pdp-v3 .li .nm{font-weight:500}.pdp-v3 .li .nm small{display:block;font-weight:400;font-size:12.5px;color:var(--mut);margin-top:1px}.pdp-v3 .li .pr{white-space:nowrap;font-size:13.5px;font-weight:600}.pdp-v3 .li .pr s{color:#b3ada1;font-weight:400;margin-right:6px}.pdp-v3 .li .pr .free{color:var(--green);font-weight:600;letter-spacing:.02em}.pdp-v3 .li.hero-item{background:var(--gold-lt);margin:0 -16px;padding:11px 16px}.pdp-v3 .li.free-set{background:#cff9a4;margin:0 -16px;padding:11px 16px}.pdp-v3 .li.free-set .tag{background:var(--green) !important}.pdp-v3 .li.new-item .tag{display:inline-block;background:var(--gold);color:#fff;font-size:9px;font-weight:600;letter-spacing:.1em;padding:2px 5px;border-radius:2px;margin-left:6px;vertical-align:middle}.pdp-v3 .totals{border-top:2px solid var(--ink);padding:14px 16px;background:var(--cream)}.pdp-v3 .trow{display:flex;justify-content:space-between;font-size:13.5px;padding:2px 0;color:var(--ink2)}.pdp-v3 .trow s{color:#9c968a}.pdp-v3 .trow.big{font-size:20px;font-weight:600;color:var(--ink);align-items:baseline;padding-top:6px}.pdp-v3 .trow.save{color:var(--green);font-weight:600}.pdp-v3 .swatches{display:flex;gap:9px;padding:22px 0 26px;justify-content:flex-start}.pdp-v3 .sw{width:34px;height:34px;border-radius:50%;border:2px solid transparent;box-shadow:0 0 0 1px var(--line);cursor:pointer}.pdp-v3 .sw.on{border-color:#181713;box-shadow:0 0 0 1px #45423b}.pdp-v3 .sw.silver{background:linear-gradient(135deg,#e8e8e8,#b6b6b6)}.pdp-v3 .sw.black{background:linear-gradient(135deg,#3a3a3a,#0d0d0d)}.pdp-v3 .sw.gold{background:linear-gradient(135deg,#e2c268,#b08a2a)}.pdp-v3 .cta{display:block;width:calc(100% - 32px);margin:14px 16px 8px;background:#141310;color:#fff;border:0;border-radius:6px;padding:17px;font-size:15px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;cursor:pointer}.pdp-v3 .cta:hover{background:#23211c}.pdp-v3 .cta-sub{text-align:center;font-size:13px;color:var(--mut);padding:0 16px 16px}.pdp-v3 .trustrow{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;border-top:1px solid var(--line);padding:12px 10px;font-size:12px;text-align:center;color:var(--ink2);line-height:1.25}.pdp-v3 .trustrow b{display:block;font-size:12.5px}

/* NO-SUB BAR */.pdp-v3 .nosub{background:#141310;color:#fff;border-radius:var(--radius);padding:18px 22px;margin-top:16px;display:flex;gap:16px;align-items:center}.pdp-v3 .nosub .k{font-size:26px;font-weight:600;letter-spacing:-.02em;color:#f0d488;line-height:1;white-space:nowrap}.pdp-v3 .nosub p{font-size:13px;color:#d7d3ca;line-height:1.45}.pdp-v3 .nosub p b{color:#fff}

/* ACCORDION */.pdp-v3 .acc{border-top:1px solid var(--line);margin-top:20px}.pdp-v3 details{border-bottom:1px solid var(--line)}.pdp-v3 summary{padding:15px 0;font-size:14px;font-weight:600;cursor:pointer;list-style:none;display:flex;justify-content:space-between;align-items:center}.pdp-v3 summary::-webkit-details-marker{display:none}.pdp-v3 summary::after{content:"+";font-size:19px;font-weight:400;color:var(--mut)}.pdp-v3 details[open] summary::after{content:"–"}.pdp-v3 details .body{padding:0 0 16px;font-size:13.5px;color:var(--ink2);line-height:1.6}.pdp-v3 details .body ul{margin:8px 0 0 18px}.pdp-v3 details .body li{margin-bottom:5px}

/* KIT CARDS */.pdp-v3 .kit{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;margin-top:38px}.pdp-v3 .kitcard .shot{aspect-ratio:4/3;margin-bottom:12px}.pdp-v3 .kitcard h3{margin-bottom:4px;display:flex;align-items:center;gap:7px;flex-wrap:wrap}.pdp-v3 .pill{font-size:10.5px;font-weight:600;letter-spacing:.09em;padding:2px 6px;border-radius:2px;text-transform:uppercase}.pdp-v3 .pill.free{background:#e6f3eb;color:var(--green)}.pdp-v3 .pill.new{background:var(--gold);color:#fff}.pdp-v3 .kitcard p{font-size:13.5px;color:var(--mut);line-height:1.45}

/* FINISHER */.pdp-v3 .steps{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:38px}.pdp-v3 .step{border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}.pdp-v3 .step .shot{border:0;border-radius:0;aspect-ratio:5/4}.pdp-v3 .step .txt{padding:18px}.pdp-v3 .stepno{font-size:11.5px;font-weight:600;letter-spacing:.14em;color:var(--gold);text-transform:uppercase;margin-bottom:5px}.pdp-v3 .step p{font-size:14px;color:var(--ink2);margin-top:6px}.pdp-v3 .callout{border-left:3px solid var(--gold);background:var(--gold-lt);padding:18px 22px;border-radius:0 8px 8px 0;margin-top:32px;font-size:14.5px;color:var(--ink2);max-width:820px}.pdp-v3 .callout b{color:var(--ink)}

/* MICRO */.pdp-v3 .micro{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:38px}.pdp-v3 .micro .shot{aspect-ratio:16/10;margin-bottom:12px}.pdp-v3 .micro h3{font-size:14.5px}.pdp-v3 .micro p{font-size:14px;color:var(--mut);margin-top:5px}.pdp-v3 .micro .m-tag{font-size:11.5px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;margin-bottom:4px}

/* REASONS */.pdp-v3 .reasons{display:grid;grid-template-columns:repeat(3,1fr);gap:2px;margin-top:38px;background:var(--line);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}.pdp-v3 .reason{background:#fff;padding:26px 24px}.pdp-v3 .rnum{font-size:11.5px;font-weight:600;color:var(--gold);letter-spacing:.1em;margin-bottom:9px}.pdp-v3 .reason h3{margin-bottom:7px;font-size:16px}.pdp-v3 .reason p{font-size:14px;color:var(--ink2)}.pdp-v3 .quotelet{margin-top:11px;font-size:13px;color:var(--mut);font-style:italic;border-left:2px solid var(--line);padding-left:10px}.pdp-v3 .quotelet span{display:block;font-style:normal;font-size:12px;margin-top:3px;letter-spacing:.04em}

/* FEATURES */.pdp-v3 .feats{display:grid;grid-template-columns:repeat(3,1fr);gap:30px 26px;margin-top:38px}.pdp-v3 .feat .shot{aspect-ratio:16/10;margin-bottom:13px}.pdp-v3 .feat h3{margin-bottom:5px}.pdp-v3 .feat p{font-size:14px;color:var(--mut)}

/* COMPARE */.pdp-v3 .tablewrap{margin-top:38px;overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius)}.pdp-v3 table{border-collapse:collapse;width:100%;min-width:940px;font-size:12.5px;background:#fff}.pdp-v3 th, .pdp-v3 td{padding:13px 12px;text-align:center;border-bottom:1px solid var(--line);vertical-align:middle}.pdp-v3 thead th{background:var(--cream2);font-size:11.5px;font-weight:600;line-height:1.25;border-bottom:2px solid #ddd7c9}.pdp-v3 tbody th{text-align:left;font-weight:600;color:var(--ink2);background:#fbfaf7;font-size:12px;min-width:190px;position:sticky;left:0}.pdp-v3 .col-us{background:var(--gold-lt) !important;border-left:2px solid var(--gold);border-right:2px solid var(--gold)}.pdp-v3 thead .col-us{background:#f2e6c4 !important;border-top:2px solid var(--gold)}.pdp-v3 tbody tr:last-child .col-us{border-bottom:2px solid var(--gold)}.pdp-v3 .brandname{display:block;font-size:13px;font-weight:600;letter-spacing:-.01em}.pdp-v3 .brandsub{display:block;font-size:11.5px;color:var(--mut);font-weight:500;margin-top:2px}.pdp-v3 .y{color:var(--green);font-weight:600;font-size:15px}.pdp-v3 .n{color:var(--red);font-weight:600;font-size:15px}.pdp-v3 .mini{display:block;font-size:11.5px;color:var(--mut);margin-top:2px;line-height:1.25}.pdp-v3 .tnote{font-size:12.5px;color:var(--mut);margin-top:14px;line-height:1.55;max-width:100%}.pdp-v3 .hilite{font-weight:600;color:var(--ink)}

/* PROOF */.pdp-v3 .proof{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-top:38px}.pdp-v3 .qt{border:1px solid var(--line);border-radius:var(--radius);padding:20px;background:#fff;display:flex;flex-direction:column}.pdp-v3 .qt .stars{margin-bottom:9px}.pdp-v3 .qt p{font-size:14.5px;line-height:1.5;font-weight:500;flex:1}.pdp-v3 .qt .who{margin-top:13px;font-size:13px;color:var(--mut);border-top:1px solid var(--line);padding-top:10px}.pdp-v3 .qt .who b{color:var(--ink);display:block;font-size:12.5px}.pdp-v3 .qt .vd{color:var(--green);font-size:10.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase}.pdp-v3 .statbar{display:grid;grid-template-columns:repeat(4,1fr);gap:2px;margin-top:34px;background:var(--line);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}.pdp-v3 .statbar div{background:#fff;padding:24px 16px;text-align:center}.pdp-v3 .statbar b{display:block;font-size:34px;font-weight:600;letter-spacing:-.03em}.pdp-v3 .statbar span{font-size:13px;color:var(--mut);display:block;margin-top:3px;line-height:1.3}

/* GUARANTEE */.pdp-v3 .guar{display:grid;grid-template-columns:1fr 1fr;gap:2px;background:var(--line);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;margin-top:38px}.pdp-v3 .guar > div{background:#fff;padding:34px 30px}.pdp-v3 .gseal{width:64px;height:64px;border-radius:50%;background:#141310;color:#f0d488;display:flex;flex-direction:column;align-items:center;justify-content:center;font-weight:600;line-height:1;margin-bottom:16px}.pdp-v3 .gseal b{font-size:19px}.pdp-v3 .gseal span{font-size:8px;letter-spacing:.1em;margin-top:2px}.pdp-v3 .guar h3{font-size:19px;margin-bottom:8px}.pdp-v3 .guar p{font-size:13.5px;color:var(--ink2)}

/* CROSS SELL */.pdp-v3 .xsell{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-top:34px}.pdp-v3 .xcard{border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;background:#fff}.pdp-v3 .xcard .shot{border:0;border-radius:0;aspect-ratio:1/1}.pdp-v3 .xcard .b{padding:14px}.pdp-v3 .xcard h3{font-size:13.5px;margin-bottom:3px}.pdp-v3 .xcard .px{font-size:13px;font-weight:600;margin:6px 0 10px}.pdp-v3 .addbtn{width:100%;border:1.5px solid #45423b;background:#fff;padding:9px;border-radius:5px;font-weight:600;font-size:12px;cursor:pointer;letter-spacing:.04em}.pdp-v3 .addbtn:hover{background:#141310;color:#fff}

/* FAQ */.pdp-v3 .faq{max-width:880px;margin:38px auto 0}.pdp-v3 .faq details{border-bottom:1px solid var(--line)}.pdp-v3 .faq summary{font-size:15px;padding:19px 0}

/* FINAL */.pdp-v3 .final{background:#141310;color:#fff;text-align:center;padding:72px 20px}.pdp-v3 .final h2{color:#fff}.pdp-v3 .final p{color:#c9c5bc;margin:14px auto 26px;max-width:520px;font-size:15px}.pdp-v3 .final .cta{display:inline-block;width:auto;margin:0;background:#f0d488;color:#181713;padding:18px 54px;text-decoration:none}.pdp-v3 .final .cta:hover{background:#fff}.pdp-v3 .final small{display:block;margin-top:16px;color:#8f8b83;font-size:12.5px}

/* MOBILE STICKY */.pdp-v3 .mobile-bar{display:none}

@media(max-width:900px){.pdp-v3 .hero-grid{grid-template-columns:1fr;gap:28px}.pdp-v3 .gallery{position:static}.pdp-v3 .kit, .pdp-v3 .feats, .pdp-v3 .proof, .pdp-v3 .micro, .pdp-v3 .xsell{grid-template-columns:repeat(2,1fr)}.pdp-v3 .reasons, .pdp-v3 .steps, .pdp-v3 .guar{grid-template-columns:1fr}.pdp-v3 .statbar{grid-template-columns:repeat(2,1fr)}.pdp-v3 .chips{grid-template-columns:repeat(2,1fr)}.pdp-v3 .chip:nth-child(2){border-right:0}.pdp-v3 .chip:nth-child(1), .pdp-v3 .chip:nth-child(2){border-bottom:1px solid var(--line)}.pdp-v3 .nosub{flex-direction:column;align-items:flex-start;gap:8px}.pdp-v3 .sec{padding:52px 0}.pdp-v3 .mobile-bar{display:flex;position:fixed;bottom:0;left:0;right:0;background:#fff;border-top:1px solid var(--line);padding:10px 14px;gap:12px;align-items:center;z-index:70;box-shadow:0 -4px 18px rgba(0,0,0,.07)}.pdp-v3 .mobile-bar .p{font-size:13.5px;font-weight:600;line-height:1.15}.pdp-v3 .mobile-bar .p s{display:block;font-weight:400;color:var(--mut);font-size:12px}.pdp-v3 .mobile-bar button{flex:1;background:#141310;color:#fff;border:0;border-radius:5px;padding:14px;font-weight:600;font-size:14px;letter-spacing:.04em}.pdp-v3-has-mobilebar{padding-bottom:66px}
}
@media(max-width:560px){.pdp-v3 .kit, .pdp-v3 .feats, .pdp-v3 .proof, .pdp-v3 .micro, .pdp-v3 .xsell{grid-template-columns:1fr}.pdp-v3 .subnav{display:none}.pdp-v3 .final a.cta{font-size:16px;padding:18px 30px;white-space:nowrap}
}
@media(max-width:360px){.pdp-v3 .final a.cta{font-size:14px}}.pdp-v3 .note{max-width:var(--max);margin:0 auto;padding:14px 20px;font-size:11.5px;color:#8a8477;border-top:1px dashed var(--line)}

/* ===== IM8-STYLE OPTION CARDS ===== */.pdp-v3 .opts{display:flex;flex-direction:column;gap:10px}.pdp-v3 .opt{display:block;position:relative;border:1.5px solid var(--line);border-radius:var(--radius);padding:14px 16px 16px;cursor:pointer;background:#fff;overflow:hidden}.pdp-v3 .opt.on{border:2px solid var(--ink);background:#fffdf8}.pdp-v3 .ribbon{position:absolute;top:0;right:0;background:#141310;color:#f0d488;font-size:10px;font-weight:600;letter-spacing:.11em;padding:5px 11px;border-radius:0 0 0 8px}.pdp-v3 .opt-hd{display:flex;align-items:center;gap:9px;margin-bottom:6px}.pdp-v3 .radio{width:17px;height:17px;border-radius:50%;border:2px solid #c9c3b6;flex:none;position:relative;opacity:1}.pdp-v3 .opt.on .radio{border-color:var(--ink)}.pdp-v3 .opt.on .radio::after{content:"";position:absolute;inset:3px;border-radius:50%;background:var(--ink)}.pdp-v3 .opt-nm{font-size:15px;font-weight:600;letter-spacing:-.01em}.pdp-v3 .savebadge{background:var(--gold-lt);color:#8a6a17;font-size:10px;font-weight:600;letter-spacing:.06em;padding:3px 8px;border-radius:20px}.pdp-v3 .priceline{display:flex;align-items:baseline;justify-content:space-between;gap:10px;flex-wrap:wrap;margin:2px 0 4px}.pdp-v3 .bigp{font-size:34px;font-weight:600;letter-spacing:-.035em;line-height:1}.pdp-v3 .bigp small{font-size:13px;font-weight:500;color:var(--mut);letter-spacing:0;margin-left:3px}.pdp-v3 .rightp{font-size:13px;font-weight:600;color:var(--green);text-align:right;letter-spacing:.02em}.pdp-v3 .subline{display:flex;justify-content:space-between;gap:10px;font-size:13px;color:var(--mut);border-bottom:1px solid #ede7da;padding-bottom:11px;margin-bottom:11px}.pdp-v3 .subline s{color:#a9a396}.pdp-v3 .ticks{display:grid;gap:6px;margin-bottom:14px}.pdp-v3 .tick{display:flex;gap:8px;font-size:14px;color:var(--ink2);line-height:1.35}.pdp-v3 .tick i{color:var(--green);font-style:normal;font-weight:600;flex:none;font-size:12px;margin-top:1px}.pdp-v3 .tick b{color:var(--ink)}.pdp-v3 .kithd{font-size:11px;font-weight:600;letter-spacing:.11em;color:var(--gold);text-transform:uppercase;margin-bottom:9px}.pdp-v3 .kitgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px 7px}.pdp-v3 .kt{text-align:center;border-radius:8px;padding:3px 3px 7px}.pdp-v3 .kt .box{background:#fff;border:0;border-radius:6px;height:58px;display:flex;align-items:center;justify-content:center;font-size:8px;color:#b0a894;padding:4px;line-height:1.15;overflow:hidden}.pdp-v3 .kt .box img{width:100%;height:100%;object-fit:contain}.pdp-v3 .kt s{display:block;font-size:12px;color:#a9a396;margin-top:5px;text-decoration:none}.pdp-v3 .kt span{display:block;font-size:12.5px;font-weight:600;color:var(--ink);line-height:1.2;margin-top:1px}.pdp-v3 .opt.slim{padding:13px 16px}.pdp-v3 .opt.slim .opt-hd{margin-bottom:0}.pdp-v3 .opt.slim .p2{margin-left:auto;font-size:15px;font-weight:600}
/* image-aware placeholders */.pdp-v3 .shot.hasimg{padding:0;border:0;background:var(--cream);overflow:hidden}.pdp-v3 .shot.hasimg img{width:100%;height:100%;object-fit:cover;display:block}.pdp-v3 .qt .av{width:34px;height:34px;border-radius:50%;object-fit:cover;flex:none;background:var(--cream2)}.pdp-v3 .qt .who{display:flex;gap:10px;align-items:center}
@media(max-width:900px){.pdp-v3 .kitgrid{grid-template-columns:repeat(4,1fr)}}

/* ===== COMPACT METHOD STRIP ===== */.pdp-v3 .methodstrip{display:grid;grid-template-columns:1.05fr .95fr;gap:40px;align-items:center;border:1px solid var(--line);border-radius:var(--radius);padding:30px 32px;background:var(--cream)}.pdp-v3 .ms-steps{display:grid;gap:12px}.pdp-v3 .msx{display:flex;gap:14px;align-items:flex-start;background:#fff;border:1px solid var(--line);border-radius:8px;padding:13px 15px}.pdp-v3 .msx b{font-size:12px;font-weight:600;color:var(--gold);letter-spacing:.08em;flex:none;padding-top:2px}.pdp-v3 .msx span{font-size:14px;font-weight:600;line-height:1.25}.pdp-v3 .msx small{display:block;font-weight:400;font-size:14px;color:var(--mut);margin-top:3px;line-height:1.4}
/* ===== SPEC STRIP under the benefit grid ===== */.pdp-v3 .specstrip{display:grid;grid-template-columns:repeat(4,1fr);gap:2px;margin-top:34px;background:var(--line);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}.pdp-v3 .specstrip>div{background:#fff;padding:18px 14px;text-align:center}.pdp-v3 .specstrip b{display:block;font-size:17px;font-weight:600;letter-spacing:-.02em}.pdp-v3 .specstrip span{display:block;font-size:11.5px;color:var(--mut);margin-top:3px;line-height:1.3}.pdp-v3 .feat .quotelet{margin-top:12px;font-size:13px;color:var(--mut);font-style:italic;border-left:2px solid var(--line);padding-left:11px}.pdp-v3 .feat .quotelet span{display:block;font-style:normal;font-size:12px;margin-top:4px;letter-spacing:.03em}
@media(max-width:900px){.pdp-v3 .methodstrip{grid-template-columns:1fr;gap:24px;padding:24px}.pdp-v3 .specstrip{grid-template-columns:repeat(2,1fr)}}

/* ===== SPEC LIST ===== */.pdp-v3 .spec-list{list-style:none;margin:6px 0 0 !important;padding:0}.pdp-v3 .spec-list li{display:flex;justify-content:space-between;gap:16px;align-items:baseline;padding:7px 0;border-bottom:1px solid #ede7da;margin:0 !important;font-size:13px}.pdp-v3 .spec-list li:last-child{border-bottom:0}.pdp-v3 .spec-list span{color:var(--mut);flex:none;max-width:47%}.pdp-v3 .spec-list b{text-align:right;font-weight:500;color:var(--ink)}

/* v3 buttons: pill shape + Jost semibold tracking, matching the live theme's button treatment */
.pdp-v3 .cta, .pdp-v3 .mobile-bar button, .pdp-v3 .addbtn{border-radius:999px;font-weight:600;letter-spacing:.08em;text-transform:uppercase}
.pdp-v3 .swatches{padding:22px 0 0}

/* legibility pass 2026-08-29: 35+ audience. Muted tier #6a665c (5.7:1), gold labels #8a6a17 (5.1:1),
   support text <=13px weight 500. */
.pdp-v3 .kithd, .pdp-v3 .stepno, .pdp-v3 .msx b, .pdp-v3 .rnum{color:#8a6a17}.pdp-v3 .m-tag{--gold:#8a6a17}
.pdp-v3 .stars{color:#a9802d}
.pdp-v3 .tnote, .pdp-v3 .mini, .pdp-v3 .chip span, .pdp-v3 .cta-sub, .pdp-v3 .trustrow, .pdp-v3 .statbar span, .pdp-v3 .qt .who, .pdp-v3 .quotelet span, .pdp-v3 .li .nm small, .pdp-v3 .kt s, .pdp-v3 .kt span, .pdp-v3 .subline, .pdp-v3 .brandsub, .pdp-v3 .rating-row, .pdp-v3 .mobile-bar .p s{font-weight:500}
.pdp-v3 .final small{color:#b8b2a4}

/* scroll reveal (below the fold only; JS-gated via html.v3-anim, reduced-motion exits before init) */
html.v3-anim .pdp-v3 .v3r{opacity:0;transform:translateY(12px);transition:opacity .45s cubic-bezier(.2,.6,.2,1),transform .45s cubic-bezier(.2,.6,.2,1)}
html.v3-anim .pdp-v3 .v3r.v3r-in{opacity:1;transform:none}
@media (prefers-reduced-motion: reduce){html.v3-anim .pdp-v3 .v3r{opacity:1;transform:none;transition:none}}

/* BUY-BOX POLISH (2026-08-30): boxed trust row w/ thin dark stroke; ribbon corner matches card radius */
.pdp-v3 .trustrow{border-top:0;padding:14px 0 0;gap:8px}
.pdp-v3 .trustrow>div{border:1px solid #45423b;border-radius:10px;padding:10px 8px;background:transparent}
@media(max-width:560px){.pdp-v3 .trustrow{grid-template-columns:repeat(2,1fr)}}
.pdp-v3 .specstrip{background:transparent;border:0;gap:10px;overflow:visible}
.pdp-v3 .specstrip>div{border-radius:10px}
.pdp-v3 .opt .bv-tag{position:absolute;top:14px;right:14px;margin-bottom:0}
@media(min-width:901px){.pdp-v3 .hero-grid{grid-template-columns:9fr 11fr}}
.pdp-v3 .faq summary{font-size:18px}
.pdp-v3 .faq details .body{font-size:15px}

/* MOBILE DEBUG PASS (2026-08-30): sticky labeled corner cell, tighter label column,
   kill rogue white blocks, hide Mode announcement bar on mobile, bolder utility text */
.pdp-v3 thead .th-feature{position:sticky;left:0;z-index:3;text-align:left;background:var(--cream2);border-right:1px solid var(--line);font-size:13px}
.pdp-v3 tbody th{position:sticky;left:0;z-index:2;border-right:1px solid var(--line)}
.pdp-v3 #compare tbody th{font-size:13px}
.pdp-v3 #compare tbody th, .pdp-v3 #compare tbody td{vertical-align:top;padding-top:15px}

/* BUY-BOX BREATHING ROOM (2026-08-30): widen group seams, keep pairs tight */
.pdp-v3 .opt{padding:18px 18px 20px}
.pdp-v3 .opt-hd{margin-bottom:8px}
.pdp-v3 .ticks{gap:10px;margin-bottom:16px}
.pdp-v3 .tick{line-height:1.45}
.pdp-v3 .subline{padding-bottom:12px;margin-bottom:14px}
.pdp-v3 .kithd{margin-bottom:11px}
.pdp-v3 .kitgrid{gap:10px 8px}
.pdp-v3 .subline{color:#45423b}
.pdp-v3 .subline s{color:#8a857a}
@media(max-width:900px){
  .pdp-v3-has-mobilebar{padding-bottom:0}
  .pdp-v3 tbody th{min-width:118px;max-width:128px;font-size:11.5px;padding:12px 10px}
  .pdp-v3 table{min-width:760px;font-size:12px}
  [id$='__announcement-bar']{display:none}
  .pdp-v3 .announce.u-bar .u-msg, .pdp-v3 .announce.u-bar .u-msg b{font-weight:600 !important}
  .pdp-v3 #compare tbody th{min-width:118px;max-width:130px;font-size:12.5px}
}
@media(max-width:560px){[id*='__v3_subnav'] .topnav{display:none}}
@media(max-width:560px){.pdp-v3 .opt .bv-tag{position:static;margin-bottom:10px}}
@media(max-width:900px){.pdp-v3 .gallery>.shot{aspect-ratio:4/3}}
.pdp-v3 .specstrip .spec-ic{display:block;margin:0 auto 8px;color:var(--ink)}

/* Proof-numbers band: no hairline above or below it */
[id*='__v3_proof_numbers'] .pdp-v3 .sec{border-top:0}
[id*='__v3_proof_numbers'] + .shopify-section .pdp-v3 .sec{border-top:0}
/* Desktop: full-bleed white strip, no card look, no hover */
@media(min-width:901px){
  [id*='__v3_proof_numbers'] .pdp-v3 .sec{background:#fff}
  .pdp-v3 .statbar.proofband-stats{background:transparent;border-radius:0}
  .pdp-v3 .statbar.proofband-stats>div{background:transparent}
}

/* CARD HOVERS (2026-08-30): strokeless cards gain an ink stroke; stroked trust cells invert to dark */
@media(hover:hover){
  .pdp-v3 .hero .chip,.pdp-v3 .specstrip>div,.pdp-v3 .qt,.pdp-v3 .micro>div,.pdp-v3 .guar>div,.pdp-v3 .feats .shot{transition:box-shadow .18s ease}
  .pdp-v3 .hero .chip:hover,.pdp-v3 .specstrip>div:hover,.pdp-v3 .qt:hover,.pdp-v3 .micro>div:hover,.pdp-v3 .guar>div:hover,.pdp-v3 .feats>div:hover .shot{box-shadow:inset 0 0 0 1px #181713}
  .pdp-v3 .trustrow>div{transition:background-color .18s ease,color .18s ease}
  .pdp-v3 .trustrow>div:hover{background:#141310;color:#dcd7cb}
  .pdp-v3 .trustrow>div:hover b{color:#fff}
  .pdp-v3 .kt{transition:box-shadow .18s ease}
  .pdp-v3 .kt:hover{box-shadow:inset 0 0 0 1px #181713}
  .pdp-v3 .cta,.pdp-v3 .addbtn,.pdp-v3 .rev-toggle{transition:background-color .18s ease,color .18s ease,border-color .18s ease,transform .18s ease,box-shadow .18s ease}
  .pdp-v3 .cta:hover,.pdp-v3 .addbtn:hover,.pdp-v3 .rev-toggle:hover{transform:translateY(-1px);box-shadow:0 6px 16px rgba(20,19,16,.16)}
  .pdp-v3 .cta:active,.pdp-v3 .addbtn:active{transform:translateY(0);box-shadow:0 2px 6px rgba(20,19,16,.14)}
  .pdp-v3 .rev-toggle:hover{background:#141310;color:#fff;border-color:#141310}
}
.pdp-v3 .cta:focus-visible,.pdp-v3 .addbtn:focus-visible,.pdp-v3 .rev-toggle:focus-visible{outline:2px solid #181713;outline-offset:3px}
.pdp-v3 .final .cta:focus-visible{outline-color:#f0d488}
@media (prefers-reduced-motion: reduce){
  .pdp-v3 .cta,.pdp-v3 .addbtn,.pdp-v3 .rev-toggle,.pdp-v3 .kt,.pdp-v3 .hero .chip,.pdp-v3 .specstrip>div,.pdp-v3 .statbar,.pdp-v3 .trustrow>div{transition:none}
  .pdp-v3 .cta:hover,.pdp-v3 .addbtn:hover,.pdp-v3 .rev-toggle:hover{transform:none}
}

.pdp-v3 .kt .box{background:transparent;height:auto;aspect-ratio:3/2}
.pdp-v3 .kt .box img{object-fit:cover}

/* Swatches live inside the kit card with a labeled color name */
.pdp-v3 .opt .sw-wrap{margin:2px 0 16px}
.pdp-v3 .sw-label{font-size:12.5px;font-weight:500;color:var(--mut);margin-bottom:8px}
.pdp-v3 .sw-label b{color:var(--ink);font-weight:600}
.pdp-v3 .opt .swatches{padding:0}
.pdp-v3 .opt .sw{width:28px;height:28px}

/* Desktop sticky purchase bar (auto-hides while the in-page CTA is visible) */
.pdp-v3 .desk-bar{display:none}
@media(min-width:901px){
  .pdp-v3 .desk-bar{display:block;position:fixed;left:0;right:0;bottom:0;z-index:70;background:rgba(255,255,255,.97);backdrop-filter:blur(8px);border-top:1px solid var(--line);box-shadow:0 -6px 24px rgba(0,0,0,.06);transform:translateY(102%);transition:transform .25s ease;pointer-events:none}
  .pdp-v3 .desk-bar.show{transform:translateY(0);pointer-events:auto}
  .pdp-v3 .db-in{display:flex;align-items:center;gap:18px;padding:10px 20px}
  .pdp-v3 .db-name{font-weight:600;font-size:14.5px}
  .pdp-v3 .db-price{font-weight:600;font-size:15px;margin-left:auto}
  .pdp-v3 .db-cta{width:auto;margin:0;padding:12px 36px;border-radius:999px;font-size:13.5px;letter-spacing:.08em}
}
@media(prefers-reduced-motion:reduce){.pdp-v3 .desk-bar{transition:none}}

/* Kit gear marquee: 8x1 row drifting right-to-left, pauses on hover, shorter card */
.pdp-v3 .kitrow{overflow:hidden;margin:0 -4px}
.pdp-v3 .kitrow .kitgrid{display:flex;gap:0;width:max-content;animation:pdpV3KitDrift 36s linear infinite}
.pdp-v3 .kitrow:hover .kitgrid{animation-play-state:paused}
.pdp-v3 .kitrow .kt{flex:none;width:112px;margin-right:10px;padding:3px 3px 7px}
.pdp-v3 .kitrow .kt .box{aspect-ratio:3/2}
.pdp-v3 .kitrow .kt s{font-size:11.5px}
.pdp-v3 .kitrow .kt span{font-size:12px}
@keyframes pdpV3KitDrift{to{transform:translateX(-50%)}}
@media (prefers-reduced-motion: reduce){
  .pdp-v3 .kitrow{overflow-x:auto}
  .pdp-v3 .kitrow .kitgrid{animation:none}
}

/* Kit marquee v2: ~4 tiles visible, JS-driven drift, draggable */
.pdp-v3 .kitrow{cursor:grab;touch-action:pan-y}
.pdp-v3 .kitrow.dragging{cursor:grabbing}
.pdp-v3 .kitrow .kitgrid{animation:none;will-change:transform}
.pdp-v3 .kitrow .kt{width:130px;margin-right:12px}
.pdp-v3 .kitrow img{-webkit-user-drag:none;user-select:none}
@media(max-width:560px){.pdp-v3 .kitrow .kt{width:118px}}

/* contain the marquee: stop max-content track from widening the buy-box column */
.pdp-v3 .buybox{min-width:0}
.pdp-v3 .kitrow{max-width:100%}

/* Tighten gap between Mode header and the v3 utility bar */
[id*='__v3_subnav']{display:block;margin-top:-44px;position:relative}

/* Kit marquee v3: smaller tiles, tighter gaps, soft edge fade */
.pdp-v3 .kitrow .kt{width:104px;margin-right:8px}
.pdp-v3 .kitrow{-webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
@media(max-width:560px){.pdp-v3 .kitrow .kt{width:96px}}

/* Desk bar v2: floating glass dock (frosted panel, inner light edge, tinted shadow) */
@media(min-width:901px){
  .pdp-v3 .desk-bar{left:50%;right:auto;bottom:20px;width:min(640px,calc(100vw - 48px));border:1px solid rgba(24,23,19,.1);border-radius:999px;background:rgba(255,255,255,.82);backdrop-filter:blur(14px) saturate(160%);-webkit-backdrop-filter:blur(14px) saturate(160%);box-shadow:inset 0 1px 0 rgba(255,255,255,.6),0 14px 44px rgba(20,19,16,.16);transform:translate(-50%,150%);transition:transform .3s cubic-bezier(.2,.6,.2,1)}
  .pdp-v3 .desk-bar.show{transform:translate(-50%,0)}
  .pdp-v3 .db-in{display:flex;align-items:center;gap:14px;padding:8px 8px 8px 10px}
  .pdp-v3 .db-thumb{width:48px;height:48px;border-radius:50%;object-fit:cover;background:var(--cream);flex:none}
  .pdp-v3 .db-meta{display:flex;flex-direction:column;line-height:1.2}
  .pdp-v3 .db-name{font-weight:600;font-size:14px}
  .pdp-v3 .db-price{font-weight:500;font-size:13px;color:var(--mut);margin-left:0}
  .pdp-v3 .db-cta{margin-left:auto;width:auto;padding:13px 34px;border-radius:999px;font-size:13.5px;letter-spacing:.08em}
}
@media (prefers-reduced-transparency: reduce){.pdp-v3 .desk-bar{background:#fff;backdrop-filter:none;-webkit-backdrop-filter:none}}

/* Kill Mode announcement bar on v3 pages (all widths); aux Blog/Contact links live in the anchor nav */
[id$='__announcement-bar']{display:none}
.pdp-v3 .subnav-aux{position:absolute;right:20px;top:50%;transform:translateY(-50%);display:flex;gap:16px}
.pdp-v3 .subnav-aux a{color:var(--mut);text-decoration:none;font-size:12px;font-weight:500;letter-spacing:.04em;text-transform:uppercase;padding:4px 0;border-bottom:2px solid transparent}
.pdp-v3 .subnav-aux a:hover{color:var(--ink);border-color:var(--ink)}
@media(max-width:900px){.pdp-v3 .subnav-aux{display:none}}

/* Utility messages are interactive: pointer + underline affordance */
.pdp-v3 .u-bar .u-msg[data-goto]{cursor:pointer}
@media(hover:hover){.pdp-v3 .u-bar .u-msg[data-goto]:hover{text-decoration:underline;text-underline-offset:3px}}
.pdp-v3 .u-bar .u-msg[data-goto]:focus-visible{outline:2px solid #f0d488;outline-offset:2px}

/* $0/mo band: slightly larger body so the last line fills out */
.pdp-v3 .nosub p{font-size:14.5px;line-height:1.5}

/* Per-card buy controls (Manscaped pattern, house style): expand on selection */
.pdp-v3 .opt-buy{display:flex;gap:12px;align-items:center;max-height:0;opacity:0;overflow:hidden;margin:0;transition:max-height .35s ease,opacity .3s ease,margin .35s ease}
.pdp-v3 .opt.on .opt-buy{max-height:64px;opacity:1;margin-top:14px}
.pdp-v3 .qty{display:flex;align-items:center;border:1px solid var(--line);border-radius:999px;background:#fff;flex:none}
.pdp-v3 .qbtn{width:40px;height:46px;background:none;border:0;font-size:18px;color:var(--ink2);cursor:pointer;line-height:1}
.pdp-v3 .qnum{min-width:26px;text-align:center;font-weight:600;font-size:15px}
.pdp-v3 .opt-cta{flex:1;width:auto;margin:0;border-radius:999px;padding:14px 20px;font-size:14px;letter-spacing:.08em;text-transform:uppercase}
@media(prefers-reduced-motion: reduce){.pdp-v3 .opt-buy{transition:none}}

/* Mobile buy controls: full-width stepper stacked over full-width ATC (Manscaped mobile pattern) */
@media(max-width:560px){
  .pdp-v3 .opt-buy{flex-direction:column;align-items:stretch;gap:10px}
  .pdp-v3 .opt.on .opt-buy{max-height:150px}
  .pdp-v3 .qty{width:100%;justify-content:space-between;height:46px}
  .pdp-v3 .qbtn{width:56px}
  .pdp-v3 .opt-cta{font-size:14px;padding:15px 12px;white-space:nowrap}
}

.pdp-v3 .opt-buy{flex-wrap:wrap}
.pdp-v3 .opt.on .opt-buy{max-height:110px}
@media(max-width:560px){.pdp-v3 .opt.on .opt-buy{max-height:210px}}

/* Collapsed solo card: anchor line without the stray hairline */
.pdp-v3 .opt.slim:not(.on) .subline{border-bottom:0;padding-bottom:0;margin-bottom:0}

/* Trust chips: oblong (pill vocabulary) */
.pdp-v3 .trustrow>div{border-radius:30px}

/* Trust chip values: uppercase micro-label treatment */
.pdp-v3 .trustrow b{text-transform:uppercase;letter-spacing:.07em}

/* Swatches: high-res Figma renders (197px sources) replace CSS gradients */
.pdp-v3 .sw{background-size:118% 118%;background-position:center;background-repeat:no-repeat}
.pdp-v3 .sw.silver{background-image:url(pdp-v3-sw-silver.webp);background-size:118% 118%;background-position:center;background-repeat:no-repeat}
.pdp-v3 .sw.black{background-image:url(pdp-v3-sw-black.webp);background-size:118% 118%;background-position:center;background-repeat:no-repeat}
.pdp-v3 .sw.gold{background-image:url(pdp-v3-sw-gold.webp);background-size:118% 118%;background-position:center;background-repeat:no-repeat}

/* Desk dock: one notch larger for target size and legibility */
@media(min-width:901px){
  .pdp-v3 .desk-bar{width:min(720px,calc(100vw - 48px))}
  .pdp-v3 .db-in{padding:10px 10px 10px 12px;gap:16px}
  .pdp-v3 .db-thumb{width:54px;height:54px}
  .pdp-v3 .db-name{font-size:15px}
  .pdp-v3 .db-price{font-size:14px}
  .pdp-v3 .db-cta{padding:15px 42px;font-size:14.5px}
}

/* Color selector: bigger label and circles */
.pdp-v3 .sw-label{font-size:14px}
.pdp-v3 .opt .sw{width:38px;height:38px}
.pdp-v3 .opt.slim .sw-wrap{margin:12px 0 4px}

/* Solo card: color selector collapses with the card like its buy controls */
.pdp-v3 .opt.slim .sw-wrap{max-height:0;opacity:0;overflow:hidden;margin:0;transition:max-height .35s ease,opacity .3s ease,margin .35s ease}
.pdp-v3 .opt.slim.on .sw-wrap{max-height:110px;opacity:1;margin:12px 0 4px}
@media(prefers-reduced-motion: reduce){.pdp-v3 .opt.slim .sw-wrap{transition:none}}

/* First fold frames the kit card: content below it fades up on first scroll (JS-gated, desktop only) */
@media(min-width:901px){
  html.v3-folddefer .pdp-v3 .fold-defer{opacity:0;transform:translateY(12px);transition:opacity .5s ease,transform .5s cubic-bezier(.2,.6,.2,1)}
  html.v3-folddefer .pdp-v3 .fold-defer.in{opacity:1;transform:none}
}

/* Mobile bar: product name is a plain span (was an <s> rendering struck-through) */
.pdp-v3 .mobile-bar .p .mb-nm{display:block;font-weight:500;color:var(--mut);font-size:12px;text-decoration:none}

/* Final CTA: tighter top on mobile */
@media(max-width:560px){.pdp-v3 .final{padding:40px 20px 56px}}

/* Mobile bar v2: floating glass dock, larger tap target (mirrors desktop dock) */
@media(max-width:900px){
  .pdp-v3 .mobile-bar{left:10px;right:10px;bottom:10px;border-radius:999px;border:1px solid rgba(24,23,19,.1);border-top:1px solid rgba(24,23,19,.1);background:rgba(255,255,255,.88);backdrop-filter:blur(12px) saturate(160%);-webkit-backdrop-filter:blur(12px) saturate(160%);box-shadow:inset 0 1px 0 rgba(255,255,255,.6),0 10px 30px rgba(20,19,16,.18);padding:8px 8px 8px 18px}
  .pdp-v3 .mobile-bar button{border-radius:999px;font-size:14px;padding:16px 14px}
  .pdp-v3-has-mobilebar{padding-bottom:0}
}
@media (prefers-reduced-transparency: reduce){.pdp-v3 .mobile-bar{background:#fff;backdrop-filter:none;-webkit-backdrop-filter:none}}

/* Mobile top rhythm: tighter, even gap under the utility bar; rating block = deliberate 2-line lockup */
@media(max-width:900px){
  .pdp-v3 .hero{padding:18px 0 44px}
  .pdp-v3 .buybox-head-m .rating-row{margin-bottom:10px;row-gap:6px;font-size:14px}
  .pdp-v3 .buybox-head-m .rating-row .stars{font-size:16px}
  .pdp-v3 .buybox-head-m .rating-row{display:block;line-height:1.6}
  .pdp-v3 .buybox-head-m .badge-1{display:block;width:max-content;margin-top:8px}
}

/* Mobile bar: name-first hierarchy + same auto-hide as the desktop dock */
@media(max-width:900px){
  .pdp-v3 .mobile-bar{transform:translateY(130%);transition:transform .3s cubic-bezier(.2,.6,.2,1)}
  .pdp-v3 .mobile-bar.show{transform:none}
  .pdp-v3 .mobile-bar .p .mb-title{display:block;font-weight:600;font-size:14px;color:var(--ink)}
  .pdp-v3 .mobile-bar .p .mb-pr{display:block;font-weight:500;font-size:12.5px;color:var(--mut)}
}
@media (prefers-reduced-motion: reduce){.pdp-v3 .mobile-bar{transition:none}}

/* Mobile: the -44px desktop pull-up overlapped the header — give logo/buttons air */
@media(max-width:900px){[id*='__v3_subnav']{margin-top:-22px}}

/* Mobile in-card ATCs: one notch smaller and tighter */
@media(max-width:560px){
  .pdp-v3 .hero .opt-cta{font-size:14px;letter-spacing:.06em;padding:14px 10px}
  .pdp-v3 .mobile-bar button{font-size:14px;letter-spacing:.06em}
}

/* Mobile ATC consistency: both pills 13px type with the gold CTA's generous vertical padding */
@media(max-width:560px){
  .pdp-v3 .hero .opt-cta{padding:16px 10px}
  .pdp-v3 .final a.cta{font-size:14px;letter-spacing:.06em;padding:16px 30px;line-height:1.2}
  .pdp-v3 .hero .opt-cta{line-height:1.2}
}

/* Lede disclaimers: escape the parent line-height strut, own rhythm */
.pdp-v3 p.lede > span{display:block;margin-top:10px;line-height:1.55}

/* Mobile alignment system: band headers centered, body text left (final CTA stays centered) */
@media(max-width:560px){
  .pdp-v3 .center .lede{text-align:left}
  .pdp-v3 .final p{text-align:center}
}

/* Mobile: one left rail — section headers join the body on the left edge.
   Exceptions (poster moments): stats strip and final CTA stay centered. */
@media(max-width:560px){
  .pdp-v3 .sec .center{text-align:left}
  .pdp-v3 .center .lede{margin-left:0;margin-right:0}
  .pdp-v3 .statbar div{text-align:center}
  .pdp-v3 .final, .pdp-v3 .final .center{text-align:center}
}

/* Fold veil: gradual white gradient + blur pinned to the viewport bottom while the visitor
   is at the top of the page — softens the downsell card so the kit card owns the fold.
   Fades out past 90px of scroll and comes back if they return to the top. Desktop only. */
.pdp-v3 .fold-veil{display:none}
@media(min-width:901px){
  .pdp-v3 .fold-veil{display:block;position:fixed;left:0;right:0;bottom:0;height:120px;z-index:40;pointer-events:none;
    background:linear-gradient(to top,#ffffff 0%,rgba(255,255,255,.82) 38%,rgba(255,255,255,0) 100%);
    -webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);
    -webkit-mask-image:linear-gradient(to top,#000 45%,transparent 100%);mask-image:linear-gradient(to top,#000 45%,transparent 100%);
    opacity:1;transition:opacity .35s ease}
  .pdp-v3 .fold-veil.off{opacity:0}
}

/* Keep the kit card crisp above the fold veil — the veil may only soften the downsell card. */
@media(min-width:901px){
  .pdp-v3 .opt[data-opt="kit"]{position:relative;z-index:45}
}

/* Mobile fold veil: same idea, much subtler — shallow fade, light blur. Kit card stays crisp
   at every width, and selecting the downsell card kills the veil for good (never veil a
   customer's chosen option). */
@media(max-width:900px){
  .pdp-v3 .fold-veil{display:block;position:fixed;left:0;right:0;bottom:0;height:64px;z-index:40;pointer-events:none;
    background:linear-gradient(to top,rgba(255,255,255,.7) 0%,rgba(255,255,255,.4) 45%,rgba(255,255,255,0) 100%);
    -webkit-backdrop-filter:blur(2.5px);backdrop-filter:blur(2.5px);
    -webkit-mask-image:linear-gradient(to top,#000 35%,transparent 100%);mask-image:linear-gradient(to top,#000 35%,transparent 100%);
    opacity:1;transition:opacity .35s ease}
  .pdp-v3 .fold-veil.off{opacity:0}
}
.pdp-v3 .opt[data-opt="kit"]{position:relative;z-index:45}
html.v3-veil-dead .pdp-v3 .fold-veil{display:none}

/* Direction-aware sticky bars (Instagram pattern): scrolling down compacts the bar so content
   breathes; scrolling up springs it back to full size — the size change is the attention cue.
   JS skips the toggle under prefers-reduced-motion. */
@media(min-width:901px){
  .pdp-v3 .desk-bar{transform-origin:50% 100%}
  .pdp-v3 .desk-bar.show.compact{transform:translate(-50%,0) scale(.9)}
}
@media(max-width:900px){
  .pdp-v3 .mobile-bar{transform-origin:50% 100%}
  .pdp-v3 .mobile-bar.show.compact{transform:scale(.92)}
}

/* Compare table, mobile: make the sideways pan discoverable.
   Root cause of the old version: a hard border with a cleanly clipped right edge
   reads as a finished box. Three layers, only two visible at rest.
   1) the last column bleeds out under a gradient instead of being cut flush
   2) a hairline rail under the table shows position and how much is left
   3) a single one-time nudge (JS) shows the table moves, then hands control back */
@media(max-width:900px){
  .pdp-v3 #compare .cmp-scroller{position:relative}
  .pdp-v3 #compare .tablewrap{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0;
    -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 46px),rgba(0,0,0,.25) 100%);
    mask-image:linear-gradient(to right,#000 calc(100% - 46px),rgba(0,0,0,.25) 100%);
    scroll-behavior:auto}
  .pdp-v3 #compare .tablewrap.at-end{-webkit-mask-image:none;mask-image:none;border-right:1px solid #45423b}
  .pdp-v3 #compare .tablewrap.no-pan{-webkit-mask-image:none;mask-image:none;border-right:1px solid #45423b}
  .pdp-v3 #compare .cmp-rail{height:2px;border-radius:2px;background:#e2ddd0;margin:12px 0 0;overflow:hidden}
  .pdp-v3 #compare .tablewrap.no-pan ~ .cmp-rail{display:none}
  .pdp-v3 #compare .cmp-rail span{display:block;height:100%;width:12%;border-radius:2px;background:#a9802d;
    transition:width .18s linear}
}
@media(max-width:900px) and (prefers-reduced-motion:reduce){
  .pdp-v3 #compare .cmp-rail span{transition:none}
}

/* Method steps, mobile: the step rows carried their own 20px padding INSIDE the wrap's 20px,
   so the numbers sat at 40px while every section headline sat at 20px. Drop the horizontal
   padding so the numbers land on the same left rail as the rest of the page. */
@media(max-width:560px){
  .pdp-v3 #method .msx{padding-left:0;padding-right:0}
}

/* Buy box restructure (2026-08-31): no card preselected, ribbon straddles the top border,
   card title leads the hierarchy, price carries its struck compare inline, gear strip is
   selection-gated and mirrored greyed-out on the solo card, dispatch line gets a live
   countdown to the 11am EST cutoff. */
.pdp-v3 .opt[data-opt="kit"]{overflow:visible}
.pdp-v3 .bv-ribbon{position:absolute;top:-13px;right:16px;background:#141310;color:#f0d488;
  font-size:12px;font-weight:600;letter-spacing:.13em;text-transform:uppercase;
  padding:6px 16px;border-radius:999px;line-height:1;z-index:2}
.pdp-v3 .opt .kit-title{font-size:26px;letter-spacing:-.01em}
.pdp-v3 .kit-priceline{display:flex;justify-content:space-between;align-items:baseline;gap:12px}
.pdp-v3 .kit-priceline .pnow{font-size:21px;font-weight:600;color:var(--ink)}
.pdp-v3 .kit-priceline .pwas{font-weight:400;font-size:16px;color:#9c968a}
.pdp-v3 .kit-priceline .pwas s{color:#9c968a}
.pdp-v3 .kitwrap{max-height:0;opacity:0;overflow:hidden;margin:0;
  transition:max-height .35s ease,opacity .3s ease}
.pdp-v3 .opt.on .kitwrap{max-height:300px;opacity:1;margin-top:4px}
.pdp-v3 .kitwrap .kithd{margin-top:10px}
.pdp-v3 .solo-gear .kitgrid{filter:grayscale(1)}
.pdp-v3 .solo-gear .kt{opacity:.55}
.pdp-v3 .solo-gear .kithd{color:#8a6a17}
@media(max-width:560px){
  .pdp-v3 .bv-ribbon{right:12px;font-size:11px;padding:5px 13px}
  .pdp-v3 .opt .kit-title{font-size:21px}
  .pdp-v3 .kit-priceline .pnow{font-size:18px}
  .pdp-v3 .kit-priceline .pwas{font-size:14px}
  .pdp-v3 .opt.on .kitwrap{max-height:300px}
}

/* Parity mode (2026-08-31, owner call): the two options carry equal visual weight.
   Solo card title/price match the kit card, the BEST VALUE ribbon is gone, and the
   fold veil is retired: its only job was de-emphasising the solo card. Revert by
   removing this block and restoring the ribbon markup. */
.pdp-v3 .opt.slim .opt-nm{font-size:26px;letter-spacing:-.01em}
.pdp-v3 .opt.slim .p2{font-size:21px;font-weight:600;color:var(--ink)}
.pdp-v3 .fold-veil{display:none !important}
@media(max-width:560px){
  .pdp-v3 .opt.slim .opt-nm{font-size:21px}
  .pdp-v3 .opt.slim .p2{font-size:18px}
}

/* Density pass (2026-08-31): one price statement (badge + struck compare), one tick (the
   foil differentiator), gear tiles carry image + label only — the heading already totals
   the $71. "You save" line and per-tile prices removed as redundant. */
.pdp-v3 .kt s{display:none}

/* Card coherence pass (2026-08-31): both cards share one header grammar —
   radio + title on the left, price on the right — and the tick list gets air
   below the header so the large type reads as its own tier. */
.pdp-v3 .opt-hd .p2{margin-left:auto;font-size:21px;font-weight:600;color:var(--ink);white-space:nowrap}
.pdp-v3 .kit-p2 .pwas{font-weight:400;font-size:15px;color:#9c968a}
.pdp-v3 .kit-p2 .pwas s{color:#9c968a}
.pdp-v3 .opt .ticks{margin-top:16px}
@media(max-width:560px){
  .pdp-v3 .opt-hd{flex-wrap:wrap;row-gap:2px}
  .pdp-v3 .opt-hd .p2{font-size:18px}
  .pdp-v3 .kit-p2{flex-basis:100%;text-align:right;margin-left:0}
  .pdp-v3 .kit-p2 .pwas{font-size:13px}
  .pdp-v3 .opt .ticks{margin-top:12px}
}

/* Price colour pass (2026-08-31): struck compare in red, SAVE badge and the save line in
   green, BEST VALUE pill back — centered and sitting on the card's top stroke. */
.pdp-v3 .kit-p2 .pwas, .pdp-v3 .kit-p2 .pwas s{color:var(--red)}
.pdp-v3 .savebadge{background:#eef7f1;color:var(--green)}
.pdp-v3 .bv-ribbon{left:50%;right:auto;transform:translateX(-50%)}
/* Contrast fix (gradientdeck audit): IN THE BOX micro-label was large-label gold #a9802d
   at 11px on cream = 3.55:1. Small labels use the dark gold token per the design system. */
.pdp-v3 .kithd{color:#8a6a17}

/* Card anatomy per owner mock (2026-09-01): hairline dividers zone the card
   (price | ticks | contents), SAVE badge rides the right rail, price pair sits
   under the title with the save line, and the gear strip becomes a bordered
   panel with a static grid and per-item prices. */
.pdp-v3 .cardline{border-top:1px solid #ede7da;margin:14px 0}
.pdp-v3 .opt-hd .badge-r{margin-left:auto}
.pdp-v3 .kit-pricewrap{margin-top:2px}
.pdp-v3 .kit-pricewrap .pnow{font-size:24px;font-weight:600;color:var(--ink)}
.pdp-v3 .kit-pricewrap .pwas{font-weight:400;font-size:15px}
.pdp-v3 .kitpanel{border:1px solid var(--line);border-radius:12px;padding:14px 16px;background:#fff;margin-top:2px}
.pdp-v3 .kitpanel .kithd{margin:0 0 12px}
.pdp-v3 .kitpanel .kitgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px 8px;max-width:none;transform:none}
.pdp-v3 .kitpanel .kt{width:auto;min-width:0;margin:0;padding:3px 3px 6px}
.pdp-v3 .kt s{display:block}
.pdp-v3 .opt .ticks{margin:0 0 2px;gap:9px}
.pdp-v3 .opt.on .kitwrap{max-height:560px}
@media(max-width:560px){
  .pdp-v3 .kitpanel .kitgrid{gap:10px 6px}
  .pdp-v3 .kitpanel .kt .box{height:52px}
  .pdp-v3 .kit-pricewrap .pnow{font-size:20px}
  .pdp-v3 .opt.on .kitwrap{max-height:640px}
}

/* Marquee back inside the bordered panel (2026-09-01): drift + drag as before, framed
   by the panel with its heading and per-item prices. Overrides the brief static-grid pass. */
.pdp-v3 .kitpanel .kitgrid{display:flex;width:max-content;grid-template-columns:none;gap:0}
.pdp-v3 .kitpanel .kt{width:104px;min-width:104px;margin:0 8px 0 0;flex:none}
.pdp-v3 .kitpanel .kitrow{overflow:hidden;max-width:100%;cursor:grab;touch-action:pan-y;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
@media(max-width:560px){.pdp-v3 .kitpanel .kt{width:96px;min-width:96px}}

/* No secondary white surfaces inside the buy box (2026-09-01): the gear panel and the
   per-tile boxes lose their white fills and sit on the card itself. The panel keeps its
   hairline so the mock's zoning survives without a second background layer.
   Price arrangement restored: struck compare left of the sale price on the right rail,
   save line right-aligned beneath it. */
.pdp-v3 .kitpanel{background:transparent}
.pdp-v3 .kt .box{background:transparent}

/* Colour selector follows the same rule on every card (2026-09-01): visible only while the
   card is selected. Its divider collapses with it so no orphan hairline is left behind. */
.pdp-v3 .opt .sw-wrap{max-height:0;opacity:0;overflow:hidden;margin:0;
  transition:max-height .35s ease,opacity .3s ease,margin .35s ease}
.pdp-v3 .opt.on .sw-wrap{max-height:130px;opacity:1;margin:2px 0 16px}
.pdp-v3 .opt.slim.on .sw-wrap{margin:12px 0 4px}
.pdp-v3 .opt .cardline.dyn{max-height:0;opacity:0;margin:0;overflow:hidden;
  transition:max-height .35s ease,opacity .3s ease,margin .35s ease}
.pdp-v3 .opt.on .cardline.dyn{max-height:2px;opacity:1;margin:14px 0}
@media(prefers-reduced-motion: reduce){
  .pdp-v3 .opt .sw-wrap, .pdp-v3 .opt .cardline.dyn{transition:none}
}

/* FINAL SWEEP (2026-09-01) — one type scale across both option cards.
   Audit found: solo subline off-tier (13/500 vs body 14/400), card paddings unequal
   (18/18/20 vs 13/16), badge below the 10.5px micro floor, save line off-scale at 13.5px,
   tile label/price off-scale and line-height 1.17, and only 24px of air between the spec
   chips and the card (12px to the ribbon). */

/* air above the buy box so the ribbon clears the spec chips */
.pdp-v3 .opts{margin-top:34px}

/* identical padding on both cards */
.pdp-v3 .opt, .pdp-v3 .opt.slim{padding:18px 18px 20px}

/* body tier: ticks and the solo subline read at the same weight and colour */
.pdp-v3 .opt .subline{font-size:14px;color:var(--ink2)}
.pdp-v3 .opt .subline span{font-size:14px;font-weight:400;color:var(--ink2);line-height:1.4}

/* micro tier: badge back above the 10.5px floor, tiles on-scale with readable leading */
.pdp-v3 .savebadge{font-size:11px}
.pdp-v3 .kt span{font-size:12px;font-weight:600;line-height:1.3}
.pdp-v3 .kt s{font-size:12px;font-weight:400}

@media(max-width:560px){
  .pdp-v3 .opts{margin-top:26px}
  .pdp-v3 .opt, .pdp-v3 .opt.slim{padding:16px 16px 18px}
}
.pdp-v3 .kitrow .kt s{font-size:12px;font-weight:400}

/* ATC stamp (2026-09-01, owner): the button states the action, not the price. The kit's
   discount rides it as an inset pill — gold on ink, the same palette inversion the BEST
   VALUE ribbon uses, so the two read as one family. The solo button carries no stamp:
   there is no discount on that option and a false one would be worse than none. */
.pdp-v3 .opt-cta{display:flex;align-items:center;justify-content:center;gap:10px}
.pdp-v3 .cta-save{background:#f0d488;color:#141310;font-size:11px;font-weight:600;
  letter-spacing:.09em;padding:4px 9px;border-radius:999px;line-height:1;flex:none;
  text-transform:uppercase}
@media(hover:hover){
  .pdp-v3 .opt-cta:hover .cta-save{background:#fff}
}
@media(max-width:560px){
  .pdp-v3 .opt-cta{gap:8px}
  .pdp-v3 .cta-save{font-size:10.5px;padding:3px 7px}
}
@media(prefers-reduced-motion: reduce){.pdp-v3 .cta-save{transition:none}}

/* Swatch rhythm identical on both cards (2026-09-01): the solo card carried a legacy
   12px/4px margin from when it was the slim downsell, leaving only 6px under the swatches
   against the kit's 18px. Both now use one value, and the solo's subline divider matches
   the kit's cardline rhythm above it. */
.pdp-v3 .opt.slim.on .sw-wrap{margin:2px 0 16px}
.pdp-v3 .opt .subline{padding-bottom:14px;margin-bottom:14px}

/* Final CTA carries the same stamp as the kit button. On the gold CTA the pill inverts to
   ink so the pair reads as one family across both button colours. */
.pdp-v3 .final .cta{display:inline-flex;align-items:center;justify-content:center;gap:10px}
.pdp-v3 .final .cta-save{background:#141310;color:#f0d488}
@media(hover:hover){.pdp-v3 .final .cta:hover .cta-save{background:#000}}

/* Sweep fixes (2026-09-01).
   1. Rating stars were large-label gold on cream: 3.26-3.61:1, under AA. They carry the
      rating meaning next to the score, so they use the dark-gold small-label token.
   2. Utility-bar messages are clickable but only 20px tall, under the 24px WCAG 2.5.8
      target floor; padding lifts the hit area without moving the text.
   3. Reviews toggle raised to a 44px thumb target. */
.pdp-v3 .rating-row .stars, .pdp-v3 .stars{color:#8a6a17}
.pdp-v3 .announce.u-bar .u-msg{display:inline-block;padding:4px 2px}
.pdp-v3 .rev-toggle{min-height:44px}
.pdp-v3 #reviews .stars{color:#8a6a17}

/* Swatch clip fix (2026-09-01): the collapse wrapper uses overflow:hidden, and the circles
   sat flush on its bottom edge, so each swatch's 1px ring (and the selected ring) was
   sheared off. Six px of interior room, taken back out of the margin so the outer rhythm
   below the swatches stays at 16px on both cards. */
.pdp-v3 .opt.on .sw-wrap, .pdp-v3 .opt.slim.on .sw-wrap{padding-bottom:6px;margin:2px 0 10px}

/* Sticky bars carry the same stamp, and only while the kit is the active option:
   the solo shaver has no discount, so the pill hides rather than lying. */
.pdp-v3 .mobile-bar button, .pdp-v3 .desk-bar .db-cta{display:flex;align-items:center;justify-content:center;gap:8px}
.pdp-v3 .mobile-bar .cta-save, .pdp-v3 .desk-bar .cta-save{font-size:10.5px;padding:3px 7px}
.pdp-v3 [data-bar-save][hidden]{display:none}

/* Gear section loses its sub-container (2026-09-01): no nested box inside the card, just a
   hairline divider matching the card's other rules. Dropping the 16px inner padding also
   puts the gear on the card's own content rail. */
.pdp-v3 .kitpanel{border:0;border-top:1px solid #ede7da;border-radius:0;padding:14px 0 0;margin-top:0}

/* Gear now precedes the colour selector (2026-09-01) so every input the buyer touches -
   colour, quantity, add to cart - sits together at the foot of the card. The dividers are
   real .cardline rules again, so the gear block carries none of its own. */
.pdp-v3 .kitpanel{border-top:0;padding-top:0}

/* Form semantics (2026-09-01): the option cards now carry a real radio input, visually
   hidden but focusable, so arrow keys and Space work natively and assistive tech announces
   the choice. The visible ring follows the input's focus. */
.pdp-v3 .opt-input{position:absolute;opacity:0;width:1px;height:1px;margin:0;pointer-events:none}
.pdp-v3 .opt:has(.opt-input:focus-visible){outline:2px solid var(--ink);outline-offset:3px}
.pdp-v3 .sw:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
.pdp-v3 .sw[aria-disabled="true"]{cursor:not-allowed}

/* Above the fold (2026-09-01, team review): spec bubbles cut; the promise line becomes two
   scannable bullets. Type stays at the subpromise size so the hierarchy is unchanged. */
.pdp-v3 ul.subpromise{list-style:none;margin:0 0 24px;padding:0;display:grid;gap:8px}
.pdp-v3 ul.subpromise li{position:relative;padding-left:20px;font-size:16.5px;color:var(--ink2);line-height:1.45}
.pdp-v3 ul.subpromise li::before{content:"";position:absolute;left:2px;top:.62em;width:6px;height:6px;
  border-radius:50%;background:var(--gold)}
@media(max-width:560px){
  .pdp-v3 ul.subpromise li{font-size:15.5px;padding-left:18px}
  .pdp-v3 ul.subpromise{margin-bottom:20px}
}

/* Promise bullets (2026-09-01): kill the theme's native marker that was doubling the gold
   dot, and step the text up one tier so it reads as the value proposition, not a footnote. */
.pdp-v3 ul.subpromise, .pdp-v3 ul.subpromise li{list-style:none}
.pdp-v3 ul.subpromise li::marker{content:""}
.pdp-v3 ul.subpromise li{font-size:18px;font-weight:500;color:var(--ink);line-height:1.4}
.pdp-v3 ul.subpromise li::before{top:.58em;width:7px;height:7px}
@media(max-width:560px){.pdp-v3 ul.subpromise li{font-size:16.5px}}

/* Promise bullets, final (2026-09-01): back to the 16.5px body size, emphasis via weight and
   ink rather than scale. Measured against the 598px column: 600 weight with -0.01em tracking
   keeps the 77-character line single with 19px to spare; anything larger wrapped or landed
   inside 7px, which Windows font rendering would eat. */
.pdp-v3 ul.subpromise li{font-size:16.5px;font-weight:600;letter-spacing:-.01em;color:var(--ink);line-height:1.4}
.pdp-v3 ul.subpromise li::before{top:.55em;width:6px;height:6px}
@media(max-width:560px){.pdp-v3 ul.subpromise li{font-size:15.5px}}

/* Compare table header (2026-09-01): the header row sat in the same cream as the page and
   disappeared. Ink header, white brand names, muted subs, and the Aberlite column's header
   in gold so the highlighted column still leads. Applies to the sticky corner cell and the
   mobile pan as well; the !important mirrors the section rule it has to beat. */
.pdp-v3 #compare thead th{background:#141310;color:#fff;border-bottom:1px solid #2a2822}
.pdp-v3 #compare thead .th-feature{background:#141310;color:#d9d5cc;border-right-color:#2a2822}
.pdp-v3 #compare thead th .brandname{color:#fff}
.pdp-v3 #compare thead th .brandsub{color:#b8b2a4}
.pdp-v3 #compare thead .col-us{background:#141310 !important;border-top:2px solid #c9a868}
.pdp-v3 #compare thead .col-us .brandname{color:#f0d488}
.pdp-v3 #compare thead .col-us .brandsub{color:#d4b56a}

/* Compare table header, light (2026-09-02): team keeps the light theme. Warm stone fill from
   the hairline token separates the head from the cream page without a dark band; the
   Aberlite column header keeps its gold outline and takes the small-label gold. Brand names
   stay on one line. Overrides the ink pass above. */
.pdp-v3 #compare thead th{background:#ede7da;color:var(--ink);border-bottom:1px solid #e0d9c8}
.pdp-v3 #compare thead .th-feature{background:#ede7da;color:var(--ink2);border-right-color:#e0d9c8}
.pdp-v3 #compare thead th .brandname{color:var(--ink);white-space:nowrap}
.pdp-v3 #compare thead th .brandsub{color:var(--mut)}
.pdp-v3 #compare thead .col-us{background:#ede7da !important;border-top:2px solid #c9a868}
.pdp-v3 #compare thead .col-us .brandname{color:#8a6a17}
.pdp-v3 #compare thead .col-us .brandsub{color:#8a6a17}

/* Compare table header, white (2026-09-02): pure white head on the near-white body, with the
   hairline token as its bottom edge so the band still has a defined foot. Overrides the
   stone pass above. */
.pdp-v3 #compare thead th{background:#fff;border-bottom:1px solid var(--line)}
.pdp-v3 #compare thead .th-feature{background:#fff;border-right-color:var(--line)}
.pdp-v3 #compare thead .col-us{background:#fff !important}

/* Compare table per team spec (2026-09-02): "Feature" bold, darker rule under the header row. */
.pdp-v3 #compare thead .th-feature{font-weight:700;color:var(--ink)}
.pdp-v3 #compare thead th{border-bottom:1px solid #45423b}

/* Compare table (2026-09-02): no outer stroke. The rows' own hairlines carry the structure;
   the mobile pan states that restored a right edge drop it too. */
.pdp-v3 #compare .tablewrap,
.pdp-v3 #compare .tablewrap.at-end,
.pdp-v3 #compare .tablewrap.no-pan{border:0}

/* Compare table header emphasis (2026-09-02): taller band, brand names up a tier. */
.pdp-v3 #compare thead th{padding-top:22px;padding-bottom:22px;vertical-align:middle}
.pdp-v3 #compare thead th .brandname{font-size:15.5px;letter-spacing:-.01em}
.pdp-v3 #compare thead th .brandsub{font-size:12.5px;margin-top:3px}
.pdp-v3 #compare thead .th-feature{font-size:15px}
@media(max-width:560px){
  .pdp-v3 #compare thead th{padding-top:18px;padding-bottom:18px}
  .pdp-v3 #compare thead th .brandname{font-size:14.5px}
  .pdp-v3 #compare thead .th-feature{font-size:14px}
}

/* ===== FIRST-FOLD ENTRANCE (2026-09-02) =====
   Apple-style settle: critically damped (no overshoot), transform + opacity only, staggered
   so the stack reads as settling into place. html.v3-enter-arm is set before the hero paints
   (no flash), html.v3-enter starts it. Reduced motion never arms, so nothing is ever hidden. */
@keyframes v3-rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@keyframes v3-settle{from{opacity:0;transform:scale(1.03)}to{opacity:1;transform:none}}
@keyframes v3-fade{from{opacity:0}to{opacity:1}}

/* armed: hold everything at its start pose */
html.v3-enter-arm .pdp-v3 .hero .buybox > *,
html.v3-enter-arm .pdp-v3 .hero .buybox-head-m > *,
html.v3-enter-arm .pdp-v3 .hero .gallery > .shot,
html.v3-enter-arm .pdp-v3 .hero .gallery > .thumbs{opacity:0}
html.v3-enter-arm .pdp-v3 .announce, html.v3-enter-arm .pdp-v3 .topnav{opacity:0}

/* started: play, then hold the end pose */
html.v3-enter .pdp-v3 .announce, html.v3-enter .pdp-v3 .topnav{animation:v3-fade .42s ease-out both}
html.v3-enter .pdp-v3 .hero .gallery > .shot{animation:v3-settle .72s cubic-bezier(.22,1,.36,1) both;animation-delay:60ms;will-change:transform,opacity}
html.v3-enter .pdp-v3 .hero .gallery > .thumbs{animation:v3-rise .56s cubic-bezier(.22,1,.36,1) both;animation-delay:280ms}
html.v3-enter .pdp-v3 .hero .buybox > *{animation:v3-rise .56s cubic-bezier(.22,1,.36,1) both}
html.v3-enter .pdp-v3 .hero .buybox > :nth-child(1){animation-delay:140ms}
html.v3-enter .pdp-v3 .hero .buybox > :nth-child(2){animation-delay:195ms}
html.v3-enter .pdp-v3 .hero .buybox > :nth-child(3){animation-delay:250ms}
html.v3-enter .pdp-v3 .hero .buybox > :nth-child(4){animation-delay:305ms}
html.v3-enter .pdp-v3 .hero .buybox > :nth-child(5){animation-delay:360ms}
html.v3-enter .pdp-v3 .hero .buybox > :nth-child(6){animation-delay:415ms}
html.v3-enter .pdp-v3 .hero .buybox > :nth-child(7){animation-delay:470ms}
html.v3-enter .pdp-v3 .hero .buybox > :nth-child(n+8){animation-delay:525ms}
/* mobile: the headline block sits above the gallery, so it leads */
html.v3-enter .pdp-v3 .hero .buybox-head-m > *{animation:v3-rise .56s cubic-bezier(.22,1,.36,1) both}
html.v3-enter .pdp-v3 .hero .buybox-head-m > :nth-child(1){animation-delay:60ms}
html.v3-enter .pdp-v3 .hero .buybox-head-m > :nth-child(2){animation-delay:115ms}
html.v3-enter .pdp-v3 .hero .buybox-head-m > :nth-child(3){animation-delay:170ms}
@media(max-width:900px){
  html.v3-enter .pdp-v3 .hero .gallery > .shot{animation-delay:240ms}
  html.v3-enter .pdp-v3 .hero .gallery > .thumbs{animation-delay:380ms}
  html.v3-enter .pdp-v3 .hero .buybox > :nth-child(4){animation-delay:440ms}
  html.v3-enter .pdp-v3 .hero .buybox > :nth-child(5){animation-delay:495ms}
  html.v3-enter .pdp-v3 .hero .buybox > :nth-child(n+6){animation-delay:550ms}
}
/* the sticky container is .gallery; the animated node is its child, and the keyframe ends at transform:none, so nothing lingers */
html.v3-enter .pdp-v3 .hero .gallery > .shot{animation-fill-mode:both}

/* Compare table feature column (2026-09-02): more inset from the table's edge. */
.pdp-v3 #compare tbody th, .pdp-v3 #compare thead .th-feature{padding-left:24px;padding-right:18px}
@media(max-width:560px){
  .pdp-v3 #compare tbody th, .pdp-v3 #compare thead .th-feature{padding-left:20px;padding-right:14px}
}

/* Swatch ring clip, left edge (2026-09-02): the selected ring sits 1px outside the circle and
   the first circle was flush on the collapse wrapper's overflow:hidden edge. 3px of interior
   room on the left, pulled back with a negative margin so the rail does not move. */
.pdp-v3 .opt.on .sw-wrap, .pdp-v3 .opt.slim.on .sw-wrap{padding-left:3px;margin-left:-3px}

/* Mobile sticky bar (2026-09-02): the SAVE stamp leaves the ATC pill and rides the price
   line, so the button carries one message and the discount reads against the number it
   discounts. Two lines, not three - name, then price + stamp - so the bar keeps its height.
   Mobile only: the mobile bar is itself mobile-only, and the desktop dock keeps the stamp on
   its button. The price line is its own .mb-line flex row - flex centres the pill on the price
   optically, which a baseline-aligned inline-block does not. It has to be that wrapper and not
   .p itself: a flex .p reports the whole row as its max-content (name + price + pill on one
   line), which starved the button and wrapped ADD TO CART onto three lines.
   :not([hidden]) so the solo-option hide still wins - the stamp is only true while the kit is
   the active option. */
.pdp-v3 .mobile-bar .p .mb-line{display:flex;align-items:center;column-gap:6px}
.pdp-v3 .mobile-bar .p .mb-save:not([hidden]){display:inline-block;margin-top:0;
  font-size:10px;padding:2.5px 7px;letter-spacing:.08em}

/* Kit card pass (2026-09-04, owner).
   1. SAVE stamp on the card title inverts to ink. The text stays green, but not the --green
      token: #1e7b45 on #141310 is 3.52:1, under AA for 11px text, and the stars/IN THE BOX
      fixes in this file set the precedent. #3aa564 is the same hue, lifted to 6.05:1.
   2. Tick bullets become a solid black circle-check. The glyph carried its meaning in colour
      alone; the mark now carries it in shape, so it reads without the green.
   3. .saveline (You save $...) and .opt-sub (the 11am dispatch line, and the countdown that
      fed it) are gone from the markup, schema and JS - see git for the countdown if the
      cutoff is ever confirmed. */
.pdp-v3 .savebadge{background:#141310;color:#3aa564}
.pdp-v3 .opt .tick i{align-self:flex-start;display:block;line-height:0;font-size:0;margin-top:2px}
.pdp-v3 .opt .tick i svg{display:block;width:16px;height:16px}

/* The .opt-buy collapse ceilings were sized around the dispatch line that row no longer
   carries: measured content is now 48px desktop / 104.8px mobile against 110px / 210px of
   max-height, so the expand animated most of its distance through empty space. Retuned with
   slack for a longer button label. */
.pdp-v3 .opt.on .opt-buy{max-height:64px}
@media(max-width:560px){.pdp-v3 .opt.on .opt-buy{max-height:124px}}

/* Solo card gets the kit's price treatment (2026-09-04, owner): a struck compare price in
   red ahead of the live one. Sized in em so it tracks whatever the price scale is at each
   breakpoint - the kit's pair runs ~.62 of the price, and this matches it. The strike is on
   the element itself rather than a wrapper so the rule inherits the red instead of staying
   the browser's currentColor. */
.pdp-v3 .opt.slim .solo-p2 .pwas{font-weight:400;font-size:.64em;color:var(--red);
  text-decoration-color:var(--red);margin-right:2px}

/* Press bar (2026-09-04, owner) replaces the proof-numbers stats. One flat SVG, so it cannot
   reflow to two rows on mobile - it scales instead, and the cap keeps the logos from
   collapsing to hairlines on a narrow phone. Black is baked into the asset rather than
   applied with a brightness() filter, so the fill is a real colour value. */
.pdp-v3 .pressband{padding:56px 0}
.pdp-v3 .pressband .wrap{display:flex;flex-direction:column;align-items:center;gap:22px}
.pdp-v3 .press-hd{font-size:11px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  color:#8a6a17;margin:0}
/* One logo per outlet with its pull quote under it (2026-09-04, owner). The three marks have
   very different proportions - NYT is 7.3:1, Men's Health 4.5:1, GQ nearly square - so they are
   sized by HEIGHT in a shared 28px box with object-fit:contain. Sizing by width would blow GQ
   up to several times the others' cap height. */
.pdp-v3 .pressgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:34px;width:100%;
  align-items:start}
.pdp-v3 .pressitem{display:flex;flex-direction:column;align-items:center;gap:14px;margin:0}
.pdp-v3 .press-logo{height:28px;display:flex;align-items:center;justify-content:center;width:100%}
.pdp-v3 .press-logo img{max-height:100%;max-width:100%;width:auto;height:auto;display:block}
.pdp-v3 .pressitem blockquote{font-size:14.5px;line-height:1.55;color:var(--ink2);text-align:center;
  max-width:330px;margin:0}
@media(max-width:760px){
  .pdp-v3 .pressgrid{grid-template-columns:1fr;gap:26px}
  .pdp-v3 .pressitem blockquote{max-width:420px}
}
@media(max-width:560px){
  .pdp-v3 .pressband{padding:40px 0}
  .pdp-v3 .press-logo{height:24px}
  .pdp-v3 .pressitem blockquote{font-size:14px}
}

/* Save stamps go solid green with white text (2026-09-04, owner), replacing the ink pill from
   earlier today. --green (#1e7b45) is the design-system token rather than a new near-duplicate
   hex; white on it measures 5.35:1, clear of AA at 11px. Both option cards carry one now: the
   kit's 40% and the solo card's 20%, which is exactly $99.99 -> $79.99. The .cta-save pills
   inside the buttons are untouched and stay gold. */
.pdp-v3 .savebadge{background:var(--green);color:#fff}

/* HOW IT WORKS (2026-09-04, owner): the split "methodstrip" - copy left, numbered rule-list
   right - becomes a centred header over two photo cards. The old #method rules lived in that
   section's own {% style %} block and left with it. Strokeless white cards, so they take the
   house hover ring (inset, no layout shift). Aspect ratio is pinned to the source render
   (1536x1060) so the pair cannot jitter as the images decode. */
.pdp-v3 #method .mhead .lede{margin-top:12px;max-width:640px}
.pdp-v3 #method .ms-note{font-size:13.5px;color:var(--ink2);margin-top:14px}
.pdp-v3 #method .center .ms-note{margin-left:auto;margin-right:auto;max-width:640px}
.pdp-v3 .mcards{display:grid;grid-template-columns:repeat(2,1fr);gap:24px;margin-top:38px}
.pdp-v3 .mcard{background:#fff;border-radius:var(--radius);overflow:hidden;padding:0 20px 20px;
  transition:box-shadow .18s ease}
.pdp-v3 .mcard .mshot{border-radius:0;overflow:hidden;aspect-ratio:4/3;background:var(--cream);margin:0 -20px}
.pdp-v3 .mcard .mshot img{width:100%;height:100%;object-fit:cover;display:block}
.pdp-v3 .mcard .mbody{padding:16px 0 0;display:flex;gap:14px;align-items:flex-start}
/* Step numeral: largest glyph in the card by size, lightest by weight, so the h3 still leads the read. Jost ships 400/500/600 only. */
.pdp-v3 .mcard .mnum{flex:none;font-size:38px;font-weight:400;line-height:1;letter-spacing:-.02em;color:#a9802d;font-variant-numeric:tabular-nums;margin-top:-1px}
/* h3 + p sit on the same scale as the Mechanism cards (#why .micro): 21px/600 over 14px */
.pdp-v3 .mcard h3{font-size:21px;font-weight:600;letter-spacing:-.01em}
.pdp-v3 .mcard p{font-size:14px;color:#5a564c;line-height:1.5;margin-top:5px}
@media(prefers-reduced-motion: reduce){.pdp-v3 .mcard{transition:none}}
@media(max-width:700px){
  .pdp-v3 .mcards{grid-template-columns:1fr}
  .pdp-v3 .mcard .mnum{font-size:32px}
}

/* Benefit / review cards (2026-09-04, owner): four cards under the press bar, quote revealed
   on hover. Revised twice the same day - 2x2 and light, per the owner.

   Grid: 2x2, not 4 across. At 4-up the card was 272px and the before/after pair inside it was
   182px tall; at 2-up it is roughly twice that, which is what these side-by-side shots need to
   read at all.

   Height: no aspect-ratio. The card reserves a fixed 132px of padding-bottom for the collapsed
   panel and the photo sits above it at its source ratio (2528x1696), so the card is exactly as
   tall as photo + panel at ANY column width. The earlier fixed ratio only balanced at one
   width and either cropped or left slack elsewhere.

   Hover: the panel is absolutely positioned and grows OVER the photo. An earlier cut grew it
   by shrinking the photo row, which collapsed the photo to 53px on the 304-character quote.
   Photo never resizes, card never changes height, neighbours never move.

   Palette: white card on the cream band, the same strokeless-white-card vocabulary as the spec
   cards and review cards elsewhere, so it takes the ink hover ring rather than a gold one.
   Small labels use the dark gold #8a6a17, not the large-label #a9802d - the contrast rule this
   file already applies to the rating stars and the IN THE BOX label.

   The reveal is INVERTED against the usual pattern - the quote is visible by default and only
   collapses inside @media(hover:hover). Touch reports no hover, so a hover-only reveal would
   hide it permanently on phones, which the build notes forbid. :focus-within opens it for
   keyboard users. */
.pdp-v3 .bcards-sec .bc-head .lede{margin-top:12px;max-width:640px}
/* Benefit cards · Filmstrip peek (2026-09-04, Direction A, replaces the 2-up dots carousel).
   Header is centred like every other v3 section; no arrows. The track shows two full cards + an
   18% peek of the third, which is the "more exists" signal; the rule under the cards is the
   position readout and the scrubber. The
   quote is always visible as a two-line excerpt; a real button expands it and the panel grows OVER
   the photo, so card height and neighbours never move. Native overflow scrolling stays the
   transport (drag, trackpad, keyboard, JS-off all work). ONE motion spend: the critically damped
   settle that carries the peek card to full width (arrows + mouse flick); reduced motion jumps. */
.pdp-v3 .vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.pdp-v3 .bcards-sec .bc-head .lede{margin-left:auto;margin-right:auto}

/* Track. --peek is the fraction of the third card that shows; the JS reads real card widths so the
   maths lives here only. The right fade is a functional mask over the peek card; it switches off at the end. The left fade only
   appears when a card is actually cut on the left (JS ramps it from the distance to the nearest card boundary),
   so a flush card is never masked. */
.pdp-v3 .bcarousel{margin-top:38px}
.pdp-v3 .bcar-view{position:relative;border-radius:2px}
.pdp-v3 .bcards{--gap:24px;--peek:.18;--fade-l:0px;--fade-r:48px;
  display:flex;align-items:flex-start;gap:var(--gap);overflow-x:auto;
  scroll-snap-type:x mandatory;scrollbar-width:none;-ms-overflow-style:none;padding-bottom:2px;
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 var(--fade-l),#000 calc(100% - var(--fade-r)),transparent 100%);
          mask-image:linear-gradient(90deg,transparent 0,#000 var(--fade-l),#000 calc(100% - var(--fade-r)),transparent 100%)}
.pdp-v3 .bcards::-webkit-scrollbar{display:none}
/* No ring on the track (2026-09-06, owner saw the 2px offset box and read it as a defect). The track is
   out of the tab order; the arrows are the keyboard path and wear their own focus rings. */
.pdp-v3 .bcards:focus,.pdp-v3 .bcards:focus-visible{outline:none}
.pdp-v3 .bcards.is-free{scroll-snap-type:none}
.pdp-v3 .bcards > .bcard{flex:0 0 calc((100% - 2 * var(--gap)) / (2 + var(--peek)));scroll-snap-align:start}
/* Scroll-position rule under the track (Direction C graft): ink segment = the share of the track on
   screen, hairline = the rest. Driven from scrollLeft in the same paint as the count, so it is a
   readout of where you are, not a second motion. Hidden when nothing scrolls. */
.pdp-v3 .bcar-scrub{margin-top:10px;padding:12px 0;cursor:pointer;touch-action:pan-y;user-select:none}
.pdp-v3 .bcar-scrub[hidden]{display:none}
.pdp-v3 .bcar-rule{position:relative;height:2px;background:var(--line);border-radius:2px;overflow:hidden;transition:height .18s ease}
.pdp-v3 .bcar-rule span{position:absolute;left:0;top:0;height:100%;width:40%;background:var(--ink);border-radius:2px;will-change:transform}
@media(hover:hover){.pdp-v3 .bcar-scrub:hover .bcar-rule,.pdp-v3 .bcar-scrub.is-scrubbing .bcar-rule{height:4px}}
@media(prefers-reduced-motion: reduce){.pdp-v3 .bcar-rule{transition:none}}
@media(pointer:fine){
  .pdp-v3 .bcards{cursor:grab}
  .pdp-v3 .bcards.is-dragging{cursor:grabbing;user-select:none}
}

/* Card (2026-09-06, owner's Loom): white, strokeless, on the cream band. The photo is the ORIGINAL
   before/after screenshot at 790x525 (3:2); the panel sits under it in normal flow at every width, nothing
   clamped, nothing overlaid, centred like the live PDP's review cards. Title in ink caps, stars under it,
   the quote in regular weight with one phrase washed the lander green (#cff9a4, ink text), then name and
   the Verified pill. Cards size to their own quote at every width and rows top-align (owner's call,
   2026-09-06: the equal-height stretch left a white hole under short quotes). */
.pdp-v3 .bcard{position:relative;display:flex;flex-direction:column;border-radius:var(--radius);overflow:hidden;background:#fff}
.pdp-v3 .bcard .bc-img{flex:0 0 auto;aspect-ratio:790/525;width:100%;background:var(--cream)}
.pdp-v3 .bcard .bc-img img{width:100%;height:100%;object-fit:cover;display:block;-webkit-user-drag:none;user-select:none}
.pdp-v3 .bcard .bc-ph{width:100%;height:100%;display:flex;align-items:center;justify-content:center;
  background:repeating-linear-gradient(45deg,#f0eee9,#f0eee9 10px,#e9e6df 10px,#e9e6df 20px)}
.pdp-v3 .bcard .bc-ph b{font-size:10.5px;font-weight:600;letter-spacing:.14em;color:#9c968a}
.pdp-v3 .bcard .bc-panel{flex:1 1 auto;display:flex;flex-direction:column;align-items:center;text-align:center;
  padding:20px;background:#fff;color:var(--ink)}
.pdp-v3 .bcard .bc-role{font-size:16px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink);line-height:1.25;margin:0}
.pdp-v3 .bcard .bc-stars{color:#8a6a17;font-size:15px;letter-spacing:1px;line-height:1;margin:6px 0 0}
.pdp-v3 .bcard .bc-quote{font-size:15px;line-height:1.55;font-weight:400;color:var(--ink);margin:10px 0 0;
  padding:0;border:0;font-style:normal;quotes:none;max-width:40ch}
/* The base theme decorates blockquote with an italic face and an opening-quote pseudo glyph; both leak in. */
.pdp-v3 .bcard .bc-quote::before,.pdp-v3 .bcard .bc-quote::after{content:none}
.pdp-v3 .bcard .bc-hl{background:#cff9a4;color:inherit;padding:0 3px;margin:0 -3px;border-radius:3px;
  -webkit-box-decoration-break:clone;box-decoration-break:clone}
.pdp-v3 .bcard .bc-meta{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:6px 10px;margin:0;padding-top:14px;font-size:13px}
.pdp-v3 .bcard .bc-name{font-weight:600;color:var(--ink);font-size:13px;margin:0}
.pdp-v3 .bcard .bc-tag{font-size:10.5px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--ink2);
  border:1px solid var(--line);border-radius:999px;padding:3px 10px;line-height:1.3}

/* Tablet and down: one card + peek. */
@media(max-width:900px){
  .pdp-v3 .bcards{--gap:16px;--peek:.14}
  .pdp-v3 .bcards > .bcard{flex-basis:calc((100% - var(--gap)) / (1 + var(--peek)))}
}
/* Phones (83% of traffic): header stacks, controls become their own row above the track, the track
   bleeds to the screen edge so the peek runs off-screen, and the panel returns to normal flow so
   nothing overlays the photo. */
@media(max-width:560px){
  .pdp-v3 .bcar-view{margin:0 -20px}
  .pdp-v3 .bcards{--fade-r:28px;padding:0 20px 2px;scroll-padding-inline:20px}
  .pdp-v3 .bcards > .bcard{flex-basis:calc((100% - var(--gap)) / (1 + var(--peek)))}
  .pdp-v3 .bcard .bc-quote{font-size:14.5px}
  .pdp-v3 .bcar-scrub{margin-top:6px}
}

/* Compare table (2026-09-04, owner): a note can now hang under the ROW LABEL instead of under
   one cell's figure. "changing blades every 3 months" qualifies the whole 1-year-cost row, not
   just the Aberlite column it happened to sit in. The label cell is 600 weight, so the note
   resets to 500 to stay in the support tier rather than reading as a second heading. */
.pdp-v3 #compare tbody th .mini{font-weight:500;margin-top:3px}

/* Compare table brand shots (2026-09-04, owner): a small product image under each brand name.
   One fixed contain box per column, so four images with different framing and aspect ratios
   (the Touch 2 render is 16:9, the rest are square) all land the same size without cropping.
   alt is empty by design - the brand name sits directly above as text, so the image is
   decorative and a screen reader should not read the product twice. */
.pdp-v3 #compare thead .brandshot{display:block;height:54px;margin:9px auto 0}
.pdp-v3 #compare thead .brandshot img{width:100%;height:100%;object-fit:contain;display:block;margin:0 auto}
@media(max-width:560px){
  .pdp-v3 #compare thead .brandshot{height:42px;margin-top:7px}
}

/* Compare table pass (2026-09-04, owner), to the owner's second reference:
   1. The Touch 2 column goes to a pale yellow wash instead of the near-white it had drifted to
      through three earlier header overrides. One value for header and body so the column reads
      as a single block; the gold rule around it stays.
   2. Brand shot moves above the name.
   3. Tick and cross become filled circles with a white glyph, still green and red. They are
      rendered in Liquid from the plain "✓" / "✗" a merchant types, so the editor is unchanged
      and the mark carries its meaning in shape as well as colour - the same reasoning as the
      buy-box tick bullets. */
.pdp-v3 #compare .col-us{background:#fdf7e3 !important}
.pdp-v3 #compare thead .col-us{background:#fdf7e3 !important;border-top:2px solid var(--gold)}
.pdp-v3 #compare thead .col-us .brandname{color:#8a6a17}
.pdp-v3 #compare thead .col-us .brandsub{color:#8a6a17}
.pdp-v3 #compare thead .brandshot{margin:0 auto 8px}
.pdp-v3 #compare .cmp-ic{display:inline-flex;align-items:center;justify-content:center;line-height:0}
.pdp-v3 #compare .cmp-ic svg{display:block;width:20px;height:20px}
@media(max-width:560px){
  .pdp-v3 #compare .cmp-ic svg{width:18px;height:18px}
}

/* The Touch 2 brand name kept the large-label gold #a9802d, which measures 3.37:1 on the new
   #fdf7e3 wash - under AA at 13px. Small labels take the darker #8a6a17 per the design system,
   the same swap this file already made for the rating stars and the IN THE BOX label. */

/* Press bar (2026-09-04, owner): more air top and bottom - it was sitting hard against the
   band above on a 30px inline padding, which also beat every stylesheet rule. Padding moved
   into CSS so it is tunable in one place. Logos re-baked from ink to the muted grey #6a665c
   rather than dimmed with opacity, so the asset states its own colour. */

/* Review card panel loses its white-to-transparent gradient (2026-09-04, owner). The soft top
   edge washed the bottom of the photo and, worse, put the first line of the quote on a
   half-white ground where the ink lost contrast against whatever the photo happened to be.
   Solid white: the quote reads at a flat 10.02:1 everywhere, and the panel edge is a clean
   line rather than a smear across the shot. */

/* Review wall (2026-09-04, owner): the quotes were set at 600, which made every card shout
   equally and left nothing to emphasise. Body drops to 400 and the phrases that actually earn
   attention are tinted green instead. The tint is the same #eef7f1 the free-gear row uses, and
   #1e7b45 on it measures 4.94:1, so the highlight is legible rather than decorative.
   box-decoration-break keeps the wash whole when a phrase wraps across two lines. */
.pdp-v3 #reviews .qt p .hl{color:#141310;border-radius:3px;padding:0 3px;margin:0 -3px;
  background-image:linear-gradient(#cff9a4,#cff9a4);background-repeat:no-repeat;
  background-size:100% 100%;
  -webkit-box-decoration-break:clone;box-decoration-break:clone}

/* The wash is swept in like a highlighter pen as the card arrives (2026-09-04, owner).
   Painted state is the DEFAULT and the zero-width start is gated behind html.v3-anim, which
   pdp-v3-reveal.js only adds when it actually runs. Reduced motion makes that script return
   before the gate, and so does no-JS, so in both cases the highlight is simply there - the
   file's standing rule that nothing is ever left hidden by an animation that never fires.
   It rides the card's own .v3r-in reveal rather than a second observer, so the sweep starts
   only once the card has settled, and each phrase in a card follows the one before it.

   Green wash, ink text (2026-09-05, owner), reverting the brief ink-and-white pass. That one
   had to animate the text colour alongside the sweep, because white type would have been
   invisible on the white card until the black wash reached it. A light wash needs none of
   that: #141310 is legible on the card AND on #cff9a4 (the page-wide wash since the 2026-09-06 sweep), so the colour is constant and only
   background-size animates - no layout, and nothing to mistime. The sweep goes back to .55s
   and the per-phrase stagger to a plain transition-delay, since there is no second property
   whose timing a shared delay could break. */
html.v3-anim .pdp-v3 #reviews .qt.v3r p .hl{background-size:0 100%;
  transition:background-size .55s cubic-bezier(.22,1,.36,1)}
html.v3-anim .pdp-v3 #reviews .qt.v3r-in p .hl{background-size:100% 100%}
html.v3-anim .pdp-v3 #reviews .qt.v3r-in p .hl:nth-of-type(1){transition-delay:200ms}
html.v3-anim .pdp-v3 #reviews .qt.v3r-in p .hl:nth-of-type(2){transition-delay:420ms}
html.v3-anim .pdp-v3 #reviews .qt.v3r-in p .hl:nth-of-type(3){transition-delay:640ms}
@media(prefers-reduced-motion: reduce){
  .pdp-v3 #reviews .qt p .hl{background-size:100% 100% !important;transition:none !important}
}
}

/* Gear tile centring (2026-09-04, owner). Under 560px `.kitpanel .kt .box` is pinned to
   height:52px while still carrying aspect-ratio:3/2, so the box computes to 78px wide inside a
   90px content box. It is a block, so the leftover 12px all fell on the right and the image sat
   6px left of the price and label, which stayed centred. Auto side margins put the box back on
   the tile's centre line. A no-op at desktop, where the box is already full width. */
.pdp-v3 .kt .box{margin-left:auto;margin-right:auto}

/* Foil gauge (2026-09-04, owner): the two caliper photos side by side under the compare table.
   The shots have different proportions - 0.20 is square, 0.05 is portrait 607x800 - so they
   share ONE square box with object-fit:contain. Cover would take about a quarter off the
   portrait's height, which is where the caliper jaw and the foil head are; the whole point of
   the picture is that you can read the measurement and see what is being measured. The 0.05
   therefore sits narrower inside its box, on the card's own white, which is what its backing
   already is. */
.pdp-v3 .fgauge .fg-head .lede{margin-top:12px;max-width:640px}
.pdp-v3 .fg-cards{display:grid;grid-template-columns:repeat(2,1fr);gap:24px;margin-top:38px}
.pdp-v3 .fg-card{position:relative;background:#fff;border:0;border-radius:var(--radius);overflow:hidden;
  padding:0 20px 20px;transition:box-shadow .18s ease}
.pdp-v3 .fg-card.is-us{border:0;padding:0 20px 20px}
.pdp-v3 .fg-shot{aspect-ratio:1/1;border-radius:0;overflow:hidden;background:#fff;margin:0 -20px}
.pdp-v3 .fg-shot img{width:100%;height:100%;object-fit:contain;display:block}
.pdp-v3 .fg-meta{display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-top:16px}
.pdp-v3 .fg-label{font-size:10.5px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:var(--mut)}
.pdp-v3 .fg-card.is-us .fg-label{color:var(--ink2)}
.pdp-v3 .fg-pill{flex:none;font-size:10.5px;font-weight:600;letter-spacing:.06em;
  padding:4px 10px;border-radius:999px;background:#f1f0ec;color:var(--ink2);white-space:nowrap}
.pdp-v3 .fg-card.is-us .fg-pill{background:#141310;color:#fff}
.pdp-v3 .fg-value{font-size:38px;font-weight:600;letter-spacing:-.035em;line-height:1;
  color:var(--ink);margin-top:12px}
.pdp-v3 .fg-value small{font-size:15px;font-weight:500;letter-spacing:0;color:var(--mut);
  margin-left:5px}
.pdp-v3 .fg-card h3{font-size:16px;font-weight:600;margin-top:8px}
.pdp-v3 .fg-body{font-size:13px;line-height:1.55;color:var(--mut);margin-top:7px}
@media(prefers-reduced-motion: reduce){.pdp-v3 .fg-card{transition:none}}
@media(max-width:760px){
  .pdp-v3 .fg-cards{grid-template-columns:1fr}
  .pdp-v3 .fg-value{font-size:32px}
}

/* The gauge shots are animated webp now (2026-09-04, owner), wrapped in <picture> so the
   still is served to reduced motion instead. */
.pdp-v3 .fg-shot picture{display:block;width:100%;height:100%}

/* Press quotes carry their own typographic quotes in the copy, so no decorative mark sits
   beside them (2026-09-07, owner: "delete the repeated large double quotation marks"). The base
   theme's slanted blockquote ::before is killed here, the same reset the benefit cards use. */
.pdp-v3 .pressitem blockquote{font-style:normal;quotes:none}
.pdp-v3 .pressitem blockquote::before,.pdp-v3 .pressitem blockquote::after{content:none}

/* Compare table (2026-09-04, owner): the product shots grow and straddle the top of the table,
   and rows tint on hover.

   The overlap without breaking the scroller: .tablewrap scrolls horizontally, so its computed
   overflow-y is auto and anything pulled above the table would be clipped. Padding is inside
   the scrollport, so the wrapper gains padding-top and the shot is pulled up by a negative
   margin INTO that padding - the overhang lives inside the box that would otherwise cut it.
   No absolute positioning, so nothing depends on position:relative working on a <th>.

   The negative top margin also drags the name and subtitle up with it, so the bottom margin
   pays that back: flow contribution is -56 + 74 + 8 = 26px, which is where the name sat before.
   All four shots carry real alpha, so crossing from the cream band onto the white header cell
   shows no matte edge. */
.pdp-v3 #compare .tablewrap{padding-top:40px}
.pdp-v3 #compare thead .brandshot{height:74px;margin:-56px auto 8px}
@media(max-width:560px){
  .pdp-v3 #compare .tablewrap{padding-top:32px}
  .pdp-v3 #compare thead .brandshot{height:58px;margin:-44px auto 8px}
}

/* Row hover. Every declaration is !important, and not for the usual reason. .col-us needs it
   to beat this file's own gold wash - but the PLAIN cells need it too: an inline background on
   a td is ignored on this page, which can only happen if some rule already carries !important.
   It is in one of the app stylesheets the page loads cross-origin (widget.min.css and friends),
   so the CSSOM cannot name it and it cannot be edited out. Matching the weight is the only way
   a row tint lands at all. Verified by testing an inline background with and without the flag.
   Hover-capable pointers only; transition dropped under reduced motion. */
.pdp-v3 #compare tbody td,
.pdp-v3 #compare tbody th{transition:background-color .16s ease}
@media(hover:hover){
  .pdp-v3 #compare tbody tr:hover td{background:#faf9f6 !important}
  .pdp-v3 #compare tbody tr:hover th{background:#f2f0ea !important}
  .pdp-v3 #compare tbody tr:hover .col-us{background:#faf0d5 !important}
}
@media(prefers-reduced-motion: reduce){
  .pdp-v3 #compare tbody td,
  .pdp-v3 #compare tbody th{transition:none}
}

/* Compare table (2026-09-04, owner): no stroke around the outside, a soft shadow instead.

   There was never a border on .tablewrap or on the table - that was already zeroed. The outer
   frame was drawn by the CELLS: the base theme puts a 1px #e2e2e2 top border on every td and
   th, so the first row's tops read as the table's top edge, and the edge cells' right/bottom
   hairlines close the box. Those three edges are dropped; the interior row rules stay, because
   they are what carries the table's structure. .col-us is excluded throughout so the gold frame
   around the Touch 2 column survives - that is column emphasis, not the outer stroke.

   The shadow cannot go on .tablewrap: it scrolls, so it clips its own children, and its box now
   includes the 40px of top padding the overlapping shots hang into - a shadow there would float
   above the table's real top edge. It is drawn instead by a pseudo-element on .cmp-scroller,
   inset from the top by that same padding, which is shared as --cmp-pad so the two cannot drift
   apart. Outer box-shadow paints outside its own border box, so the ink lands on the band around
   the table and never over the table itself; pointer-events:none keeps it out of the way. */
.pdp-v3 #compare{--cmp-pad:40px}
.pdp-v3 #compare .cmp-scroller{position:relative}
.pdp-v3 #compare .tablewrap{padding-top:var(--cmp-pad)}
.pdp-v3 #compare .cmp-scroller::after{content:"";position:absolute;left:0;right:0;
  top:var(--cmp-pad);bottom:0;pointer-events:none;
  box-shadow:0 1px 2px rgba(20,19,16,.05),0 12px 30px rgba(20,19,16,.09)}
.pdp-v3 #compare thead tr th:not(.col-us){border-top:0}
.pdp-v3 #compare tbody tr:last-child td:not(.col-us),
.pdp-v3 #compare tbody tr:last-child th{border-bottom:0}
.pdp-v3 #compare thead th:last-child,
.pdp-v3 #compare tbody tr td:last-child{border-right:0}
@media(max-width:560px){
  .pdp-v3 #compare{--cmp-pad:32px}
}

/* Touch 2 column loses its gold rule (2026-09-04, owner): the wash carries the emphasis on its
   own now. Only the 2px gold edges go - the 1px row hairlines on those cells stay, so the row
   rules still run unbroken across the table instead of stopping either side of the column. */
.pdp-v3 #compare .col-us,
.pdp-v3 #compare thead .col-us,
.pdp-v3 #compare tbody tr:last-child .col-us{border-left:0;border-right:0}
.pdp-v3 #compare thead .col-us{border-top:0}
.pdp-v3 #compare tbody tr:last-child .col-us{border-bottom:0}

/* ===== CONSISTENCY PASS (2026-09-04) =====
   One scale for every content card on the page. Measured on the live page before this pass, card
   titles ran 16/20/21/22px, small labels 10.5/11/12px, ledes 15/16/17px and bodies 13/14/14.5px.
   Section-level {% style %} blocks lose to this sheet at equal specificity (every section re-links
   it, so the sheet always sits later in the cascade), so those overrides now live here instead. */
.pdp-v3{--card-shadow:0 1px 2px rgba(20,19,16,.05),0 12px 30px rgba(20,19,16,.09);
        --card-shadow-hover:0 2px 4px rgba(20,19,16,.06),0 18px 40px rgba(20,19,16,.13)}
/* Type tiers */
.pdp-v3 .eyebrow{font-size:12px;font-weight:600;letter-spacing:.16em;color:var(--mut)}
.pdp-v3 .lede,.pdp-v3 #why .lede,.pdp-v3 #faq .lede{font-size:16px}
.pdp-v3 .micro h3,.pdp-v3 .feat h3,.pdp-v3 .fg-card h3,.pdp-v3 .guar>div h3,.pdp-v3 .mcard h3{font-size:21px;font-weight:600;letter-spacing:-.01em;line-height:1.2}
.pdp-v3 .micro p,.pdp-v3 .feat p,.pdp-v3 .fg-body,.pdp-v3 .guar>div p,.pdp-v3 .mcard p{font-size:14px;line-height:1.5;color:#5a564c}
.pdp-v3 .micro .m-tag,.pdp-v3 .fg-label{font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase}
.pdp-v3 .fg-label{color:var(--mut)}
.pdp-v3 .fg-card.is-us .fg-label{color:#8a6a17}
.pdp-v3 .feat .quotelet{font-size:13.5px;color:#45423b;border-left-color:#d9d2c2}
.pdp-v3 .feat .quotelet span{font-size:12.5px;color:var(--mut)}
.pdp-v3 .specstrip span{font-size:13px}
/* Micro cards, moved out of the section's style block */
.pdp-v3 #why .micro{gap:24px}
.pdp-v3 #why .micro>div{background:#fff;border-radius:var(--radius);overflow:hidden;padding:0 20px 20px}
/* Cards carry the compare table's shadow and drop their hairline. The gauge's Touch 2 card keeps its
   ink ring: that is the highlight device, same job as the table's Touch 2 column wash. */
.pdp-v3 .micro>div,.pdp-v3 .mcard,.pdp-v3 .bcard,.pdp-v3 .fg-card,.pdp-v3 .qt,.pdp-v3 .guar,.pdp-v3 .specstrip{box-shadow:var(--card-shadow)}
.pdp-v3 .fg-card,.pdp-v3 .qt,.pdp-v3 .guar,.pdp-v3 .specstrip{border:0}
.pdp-v3 .fg-card.is-us{border:0;padding:0 20px 20px}
/* The review carousel clips at the track edge, so the track grows by the shadow's reach on every
   side and pulls the scrub rule back up by the same amount. Snap maths is unchanged: scroll-padding
   matches the new inline padding. */
.pdp-v3 .bcards{padding:0 24px 44px;margin:0 -24px -42px;scroll-padding-inline:24px}
@media(max-width:560px){.pdp-v3 .bcards{padding:0 20px 44px;margin:0 0 -42px}}
/* One hover language: content cards lift, the way the CTAs already do. Static grids (guarantee,
   spec strip) are panels, not cards, so they no longer react. Feature shots breathe instead of
   growing a stroke. */
@media(hover:hover){
  .pdp-v3 .micro>div,.pdp-v3 .mcard,.pdp-v3 .fg-card,.pdp-v3 .qt,.pdp-v3 .bcard{transition:translate .25s cubic-bezier(.2,.7,.2,1),box-shadow .25s cubic-bezier(.2,.7,.2,1)}
  .pdp-v3 .micro>div:hover,.pdp-v3 .mcard:hover,.pdp-v3 .fg-card:hover,.pdp-v3 .qt:hover,.pdp-v3 .bcard:hover{translate:0 -2px;box-shadow:var(--card-shadow-hover)}
  .pdp-v3 .guar>div:hover,.pdp-v3 .specstrip>div:hover,.pdp-v3 .feats>div:hover .shot{box-shadow:none}
  .pdp-v3 .feat .shot img{transition:transform .6s cubic-bezier(.2,.7,.2,1);will-change:transform}
  .pdp-v3 .feat:hover .shot img{transform:scale(1.04)}
}
@media(prefers-reduced-motion:reduce){
  .pdp-v3 .micro>div,.pdp-v3 .mcard,.pdp-v3 .fg-card,.pdp-v3 .qt,.pdp-v3 .bcard,.pdp-v3 .feat .shot img{transition:none}
  .pdp-v3 .micro>div:hover,.pdp-v3 .mcard:hover,.pdp-v3 .fg-card:hover,.pdp-v3 .qt:hover,.pdp-v3 .bcard:hover{translate:none}.pdp-v3 .feat:hover .shot img{transform:none}
}
/* Guarantee: two stand-alone cards, moved out of the section's style block. The cells are the cards
   here, so they take the card shadow and the card lift; the wrapper stays invisible. */
.pdp-v3 .sec .guar{background:transparent;border:0;border-radius:0;overflow:visible;gap:24px;box-shadow:none}
.pdp-v3 .sec .guar>div{border-radius:var(--radius);box-shadow:var(--card-shadow)}
.pdp-v3 .sec .guar>div h3{font-size:21px;font-weight:600;letter-spacing:-.01em;line-height:1.2}
.pdp-v3 .sec .guar>div p{font-size:14px;line-height:1.5;color:#5a564c}
.pdp-v3 .sec .gseal b{font-size:20px}
.pdp-v3 .sec .gseal span{color:#fff;font-size:8.5px;font-weight:500}
@media(hover:hover){
  .pdp-v3 .sec .guar>div{transition:translate .25s cubic-bezier(.2,.7,.2,1),box-shadow .25s cubic-bezier(.2,.7,.2,1)}
  .pdp-v3 .sec .guar>div:hover{translate:0 -2px;box-shadow:var(--card-shadow-hover)}
}
@media(prefers-reduced-motion:reduce){.pdp-v3 .sec .guar>div{transition:none}.pdp-v3 .sec .guar>div:hover{translate:none}}
/* Web Interface Guidelines pass: comparison figures in tabular numerals, headings balanced so a
   two-line h2 never strands one word. */
.pdp-v3 .fg-value,.pdp-v3 .specstrip b{font-variant-numeric:tabular-nums}
.pdp-v3 h2,.pdp-v3 h3{text-wrap:balance}
.pdp-v3 .lede{text-wrap:pretty}
/* Review carousel accordion (2026-09-05): the quote's height animates open and closed */
/* Six things on mobile: three cards, then a toggle. Same device as the reviews wall. */
.pdp-v3 .feat-toggle{display:none;margin:18px auto 0;background:#fff;border:1px solid var(--ink2);border-radius:10px;padding:12px 22px;min-height:44px;font-family:inherit;font-size:13px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--ink);cursor:pointer}
.pdp-v3 .feat-toggle:focus-visible{outline:2px solid #181713;outline-offset:3px}
@media(hover:hover){
  .pdp-v3 .feat-toggle{transition:background-color .18s ease,color .18s ease,border-color .18s ease,translate .18s ease,box-shadow .18s ease}
  .pdp-v3 .feat-toggle:hover{background:#141310;color:#fff;border-color:#141310;translate:0 -1px;box-shadow:0 6px 16px rgba(20,19,16,.16)}
}
@media(prefers-reduced-motion:reduce){.pdp-v3 .feat-toggle{transition:none}.pdp-v3 .feat-toggle:hover{translate:none}}
@media(max-width:560px){
  .pdp-v3 .feats.is-collapsed{position:relative}
  .pdp-v3 .feats.is-collapsed .feat:nth-child(n+4){display:none}
  .pdp-v3 .feats.is-collapsed::after{content:"";position:absolute;left:0;right:0;bottom:0;height:130px;background:linear-gradient(180deg,rgba(244,243,244,0),#F4F3F4);pointer-events:none}
  .pdp-v3 .feats.is-collapsed + .feat-toggle{display:block}
}
/* Compare table swipe hint (2026-09-05): the owner's animated swipe arrows SVG (two ink chevrons) over the
   middle of the visible part of the table where it pans (<=900px), placed by the section script.
   Fades on its own after about one loop or on the first sideways gesture. The SVG animates itself
   (SMIL inside an <img>), which cannot be paused from CSS, so reduced-motion users get no hint; the
   edge fade and the rail still say the table moves. */
.pdp-v3 #compare .cmp-hint-wrap{display:none}
@media(max-width:900px){
  .pdp-v3 #compare .cmp-hint-wrap{display:block;position:absolute;left:0;right:0;top:var(--cmp-pad);bottom:0;pointer-events:none;z-index:4}
  .pdp-v3 #compare .tablewrap.no-pan ~ .cmp-hint-wrap{display:none}
  .pdp-v3 #compare .cmp-hint{position:absolute;left:50%;top:0;width:120px;height:120px;margin-left:-60px;opacity:.92;transition:opacity .4s ease}
  .pdp-v3 #compare .cmp-hint img{display:block;width:100%;height:100%;filter:drop-shadow(0 2px 6px rgba(20,19,16,.18))}
  .pdp-v3 #compare .cmp-hint.is-gone{opacity:0}
  .pdp-v3 #compare .cmp-rail{height:2px;background:var(--line)}
  .pdp-v3 #compare .cmp-rail span{width:auto;background:var(--ink);transition:none;will-change:transform}
}
@media(prefers-reduced-motion:reduce){.pdp-v3 #compare .cmp-hint-wrap{display:none}}
/* Announcement bar on mobile (2026-09-05): the subnav section's own mobile rule for the cycling
   message lost to the sheet's inline-block/padding rule above, so the text sat at the top of the
   40px bar. Lives here now so it wins. */
@media(max-width:899px){
  .pdp-v3 .announce.u-bar .u-msg{display:flex;align-items:center;justify-content:center;padding:0 16px;text-align:center}
}
/* Mobile sweep (2026-09-05, owner call). Price line on both option cards moves under the title,
   left-aligned, current price first and the struck compare after it. Sticky bar gets air between
   the name and the price row. "Read full review" grows to a real tap target without moving the
   text. */
@media(max-width:560px){
  .pdp-v3 .opt-hd .p2{flex-basis:100%;margin-left:0;margin-top:4px;display:flex;align-items:baseline;justify-content:flex-start;gap:8px;text-align:left}
  .pdp-v3 .opt-hd .p2 .pwas{order:2}
}
@media(max-width:900px){
  .pdp-v3 .mobile-bar .p .mb-line{margin-top:4px}
}

/* ===== MOTION PASS (2026-09-05): Apple-style motion =====
   One deceleration curve for every UI state change (a critically damped settle: fast start, long
   ease-out, no overshoot), three durations, press feedback on pointer-down, transform/opacity
   wherever the layout allows, and every transition re-locked to none under reduced motion.
   Symmetric `ease` is gone from UI state; `linear` survives only on the constant-speed kit marquee.
   The review carousel keeps its own spring (x(t) = (x0 + (v0 + w x0) t) e^(-w t)), which already
   inherits velocity, projects momentum and can be grabbed mid-flight. Entrance keyframes keep
   their longer ease-out (.22,1,.36,1). */
.pdp-v3{--ease-out:cubic-bezier(.2,.7,.2,1);--t-press:.12s;--t-fast:.18s;--t-base:.28s;--t-slow:.42s}
@media(hover:hover){
  .pdp-v3 .trustrow>div{transition:background-color var(--t-fast) var(--ease-out),color var(--t-fast) var(--ease-out)}
  .pdp-v3 .kt{transition:box-shadow var(--t-fast) var(--ease-out)}
  .pdp-v3 .cta,.pdp-v3 .addbtn,.pdp-v3 .rev-toggle,.pdp-v3 .feat-toggle{transition:background-color var(--t-fast) var(--ease-out),color var(--t-fast) var(--ease-out),border-color var(--t-fast) var(--ease-out),transform var(--t-fast) var(--ease-out),translate var(--t-fast) var(--ease-out),box-shadow var(--t-fast) var(--ease-out)}
  .pdp-v3 .feats .shot{transition:none}
  /* scrubber rule thickens through a transform, not a height change */
  .pdp-v3 .bcar-scrub:hover .bcar-rule,.pdp-v3 .bcar-scrub.is-scrubbing .bcar-rule{height:2px;transform:scaleY(2)}
}
.pdp-v3 .bcar-rule{transition:transform var(--t-fast) var(--ease-out);transform-origin:50% 50%}
.pdp-v3 .opt-buy,.pdp-v3 .opt.slim .sw-wrap{transition:max-height var(--t-base) var(--ease-out),opacity var(--t-base) var(--ease-out),margin var(--t-base) var(--ease-out)}
.pdp-v3 .kitwrap{transition:max-height var(--t-base) var(--ease-out),opacity var(--t-base) var(--ease-out)}
.pdp-v3 .fold-defer{transition:opacity var(--t-slow) var(--ease-out),transform var(--t-slow) var(--ease-out)}
.pdp-v3 .desk-bar,.pdp-v3 .mobile-bar{transition:transform var(--t-base) var(--ease-out)}
.pdp-v3 #compare tbody th{transition:background-color var(--t-fast) var(--ease-out)}
.pdp-v3 #compare .cmp-hint{transition:opacity var(--t-base) var(--ease-out)}
/* press feedback: respond on pointer-down, release settles on the same curve */
.pdp-v3 .qbtn{transition:transform var(--t-press) var(--ease-out),opacity var(--t-press) var(--ease-out)}
.pdp-v3 .qbtn:active,.pdp-v3 .rev-toggle:active,.pdp-v3 .feat-toggle:active{transform:scale(.96)}
@media(prefers-reduced-motion:reduce){
  .pdp-v3 .trustrow>div,.pdp-v3 .kt,.pdp-v3 .cta,.pdp-v3 .addbtn,.pdp-v3 .rev-toggle,.pdp-v3 .feat-toggle,.pdp-v3 .bcar-rule,
  .pdp-v3 .opt-buy,.pdp-v3 .opt.slim .sw-wrap,.pdp-v3 .kitwrap,.pdp-v3 .fold-defer,.pdp-v3 .desk-bar,.pdp-v3 .mobile-bar,
  .pdp-v3 #compare tbody th,.pdp-v3 #compare .cmp-hint,.pdp-v3 .qbtn{transition:none}
  .pdp-v3 .qbtn:active,.pdp-v3 .rev-toggle:active,.pdp-v3 .feat-toggle:active{transform:none}
  .pdp-v3 .bcar-scrub:hover .bcar-rule,.pdp-v3 .bcar-scrub.is-scrubbing .bcar-rule{transform:none;height:4px}
}
/* Base-theme transitions (links, buttons, icons) reach into the PDP on the symmetric `ease` curve;
   keep their property lists, swap the curve. Spec tiles no longer react, so no transition at all. */
.pdp-v3 a,.pdp-v3 button,.pdp-v3 svg,.pdp-v3 summary,.pdp-v3 input,.pdp-v3 label{transition-timing-function:var(--ease-out)}
.pdp-v3 #compare td,.pdp-v3 #compare tbody th{transition:background-color var(--t-fast) var(--ease-out)}
.pdp-v3 .specstrip>div{transition:none}
@media(prefers-reduced-motion:reduce){
  .pdp-v3 a,.pdp-v3 button,.pdp-v3 svg,.pdp-v3 summary,.pdp-v3 input,.pdp-v3 label,.pdp-v3 #compare td,.pdp-v3 #compare tbody th{transition:none}
}
.pdp-v3 .opt .sw-wrap,.pdp-v3 .opt .cardline.dyn{transition:max-height var(--t-base) var(--ease-out),opacity var(--t-base) var(--ease-out),margin var(--t-base) var(--ease-out)}
.pdp-v3 #compare tbody td{transition:background-color var(--t-fast) var(--ease-out)}
@media(prefers-reduced-motion:reduce){.pdp-v3 .opt .sw-wrap,.pdp-v3 .opt .cardline.dyn,.pdp-v3 #compare tbody td{transition:none}}

/* Press bar to full ink (2026-09-05, owner). The logos are re-baked in the asset rather than
   dimmed or filtered, same as when they went grey, so each file states its own colour. Quote
   text moves off --ink2 onto the same #141310 and goes up a step, 14.5 -> 16px desktop and
   14 -> 15px mobile. The max-width rises with it so the GQ quote still breaks over two lines
   at the larger size instead of three. */
.pdp-v3 .pressitem blockquote{font-size:16px;color:#141310;max-width:400px}
@media(max-width:760px){
  .pdp-v3 .pressitem blockquote{max-width:480px}
}
@media(max-width:560px){
  .pdp-v3 .pressitem blockquote{font-size:15px}
}

/* Gauge shots reshot 4:3 (2026-09-05, owner): the replacement clips are 2048x1536, where the
   first pair was square. The box follows them to 4/3 rather than keeping a square frame and
   letterboxing a landscape clip - both cards move together, so they stay matched. */
.pdp-v3 .fg-shot{aspect-ratio:4/3}

/* Spec strip (2026-09-05, owner): the shared panel goes, each tile carries its own shadow, and the
   tiles zoom on hover. This reverses the consistency pass's "static grids are panels, not cards"
   call for this one strip at the owner's request - the guarantee grid keeps that treatment.
   Gap widens 10 -> 16px: four separately-shadowed tiles need air between them, and a 1.03 zoom
   grows a tile ~4px a side, which must stay short of the half-gap or neighbours touch mid-hover.
   Scale lives on transform so nothing reflows; will-change keeps it on the compositor. */
.pdp-v3 .specstrip{background:transparent;border:0;box-shadow:none;gap:16px;overflow:visible}
.pdp-v3 .specstrip>div{box-shadow:var(--card-shadow)}
@media(hover:hover){
  .pdp-v3 .specstrip>div{transition:transform .28s cubic-bezier(.2,.7,.2,1),box-shadow .28s cubic-bezier(.2,.7,.2,1);
    will-change:transform}
  .pdp-v3 .specstrip>div:hover{transform:scale(1.03);
    box-shadow:var(--card-shadow-hover,0 2px 4px rgba(20,19,16,.06),0 18px 40px rgba(20,19,16,.13))}
}
@media(max-width:900px){.pdp-v3 .specstrip{gap:14px}}
@media(prefers-reduced-motion:reduce){
  .pdp-v3 .specstrip>div{transition:none}
  .pdp-v3 .specstrip>div:hover{transform:none}
}

/* Type-floor sweep (2026-09-05, owner's all-widths check). Two labels sat under the notes' 10.5px
   micro floor: the guarantee seal unit (DAY / YEAR) at 8.5px from the consistency pass, and the
   mobile-bar SAVE pill at 10px from the sticky-bar rework. Both to 10.5px. The seal label also
   drops its tracking to 0 so the longer "YEAR" still clears the seal's circle at the larger size. */
.pdp-v3 .sec .gseal span{font-size:10.5px;letter-spacing:0}
.pdp-v3 .mobile-bar .p .mb-save:not([hidden]){font-size:10.5px}

/* ===== REAL REVIEWS + HERO BULLETS (2026-09-06, owner's Slack + Loom) ===== */
/* Review section head: eyebrow, a light pre-headline, then the bold h2 (the owner's three-line stack). */
.pdp-v3 .bcards-sec .bc-head .bc-pre{margin:10px auto 8px;max-width:640px;font-size:18px;font-weight:400;letter-spacing:0;color:var(--ink2);line-height:1.35}
@media(max-width:560px){.pdp-v3 .bcards-sec .bc-head .bc-pre{font-size:16px;margin:8px auto 6px}}

/* Arrows either side of the track (the owner asked for a click target, not just the scrubber). Anchored
   to the centre of the photo (--arrow-top from the script) so they never sit in a tall card's text; they
   fade out at the ends rather than greying, so the edge reads as "nothing more" instead of "broken". Half
   outside the track on desktop where the wrap has margin; inside the bleed on phones. */
.pdp-v3 .bcar-arrow{position:absolute;top:var(--arrow-top,140px);left:-22px;z-index:3;width:44px;height:44px;margin:-22px 0 0;padding:0;
  border-radius:50%;border:1px solid var(--line);background:#fff;color:var(--ink);display:flex;align-items:center;justify-content:center;
  cursor:pointer;box-shadow:var(--card-shadow);font:inherit;
  transition:opacity var(--t-fast) var(--ease-out),transform var(--t-press) var(--ease-out),box-shadow var(--t-fast) var(--ease-out),border-color var(--t-fast) var(--ease-out)}
.pdp-v3 .bcar-arrow.next{left:auto;right:-22px}
.pdp-v3 .bcar-arrow svg{width:20px;height:20px;display:block}
.pdp-v3 .bcar-arrow:disabled{opacity:0;pointer-events:none}
.pdp-v3 .bcar-arrow:active{transform:scale(.94)}
.pdp-v3 .bcar-arrow:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.pdp-v3 .bcarousel:not(.js) .bcar-arrow{display:none}
@media(hover:hover){.pdp-v3 .bcar-arrow:hover{border-color:var(--ink);box-shadow:var(--card-shadow-hover)}}
@media(max-width:900px){.pdp-v3 .bcar-arrow{left:-12px}.pdp-v3 .bcar-arrow.next{right:-12px}}
@media(max-width:560px){.pdp-v3 .bcar-arrow{left:6px}.pdp-v3 .bcar-arrow.next{right:6px}}
@media(prefers-reduced-motion:reduce){.pdp-v3 .bcar-arrow{transition:none}.pdp-v3 .bcar-arrow:active{transform:none}}

/* Hero subpromise (2026-09-06, owner's copy): a bold lead line under the display heading, then three check
   bullets, each with a bold label before the colon. An ink disc with a white check replaces the gold dot. */
.pdp-v3 .subpromise-lead{margin:12px 0 12px;font-size:17px;font-weight:600;letter-spacing:-.01em;color:var(--ink);line-height:1.35}
.pdp-v3 ul.subpromise{gap:9px}
.pdp-v3 ul.subpromise li{padding-left:26px;font-size:15.5px;font-weight:400;letter-spacing:0;color:var(--ink2);line-height:1.45}
.pdp-v3 ul.subpromise li b{font-weight:600;color:var(--ink)}
.pdp-v3 ul.subpromise li::before{left:0;top:.22em;width:16px;height:16px;border-radius:50%;
  background:var(--ink) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.6 6.3l2.3 2.3 4.5-4.9' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/9px 9px no-repeat}
@media(max-width:560px){.pdp-v3 .subpromise-lead{font-size:16px;margin:10px 0 10px}.pdp-v3 ul.subpromise li{font-size:14.5px;padding-left:24px}}

/* ===== FINAL SWEEP (2026-09-06, measured audit at 1440 and 390) ===== */
/* One seam (38px head to content), one card inset (20px), one gap rhythm (24 desktop / 16 phones), one
   lede measure (640), one star gold, one wash, one hover: the outliers above were consolidated in place;
   these are the rules that had to land after the blocks they correct. */
.pdp-v3 .sec .guar>div{padding:24px 20px}
.pdp-v3 .sec .guar h3{font-size:21px;font-weight:600;letter-spacing:-.01em}
@media(max-width:760px){.pdp-v3 .mcards,.pdp-v3 .fg-cards,.pdp-v3 #why .micro,.pdp-v3 .sec .guar{gap:16px}}
/* the review track scrolls, so it clips: 4px of head-room lets the -2px lift and its shadow breathe */
.pdp-v3 .bcards{padding-top:4px;margin-top:-4px}
.pdp-v3 .bcards.is-dragging .bcard:hover{translate:none}
/* Count-up spans (see pdp-v3-reveal.js): tabular figures so the digits tick without the word shifting. */
.pdp-v3 .cnt{font-variant-numeric:tabular-nums}

/* Photo cards, one construction (2026-09-07, owner): the gauge, method and micro-diff cards are built like the
   review card. Photo edge to edge at the top (the card's own radius clips the corners), 4:3 for the two
   step/measure pairs, then a 20px text panel; numeral display at 38px. Only the gauge's "ours" card keeps a
   border, and its photo sits inside that border. */
.pdp-v3 #why .micro .shot{border-radius:0;margin:0 -20px 16px}
.pdp-v3 .fg-card.is-us .fg-shot{margin:0 -20px}

/* Important numbers in gold (2026-09-07, owner): the gauge values, unit included, and the step numerals share
   #a9802d at one weight (500). Headline figures stay ink (owner reverted those); they keep the count-up. The
   gauge pills go to caps on the small-label tier, like the Verified pill. */
.pdp-v3 .fg-value,.pdp-v3 .fg-value small{color:#a9802d}
.pdp-v3 .fg-value{font-weight:500}
.pdp-v3 .mcard .mnum{font-weight:500}
.pdp-v3 .fg-pill{text-transform:uppercase;letter-spacing:.1em}

/* "Ours" emphasis on the gauge card (2026-09-07, owner: better than a black stroke). Same grammar as the compare
   table's Touch 2 column and the guarantee seals: gold and ink, never a border. A warm surface (the selected
   kit card's white), a hairline gold edge that reads as a lit rim rather than a stroke, and one step more depth
   at rest so it sits proud of the baseline card. Hover takes it one step further along the same axis. (A 3px
   gold rule across the top was tried and read as an artefact over the photo; dropped 2026-09-07.) */
.pdp-v3 .fg-card.is-us{background:#fffdf8;
  box-shadow:0 0 0 1px rgba(169,128,45,.28),0 2px 4px rgba(20,19,16,.06),0 18px 40px rgba(20,19,16,.13)}
@media(hover:hover){
  .pdp-v3 .fg-card.is-us:hover{box-shadow:0 0 0 1px rgba(169,128,45,.4),0 4px 8px rgba(20,19,16,.07),0 26px 56px rgba(20,19,16,.16)}
}

/* CARD FLOOR (2026-09-07, owner: "make sure the bottom of the cards have ample padding"). Text sitting
   20px off a card's floor reads tighter than the 20px sides, because the eye measures from the baseline
   and the line box hides the last 5px. Every card with a floor takes 24px below, the guarantee cells'
   value; sides and top stay at 20. Photo cards (gauge, method, micro), the review panel and the proof
   quotes all pick it up here so the token lives in one place. */
.pdp-v3 .fg-card,.pdp-v3 .fg-card.is-us,.pdp-v3 .mcard,.pdp-v3 #why .micro>div{padding-bottom:24px}
.pdp-v3 .bcard .bc-panel{padding-bottom:24px}
.pdp-v3 #reviews .qt{padding-bottom:24px}

/* SWATCH SIZE (2026-09-07, owner: a touch smaller). At 38px the discs read as heavy as the buy row's
   stepper beside a 14px label. 32px is the hero's original disc; it sits under the label as a control,
   not a feature. The tap target stays 44px on touch through an invisible halo, so nothing gets harder
   to hit; clicks on the halo land on the swatch itself. */
.pdp-v3 .opt .sw{width:32px;height:32px;position:relative}
.pdp-v3 .opt .swatches{gap:10px}
.pdp-v3 .opt .sw::after{content:"";position:absolute;inset:-8px;border-radius:50%} /* -8, not -6: the 2px border is outside the containing block, so 28 + 16 = 44 */

/* EYEBROW AIR (2026-09-07, owner: a tiny bit more space between eyebrow and headline, everywhere). The
   eyebrow's line box sat flush on the headline's; 6px lets the cap height clear the small caps. */
.pdp-v3 .eyebrow+h2{margin-top:6px}
/* Micro-diff headline (2026-09-07, owner): on phone the browser broke "micro-difference" at its hyphen.
   The heading carries a newline after the word so phone reads "The micro-difference / is massive"; on
   wider screens the line fits whole, so the break is hidden. Scoped to this one heading: the how-to and
   why-switch headings keep their authored breaks at every width. */
@media(min-width:761px){.pdp-v3 #why h2 br{display:none}}

/* SAVE BADGE TO THE CARD EDGE (2026-09-08, owner: "the green save 40% off and save 20% off should be
   right aligned also to the right side of the card"). Under 560px the mobile sweep above already drops
   the price onto its own row, so the header row is radio, name, badge and the badge can take the right
   edge cleanly. Above 560px the price owns that edge, so the badge stays beside the title there rather
   than colliding with it. Applies to both cards; the solo badge is conditional in the Liquid. */
@media(max-width:560px){
  .pdp-v3 .opt-hd .savebadge{margin-left:auto}
}

/* How-it-works shots reshot portrait (2026-09-09, owner): 1731x3102 where the first pair was
   1536x1060 landscape. In both frames the subject - head, tool, hand, ear - sits in the top
   55% and the rest is shoulder and shirt. A 4:3 cover crop would keep the middle band, losing
   the tool at the top edge and keeping shirt; a full-height box would run the cards to nearly
   1000px to show that shirt. So the box goes square and the crop anchors to the TOP: the whole
   subject survives and only the shoulder goes. The assets are exported uncropped so this crop
   lives in CSS alone - a 4:5 box is a one-line change if the owner wants the neck back. */
.pdp-v3 .mcard .mshot{aspect-ratio:1/1}
.pdp-v3 .mcard .mshot img{object-position:50% 0}

/* Gallery thumbnails follow the colour (2026-09-10, owner). Every colour's angle, side and
   charge shots are in the strip tagged data-color; only the selected colour's are shown.
   display:none takes the others out of the 5-column grid entirely, so the five that remain
   fill it exactly as the five untagged ones did before. */
.pdp-v3 .thumbs [data-color]:not(.is-on){display:none}

/* Mobile main shot back to square (2026-09-10, owner). The 4:3 crop under 900px was there to
   trim the baked-in whitespace of the original product render. The kit and solo renders that
   now fill this slot are edge-to-edge compositions - person, product, gear strip - and the same
   crop was taking the top of the head and the bottom of the gear off. The slot is shared by
   both cards, so one rule covers The Complete Kit and Just the Touch 2 alike; thumbnails were
   square already. */
@media(max-width:900px){.pdp-v3 .gallery>.shot{aspect-ratio:1/1}}

/* MOBILE GALLERY STRIP: ONE LINE + WHITE EDGE FADE (2026-09-12, owner: "for the gallery since we
   have a lot, can we make the mobile breakout have 1 line for the gallery photos with just the
   white gradient overlay"; 2026-09-12 later: "a gradient that looks like the color of the
   background", so the fade runs to var(--cream), the hero ground, not white). Under 900px the ten tiles (main + nine slides) become one horizontal
   scroller sized to the rail: tile = (rail - 4 gaps) / 4.5, so exactly four and a half tiles show
   on every phone width and the half tile is the "more" cue (owner 2026-09-12: "make the part of the
   next slide also visible ... dynamic spacing depending on the phone size"). The fade box is the
   same square, so it always covers the cut tile and nothing else. The fade sits on
   .gallery::after over the strip's right edge (the strip is the gallery's last child, so bottom:0
   plus the strip height lands on it exactly) and the hero script drops it once the strip is
   scrolled to the end, per the house rule that an edge fade only sits over a cut tile. No arrows,
   no dots. min-width:0 on .gallery matters: as a 1fr grid item its min-content width would
   otherwise grow to the whole strip and the page would scroll sideways. top:auto matters too: the
   desktop sticky rule leaves top:74px behind, and on a relative box that shoved the gallery 74px
   down into the buybox. Desktop grid untouched. */
@media(max-width:900px){
  .pdp-v3 .hero .gallery{position:relative;top:auto;min-width:0;max-width:100%}
  .pdp-v3 .hero .thumbs{display:flex;width:100%;flex-wrap:nowrap;gap:8px;overflow-x:auto;overscroll-behavior-x:contain;scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch;scrollbar-width:none}
  .pdp-v3 .hero .thumbs::-webkit-scrollbar{display:none}
  .pdp-v3 .hero .thumbs .shot{flex:0 0 calc((100% - 32px) / 4.5);width:auto;height:auto;scroll-snap-align:start}
  .pdp-v3 .hero .gallery::after{content:"";position:absolute;right:0;bottom:0;width:calc((100% - 32px) / 4.5 * .95);aspect-ratio:1/1;background:linear-gradient(to right,rgba(244,243,244,0),var(--cream) 70%);pointer-events:none;transition:opacity .2s var(--ease-out)}
  .pdp-v3 .hero .gallery.thumbs-end::after{opacity:0}
}

/* GALLERY TILES AT REST (2026-09-12, owner: "lower the opacity of the unselected gallery image so
   it isn't too much on the eyes", desktop and mobile alike). Ten infographic tiles at full strength
   compete with the main shot, so every tile rests at .55 and only the tile whose slide is on the
   main shot (is-current, set by the hero script on load, colour change and tile click) sits at 1.
   Hover and keyboard focus lift a resting tile to .85 so it still reads as a control. Opacity only,
   no tint, no border, no scale, so the infographic colours stay true when selected. */
.pdp-v3 .thumbs [data-thumb]{opacity:.55;transition:opacity .2s var(--ease-out)}
.pdp-v3 .thumbs [data-thumb]:hover,.pdp-v3 .thumbs [data-thumb]:focus-visible{opacity:.85}
.pdp-v3 .thumbs [data-thumb].is-current{opacity:1}


/* GALLERY: COUNTER, SWIPE, ZOOM, CURRENT RING (2026-09-12, owner: "improve the gallery to be like
   this (other ecom landers do this)", items 1, 2 and 5 of the gallery review). Counter pill sits in
   the main shot's bottom-right, tabular digits so "3 / 10" does not jitter. The current tile gets a
   1.5px ink ring on top of the opacity so keyboard users and low-contrast screens can find it. The
   zoom overlay is moved to <body> by the hero script, so it is styled by its own class, not under
   .pdp-v3; fonts and colours are restated. Fit-to-viewport on open, a tap toggles 2x (capped at
   2400px, twice the 1200px source) inside a native scroll box, so pan is the browser's own. */
.pdp-v3 .gallery>.shot{position:relative;cursor:zoom-in}
.pdp-v3 .gallery>.shot:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.pdp-v3 .gal-count{position:absolute;right:12px;bottom:12px;font-size:12px;font-weight:600;letter-spacing:.04em;line-height:1;color:var(--ink);background:rgba(255,255,255,.9);border-radius:20px;padding:6px 10px;pointer-events:none;font-variant-numeric:tabular-nums;box-shadow:0 1px 4px rgba(20,19,16,.08)}
.pdp-v3 .gal-count:empty{display:none}
.pdp-v3 .thumbs [data-thumb].is-current{box-shadow:inset 0 0 0 1.5px var(--ink)}
html.pdp-v3-galzoom-open{overflow:hidden}
.pdp-v3-galzoom{position:fixed;inset:0;z-index:2147483000;background:#fff;display:flex;flex-direction:column;font-family:Jost,system-ui,sans-serif;color:#141310}
.pdp-v3-galzoom[hidden]{display:none}
.pdp-v3-galzoom .gz-scroll{flex:1;min-height:0;overflow:auto;-webkit-overflow-scrolling:touch;display:flex;align-items:center;justify-content:center;overscroll-behavior:contain}
.pdp-v3-galzoom .gz-scroll img{display:block;width:100%;max-width:min(100vw,calc(100vh - 80px));height:auto;cursor:zoom-in;touch-action:pan-x pan-y}
.pdp-v3-galzoom.is-zoomed .gz-scroll{display:block}
.pdp-v3-galzoom.is-zoomed .gz-scroll img{width:min(260vw,2400px);max-width:none;cursor:zoom-out}
.pdp-v3-galzoom .gz-x{position:absolute;top:12px;right:12px;z-index:2;width:44px;height:44px;border-radius:50%;border:0;background:rgba(255,255,255,.94);box-shadow:0 2px 10px rgba(20,19,16,.14);font:400 26px/44px Jost,system-ui,sans-serif;color:#141310;text-align:center;cursor:pointer;padding:0}
.pdp-v3-galzoom .gz-bar{display:flex;align-items:center;justify-content:center;gap:16px;padding:14px 0 calc(14px + env(safe-area-inset-bottom));font-size:13px;font-weight:600;font-variant-numeric:tabular-nums;border-top:1px solid #ede7da}
.pdp-v3-galzoom .gz-bar button{width:44px;height:44px;border-radius:50%;border:1px solid #ede7da;background:#fff;font:400 24px/42px Jost,system-ui,sans-serif;color:#141310;cursor:pointer;padding:0}
.pdp-v3-galzoom button:focus-visible{outline:2px solid #141310;outline-offset:2px}
@media(prefers-reduced-motion:no-preference){.pdp-v3-galzoom{animation:pdp-v3-galzoom-in .18s ease-out both}}
@keyframes pdp-v3-galzoom-in{from{opacity:0}to{opacity:1}}

/* COMPARISON TABLE CHEVRONS (2026-09-12, owner: "delete that animation and instead add in a dynamic
   chevron that appears and disappears like how we did with the real review section, script it so
   it follows the screen when the viewer is scrolling downwards"). The animated swipe hint is gone
   from the markup (asset kept). The chevrons reuse the review carousel's .bcar-arrow look; each
   lives in its own full-height column inside the existing mobile-only .cmp-hint-wrap overlay and is
   position:sticky at mid-viewport, so it rides with the reader down a tall table and stops at the
   table's ends. The section script shows only the one that leads back in (right at the start, left
   at the end), the review-carousel rule. Overlay stays pointer-events:none; the buttons take it. */
.pdp-v3 #compare .cmp-chev-col{position:absolute;top:0;bottom:0;left:4px;width:44px;pointer-events:none}
.pdp-v3 #compare .cmp-chev-col.next{left:auto;right:4px}
.pdp-v3 #compare .cmp-chev{position:sticky;top:calc(50vh - 22px);left:auto;right:auto;margin:0;pointer-events:auto}
.pdp-v3 #compare .cmp-chev:disabled{pointer-events:none}
@media(prefers-reduced-motion:reduce){.pdp-v3 #compare .cmp-hint-wrap.cmp-chevs{display:block}}
@media(min-width:901px){.pdp-v3 #compare .cmp-hint-wrap.cmp-chevs{display:none}}

/* FINAL CTA ANCHOR (2026-09-12 sweep): the final CTA links to #pdp-v3-buy, which no element carried
   (the audit's dead-anchor item), so the click did nothing. The buy box now owns that id; the
   scroll margin keeps it clear of the sticky subnav when the jump lands. */
.pdp-v3 .buybox{scroll-margin-top:84px}

/* OPTION TITLE WRAPS, BADGE STAYS ON THE FIRST ROW (2026-09-12, owner: Teng's longer solo name
   "Touch 2 Foil Head Shaver" pushed the SAVE 20% pill onto its own row under 560px: "definitely
   ruined the arrangement of the mobile version"). The name now takes the remaining row width and
   wraps inside it, so radio, name and pill share the first row on every phone width and the price
   keeps its own row below (the .p2 flex-basis:100% rule). Kit card unchanged: its title fits. */
@media(max-width:560px){
  .pdp-v3 .opt-hd .opt-nm{flex:1 1 0;min-width:0}
}
@media(max-width:360px){
  .pdp-v3 .opt-hd .kit-title{font-size:19px}   /* 157px rail share at 360 (21px already wrapped): keeps "The Complete Kit" on one line */
}

/* SOLO CARD TICKS (2026-09-12, Teng's edit: two ticks under "Just the Touch 2"). The kit card gets
   its hairlines from .subline above the ticks and .cardline below; the solo card has neither, so
   its ticks sat flush against the price and the IN THE BOX heading. Same rhythm as the kit: 11px
   air and a hairline on both sides of the tick list.
   Revised 2026-09-12 (Teng): solo card is one tick only ("1x Touch 2 Foil Head Shaver"); the
   "(Spare Shaver Replacement not included)" tick and the hairline below the list are removed. */
.pdp-v3 .opt[data-opt="solo"] .ticks{margin-top:10px;padding-top:12px;border-top:1px solid #ede7da;margin-bottom:12px}

/* ===== 2026-09-14 · ALL REVIEWS (Judge.me app block host) + buybox rating link ===== */
.pdp-v3 .rating-row .rating-link{display:inline-flex;align-items:center;gap:9px;color:inherit;text-decoration:none;cursor:pointer}
.pdp-v3 .rating-row .rating-link:hover{text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--mut)}
.pdp-v3 .rating-row .rating-link:focus-visible{outline:2px solid var(--ink);outline-offset:3px;border-radius:3px}
.pdp-v3 .reviews-all{scroll-margin-top:84px}
.pdp-v3 .reviews-all .center{margin-bottom:30px}
.pdp-v3 .reviews-all-widget{max-width:1000px;margin:0 auto}
.pdp-v3 .reviews-all-widget .jdgm-widget{font-family:inherit}
.pdp-v3 .reviews-all .center{margin-bottom:26px}
.pdp-v3 .reviews-all-widget .jdgm-rev-widg__title{display:none!important}
.pdp-v3 .reviews-all-widget .jdgm-rev-widg{padding-top:0}
/* attached mode: second half of the Real Results section */
.pdp-v3 .reviews-all.is-attached{border-top:0;padding-top:0;margin-top:-16px}
.pdp-v3 .reviews-all.is-attached .wrap{border-top:1px solid var(--line);padding-top:44px}
.pdp-v3 .reviews-all.is-attached .center h2{font-size:clamp(24px,2.6vw,32px)}
@media(max-width:560px){.pdp-v3 .reviews-all.is-attached{margin-top:0}.pdp-v3 .reviews-all.is-attached .wrap{padding-top:34px}}
/* hide the list while the widget re-sorts to the page default (no most-recent flash) */
.pdp-v3 .reviews-all-widget .jdgm-rev-widg__reviews,.pdp-v3 .reviews-all-widget .jdgm-paginate{transition:opacity .25s}
.pdp-v3 .reviews-all-widget.is-resorting .jdgm-rev-widg__reviews,.pdp-v3 .reviews-all-widget.is-resorting .jdgm-paginate{opacity:0}
/* live star fill: --pct = average / scale (hero rating rows) */
.pdp-v3 .rating-row .stars-live{background:linear-gradient(90deg,#8a6a17 var(--pct,100%),#d6d0c2 var(--pct,100%));-webkit-background-clip:text;background-clip:text;color:transparent}

/* ===== 2026-09-14 · hero first in the template (subnav hidden): absorb the theme header's bottom gap the way the
   subnav did (-44px desktop / -22px ≤900px), and trim the hero's own top padding so the rating row sits ~24px under the nav. ===== */
[id*='__v3_subnav'] + [id*='__v3_hero'], [id*='__v3_hero']:first-child{margin-top:-44px;position:relative}
[id*='__v3_subnav']:not([style*='display:none']) + [id*='__v3_hero']{margin-top:0}
[id*='__v3_hero']:first-child .pdp-v3 .hero{padding-top:24px}
@media(max-width:900px){[id*='__v3_hero']:first-child{margin-top:-22px}}
@media(max-width:560px){[id*='__v3_hero']:first-child .pdp-v3 .hero{padding-top:14px}}

/* SWATCH SELECTED RING (2026-09-16, owner Loom: "black is not visible, change the ring colour").
   The old selected state was a 2px ink border on the disc itself, invisible on the black photo.
   Offset ring instead: a 2px white gap inside the disc, then a 2px ink ring outside, so every
   colour (black included) reads as selected. Unselected discs unchanged. */
.pdp-v3 .sw.on{border-color:#fff;box-shadow:0 0 0 2px var(--ink)}

/* COMPARE TABLE CORNERS (2026-09-16, Shun: "corner radius consistent with the other cards").
   border-collapse ignores border-radius, so the white table sat square inside a 10px page of
   cards (the wrap's radius is 40px above it, in the transparent overhang zone). Separate model
   with zero spacing: each body cell draws only its bottom line (the top line that collapse used
   to merge away is zeroed, so no double rules), then the table and its four corner cells take
   the house radius. Row heights unchanged, sticky feature column unchanged. */
.pdp-v3 #compare table{border-collapse:separate;border-spacing:0;border-radius:var(--radius)}
.pdp-v3 #compare tbody td,.pdp-v3 #compare tbody th{border-top:0}
.pdp-v3 #compare thead .th-feature{border-top-left-radius:var(--radius)}
.pdp-v3 #compare thead th:last-child{border-top-right-radius:var(--radius)}
.pdp-v3 #compare tbody tr:last-child th{border-bottom-left-radius:var(--radius)}
.pdp-v3 #compare tbody tr:last-child td:last-child{border-bottom-right-radius:var(--radius)}
/* The table's shadow is the .cmp-scroller::after rectangle (see COMPARE shadow note above); it was
   square, so its 1px bottom edge read as a straight rule under the now-rounded table. Same radius. */
.pdp-v3 #compare .cmp-scroller::after{border-radius:var(--radius)}
