#!/usr/bin/env python3
# Book 18 (UltraTech Cement) — THE GLUE THAT HOLDS CITIES. Science->business: limestone (an ancient
# sea pressed into rock) is roasted in a kiln into grey powder -> mixed with water, tiny crystals GROW
# and lock into man-made stone (concrete) -> the giant that pours the stone Indian cities stand on.
import os
ART="/root/omahaindia.com/comics/site/book/ultratech/art"
OUT="/root/omahaindia.com/comics/site/book/ultratech/index.html"
STYLE=("children's storybook manga illustration, warm painted animation style, soft cinematic light, "
"clean linework, NO text NO letters NO words")
CHARLOTTE=("Charlotte, the SAME young Indian CHILD girl from the reference, round young face, warm tan skin, "
"freckles, glossy black hair in two low twin ponytails, big curious dark eyes, bright TEAL t-shirt, NO facial hair")
GRAHAM="Ben, a kind scholarly elderly American gentleman, round wire spectacles, tweed suit and bow tie"
BUFFETT="Warren, a folksy cheerful elderly American man, thinning white hair, big friendly glasses, grey suit"
MUNGER="Charlie, a stocky wise elderly American man, very thick black-framed glasses, dark suit"
VERA=("Vera, a warm friendly Western CIVIL ENGINEER woman, NOT Indian, a white hard hat, a rolled "
"blueprint under one arm, bright orange hi-vis safety vest over a teal shirt, confident kind smile")

# name -> (w,h,seed,prompt,ref). ref set -> Seedream character; None -> flux scene. Ritual panels copied by mkbook.
NEW={
 "00_cover":(1024,1180,1800,f"{STYLE}. BOOK COVER, {CHARLOTTE} standing with {VERA} on a tall concrete bridge, Charlotte holding up a handful of soft grey powder that swirls upward and turns into a shining city skyline of towers and bridges, warm golden light, bright-eyed wonder, cinematic","charlotte"),
 "_ref_vera":(1024,1024,1801,f"{STYLE}. clean friendly character portrait, {VERA}, plain soft warm background, confident kind smile, head and shoulders",None),
 # Ch1
 "ut_c1_coin":(1024,720,1810,f"{STYLE}. {CHARLOTTE} at home, Grandpa Ben's glowing brass compass twitching between a little glass jar of soft grey powder and the tall city towers outside the window, EXPRESSION puzzled and curious, cozy lamp light","charlotte"),
 "ut_c1_diary":(1024,720,1811,f"{STYLE}. an open magical diary glowing warm gold on a desk, a faint ribbon of grey dust rising from the page and curling into a tiny stone tower, no people",None),
 "ut_c1_swirl":(1024,720,1812,f"{STYLE}. {CHARLOTTE} pulled into a swirling spiral of golden light and soft grey dust from a glowing diary, EXPRESSION thrilled, magical","charlotte"),
 # Ch2 — arrive at the limestone quarry, meet Vera
 "ut_c2_arrive":(1024,720,1813,f"{STYLE}. {CHARLOTTE} landing wide-eyed at the rim of an enormous terraced limestone quarry, giant pale grey-white steps of rock carved into a whole mountain, EXPRESSION astonished delight, bright daylight","charlotte"),
 "ut_c2_vera":(1024,720,1814,f"{STYLE}. {VERA} warmly welcoming {CHARLOTTE} at the quarry, tipping her white hard hat, EXPRESSION Charlotte shy eager smile; keep the SAME civil engineer from the reference, same white hard hat, same orange hi-vis vest, same rolled blueprint","vera"),
 "ut_c2_quarry":(1024,720,1815,f"{STYLE}. a vast pale limestone quarry seen from above, huge terraced white-grey walls, tiny yellow trucks carrying rock toward a giant plant with tall round silos on the horizon, powerful and awe-inspiring, no faces close up",None),
 # Ch3 — limestone: the rock made of an ancient sea
 "ut_c3_shells":(1024,720,1816,f"{STYLE}. {VERA} kneeling to show {CHARLOTTE} a pale chunk of limestone with a perfect spiral seashell fossil inside it, EXPRESSION Charlotte fascinated leaning close; SAME civil engineer, white hard hat, orange vest","vera"),
 "ut_c3_sea":(1024,720,1817,f"{STYLE}. a warm ancient shallow sea glowing with sunlight, teeming with shelled sea creatures, corals and spiral shells drifting down like slow snow onto the sea floor, magical and alive, no people",None),
 "ut_c3_rock":(1024,720,1818,f"{STYLE}. a friendly close up of pale limestone rock dotted with tiny shell and coral fossils, as if a whole ancient sea is sleeping inside the stone, playful science, no people",None),
 # Ch4 — the kiln: roasting rock into grey powder
 "ut_c4_kiln":(1024,720,1819,f"{STYLE}. {VERA} showing {CHARLOTTE} a colossal slowly-turning steel kiln tube glowing orange at its mouth, crushed pale rock feeding in, EXPRESSION Charlotte wide-eyed awe stepping back from the heat; SAME civil engineer, white hard hat, orange vest","vera"),
 "ut_c4_fire":(1024,720,1820,f"{STYLE}. a magical cutaway inside a great rotating kiln, tumbling rocks glowing orange and white in a roaring heat brighter than lava, warm dramatic light, no people",None),
 "ut_c4_powder":(1024,720,1821,f"{STYLE}. dark roasted pebbles being ground between great steel rollers into a soft fine grey powder that pours down like grey flour, gentle and satisfying, no people",None),
 # Ch5 — water wakes the powder: crystals grow and lock
 "ut_c5_mix":(1024,720,1822,f"{STYLE}. {VERA} mixing grey powder with water, sand and pebbles in a wide pan while {CHARLOTTE} stirs, thick grey paste folding like dough, EXPRESSION Charlotte delighted 'aha'; SAME civil engineer, white hard hat, orange vest","vera"),
 "ut_c5_crystal":(1024,720,1823,f"{STYLE}. a magical microscope view inside wet cement paste, thousands of tiny glowing needle-like crystals growing outward from grey grains and weaving together like interlocking fingers, sparkling teal and gold, no people",None),
 # Ch6 — paste turns to man-made stone, even under water
 "ut_c6_harden":(1024,720,1824,f"{STYLE}. {CHARLOTTE} rapping her knuckles on a smooth grey concrete slab that was soft paste yesterday, EXPRESSION intrigued disbelief, {VERA} smiling knowingly beside her; SAME civil engineer, white hard hat, orange vest","vera"),
 "ut_c6_underwater":(1024,720,1825,f"{STYLE}. an underwater view of a great concrete bridge pillar standing firm on the riverbed, curious fish circling it, sunbeams slanting through blue-green water, calm and wondrous, no people",None),
 # Ch7 — the glue that holds cities
 "ut_c7_city":(1024,720,1826,f"{STYLE}. a joyful sweeping view of a bright Indian city — tall towers, a metro line on graceful pillars, a school, a hospital, a flyover — all built of concrete, warm morning light, no faces close up",None),
 "ut_c7_everywhere":(1024,720,1827,f"{STYLE}. a warm storybook map of India dotted with rising homes, bridges, dams and roads, thin grey ribbons of fresh concrete flowing out to every corner, gentle and grand, no people",None),
 # Ch8 — reveal UltraTech
 "ut_c8_reveal":(1024,720,1828,f"{STYLE}. {CHARLOTTE} and {VERA} standing proudly before a vast modern cement plant with tall round silos and a long kiln glowing against a blue sky, EXPRESSION Charlotte beaming pride; SAME civil engineer, white hard hat, orange vest","charlotte"),
 "ut_c8_history":(1024,720,1829,f"{STYLE}. warm sepia scene, many scattered cement plants across a wide land being gathered together under one great flag, hopeful workers and rising silos, inspiring, no text",None),
 "ut_c8_scale":(1024,720,1830,f"{STYLE}. a mighty modern cement plant at golden hour, colossal silos and conveyors, long lines of cement trucks rolling out toward distant city skylines, proud and grand, no people",None),
 # Ch10 (ch9 uses ritual castle/invert/verdict; ch10 uses ritual wake/diary)
 "ut_c10_look":(1024,720,1831,f"{STYLE}. {CHARLOTTE} outside on a bright morning looking around as every building, bridge, pavement and flyover near her glows softly grey-gold, knowing each one is poured stone, EXPRESSION soft glowing joy","charlotte"),
}

def P(img,cap=None,b1=None,b2=None,sfx=None,sfxc="#e8425a",tall=False): return ("panel",img,cap,b1,b2,sfx,sfxc,tall)
def SUB(d,t): return ("sub",d,t)
def WOW(t): return ("wow",t)
def NOTE(t,b): return ("note",t,b)
def TL(r): return ("timeline",r)
def MOAT(c): return ("moat",c)

CHAPTERS=[
 ("c1","CHAPTER 1","The Powder and the Towers","pages 1-8",[
   P("ut_c1_coin","Back home, Grandpa Ben's compass twitched again — pointing between a little jar of grey powder and the tall towers outside the window.","Dusty grey powder… and a whole CITY? What's the link?",None,"twitch"),
   P("ut_c1_diary","The old diary fell open. A new line shimmered in Grandpa Ben's hand.",None,'"Find the powder that turns back into stone."'),
   WOW("A pinch of soft grey powder and a giant tower don't seem to belong together — yet almost every building, bridge and road you've ever stood on began as powder in a bag. How does something softer than flour hold up a city? That's the puzzle of this whole adventure."),
   P("ut_c1_swirl","Golden light swirled up and pulled Charlotte in.","Here we GO!",None,"WHOOSH","#5b7a99"),
   NOTE("Charlotte's Secret Notebook","Two BIG questions:<br>➊ How can a soft grey powder hold up giant buildings?<br>➋ Grandpa Ben says it <i>turns back into stone</i>. Back? Was it stone BEFORE? 🪨"),
 ]),
 ("c2","CHAPTER 2","The Mountain With Stairs","pages 9-16",[
   P("ut_c2_arrive","One blink, and she stood at the rim of a pale grey mountain carved into giant steps, winding down and down.","Somebody cut STAIRS into a whole mountain!"),
   P("ut_c2_vera","A woman in a white hard hat waved, a blueprint under her arm. \"I'm Vera, a civil engineer — I build bridges and towers. And every one of them starts with THIS rock.\"","A whole city… from one grey rock?!"),
   P("ut_c2_quarry","Far below, tiny trucks carried pale rock toward a plant with silos taller than trees.","Where are they taking all of it?","To the kitchen, kiddo. The biggest kitchen you've ever seen."),
   NOTE("Charlotte's Secret Notebook","Vera builds bridges for a living, and she grins like she has a secret — just like the other guides did. She says cities start with this pale rock, called LIMESTONE. Okay Vera… show me how! ✨"),
 ]),
 ("c3","CHAPTER 3","The Rock Made of Seashells","pages 17-26",[
   P("ut_c3_shells","Vera held up a chunk of pale rock. Inside it curled a perfect little seashell. \"This mountain,\" she said, \"used to be a SEA.\"","There's a seashell inside the STONE!"),
   P("ut_c3_sea","\"Long, long ago, tiny sea creatures built shells here. When they died, their shells drifted down like slow snow, year after year after year.\"","A snowfall of seashells!"),
   P("ut_c3_rock","\"Millions of years pressed those shells into hard pale rock — limestone. A whole ancient sea, sleeping inside a mountain.\"","So the mountain is made of old sea creatures!",None,"press","#5b7a99"),
   WOW("Here's the first secret! 💡 <b>Limestone is a rock made by life.</b> Countless tiny sea creatures built shells; the shells piled up on the sea floor and were pressed for <b>millions of years</b> into pale stone. The mountain Charlotte is standing on used to be a sea."),
   ("diagram",),
   NOTE("Charlotte's Secret Notebook","Limestone = an ancient sea floor! Tiny creatures made shells, the shells piled up, and time pressed them into pale rock. Answer to question ➋: yes — the grey powder WAS stone once. 🐚"),
 ]),
 ("c4","CHAPTER 4","The Great Roasting","pages 27-36",[
   P("ut_c4_kiln","Vera led her to a steel tube as long as a train, turning slowly, glowing at its mouth. \"This is the kiln — the city's oven.\"","An oven the size of a TRAIN!"),
   P("ut_c4_fire","\"Inside, crushed limestone tumbles through a fire hotter than a volcano's lava. The heat changes the rock deep inside — it becomes something NEW.\"","Hotter than LAVA?!",None,"ROAR","#c8621f"),
   P("ut_c4_powder","\"The roasted pebbles cool, and we grind them into a soft grey flour,\" said Vera. \"THAT is cement.\"","THAT'S what's in my jar!"),
   WOW("Roast limestone in a kiln <b>hotter than lava</b> and the rock changes inside — the old sea-shell stone becomes something new. Grind it fine, and you get <b>cement</b>: a soft grey powder with a trick hidden in it, waiting for one magic ingredient."),
   NOTE("Charlotte's Secret Notebook · SOLVED (part 1)","Limestone is roasted in a giant kiln (hotter than lava!), then ground into soft grey powder — CEMENT. But powder isn't stone yet… what wakes it up? 🔥"),
 ]),
 ("c5","CHAPTER 5","The Magic in the Mix","pages 37-44",[
   P("ut_c5_mix","Vera poured water into the grey powder with sand and pebbles, and stirred. \"Watch closely. Water doesn't make it wet — water wakes it UP.\"","It's turning into grey dough!",None,"slosh","#5b7a99"),
   P("ut_c5_crystal","\"Inside the paste, tiny crystals are GROWING — thousands of little needles reaching out, weaving together, locking the sand and stones in their arms.\"","The crystals are HOLDING HANDS!"),
   WOW("This is the heart of the whole secret! Cement doesn't \"dry\" like a puddle. When water touches it, <b>tiny crystals grow</b> — needle after needle, lacing through the mix and <b>locking everything together</b>. The paste doesn't dry out. It <b>grows solid.</b>"),
   NOTE("Charlotte's Secret Notebook","Water WAKES cement up. Tiny crystals grow like a million holding hands, locking sand and pebbles into one piece. It doesn't dry — it GROWS solid! 💧✨"),
 ]),
 ("c6","CHAPTER 6","Stone You Can Pour","pages 45-52",[
   P("ut_c6_harden","The next day, Vera rapped her knuckles on yesterday's soft grey paste. It rang like rock. \"Man-made stone,\" she said. \"We call it concrete.\"","Yesterday I could STIR this!"),
   P("ut_c6_underwater","\"And here's the strangest part — because the crystals grow by drinking water, concrete hardens even UNDER water.\"","It gets hard… under WATER?!"),
   WOW("Concrete is <b>stone you can pour</b>: soft enough to flow into any shape today, hard as rock tomorrow. And since the crystals <b>drink water to grow</b>, it hardens even underwater — which is how we build dams, sea bridges and harbour walls. No other glue does that."),
   NOTE("Charlotte's Secret Notebook · SOLVED!","The whole chain: ancient sea → limestone → roasted in a kiln → grey powder (cement) → add water → crystals GROW and lock → CONCRETE, man-made stone. It even hardens underwater! 🌊"),
 ]),
 ("c7","CHAPTER 7","The Glue That Holds Cities","pages 53-60",[
   P("ut_c7_city","Vera swept her blueprint across the skyline. Towers, the metro line, the school, the hospital, the flyover — all of it poured stone.","EVERYTHING here is concrete?!"),
   P("ut_c7_everywhere","\"After water,\" said Vera, \"people use more concrete than ANY other thing on Earth. Every growing city is hungry for it.\"","The whole country is built on grey powder!"),
   WOW("This isn't a small thing. Concrete is the <b>most-used building material on Earth</b> — humans use more of it than anything else except water. Every home, school, dam and metro line in a growing India begins as bags of grey powder. Cement really is <b>the glue that holds cities.</b>"),
   NOTE("Charlotte's Secret Notebook","People use more concrete than anything on Earth except water! Homes, schools, dams, metros — a growing country is hungry for grey powder. 🌏🏗️"),
 ]),
 ("c8","CHAPTER 8 · THE BIG DISCOVERY","The Giant That Pours the Stone","pages 61-70",[
   P("ut_c8_reveal","Vera led Charlotte to a viewpoint over the enormous plant, its silos shining against the sky.","Who makes ALL of this grey magic?"),
   P("ut_c8_history","\"In 2004,\" said Vera, \"a great business family gathered mighty cement plants under one new flag — and kept building more, always close to the limestone and close to the cities.\"","One giant, plant by plant!"),
   P("ut_c8_scale","\"It grew and grew — until it became India's biggest cement maker, and one of the biggest in the whole world.\"","The country's BIGGEST pourer of stone!"),
   WOW("A \"company\" can be a giant shared job. <b>UltraTech Cement</b> was born in 2004, gathered plants across the land, and grew into <b>India's largest cement maker</b> — one of the biggest on Earth. Its trick: sit ON the limestone, and stand NEAR the cities that need it."),
   TL([("2004","The UltraTech name is born as great cement plants come together under one flag."),
       ("Over the years","It builds and joins with more plants — always near limestone, always near growing cities."),
       ("Today","It is India's biggest cement maker, one of the largest in the whole world."),
       ("Tomorrow","It works to make cement cleaner — recycled heat, green power, less smoke. 🏗️")]),
   NOTE("Charlotte's Secret Notebook","UltraTech (2004) gathered plants into ONE giant and became India's biggest cement maker. Its plants sit on the limestone AND near the cities. 🏆"),
 ]),
 ("c9","CHAPTER 9","The Castle on the Grey Mountain","pages 71-80",[
   P("ut_c9_castle","Two kind old men appeared with a glow. Warren pointed at a castle standing on pale limestone hills. \"What keeps rivals out, Charlotte?\"","Walls! But what kind?"),
   MOAT([("🪨","Wall One: It Owns the Rock","No limestone, no cement. UltraTech's plants sit on their own limestone — a rival can't make cement out of wishes.",False),
         ("🚚","Wall Two: Heavy Things Hate Travelling","A bag of cement is heavy but cheap, so hauling it far eats all the profit. Plants and depots close to the cities win — and the best spots are already taken.",False),
         ("🏗️","Wall Three: Giant Scale, Trusted Name","The biggest network of plants, trucks and shops, and a name builders trust with their bridges. Decades of work a newcomer can't copy overnight.",False),
         ("⚠️","The Crack in the Wall","Roasting rock hotter than lava gulps energy and puffs out gas that warms the planet. A cement giant must learn to make its fire cleaner, or the world will frown on it.",True)]),
   P("ut_c9_munger","Charlie tapped his head. \"Don't just ask how to WIN. Ask how you'd LOSE — then don't do that. Invert!\"","Think backwards?"),
   WOW("<b>Charlie's Inversion:</b> to keep a cement giant strong, imagine how it could CRUMBLE — building plants far from the cities, letting quality slip so bridges crack, or running dirty kilns while the world demands clean — then carefully avoid each one, and green the fire early."),
   P("ut_c9_verdict","Warren nodded. \"It owns the rock, stands near the cities, and pours at giant scale — a mighty castle, so long as it keeps making its fire cleaner.\"","I SEE the whole picture!"),
   NOTE("Charlotte's Secret Notebook · The Big Secret","UltraTech is hard to copy: it OWNS the limestone, cement is too heavy to ship far (so its spots near cities are gold), and it's GIANT and trusted. But the kilns must get CLEANER. Charlie's trick: picture how you'd lose (far plants, cracked quality, dirty fire), then never do it. Invert! 🏰"),
 ]),
 ("c10","CHAPTER 10","The City That Was Poured","pages 81-88",[
   P("ut_c10_wake","Charlotte woke in her own bed. The great kiln was gone… but the little jar of grey powder on her desk shimmered softly.","Was it real? It FELT real…"),
   P("ut_c10_diary","On the diary's page, a new line glowed — as if Grandpa Ben wrote it just for her.",None,'"Now you see the stone hiding in the powder. Well done."'),
   P("ut_c10_look","She ran outside into the morning. Every building, every bridge, every pavement under her feet — all of it, quietly, was stone that people had poured.","The whole city was POURED — I just couldn't see it!"),
   WOW("Next time you touch a wall, you'll know the secret: it may be an <b>ancient sea</b> — shells pressed into limestone, roasted into grey powder, woken by water into crystals that locked into man-made stone. That's <b>the glue that holds cities.</b> 🐚🏙️"),
   NOTE("Charlotte's Secret Notebook · What I Learned","➊ Limestone is an ancient sea — shells pressed into pale rock for millions of years.<br>➋ Roast it in a kiln hotter than lava, grind it → CEMENT, the grey powder.<br>➌ Water wakes it: tiny crystals GROW and lock → CONCRETE, man-made stone — it even hardens underwater.<br>➍ People use more concrete than anything on Earth except water.<br>➎ UltraTech owns the rock and stands near the cities; but Charlie's trick — picture how you'd lose (dirty fire, far plants), then make the kilns cleaner. 💛"),
 ]),
]

HOOK=("ut_c1_swirl","EVERY ORDINARY THING HIDES A SECRET.",
 "Charlotte found the ancient sea sleeping inside a grey powder. But the compass is twitching again — toward the bright colours drying on her freshly painted wall. What is paint, really, and how does a rainbow learn to stick?",
 "NEXT ADVENTURE · The Rainbow in a Bucket →")

DIAGRAM='''<div class="panel wide" style="background:#eef3f7;">
<svg viewBox="0 0 820 380"><rect width="820" height="380" fill="#eef3f7"/>
<text x="410" y="38" text-anchor="middle" font-family="Bangers" font-size="24" fill="#37627a">CONCRETE IS POURED STONE</text>
<g><circle cx="120" cy="150" r="34" fill="#7fc4e8" stroke="#37627a" stroke-width="4"/><text x="120" y="112" text-anchor="middle" font-family="Baloo 2" font-size="15" fill="#37627a">ANCIENT SEA</text><text x="120" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">shells drift down for ages</text></g>
<g stroke="#5b7a99" stroke-width="5" fill="#5b7a99"><line x1="160" y1="150" x2="300" y2="150" stroke-dasharray="10 8"/><path d="M296 141 L314 150 L296 159Z"/></g>
<g><rect x="320" y="112" width="150" height="90" rx="12" fill="#fff" stroke="#171717" stroke-width="4"/><text x="395" y="102" text-anchor="middle" font-family="Baloo 2" font-size="14" fill="#5b7a99">LIMESTONE</text><text x="395" y="165" text-anchor="middle" font-family="Bangers" font-size="24" fill="#5b7a99">pressed shells</text><text x="395" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">a sea floor turned to rock</text></g>
<g stroke="#c8621f" stroke-width="5" fill="#c8621f"><line x1="480" y1="150" x2="600" y2="150" stroke-dasharray="10 8"/><path d="M596 141 L614 150 L596 159Z"/></g>
<text x="540" y="135" text-anchor="middle" font-family="Baloo 2" font-size="12" fill="#c8621f">roasted in a kiln</text>
<text x="540" y="182" text-anchor="middle" font-family="Nunito" font-size="12" fill="#555">hotter than lava</text>
<g><rect x="620" y="112" width="150" height="90" rx="12" fill="#5b6472" stroke="#171717" stroke-width="4"/><text x="695" y="102" text-anchor="middle" font-family="Baloo 2" font-size="16" fill="#37627a">CEMENT</text><text x="695" y="165" text-anchor="middle" font-family="Bangers" font-size="24" fill="#eef3f7">grey powder</text><text x="695" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">stone ground into flour</text></g>
<rect x="70" y="300" width="680" height="52" rx="9" fill="#fff" stroke="#171717" stroke-width="3"/>
<text x="410" y="322" text-anchor="middle" font-family="Nunito" font-size="14" fill="#123">Add WATER &#8594; tiny crystals GROW and lock together &#8594; CONCRETE, man-made stone that builds cities.</text>
<text x="410" y="343" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">Because the crystals drink water to grow, it hardens even under water.</text>
</svg><div class="figcap">An ancient sea is pressed into limestone, roasted into cement powder, then woken by water into man-made stone.</div></div>'''

try:
    from book_extra import EXTRA, NEW2
    NEW.update(NEW2)
except Exception:
    EXTRA={}

def render_panel(pn,pageno=None):
    _,img,cap,b1,b2,sfx,sfxc,tall=pn
    pg=f'<div class="pageno">{pageno}</div>' if pageno else ''
    p=[f'<div class="panel wide">{pg}<img src="art/{img}.jpg" alt="" loading="lazy">']
    if cap: p.append(f'<div class="cap tl tilt">{cap}</div>')
    if b1: p.append(f'<div class="bubble dl" style="left:12px;bottom:12px;">{b1}</div>')
    if b2: p.append(f'<div class="bubble dr" style="right:12px;top:12px;">{b2}</div>')
    if sfx: p.append(f'<div class="sfx" style="left:40%;top:14px;font-size:32px;color:{sfxc};">{sfx}</div>')
    p.append('</div>'); return "".join(p)

def render_item(it,pageno=None):
    t=it[0]
    if t=="panel": return render_panel(it,pageno)
    if t=="diagram": return DIAGRAM
    if t=="sub": return f'<div class="sub"><span class="dot">{it[1]}</span><b>{it[2]}</b></div>'
    if t=="wow": return f'<div class="wow">{it[1]}</div>'
    if t=="note": return f'<div class="note"><div class="nt">{it[1]}</div><p>{it[2]}</p></div>'
    if t=="timeline":
        rows="".join(f'<div class="tl"><div class="yr">{y}</div><p>{x}</p></div>' for y,x in it[1])
        return f'<div class="timeline">{rows}</div>'
    if t=="moat":
        cards="".join(f'<div class="mc{" bad" if bad else ""}"><h4>{ic} {ti}</h4><p>{tx}</p></div>' for ic,ti,tx,bad in it[1])
        return f'<div class="moat">{cards}</div>'
    return ""

def referenced_images():
    imgs=set()
    for cls,_,_,_,items in CHAPTERS:
        for it in items:
            if it[0]=="panel": imgs.add(it[1])
        for it in EXTRA.get(cls,[]):
            if it[0]=="panel": imgs.add(it[1])
    imgs.add(HOOK[0]); imgs.add("00_cover"); imgs.add("_ref_vera"); return imgs

def build():
    body=[]; pageno=0
    for cls,num,title,pglabel,items in CHAPTERS:
        items=list(items); extra=EXTRA.get(cls,[])
        if extra:
            idx=[i for i,it in enumerate(items) if it[0]=="panel"]
            at=(idx[-1]+1) if idx else len(items)
            for ex in reversed(extra): items.insert(at,ex)
        start=pageno+1
        inner=[f'<div class="chapbar {cls}"><div class="n">{num}</div><h2>{title}</h2></div>']
        for it in items:
            if it[0]=="panel": pageno+=1; inner.append(render_item(it,pageno))
            else: inner.append(render_item(it))
        lbl=f"pages {start}-{pageno}" if pageno>=start else pglabel
        body.append(f'<div class="sheet" data-pg="{lbl}">{"".join(inner)}</div>')
    hook=f'''<div class="sheet" data-pg="the end… for now"><div class="hook"><img src="art/{HOOK[0]}.jpg" alt="">
<div class="hc"><h3>{HOOK[1]}</h3><p>{HOOK[2]}</p><div class="b2">{HOOK[3]}</div></div></div></div>'''
    head=open("/root/omahaindia.com/comics/site/book/ultratech/_head.html").read()
    tail=open("/root/omahaindia.com/comics/site/book/ultratech/_tail.html").read()
    open(OUT,"w").write(head+"".join(body)+hook+tail)
    print("built",OUT,"| chapters:",len(CHAPTERS),"| images:",len(referenced_images()))

if __name__=="__main__":
    build()
