#!/usr/bin/env python3
# Book 44 (Grasim Industries) — THE THREAD AND THE STONE. Science->business: a TREE becomes CLOTH
# (wood mashed to pulp -> dissolved into a golden syrup -> squeezed through a shower head of tiny holes
# into a bath where it hardens into long silky threads -> woven into cloth) — a man-made fibre from a
# natural thing; and the SAME company also bakes ROCK into CEMENT (stone). Two branches from one trunk.
import os
ART="/root/omahaindia.com/comics/site/book/grasim/art"
OUT="/root/omahaindia.com/comics/site/book/grasim/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"
TILDA=("Tilda, a warm friendly Western TEXTILE MAKER, NOT Indian, greying hair in a long braid, patient creative smile, "
"an indigo apron over a linen shirt, a spool of silky thread 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,1600,f"{STYLE}. BOOK COVER, {CHARLOTTE} standing with {TILDA} outside a bright thread workshop beside a green wood, holding up a shimmering silky white thread in one hand and a smooth grey stone in the other, a soft cloth and a strong wall on the horizon, wonder, cinematic","charlotte"),
 "_ref_tilda":(1024,1024,1601,f"{STYLE}. clean friendly character portrait, {TILDA}, plain soft warm background, kind smile, head and shoulders",None),
 # Ch1
 "gr_c1_coin":(1024,720,1610,f"{STYLE}. {CHARLOTTE} at home, Grandpa Ben's glowing brass compass twitching between a soft silky white thread and a hard grey stone on the table, EXPRESSION puzzled and intrigued, cozy lamp light","charlotte"),
 "gr_c1_diary":(1024,720,1611,f"{STYLE}. an open magical diary glowing warm gold on a desk, a faint ribbon of light rising from the page and splitting into a silky thread and a tiny grey stone, no people",None),
 "gr_c1_swirl":(1024,720,1612,f"{STYLE}. {CHARLOTTE} pulled into a swirling spiral of golden light and drifting threads and stone dust from a glowing diary, EXPRESSION thrilled, magical","charlotte"),
 # Ch2 — arrive at the workshop, meet Tilda
 "gr_c2_arrive":(1024,720,1613,f"{STYLE}. {CHARLOTTE} landing wide-eyed outside a bright busy thread workshop beside a green woodland, humming machines through the windows, EXPRESSION awe and delight, bright daylight","charlotte"),
 "gr_c2_tilda":(1024,720,1614,f"{STYLE}. {TILDA} warmly welcoming {CHARLOTTE} at the workshop door, holding out a shining spool of thread, EXPRESSION Charlotte shy happy smile; keep the SAME textile maker from the reference, same indigo apron, same linen shirt, same spool of silky thread","tilda"),
 "gr_c2_pit":(1024,720,1615,f"{STYLE}. the inside of a vast bright thread-spinning mill, endless rows of machines winding shimmering white threads by the mile, soft glow, no faces close up",None),
 # Ch3 — the tree and the wood pulp
 "gr_c3_leaf":(1024,720,1616,f"{STYLE}. {TILDA} kneeling to show {CHARLOTTE} a small wooden block in one hand and a puff of soft white fluff in the other, EXPRESSION Charlotte fascinated leaning in; SAME textile maker, indigo apron, linen shirt","tilda"),
 "gr_c3_forest":(1024,720,1617,f"{STYLE}. a peaceful managed woodland of tall straight fast-growing trees in warm golden light, neat and healthy, planted for cloth, no people",None),
 "gr_c3_store":(1024,720,1618,f"{STYLE}. a friendly close up of a log being mashed and softened into wet grey wood pulp like thick porridge in a tub, playful science, no people",None),
 # Ch4 — dissolving the pulp into a golden syrup
 "gr_c4_sink":(1024,720,1619,f"{STYLE}. {CHARLOTTE} watching in wonder as soft wet wood pulp is stirred into a great vat and dissolves into a thick honey-gold liquid, EXPRESSION amazed and thoughtful, warm workshop light","charlotte"),
 "gr_c4_press":(1024,720,1620,f"{STYLE}. a magical cutaway of a big mixing vat where soft wood pulp melts and swirls into a glowing golden syrup, gentle swirls of gold, no people",None),
 "gr_c4_rock":(1024,720,1621,f"{STYLE}. a beautiful close up of thick glossy golden viscose syrup dripping slowly off a spoon, honey-like and shining, no people",None),
 # Ch5 — squeezed through tiny holes into a bath, hardens into silky thread
 "gr_c5_burn":(1024,720,1622,f"{STYLE}. thick golden syrup being pushed through a shiny metal cap dotted with hundreds of tiny holes like a little shower head, dozens of hair-thin golden streams jetting out, no people",None),
 "gr_c5_boil":(1024,720,1623,f"{STYLE}. {TILDA} showing {CHARLOTTE} how the thin golden streams plunge into a clear liquid bath and instantly harden into long silky white threads being lifted out, EXPRESSION Charlotte delighted 'aha'; SAME textile maker, indigo apron, linen shirt","tilda"),
 # Ch6 — threads twisted and woven into cloth
 "gr_c6_spin":(1024,720,1624,f"{STYLE}. {CHARLOTTE} watching hundreds of silky threads twist together and wind onto a fast spinning spool in a soft shimmering blur, her ponytails lifting, EXPRESSION awed and excited, bright hall","charlotte"),
 "gr_c6_electric":(1024,720,1625,f"{STYLE}. soft finished cloth flowing off a loom in gentle waves, a shirt and a flowing scarf made from it, warm and inviting, no people",None),
 # Ch7 — the other branch: rock into cement (stone)
 "gr_c7_everyone":(1024,720,1626,f"{STYLE}. a big cement works — hard grey rock crushed, a tall kiln baking it, mountains of soft grey cement powder pouring into trucks, powerful and grand, no faces close up",None),
 "gr_c7_half":(1024,720,1627,f"{STYLE}. a warm storybook scene of grey cement powder mixed with water and sand and setting into a strong wall and a new house, showing powder becoming solid stone, no people",None),
 # Ch8 — reveal Grasim
 "gr_c8_reveal":(1024,720,1628,f"{STYLE}. {CHARLOTTE} and {TILDA} standing proudly before a great factory with two wings — a thread mill on one side and a cement plant on the other — glowing against a blue sky, EXPRESSION proud recognition; SAME textile maker, indigo apron, linen shirt","charlotte"),
 "gr_c8_1975":(1024,720,1629,f"{STYLE}. warm sepia 1940s scene, the first man-made-thread mill starting up, spools and looms and hopeful workers and old machines, inspiring, no text",None),
 "gr_c8_scale":(1024,720,1630,f"{STYLE}. a mighty modern factory at golden hour, a colossal thread mill on one side and an enormous cement plant with a tall kiln on the other, one of the world's biggest fibre makers, proud and grand, no people",None),
 # Ch10 (ch9 uses ritual castle/invert/verdict; ch10 uses ritual wake/diary)
 "gr_c10_look":(1024,720,1631,f"{STYLE}. {CHARLOTTE} outside at dusk looking with wonder at her own soft shirt and a nearby strong brick wall, knowing one came from a tree and one from a stone, 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 Soft and the Hard","pages 1-8",[
   P("gr_c1_coin","Back home, Grandpa Ben's compass twitched again — pointing between a soft silky thread and a hard grey stone.","A thread… and a stone? What's the link?",None,"twitch"),
   P("gr_c1_diary","The old diary fell open. A new line shimmered in Grandpa Ben's hand.",None,'"Find the tree that learned to become cloth — and the rock that learned to become a wall."'),
   WOW("A soft thread and a hard stone seem like total opposites — one you'd wear, one you'd build with. Yet somewhere, ONE company makes both. How can a tree turn into cloth? And how can a rock turn into a wall? That's the double puzzle of this whole adventure."),
   P("gr_c1_swirl","Golden light swirled up and pulled Charlotte in.","Here we GO!",None,"WHOOSH","#c8621f"),
   NOTE("Charlotte's Secret Notebook","Two BIG questions:<br>➊ How can a soft thread and a hard stone come from the SAME place?<br>➋ Grandpa Ben says a <i>tree</i> becomes cloth. How does a tree turn into thread? 🧵"),
 ]),
 ("c2","CHAPTER 2","The Workshop by the Woods","pages 9-16",[
   P("gr_c2_arrive","One blink, and she stood outside a bright, busy workshop beside a green wood, humming with machines.","A whole factory — right by the trees!"),
   P("gr_c2_tilda","A friendly woman in an indigo apron waved. \"I'm Tilda, a thread-maker. Here we teach a tree how to become cloth.\"","A tree… into CLOTH?!"),
   P("gr_c2_pit","Inside, machines wound shimmering white threads by the mile, softer than moonlight.","So much thread — and it started as a TREE?","Stick with me, little one."),
   NOTE("Charlotte's Secret Notebook","Tilda is a thread-maker, and she smiles like she has a lovely secret — just like the other guides did. She says a tree can become cloth. Okay Tilda… show me how! ✨"),
 ]),
 ("c3","CHAPTER 3","The Tree in the Workshop","pages 17-26",[
   P("gr_c3_leaf","Tilda held up a wooden block, and beside it a puff of soft white fluff. \"Believe it or not — this fluff began as this wood.\"","Hard wood turns into soft fluff?"),
   P("gr_c3_forest","\"It starts with trees — tall, fast-growing trees, planted and grown just for this.\"","A whole forest, grown to become cloth!"),
   P("gr_c3_store","\"First we mash the wood into soft, wet wood pulp — like grey porridge. That's the beginning of every thread.\"","The hard wood goes all soft and mushy!",None,"squish","#c8621f"),
   WOW("Here's the first secret! 🌳 The soft, silky thread starts as ordinary <b>wood</b>. Fast-growing trees are grown just for this. The wood is mashed into soft, wet <b>wood pulp</b> — a bit like the mush that paper is made from. A tree is about to go on an amazing journey."),
   ("diagram",),
   NOTE("Charlotte's Secret Notebook","Silky thread begins as WOOD from fast-growing trees. The wood is mashed into soft wet wood pulp — like grey porridge. That mush is the start of every thread. 🌳"),
 ]),
 ("c4","CHAPTER 4","Into a Golden Soup","pages 27-36",[
   P("gr_c4_sink","\"Now the clever part,\" said Tilda. \"We stir the pulp until it dissolves — the wood melts into a thick golden syrup.\"","The wood turned into a LIQUID!"),
   P("gr_c4_press","\"It looks like honey now,\" she said, \"but it's really a whole tree, turned runny and gold.\"","A tree you could pour from a jug!",None,"swirl","#c8621f"),
   P("gr_c4_rock","\"This golden syrup is the special ink we'll write our threads with,\" she smiled.","So gloopy and shiny!"),
   WOW("A tree that you can POUR? 🍯 The wet wood pulp is dissolved into a thick, glossy <b>golden syrup</b>. The hard tree has become a runny liquid — still all the same tree-stuff, just softened and gooey, ready to be shaped into thread."),
   NOTE("Charlotte's Secret Notebook","The wet wood pulp is dissolved into a thick GOLDEN SYRUP — like honey. The hard tree is now a runny liquid, ready to be turned into thread. 🍯"),
 ]),
 ("c5","CHAPTER 5","Through a Thousand Tiny Holes","pages 37-44",[
   P("gr_c5_burn","\"Watch closely.\" Tilda pushed the golden syrup through a shiny cap dotted with hundreds of tiny holes — like a little shower head.","It's squeezing out in thin streams!",None,"shhh","#4b53b8"),
   P("gr_c5_boil","\"The streams dive into a special bath — and the moment they touch it, they harden into long, silky threads!\"","The liquid turned back into SOLID string!"),
   WOW("Here's the big trick! 🚿 The golden syrup is pushed through a <b>shower head of tiny holes</b> into a special <b>bath</b>. The instant each thin stream touches the bath, it <b>hardens into a long silky thread</b>. A liquid tree comes out as solid string — a <b>man-made fibre from a natural thing.</b>"),
   NOTE("Charlotte's Secret Notebook · SOLVED (part 1)","Push the golden syrup through a shower-head of tiny holes into a special bath. Each stream instantly HARDENS into a long silky thread. A tree became thread! 🚿🧵"),
 ]),
 ("c6","CHAPTER 6","From Thread to Cloth","pages 45-52",[
   P("gr_c6_spin","Hundreds of the new threads twisted together and wound onto spinning spools in a soft, shimmering blur.","So many threads, all at once!"),
   P("gr_c6_electric","\"Then we weave the threads into cloth,\" said Tilda, \"and a tree finally becomes a shirt, a dress, a scarf.\"","The tree turned into something I can WEAR!"),
   WOW("Twist the silky threads together into yarn, then <b>weave the yarn into cloth</b> — and a tree becomes a soft shirt or a flowing dress. Wood → pulp → golden syrup → tiny holes → thread → cloth. A man-made fibre from a natural thing. What a journey!"),
   NOTE("Charlotte's Secret Notebook · SOLVED!","Threads are twisted into yarn and woven into cloth. The whole chain: WOOD → pulp → golden syrup → shower-head → thread → CLOTH! 🧵👗"),
 ]),
 ("c7","CHAPTER 7","The Other Branch: Stone","pages 53-60",[
   P("gr_c7_everyone","Tilda walked her across the yard. \"Now — the SAME company has a second branch. Come see something completely different.\"","Not thread this time?"),
   P("gr_c7_half","\"Here we take hard grey rock, bake it, and grind it to cement — a powder that, with water, turns into strong STONE for walls and bridges.\"","A powder that becomes a WALL?!"),
   WOW("Now the second secret! 🪨 The very same company also makes <b>cement</b>: hard rock is baked and ground into a soft grey powder. Mix that powder with water and sand and it sets hard as <b>stone</b> — the walls, floors and bridges all around us. One company, making both <b>thread AND stone.</b>"),
   NOTE("Charlotte's Secret Notebook","The same company has a SECOND branch: cement. Rock is baked and ground into grey powder; add water and it hardens into stone for buildings. Thread on one branch, stone on the other! 🪨"),
 ]),
 ("c8","CHAPTER 8 · THE BIG DISCOVERY","The Giant of Thread and Stone","pages 61-70",[
   P("gr_c8_reveal","Tilda led Charlotte to a viewpoint over the whole works — a thread mill on one side, a cement plant on the other.","One company makes ALL of this?"),
   P("gr_c8_1975","\"Long ago, in 1947, it began as a maker of man-made thread,\" said Tilda. \"Turning wood into silky cloth.\"","It started with thread!"),
   P("gr_c8_scale","\"Then it grew a second branch — cement — and became a giant at BOTH: one of the world's biggest thread-makers, and a mighty maker of stone.\"","Two giants in ONE!"),
   WOW("A \"company\" can grow more than one branch. <b>Grasim</b> began in 1947 making man-made thread from wood, then grew a second branch making cement. Today it's <b>two very different businesses from one trunk</b> — a huge maker of viscose thread AND a giant of cement."),
   TL([("1947","A company begins making man-made thread — turning wood into silky cloth."),
       ("Later","It grows a second branch: making cement — turning rock into strong stone."),
       ("Today","One of the world's biggest makers of viscose thread, and a giant of cement too."),
       ("Tomorrow","Two branches, one trunk — growing carefully so BOTH stay strong. 🧵")]),
   NOTE("Charlotte's Secret Notebook","Grasim (1947) started by turning wood into silky thread, then grew a second branch making cement from rock. Two very different businesses from ONE company. 🏆"),
 ]),
 ("c9","CHAPTER 9","The Castle of Two Towers","pages 71-80",[
   P("gr_c9_castle","Two kind old men appeared with a glow. Warren pointed at a castle with TWO tall towers. \"What keeps rivals out, Charlotte?\"","Two towers? Why two?"),
   MOAT([("🧵","Wall One: Cheap Thread, Made Big","It grows its own trees and runs giant fibre plants, so it can make silky thread cheaply — far more, and far cheaper, than a small rival ever could.",False),
         ("🪨","Wall Two: Cheap Stone, Made Big","It owns great quarries of rock and runs huge cement plants, so it makes stone-powder cheaply and by the mountain. A scale a newcomer can't match.",False),
         ("🌳","Wall Three: Two Branches, One Trunk","When a storm bends one branch — say, thread has a hard year — the other branch can help hold the whole tree up. Two legs are steadier than one.",False),
         ("⚠️","The Crack in the Wall","But two businesses means TWO sets of storms. You must tend BOTH branches, always. Neglect one, and it can drag the whole tree down.",True)]),
   P("gr_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 two-branch giant strong, imagine how it could FADE — letting one branch rot while minding the other, or growing so fast it forgets to make either one cheaply — then carefully avoid each one, and tend both branches with equal care."),
   P("gr_c9_verdict","Warren nodded. \"It makes thread AND stone cheaply and at giant scale — a mighty castle, so long as it tends BOTH towers with equal care.\"","I SEE the whole picture!"),
   NOTE("Charlotte's Secret Notebook · The Big Secret","Grasim is hard to copy: it makes thread AND stone cheaply and BIG, and two branches steady one trunk. But two businesses means two storms — it must tend both. Charlie's trick: picture how you'd lose (neglect a branch), then never do it. Invert! 🏰"),
 ]),
 ("c10","CHAPTER 10","Thread, Stone, and Everything","pages 81-88",[
   P("gr_c10_wake","Charlotte woke in her own bed. The workshop was gone… but a silky thread and a smooth grey stone lay shimmering on her desk.","Was it real? It FELT real…"),
   P("gr_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 tree in your shirt and the stone in your walls. Well done."'),
   P("gr_c10_look","She ran outside at dusk. Her soft shirt, a strong brick wall, a passing truck of cement — all of it, quietly, was thread and stone from ONE clever company.","A tree in my shirt, a stone in my wall — and I never knew!"),
   WOW("Next time you pull on a soft shirt or pass a strong wall, you'll know the secret: one may be a <b>tree turned to thread</b>, the other a <b>rock turned to stone</b> — and both can come from ONE company with two branches. That's <b>the thread and the stone.</b> 🧵🪨"),
   NOTE("Charlotte's Secret Notebook · What I Learned","➊ Silky thread begins as WOOD — mashed to pulp, dissolved into a golden syrup.<br>➋ Pushed through a shower-head of tiny holes into a bath, it hardens into thread → woven into CLOTH.<br>➌ The same company also bakes rock into CEMENT — powder that sets into strong stone.<br>➍ Two very different branches from one trunk; its moat is cheap inputs and giant scale in both.<br>➎ But two businesses means two storms — Charlie's trick: picture how you'd lose (neglect a branch), then tend both. 💛"),
 ]),
]

HOOK=("gr_c1_swirl","EVERY ORDINARY THING HIDES A SECRET.",
 "Charlotte learned how a tree becomes cloth and a rock becomes a wall. But the compass is twitching yet again — this time toward the bright white paint drying on her garden fence. Where do all the colours come from, and who mixes them?",
 "NEXT ADVENTURE · The Colour Factory →")

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="#4b53b8">A TREE BECOMES CLOTH</text>
<g><circle cx="120" cy="150" r="34" fill="#7cc46a" stroke="#2aa15a" stroke-width="4"/><text x="120" y="112" text-anchor="middle" font-family="Baloo 2" font-size="15" fill="#2aa15a">A TREE</text><text x="120" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">grown just for cloth</text></g>
<g stroke="#2aa15a" stroke-width="5" fill="#2aa15a"><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="#8a6a3f">WOOD PULP</text><text x="395" y="165" text-anchor="middle" font-family="Bangers" font-size="24" fill="#8a6a3f">mashed soft</text><text x="395" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">wood becomes mush</text></g>
<g stroke="#c8a23f" stroke-width="5" fill="#c8a23f"><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="#c8a23f">dissolved to syrup</text>
<text x="540" y="182" text-anchor="middle" font-family="Nunito" font-size="12" fill="#555">then through tiny holes</text>
<g><rect x="620" y="112" width="150" height="90" rx="12" fill="#4b53b8" stroke="#171717" stroke-width="4"/><text x="695" y="102" text-anchor="middle" font-family="Baloo 2" font-size="16" fill="#4b53b8">SILKY THREAD</text><text x="695" y="165" text-anchor="middle" font-family="Bangers" font-size="22" fill="#fff">woven to cloth</text><text x="695" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">a man-made fibre</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">Mash wood to pulp &#8594; dissolve it into a GOLDEN SYRUP &#8594; push it through a shower-head of tiny holes into a bath &#8594; it hardens into THREAD.</text>
<text x="410" y="343" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">A tree you can wear — a man-made fibre from a natural thing.</text>
</svg><div class="figcap">Wood is mashed to pulp, dissolved into a golden syrup, squeezed through tiny holes into a bath where it hardens into silky thread, then woven into cloth.</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_tilda"); 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/grasim/_head.html").read()
    tail=open("/root/omahaindia.com/comics/site/book/grasim/_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()
