"""Render the existing exposure-expression arithmetic; no mission model."""
from pathlib import Path
import math, json, csv, hashlib
from xml.sax.saxutils import escape
OUT=Path(__file__).resolve().parent
SOURCE=OUT/'exposure-scaling.csv'
def rhs(s,d):
    return 3.54e-3*s**4*7**2*(1+.79+.05)*d**-3/(365.25*86400)
rows=list(csv.DictReader(SOURCE.open()))
assert all(math.isclose(rhs(int(r['side_pixels']),int(r['aperture_m'])),float(r['total_rhs_Julian_years']),rel_tol=1e-14) for r in rows)
s=['<svg xmlns="http://www.w3.org/2000/svg" width="288" height="780" viewBox="0 0 288 780" role="img" aria-labelledby="t d"><title id="t">Published exposure expression, fixed assumptions</title><desc id="d">Calculated inequality right-hand side in Julian years, for one and two metre apertures and25 to200 pixels per side. Logarithmic vertical axis. Not a mission duration or operational guarantee.</desc><rect width="288" height="780" fill="white"/><g font-family="Arial,sans-serif" font-size="18" fill="#142440">']
def text(x,y,v,size=18,anchor='start'):
    s.append(f'<text x="{x}" y="{y}" font-size="{size}" text-anchor="{anchor}">{escape(v)}</text>')
def line(x,y,X,Y,c='#cbd5e1',dash=''):
    s.append(f'<path d="M{x} {y}L{X} {Y}" fill="none" stroke="{c}" stroke-dasharray="{dash}"/>')
text(16,30,'Published exposure',21);text(16,57,'expression',21)
text(16,89,'SNR 7 · 30 pc · 650 AU')
text(16,122,'Integration RHS (years)')
text(16,149,'Logarithmic vertical scale',17)
for yy,c,label,dash in [(182,'#9b288f','1 m aperture',''),(213,'#176a8a','2 m aperture','6 3')]:
    line(18,yy,44,yy,c,dash);text(54,yy+6,label)
left,right,top,bottom=65,269,254,574
def X(n):return left+(right-left)*(n-25)/175
def Y(v):return bottom-(math.log10(v)+4)/6*(bottom-top)
for v,label in [(1e-4,'0.0001'),(.01,'0.01'),(1,'1'),(100,'100')]:
    y=Y(v);line(left,y,right,y);text(left-6,y+5,label,16,'end')
for n in [25,100,200]:
    x=X(n);line(x,top,x,bottom);text(x,601,str(n),18,'middle')
for d,c,dash in [(1,'#9b288f',''),(2,'#176a8a','6 3')]:
    pts=' '.join(f'{X(n):.6f},{Y(rhs(n,d)):.6f}' for n in range(25,201))
    s.append(f'<polyline points="{pts}" fill="none" stroke="{c}" stroke-width="2" stroke-dasharray="{dash}"/>')
text(144,634,'Pixels along each side',18,'middle');text(144,660,'Total pixels = side²',18,'middle')
text(16,702,'Published inequality RHS,',18);text(16,728,'not a mission duration',18);text(16,754,'or operational guarantee.',18)
s.append('</g></svg>')
(OUT/'exposure-mobile.svg').write_text('\n'.join(s)+'\n',encoding='utf-8')
(OUT/'exposure-mobile-provenance.json').write_text(json.dumps({'source_csv_sha256':hashlib.sha256(SOURCE.read_bytes()).hexdigest(),'csv_rows_verified':len(rows),'curve_points_per_series':176,'max_relative_tolerance_csv':1e-14,'scope':'Same fixed expression as exposure.py, algebraically simplified at fixed parameters; full176points per curve retained; new layout only.'},indent=2),encoding='utf-8')
