#!/usr/bin/env python3
# Book 40 (Axis Bank) — THE WEB OF WALLETS. Science->business: money moving is really a MESSAGE
# ('take a little from this wallet, add it to that one' -> checked & settled in a blink -> every wallet
# balances) -> a NETWORK that grows itself (more shops -> more cards -> more shops) -> the bank that
# weaves the web of accounts, cards and the plumbing under a tap.
import os
ART="/root/omahaindia.com/comics/site/book/axis/art"
OUT="/root/omahaindia.com/comics/site/book/axis/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"
WANDA=("Wanda, a warm friendly Western PAYMENTS BANKER, NOT Indian, sleek dark bob, quick clever smile, "
"a smart magenta blazer, a shiny bank card held 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,4000,f"{STYLE}. BOOK COVER, {CHARLOTTE} standing with {WANDA} inside a vast glowing web of light-threads that link countless tiny shops and homes, holding up a shiny card that sends a bright ribbon of light between two glowing wallets, a warm city of tap-terminals sparkling on the horizon, wonder, cinematic","charlotte"),
 "_ref_wanda":(1024,1024,4001,f"{STYLE}. clean friendly character portrait, {WANDA}, plain soft warm background, quick clever smile, head and shoulders",None),
 # Ch1
 "ax_c1_coin":(1024,720,4010,f"{STYLE}. {CHARLOTTE} at home, Grandpa Ben's glowing brass compass twitching between a flat plastic bank card and a little glowing shop tap-machine on the table, EXPRESSION puzzled and intrigued, cozy lamp light","charlotte"),
 "ax_c1_diary":(1024,720,4011,f"{STYLE}. an open magical diary glowing warm gold on a desk, a faint ribbon of light rising from the page and curling into a tiny glowing envelope flitting between two coins, no people",None),
 "ax_c1_swirl":(1024,720,4012,f"{STYLE}. {CHARLOTTE} pulled into a swirling spiral of magenta and blue light and glowing coins from a glowing diary, EXPRESSION thrilled, magical","charlotte"),
 # Ch2 — arrive at the payments hall, meet Wanda
 "ax_c2_arrive":(1024,720,4013,f"{STYLE}. {CHARLOTTE} landing wide-eyed inside an enormous glowing hall crisscrossed with countless threads of light that link tiny shops, homes and tills, EXPRESSION awe and delight, bright airy light","charlotte"),
 "ax_c2_wanda":(1024,720,4014,f"{STYLE}. {WANDA} warmly welcoming {CHARLOTTE} in the payments hall, offering a friendly hand, EXPRESSION Charlotte shy happy smile; keep the SAME banker from the reference, same magenta blazer, same sleek dark bob, same bank card in hand","wanda"),
 "ax_c2_pit":(1024,720,4015,f"{STYLE}. a vast glowing web seen from above, millions of tiny glowing wallets and shop tills joined by shimmering threads of light, tiny tap-terminals sparkling for scale, powerful and awe-inspiring, no faces close up",None),
 # Ch3 — money is a message
 "ax_c3_leaf":(1024,720,4016,f"{STYLE}. {WANDA} kneeling to show {CHARLOTTE} a card tapping a little terminal, a tiny glowing envelope of light leaping off the card toward a shop's till, EXPRESSION Charlotte fascinated leaning in; SAME banker, magenta blazer, sleek dark bob, bank card","wanda"),
 "ax_c3_forest":(1024,720,4017,f"{STYLE}. a magical night city seen from above, countless tiny glowing message-envelopes zipping along shimmering light-threads between shops and homes, alive and magical, warm glow, no people",None),
 "ax_c3_store":(1024,720,4018,f"{STYLE}. a friendly close up of two glowing wallet-jars, a single little glowing coin lifting out of one as a bright message and dropping softly into the other, playful science, no people",None),
 # Ch4 — every wallet must balance
 "ax_c4_sink":(1024,720,4019,f"{STYLE}. {CHARLOTTE} watching in wonder as a giant golden balance scale stays perfectly level while one coin slides from a glowing wallet on one pan to a glowing wallet on the other, EXPRESSION amazed and thoughtful, warm dramatic light","charlotte"),
 "ax_c4_press":(1024,720,4020,f"{STYLE}. a magical twin-column ledger book glowing softly, every 'take a little' line on the left joined by a shining thread to a matching 'add a little' line on the right, warm gold glow, no people",None),
 "ax_c4_rock":(1024,720,4021,f"{STYLE}. a beautiful close up of two balanced glowing scale pans, exactly even, a single coin of light caught mid-flight between them, dark rim bright center, no people",None),
 # Ch5 — the plumbing under a tap
 "ax_c5_burn":(1024,720,4022,f"{STYLE}. a single card tapping a shop terminal, a warm burst of golden light at the touch as a bright message shoots away, glowing sparks, no people",None),
 "ax_c5_boil":(1024,720,4023,f"{STYLE}. {WANDA} lifting a shop counter to show {CHARLOTTE} the hidden glowing pipes and rails beneath, carrying a message of light from the tap toward a distant bank tower and back, EXPRESSION Charlotte delighted 'aha'; SAME banker, magenta blazer, sleek dark bob, bank card","wanda"),
 # Ch6 — the network effect
 "ax_c6_spin":(1024,720,4024,f"{STYLE}. {CHARLOTTE} watching a glowing web grow before her eyes — more shops lighting up, more cards appearing, threads multiplying in a rush, her ponytails blown back, EXPRESSION awed and excited, bright hall","charlotte"),
 "ax_c6_electric":(1024,720,4025,f"{STYLE}. bright ribbons of light racing between more and more shops and homes as the network spreads, each new glowing shop drawing new glowing cards toward it, magical, no people",None),
 # Ch7 — woven into a whole day
 "ax_c7_everyone":(1024,720,4026,f"{STYLE}. a joyful city where homes, a school, a market stall, a railway ticket window all pay with a tap and a card, glowing threads of light connecting them all, warm togetherness, no faces close up",None),
 "ax_c7_half":(1024,720,4027,f"{STYLE}. a warm storybook map of India glowing at night, millions of tiny points of light joined by shimmering payment-threads crisscrossing the whole land, gentle and grand, no people",None),
 # Ch8 — reveal Axis Bank
 "ax_c8_reveal":(1024,720,4028,f"{STYLE}. {CHARLOTTE} and {WANDA} standing proudly before a great gleaming private-bank tower with a glowing web of light radiating out across the city, EXPRESSION proud recognition; SAME banker, magenta blazer, sleek dark bob, bank card","charlotte"),
 "ax_c8_1975":(1024,720,4029,f"{STYLE}. warm sepia 1990s scene, a brand-new bank opening its doors for the very first time, hopeful staff and early boxy computers, a fresh start, inspiring, no text",None),
 "ax_c8_scale":(1024,720,4030,f"{STYLE}. a mighty modern bank at golden hour, gleaming towers, rows of glowing ATMs and a bright web of light spreading out, one of India's biggest private banks, proud and grand, no people",None),
 # Ch10 (ch9 uses ritual castle/invert/verdict; ch10 uses ritual wake/diary)
 "ax_c10_look":(1024,720,4031,f"{STYLE}. {CHARLOTTE} outside in a busy evening market watching with wonder as every card tap around her sends a tiny glowing message flitting away, knowing each one is money moving as a message, 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 Card That Held a Secret","pages 1-8",[
   P("ax_c1_coin","Back home, Grandpa Ben's compass twitched again — pointing between a flat plastic card and a little shop machine that beeped when you tapped it.","A card… and a beep? What's the link?",None,"beep"),
   P("ax_c1_diary","The old diary fell open. A new line shimmered in Grandpa Ben's hand.",None,'"Follow the money that never moves — it only sends a message."'),
   WOW("A flat little card buys a whole basket of shopping with one tap — and no coins or notes change hands at all. So how does the money get from you to the shopkeeper? Where does it actually GO? That's the puzzle of this whole adventure."),
   P("ax_c1_swirl","Golden light swirled up and pulled Charlotte in.","Here we GO!",None,"WHOOSH","#c0257e"),
   NOTE("Charlotte's Secret Notebook","Two BIG questions:<br>➊ When you tap a card, how does the money reach the shop if nothing moves?<br>➋ Grandpa Ben says the money only sends a <i>message</i>. What does that even mean? 💳"),
 ]),
 ("c2","CHAPTER 2","The Hall of a Million Threads","pages 9-16",[
   P("ax_c2_arrive","One blink, and she stood inside the busiest room she'd ever seen — glowing threads of light shooting between a million tiny shops and homes.","It's a whole web made of LIGHT!"),
   P("ax_c2_wanda","A cheerful woman in a magenta blazer waved a shiny card. \"I'm Wanda, a payments banker. Down here, we move money by sending little messages.\"","Move money… with MESSAGES?!"),
   P("ax_c2_pit","All around, tiny wallets and shop tills glowed, joined by shimmering threads too many to count.","So many threads — and money runs along ALL of them?","Stick with me, kiddo."),
   NOTE("Charlotte's Secret Notebook","Wanda is a payments banker, and she grins like she has a secret — just like the other guides did. She says money moves as a 'message'. Okay Wanda… show me how! ✨"),
 ]),
 ("c3","CHAPTER 3","Money Is a Message","pages 17-26",[
   P("ax_c3_leaf","Wanda held a card to a little machine. A tiny envelope of light leapt off. \"See? Nothing solid travels. A message flies out: take a little from this wallet, add it to that one.\"","The money is a MESSAGE!"),
   P("ax_c3_forest","\"Every second, millions of these little messages zip between wallets — buying bread, paying buses, sending pocket money.\"","A whole sky full of tiny messages!"),
   P("ax_c3_store","\"The shop's wallet goes up by exactly what yours goes down. Same little bit — just moved.\"","It didn't vanish — it just HOPPED across!",None,"zip","#2563eb"),
   WOW("Here's the first secret! 💡 When you pay, money doesn't really travel — a <b>message</b> does. It says: <b>take a little from this wallet, add it to that one.</b> The bank checks it and settles it in a <b>blink</b>. That's all a payment is: a tiny, trusted message."),
   ("diagram",),
   NOTE("Charlotte's Secret Notebook","Paying is really sending a MESSAGE: 'take a little from here, add a little there.' The bank checks it and settles it in a blink. No coins fly — just a trusted little note. 💌"),
 ]),
 ("c4","CHAPTER 4","Every Wallet Must Balance","pages 27-36",[
   P("ax_c4_sink","Wanda tipped a giant golden scale. A coin slid from one wallet to another — yet the scale stayed perfectly level.","It didn't tip at all!"),
   P("ax_c4_press","\"That's the rule,\" she said. \"For every 'take a little' there is a matching 'add a little.' Money is never made or lost in a move — it only changes wallets.\"","Every take has an add!",None,"click","#2563eb"),
   P("ax_c4_rock","\"So the totals always match. If they don't, we know something is wrong — and we stop and check.\"","So the numbers must ALWAYS agree!"),
   WOW("A payment always has <b>two halves</b>: a little taken from one wallet, the SAME little added to another. So every wallet must <b>balance</b> — nothing appears from nowhere. If the two halves don't match, the network knows at once that something went wrong."),
   NOTE("Charlotte's Secret Notebook · SOLVED (part 1)","Every payment has TWO halves that must match: take a little / add a little. Money isn't made or lost — it just moves. So every wallet balances, and the totals always agree. ⚖️"),
 ]),
 ("c5","CHAPTER 5","The Plumbing Under a Tap","pages 37-44",[
   P("ax_c5_burn","Wanda tapped a card on a till. Light flashed and a message shot away. \"Watch what happens in the blink you never see.\"","So much, in one little tap!",None,"TAP","#c0257e"),
   P("ax_c5_boil","She lifted the counter to show glowing pipes rushing beneath. \"Card, account, and the rails that carry the message to the bank and back — all hidden under one tap.\"","There's a whole world UNDER the counter?!"),
   WOW("Under one simple tap is clever <b>plumbing</b>: your card, your account, and the hidden <b>rails</b> that carry the message. In a blink it flies to the bank — <i>check the wallet, approve, settle</i> — and races back with a friendly beep. Easy on top, busy underneath."),
   NOTE("Charlotte's Secret Notebook","A tap looks simple, but underneath: card → rails → bank → check → approve → settle → back again, all in a blink. Cards and accounts are the easy handles; the plumbing does the work. 🔧💳"),
 ]),
 ("c6","CHAPTER 6","The Web That Grows Itself","pages 45-52",[
   P("ax_c6_spin","The web began to grow before her eyes — one new shop lit up, then ten, then a thousand cards rushed to join them. Charlotte's ponytails flew back.","It's growing all by ITSELF!"),
   P("ax_c6_electric","\"More shops that accept cards means more people carry them,\" said Wanda, \"and more people carrying means even more shops want in.\"","Each one pulls in the next!"),
   WOW("This is the magic of a <b>network</b>: more shops accepting cards → more people carrying them → more shops wanting to accept them. Round and round it grows, each side pulling the other. A web like that gets <b>stronger the bigger it gets</b> — it grows itself!"),
   NOTE("Charlotte's Secret Notebook · SOLVED!","The NETWORK EFFECT: more shops → more cards → more shops. Each side pulls the other, so the web keeps growing and growing. The bigger it gets, the more useful — and the harder to leave. 🕸️"),
 ]),
 ("c7","CHAPTER 7","Woven Into a Whole Day","pages 53-60",[
   P("ax_c7_everyone","Wanda swept her arm across the city. A school, a market, a bus, a ticket window — all humming with quiet taps and glowing threads.","EVERYONE's money runs through this?!"),
   P("ax_c7_half","\"From a morning chai to an evening bill,\" said Wanda, \"a whole country's day runs on these little messages.\"","The whole day is stitched together with them!"),
   WOW("Step back and look: accounts, cards, taps and the rails beneath them carry the <b>everyday money of a whole nation</b> — wages, shopping, buses, bills. Trillions of tiny messages, each one 'take a little, add a little', woven quietly under an ordinary day."),
   NOTE("Charlotte's Secret Notebook","Salaries, shopping, buses, bills — a whole country's daily money moves as tiny messages on the web. It's woven so quietly into the day that most people never even notice it. 🌏💫"),
 ]),
 ("c8","CHAPTER 8 · THE BIG DISCOVERY","The Bank That Wove the Web","pages 61-70",[
   P("ax_c8_reveal","Wanda led Charlotte to a viewpoint before a gleaming bank tower, threads of light streaming out of it.","Who WEAVES a web this big?"),
   P("ax_c8_1975","\"In 1994,\" said Wanda, \"a brand-new private bank opened its doors and began stitching accounts and cards together.\"","A whole web, started from nothing!"),
   P("ax_c8_scale","\"It grew and grew — accounts, cards, taps — into one of India's biggest private banks.\"","From one door… to a nation's web!"),
   WOW("A \"bank\" can be a great <b>web-weaver</b>. <b>Axis Bank</b> opened in 1994 (first as UTI Bank, renamed Axis Bank in 2007) and grew into one of India's largest private banks — weaving the accounts, cards and payment rails that carry a nation's daily messages."),
   TL([("1994","A brand-new private bank opens its doors and starts weaving the web."),
       ("2007","It takes the name we know today — Axis Bank."),
       ("Over the years","It grows into one of India's biggest private banks — accounts, cards, taps everywhere."),
       ("Tomorrow","It works to keep every strand of the web safe and trusted. 🕸️")]),
   NOTE("Charlotte's Secret Notebook","Axis Bank (1994, first called UTI Bank) grew into one of India's biggest private banks. It weaves the web of accounts, cards and rails that carry a whole country's little money-messages. 🏦"),
 ]),
 ("c9","CHAPTER 9","The Castle on the Web","pages 71-80",[
   P("ax_c9_castle","Two kind old men appeared with a glow. Warren pointed at a castle standing on a glowing web of light. \"What keeps rivals out, Charlotte?\"","Walls! But what kind?"),
   MOAT([("🕸️","Wall One: The Web Itself","Millions of wallets, cards and shops are already linked. A rival must build the WHOLE web first — but no one joins an empty web, and no web forms without people. Hard to build, easy to use.",False),
         ("🏦","Wall Two: Trust, Built Slowly","People keep their money where they trust it — and trust takes years to earn. Decades of accounts and steady service can't be copied overnight.",False),
         ("📌","Wall Three: Easy In, Hard to Leave","Once your salary, your bills and your taps all run through one web, switching is a real bother. The web is easy to use and quietly hard to leave.",False),
         ("⚠️","The Crack in the Wall","A web of trust breaks if one strand is careless. One weak lock, one sloppy mistake, and the trust that took years to build can fray in a day.",True)]),
   P("ax_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 payments web strong, imagine how it could FAIL — a careless strand, a broken lock, trust let slip — then carefully guard against each one. Protect the trust first, because the whole web is only as strong as its weakest strand."),
   P("ax_c9_verdict","Warren nodded. \"It's woven into everyone's day and grows itself — a mighty castle, so long as it guards the trust that holds every strand together.\"","I SEE the whole picture!"),
   NOTE("Charlotte's Secret Notebook · The Big Secret","The web itself is the moat: hard to build, easy to use, and hard to leave. But it lives on TRUST — one careless strand and it frays. Charlie's trick: picture how you'd lose (a broken lock, sloppy care), then never do it. Invert! 🏰"),
 ]),
 ("c10","CHAPTER 10","The Messages All Around Us","pages 81-88",[
   P("ax_c10_wake","Charlotte woke in her own bed. The glowing hall was gone… but the card on her desk shimmered softly.","Was it real? It FELT real…"),
   P("ax_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 messages moving all around you. Well done."'),
   P("ax_c10_look","She ran out into the evening market. Every tap, every beep, every little card — each one, quietly, was a message moving money.","It was messages the whole time — I just couldn't see them!"),
   WOW("Next time you hear a card go <i>beep</i>, you'll know the secret: money didn't fly — a <b>message</b> did. Take a little, add a little, checked and balanced in a blink, along a web that grows itself. That's <b>the web of wallets.</b> 💳✨"),
   NOTE("Charlotte's Secret Notebook · What I Learned","➊ Paying is sending a MESSAGE: take a little here, add a little there.<br>➋ Every wallet must balance — the two halves always match.<br>➌ Under one tap: card, account and the rails that check and settle in a blink.<br>➍ More shops → more cards → more shops: the web grows itself.<br>➎ Axis Bank weaves that web; but Charlie's trick — picture how you'd lose (a careless strand), then guard the trust. 💛"),
 ]),
]

HOOK=("ax_c1_swirl","EVERY ORDINARY THING HIDES A SECRET.",
 "Charlotte learned that money moves as a message. But the compass is twitching again — this time toward the little glass phone in her pocket, where a voice can leap across the whole world in a heartbeat. How does a voice fly through the empty air?",
 "NEXT ADVENTURE · Catching a Voice from the Air →")

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="#c0257e">MONEY IS A MESSAGE</text>
<g><circle cx="120" cy="150" r="34" fill="#f6b53f" stroke="#c0257e" stroke-width="4"/><text x="120" y="112" text-anchor="middle" font-family="Baloo 2" font-size="15" fill="#c0257e">WALLET A</text><text x="120" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">you tap your card</text></g>
<g stroke="#2563eb" stroke-width="5" fill="#2563eb"><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="#2563eb">take a little</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="#2563eb">THE NETWORK</text><text x="395" y="165" text-anchor="middle" font-family="Bangers" font-size="24" fill="#2563eb">checks it</text><text x="395" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">settles in a blink</text></g>
<g stroke="#2aa15a" stroke-width="5" fill="#2aa15a"><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="#2aa15a">add a little</text>
<g><rect x="620" y="112" width="150" height="90" rx="12" fill="#2aa15a" stroke="#171717" stroke-width="4"/><text x="695" y="102" text-anchor="middle" font-family="Baloo 2" font-size="16" fill="#c0257e">WALLET B</text><text x="695" y="165" text-anchor="middle" font-family="Bangers" font-size="22" fill="#f6b53f">shop paid</text><text x="695" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">up by the same little bit</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">Nothing solid travels &#8594; a MESSAGE does: take a little from one wallet, add it to another &#8594; checked &amp; settled in a blink.</text>
<text x="410" y="343" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">Wallet A goes down by exactly what Wallet B goes up — so every wallet stays balanced.</text>
</svg><div class="figcap">Paying doesn't move money — it sends a message: take a little from one wallet, add it to another, checked and balanced in a blink.</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_wanda"); 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/axis/_head.html").read()
    tail=open("/root/omahaindia.com/comics/site/book/axis/_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()
