
from pathlib import Path
from weasyprint import HTML
import subprocess
root=Path('/mnt/data/next_rc59_work')
qa=root/'qa_static'; shots=root/'qa_screenshots'
qa.mkdir(exist_ok=True); shots.mkdir(exist_ok=True)
CSS = '''
@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 96px;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}.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:250px}.content{position:relative;z-index:1;padding:20px;display:grid;gap:10px;max-width:72%}.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:33ch;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}.progress{display:grid;gap:6px;color:rgba(226,240,255,.75);font-weight:820}.bar{height:7px;border-radius:999px;background:rgba(87,144,185,.18);overflow:hidden}.bar b{display:block;height:100%;width:58%;background:linear-gradient(90deg,#4bdfff,#7cc9ff);border-radius:inherit}.list{display:grid;gap:10px}.listCard{padding:16px;display:grid;grid-template-columns:54px minmax(0,1fr);gap:12px}.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{grid-column:1/-1;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:10px}.rhythm{display:flex;flex-wrap:wrap;gap:6px}.day{border:1px solid rgba(104,222,255,.17);border-radius:17px;background:rgba(4,14,28,.54);padding:12px;display:grid;gap:10px}.dayHead{display:flex;gap:8px;align-items:baseline}.dayHead b{color:#7ef1ff;text-transform:uppercase;letter-spacing:.13em;font-size:11px}.dayHead strong{font-size:18px}.block{border:1px solid rgba(104,222,255,.12);border-radius:14px;background:rgba(5,16,30,.44);overflow:hidden}.blockHead{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px;padding:7px 10px;border-bottom:1px solid rgba(104,222,255,.10);background:linear-gradient(90deg,rgba(3,80,115,.34),rgba(5,20,36,.18))}.blockHead strong{color:#8cf2ff;text-transform:uppercase;letter-spacing:.16em;font-size:10px}.blockHead span{justify-self:end;color:rgba(226,240,255,.64);font-size:11px}ul{margin:0;padding:0;list-style:none}li{min-height:30px;display:grid;grid-template-columns:38px minmax(0,1fr) auto;gap:8px;align-items:center;padding:6px 9px;border-top:1px solid rgba(104,222,255,.08);color:rgba(226,240,255,.78);font-size:12px}li:first-child{border-top:0}li b{width:28px;min-height:22px;display:grid;place-items:center;border-radius:8px;border:1px solid rgba(104,222,255,.18);color:#8cf2ff;font-size:10px}.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 .featured{display:grid;grid-template-columns:1fr 1fr}.desktop .listCard{grid-template-columns:62px minmax(0,1fr) 260px}.desktop .listActions{grid-column:auto;grid-template-columns:1fr}.tablet{padding:24px}.tablet .top{height:88px;border-radius:30px}.tablet .page{max-width:820px}.tablet .card h2{font-size:42px}
'''
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">Påbörjade program</div><section class="card"><div class="content"><span class="badge">Påbörjat</span><h2>Snabbhetsmix</h2><p class="target">9–12 år · Utveckling</p><div class="chips"><span class="chip">Snabbhet</span><span class="chip">Hopp</span></div><div class="progress"><span>7 av 12 pass</span><div class="bar"><b></b></div></div><div class="actions"><div class="btn">Förhandsvisa</div><div class="btn primary">Återuppta</div></div></div></section><div class="section">Rekommenderade program</div><section class="card featured"><div class="content"><span class="badge">Bäst match</span><h2>Explosiv hockeygrund</h2><p class="target">9–12 år · Utveckling</p><p class="desc">Snabbhet, styrka och koordination för unga hockeyspelare.</p><div class="chips"><span class="chip">12 pass</span><span class="chip">4 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">Välj program</div></div></div></section><div class="section">Alla program</div><section class="list"><article class="listCard"><div class="ico">▥</div><div><h3>Rörlighet & kontroll</h3><p class="target">9–12 år · Utveckling</p><div class="chips"><span class="chip">Balans</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 grupperar passen som passöversikten.</p></header><section class="card"><div class="content" style="max-width:100%"><h2>Explosiv hockeygrund</h2><p class="target">9–12 år · Utveckling</p><div class="preview"><strong>Förhandsvisning</strong><p class="desc">Vecka 1 visas utan kalenderstatus.</p><div class="rhythm"><span class="chip">Mån Pass 1</span><span class="chip">Tis Pass 2</span><span class="chip">Ons Vila</span><span class="chip">Tor Pass 3</span></div><article class="day"><div class="dayHead"><b>Dag 1</b><strong>Helkropp</strong></div><div class="block"><div class="blockHead"><strong>Uppvärmning</strong><span>Uppvärmning</span></div><ul><li><b>0</b><span>Dynamisk uppvärmning</span><em>—</em></li></ul></div><div class="block"><div class="blockHead"><strong>Explosivitet</strong><span>Snabbhet & explosivitet</span></div><ul><li><b>1</b><span>Pogohopp sidled</span><em>2 × 9 m</em></li><li><b>2</b><span>Carioca-steg</span><em>2 × 18 m</em></li><li><b>A</b><span>Sidledshopp</span><em>4 hopp/sida</em></li></ul></div><div class="block"><div class="blockHead"><strong>Styrka</strong><span>Styrka</span></div><ul><li><b>A</b><span>Knäböj</span><em>8 reps</em></li><li><b>B</b><span>Armhävning</span><em>6 reps</em></li></ul></div></article></div></div></section></main>'''
modal=base + '''<div class="modalBackdrop"><div class="modal"><strong>Återuppta program?</strong><p>Du har tidigare genomfört 7 av 12 pass i Snabbhetsmix. 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>'''

renders=[
 ('rc59_program_mobile_390x844',390,844,base,''),
 ('rc59_program_full_mobile_390x1600',390,1600,base,''),
 ('rc59_program_preview_mobile_390x844',390,844,preview,''),
 ('rc59_program_resume_modal_mobile_390x844',390,844,modal,''),
 ('rc59_program_ipad_820x1180',820,1180,base,'tablet'),
 ('rc59_program_desktop_1440x1024',1440,1024,base,'desktop'),
]
for name,w,h,content,klass in renders:
    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')
