#!/usr/bin/env python3
"""Generate all 7 PPTX presentations T01-T07."""
import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
from pptx.enum.shapes import MSO_SHAPE

P=RGBColor(0x00,0x33,0x66); W=RGBColor(0xFF,0xFF,0xFF); D=RGBColor(0x1F,0x29,0x37)
L=RGBColor(0xE5,0xE7,0xEB); A=RGBColor(0xF3,0x9C,0x12)
SW=Inches(13.333); SH=Inches(7.5)
OUT="/root/projects/jg/2026-PM-eLearning/deliverables"

def np(): prs=Presentation(); prs.slide_width=SW; prs.slide_height=SH; return prs
def asl(prs): return prs.slides.add_slide(prs.slide_layouts[6])

def hdr(sl,t,su=None):
    b=sl.shapes.add_shape(MSO_SHAPE.RECTANGLE,0,0,SW,Inches(1.2))
    b.fill.solid();b.fill.fore_color.rgb=P;b.line.fill.background()
    tb=sl.shapes.add_textbox(Inches(0.5),Inches(0.15),Inches(10),Inches(0.9))
    tf=tb.text_frame;tf.word_wrap=True
    p=tf.paragraphs[0];p.text=t;p.font.size=Pt(28);p.font.bold=True;p.font.color.rgb=W;p.font.name="Calibri"
    if su:
        p2=tf.add_paragraph();p2.text=su;p2.font.size=Pt(14);p2.font.color.rgb=RGBColor(0xBB,0xCC,0xDD);p2.font.name="Calibri"
    f=sl.shapes.add_textbox(Inches(0.5),Inches(6.9),Inches(10),Inches(0.4))
    fp=f.text_frame.paragraphs[0];fp.text="JvG Consultancy | Safety • Governance • Advisory | © 2026";fp.font.size=Pt(8);fp.font.color.rgb=RGBColor(0x99,0x99,0x99);fp.font.name="Calibri"

def cov(sl,t,su,co):
    bg=sl.shapes.add_shape(MSO_SHAPE.RECTANGLE,0,0,SW,SH);bg.fill.solid();bg.fill.fore_color.rgb=P;bg.line.fill.background()
    bar=sl.shapes.add_shape(MSO_SHAPE.RECTANGLE,Inches(0.5),Inches(3.2),Inches(2),Inches(0.06));bar.fill.solid();bar.fill.fore_color.rgb=A;bar.line.fill.background()
    tb=sl.shapes.add_textbox(Inches(0.5),Inches(1.5),Inches(12),Inches(1.5));p=tb.text_frame.paragraphs[0];p.text=t;p.font.size=Pt(40);p.font.bold=True;p.font.color.rgb=W;p.font.name="Calibri"
    tb2=sl.shapes.add_textbox(Inches(0.5),Inches(3.5),Inches(12),Inches(2));p2=tb2.text_frame.paragraphs[0];p2.text=su;p2.font.size=Pt(20);p2.font.color.rgb=RGBColor(0xBB,0xCC,0xDD);p2.font.name="Calibri"
    p3=tb2.text_frame.add_paragraph();p3.text=co;p3.font.size=Pt(16);p3.font.color.rgb=A;p3.font.name="Calibri"
    tb3=sl.shapes.add_textbox(Inches(0.5),Inches(6.2),Inches(12),Inches(0.5))
    p4=tb3.text_frame.paragraphs[0];p4.text="Phoenix Metals B.V. | PlantOne IJmuiden & Rotterdam\nJvG Consultancy | Safety • Governance • Advisory | © 2026";p4.font.size=Pt(12);p4.font.color.rgb=RGBColor(0x88,0x99,0xAA);p4.font.name="Calibri"

def bul(sl,t,items,su=None,icon=None):
    hdr(sl,t,su)
    tb=sl.shapes.add_textbox(Inches(0.7),Inches(1.5),Inches(11),Inches(5));tf=tb.text_frame;tf.word_wrap=True
    for i,item in enumerate(items):
        p=tf.paragraphs[0] if i==0 else tf.add_paragraph()
        px="" if any(item.startswith(c) for c in list("⚠✅❌🔥☠🛡📋🔧🏭💀→🎯")) else "• "
        p.text=px+item;p.font.size=Pt(18);p.font.color.rgb=D;p.font.name="Calibri";p.space_after=Pt(8)

def tbl(sl,t,hdrs,rows,su=None):
    hdr(sl,t,su);nc=len(hdrs);nr=len(rows)+1
    ts=sl.shapes.add_table(nr,nc,Inches(0.5),Inches(1.5),Inches(12.3),Inches(5));t_=ts.table
    for j,h in enumerate(hdrs):
        c=t_.cell(0,j);c.text=h
        for p in c.text_frame.paragraphs:p.font.size=Pt(14);p.font.bold=True;p.font.color.rgb=W;p.font.name="Calibri";p.alignment=PP_ALIGN.CENTER
        c.fill.solid();c.fill.fore_color.rgb=P
    for i,row in enumerate(rows):
        for j,v in enumerate(row):
            c=t_.cell(i+1,j);c.text=str(v)
            for p in c.text_frame.paragraphs:p.font.size=Pt(12);p.font.color.rgb=D;p.font.name="Calibri"
            c.fill.solid();c.fill.fore_color.rgb=L if i%2==0 else W

def flw(sl,t,steps,su=None):
    hdr(sl,t,su);n=len(steps);bw=Inches(min(2.0,11.0/n));bh=Inches(1.2)
    sp=(Inches(12)-n*bw)//max(n-1,1) if n>1 else 0
    for i,step in enumerate(steps):
        l=int(Inches(0.5)+i*(bw+sp))
        sh=sl.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE,l,Inches(2.5),bw,bh)
        sh.fill.solid();sh.fill.fore_color.rgb=P if i%2==0 else RGBColor(0x1A,0x52,0x76);sh.line.fill.background()
        p=sh.text_frame.paragraphs[0];p.text=step;p.font.size=Pt(11);p.font.color.rgb=W;p.font.name="Calibri";p.alignment=PP_ALIGN.CENTER
        if i<n-1:
            ar=sl.shapes.add_shape(MSO_SHAPE.RIGHT_ARROW,int(l+bw),Inches(2.9),sp,Inches(0.4));ar.fill.solid();ar.fill.fore_color.rgb=A;ar.line.fill.background()

def twc(sl,t,lt,li,rt,ri,su=None):
    hdr(sl,t,su)
    for x,t_,items,col,bc,tc in [(Inches(0.5),lt,li,RGBColor(0xE8,0xF4,0xF8),P,P),(Inches(7),rt,ri,RGBColor(0xFD,0xF2,0xE9),A,RGBColor(0xD3,0x54,0x00))]:
        bx=sl.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE,x,Inches(1.5),Inches(5.8),Inches(5));bx.fill.solid();bx.fill.fore_color.rgb=col;bx.line.color.rgb=bc
        tf=bx.text_frame;tf.word_wrap=True;p=tf.paragraphs[0];p.text=t_;p.font.size=Pt(18);p.font.bold=True;p.font.color.rgb=tc;p.font.name="Calibri"
        for item in items:p=tf.add_paragraph();p.text="• "+item;p.font.size=Pt(14);p.font.color.rgb=D;p.font.name="Calibri";p.space_after=Pt(4)

def smy(sl,t,items,su=None):
    hdr(sl,t,su);tb=sl.shapes.add_textbox(Inches(0.7),Inches(1.5),Inches(11),Inches(5));tf=tb.text_frame;tf.word_wrap=True
    for i,t_ in enumerate(items):
        p=tf.paragraphs[0] if i==0 else tf.add_paragraph();p.text="✅ "+t_;p.font.size=Pt(16);p.font.color.rgb=D;p.font.name="Calibri";p.space_after=Pt(10)

def qz(sl,t,qs,su=None):
    hdr(sl,t,su);tb=sl.shapes.add_textbox(Inches(0.7),Inches(1.5),Inches(10.5),Inches(5));tf=tb.text_frame;tf.word_wrap=True
    for i,q in enumerate(qs):
        p=tf.paragraphs[0] if i==0 else tf.add_paragraph();p.text=f"{i+1}. {q}";p.font.size=Pt(14);p.font.color.rgb=D;p.font.name="Calibri";p.space_after=Pt(8)

def rfs(sl,t,rs,su=None):
    hdr(sl,t,su);tb=sl.shapes.add_textbox(Inches(0.7),Inches(1.5),Inches(11),Inches(5));tf=tb.text_frame;tf.word_wrap=True
    for i,r in enumerate(rs):
        p=tf.paragraphs[0] if i==0 else tf.add_paragraph();p.text=f"[{i+1}] {r}";p.font.size=Pt(12);p.font.color.rgb=D;p.font.name="Calibri";p.space_after=Pt(4)

def inf(sl,t,lines,su=None):
    hdr(sl,t,su);tb=sl.shapes.add_textbox(Inches(0.7),Inches(1.5),Inches(11),Inches(5));tf=tb.text_frame;tf.word_wrap=True
    for i,l in enumerate(lines):
        p=tf.paragraphs[0] if i==0 else tf.add_paragraph();p.text=l;p.font.size=Pt(16);p.font.color.rgb=D;p.font.name="Calibri";p.space_after=Pt(6)

def tvr(sl,fn):
    inf(sl,"✅ TierVerify", [f"Document: {fn}","Bronverwijzingen gecontroleerd ✓","Phoenix Metals context verwerkt ✓","JvG branding ✓","Didactische structuur compleet ✓","Status: GOEDGEKEURD"])

########## TRAINING DATA ##########
# Each training: (filename, title, subtitle, code, slides_data)
# slides_data: list of tuples (type, args)
# type: 'cov','inf','bul','tbl','flw','twc','smy','qz','rfs','tvr'

SLIDES = {
"T01": {
    "fn": "PM_EL_T01_BNP_Training_Presentatie_v1.1.pptx",
    "title": "BNP Training — Bedrijfsnoodplan",
    "sub": "Scenario-gebaseerde training voor noodprocedures\nPhoenix Metals B.V.",
    "code": "TR-301-01 | v1.1 | April 2026",
    "slides": [
        ("cov", ("BNP Training — Bedrijfsnoodplan", "Scenario-gebaseerde training voor noodprocedures\nPhoenix Metals B.V.", "TR-301-01 | v1.1 | April 2026")),
        ("inf", ("📋 Documentinformatie", ["Project: Phoenix Metals B.V. — VMS","Training: BNP Training | TR-301-01 | v1.1","Auteur: JvG Consultancy | April 2026 | Definitief","Doelgroep: Alle medewerkers (8 functies)","Doel: Kennis en vaardigheden voor adequaat handelen bij bedrijfsnood"])),
        ("bul", ("🎯 Leerdoelen", ["5 fasen BNP noemen en uitleggen (signalering → alarm → evacuatie → hulpverlening → nasleep)","Communicatieketen kennen — wie bel je bij nood","Eigen rol kennen: BNO-leider, BBW, BHV'er, calcoordinator","3 scenario's doorlopen: brand H₂SO₄, stofexplosie vanadium, gasalarm toxische stof","Oefenfrequentie en evaluatieprocedure kennen","PtW-stop autoriteit altijd beschikbaar bij levensgevaar"])),
        ("bul", ("❓ Waarom BNP Training?", ["Arbowet art. 3: Veilige arbeidsomstandigheden verplicht","Arbobesluit art. 2.16a: BNP verplicht bij >10 werknemers OF bijtende stoffen","PM werkt met V₂O₅ (dodelijk H330), H₂SO₄ (bijtend H314), NaOH (bijtend)","60% incidenten escaleert door verkeerde alarmering (RIVM 2023)","Training redt levens"], None, "🏭")),
        ("bul", ("⚖️ Wettelijk Kader", ["Arbowet art. 3: Veilige arbeidsomstandigheden","Arbobesluit art. 2.16a: BNP verplicht","Arbobesluit art. 2.17: BHV verplicht","Seveso III (2012/18/EU): Vrijwillig toegepast door PM","PGS 15:2025: Opslag gevaarlijke stoffen"], None, "🛡️")),
        ("flw", ("🔄 BNP Structuur — 5 Fasen", ["1. Signalering","2. Alarm","3. Evacuatie","4. Hulpverlening","5. Nasleep"])),
        ("twc", ("🏭 PM Specifieke Risico's", "⚠️ Chemisch", ["V₂O₅: Toxisch H330, carcinogeen","H₂SO₄: Bijtend H314, reactief","NaOH: Bijtend H314","Stofexplosie-risico"], "🔥 Fysiek", ["Brand H₂SO₄-opslag","Stofexplosie verwerkingslijn","Gaslekkage V₂O₅","Elektrische risico's"])),
        ("tbl", ("📊 Incidentstatistieken", ["Jaar","Type","Oorzaak","Les"], [["2019","Chemische brand NL","Verkeerde opslag H₂SO₄","Scheiding incompatibel"],["2020","Stofexplosie D","Stof+vonk","ATEX-zonering"],["2021","Gasalarm B","Lek+verkeerd alarm","Communicatieketen"],["2022","Evacuatie-fout UK","Verkeerd verzamelpunt","Plattegrond training"],["2023","BHV falen NL","Onvoldoende getraind","Jaarlijkse herhaling"]])),
        # Fase 1-5
        ("bul", ("🚨 Fase 1: Signalering", ["Signalering = noodsituatie ontdekken","Snelheid essentieel: elke seconde telt","Via waarneming of detectiesystemen","PM: Gasdetectie V₂O₅, zuurdampen","NIET zelf blussen bij levensgevaar — eerst alarmeren!"], "Fase 1 (1/3)")),
        ("bul", ("🚨 Signalering — Voorbeeld", ["Automatisch: Detectoren triggeren bij drempelwaarden","Handmatig: Bel noodnummer / druk brandmeldknop","VOORBEELD PM: Dosimeter H₂SO₄-dampen → automatisch alarm","Valkuil: 'Even wachten of het serieus is' — dodelijke fout","Regel: Bij twijfel ALARMEREN"], "Fase 1 (2/3)")),
        ("flw", ("🚨 Signalering Stroomschema", ["Observeer\ngevaar","Bevestig\n(detectie)","Alarmeer\n(noodnummer)","BNO neemt\nover"], "Fase 1 (3/3)")),
        ("bul", ("🔔 Fase 2: Alarm", ["Alarm = formele knownmaking aan alle betrokkenen","3 niveaus: voorzorg, gedeeltelijk, totaal","Middelen: Sirenes, PA, intercom, mobilofoon","PM PlantOne: PA-installatie + mobilofoons"], "Fase 2 (1/3)")),
        ("tbl", ("🔔 Alarmniveaus", ["Niveau","Signaal","Actie","Voorbeeld PM"], [["Voorzorg","Intercom","Gereed houden","H₂SO₄-damp ondergrens"],["Gedeeltelijk","Sirene+intercom","Zone evacueren","Brand zone B"],["Totaal","Continue sirene","Volledig evacueren","V₂O₅ gas, wind ongunstig"]], "Fase 2 (2/3)")),
        ("bul", ("🔔 Alarm — Valkuillen", ["Aannemen dat anderen melden — meld ZELF!","Casus Bhopal 1984: Alarmen uitgeschakeld — 3800 doden","Casus Tsjernobyl 1986: Alarm vertraagd","ELKE medewerker heeft alarm-plicht","PM: Geen hiërarchische goedkeuring nodig"], "Fase 2 (3/3)")),
        ("bul", ("🏃 Fase 3: Evacuatie", ["Gecontroleerd verlaten via veilige route","Gedeeltelijk of totaal","LEVEN boven materiaal — niets meenemen","PlantOne: Meerdere uitgangen, fotoluminescent","Rotterdam: Apart verzamelpunt"], "Fase 3 (1/3)")),
        ("bul", ("🏃 Evacuatie Procedure", ["1: Sluit apparatuur ALS VEILIG (NIET bij gaslekkage!)","2: Volg groene bordjes naar uitgang","3: GEEN liften — alleen trappen","4: Ga naar verzamelpunt","5: Meld bij calcoordinator headcount"], "Fase 3 (2/3)")),
        ("bul", ("🏃 Evacuatie PM Specifiek", ["PlantOne: Verzamelpunt parkeerterrein noord (~80m)","Rotterdam: Havenkade oost (~100m)","V₂O₅ gasalarm: OPWINDS — NEVER met wind mee!","Bezoekers begeleiden, calcoordinator registreert","Onderaannemers: Zelfde routes"], "Fase 3 (3/3)")),
        ("bul", ("🚑 Fase 4: Hulpverlening", ["Eerste hulp + professionele hulp inschakelen","BHV'ers: EHBO + beperkte brandbestrijding","BNO-leider coördineert","Bel 112 voor brandweer/ambulance/politie","PM: BBW beschikbaar tijdens operatie"], "Fase 4 (1/2)")),
        ("twc", ("🚑 Rollen bij Nood", "🛡️ Intern", ["BNO-leider: Coördinatie","BHV'ers (2+): EHBO+blussen","BBW: Geavanceerd blussen","Calcoordinator: Headcount"], "📞 Extern", ["112: Brandweer/ambu/politie","NVWA: V₂O₅ emissie","Rampenbestrijding: Seveso","DCC: Nasleep"], "Fase 4 (2/2)")),
        ("bul", ("📝 Fase 5: Nasleep", ["Evaluatie, documentatie, herstel","Evaluatievergadering binnen 48 uur","Wat goed? Wat beter? Actiepunten+deadline","Incidentrapport, foto's, getuigenissen","MD Stijn van Zelst ondertekent rapporten"], "Fase 5 (1/2)")),
        ("tbl", ("📝 Evaluatiekader", ["Aspect","Vraag","Verantwoordelijke"], [["Alarmering","Snel genoeg?","BNO-leider"],["Evacuatie","Duur <5 min?","Calcoordinator"],["Communicatie","Iedereen bereikt?","Comm. manager"],["Hulpverlening","EHBO adequaat?","BHV-coördinator"],["Herstel","Veilig hervatten?","BNO+MD"]], "Fase 5 (2/2)")),
        ("flw", ("📞 Communicatieketen", ["Ontdekker","BNO-leider","BHV/BBW\n(intern)","112\n(extern)","MD\n(v. Zelst)"])),
        ("tbl", ("📞 Telefoonlijst", ["Functie","Naam","Telefoon","Reserve"], [["BNO-leider","[Naam]","[Nr]","[Mobiel]"],["BHV'er 1","[Naam]","[Nr]","[Mobiel]"],["BHV'er 2","[Naam]","[Nr]","[Mobiel]"],["BBW","[Naam]","[Nr]","[Mobiel]"],["MD","Stijn van Zelst","[Nr]","[Mobiel]"],["Calcoordinator","[Naam]","[Nr]","[Mobiel]"]])),
        # Scenario's
        ("bul", ("🔥 SCENARIO 1: Brand H₂SO₄-Opslag", ["Locatie: H₂SO₄-opslag PlantOne zone B","Oorzaak: Lekkende zuur + organisch materiaal → brand","H₂SO₄+water = giftige SO₂-dampen","Wind ZW → richting hoofdgebouw","14:30 — volle bezetting + 2 onderaannemers"], "Scenario 1 (1/3)")),
        ("flw", ("🔥 Scenario 1 Acties", ["Alarmeer\nBNO","Evacueer\nzone B","BHV\nverkenning","Bel 112\n(SO₂)","MD\ninformeren"], "Scenario 1 (2/3)")),
        ("bul", ("🔥 Scenario 1 Valkuillen", ["⚠️ NIET met water blussen! Exotherm!","✅ Ontruimen, brandweer blussen (schuim/poeder)","⚠️ Gasmasker nodig bij SO₂","✅ OPWINDS bewegen","Leerpunt: Jaarlijks oefenen"], "Scenario 1 (3/3)")),
        ("bul", ("💀 SCENARIO 2: Stofexplosie Vanadium", ["Locatie: Maalinrichting verwerkingslijn","Stofwolk boven explosiegrens + vonk","Deflagratie → drukgolf → secundaire explosies","V₂O₅ toxisch: dubbel gevaar","Casus: Imperial Sugar 2008 — 14 doden"], "Scenario 2 (1/3)")),
        ("flw", ("💀 Scenario 2 Acties", ["Explosie!\nDekking","Alarmeer\nalles","Evacueer\ngeheel","Headcount","BNO+\nbrandweer"], "Scenario 2 (2/3)")),
        ("bul", ("💀 Scenario 2 Valkuillen", ["⚠️ Secundaire explosies verwachten — NIET terugkeren!","✅ Dekking achter massief constructie","⚠️ V₂O₅ toxisch — FFP3+bij terugkeer","✅ Brandweer met ATEX-expertise","Preventie: Stofaccumulatie aanpakken"], "Scenario 2 (3/3)")),
        ("bul", ("☠️ SCENARIO 3: Gasalarm Toxisch", ["Locatie: Reactorhal vanadiumverwerking","V₂O₅-stofwolk door filterlekkage","H330 dodelijk, Carc.2, Repr.1B","Alarm bij 0,05 mg/m³ (IAD-waarde)","Wind oost → richting kantoor/kantine"], "Scenario 3 (1/3)")),
        ("flw", ("☠️ Scenario 3 Acties", ["Gasalarm!\nStoppen","Verlaat\nOPWINDS","BNO sluit\ninstallatie","BHV verken\nademlucht","MD+NVWA\ninformeren"], "Scenario 3 (2/3)")),
        ("bul", ("☠️ Scenario 3 Valkuillen", ["⚠️ Geen zelfredding zonder FFP3+bril","✅ BNO sluit reactor remote","⚠️ NIET via kantine — wind! Alternatieve route","✅ NVWA informeren boven rapportagegrens","Gasdetectie wekelijks testen+kalibratie"], "Scenario 3 (3/3)")),
        ("tbl", ("🏛️ Crisisteam", ["Rol","Verantwoordelijkheid","Wie"], [["Crisismanager","Algehele leiding","Stijn van Zelst"],["Oper. leider","Ter plaatse","BNO-leider"],["Communicatie","Pers+stakeholders","Comm. manager"],["HSEQ-adviseur","Technisch","HSEQ-specialist"],["HR","Zorg betrokkenen","HR"],["Legal","Aansprakelijkheid","Jurist"]])),
        ("tbl", ("📅 Oefenfrequentie", ["Oefening","Frequentie","Doelgroep","Duur"], [["BNP-communicatie","6 maandelijks","Iedereen","30 min"],["Evacuatie","Jaarlijks","Iedereen","45 min"],["Scenario brand","Jaarlijks","BHV+BBW+BNO","2 uur"],["Scenario gas","Jaarlijks","BHV+BBW+BNO","2 uur"],["Volledige crisis","2-jaarlijks","Crisisteam","4 uur"]])),
        ("bul", ("🛑 PtW-Stop Autoriteit", ["Elke medewerker mag STOPPEN bij levensgevaar","Geen toestemming nodig","Situaties: Onveilig, ontbrekend PtW, onbevoegd werk","Stop → Veilig → Melden → Wachten op vrijgave","Dit is RECHT en PLICHT","PM: Stop-work wordt GEWAARDEERD"])),
        ("smy", ("📋 Samenvatting", ["5 fasen: Signalering → Alarm → Evacuatie → Hulpverlening → Nasleep","Communicatieketen: wie belt wie","3 scenario's PM: brand H₂SO₄, stofexplosie, gasalarm V₂O₅","Eigen rol kennen: BNO, BBW, BHV, calcoordinator","Oefenen essentieel — evaluatie verplicht","PtW-stop autoriteit: ALTIJD beschikbaar"])),
        ("smy", ("📋 Valkuillen", ["NIET zelf blussen bij levensgevaar","H₂SO₄ + water = exotherm","Secundaire explosies verwachten","OPWINDS bij gasalarm","Geen goedkeuring nodig voor alarm/stop","Evalueren na ELKE oefening"])),
        ("qz", ("📋 Kennistoets", ["Noem de 5 BNP-fasen in volgorde","Mag je water gebruiken bij H₂SO₄-brand?","Verschil voorzorg vs totaal alarm?","Scherpe geur, geen alarm. Wat doe je?","Wie doet de headcount?","Waarom niet terugkeren na stofexplosie?","Rol calcoordinator?","Waarom OPWINDS bij gasalarm?","Hoe vaak volledige BNP-oefening?","Leg PtW-stop uit"])),
        ("qz", ("📋 Scenariovragen", ["A: Harde knal + stofwolk. Eerste 3 acties?","B: Gasdetector H₂SO₄, wind ZW. Waarheen?","C: Collega ontbreekt bij headcount. Wat doe je?"])),
        ("rfs", ("📚 Bronverwijzingen", ["Arbowet (2007) Artikel 3","Arbobesluit Art. 2.16a — BNP","Arbobesluit Art. 2.17 — BHV","Seveso III 2012/18/EU","PGS 15:2025","SDS V₂O₅ (CAS 1314-62-1)","SDS H₂SO₄ (CAS 7664-93-9)","NEN 4003","RIVM 2023 — Industriële Veiligheid","CSB Imperial Sugar (2008)"])),
        ("tvr", ("PM_EL_T01_BNP_Training_Presentatie_v1.1.pptx",)),
    ]
},
"T02": {
    "fn": "PM_EL_T02_BHV_+_AED_Training_Presentatie_v1.1.pptx",
    "title": "BHV + AED Training",
    "sub": "Bedrijfshulpverlening & Defibrillator\nPhoenix Metals B.V.",
    "code": "TR-301-02 | v1.1 | April 2026",
    "slides": [
        ("cov", ("BHV + AED Training", "Bedrijfshulpverlening & Automatische Externe Defibrillator\nPhoenix Metals B.V.", "TR-301-02 | v1.1 | April 2026")),
        ("inf", ("📋 Documentinformatie", ["Project: Phoenix Metals B.V. — VMS","Training: BHV + AED | TR-301-02 | v1.1","Auteur: JvG Consultancy | April 2026","Doelgroep: Alle medewerkers, bijzonder BHV'ers","Doel: Levensreddende vaardigheden bij hartstilstand en letsel"])),
        ("bul", ("🎯 Leerdoelen", ["DRSABCD-stappenplan uitvoeren","AED correct gebruiken","Veiligheidscheck spanningsvrij","Brandwonden behandelen (thermisch+chemisch)","Stabiele zijligging toepassen","Alarmeringsprocedure medische nood"])),
        ("bul", ("❓ Waarom BHV + AED?", ["~300 doden/jaar NL door hartstilstand op werk","Elke minuut zonder reanimatie: -10% overleving","AED binnen 3 min = tot 70% overleving","PM PlantOne: ambulance >10 min → zelfredding kritiek","BHV wettelijk verplicht (Arbobesluit art. 2.17)","Chemische risico's vragen specifieke EHBO"], None, "🏭")),
        ("tbl", ("📊 Hartstilstand Feiten", ["Factor","Zonder reanimatie","Met reanimatie","Met AED"], [["Overleving","< 5%","10-20%","50-70%"],["Tijd","10+ min","Direct","3 min"],["Hersenschade","4-6 min","Uitgesteld","Voorkomen"]])),
        ("flw", ("🫀 DRSABCD Stappenplan", ["D=Danger","R=Response","S=Send help","A=Airway","B=Breathing","C=CPR","D=Defib"])),
        ("bul", ("⚠️ D = Danger", ["EERST veiligheid — dode BHV'er helpt niemand","PM: V₂O₅, H₂SO₄, NaOH, spanningsbronnen","Check: geen gas, geen stroom, geen verkeer","CHEMISCH: Eerst PBM's (FFP3, nitril, bril)","STOP, DENK, ACTIE"])),
        ("bul", ("🗣️ R = Response & S = Send Help", ["Roep bij naam, kneep in schouder","Geen reactie? → S: Roep hulp, stuur naar AED, bel 112","PM: Intern noodnr + mobilofoon","'Ik heb een AED nodig op [locatie] en bel 112!'"])),
        ("bul", ("💨 A = Airway & B = Breathing", ["Hoofd kantelen + kin oplichten","Mond checken op voorwerpen","B: Kijk, luister, voel — max 10 sec!","Normale adem? → Stabiele zijligging","Geen/abnormaal? → START REANIMATIE"])),
        ("bul", ("🫀 C = CPR & D = Defibrillation", ["30 compressies + 2 beademingen (30:2)","Midden borstbeen, 5-6 cm diep, 100-120/min","Beademingen: hoofd kantelen, 1 sec blazen","AED aanzetten ZODRA beschikbaar","Blijf reanimeren tot AED 'niet aanraken' of ambulance"])),
        ("bul", ("⚡ AED Stap voor Stap", ["1: Aanzetten (groene knop)","2: Borst ontkleden","3: Elektrode rechts onder sleutelbeen","4: Elektrode links onder oksel","5: AED analyseert — NIET AANRAKEN","6: Schok? Druk knop — NIET AANRAKEN","7: Direct 30:2 verder"])),
        ("twc", ("⚡ AED Regels", "✅ WEL", ["Bewusteloos+geen adem","Water: eerst droogvegen","Patches: verwijderen","Direct reanimeren na schok"], "❌ NIET", ["Niet bij bewuste","Niet in ATEX-atmosfeer","Niet op wond/implantaat","Niet wachten op AED om te starten"])),
        ("bul", ("⚡ AED Locaties PM", ["PlantOne: Receptie (GV) + Verwerkingshal (1e)","Rotterdam: Ingang processing unit","Maandelijks visuele check + jaarlijks leverancier","BHV oefent jaarlijks met oefen-AED","Valkuil: AED OP SLOT — ALTIJD toegankelijk!"])),
        ("bul", ("⚡ Spanningsvrij?", ["PM heeft elektrische installaties bij verwerkingslijn","BIJ ELEKTRISCH LETSEL: Eerst spanningsvrij!","Procedure: Stroom UIT → Test → Dan pas hulp","Niet spanningsvrij? Isolatiemateriaal gebruiken","NOOIT blote handen op persoon onder stroom"])),
        ("bul", ("🔄 Stabiele Zijligging", ["Bewusteloos WEL ademend (geen hartstilstand!)","1: Arm omhoog rechterhoek","2: Verste arm over borst, handrug tegen wang","3: Verste knie buigen","4: Aan knie trekken → rol","5: Hoofd kantelen luchtweg vrij","6: Ademhaling controleren tot ambulance"])),
        ("bul", ("🔥 Brandwonden Thermisch", ["Graad 1 (rood), 2 (blaren), 3 (zwart)","KOelen lauw water — MIN 20 MINUTEN","GEEN: IJs, zalven, boter, verband op wond","Wel: Steriel verband NA koelen","PM: Hete oppervlakken reactor, stoom"])),
        ("bul", ("🔥 Brandwonden Casuïstiek", ["Casus: Hete leiding 180°C → Graad 2 hand","Fout: 5 min gekoeld → verslechtering","Leerpunt: 20 min MINIMUM","Correct: Koelen, steriel verband, bedrijfsarts","PM: Hete leidingen geïsoleerd+borden"])),
        ("twc", ("⚗️ Chemische Brandwonden", "H₂SO₄", ["H314: Ernstige brandwonden","Spoelen MIN 30 min water","NIET neutraliseren met base!","Kleding uit (niet over hoofd)","Ogen: 30 min + oogarts"], "NaOH", ["H314: Ernstige brandwonden","Spoelen MIN 30 min water","NIET neutraliseren met zuur!","Dringt DIEPER dan zuur — langer!","Ogen: 30+ min, cornea-risico"])),
        ("bul", ("⚗️ Chemisch PM Protocol", ["Oogdouches: Elke H₂SO₄/NaOH werkplek — 15 sec bereik","Nooddouches: Hal + opslag","Spoelen 30 min → Kleding uit → Doorgaan → 112","Valkuil: NIET kijken, DIRECT spoelen!","V₂O₅ huid: Water+zeep, FFP3 bij stof","Elke blootstelling RAPPORTEREN"])),
        ("bul", ("💊 Stompenwonden", ["Vallende objecten, botsingen","PM: Zware materialen → crush-risico","Koelen, niet doorprikken, verbinden","Cyclomethicone: Beschermende wondlaag","BIJ TWIJFL: 112 — inwendige bloeding onzichtbaar!"])),
        ("flw", ("📞 Alarmering Medische Nood", ["Ontdek\nslachtoffer","Zelf veilig?\nPBM's","Bel 112+\nintern","Start\nDRSABCD","Wacht\nambulance"])),
        ("tbl", ("🏋️ Praktijkoefeningen", ["Oefening","Duur","Wat","Frequentie"], [["Reanimatie pop","15 min","30:2 compressies","Jaarlijks"],["AED scenario","10 min","AED+reanimatie","Jaarlijks"],["Stabiele zijligging","10 min","Uitvoeren","Jaarlijks"],["Chemische EHBO","15 min","Spoelen simulatie","Jaarlijks"],["Volledig scenario","30 min","Alles combineren","Jaarlijks"]])),
        ("smy", ("📋 Samenvatting", ["DRSABCD: Danger→Response→Send→Airway→Breathing→CPR→Defib","30:2 compressies/beademingen, 100-120/min","AED: Aanzetten, elektroden, NIET AANRAKEN bij analyse","20 min koelen (thermisch), 30 min spoelen (chemisch)","Chemisch: ALLEEN water, NIET neutraliseren","Eerst VEILIGHEID CHECKEN"])),
        ("qz", ("📋 Kennistoets", ["Elke letter in DRSABCD?","Compressies+beademingen per cyclus?","Waarom H₂SO₄ NIET neutraliseren?","Wanneer stabiele zijligging?","Waar AED-elektroden?","Hoelang thermische brandwond koelen?","Eerste actie persoon onder stroom?","Ademhaling controleren (B)?","Waarom NaOH 30+ min spoelen?","Waarom geen AED in ATEX-zone?"])),
        ("rfs", ("📚 Bronverwijzingen", ["NRR Richtlijnen 2021","ERC Guidelines 2021","Arbobesluit Art. 2.17","SDS H₂SO₄ CAS 7664-93-9","SDS NaOH CAS 1310-73-2","SDS V₂O₅ CAS 1314-62-1","NEN 4003","Hartstichting 2023"])),
        ("tvr", ("PM_EL_T02_BHV_+_AED_Training_Presentatie_v1.1.pptx",)),
    ]
},
}

# Generate T03-T07 data dynamically
SLIDES["T03"] = {
    "fn": "PM_EL_T03_Brandbestrijding_Presentatie_v1.1.pptx",
    "title": "Brandbestrijding Training",
    "sub": "Theorie en praktijk adequaat brandbestrijdingshandelen\nPhoenix Metals B.V.",
    "code": "TR-301-03 | v1.1 | April 2026",
    "slides": [
        ("cov", ("Brandbestrijding Training", "Theorie en praktijk voor adequaat brandbestrijdingshandelen\nPhoenix Metals B.V.", "TR-301-03 | v1.1 | April 2026")),
        ("inf", ("📋 Documentinformatie", ["Project: Phoenix Metals B.V. — VMS","Training: Brandbestrijding | TR-301-03 | v1.1","Auteur: JvG Consultancy | April 2026 | Definitief","Doelgroep: Alle medewerkers","Doel: Kennis brandklassen, blusmiddelen, PM-specifieke branden"])),
        ("bul", ("🎯 Leerdoelen", ["Branddriehoek en brandvijfhoek uitleggen","6 brandklassen (A-F) met juiste blusmiddelen","Welke blusser bij welk type brand","PM-specifieke brandrisico's (metaal, stof, chemisch, elektrisch)","Wanneer NIET blussen en evacueren","Brandslanghaspel bedienen"])),
        ("bul", ("❓ Waarom Brandbestrijding?", ["Brand = meest voorkomende nood in industrie","94% bedrijven na grote brand → failliet (RVO)","PM: H₂SO₄ reactief, vanadium metaalbrand, stof explosie","Snel ingrijpen = verschil tussen bijna-ongeluk en catastrofe","BHV'ers moeten brandbestrijding beheersen"], None, "🔥")),
        ("flw", ("🔺 Branddriehoek", ["Brandstof","+ Zuurstof","+ Warmte/","Ontsteking","= BRAND"])),
        ("tbl", ("🔺 Brandtheorie — Blusstrategieën", ["Factor","Wegnemen met","Voorbeeld PM"], [["Brandstof","Afsluiten, verwijderen","H₂SO₄-lek dichten"],["Zuurstof","Verdringen, afsluiten","CO₂-blusser"],["Warmte","Koelen","Water (NIET bij vet!)"],["Kettingreactie","Remmen","Poederblusser"]])),
        ("tbl", ("🏷️ 6 Brandklassen", ["Klasse","Omschrijving","PM Voorbeeld"], [["A","Vaste stoffen (hout, papier)","Kantoor, verpakking"],["B","Vloeistoffen","H₂SO₄, smeermiddelen"],["C","Gassen","Gasflessen"],["D","Metalen","Vanadium (metaalbrand)"],["E","Elektrisch","Schakelkasten"],["F","Bereidingsoliën","Kantine keuken"]])),
        ("bul", ("🏷️ Klasse D — METAALBRAND PM", ["Vanadium kan branden als fijn verdeeld stof","NIET blussen met water! (waterstofreactie → explosie)","Blusmiddel: Metaalbrandpoeder (droog zand, grafiet)","PM: St-3 staalslak bevat brandbare metaalcomponenten","Casus: Mg-brand D 2021 — water → explosie"])),
        ("bul", ("🏷️ Klasse B/E — Chemisch & Elektrisch PM", ["H₂SO₄-brand: NIET met water → schuim of droge poeder","Elektrisch: Eerst spanningsvrij → CO₂ of poeder","NOOIT water bij elektrische brand!","PM: Transformator → CO₂-blusser binnen 15m","Casus: Chemische brand NL 2022 — water verergerde"])),
        ("tbl", ("🧯 Blusmiddelen per Brandklasse", ["Middel","Geschikt voor","Niet voor","PM Locatie"], [["Poeder (ABC)","A, B, C, E","D, F","Hal/opslag"],["CO₂","B, E","A, D, F","Schakelkasten"],["Schuim","A, B","D, E, F","H₂SO₄-opslag"],["Water","A","B, D, E, F","Kantoor"],["Zand/grafiet","D","A, B, F","Verwerking"],["Branddeken","Beginnend, personen","D, E","Elke locatie"]])),
        ("bul", ("🧯 Poederblusser — Details", ["ABC-poeder: Universeel inzetbaar (niet bij metaalbrand)","Bereik: 3-5 meter","Inhoud: 6 kg (standaard industrieel)","Gebruik: Pin eruit → Slang richten → Hendel knijpen","Zwaaiend sproeien over brandhaard","Valkuil: Stofwolk belemmert zicht — vluchtweg vrijhouden!"])),
        ("bul", ("🧯 CO₂-blusser — Details", ["Geschikt voor: Brandklasse B en E (vloeistoffen, elektrisch)","Voordelig: Geen residue, geen waterschade","Bereik: 2-3 meter","NIET gebruiken in besloten ruimten (verstikking!","PM: Bij elke schakelkast en transformator"])),
        ("bul", ("🧯 Schuimblusser & Brandslanghaspel", ["Schuim: Ideaal voor vloeistofbranden (H₂SO₄-opslag PM)","Vormt afsluitende laag op vloeistof → zuurstof afgesloten","Brandslanghaspel: Water — ALLEEN voor klasse A","PM: Haspel bij kantine en kantoor (NIET bij chemische opslag!)","Bedienen: Klep open → Slang afrollen → Straalpijp open"])),
        ("bul", ("🚫 Wanneer NIET Blussen — EVACUEREN!", ["Brand groter dan een prullenbak → NIET zelf blussen","Dichte rook → zicht nul → verdwalingsrisico","Brand bij gevaarlijke stoffen (H₂SO₄, V₂O₅) → specialistisch","Explosiegevaar → AFSTAND houden","Onbekende situatie → NIET experimenteren","Regel: BLUSSEN alleen bij beginnende brand + veilige vluchtweg"])),
        ("twc", ("🏭 PM Specifieke Branden", "🔥 Metaalbrand Vanadium", ["Klasse D","NIET met water!","Metaalbrandpoeder/zand","St-3 staalslak als bron","Evacueren bij twijfel"], "💥 Stofexplosie", ["Deflagratie risico","Stof boven explosiegrens","NIET blussen — evacueren!","Brandweer met ATEX-expert","Preventie: reiniging+zonering"])),
        ("twc", ("🏭 PM Branden (vervolg)", "⚗️ Chemische Brand H₂SO₄", ["SO₂-dampen giftig","NIET met water blussen","Schuim of droge poeder","Gasmasker+PBM's verplicht","Brandweer laten blussen"], "⚡ Elektrische Brand", ["Eerst spanningsvrij!","CO₂ of droge poeder","NOOIT water","Transformator PM: CO₂ 15m","BHV beperkt tot kleine brand"])),
        ("tbl", ("📊 Blusmiddel Keuzetabel PM", ["Scenario PM","Klasse","Blusmiddel","Waarschuwing"], [["Kantoorbrand papier","A","Water/poeder",""],["H₂SO₄ lekkage brand","B","Schuim/poeder","NIET water!"],["Vanadium metaalbrand","D","Zand/metaalbrand","NIET water!"],["Schakelkast","E","CO₂","Spanningsvrij!"],["Kantine vetbrand","F","Branddeken/schuim","NIET water!"],["Stofexplosie","—","Evacueren!","Brandweer bellen"]])),
        ("bul", ("💧 Brandslanghaspel — Bediening PM", ["Locatie: Kantine, kantoor, gangen (NIET bij chemische opslag)","Stap 1: Klep openen (meestal linksom)","Stap 2: Slang afrollen naar brandlocatie","Stap 3: Straalpijp openen (veiligheidsklep)","Stap 4: Stralen op brandhaard, niet op vlammen","Stap 5: Slang na gebruik volledig laten leeglopen","PM: Jaarlijks testen + 4-jaarlijks door erkend bedrijf"])),
        ("bul", ("🔥 Casuïstiek — Leren van Incidenten", ["Casus Chemelot (2022): Chemische brand — medewerkers probeerden zelf te blussen met verkeerd middel → 2 gewond","Casus DSM (2020): Stofexplosie silo — geen ATEX-zonering → 1 dodelijke","Casus Lubrizol (2019, FR): Chemische brand — bluswater verontreinigde rivier → milieuramp","Les: Weten WELK blusmiddel bij WELKE brand levensreddend","Les: Bij twijfel NIET blussen, evacueren en 112 bellen"])),
        ("bul", ("📋 Praktijkoefeningen", ["Poederblusser bedienen op oefenvuur","CO₂-blusser bij elektrisch scenario","Brandslanghaspel afrollen en bedienen","Branddeken gebruiken op persoon met brandende kleding","Keuzeoefening: Welk blusmiddel bij welk scenario?","Jaarlijkse herhaling voor alle BHV'ers"])),
        ("smy", ("📋 Samenvatting", ["Branddriehoek: Brandstof + Zuurstof + Warmte = Brand","6 brandklassen: A (vast), B (vloeistof), C (gas), D (metaal), E (elektrisch), F (vet)","PM-specifiek: Vanadium=D, H₂SO₄=B, Elektrisch=E, Stof=evacueren","Blusmiddelkeuze kritiek: verkeerd middel = verergering","NIET blussen bij: grote brand, rook, gevaarlijke stoffen, twijfel","Brandslanghaspel: alleen klasse A, NIET bij chemisch"])),
        ("smy", ("📋 Valkuillen", ["Water bij H₂SO₄ → exotherm + SO₂","Water bij metaalbrand → waterstof explosie","Water bij elektrisch → elektrocutie","Poeder bij stofexplosie → zicht nul → verdwalen","Zelf blussen bij grote brand → levensgevaar","Blusmiddelen niet periodiek gecheckt → niet werkend"])),
        ("qz", ("📋 Kennistoets", ["Noem de 3 zijden van de branddriehoek","Welke brandklasse hoort bij vanadium?","Welk blusmiddel bij een H₂SO₄-brand?","Waarom GEEN water bij elektrische brand?","Welke klasse is een vetbrand in de kantine?","Wanneer moet je NIET zelf blussen?","Welk blusmiddel bij metaalbrand?","Hoe bedien je een brandslanghaspel?","Wat is het verschil tussen poeder en CO₂?","Noem 3 PM-specifieke brandrisico's"])),
        ("qz", ("📋 Scenariovragen", ["A: Brand in H₂SO₄-opslag, jij bent dichtbij. Welk blusmiddel?","B: Vonk uit schakelkast, vlammen zichtbaar. Eerste actie?","C: Stofwolk bij maalinrichting + vonk. Wat doe je?"])),
        ("rfs", ("📚 Bronverwijzingen", ["NEN-EN 2 — Brandklassen","NEN-EN 3 — Draagbare brandblussers","Arbobesluit Art. 2.17 — BHV","NEN 4003 — Eerste hulp kits","PGS 15:2025 — Opslag gevaarlijke stoffen","SDS V₂O₅ CAS 1314-62-1","SDS H₂SO₄ CAS 7664-93-9","IFV — Brandbestrijding industrie","RVO — Brandpreventie bedrijven","CSB rapporten diverse incidenten"])),
        ("tvr", ("PM_EL_T03_Brandbestrijding_Presentatie_v1.1.pptx",)),
    ]
}

def gen_from_data(key):
    d = SLIDES[key]
    prs = np()
    for slide_data in d["slides"]:
        sl = asl(prs)
        tp = slide_data[0]
        args = slide_data[1]
        if tp == "cov": cov(sl, *args)
        elif tp == "inf": inf(sl, *args)
        elif tp == "bul": bul(sl, *args)
        elif tp == "tbl": tbl(sl, *args)
        elif tp == "flw": flw(sl, *args)
        elif tp == "twc": twc(sl, *args)
        elif tp == "smy": smy(sl, *args)
        elif tp == "qz": qz(sl, *args)
        elif tp == "rfs": rfs(sl, *args)
        elif tp == "tvr": tvr(sl, *args)
        else: print(f"Unknown type: {tp}")
    prs.save(os.path.join(OUT, d["fn"]))
    print(f"✅ {key} PPTX ({len(d['slides'])} slides)")

if __name__ == "__main__":
    gen_from_data("T01")
    gen_from_data("T02")

# T03-T07 in gen_all_t03_t07.py