#!/usr/bin/env python3
# Book 17 (Mahindra & Mahindra) — THE BEAST THAT PLOUGHS THE FIELD. Science->business: the secret is
# TORQUE, the twisting PULL of an engine (fuel burns in cylinders -> pushes pistons up and down ->
# spins a crankshaft -> gears MULTIPLY the twist into strong low-speed PULL -> turns big wheels slowly
# but mightily to drag a plough or climb a hill) -> the maker of tractors that give farmers this mighty
# pull, and tough SUVs, a world leader in tractors by number.
import os
ART="/root/omahaindia.com/comics/site/book/mm/art"
OUT="/root/omahaindia.com/comics/site/book/mm/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"
MAX=("Max, a warm friendly Western TRACTOR and AUTO ENGINEER, NOT Indian, sturdy build, cheerful oil-smudged grin, "
"blue denim overalls, a bright red cap, a shiny wrench in one hand")

# name -> (w,h,seed,prompt,ref). ref set -> Seedream character; None -> flux scene. Ritual panels copied by mkbook.
NEW={
 "00_cover":(1024,1180,1700,f"{STYLE}. BOOK COVER, {CHARLOTTE} standing with {MAX} beside a mighty red farm tractor at the edge of a golden field, she rests a hand on its huge rear wheel as it drags a plough through rich brown soil, a rough green hill and warm sunrise behind, wonder, cinematic","charlotte"),
 "_ref_max":(1024,1024,1701,f"{STYLE}. clean friendly character portrait, {MAX}, plain soft warm background, kind smile, head and shoulders",None),
 # Ch1
 "mm_c1_coin":(1024,720,1710,f"{STYLE}. {CHARLOTTE} at home, Grandpa Ben's glowing brass compass twitching between a shiny toy race car and a chunky toy tractor on the table, EXPRESSION puzzled and intrigued, cozy lamp light","charlotte"),
 "mm_c1_diary":(1024,720,1711,f"{STYLE}. an open magical diary glowing warm gold on a desk, a faint spinning wheel of light and little turning gears rising from the page, no people",None),
 "mm_c1_swirl":(1024,720,1712,f"{STYLE}. {CHARLOTTE} pulled into a swirling spiral of golden light and spinning gears from a glowing diary, EXPRESSION thrilled, magical","charlotte"),
 # Ch2 — arrive at the farm workshop, meet Max
 "mm_c2_arrive":(1024,720,1713,f"{STYLE}. {CHARLOTTE} landing wide-eyed in a sunny farm workshop full of tractors and shiny engine parts, a huge red tractor towering beside her, EXPRESSION awe and delight, bright daylight","charlotte"),
 "mm_c2_max":(1024,720,1714,f"{STYLE}. {MAX} warmly welcoming {CHARLOTTE} in the workshop, tipping his red cap, EXPRESSION Charlotte shy happy smile; keep the SAME engineer from the reference, same denim overalls, same red cap, same wrench","max"),
 "mm_c2_pit":(1024,720,1715,f"{STYLE}. the inside of a bright tractor workshop, a giant red tractor up on a ramp with its engine open, tools and gleaming gears all around, powerful and inviting, no faces close up",None),
 # Ch3 — fuel burns in the cylinders: tiny controlled explosions that PUSH
 "mm_c3_spark":(1024,720,1716,f"{STYLE}. {MAX} kneeling to show {CHARLOTTE} a single shiny metal cylinder with a bright spark inside lighting a puff of fuel, a tiny warm flame flash, EXPRESSION Charlotte fascinated leaning in; SAME engineer, denim overalls, red cap","max"),
 "mm_c3_fire":(1024,720,1717,f"{STYLE}. a magical cutaway of one engine cylinder, a tiny bright orange explosion of burning fuel flashing inside a shiny metal tube, sparks and warm light, playful science, no people",None),
 "mm_c3_push":(1024,720,1718,f"{STYLE}. a friendly close up of a metal piston being shoved firmly downward inside its cylinder by a burst of orange flame above it, bold arrows of pushing force, warm glow, no people",None),
 # Ch4 — pistons pump up and down -> spin a crankshaft
 "mm_c4_pump":(1024,720,1719,f"{STYLE}. {CHARLOTTE} watching in wonder as several shiny pistons pump up and down in a blur inside an open engine, EXPRESSION amazed and thoughtful, bright workshop light","charlotte"),
 "mm_c4_crank":(1024,720,1720,f"{STYLE}. a magical cutaway of an engine, straight up-and-down pushes of the pistons turning a bent metal crankshaft into a smooth round SPIN, curved arrows showing push becoming turn, warm metallic glow, no people",None),
 "mm_c4_spin":(1024,720,1721,f"{STYLE}. a beautiful close up of a polished crankshaft spinning round and round in a blur of motion, motion lines, gleaming steel, no people",None),
 # Ch5 — gears multiply the twist: trade speed for strength -> TORQUE
 "mm_c5_gears":(1024,720,1722,f"{STYLE}. {MAX} showing {CHARLOTTE} a small fast gear turning a big slow gear, the big one turning strong and mighty, EXPRESSION Charlotte delighted 'aha'; SAME engineer, denim overalls, red cap","max"),
 "mm_c5_bike":(1024,720,1723,f"{STYLE}. a cheerful child on a bicycle in its lowest gear pedalling fast to climb a steep grassy hill strongly and slowly, playful science, bright day, side view, no faces close up",None),
 # Ch6 — that twisting pull turns big wheels slowly but mightily
 "mm_c6_wheel":(1024,720,1724,f"{STYLE}. {CHARLOTTE} watching a giant deep-treaded tractor wheel turn slowly and powerfully, gripping the earth, her ponytails lifting, EXPRESSION awed and excited, bright field","charlotte"),
 "mm_c6_grip":(1024,720,1725,f"{STYLE}. a dramatic low close up of a huge knobbly tractor tyre biting into brown soil and pushing forward with unstoppable strength, flying clods of earth, no people",None),
 # Ch7 — the mighty pull at work: drag the plough, climb the hill, for farmers
 "mm_c7_plough":(1024,720,1726,f"{STYLE}. a mighty red tractor dragging a heavy plough through a big field, curling waves of rich brown soil turning over behind it, a happy farmer in the distance, golden light, no faces close up",None),
 "mm_c7_hill":(1024,720,1727,f"{STYLE}. a tough boxy SUV climbing a rough rocky green hill with ease, mud and rocks under its strong tyres, adventurous and grand, wide landscape, no faces close up",None),
 # Ch8 — reveal Mahindra
 "mm_c8_reveal":(1024,720,1728,f"{STYLE}. {CHARLOTTE} and {MAX} standing proudly before a big modern factory with rows of red tractors and tough SUVs gleaming under a blue sky, EXPRESSION proud recognition; SAME engineer, denim overalls, red cap","charlotte"),
 "mm_c8_1945":(1024,720,1729,f"{STYLE}. warm sepia 1940s scene, a hopeful new company beginning in India, workers and old machines assembling the very first sturdy vehicles in a small workshop, inspiring, no text",None),
 "mm_c8_scale":(1024,720,1730,f"{STYLE}. a proud modern assembly line at golden hour, a long row of bright red tractors rolling out one after another, the biggest tractor maker in the world by number, grand and busy, no people",None),
 # Ch10 (ch9 uses ritual castle/invert/verdict; ch10 uses ritual wake/diary)
 "mm_c10_look":(1024,720,1731,f"{STYLE}. {CHARLOTTE} outside at golden hour watching a tractor plough a nearby field and a sturdy vehicle roll down the road, knowing each one holds the secret twisting pull, EXPRESSION delighted wonder","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 Twitching Compass","pages 1-8",[
   P("mm_c1_coin","Back home, Grandpa Ben's compass twitched again — pointing between a fast little race car and a chunky, slow-looking tractor.","A speedy car… and a slow tractor? What's the link?",None,"twitch"),
   P("mm_c1_diary","The old diary fell open. A new line shimmered in Grandpa Ben's hand.",None,'"Find the mighty PULL hidden inside a spinning engine."'),
   WOW("A little tractor chugs along slower than a race car — yet it can drag a heavy plough through hard soil and haul loads a race car never could. Where does all that strength come from? That's the puzzle of this whole adventure."),
   P("mm_c1_swirl","Golden light and spinning gears swirled up and pulled Charlotte in.","Here we GO!",None,"WHOOSH","#e31837"),
   NOTE("Charlotte's Secret Notebook","Two BIG questions:<br>➊ How can a slow tractor be so much STRONGER than a fast car?<br>➋ Grandpa Ben says there is a mighty <i>pull</i> hidden inside a spinning engine. What IS that pull? ⚙️"),
 ]),
 ("c2","CHAPTER 2","The Workshop Full of Giants","pages 9-16",[
   P("mm_c2_arrive","One blink, and she stood in a sunny workshop crowded with tractors taller than she was, their engines gleaming.","These machines are ENORMOUS!"),
   P("mm_c2_max","A cheerful man in a red cap waved. \"I'm Max, an engine engineer. In here we build a very mighty kind of PULL.\"","A mighty… PULL?!"),
   P("mm_c2_pit","A giant red tractor sat up on a ramp, its engine wide open, gears and pistons winking in the light.","So much machine — and it hides a secret PULL?","Stick with me, kiddo."),
   NOTE("Charlotte's Secret Notebook","Max is an engine engineer, and he grins like he has a secret — just like the other guides did. He calls it a 'mighty pull'. Okay Max… show me how! ✨"),
 ]),
 ("c3","CHAPTER 3","The Tiny Fires Inside","pages 17-26",[
   P("mm_c3_spark","Max opened a shiny metal tube. \"This is a cylinder. We squirt in a little fuel, add a spark — and POP! A tiny fire flashes inside.\"","A little explosion — INSIDE the engine!"),
   P("mm_c3_fire","\"Each tiny fire happens hundreds of times a minute,\" said Max, \"one flash after another, over and over.\"","So many little fires!",None,"POP","#e31837"),
   P("mm_c3_push","\"And every fire does ONE simple job: it shoves a metal piston down — HARD.\"","The fire PUSHES the metal down!",None,"shove","#2b2b2b"),
   WOW("Here's the first secret! 💡 Inside an engine are metal tubes called <b>cylinders</b>. In each one, a bit of fuel burns in a tiny controlled <b>explosion</b>, hundreds of times a minute. Every little fire does one thing: it <b>pushes a piston</b> down with a strong shove."),
   ("diagram",),
   NOTE("Charlotte's Secret Notebook","Fuel burns in little tubes called cylinders. Each tiny fire PUSHES a metal piston down hard — hundreds of pushes every minute. The engine's power starts as lots of tiny fires. 🔥"),
 ]),
 ("c4","CHAPTER 4","From Push to Spin","pages 27-36",[
   P("mm_c4_pump","\"Watch the pistons,\" said Max. Up, down, up, down — they pumped in a blur.","Up and down, up and down — so fast!"),
   P("mm_c4_crank","\"But wheels don't go up and down — they SPIN,\" said Max. \"So a clever bent bar called a crankshaft turns every up-and-down push into a smooth round spin.\"","It turns pushing into SPINNING!",None,"turn","#e31837"),
   P("mm_c4_spin","And there it was — the crankshaft whirling round and round, faster than she could follow.","The straight pushes became a circle!"),
   WOW("The pistons only go <b>up and down</b>. But a bent bar — the <b>crankshaft</b> — catches every push and swings it around into a smooth <b>spin</b>, just like your legs pushing pedals up and down to spin a bicycle wheel. Push becomes turn."),
   NOTE("Charlotte's Secret Notebook · SOLVED (part 1)","Tiny fires push pistons up and down. A bent bar called the CRANKSHAFT turns all that up-and-down pushing into a round SPIN — the same way pedalling spins a bike wheel. ⚙️"),
 ]),
 ("c5","CHAPTER 5","The Trick of the Gears","pages 37-44",[
   P("mm_c5_gears","Max spun a tiny fast gear against a big one. The big gear turned slowly — but oh, so STRONG. \"Gears trade speed for strength,\" he said.","Slower… but MIGHTIER!"),
   P("mm_c5_bike","\"It's just like your bike,\" he grinned. \"Drop into a low gear on a hill: you pedal fast, but you climb strong and slow. That twisting strength has a name — TORQUE.\"","Torque! The twisting PULL!",None,"climb","#2b2b2b"),
   WOW("Here's the big secret — <b>TORQUE</b>! 💪 Gears can <b>trade speed for strength</b>. A small fast gear turns a big gear slowly but with huge twisting PULL — just like a low gear on your bike helps you climb a steep hill. That mighty twist is <b>torque</b>."),
   NOTE("Charlotte's Secret Notebook · SOLVED!","GEARS trade speed for strength. A fast spin becomes a slow, super-strong TWIST called TORQUE. Low gear on a bike = pedal fast, climb strong. That's the mighty pull! 🚲"),
 ]),
 ("c6","CHAPTER 6","The Mighty Wheel","pages 45-52",[
   P("mm_c6_wheel","The torque flowed to a giant tractor wheel. It turned slowly — but nothing on earth seemed able to stop it.","It turns SLOW but so, so strong!"),
   P("mm_c6_grip","\"That twisting pull turns the big wheels,\" said Max, \"slowly but mightily — enough to drag a heavy plough or climb a rocky hill.\"","So THAT'S where the strength goes!"),
   WOW("All that torque flows to the <b>big wheels</b> and turns them <b>slowly but mightily</b>. A race car spins its wheels fast; a tractor turns them slow and STRONG — strong enough to drag a plough through hard soil or crawl up a rough hill. Fire → push → spin → gears → TORQUE → mighty wheels!"),
   NOTE("Charlotte's Secret Notebook","The torque turns the big wheels slowly but mightily. The whole chain: FIRE → push a piston → spin the crankshaft → GEARS → torque → strong wheels that pull! 💥"),
 ]),
 ("c7","CHAPTER 7","The Beast That Ploughs","pages 53-60",[
   P("mm_c7_plough","Max swept his arm across the field. A red tractor dragged a plough, curling up waves of rich brown earth.","It's turning the whole field over!"),
   P("mm_c7_hill","\"And the same mighty pull,\" said Max, \"lets a tough SUV climb rocky hills that would stop an ordinary car.\"","The same twisting power — for hills too!"),
   WOW("This is what torque is FOR. A tractor's mighty pull <b>drags a heavy plough</b> so a farmer can plant a whole field, and haul loads across the land. That same twisting strength lets a <b>tough SUV</b> climb rough, rocky hills. Slow and strong beats fast and weak — when there's real work to do."),
   NOTE("Charlotte's Secret Notebook","Torque is for WORK. It lets a tractor drag a plough and turn a whole field, and lets a tough SUV climb rocky hills. Slow-and-strong wins when the job is hard. 🚜"),
 ]),
 ("c8","CHAPTER 8 · THE BIG DISCOVERY","The Maker of the Mighty Pull","pages 61-70",[
   P("mm_c8_reveal","Max led Charlotte to a viewpoint over a great factory, rows of red tractors and tough SUVs gleaming below.","Who BUILDS all of these?"),
   P("mm_c8_1945","\"Long ago, in 1945,\" said Max, \"a bold new company began right here in India, building sturdy machines for a whole young country.\"","A company as old as that!"),
   P("mm_c8_scale","\"It grew and grew — until it made more tractors than anyone else on Earth, and tough SUVs too.\"","The world's BIGGEST tractor maker!"),
   WOW("A \"company\" can be a giant shared workshop. <b>Mahindra &amp; Mahindra</b> began in 1945 and grew into the <b>world's largest maker of tractors by number</b> — plus tough, go-anywhere SUVs — giving farmers everywhere the mighty pull to work their fields."),
   TL([("1945","A bold new company begins in India, building sturdy machines."),
       ("Over decades","It grows into the world's biggest tractor maker by number."),
       ("Today","Its tractors give farmers a mighty pull; its tough SUVs climb any road."),
       ("Tomorrow","It keeps inventing — smarter, cleaner engines and new electric power. ⚡")]),
   NOTE("Charlotte's Secret Notebook","Mahindra & Mahindra (1945) grew into the world's biggest tractor maker by number, and makes tough SUVs too. It builds the mighty PULL that helps farmers work the land. 🏆"),
 ]),
 ("c9","CHAPTER 9","The Castle in the Fields","pages 71-80",[
   P("mm_c9_castle","Two kind old men appeared with a glow. Warren pointed at a castle standing in golden farm fields. \"What keeps rivals out, Charlotte?\"","Walls! But what kind?"),
   MOAT([("🤝","Wall One: The Farmers' Trust","For decades farmers have trusted these tractors to never let them down at harvest. Trust like that is earned slowly — and very hard for a rival to copy.",False),
         ("🛠️","Wall Two: The Village Network","A vast web of dealers and repair shops reaches deep into the villages, so help and spare parts are always near. Building that everywhere takes many years.",False),
         ("⚙️","Wall Three: Decades of Know-How","Learning to build engines that pull hard and last for years takes long practice. That deep engineering skill can't be bought overnight.",False),
         ("⚠️","The Crack in the Wall","Many rivals want the very same fields and buyers. The company must keep inventing and keep earning trust, or a hungrier maker could pull ahead.",True)]),
   P("mm_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 tractor giant strong, imagine how it could FADE — building weaker engines, letting a rival serve farmers better, or forgetting the villages — then carefully avoid each one, and keep earning the farmers' trust every single season."),
   P("mm_c9_verdict","Warren nodded. \"Trusted by farmers, close to every village, and rich with know-how — a mighty castle, so long as it keeps inventing and never takes that trust for granted.\"","I SEE the whole picture!"),
   NOTE("Charlotte's Secret Notebook · The Big Secret","Mahindra is hard to copy: farmers TRUST it, its help reaches every VILLAGE, and it has decades of KNOW-HOW. But rivals want the same fields, so it must keep INVENTING. Charlie's trick: picture how you'd lose, then never do it. Invert! 🏰"),
 ]),
 ("c10","CHAPTER 10","The Pull Beneath the Fields","pages 81-88",[
   P("mm_c10_wake","Charlotte woke in her own bed. The workshop was gone… but the little toy tractor on her desk seemed to hum with hidden strength.","Was it real? It FELT real…"),
   P("mm_c10_diary","On the diary's page, a new line glowed — as if Grandpa Ben wrote it just for her.",None,'"Now you know the mighty pull that turns the wheels. Well done."'),
   P("mm_c10_look","She ran outside. A tractor ploughed a nearby field and a sturdy vehicle rolled by — and now she knew the twisting secret inside each one.","It was TORQUE the whole time — I just couldn't see it!"),
   WOW("Next time a tractor turns the soil, you'll know the secret: it's <b>torque</b>, the mighty twisting PULL. Tiny fires push pistons, a crankshaft spins them, gears trade speed for strength, and big wheels heave the plough through the earth. That's <b>the beast that ploughs the field.</b> 🚜⚙️"),
   NOTE("Charlotte's Secret Notebook · What I Learned","➊ Fuel burns in cylinders — tiny fires PUSH the pistons.<br>➋ A crankshaft turns that up-and-down push into a SPIN.<br>➌ GEARS trade speed for strength — a slow, mighty twist called TORQUE.<br>➍ That torque turns big wheels to drag a plough and climb hills.<br>➎ Mahindra builds the world's most tractors; its moat is farmers' trust, a village-deep network, and know-how — but Charlie's trick says keep inventing so rivals can't pull ahead. Invert! 💛"),
 ]),
]

HOOK=("mm_c1_swirl","EVERY ORDINARY THING HIDES A SECRET.",
 "Charlotte found the mighty pull twisting inside an engine. But the compass is twitching again — this time toward the tiny glowing screen in her hand that somehow knows everything. What is really happening inside it, and who taught the sand to think?",
 "NEXT ADVENTURE · The Sand That Learned to Think →")

DIAGRAM='''<div class="panel wide" style="background:#fbf3ec;">
<svg viewBox="0 0 820 380"><rect width="820" height="380" fill="#fbf3ec"/>
<text x="410" y="38" text-anchor="middle" font-family="Bangers" font-size="24" fill="#e31837">GEARS TURN SPEED INTO STRENGTH</text>
<g><circle cx="120" cy="150" r="34" fill="#f6941d" stroke="#e31837" stroke-width="4"/><text x="120" y="112" text-anchor="middle" font-family="Baloo 2" font-size="15" fill="#e31837">TINY FIRE</text><text x="120" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">fuel burns in a cylinder</text></g>
<g stroke="#2b2b2b" stroke-width="5" fill="#2b2b2b"><line x1="160" y1="150" x2="300" y2="150" stroke-dasharray="10 8"/><path d="M296 141 L314 150 L296 159Z"/></g>
<text x="230" y="135" text-anchor="middle" font-family="Baloo 2" font-size="12" fill="#2b2b2b">pushes down</text>
<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="#2b2b2b">CRANKSHAFT</text><text x="395" y="165" text-anchor="middle" font-family="Bangers" font-size="24" fill="#2b2b2b">it SPINS</text><text x="395" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">push becomes turn</text></g>
<g stroke="#6b7280" stroke-width="5" fill="#6b7280"><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="#6b7280">gears trade</text>
<text x="540" y="182" text-anchor="middle" font-family="Nunito" font-size="12" fill="#555">speed for strength</text>
<g><rect x="620" y="112" width="150" height="90" rx="12" fill="#e31837" stroke="#171717" stroke-width="4"/><text x="695" y="102" text-anchor="middle" font-family="Baloo 2" font-size="16" fill="#2b2b2b">TORQUE</text><text x="695" y="165" text-anchor="middle" font-family="Bangers" font-size="22" fill="#f6941d">mighty pull</text><text x="695" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">strong slow twisting force</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">Fire pushes a piston &#8594; the crankshaft SPINS &#8594; gears trade speed for STRENGTH &#8594; TORQUE turns the big wheels.</text>
<text x="410" y="343" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">Slow and strong beats fast and weak &#8212; enough to drag a heavy plough through the soil.</text>
</svg><div class="figcap">Tiny fires push the pistons, the crankshaft spins, gears trade speed for strength, and torque turns the mighty wheels.</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_max"); 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/mm/_head.html").read()
    tail=open("/root/omahaindia.com/comics/site/book/mm/_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()
