#!/usr/bin/env python3
# Book 43 (Tech Mahindra) — THE VOICE ON THE OTHER END. Science->business: a VOICE becomes a NUMBER
# becomes a PULSE OF LIGHT racing down a hair-thin glass thread (fibre), bouncing along by total
# internal reflection, then becomes a voice again — all in a heartbeat, across oceans. The company
# that BUILDS AND RUNS the systems telecom companies lean on.
import os
ART="/root/omahaindia.com/comics/site/book/techm/art"
OUT="/root/omahaindia.com/comics/site/book/techm/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"
OWEN=("Owen, a warm friendly Western NETWORK ENGINEER, NOT Indian, kind steady eyes and an easy smile, "
"a teal shirt with the sleeves rolled up, a slim headset over one ear, a neat coil of glowing fibre-optic cable 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,4300,f"{STYLE}. BOOK COVER, {CHARLOTTE} standing with {OWEN} inside a glowing network hub, holding up a hair-thin loop of glass fibre with a bright pulse of light racing through it, ribbons of coloured light streaming out toward a distant city and across a dark ocean, wonder, cinematic","charlotte"),
 "_ref_owen":(1024,1024,4301,f"{STYLE}. clean friendly character portrait, {OWEN}, plain soft warm background, kind smile, head and shoulders",None),
 # Ch1
 "te_c1_coin":(1024,720,4310,f"{STYLE}. {CHARLOTTE} at home, Grandpa Ben's glowing brass compass twitching between a little telephone handset and a bright thread of light on the table, EXPRESSION puzzled and intrigued, cozy lamp light","charlotte"),
 "te_c1_diary":(1024,720,4311,f"{STYLE}. an open magical diary glowing warm gold on a desk, a faint ribbon of light lifting off the page and curling into a tiny bright spark, no people",None),
 "te_c1_swirl":(1024,720,4312,f"{STYLE}. {CHARLOTTE} pulled into a swirling spiral of golden light and streaming ribbons of colour from a glowing diary, EXPRESSION thrilled, magical","charlotte"),
 # Ch2 — arrive at the network hub, meet Owen
 "te_c2_arrive":(1024,720,4313,f"{STYLE}. {CHARLOTTE} landing wide-eyed inside an enormous humming network hub, tall racks of softly blinking lights and rivers of glowing cables running to the ceiling, EXPRESSION awe and delight, cool bright glow","charlotte"),
 "te_c2_owen":(1024,720,4314,f"{STYLE}. {OWEN} warmly welcoming {CHARLOTTE} at the hub, offering her the glowing coil of fibre, EXPRESSION Charlotte shy happy smile; keep the SAME network engineer from the reference, same teal shirt with rolled sleeves, same headset, same glowing fibre coil","owen"),
 "te_c2_hub":(1024,720,4315,f"{STYLE}. a vast network operations hall seen wide, endless aisles of blinking equipment and bundles of shining fibre, tiny figures walking between them for scale, powerful and awe-inspiring, no faces close up",None),
 # Ch3 — a voice becomes a number
 "te_c3_listen":(1024,720,4316,f"{STYLE}. {OWEN} speaking gently into his headset, soft glowing sound-wave ripples spreading from his lips, showing {CHARLOTTE} how a voice makes waves, EXPRESSION Charlotte fascinated leaning in; SAME network engineer, teal shirt, headset","owen"),
 "te_c3_wave":(1024,720,4317,f"{STYLE}. a friendly glowing sound wave rippling across the frame, being gently sliced into a neat row of tiny measuring dots, playful science, warm blue light, no people",None),
 "te_c3_numbers":(1024,720,4318,f"{STYLE}. a friendly close up of a glowing sound wave turning into a flowing stream of tiny sparkling numbers, as if the voice is being written down as counting, playful science, no people",None),
 # Ch4 — a number becomes light
 "te_c4_flash":(1024,720,4319,f"{STYLE}. {CHARLOTTE} watching a stream of glowing numbers turn into quick flashes of light — blink, dark, blink, blink — dancing in the air, EXPRESSION eager and curious, cool bright glow","charlotte"),
 "te_c4_code":(1024,720,4320,f"{STYLE}. a friendly little machine translating a ribbon of numbers into on-and-off pulses of bright light, tidy rows of light dots like a secret code, warm storybook style, no people",None),
 "te_c4_pulse":(1024,720,4321,f"{STYLE}. a beautiful close up of a single brilliant pulse of light diving into the polished end of a hair-thin glass thread, glowing tunnel of glass, dark rim bright centre, no people",None),
 # Ch5 — the glass thread: light bounces along, never escaping
 "te_c5_thread":(1024,720,4322,f"{STYLE}. a single hair-thin strand of clear glass fibre glowing from within as a pulse of light streaks along inside it, sparkles trailing behind, dark background bright thread, no people",None),
 "te_c5_bounce":(1024,720,4323,f"{STYLE}. {OWEN} showing {CHARLOTTE} a magical cutaway of a glass fibre where a beam of light zig-zags along, bouncing off the smooth inner walls and never leaking out, EXPRESSION Charlotte eyes wide with delight; SAME network engineer, teal shirt, headset","owen"),
 # Ch6 — light becomes a voice again, in a heartbeat
 "te_c6_arrive":(1024,720,4324,f"{STYLE}. {CHARLOTTE} at the far end of the thread, watching pulses of light stream out and unfold back into a river of glowing numbers, EXPRESSION astonished and glad, cool bright glow","charlotte"),
 "te_c6_voice":(1024,720,4325,f"{STYLE}. glowing numbers flowing back into a warm sound wave that lifts softly out of a friendly speaker, a voice reborn from light, gentle golden ripples, no people",None),
 # Ch7 — across the whole world
 "te_c7_world":(1024,720,4326,f"{STYLE}. a joyful nighttime globe laced with glowing threads of light connecting cities across oceans, homes, a school, a hospital all lit and linked, warm togetherness, no faces close up",None),
 "te_c7_ocean":(1024,720,4327,f"{STYLE}. a warm storybook cutaway of the deep ocean floor with a glowing fibre cable stretching between two continents, pulses of light racing through it under the waves, gentle and grand, no people",None),
 # Ch8 — reveal Tech Mahindra
 "te_c8_reveal":(1024,720,4328,f"{STYLE}. {CHARLOTTE} and {OWEN} standing proudly before a great glowing network operations centre and tall telecom towers against a blue sky, EXPRESSION proud recognition; SAME network engineer, teal shirt, headset","charlotte"),
 "te_c8_founded":(1024,720,4329,f"{STYLE}. warm sepia 1980s scene, hopeful engineers gathering around early telephone exchanges and switchboards to build the systems that carry voices, inspiring, no text",None),
 "te_c8_scale":(1024,720,4330,f"{STYLE}. a bright modern control room at golden hour, huge world-map screens glowing with live network links, calm engineers keeping the world's calls flowing, proud and hi-tech, no faces close up",None),
 # Ch10 (ch9 uses ritual castle/invert/verdict; ch10 uses ritual wake/diary)
 "te_c10_look":(1024,720,4331,f"{STYLE}. {CHARLOTTE} outside at dusk holding a small phone, smiling as glowing threads of light seem to rise from every window, lamp and passing person around her, knowing each voice is racing as light, 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 Voice That Crossed the Ocean","pages 1-8",[
   P("te_c1_coin","Back home, Grandpa Ben's compass twitched again — pointing between an old telephone and a thin thread of light.","A telephone… and a beam of light? What's the link?",None,"twitch"),
   P("te_c1_diary","The old diary fell open. A new line shimmered in Grandpa Ben's hand.",None,'"Find how a voice can fly across an ocean faster than a blink."'),
   WOW("You say \"hello\" into a phone, and a friend an ocean away hears it almost instantly. But your voice can't swim the sea! So what actually rushes across the world in that heartbeat? That's the puzzle of this whole adventure."),
   P("te_c1_swirl","Golden light swirled up and pulled Charlotte in.","Here we GO!",None,"WHOOSH","#2563eb"),
   NOTE("Charlotte's Secret Notebook","Two BIG questions:<br>➊ How does a voice cross a whole ocean in less than a blink?<br>➋ Grandpa Ben drew a thread of <i>light</i>. What has light got to do with talking? 💡"),
 ]),
 ("c2","CHAPTER 2","The Room Full of Light","pages 9-16",[
   P("te_c2_arrive","One blink, and she stood in the biggest, busiest room she'd ever seen — walls of blinking lights and rivers of glowing cables.","It's a whole city made of LIGHT and wires!"),
   P("te_c2_owen","A friendly man in a teal shirt waved, a coil of glowing thread in his hand. \"I'm Owen, a network engineer. In here, we send voices as light.\"","Voices as… LIGHT?!"),
   P("te_c2_hub","All around, thin shining threads carried tiny sparks racing faster than she could follow.","So much rushing light — and it's all people TALKING?","Stick with me, kiddo."),
   NOTE("Charlotte's Secret Notebook","Owen is a network engineer, and he grins like he has a secret — just like the other guides did. He says the glowing threads carry voices as light. Okay Owen… show me how! ✨"),
 ]),
 ("c3","CHAPTER 3","A Voice Becomes a Number","pages 17-26",[
   P("te_c3_listen","Owen spoke into his headset and soft ripples spread from his lips. \"A voice is just wiggles in the air — a wave. Watch what we do with it.\"","A voice is a WAVE?"),
   P("te_c3_wave","\"We measure that wave super fast — thousands of tiny checks every second — and write down each height as a number.\"","So my voice becomes a list of numbers!"),
   P("te_c3_numbers","\"Now your voice isn't a sound any more,\" Owen smiled. \"It's a neat stream of numbers a machine can carry.\"","My 'hello' turned into counting!",None,"tick tick","#2563eb"),
   WOW("Here's the first secret! 💡 A voice is a <b>wave</b> in the air. A machine measures that wave thousands of times a second and writes each measurement as a <b>number</b>. Your voice becomes a tidy stream of numbers — and numbers are easy to send."),
   ("diagram",),
   NOTE("Charlotte's Secret Notebook","A voice is a wave. We measure it thousands of times a second and turn each measurement into a NUMBER. So a voice becomes a stream of numbers. 🔢🗣️"),
 ]),
 ("c4","CHAPTER 4","A Number Becomes Light","pages 27-36",[
   P("te_c4_flash","\"Now the clever bit,\" said Owen. \"We turn those numbers into flashes of light — a flash for on, dark for off.\"","Blink for yes, dark for no — a secret code!"),
   P("te_c4_code","\"Every number becomes a little pattern of blinks,\" he said, \"quick flickers of bright light, faster than you can see.\"","Numbers turned into BLINKS of light!",None,"blink","#2563eb"),
   P("te_c4_pulse","\"And then,\" said Owen, \"we send those flashes diving straight into a thread of glass.\"","Light… going INTO glass?"),
   WOW("The stream of numbers is turned into <b>pulses of light</b> — a flash means one, dark means zero. Those flickers blink far too fast for your eyes, and they carry your whole voice. Then they're fired into a thin thread of <b>glass.</b>"),
   NOTE("Charlotte's Secret Notebook · SOLVED (part 1)","Numbers get turned into flashes of light — flash for ON, dark for OFF, blinking too fast to see. Then the light is sent into a thread of glass. Voice → numbers → LIGHT! ✨"),
 ]),
 ("c5","CHAPTER 5","The Glass Thread","pages 37-44",[
   P("te_c5_thread","Owen held up a thread of glass as thin as a hair. Inside it, a pulse of light streaked along in a blur.","So THIN — and the light zooms right through it!",None,"zzzip","#2563eb"),
   P("te_c5_bounce","\"The light bounces along the smooth inside walls,\" he said, \"never leaking out — so it races for miles and miles without getting lost.\"","It's bouncing like a ball down a slide!"),
   WOW("This glass thread is called <b>fibre</b>. Light poured in at just the right angle <b>bounces along the smooth inner walls</b> and never escapes — so it can race for hundreds of miles, even under whole oceans, carrying your voice as light."),
   NOTE("Charlotte's Secret Notebook","The glass thread is called FIBRE. Light bounces along its smooth inside walls and never leaks out, so it can travel miles and miles — even under the sea. 🪞💡"),
 ]),
 ("c6","CHAPTER 6","A Voice Again","pages 45-52",[
   P("te_c6_arrive","At the far end, the flashes of light spilled out and unfolded back into a stream of numbers.","The light is turning back into numbers!"),
   P("te_c6_voice","\"And the numbers become a wave again,\" said Owen, \"which a little speaker wiggles into sound. Your friend hears your voice!\"","So THAT'S how they hear me!"),
   WOW("At the other end it all runs backwards: light → numbers → a wave → a <b>voice</b> again, out of a speaker. Voice → numbers → light → glass → light → numbers → voice — and the whole journey happens in a <b>heartbeat.</b> What a trip!"),
   NOTE("Charlotte's Secret Notebook · SOLVED!","At the far end: light becomes numbers, numbers become a wave, the speaker turns it back into a VOICE. The whole chain: VOICE → numbers → light → glass → light → numbers → VOICE! ⚡"),
 ]),
 ("c7","CHAPTER 7","Across the Whole World","pages 53-60",[
   P("te_c7_world","Owen swept his arm across a glowing globe. Cities everywhere were stitched together with threads of light.","The whole WORLD is joined by light!"),
   P("te_c7_ocean","\"Under the oceans,\" said Owen, \"long glass cables carry these pulses between continents — remember Airtel's invisible threads? This is what rushes along them.\"","Light racing right under the sea!"),
   WOW("This isn't a small thing. Threads of light run <b>under the oceans</b>, linking continent to continent, so a child in one country can talk to a grandparent in another in a heartbeat. Book 4's Airtel strung invisible threads — and it's <b>light</b> that races along them."),
   NOTE("Charlotte's Secret Notebook","Glass cables run under the oceans, carrying pulses of light between continents. That's how a voice crosses the whole world in a blink. Just like Airtel's invisible threads! 🌏💡"),
 ]),
 ("c8","CHAPTER 8 · THE BIG DISCOVERY","The Company Behind the Voice","pages 61-70",[
   P("te_c8_reveal","Owen led Charlotte to a viewpoint over a huge control centre and tall telecom towers.","But who BUILDS and looks after all of this?"),
   P("te_c8_founded","\"Back in 1986,\" said Owen, \"a company set out to help build the systems that carry voices.\"","Somebody has to make it all work!"),
   P("te_c8_scale","\"It grew and grew,\" he said, \"until it helped run the networks that phone companies all over the world depend on.\"","They keep the whole world talking!"),
   WOW("A \"company\" can be a giant shared job. <b>Tech Mahindra</b> began in 1986 and grew into a builder and runner of the <b>systems telecom companies lean on</b> — the software and know-how that keep calls and messages flowing worldwide."),
   TL([("1986","A company sets out to help build the systems that carry voices."),
       ("Over decades","It grows into a builder and runner of telecom networks used around the world."),
       ("Today","Its engineers help keep the world's calls and messages flowing."),
       ("Tomorrow","It keeps learning the newest tech — faster networks and smarter software. 📡")]),
   NOTE("Charlotte's Secret Notebook","Tech Mahindra (1986) builds and RUNS the systems that telecom companies depend on — the software and know-how behind the calls. It helps keep the whole world talking. 🏆"),
 ]),
 ("c9","CHAPTER 9","The Castle of Know-How","pages 71-80",[
   P("te_c9_castle","Two kind old men appeared with a glow. Warren pointed at a castle standing on a field of glowing network towers. \"What keeps rivals out, Charlotte?\"","Walls! But what kind?"),
   MOAT([("🧠","Wall One: Deep Know-How","Running a telecom network takes years of hard-won knowledge. You can't just pick it up overnight — and that deep skill is very hard to copy.",False),
         ("📜","Wall Two: Long Contracts","Telecom companies sign long deals and let the systems get woven deep into how they work. Swapping them out would be slow and risky — so they stay.",False),
         ("🌐","Wall Three: Woven Into Everything","When networks whole countries rely on run on your systems, you're hard to replace quickly. The calls simply must not stop.",False),
         ("⚠️","The Crack in the Wall","Technology shifts FAST. Yesterday's clever skill can go stale in a few years. A company like this must keep learning, or the world races ahead without it.",True)]),
   P("te_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 tech giant strong, imagine how it could FADE — resting on old skills while faster new technology arrives, or letting a network fail — then carefully avoid each one, and keep learning the newest tricks early."),
   P("te_c9_verdict","Warren nodded. \"Deep know-how and long contracts make a fine castle — so long as it keeps learning, because in tech the walls can crumble fast.\"","I SEE the whole picture!"),
   NOTE("Charlotte's Secret Notebook · The Big Secret","Tech Mahindra is hard to copy: DEEP know-how, LONG contracts, and it's woven into everything. But tech changes FAST — yesterday's skill can go stale, so it must keep learning. Charlie's trick: picture how you'd lose (resting on old skills), then never do it. Invert! 🏰"),
 ]),
 ("c10","CHAPTER 10","The Voice on the Other End","pages 81-88",[
   P("te_c10_wake","Charlotte woke in her own bed. The humming hub was gone… but her little phone screen glowed softly.","Was it real? It FELT real…"),
   P("te_c10_diary","On the diary's page, a new line glowed — as if Grandpa Ben wrote it just for her.",None,'"Now you know what races along the invisible threads. Well done."'),
   P("te_c10_look","She called a friend far away. \"Hi!\" came the voice — and Charlotte grinned, knowing it had just travelled as light across the world.","There's a whole light-journey behind every 'hello'!"),
   WOW("Next time you hear a voice on the other end, you'll know the secret: it flew to you as <b>light</b>. Your voice became numbers, became flashes of light, bounced down a glass thread across the ocean, and became a voice again — in a heartbeat. That's <b>the voice on the other end.</b> 💡🗣️"),
   NOTE("Charlotte's Secret Notebook · What I Learned","➊ A voice is a wave; measured fast, it becomes a stream of NUMBERS.<br>➋ Numbers become flashes of LIGHT — flash for on, dark for off.<br>➌ Light bounces down a glass FIBRE thread, even under oceans, then turns back into a voice.<br>➍ It all happens in a heartbeat, joining the whole world.<br>➎ Tech Mahindra builds and runs those systems; but Charlie's trick — picture how you'd lose (resting on old skills), then keep learning. 💛"),
 ]),
]

HOOK=("te_c1_swirl","EVERY ORDINARY THING HIDES A SECRET.",
 "Charlotte learned how a voice flies across the world as light. But the compass is twitching again — this time toward the little glowing screen in her pocket, and all the games and words that live inside it. Who writes the secret instructions a machine follows?",
 "NEXT ADVENTURE · The Machine That Follows Rules →")

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">A VOICE BECOMES A PULSE OF LIGHT</text>
<g><circle cx="120" cy="150" r="34" fill="#14a3a3" stroke="#0e7490" stroke-width="4"/><text x="120" y="112" text-anchor="middle" font-family="Baloo 2" font-size="15" fill="#0e7490">A VOICE</text><text x="120" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">you speak — a wave in the air</text></g>
<g stroke="#14a3a3" stroke-width="5" fill="#14a3a3"><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="#14a3a3">MEASURE THE WAVE</text><text x="395" y="165" text-anchor="middle" font-family="Bangers" font-size="26" fill="#14a3a3">NUMBERS</text><text x="395" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">thousands of checks a second</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">flash = on, dark = off</text>
<text x="540" y="182" text-anchor="middle" font-family="Nunito" font-size="12" fill="#555">faster than you can see</text>
<g><rect x="620" y="112" width="150" height="90" rx="12" fill="#37414d" stroke="#171717" stroke-width="4"/><text x="695" y="102" text-anchor="middle" font-family="Baloo 2" font-size="16" fill="#f6b53f">LIGHT</text><text x="695" y="165" text-anchor="middle" font-family="Bangers" font-size="24" fill="#f6b53f">pulses</text><text x="695" y="235" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">blinks of light down glass</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">The light bounces down a glass thread across the ocean &#8594; back into NUMBERS &#8594; back into a VOICE.</text>
<text x="410" y="343" text-anchor="middle" font-family="Nunito" font-size="13" fill="#555">The voice you hear set out as light just moments ago, oceans away — all in a heartbeat.</text>
</svg><div class="figcap">A voice is measured into numbers, the numbers become pulses of light, the light races down glass and turns back into a voice.</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_owen"); 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/techm/_head.html").read()
    tail=open("/root/omahaindia.com/comics/site/book/techm/_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()
