from pathlib import Path
from weasyprint import HTML
import subprocess
root=Path('/mnt/data/next_rc61_work')
qa=root/'qa_static'; shots=root/'qa_screenshots'
qa.mkdir(exist_ok=True); shots.mkdir(exist_ok=True)
CSS=r'''
@page{margin:0}*{box-sizing:border-box}html,body{margin:0;background:#030912;color:#f8fbff;font-family:Arial,Helvetica,sans-serif}body{padding:20px 16px 112px;background:radial-gradient(620px 360px at 85% 4%,rgba(44,160,255,.18),transparent 58%),linear-gradient(180deg,#030914,#071426 58%,#020811)}.top{height:68px;border:1px solid rgba(110,220,255,.26);border-radius:24px;background:linear-gradient(180deg,rgba(10,23,42,.94),rgba(5,13,25,.96));display:flex;align-items:center;justify-content:space-between;padding:0 24px;margin-bottom:14px;box-shadow:0 14px 36px rgba(0,0,0,.24)}.menu,.person{color:#6eeaff;text-align:center;font-size:30px;font-weight:300;line-height:1;width:46px}.logo{text-align:center}.logo b{display:block;font-size:40px;line-height:.75;letter-spacing:.16em}.logo b span{color:#5ce4ff}.logo small{font-size:8px;letter-spacing:.35em;color:#77f0ff;font-weight:800}.page{max-width:1120px;margin:0 auto;display:grid;gap:14px}.head h1{font-size:48px;line-height:.9;margin:0 0 8px;font-weight:950;letter-spacing:-.055em}.head p{font-size:16px;line-height:1.35;margin:0;color:#b9c5d5;max-width:44ch}.strip{display:flex;align-items:center;gap:8px;flex-wrap:wrap;border:1px solid rgba(104,222,255,.22);border-radius:20px;background:linear-gradient(180deg,rgba(12,28,48,.76),rgba(6,15,28,.70));padding:10px 12px}.strip strong{font-size:20px;font-weight:930;width:100%}.section{color:#7ef1ff;text-transform:uppercase;letter-spacing:.24em;font-size:12px;font-weight:950;margin-top:6px}.section small{color:rgba(218,231,246,.62);letter-spacing:.04em;text-transform:none;margin-left:8px}.chip{display:inline-flex;align-items:center;gap:6px;min-height:28px;border-radius:999px;border:1px solid rgba(104,222,255,.22);background:rgba(8,20,36,.62);padding:6px 9px;color:#f6fbff;font-size:12px;font-weight:830;white-space:nowrap}.card,.listCard{position:relative;overflow:hidden;border:1px solid rgba(104,222,255,.24);border-radius:24px;background:radial-gradient(650px 260px at 88% 18%,rgba(45,165,255,.20),transparent 56%),linear-gradient(180deg,rgba(9,23,42,.88),rgba(4,12,24,.92));box-shadow:inset 0 1px 0 rgba(255,255,255,.04),0 18px 42px rgba(0,0,0,.20)}.card{min-height:220px}.content{position:relative;z-index:1;padding:20px;display:grid;gap:10px;max-width:100%}.card h2,.listCard h3{margin:0;font-size:34px;line-height:1;letter-spacing:-.045em;font-weight:950;color:#fff}.target{margin:0;color:#73ecff;font-weight:850;font-size:15px}.desc{margin:0;max-width:38ch;color:rgba(232,242,255,.78);line-height:1.32;font-weight:650}.chips{display:flex;flex-wrap:wrap;gap:7px}.actions{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:4px}.btn{min-height:48px;border:1px solid rgba(109,222,255,.32);border-radius:16px;background:rgba(5,15,30,.64);display:flex;align-items:center;justify-content:center;gap:8px;font-weight:900}.btn.primary{border-color:rgba(89,216,255,.85);background:linear-gradient(180deg,#73c7ff,#48a9ff);color:#061226}.badge{display:inline-flex;align-items:center;min-height:28px;padding:5px 10px;border-radius:999px;border:1px solid rgba(113,231,255,.34);background:rgba(7,22,40,.58);color:#80efff;text-transform:uppercase;letter-spacing:.12em;font-size:11px;font-weight:950}.list{display:grid;gap:10px}.listCard{padding:16px;display:flex;flex-wrap:wrap;gap:12px}.listCard>div:nth-child(2){flex:1 1 230px;min-width:0}.ico{width:46px;height:46px;border-radius:16px;border:1px solid rgba(104,222,255,.22);display:grid;place-items:center;color:#7ef1ff;font-size:24px}.listActions{flex:1 1 100%;display:grid;grid-template-columns:1fr 1fr;gap:8px}.preview{margin-top:8px;padding:12px;border-radius:18px;border:1px solid rgba(104,222,255,.17);background:rgba(2,9,18,.44);display:grid;gap:12px}.previewHead{display:flex;justify-content:space-between;gap:12px}.previewHead strong{font-size:18px}.previewHead span{display:inline-flex;padding:5px 9px;border-radius:999px;border:1px solid rgba(126,241,255,.26);color:#7ef1ff;text-transform:uppercase;letter-spacing:.12em;font-size:10px;font-weight:950}.note{border:1px solid rgba(126,241,255,.12);border-radius:14px;padding:10px 12px;color:rgba(226,240,255,.76);background:rgba(6,17,31,.42);font-size:13px;line-height:1.35}.summary{display:grid;gap:12px}.summary b,.listTitle{display:block;margin:0 0 8px;color:#7ef1ff;text-transform:uppercase;letter-spacing:.18em;font-size:11px;font-weight:950}.equipment,.tags{display:flex;flex-wrap:wrap;gap:6px}.equipment span{display:inline-flex;min-height:28px;padding:6px 9px;border-radius:999px;border:1px solid rgba(104,222,255,.20);background:rgba(7,20,36,.58);font-size:12px;font-weight:820}.exList{display:grid;gap:10px}.exGroup{border:1px solid rgba(104,222,255,.15);border-radius:16px;overflow:hidden;background:rgba(3,12,24,.34)}.exHead{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:10px;padding:9px 11px;background:linear-gradient(90deg,rgba(4,80,116,.34),rgba(4,28,53,.18));border-bottom:1px solid rgba(104,222,255,.12)}.exHead strong{color:#7ef1ff;text-transform:uppercase;letter-spacing:.16em;font-size:11px}.exHead span{color:#fff;font-weight:900;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.exHead em{color:rgba(226,240,255,.58);font-style:normal;font-size:11px;font-weight:760;white-space:nowrap}ul{list-style:none;margin:0;padding:0}li{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:10px;align-items:center;padding:9px 11px;border-top:1px solid rgba(104,222,255,.09)}li:first-child{border-top:0}li>span{font-weight:820;overflow:hidden;text-overflow:ellipsis}.eqMini{display:flex;flex-wrap:wrap;gap:5px}.eqMini span{display:inline-flex;min-height:24px;padding:5px 7px;border-radius:999px;border:1px solid rgba(104,222,255,.18);background:rgba(9,29,49,.62);font-size:10.5px;font-weight:820}.modalBackdrop{position:fixed;inset:0;background:rgba(1,6,14,.58);display:grid;place-items:center;padding:24px}.modal{width:min(100%,520px);border:1px solid rgba(126,241,255,.36);border-radius:24px;background:linear-gradient(180deg,rgba(10,25,45,.96),rgba(3,10,21,.96));box-shadow:0 28px 90px rgba(0,0,0,.54);padding:20px;display:grid;gap:14px}.modal strong{font-size:30px;line-height:1}.modal p{margin:0;color:rgba(226,240,255,.78);font-size:16px;line-height:1.38;font-weight:700}.modalActions{display:grid;grid-template-columns:1fr;gap:9px}.desktop{padding:24px}.desktop .top{height:90px;border-radius:30px}.desktop .page{max-width:1180px}.desktop .card h2{font-size:44px}.desktop .listCard{flex-wrap:nowrap}.desktop .listActions{flex:0 0 260px;grid-template-columns:1fr}.desktop .summary{grid-template-columns:1fr 1fr}.tablet{padding:24px}.tablet .top{height:88px;border-radius:30px}.tablet .page{max-width:820px}.tablet .card h2{font-size:42px}@media(max-width:430px){.actions,.listActions{grid-template-columns:1fr}.exHead{grid-template-columns:1fr auto}.exHead strong{grid-column:1/-1}li{grid-template-columns:1fr}.previewHead{display:grid}.previewHead span{justify-self:start}}
'''
def shell(content,w,h,klass=''):
    return f'<!doctype html><html><head><meta charset="utf-8"><style>@page{{size:{w}px {h}px;margin:0}}{CSS}</style></head><body class="{klass}"><div class="top"><div class="menu">☰</div><div class="logo"><b>NE<span>X</span>T</b><small>ATHLETE OS</small></div><div class="person">◯</div></div>{content}</body></html>'
base='''<main class="page"><header class="head"><h1>Program</h1><p>Välj program för aktiv profil. Kalendern planerar pass utifrån programmet.</p></header><section class="strip"><strong>Isak</strong><span class="chip">Hockey</span><span class="chip">9–12 år</span><span class="chip">Utveckling</span></section><div class="section">Rekommenderat program</div><section class="card"><div class="content"><span class="badge">Valt</span><h2>9–12 år · Utveckling</h2><p class="target">Modellprogram</p><p class="desc">3 pass per vecka. Pass 1 och 2 kan ligga nära, men Pass 3 ska ha vilodag före.</p><div class="chips"><span class="chip">36 pass</span><span class="chip">12 veckor</span><span class="chip">3 pass/vecka</span></div><div class="chips"><span class="chip">Snabbhet</span><span class="chip">Styrka</span><span class="chip">Koordination</span></div><div class="actions"><div class="btn">Förhandsvisa</div><div class="btn primary">Valt program</div></div></div></section><div class="section">Alla program <small>3 i modellen</small></div><section class="list"><article class="listCard"><div class="ico">1</div><div><h3>7–9 år · Grund</h3><p class="target">24 pass · 12 veckor · 2 pass/vecka</p><div class="chips"><span class="chip">Koordination</span><span class="chip">Balans</span></div></div><div class="listActions"><div class="btn">Förhandsvisa</div><div class="btn primary">Välj program</div></div></article><article class="listCard"><div class="ico">2</div><div><h3>9–12 år · Utveckling</h3><p class="target">36 pass · 12 veckor · 3 pass/vecka</p><div class="chips"><span class="chip">Snabbhet</span><span class="chip">Styrka</span></div></div><div class="listActions"><div class="btn">Förhandsvisa</div><div class="btn primary">Valt program</div></div></article><article class="listCard"><div class="ico">3</div><div><h3>12–16 år · Avancerad</h3><p class="target">48 pass · 12 veckor · 4 pass/vecka</p><div class="chips"><span class="chip">Styrka</span><span class="chip">Teknik</span></div></div><div class="listActions"><div class="btn">Förhandsvisa</div><div class="btn primary">Välj program</div></div></article></section></main>'''
preview='''<main class="page"><header class="head"><h1>Program</h1><p>Förhandsvisning visar komplett programinnehåll utan doser.</p></header><section class="card"><div class="content" style="max-width:100%"><h2>9–12 år · Utveckling</h2><p class="target">36 pass · 12 veckor · 3 pass/vecka</p><div class="preview"><header class="previewHead"><div><strong>Programinnehåll</strong><p class="desc">9–12 år · Utveckling</p></div><span>Malläge</span></header><div class="note">Förhandsvisningen visar programmets innehåll. Kalendern planerar veckor, vila och tester när programmet väljs.</div><div class="summary"><div><b>Fokus</b><div class="tags"><span class="chip">Snabbhet</span><span class="chip">Styrka</span><span class="chip">Koordination</span></div></div><div><b>Utrustning i programmet</b><div class="equipment"><span>koner/markeringar</span><span>hopprep</span><span>medicinboll</span><span>box/bänk</span></div></div></div><div class="exList"><div class="listTitle">Övningar i programmet</div><section class="exGroup"><div class="exHead"><strong>Uppvärmning</strong><span>Uppvärmning</span><em>1 övning</em></div><ul><li><span>Dynamisk uppvärmning</span></li></ul></section><section class="exGroup"><div class="exHead"><strong>Explosivitet</strong><span>Speed & Power</span><em>5 övningar</em></div><ul><li><span>Pogohopp sidled</span><div class="eqMini"><span>koner/markeringar</span></div></li><li><span>Carioca-steg</span><div class="eqMini"><span>koner/markeringar</span></div></li><li><span>Sidledshopp</span></li><li><span>Sidokast med medicinboll</span><div class="eqMini"><span>medicinboll</span></div></li><li><span>Pro shuttle</span><div class="eqMini"><span>koner/markeringar</span></div></li></ul></section><section class="exGroup"><div class="exHead"><strong>Styrka</strong><span>Styrka</span><em>4 övningar</em></div><ul><li><span>Knäböj</span></li><li><span>Armhävning</span></li><li><span>Boxhopp</span><div class="eqMini"><span>box/bänk</span></div></li><li><span>Farmers carry</span><div class="eqMini"><span>hantlar</span></div></li></ul></section></div><div class="btn primary">Välj program</div></div></div></section></main>'''
modal=base + '''<div class="modalBackdrop"><div class="modal"><strong>Återuppta program?</strong><p>Du har tidigare genomfört 7 av 36 pass i 9–12 år · Utveckling. Vill du fortsätta där du slutade eller starta om?</p><div class="modalActions"><div class="btn">Avbryt</div><div class="btn">Starta om</div><div class="btn primary">Återuppta</div></div></div></div>'''
for name,w,h,content,klass in [
 ('rc61_program_mobile_390x844',390,844,base,''),
 ('rc61_program_full_mobile_390x1600',390,1600,base,''),
 ('rc61_program_preview_mobile_390x844',390,844,preview,''),
 ('rc61_program_resume_modal_mobile_390x844',390,844,modal,''),
 ('rc61_program_ipad_820x1180',820,1180,base,'tablet'),
 ('rc61_program_desktop_1440x1024',1440,1024,base,'desktop')]:
    html=qa/f'{name}.html'; pdf=qa/f'{name}.pdf'; basep=shots/name
    html.write_text(shell(content,w,h,klass),encoding='utf-8')
    HTML(filename=str(html), base_url=str(root)).write_pdf(str(pdf))
    subprocess.run(['pdftoppm','-png','-singlefile','-r','144',str(pdf),str(basep)],check=True)
    print(shots/f'{name}.png')
