#!/usr/bin/env python3
# Book 47 (SBI Life Insurance) — THE SAFETY NET. Science->business: POOLING risk. One thread is
# WEAK, but thousands woven together hold a falling acrobat — that is a NET. Everyone pays a little;
# the unlucky few are caught. The more hands weaving, the stronger AND cheaper the net (law of large
# numbers, told gently). -> life insurance sold through a giant bank's branches; the moat is reach +
# trust; the caveat is a net must be checked and funded for decades. (Pairs with Book 34's umbrella.)
import os
ART="/root/omahaindia.com/comics/site/book/sbilife/art"
OUT="/root/omahaindia.com/comics/site/book/sbilife/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"
NELL=("Nell, a warm friendly Western INSURANCE GUIDE, NOT Indian, chestnut hair in a low bun, warm steady smile, "
"a soft blue blazer, a woven net-motif scarf around her neck")

# name -> (w,h,seed,prompt,ref). ref set -> Seedream character; None -> flux scene. Ritual panels copied by mkbook.
NEW={
 "00_cover":(1024,1180,4700,f"{STYLE}. BOOK COVER, {CHARLOTTE} standing with {NELL} at the edge of a huge circus big top, a tiny acrobat far above on a tightrope and a vast shimmering woven safety net stretched wide below catching warm golden light, thousands of silver threads glowing, wonder, cinematic","charlotte"),
 "_ref_nell":(1024,1024,4701,f"{STYLE}. clean friendly character portrait, {NELL}, plain soft warm background, kind smile, head and shoulders",None),
 # Ch1
 "sl_c1_coin":(1024,720,4710,f"{STYLE}. {CHARLOTTE} at home, Grandpa Ben's glowing brass compass twitching between a single thin silver thread and a shiny little coin on the table, EXPRESSION puzzled and intrigued, cozy lamp light","charlotte"),
 "sl_c1_diary":(1024,720,4711,f"{STYLE}. an open magical diary glowing warm gold on a desk, a faint ribbon of silver thread rising from the page and weaving itself into a tiny glowing net, no people",None),
 "sl_c1_swirl":(1024,720,4712,f"{STYLE}. {CHARLOTTE} pulled into a swirling spiral of golden light and shimmering silver threads from a glowing diary, EXPRESSION thrilled, magical","charlotte"),
 # Ch2 — arrive at the great circus, meet Nell
 "sl_c2_arrive":(1024,720,4713,f"{STYLE}. {CHARLOTTE} landing wide-eyed inside an enormous bright circus big top, a thin tightrope high in the air and a huge woven safety net stretched far below, EXPRESSION awe and delight, warm daylight through the canvas","charlotte"),
 "sl_c2_nell":(1024,720,4714,f"{STYLE}. {NELL} warmly welcoming {CHARLOTTE}, resting a hand on her woven net-motif scarf, EXPRESSION Charlotte shy happy smile; keep the SAME insurance guide from the reference, same soft blue blazer, same net-motif scarf, same low bun","nell"),
 "sl_c2_tent":(1024,720,4715,f"{STYLE}. seen from below, a tiny brave acrobat balancing on a high tightrope with a wide woven safety net stretched between the tent poles far beneath, dizzying scale, no faces close up",None),
 # Ch3 — one thread is weak
 "sl_c3_thread":(1024,720,4716,f"{STYLE}. {NELL} kneeling to show {CHARLOTTE} a single thin silver thread pinched between her fingers, catching the light, EXPRESSION Charlotte fascinated leaning in; SAME insurance guide, soft blue blazer, net-motif scarf","nell"),
 "sl_c3_snap":(1024,720,4717,f"{STYLE}. a close up of one lonely silver thread snapping in two under the weight of a single small pebble, a tiny puff of motion, playful science, no people",None),
 "sl_c3_single":(1024,720,4718,f"{STYLE}. a friendly close up of a single dangling thread that cannot even hold up one little button, drooping sadly, gentle storybook style, no people",None),
 # Ch4 — thousands woven into a net
 "sl_c4_weave":(1024,720,4719,f"{STYLE}. {CHARLOTTE} watching in wonder as thousands of silver threads are woven together over and under into an enormous strong net, EXPRESSION amazed and thoughtful, warm bright light","charlotte"),
 "sl_c4_mesh":(1024,720,4720,f"{STYLE}. a magical close up of many threads crossing over and under one another into a tight strong mesh, little arrows showing how they share the weight between them, warm glow, no people",None),
 "sl_c4_net":(1024,720,4721,f"{STYLE}. a beautiful woven safety net stretched wide and taut and springy, thousands of threads glowing softly together, strong and inviting, no people",None),
 # Ch5 — the acrobat falls, the net catches
 "sl_c5_fall":(1024,720,4722,f"{STYLE}. a brave acrobat slipping from the high tightrope and tumbling down through the air with arms flung wide, a huge woven net waiting below, dramatic and suspenseful, no faces close up",None),
 "sl_c5_catch":(1024,720,4723,f"{STYLE}. {NELL} showing {CHARLOTTE} how the wide woven net softly catches the falling acrobat and bounces them gently back up, safe and sound, EXPRESSION Charlotte delighted 'aha'; SAME insurance guide, soft blue blazer, net-motif scarf","nell"),
 # Ch6 — everyone pays a little; the unlucky few are caught
 "sl_c6_coins":(1024,720,4724,f"{STYLE}. {CHARLOTTE} watching a long line of cheerful people each drop one small coin into a big shared pot, the pot glowing warmly, EXPRESSION awed and moved, bright hall","charlotte"),
 "sl_c6_few":(1024,720,4725,f"{STYLE}. bright ribbons of thread flowing out of a glowing shared pot to weave a net that catches the few who stumble, while most people walk on safe and happy, warm and kind, no faces close up",None),
 # Ch7 — the more hands, the stronger and cheaper
 "sl_c7_hands":(1024,720,4726,f"{STYLE}. very many hands of all kinds working together, weaving and weaving until the safety net grows enormous, warm togetherness, no faces close up",None),
 "sl_c7_cheap":(1024,720,4727,f"{STYLE}. a warm storybook picture showing that when thousands more people help weave, each person needs only a single thin thread and one tiny coin, yet the net grows huge and strong, gentle and grand, no people",None),
 # Ch8 — reveal SBI Life
 "sl_c8_reveal":(1024,720,4728,f"{STYLE}. {CHARLOTTE} and {NELL} standing proudly before a great bank building with a vast shining safety net stretched protectively over a whole town, EXPRESSION proud recognition; SAME insurance guide, soft blue blazer, net-motif scarf","charlotte"),
 "sl_c8_found":(1024,720,4729,f"{STYLE}. warm sepia scene, a mighty bank and a careful insurer joining hands to begin weaving safety nets for families, hopeful and dignified, no text",None),
 "sl_c8_scale":(1024,720,4730,f"{STYLE}. a giant trusted bank with thousands of little branch doors all across a storybook map of India, each doorway handing a family a folded woven net, proud and grand, no faces close up",None),
 # Ch10 (ch9 uses ritual castle/invert/verdict; ch10 uses ritual wake/diary)
 "sl_c10_look":(1024,720,4731,f"{STYLE}. {CHARLOTTE} outside in warm evening light, seeing faint glowing safety nets shimmering invisibly beneath every family — a market, a school, a home — quietly holding them, 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 Thread and the Coin","pages 1-8",[
   P("sl_c1_coin","Back home, Grandpa Ben's compass twitched again — pointing between one thin thread and a single shiny coin.","A thread… and a coin? What can THOSE do?",None,"twitch"),
   P("sl_c1_diary","The old diary fell open. A new line shimmered in Grandpa Ben's hand.",None,'"Find the net that catches you when you fall."'),
   WOW("A thin thread and a tiny coin — what could be weaker or smaller? Yet somehow these two little things can catch a grown-up who falls out of the sky, and keep a whole family safe. How can something so small do something so big? That's the puzzle of this whole adventure."),
   P("sl_c1_swirl","Golden light and silver threads swirled up and pulled Charlotte in.","Here we GO!",None,"WHOOSH","#2563eb"),
   NOTE("Charlotte's Secret Notebook","Two BIG questions:<br>➊ How can one thin thread ever catch a falling person?<br>➋ Grandpa Ben says a tiny <i>coin</i> is part of the secret. How can a coin keep someone safe? 🪙"),
 ]),
 ("c2","CHAPTER 2","The Tent at the Edge of the Sky","pages 9-16",[
   P("sl_c2_arrive","One blink, and she stood inside the biggest tent she'd ever seen — a thin rope high above, and something wide and woven stretched far below.","There's a rope in the SKY — and a net underneath!"),
   P("sl_c2_nell","A kind woman in a blue blazer waved, her scarf woven like a net. \"I'm Nell. I look after promises that catch people when they fall.\"","Promises that CATCH people?!"),
   P("sl_c2_tent","Far above, a tiny acrobat balanced on the tightrope, the wide net waiting patiently below.","If she slips… does the net really hold?","Stick with me, kiddo."),
   NOTE("Charlotte's Secret Notebook","Nell looks after 'promises that catch people' — and she grins like she has a secret, just like the other guides did. There's an acrobat way up high and a net far below. Okay Nell… show me how a net works! ✨"),
 ]),
 ("c3","CHAPTER 3","One Thread Is Weak","pages 17-26",[
   P("sl_c3_thread","Nell held up a single thin thread. \"On its own, one thread is weak. Watch — it can barely hold anything at all.\"","Just one thread — it looks so fragile!"),
   P("sl_c3_snap","She hung a small pebble from it. SNAP — the lonely thread broke in two.","One thread can't even hold a pebble!",None,"snap","#2563eb"),
   P("sl_c3_single","\"A single thread can't catch a falling person,\" said Nell. \"It couldn't even hold up a button.\"","So how does a NET ever hold anyone?"),
   WOW("Here's the first secret! 💡 <b>One thread is weak.</b> By itself, a single thread snaps under the tiniest weight — a pebble, a button, nothing at all. If a net were just one thread, no acrobat would ever dare to climb. So how does a net become strong enough to catch a falling grown-up? Keep watching…"),
   ("diagram",),
   NOTE("Charlotte's Secret Notebook","One thread on its own is WEAK — it snaps under even a pebble. A single thread could never catch a falling person. The strength must come from somewhere else. 🧵"),
 ]),
 ("c4","CHAPTER 4","Woven Into a Net","pages 27-36",[
   P("sl_c4_weave","\"But watch THIS,\" said Nell. Thousands of threads crossed over and under, woven together into a huge net.","So many threads — all holding hands!"),
   P("sl_c4_mesh","\"When they're woven together, each thread shares the weight with all the others,\" she said. \"No single one has to hold it alone.\"","They SHARE the heavy part!",None,"weave","#2aa15a"),
   P("sl_c4_net","\"And that,\" smiled Nell, \"is a net — strong and springy, made of thousands of weak little threads.\"","Thousands of weak threads make ONE strong net!"),
   WOW("Take thousands of weak threads and <b>weave them together</b>, and something wonderful happens: each thread only has to hold a tiny share of the weight, so together they can catch what no single thread ever could. That is a <b>net</b> — strong precisely because so many joined in. Being <b>woven together</b> is the whole trick."),
   NOTE("Charlotte's Secret Notebook · SOLVED (part 1)","A net is thousands of weak threads WOVEN together. Each thread carries only a tiny share of the weight, so together they're strong. Alone = weak. Woven together = strong. 🕸️"),
 ]),
 ("c5","CHAPTER 5","The Catch","pages 37-44",[
   P("sl_c5_fall","High above, the acrobat wobbled… and slipped! Down she tumbled through the air, arms flung wide.","Oh no — she's FALLING!",None,"gasp","#2563eb"),
   P("sl_c5_catch","But the woven net caught her softly and bounced her right back up, safe and laughing. Nell smiled at Charlotte.","The net HELD her — she's okay!"),
   WOW("Only a few people ever fall — but when one does, the net is ready. Woven from thousands of threads, it <b>catches the unlucky one</b> and holds them safe. That is exactly what a net is FOR: it waits quietly, and on the rare day someone falls, it is there. That's the promise Nell looks after."),
   NOTE("Charlotte's Secret Notebook","Most days, nobody falls. But when someone DOES, the woven net catches them and keeps them safe. A net is a promise that waits, ready for the rare bad day. 🤸"),
 ]),
 ("c6","CHAPTER 6","Everyone Pays a Little","pages 45-52",[
   P("sl_c6_coins","Nell showed her a big shared pot. One by one, hundreds of people each dropped in a single small coin.","Everyone's putting in just ONE little coin!"),
   P("sl_c6_few","\"Every coin helps weave the net,\" said Nell. \"Most people never fall — but their coins catch the unlucky few who do.\"","So EVERYONE keeps the few safe!"),
   WOW("Here's the kind part. <b>Everyone pays a little</b> — one small coin each — and all those coins together weave one big net. Most people will never fall, but their coins are what catch the <b>unlucky few</b> who do. Nobody knows in advance who will fall, so everyone chips in, and the net holds them all."),
   NOTE("Charlotte's Secret Notebook · SOLVED!","Everyone pays a LITTLE (one coin each). The coins together weave the net. Most never fall, but their coins catch the unlucky few who do. A thread = a coin. Woven together = a net that keeps everyone safe. 🪙🕸️"),
 ]),
 ("c7","CHAPTER 7","The More Hands, The Stronger","pages 53-60",[
   P("sl_c7_hands","More and more people came to help weave. With every extra pair of hands, the net grew bigger and stronger.","The more who join, the BIGGER it gets!"),
   P("sl_c7_cheap","\"And here's the magic,\" said Nell. \"With so many weaving, each person needs only a thin thread and a tiny coin — yet the net is huge and strong.\"","More hands = safer AND cheaper for everyone!"),
   WOW("The more people who join, the better it works for <b>everyone</b>. With thousands of weavers, the falls become easy to predict, so the net can be planned just right — and each person needs only a <b>thin thread and a tiny coin</b>. Bigger crowd → stronger, cheaper, fairer net. Grown-ups call this gentle idea the <b>law of large numbers.</b>"),
   NOTE("Charlotte's Secret Notebook","The MORE hands weaving, the stronger the net AND the cheaper each person's share. A huge crowd makes the net strong, fair, and cheap for all. (Grown-ups call it the law of large numbers.) 🤝"),
 ]),
 ("c8","CHAPTER 8 · THE BIG DISCOVERY","The Net Behind the Bank","pages 61-70",[
   P("sl_c8_reveal","Nell led Charlotte to a viewpoint: a great bank, with a shining net spread over a whole town.","Who weaves a net THIS big for everyone?"),
   P("sl_c8_found","\"A great, trusted bank teamed up with careful net-makers,\" said Nell, \"to weave safety nets for millions of families.\"","A bank AND net-makers, working together!"),
   P("sl_c8_scale","\"They reach families through the bank's thousands of branches — a net woven right across the country.\"","So many branches — so many nets!"),
   WOW("A \"company\" can be a giant shared job. <b>SBI Life Insurance</b> weaves the biggest net of all: it teams a hugely <b>trusted bank</b> with careful insurers, and reaches millions of families through the bank's <b>thousands of branches</b>. Everyone pays a little; the unlucky few are caught. A whole nation's safety net."),
   TL([("Long ago","People learn that many small coins, pooled together, can catch anyone who falls."),
       ("The team-up","A giant trusted bank joins careful net-makers to weave safety nets for families."),
       ("Through the branches","Families all across the land get their net through the bank's thousands of doors."),
       ("For decades","The net is checked and funded year after year, so it's always ready to catch. 🕸️")]),
   NOTE("Charlotte's Secret Notebook","SBI Life weaves the net for millions: a trusted BANK + careful net-makers, reaching families through thousands of bank branches. Everyone pays a little; the unlucky few are caught. 🏦"),
 ]),
 ("c9","CHAPTER 9","The Castle Above the Net","pages 71-80",[
   P("sl_c9_castle","Two kind old men appeared with a glow. Warren pointed at a castle standing above a great net spread across the land. \"What keeps rivals out, Charlotte?\"","Walls! But what kind?"),
   MOAT([("🏦","Wall One: Reach Through the Branches","The net is handed out through a giant trusted bank's thousands of branches. A newcomer would need thousands of doors of its own — that takes ages to build.",False),
         ("🤝","Wall Two: Trust","People only hand their coins to a promise they believe will still be there in decades. A famous, trusted name is very hard for a stranger to copy.",False),
         ("🕸️","Wall Three: The Woven Crowd","The more families already weaving in, the stronger, cheaper and fairer the net — and the harder it is for a small rival to match.",False),
         ("⚠️","The Crack in the Wall","A net is a promise for DECADES. It must be checked and funded carefully all that time. If the weaving grows careless or the pot runs thin, the promise can fail when it's needed most.",True)]),
   P("sl_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 safety net strong, imagine how it could FAIL — promising more coins-worth of catching than the pot can hold, or forgetting to fund and check it for the long decades ahead — then carefully avoid each one, and keep the net honestly funded year after year."),
   P("sl_c9_verdict","Warren nodded. \"Reach through the branches, and trust — a mighty castle, so long as the net is checked and funded for all the decades it must last.\"","I SEE the whole picture!"),
   NOTE("Charlotte's Secret Notebook · The Big Secret","SBI Life is hard to copy: it REACHES through a trusted bank's thousands of branches, people TRUST the name, and the woven crowd is huge. But a net is a promise for DECADES — it must be funded and checked, or it fails when needed. Charlie's trick: picture how you'd lose (an underfunded net), then never do it. Invert! 🏰"),
 ]),
 ("c10","CHAPTER 10","The Nets We Cannot See","pages 81-88",[
   P("sl_c10_wake","Charlotte woke in her own bed. The great tent was gone… but a tiny woven net charm on her desk shimmered softly.","Was it real? It FELT real…"),
   P("sl_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 net that thousands weave together. Well done."'),
   P("sl_c10_look","She ran outside at dusk. Beneath every family — the market, the school, the homes — she could almost see a quiet net, woven of everyone's coins, holding them all.","The nets were there the whole time — I just couldn't see them!"),
   WOW("Next time someone is caught on a hard day, you'll know the secret: a <b>net</b> was there. Thousands of weak threads — thousands of small coins — woven together so the unlucky few are caught. Everyone pays a little; the more hands, the stronger and cheaper the net. That's <b>the safety net.</b> 🕸️🪙"),
   NOTE("Charlotte's Secret Notebook · What I Learned","➊ One thread is weak; alone it snaps under a pebble.<br>➋ Thousands WOVEN together make a strong net — each carries only a tiny share.<br>➌ Everyone pays a little coin; the unlucky few who fall are caught.<br>➍ The more hands weaving, the stronger AND cheaper the net.<br>➎ SBI Life weaves it through a trusted bank's branches — but Charlie's trick: picture how you'd lose (an underfunded net), then fund and check it for decades. 💙"),
 ]),
]

HOOK=("sl_c1_swirl","EVERY ORDINARY THING HIDES A SECRET.",
 "Charlotte learned how thousands of tiny threads — and tiny coins — weave a net that catches anyone who falls. But the compass is twitching again — toward a folded promise that springs open over your head the moment the rain begins. What is the umbrella a whole family can share?",
 "NEXT ADVENTURE · The Shared Umbrella →")

DIAGRAM='''<div class="panel wide" style="background:#eef4fb;">
<svg viewBox="0 0 820 380"><rect width="820" height="380" fill="#eef4fb"/>
<text x="410" y="38" text-anchor="middle" font-family="Bangers" font-size="24" fill="#2563eb">MANY THREADS MAKE A NET</text>
<g><circle cx="120" cy="150" r="34" fill="#fff" stroke="#e8425a" stroke-width="4"/><text x="120" y="112" text-anchor="middle" font-family="Baloo 2" font-size="15" fill="#e8425a">ONE THREAD</text><text x="120" y="156" text-anchor="middle" font-family="Bangers" font-size="20" fill="#e8425a">snap!</text><text x="120" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">alone, it is weak</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="#2aa15a">MANY HANDS</text><text x="395" y="165" text-anchor="middle" font-family="Bangers" font-size="24" fill="#2aa15a">weave it</text><text x="395" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">everyone pays a little</text></g>
<g stroke="#37414d" stroke-width="5" fill="#37414d"><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="#37414d">woven together</text>
<text x="540" y="182" text-anchor="middle" font-family="Nunito" font-size="12" fill="#555">each shares the weight</text>
<g><rect x="620" y="112" width="150" height="90" rx="12" fill="#2563eb" stroke="#171717" stroke-width="4"/><text x="695" y="102" text-anchor="middle" font-family="Baloo 2" font-size="16" fill="#2563eb">A NET</text><text x="695" y="165" text-anchor="middle" font-family="Bangers" font-size="22" fill="#fff">it catches!</text><text x="695" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">strong for the unlucky few</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">One thread is weak &#8594; thousands WOVEN together make a net &#8594; everyone pays a little &#8594; the unlucky few are CAUGHT.</text>
<text x="410" y="343" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">And the more hands that help weave, the stronger and cheaper the net becomes for all.</text>
</svg><div class="figcap">One thread is weak, but thousands woven together make a net — everyone pays a little, and the unlucky few are caught.</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_nell"); 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/sbilife/_head.html").read()
    tail=open("/root/omahaindia.com/comics/site/book/sbilife/_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()
