Hearing aid care during monsoon for both battery operated hearing aids and also rechargeable hearing aids

Searching the Web

hearing aid care monsoon humidity battery rechargeable tips 2025

Searching the Web

rechargeable hearing aid moisture protection rainy season care guide

Here is a thorough, practical guide to hearing aid care during the monsoon season, covering both battery-operated and rechargeable models.

Hearing Aid Care During Monsoon Season

Monsoon conditions - high humidity (often 80-100%), frequent rain, and sudden temperature changes - create the most challenging environment for hearing aids all year. Moisture is the single biggest cause of hearing aid failure, leading to corrosion of internal circuits, blocked microphone ports, battery drain, distorted sound, and complete device failure.

Why Monsoon Is Especially Risky

  • Condensation forms inside the device when you move between air-conditioned rooms and humid outdoors
  • Continuous ambient humidity means moisture seeps in even when it is not raining
  • Sweat increases in warm, humid weather, adding another moisture source right next to the device
  • Fungal/bacterial growth can occur inside tubing and ear moulds in persistent moisture, per HearUSA's humidity guide

General Rules (Both Types)

PracticeWhat to Do
Daily wipe-downUse a soft, dry lint-free cloth every evening to wipe the shell, microphone ports, and receiver
Brush the portsUse the cleaning brush (provided with your aid) to clear microphone and sound port openings of moisture droplets or debris
Avoid bathroom storageNever store aids in the bathroom - it is the highest-humidity room in the house
Protective coverUse a moisture-resistant sleeve or "hearing aid sweatband" over the device when outdoors
Hat or umbrella ruleAlways wear a hat or carry an umbrella - direct rain on hearing aids should be avoided even for IP68-rated devices
Remove before exposureRemove aids before stepping into heavy rain, entering a steam room, or doing intense exercise
Professional checkSchedule a professional clean and check at the start of and midway through monsoon season

Battery-Operated Hearing Aid Care

Nightly Routine

  1. Open the battery door completely every night when you remove the aids. This allows air circulation, prevents moisture from being trapped against the battery contacts, and extends battery life - as recommended by Starkey and NCOA's cleaning guide.
  2. Place the aids (battery door open) inside a desiccant drying jar or electronic UV drying box overnight.
  3. Do not leave batteries inside if you plan to store the aids for more than a day - remove the batteries entirely to prevent corrosion on the contacts.

Battery-Specific Tips for Monsoon

  • Replace batteries more frequently. Humidity shortens battery life significantly - you may need to change batteries every 5-6 days instead of the usual 7-10.
  • Store spare batteries in a sealed, airtight container with a silica gel packet. Do not store them in a humid pocket or bag.
  • Check for corrosion on the battery contacts (small metal tabs inside the battery door). If you see white or greenish residue, gently clean with a dry cotton swab or the cleaning tool.
  • Never use a wet or damp battery. Dry it thoroughly before inserting.
  • Check the battery door seal - if it feels loose or does not close firmly, have it checked as it allows moisture ingress.

Rechargeable Hearing Aid Care

Rechargeable aids present a special challenge: you cannot open the battery compartment, so the internal battery and electronics are entirely dependent on your external drying routine.

Nightly Routine

  1. Power them off before placing in the charger (if the device has a power button).
  2. Wipe the charging contacts on the bottom of the aids with a dry cloth before placing them in the charger. Dirty or damp contacts can cause charging failures and corrosion, per Helton Hearing Care's maintenance guide.
  3. Place in the charging case overnight. Many modern charging cases (Phonak, ReSound, Starkey) have a built-in dehumidifying function - the case actively removes moisture while charging, per Doctors Hearing's complete guide.
  4. If your charging case does NOT have a built-in dryer, use a separate electronic drying box for 30-60 minutes before placing in the charger.

Rechargeable-Specific Tips for Monsoon

  • Never place wet aids directly into the charger. Wipe them completely dry first - moisture on the contacts can cause a short circuit or charging error.
  • If they get soaked: Power off immediately, wipe dry, place in a desiccant/dryer box for 24-48 hours, and only then return to the charger - per HearUSA's wet hearing aid guide.
  • Do not use a hairdryer or oven to speed up drying - heat damages the internal lithium-ion battery and can void your warranty.
  • Monitor charge cycles - if the battery is not holding a full charge after monsoon exposure, moisture may have degraded the battery. Contact your audiologist.
  • Check if your model is IP67 or IP68 rated (e.g. Starkey Genesis AI, Phonak Infinio) - these can handle brief splashes and rain far better, though they are not fully waterproof for prolonged immersion.

Drying Tools: Which to Use

ToolHow It WorksBest For
Silica gel desiccant jarPassive absorption of moistureBoth types - budget option, replace silica monthly
Electronic drying boxGentle heat + airflowBoth types - most effective daily dryer
UV-C drying boxUV light kills bacteria + desiccantBoth types - also sanitizes
Charging case with dryerBuilt-in dryer during chargingRechargeable only
An electronic drying box used for 6-8 hours overnight is the gold standard during monsoon. Passive silica jars are good as a backup or travel option.

What to Do If an Aid Gets Wet (Emergency)

  1. Remove immediately from moisture
  2. Power off - for rechargeable aids, press and hold the power button
  3. Do NOT press any buttons - this can push water deeper inside
  4. Wipe the exterior gently with a dry lint-free cloth, including all ports and the battery/charging area
  5. For battery aids: remove the battery and leave the door open
  6. Place in an electronic drying box or desiccant jar for 24-48 hours
  7. For rechargeable: do not put back in the charger until completely dry
  8. Do not use a rice bag - rice dust can clog microphone ports and is not as effective as proper desiccants
  9. If the aid still does not work after 48 hours, contact your audiologist for an internal inspection

Quick Monsoon Checklist

  • Drying box or desiccant jar set up at home
  • Battery door opened every night (battery aids)
  • Charging contacts wiped before charging every night (rechargeable aids)
  • Spare batteries stored in airtight container with silica gel
  • Soft cleaning brush used on microphone ports daily
  • Protective sleeve or cover for outdoor use
  • Audiologist appointment booked for mid-monsoon check
  • Emergency plan ready if aids get soaked

With consistent daily care - especially the nightly drying routine - your hearing aids can perform reliably all through the monsoon season.

Create a reference guide PDF on hearing aid monsoon care to share with family

Reading File
Reading File
Running Command

ls -la /tmp/workspace/ 2>/dev/null || echo "workspace does not exist"

Running Command

mkdir -p /tmp/workspace/hearing-aid-guide

Writing File

~/hearing-aid-guide/create_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, PageBreak
)
from reportlab.platypus.flowables import Flowable
from reportlab.lib.colors import HexColor

# ── Colour palette ────────────────────────────────────────────────────────────
TEAL       = HexColor("#0B6E8C")   # dark teal – headings
TEAL_LIGHT = HexColor("#E6F4F8")   # very light teal – section fills
SKY        = HexColor("#1BAACC")   # medium teal – accents
ORANGE     = HexColor("#E87722")   # orange – battery icon accent
GREEN      = HexColor("#2E8B57")   # green – rechargeable accent
RED_SOFT   = HexColor("#C0392B")   # red – emergency tips
GREY       = HexColor("#555555")
LIGHT_GREY = HexColor("#F5F5F5")
WHITE      = colors.white

# ── Custom Flowable: Coloured Rounded Box Header ──────────────────────────────
class SectionHeader(Flowable):
    """A rounded-rect header band for major sections."""
    def __init__(self, text, bg=TEAL, fg=WHITE, width=None, height=28):
        super().__init__()
        self.text   = text
        self.bg     = bg
        self.fg     = fg
        self._width = width
        self.height = height

    def wrap(self, aW, aH):
        self.box_width = self._width or aW
        return self.box_width, self.height + 4

    def draw(self):
        c = self.canv
        w, h = self.box_width, self.height
        c.setFillColor(self.bg)
        c.roundRect(0, 0, w, h, 6, fill=1, stroke=0)
        c.setFillColor(self.fg)
        c.setFont("Helvetica-Bold", 11)
        c.drawString(10, h / 2 - 5, self.text)


class IconBullet(Flowable):
    """A small circle bullet with a label beside it."""
    def __init__(self, icon_char, label, icon_color=TEAL, font_size=9):
        super().__init__()
        self.icon  = icon_char
        self.label = label
        self.color = icon_color
        self.fs    = font_size

    def wrap(self, aW, aH):
        self._w = aW
        return aW, self.fs + 6

    def draw(self):
        c = self.canv
        r = self.fs / 2 + 1
        c.setFillColor(self.color)
        c.circle(r, r - 1, r, fill=1, stroke=0)
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", self.fs - 2)
        c.drawCentredString(r, r - 3, self.icon)
        c.setFillColor(GREY)
        c.setFont("Helvetica", self.fs)
        c.drawString(r * 2 + 6, r - 4, self.label)


# ── Helper: build a two-column tip table ─────────────────────────────────────
def tip_table(rows, col_widths=None, row_bg=LIGHT_GREY):
    """rows = list of (label, value) tuples"""
    page_w = A4[0] - 3.6 * cm   # usable width
    if col_widths is None:
        col_widths = [page_w * 0.38, page_w * 0.62]
    data = [["Action", "What to Do"]] + list(rows)
    style = TableStyle([
        # Header row
        ("BACKGROUND",   (0, 0), (-1, 0), TEAL),
        ("TEXTCOLOR",    (0, 0), (-1, 0), WHITE),
        ("FONTNAME",     (0, 0), (-1, 0), "Helvetica-Bold"),
        ("FONTSIZE",     (0, 0), (-1, 0), 9),
        ("BOTTOMPADDING",(0, 0), (-1, 0), 6),
        ("TOPPADDING",   (0, 0), (-1, 0), 6),
        # Alternating rows
        *[("BACKGROUND", (0, i), (-1, i), LIGHT_GREY if i % 2 == 0 else WHITE)
          for i in range(1, len(data))],
        ("FONTNAME",     (0, 1), (-1, -1), "Helvetica"),
        ("FONTSIZE",     (0, 1), (-1, -1), 8.5),
        ("TOPPADDING",   (0, 1), (-1, -1), 4),
        ("BOTTOMPADDING",(0, 1), (-1, -1), 4),
        ("LEFTPADDING",  (0, 0), (-1, -1), 6),
        ("GRID",         (0, 0), (-1, -1), 0.3, HexColor("#CCCCCC")),
        ("VALIGN",       (0, 0), (-1, -1), "MIDDLE"),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1), [WHITE, TEAL_LIGHT]),
    ])
    return Table(data, colWidths=col_widths, style=style, repeatRows=1)


def checklist_table(items, accent=TEAL):
    """Single-column checklist with tick boxes."""
    page_w = A4[0] - 3.6 * cm
    data = [["  ☐  " + item] for item in items]
    style = TableStyle([
        ("FONTNAME",     (0, 0), (-1, -1), "Helvetica"),
        ("FONTSIZE",     (0, 0), (-1, -1), 9),
        ("TOPPADDING",   (0, 0), (-1, -1), 4),
        ("BOTTOMPADDING",(0, 0), (-1, -1), 4),
        ("LEFTPADDING",  (0, 0), (-1, -1), 8),
        ("ROWBACKGROUNDS", (0, 0), (-1, -1), [WHITE, TEAL_LIGHT]),
        ("GRID",         (0, 0), (-1, -1), 0.3, HexColor("#CCCCCC")),
    ])
    return Table(data, colWidths=[page_w], style=style)


def emergency_table(rows):
    page_w = A4[0] - 3.6 * cm
    data = [["Step", "Action"]] + list(rows)
    style = TableStyle([
        ("BACKGROUND",   (0, 0), (-1, 0), RED_SOFT),
        ("TEXTCOLOR",    (0, 0), (-1, 0), WHITE),
        ("FONTNAME",     (0, 0), (-1, 0), "Helvetica-Bold"),
        ("FONTSIZE",     (0, 0), (-1, 0), 9),
        ("BOTTOMPADDING",(0, 0), (-1, 0), 6),
        ("TOPPADDING",   (0, 0), (-1, 0), 6),
        ("FONTNAME",     (0, 1), (-1, -1), "Helvetica"),
        ("FONTSIZE",     (0, 1), (-1, -1), 8.5),
        ("TOPPADDING",   (0, 1), (-1, -1), 4),
        ("BOTTOMPADDING",(0, 1), (-1, -1), 4),
        ("LEFTPADDING",  (0, 0), (-1, -1), 6),
        ("GRID",         (0, 0), (-1, -1), 0.3, HexColor("#CCCCCC")),
        ("VALIGN",       (0, 0), (-1, -1), "MIDDLE"),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1), [WHITE, HexColor("#FDECEA")]),
        ("FONTNAME",     (0, 1), (-1, -1), "Helvetica"),
        ("TEXTCOLOR",    (0, 1), (0, -1), RED_SOFT),
        ("FONTNAME",     (0, 1), (0, -1), "Helvetica-Bold"),
    ])
    return Table(data, colWidths=[page_w * 0.12, page_w * 0.88], style=style)


# ── Page template callbacks ───────────────────────────────────────────────────
def on_first_page(canvas, doc):
    canvas.saveState()
    # Top banner
    canvas.setFillColor(TEAL)
    canvas.rect(0, A4[1] - 2.4 * cm, A4[0], 2.4 * cm, fill=1, stroke=0)
    # Bottom strip
    canvas.setFillColor(SKY)
    canvas.rect(0, 0, A4[0], 0.7 * cm, fill=1, stroke=0)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica", 7.5)
    canvas.drawCentredString(A4[0] / 2, 0.22 * cm,
        "Reference guide prepared July 2026 · Consult your audiologist for device-specific advice")
    canvas.restoreState()


def on_later_pages(canvas, doc):
    canvas.saveState()
    # Thin top accent
    canvas.setFillColor(TEAL)
    canvas.rect(0, A4[1] - 0.6 * cm, A4[0], 0.6 * cm, fill=1, stroke=0)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica-Bold", 7.5)
    canvas.drawString(1.8 * cm, A4[1] - 0.42 * cm,
                      "Hearing Aid Monsoon Care Guide")
    canvas.setFont("Helvetica", 7.5)
    canvas.drawRightString(A4[0] - 1.8 * cm, A4[1] - 0.42 * cm,
                           f"Page {doc.page}")
    # Bottom strip
    canvas.setFillColor(SKY)
    canvas.rect(0, 0, A4[0], 0.7 * cm, fill=1, stroke=0)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica", 7.5)
    canvas.drawCentredString(A4[0] / 2, 0.22 * cm,
        "Reference guide prepared July 2026 · Consult your audiologist for device-specific advice")
    canvas.restoreState()


# ── Build document ────────────────────────────────────────────────────────────
out_path = "/tmp/workspace/hearing-aid-guide/Hearing_Aid_Monsoon_Care_Guide.pdf"

doc = SimpleDocTemplate(
    out_path,
    pagesize=A4,
    leftMargin=1.8 * cm,
    rightMargin=1.8 * cm,
    topMargin=3.2 * cm,
    bottomMargin=1.6 * cm,
    title="Hearing Aid Monsoon Care Guide",
    author="Orris Health Guide",
)

styles = getSampleStyleSheet()

# Custom styles
title_style = ParagraphStyle("GuideTitle",
    fontName="Helvetica-Bold", fontSize=22, textColor=WHITE,
    leading=26, alignment=TA_CENTER, spaceAfter=4)

subtitle_style = ParagraphStyle("GuideSubtitle",
    fontName="Helvetica", fontSize=11, textColor=HexColor("#CCE9F5"),
    leading=14, alignment=TA_CENTER, spaceAfter=2)

date_style = ParagraphStyle("GuideDate",
    fontName="Helvetica-Oblique", fontSize=9, textColor=HexColor("#B0D8EC"),
    alignment=TA_CENTER)

body = ParagraphStyle("Body",
    fontName="Helvetica", fontSize=9, textColor=GREY,
    leading=13, spaceAfter=4, spaceBefore=2, alignment=TA_JUSTIFY)

bold_body = ParagraphStyle("BoldBody",
    fontName="Helvetica-Bold", fontSize=9, textColor=GREY,
    leading=13, spaceAfter=2)

sub_head = ParagraphStyle("SubHead",
    fontName="Helvetica-Bold", fontSize=10, textColor=TEAL,
    leading=14, spaceBefore=8, spaceAfter=3)

warn_box = ParagraphStyle("WarnBox",
    fontName="Helvetica-Bold", fontSize=9, textColor=RED_SOFT,
    backColor=HexColor("#FDECEA"), leading=13,
    leftIndent=8, rightIndent=8, spaceBefore=4, spaceAfter=4,
    borderPad=6)

tip_box = ParagraphStyle("TipBox",
    fontName="Helvetica", fontSize=9, textColor=HexColor("#1B5E20"),
    backColor=HexColor("#E8F5E9"), leading=13,
    leftIndent=8, rightIndent=8, spaceBefore=4, spaceAfter=4)

story = []

# ── COVER (first page header handled by canvas callback) ─────────────────────
story.append(Spacer(1, 0.3 * cm))
story.append(Paragraph("Hearing Aid", title_style))
story.append(Paragraph("Monsoon Care Guide", title_style))
story.append(Spacer(1, 0.1 * cm))
story.append(Paragraph("Battery-Operated & Rechargeable Hearing Aids", subtitle_style))
story.append(Paragraph("July 2026  ·  Share freely with family & caregivers", date_style))
story.append(Spacer(1, 0.5 * cm))

# Intro blurb
intro_data = [[
    Paragraph(
        "<b>Why monsoon is the riskiest season for hearing aids:</b> Humidity levels of "
        "80–100%, continuous rain, and sudden temperature changes cause condensation inside "
        "devices, corroding circuits, blocking microphone ports, draining batteries, and "
        "distorting sound. A few minutes of daily care can prevent costly repairs and keep "
        "your aids working perfectly all season.",
        body)
]]
intro_table = Table(intro_data,
    colWidths=[A4[0] - 3.6 * cm],
    style=TableStyle([
        ("BACKGROUND", (0, 0), (-1, -1), TEAL_LIGHT),
        ("BOX",        (0, 0), (-1, -1), 1, SKY),
        ("LEFTPADDING", (0, 0), (-1, -1), 10),
        ("RIGHTPADDING",(0, 0), (-1, -1), 10),
        ("TOPPADDING",  (0, 0), (-1, -1), 8),
        ("BOTTOMPADDING",(0,0), (-1, -1), 8),
    ]))
story.append(intro_table)
story.append(Spacer(1, 0.4 * cm))

# ── SECTION 1 – Why Moisture Is Dangerous ────────────────────────────────────
story.append(SectionHeader("1.  Why Moisture Is Dangerous for Hearing Aids"))
story.append(Spacer(1, 0.2 * cm))

risks = [
    ("Corrosion", "Moisture corrodes internal circuit boards and battery contacts, causing permanent failure"),
    ("Blocked ports", "Water droplets block microphone and receiver openings, muffling or cutting out sound"),
    ("Battery drain", "Humidity shortens disposable battery life by 30–50% and degrades rechargeable batteries"),
    ("Fungal growth", "Persistent moisture inside tubing and ear moulds encourages mould and bacteria"),
    ("Condensation", "Moving between AC rooms and humid outdoors creates condensation inside the shell"),
]
story.append(tip_table(risks))
story.append(Spacer(1, 0.35 * cm))

# ── SECTION 2 – General Rules (Both Types) ───────────────────────────────────
story.append(SectionHeader("2.  General Rules — Both Battery &amp; Rechargeable Aids"))
story.append(Spacer(1, 0.2 * cm))

general = [
    ("Daily wipe-down", "Each evening wipe the shell, microphone ports and receiver with a soft dry lint-free cloth"),
    ("Brush the ports", "Use your cleaning brush daily on microphone openings to clear moisture droplets and debris"),
    ("Never bathroom storage", "Bathrooms are high-humidity zones — never store aids on the sink shelf or medicine cabinet"),
    ("Protective sleeve", "Use a moisture-resistant hearing aid sleeve or 'sweatband' when outdoors in humid weather"),
    ("Hat or umbrella rule", "Always cover your ears in rain — even IP-rated devices should not take direct rain"),
    ("Remove before exposure", "Remove aids before stepping into heavy rain, steam rooms or intense exercise"),
    ("Skip hairspray first", "Apply hairspray, sunscreen or insect repellent BEFORE inserting aids, then wash hands"),
    ("Professional check", "Schedule a professional clean at the start of monsoon and once mid-season"),
]
story.append(tip_table(general))
story.append(Spacer(1, 0.35 * cm))

# ── SECTION 3 – Battery-Operated Aids ────────────────────────────────────────
story.append(SectionHeader("3.  Battery-Operated Hearing Aids — Monsoon Care",
             bg=ORANGE, fg=WHITE))
story.append(Spacer(1, 0.2 * cm))

story.append(Paragraph("Nightly Routine", sub_head))
nightly_bat = [
    ("1. Open battery door", "Open it COMPLETELY every night — allows air circulation and prevents trapped moisture corroding contacts"),
    ("2. Use a drying box", "Place aids (door open) in an electronic UV drying box or desiccant jar for 6–8 hours overnight"),
    ("3. Store spare batteries", "Keep spares in a sealed airtight container with a silica gel packet; never in a damp pocket"),
]
story.append(tip_table(nightly_bat,
    col_widths=[(A4[0]-3.6*cm)*0.32, (A4[0]-3.6*cm)*0.68]))
story.append(Spacer(1, 0.25 * cm))

story.append(Paragraph("Battery-Specific Monsoon Tips", sub_head))
bat_tips = [
    ("Change batteries more often",
     "Humidity shortens battery life — expect 5–6 days instead of the usual 7–10; carry a spare pair"),
    ("Check for corrosion",
     "Look for white or greenish residue on battery contacts; clean gently with a dry cotton swab"),
    ("Never insert damp battery",
     "Dry each battery completely before inserting — moisture bridges the contacts and drains power instantly"),
    ("Check battery door seal",
     "A loose-fitting battery door allows moisture ingress; have it checked if it does not close firmly"),
    ("Remove for long storage",
     "If aids will not be used for more than a day, remove batteries entirely to prevent corrosion"),
]
story.append(tip_table(bat_tips,
    col_widths=[(A4[0]-3.6*cm)*0.32, (A4[0]-3.6*cm)*0.68]))
story.append(Spacer(1, 0.35 * cm))

# ── SECTION 4 – Rechargeable Aids ────────────────────────────────────────────
story.append(SectionHeader("4.  Rechargeable Hearing Aids — Monsoon Care",
             bg=GREEN, fg=WHITE))
story.append(Spacer(1, 0.2 * cm))

story.append(Paragraph(
    "<b>Key difference:</b> You <b>cannot open the battery compartment</b> on rechargeable aids, "
    "so the entire burden of moisture protection falls on your external drying routine. "
    "This makes nightly drying even more critical.",
    body))
story.append(Spacer(1, 0.15 * cm))

story.append(Paragraph("Nightly Routine", sub_head))
nightly_rec = [
    ("1. Power off first",
     "Press and hold the power button to turn the aids off before placing them in the charger"),
    ("2. Wipe charging contacts",
     "Wipe the metal charging contacts on the bottom of each aid with a dry cloth before charging — damp contacts cause faults"),
    ("3. Use charging case",
     "Place in the charging case overnight; many modern cases (Phonak, ReSound, Starkey) have a built-in dehumidifier"),
    ("4. Separate dryer if needed",
     "If your case has no built-in dryer, use an electronic drying box for 30–60 min before placing in the charger"),
]
story.append(tip_table(nightly_rec,
    col_widths=[(A4[0]-3.6*cm)*0.32, (A4[0]-3.6*cm)*0.68]))
story.append(Spacer(1, 0.25 * cm))

story.append(Paragraph("Rechargeable-Specific Monsoon Tips", sub_head))
rec_tips = [
    ("Never charge while wet",
     "Always wipe aids completely dry BEFORE placing in the charger — moisture on contacts causes short circuits"),
    ("Monitor charge capacity",
     "If the battery no longer holds a full charge after heavy monsoon exposure, moisture may have degraded it — see your audiologist"),
    ("No hairdryer or oven",
     "Never use heat to speed drying — it damages the lithium-ion battery and voids the warranty"),
    ("Check IP rating",
     "IP67/IP68-rated aids (e.g. Starkey Genesis AI, Phonak Infinio) handle rain and splashes far better; ask your audiologist"),
    ("Firmware updates",
     "Moisture can cause firmware glitches; check for updates if the aid behaves erratically after heavy humidity exposure"),
]
story.append(tip_table(rec_tips,
    col_widths=[(A4[0]-3.6*cm)*0.32, (A4[0]-3.6*cm)*0.68]))
story.append(Spacer(1, 0.35 * cm))

# ── SECTION 5 – Drying Tools ─────────────────────────────────────────────────
story.append(SectionHeader("5.  Drying Tools — Which to Use"))
story.append(Spacer(1, 0.2 * cm))

dryer_rows = [
    ("Silica gel desiccant jar",
     "Passive absorption; budget option; replace silica monthly; good for travel backup",
     "Both"),
    ("Electronic drying box",
     "Gentle heat + airflow; most effective daily dryer; 6–8 hours overnight is gold standard",
     "Both"),
    ("UV-C drying box",
     "UV light kills bacteria and fungi + desiccant; best for monsoon due to infection risk",
     "Both"),
    ("Charging case with dryer",
     "Dries while charging; most convenient for rechargeable users; check your model specs",
     "Rechargeable only"),
]
dryer_data = [["Tool", "How It Works", "For"]] + dryer_rows
dryer_widths = [(A4[0]-3.6*cm)*0.26, (A4[0]-3.6*cm)*0.55, (A4[0]-3.6*cm)*0.19]
dryer_style = TableStyle([
    ("BACKGROUND",   (0, 0), (-1, 0), TEAL),
    ("TEXTCOLOR",    (0, 0), (-1, 0), WHITE),
    ("FONTNAME",     (0, 0), (-1, 0), "Helvetica-Bold"),
    ("FONTSIZE",     (0, 0), (-1, 0), 9),
    ("BOTTOMPADDING",(0, 0), (-1, 0), 6),
    ("TOPPADDING",   (0, 0), (-1, 0), 6),
    ("FONTNAME",     (0, 1), (-1, -1), "Helvetica"),
    ("FONTSIZE",     (0, 1), (-1, -1), 8.5),
    ("TOPPADDING",   (0, 1), (-1, -1), 4),
    ("BOTTOMPADDING",(0, 1), (-1, -1), 4),
    ("LEFTPADDING",  (0, 0), (-1, -1), 6),
    ("GRID",         (0, 0), (-1, -1), 0.3, HexColor("#CCCCCC")),
    ("VALIGN",       (0, 0), (-1, -1), "MIDDLE"),
    ("ROWBACKGROUNDS", (0, 1), (-1, -1), [WHITE, TEAL_LIGHT]),
    ("TEXTCOLOR",    (2, 4), (2, 4), GREEN),
    ("FONTNAME",     (2, 4), (2, 4), "Helvetica-Bold"),
])
story.append(Table(dryer_data, colWidths=dryer_widths, style=dryer_style, repeatRows=1))
story.append(Spacer(1, 0.35 * cm))

# ── SECTION 6 – Emergency: Aid Gets Wet ──────────────────────────────────────
story.append(SectionHeader("6.  Emergency: Hearing Aid Got Wet — Act Immediately",
             bg=RED_SOFT, fg=WHITE))
story.append(Spacer(1, 0.2 * cm))

emerg_rows = [
    ("1", "Remove the aid from water/rain IMMEDIATELY"),
    ("2", "Power OFF — for rechargeable aids press and hold the power button"),
    ("3", "Do NOT press any other buttons — pushing buttons drives moisture deeper inside"),
    ("4", "Wipe exterior gently with a dry lint-free cloth, including all ports and contacts"),
    ("5", "Battery aids: remove the battery and leave the door fully open"),
    ("6", "Place in an electronic drying box or desiccant jar for 24–48 hours"),
    ("7", "Rechargeable aids: do NOT put back in the charger until completely dry"),
    ("8", "Do NOT use a rice bag — rice dust clogs microphone ports"),
    ("9", "Do NOT use a hairdryer, oven, or microwave to speed drying"),
    ("10","If the aid still fails after 48 hours, contact your audiologist immediately for inspection"),
]
story.append(emergency_table(emerg_rows))
story.append(Spacer(1, 0.35 * cm))

# ── SECTION 7 – Checklist ────────────────────────────────────────────────────
story.append(SectionHeader("7.  Daily Monsoon Checklist — Print &amp; Tick Off"))
story.append(Spacer(1, 0.2 * cm))

checklist_items = [
    "Wiped hearing aids with dry cloth before storing",
    "Brushed microphone and sound ports with cleaning brush",
    "Battery door opened fully for the night  (battery aids)",
    "Charging contacts wiped dry before placing in charger  (rechargeable aids)",
    "Placed aids in drying box / desiccant jar / charging case",
    "Checked battery level and replaced if weak  (battery aids)",
    "Spare batteries stored in airtight container with silica gel  (battery aids)",
    "Wore protective sleeve or cover when outdoors today",
    "Avoided hairspray / sunscreen while aids were in",
    "Did NOT store aids in the bathroom",
    "Professional check booked for mid-monsoon",
]
story.append(checklist_table(checklist_items))
story.append(Spacer(1, 0.35 * cm))

# ── SECTION 8 – Quick Comparison ─────────────────────────────────────────────
story.append(SectionHeader("8.  Quick Comparison — Battery vs Rechargeable"))
story.append(Spacer(1, 0.2 * cm))

compare_data = [
    ["Feature", "Battery-Operated", "Rechargeable"],
    ["Open battery door nightly?", "YES — mandatory", "No — sealed unit"],
    ["Nightly drying method", "Desiccant jar / electronic dryer (door open)", "Charging case (with dryer) or separate dryer first"],
    ["Battery life in monsoon", "Shorter — change every 5–6 days", "Monitor charge capacity; degradation possible"],
    ["Corrosion risk", "Battery contacts + internal circuits", "Charging contacts + internal circuits"],
    ["If it gets wet", "Remove battery, open door, dry 24–48 hrs", "Power off, wipe contacts, dry 24–48 hrs before charging"],
    ["IP water resistance", "Varies by model — check specs", "Often higher (IP67/68) on modern models"],
    ["Travel drying", "Desiccant jar + spare batteries", "Portable charging case; carry backup charger"],
]
compare_widths = [(A4[0]-3.6*cm)*0.28, (A4[0]-3.6*cm)*0.36, (A4[0]-3.6*cm)*0.36]
compare_style = TableStyle([
    ("BACKGROUND",   (0, 0), (-1, 0), TEAL),
    ("TEXTCOLOR",    (0, 0), (-1, 0), WHITE),
    ("FONTNAME",     (0, 0), (-1, 0), "Helvetica-Bold"),
    ("FONTSIZE",     (0, 0), (-1, 0), 9),
    ("BACKGROUND",   (0, 1), (0, -1), TEAL_LIGHT),
    ("FONTNAME",     (0, 1), (0, -1), "Helvetica-Bold"),
    ("FONTSIZE",     (0, 1), (-1, -1), 8.5),
    ("TOPPADDING",   (0, 0), (-1, -1), 5),
    ("BOTTOMPADDING",(0, 0), (-1, -1), 5),
    ("LEFTPADDING",  (0, 0), (-1, -1), 6),
    ("GRID",         (0, 0), (-1, -1), 0.3, HexColor("#CCCCCC")),
    ("VALIGN",       (0, 0), (-1, -1), "MIDDLE"),
    ("ROWBACKGROUNDS", (0, 1), (-1, -1), [WHITE, HexColor("#F0F8FF")]),
    ("TEXTCOLOR",    (1, 1), (1, -1), HexColor("#7B3F00")),
    ("TEXTCOLOR",    (2, 1), (2, -1), HexColor("#1B5E20")),
])
story.append(Table(compare_data, colWidths=compare_widths,
                   style=compare_style, repeatRows=1))
story.append(Spacer(1, 0.35 * cm))

# ── SECTION 9 – Warning Signs ─────────────────────────────────────────────────
story.append(SectionHeader("9.  Warning Signs — See Your Audiologist",
             bg=ORANGE, fg=WHITE))
story.append(Spacer(1, 0.2 * cm))

warning_items = [
    "Sound is muffled, distorted, or cuts in and out after rain exposure",
    "Battery drains much faster than usual (within 1–2 days for disposable batteries)",
    "Rechargeable aid does not hold a full charge after monsoon exposure",
    "Visible corrosion (white or green residue) on battery contacts",
    "Aid stopped working after getting wet, even after 48-hour drying",
    "Whistling or feedback that was not present before",
    "Charging contacts feel sticky or show discolouration",
    "Device does not switch on at all",
]
story.append(checklist_table(warning_items, accent=ORANGE))
story.append(Spacer(1, 0.3 * cm))

story.append(Paragraph(
    "⚠  <b>Do not attempt to open or repair the hearing aid yourself.</b> "
    "Internal moisture damage requires professional equipment (ultrasonic cleaning, vacuum drying) "
    "that only a certified audiologist or service centre can provide.",
    warn_box))

story.append(Spacer(1, 0.4 * cm))

# ── CLOSING NOTE ─────────────────────────────────────────────────────────────
closing_data = [[Paragraph(
    "<b>Remember:</b> Hearing aids are precision electronic devices. The monsoon daily care routine "
    "takes under five minutes and will significantly extend the life of your device, saving on "
    "costly repairs. When in doubt, always consult your audiologist. Share this guide with "
    "every family member who helps care for a hearing aid user.",
    body)]]
closing_table = Table(closing_data,
    colWidths=[A4[0] - 3.6 * cm],
    style=TableStyle([
        ("BACKGROUND", (0, 0), (-1, -1), TEAL),
        ("TEXTCOLOR",  (0, 0), (-1, -1), WHITE),
        ("LEFTPADDING", (0, 0), (-1, -1), 10),
        ("RIGHTPADDING",(0, 0), (-1, -1), 10),
        ("TOPPADDING",  (0, 0), (-1, -1), 10),
        ("BOTTOMPADDING",(0,0), (-1, -1), 10),
        ("FONTNAME",  (0, 0), (-1, -1), "Helvetica"),
    ]))
# Override text color for white-on-teal paragraph
closing_data[0][0] = Paragraph(
    "<b>Remember:</b> Hearing aids are precision electronic devices. The monsoon daily care routine "
    "takes under five minutes and will significantly extend the life of your device, saving on "
    "costly repairs. When in doubt, always consult your audiologist. Share this guide with "
    "every family member who helps care for a hearing aid user.",
    ParagraphStyle("ClosingP",
        fontName="Helvetica", fontSize=9, textColor=WHITE,
        leading=13, alignment=TA_JUSTIFY))
story.append(closing_table)

# ── Build ─────────────────────────────────────────────────────────────────────
doc.build(story,
          onFirstPage=on_first_page,
          onLaterPages=on_later_pages)

print(f"PDF created: {out_path}")
Running Command

cd /tmp/workspace/hearing-aid-guide && python create_pdf.py 2>&1

Running Command

ls -lh /tmp/workspace/hearing-aid-guide/Hearing_Aid_Monsoon_Care_Guide.pdf

Your reference guide PDF is ready to download and share:

Hearing Aid Monsoon Care Guide

PDF Document · PDF


Here's what's included across the guide's 9 sections:
SectionContent
1. Why Moisture Is Dangerous5 key risks: corrosion, blocked ports, battery drain, fungal growth, condensation
2. General Rules8 rules that apply to both aid types
3. Battery-Operated AidsNightly routine + 5 monsoon-specific tips (corrosion checks, battery frequency, door seals)
4. Rechargeable AidsNightly routine + 5 tips (charging contacts, IP ratings, no-heat rule)
5. Drying ToolsComparison of 4 dryer types with "who it's best for"
6. Emergency: Aid Got Wet10-step emergency action plan in a red-highlighted table
7. Daily Checklist11-item printable tick-off checklist for daily use
8. Battery vs Rechargeable ComparisonSide-by-side table across 7 parameters
9. Warning Signs8 signs to call your audiologist immediately
The PDF uses a clean teal/orange colour scheme with colour-coded sections (orange for battery aids, green for rechargeable, red for emergency), making it easy for family members of all ages to follow.

Generate a reel formate for this

Asking for Preferences
Writing File

~/hearing-aid-guide/create_reel.py

"""
Instagram/Reel Carousel – Hearing Aid Monsoon Care
9 slides  ·  1080 × 1920 px  ·  Portrait
Uses reportlab canvas for full pixel control.
"""

from reportlab.pdfgen import canvas
from reportlab.lib.colors import HexColor, white, black
from reportlab.lib.units import inch
from reportlab.lib.utils import ImageReader
from io import BytesIO
import math

# ── Canvas size (1080 × 1920 px at 96 dpi → points) ─────────────────────────
PX_W, PX_H = 1080, 1920
PT_W  = PX_W * 72 / 96   # 810 pt
PT_H  = PX_H * 72 / 96   # 1440 pt

# ── Colour palette ────────────────────────────────────────────────────────────
TEAL       = HexColor("#0B6E8C")
TEAL2      = HexColor("#0E8FAF")
TEAL_DARK  = HexColor("#094F66")
TEAL_LIGHT = HexColor("#D0EEF7")
ORANGE     = HexColor("#E87722")
ORANGE_L   = HexColor("#FDE8D3")
GREEN      = HexColor("#2E8B57")
GREEN_L    = HexColor("#D4EDDA")
RED        = HexColor("#C0392B")
RED_L      = HexColor("#FDECEA")
YELLOW     = HexColor("#F5C518")
CREAM      = HexColor("#FFF8F0")
WHITE      = white
GREY_DARK  = HexColor("#333333")
GREY_MID   = HexColor("#666666")
GREY_LIGHT = HexColor("#F0F0F0")

out_path = "/tmp/workspace/hearing-aid-guide/Hearing_Aid_Monsoon_Reel.pdf"
c = canvas.Canvas(out_path, pagesize=(PT_W, PT_H))


# ── Utility helpers ───────────────────────────────────────────────────────────
def cx(frac=0.5):   return PT_W * frac
def cy(frac=0.5):   return PT_H * frac

def bg_gradient_rect(c, x, y, w, h, top_col, bot_col, steps=40):
    """Simulate vertical gradient with thin horizontal strips."""
    tr, tg, tb = top_col.red, top_col.green, top_col.blue
    br, bg_, bb = bot_col.red, bot_col.green, bot_col.blue
    strip_h = h / steps
    for i in range(steps):
        t = i / steps
        r = tr + (br - tr) * t
        g = tg + (bg_ - tg) * t
        b = tb + (bb - tb) * t
        c.setFillColorRGB(r, g, b)
        c.rect(x, y + h - (i + 1) * strip_h, w, strip_h + 0.5, fill=1, stroke=0)

def draw_full_bg(c, top_col, bot_col):
    bg_gradient_rect(c, 0, 0, PT_W, PT_H, top_col, bot_col)

def pill(c, x, y, w, h, fill_col, radius=12):
    c.setFillColor(fill_col)
    c.roundRect(x, y, w, h, radius, fill=1, stroke=0)

def icon_circle(c, cx_, cy_, r, bg_col, char, char_size=28, fg=WHITE):
    c.setFillColor(bg_col)
    c.circle(cx_, cy_, r, fill=1, stroke=0)
    c.setFillColor(fg)
    c.setFont("Helvetica-Bold", char_size)
    c.drawCentredString(cx_, cy_ - char_size * 0.35, char)

def center_text(c, text, y, font, size, col):
    c.setFillColor(col)
    c.setFont(font, size)
    c.drawCentredString(cx(), y, text)

def wrap_text(c, text, x, y, max_width, font, size, col, line_height=None):
    """Simple word-wrap. Returns final y."""
    if line_height is None:
        line_height = size * 1.45
    c.setFillColor(col)
    c.setFont(font, size)
    words = text.split()
    line = ""
    for word in words:
        test = (line + " " + word).strip()
        if c.stringWidth(test, font, size) <= max_width:
            line = test
        else:
            c.drawString(x, y, line)
            y -= line_height
            line = word
    if line:
        c.drawString(x, y, line)
        y -= line_height
    return y

def center_wrap(c, text, y, max_width, font, size, col, line_height=None):
    """Centered word-wrap. Returns final y."""
    if line_height is None:
        line_height = size * 1.45
    c.setFillColor(col)
    c.setFont(font, size)
    words = text.split()
    line = ""
    lines_out = []
    for word in words:
        test = (line + " " + word).strip()
        if c.stringWidth(test, font, size) <= max_width:
            line = test
        else:
            lines_out.append(line)
            line = word
    if line:
        lines_out.append(line)
    for ln in lines_out:
        c.drawCentredString(cx(), y, ln)
        y -= line_height
    return y

def dot_nav(c, total, current, y=38, dot_r=7, gap=22, active_col=WHITE, inactive_col=None):
    """Draw slide indicator dots."""
    if inactive_col is None:
        inactive_col = HexColor("#FFFFFF55")
    total_w = (total - 1) * gap
    start_x = cx() - total_w / 2
    for i in range(total):
        xd = start_x + i * gap
        c.setFillColor(active_col if i == current else inactive_col)
        c.circle(xd, y, dot_r if i == current else 5, fill=1, stroke=0)

def tag_pill(c, text, x, y, bg, fg=WHITE, font_size=18, pad_x=20, pad_h=14):
    w = c.stringWidth(text, "Helvetica-Bold", font_size) + pad_x * 2
    h = font_size + pad_h
    c.setFillColor(bg)
    c.roundRect(x - w / 2, y - h / 2, w, h, h / 2, fill=1, stroke=0)
    c.setFillColor(fg)
    c.setFont("Helvetica-Bold", font_size)
    c.drawCentredString(x, y - font_size * 0.35, text)

def bullet_rows(c, items, x, y, icon_char, icon_bg, font_size=22,
                icon_r=22, gap=18, max_w=None, line_h=None):
    """Draw icon + text bullet rows. Returns final y."""
    if max_w is None:
        max_w = PT_W - x - 40
    if line_h is None:
        line_h = font_size * 1.5
    for item in items:
        icon_circle(c, x + icon_r, y - icon_r + 8, icon_r, icon_bg, icon_char, char_size=font_size - 4)
        c.setFillColor(GREY_DARK)
        c.setFont("Helvetica", font_size)
        text_x = x + icon_r * 2 + 14
        # quick wrap
        words = item.split()
        line = ""
        first = True
        ty = y
        for word in words:
            test = (line + " " + word).strip()
            if c.stringWidth(test, "Helvetica", font_size) <= max_w - icon_r * 2 - 14:
                line = test
            else:
                c.drawString(text_x, ty, line)
                ty -= line_h * 0.85
                line = word
                first = False
        if line:
            c.drawString(text_x, ty, line)
        y -= max(line_h, (ty - y) * -1 + line_h * 0.4)
        y -= gap
    return y


# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 1 – COVER
# ═══════════════════════════════════════════════════════════════════════════════
draw_full_bg(c, TEAL_DARK, TEAL2)

# Big rain-drop decorative circles
c.setFillColor(HexColor("#FFFFFF08"))
c.circle(PT_W * 0.85, PT_H * 0.78, 180, fill=1, stroke=0)
c.circle(PT_W * 0.15, PT_H * 0.22, 130, fill=1, stroke=0)
c.circle(PT_W * 0.5, PT_H * 0.55, 260, fill=1, stroke=0)

# Top label pill
tag_pill(c, "MONSOON SPECIAL", cx(), PT_H - 160, ORANGE, WHITE, 22)

# Main icon
icon_circle(c, cx(), PT_H * 0.56, 100, HexColor("#FFFFFF20"), "🎧", 72, WHITE)

# Title
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 70)
c.drawCentredString(cx(), PT_H * 0.42, "Hearing Aid")
c.setFont("Helvetica-Bold", 62)
c.drawCentredString(cx(), PT_H * 0.42 - 78, "Monsoon Care")

# Subtitle
c.setFillColor(TEAL_LIGHT)
c.setFont("Helvetica", 30)
c.drawCentredString(cx(), PT_H * 0.42 - 140, "Battery & Rechargeable")

# Divider
c.setStrokeColor(HexColor("#FFFFFF40"))
c.setLineWidth(1.5)
c.line(cx() - 160, PT_H * 0.32, cx() + 160, PT_H * 0.32)

# CTA
c.setFillColor(WHITE)
c.setFont("Helvetica-Oblique", 26)
c.drawCentredString(cx(), PT_H * 0.28, "Swipe to protect your device ›")

# Bottom brand strip
c.setFillColor(HexColor("#00000040"))
c.rect(0, 0, PT_W, 90, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 22)
c.drawCentredString(cx(), 32, "Save this guide · Share with family")

dot_nav(c, 9, 0)
c.showPage()


# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 2 – WHY MONSOON IS RISKY
# ═══════════════════════════════════════════════════════════════════════════════
draw_full_bg(c, HexColor("#0B3D52"), TEAL_DARK)

# Top label
tag_pill(c, "⚠  THE RISK", cx(), PT_H - 130, RED, WHITE, 22)

center_text(c, "Why Monsoon Is Dangerous", PT_H - 220, "Helvetica-Bold", 46, WHITE)
center_text(c, "for Your Hearing Aids", PT_H - 280, "Helvetica-Bold", 46, WHITE)

# Risk cards (5 cards stacked)
risks = [
    (RED,    "💧", "Corrosion",     "Moisture corrodes internal circuits permanently"),
    (ORANGE, "🔇", "Blocked Ports", "Water clogs microphone & receiver openings"),
    (YELLOW, "🔋", "Battery Drain", "Humidity cuts battery life by up to 50%"),
    (GREEN,  "🦠", "Fungal Growth", "Mould grows inside tubing & ear moulds"),
    (TEAL2,  "🌡", "Condensation",  "AC ↔ humid air creates condensation inside"),
]
card_h = 148
card_w = PT_W - 80
card_x = 40
start_y = PT_H - 360

for i, (col, emoji, title_, desc) in enumerate(risks):
    y0 = start_y - i * (card_h + 14)
    # card bg
    c.setFillColor(HexColor("#FFFFFF10"))
    c.roundRect(card_x, y0 - card_h, card_w, card_h, 16, fill=1, stroke=0)
    # left accent strip
    c.setFillColor(col)
    c.roundRect(card_x, y0 - card_h, 8, card_h, 4, fill=1, stroke=0)
    # emoji
    c.setFont("Helvetica", 38)
    c.setFillColor(WHITE)
    c.drawString(card_x + 26, y0 - card_h + card_h / 2 - 10, emoji)
    # title
    c.setFillColor(col)
    c.setFont("Helvetica-Bold", 26)
    c.drawString(card_x + 84, y0 - card_h + card_h / 2 + 14, title_)
    # desc
    c.setFillColor(HexColor("#DDDDDD"))
    c.setFont("Helvetica", 21)
    c.drawString(card_x + 84, y0 - card_h + card_h / 2 - 20, desc)

dot_nav(c, 9, 1)
c.showPage()


# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 3 – GENERAL RULES (BOTH TYPES)
# ═══════════════════════════════════════════════════════════════════════════════
draw_full_bg(c, HexColor("#F8FEFF"), HexColor("#E0F4FA"))

tag_pill(c, "✅  BOTH AID TYPES", cx(), PT_H - 120, TEAL, WHITE, 22)
center_text(c, "General Monsoon Rules", PT_H - 210, "Helvetica-Bold", 50, TEAL_DARK)
center_text(c, "Apply to ALL hearing aids", PT_H - 268, "Helvetica", 28, GREY_MID)

rules = [
    ("🧹", "Wipe aids daily with a dry lint-free cloth"),
    ("🖌", "Brush microphone ports every evening"),
    ("🚫", "Never store in the bathroom"),
    ("🧤", "Use a moisture-resistant protective sleeve"),
    ("☂", "Always wear a hat or carry an umbrella"),
    ("❌", "Remove before heavy rain or exercise"),
    ("💆", "Apply hairspray/sunscreen BEFORE inserting"),
    ("👨‍⚕️", "Professional clean — start & mid monsoon"),
]

row_h = 96
row_w = PT_W - 80
start_y = PT_H - 320

for i, (emoji, text_) in enumerate(rules):
    y0 = start_y - i * (row_h + 8)
    bg = TEAL_LIGHT if i % 2 == 0 else WHITE
    c.setFillColor(bg)
    c.roundRect(40, y0 - row_h, row_w, row_h, 10, fill=1, stroke=0)
    c.setFont("Helvetica", 34)
    c.setFillColor(TEAL)
    c.drawString(60, y0 - row_h + row_h / 2 - 12, emoji)
    c.setFillColor(GREY_DARK)
    c.setFont("Helvetica", 22)
    c.drawString(116, y0 - row_h + row_h / 2 - 10, text_)

dot_nav(c, 9, 2, active_col=TEAL, inactive_col=HexColor("#0B6E8C55"))
c.showPage()


# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 4 – BATTERY-OPERATED CARE
# ═══════════════════════════════════════════════════════════════════════════════
draw_full_bg(c, HexColor("#3D1C00"), ORANGE)

# Decorative circles
c.setFillColor(HexColor("#FFFFFF08"))
c.circle(PT_W * 0.9, PT_H * 0.2, 200, fill=1, stroke=0)
c.circle(PT_W * 0.1, PT_H * 0.8, 150, fill=1, stroke=0)

tag_pill(c, "🔋  BATTERY-OPERATED AIDS", cx(), PT_H - 130, HexColor("#FFFFFF30"), WHITE, 20)
center_text(c, "Nightly Battery Care", PT_H - 220, "Helvetica-Bold", 52, WHITE)

steps = [
    ("1", "Open battery door FULLY every night",
     "Allows air circulation, prevents moisture trapping"),
    ("2", "Use a drying box for 6–8 hours",
     "Electronic or desiccant — gold standard overnight"),
    ("3", "Store spare batteries in airtight container",
     "With silica gel; never in a damp pocket or bag"),
    ("4", "Change batteries every 5–6 days",
     "Humidity shortens life vs. normal 7–10 days"),
    ("5", "Check contacts for corrosion",
     "White/green residue → clean with dry cotton swab"),
]

card_h = 160
card_w = PT_W - 80
sy = PT_H - 310

for i, (num, title_, sub) in enumerate(steps):
    y0 = sy - i * (card_h + 12)
    c.setFillColor(HexColor("#FFFFFF15"))
    c.roundRect(40, y0 - card_h, card_w, card_h, 14, fill=1, stroke=0)
    # number circle
    c.setFillColor(ORANGE)
    c.circle(82, y0 - card_h / 2, 28, fill=1, stroke=0)
    c.setFillColor(WHITE)
    c.setFont("Helvetica-Bold", 24)
    c.drawCentredString(82, y0 - card_h / 2 - 9, num)
    # text
    c.setFillColor(WHITE)
    c.setFont("Helvetica-Bold", 24)
    c.drawString(124, y0 - card_h / 2 + 12, title_)
    c.setFillColor(ORANGE_L)
    c.setFont("Helvetica", 20)
    c.drawString(124, y0 - card_h / 2 - 18, sub)

dot_nav(c, 9, 3)
c.showPage()


# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 5 – RECHARGEABLE CARE
# ═══════════════════════════════════════════════════════════════════════════════
draw_full_bg(c, HexColor("#0A2E1A"), GREEN)

c.setFillColor(HexColor("#FFFFFF08"))
c.circle(PT_W * 0.85, PT_H * 0.25, 180, fill=1, stroke=0)
c.circle(PT_W * 0.1, PT_H * 0.75, 140, fill=1, stroke=0)

tag_pill(c, "⚡  RECHARGEABLE AIDS", cx(), PT_H - 130, HexColor("#FFFFFF25"), WHITE, 20)
center_text(c, "Rechargeable Care", PT_H - 218, "Helvetica-Bold", 52, WHITE)

# Key callout
c.setFillColor(HexColor("#FFFFFF20"))
c.roundRect(40, PT_H - 326, PT_W - 80, 76, 12, fill=1, stroke=0)
c.setFillColor(YELLOW)
c.setFont("Helvetica-Bold", 21)
c.drawCentredString(cx(), PT_H - 292, "⚠  Cannot open battery compartment!")
c.setFillColor(WHITE)
c.setFont("Helvetica", 20)
c.drawCentredString(cx(), PT_H - 316, "Nightly drying routine is CRITICAL")

steps_r = [
    ("1", "Power OFF before charging", "Hold power button until it turns off"),
    ("2", "Wipe charging contacts dry",  "Metal contacts must be moisture-free"),
    ("3", "Use charging case overnight", "Many Phonak/ReSound cases have built-in dryer"),
    ("4", "Separate dryer if no built-in", "30–60 min in dryer box before charger"),
    ("5", "Never charge while wet",       "Moisture on contacts = short circuit risk"),
]

card_h = 148
sy = PT_H - 430

for i, (num, title_, sub) in enumerate(steps_r):
    y0 = sy - i * (card_h + 12)
    c.setFillColor(HexColor("#FFFFFF15"))
    c.roundRect(40, y0 - card_h, PT_W - 80, card_h, 14, fill=1, stroke=0)
    c.setFillColor(GREEN)
    c.circle(80, y0 - card_h / 2, 26, fill=1, stroke=0)
    c.setFillColor(WHITE)
    c.setFont("Helvetica-Bold", 22)
    c.drawCentredString(80, y0 - card_h / 2 - 8, num)
    c.setFillColor(WHITE)
    c.setFont("Helvetica-Bold", 23)
    c.drawString(120, y0 - card_h / 2 + 12, title_)
    c.setFillColor(GREEN_L)
    c.setFont("Helvetica", 19)
    c.drawString(120, y0 - card_h / 2 - 16, sub)

dot_nav(c, 9, 4)
c.showPage()


# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 6 – DRYING TOOLS
# ═══════════════════════════════════════════════════════════════════════════════
draw_full_bg(c, HexColor("#F9F9FF"), HexColor("#EAF4FF"))

tag_pill(c, "🔧  DRYING TOOLS", cx(), PT_H - 120, TEAL, WHITE, 22)
center_text(c, "Which Dryer Should You Use?", PT_H - 210, "Helvetica-Bold", 46, TEAL_DARK)

tools = [
    (TEAL,   "🫙", "Silica Gel Jar",          "Passive drying · Budget option · Replace monthly",           "Both"),
    (ORANGE, "🔌", "Electronic Drying Box",   "Best daily dryer · 6–8 hrs overnight · Gold standard",       "Both"),
    (YELLOW, "☀", "UV-C Drying Box",          "Kills bacteria + fungi · Best for monsoon season",           "Both"),
    (GREEN,  "⚡", "Charging Case w/ Dryer",  "Dries while charging · Check your model specs",             "Rechargeable"),
]

card_h = 170
card_w = PT_W - 80
sy = PT_H - 300

for i, (col, emoji, name, desc, for_) in enumerate(tools):
    y0 = sy - i * (card_h + 16)
    # Shadow
    c.setFillColor(HexColor("#00000012"))
    c.roundRect(44, y0 - card_h - 4, card_w, card_h, 16, fill=1, stroke=0)
    # Card
    c.setFillColor(WHITE)
    c.roundRect(40, y0 - card_h, card_w, card_h, 16, fill=1, stroke=0)
    # Left color bar
    c.setFillColor(col)
    c.roundRect(40, y0 - card_h, 10, card_h, 4, fill=1, stroke=0)
    # Emoji bg circle
    c.setFillColor(HexColor(col.hexval() + "22"))
    c.circle(98, y0 - card_h / 2 + 4, 34, fill=1, stroke=0)
    c.setFont("Helvetica", 34)
    c.setFillColor(col)
    c.drawCentredString(98, y0 - card_h / 2 - 7, emoji)
    # Name
    c.setFillColor(GREY_DARK)
    c.setFont("Helvetica-Bold", 25)
    c.drawString(148, y0 - card_h / 2 + 26, name)
    # Desc
    c.setFillColor(GREY_MID)
    c.setFont("Helvetica", 19)
    c.drawString(148, y0 - card_h / 2 + 2, desc)
    # For pill
    pill_col = GREEN if for_ == "Both" else TEAL
    pill_text = "✓ Both types" if for_ == "Both" else "✓ Rechargeable"
    pill_w = c.stringWidth(pill_text, "Helvetica-Bold", 17) + 20
    c.setFillColor(pill_col)
    c.roundRect(148, y0 - card_h / 2 - 26, pill_w, 28, 6, fill=1, stroke=0)
    c.setFillColor(WHITE)
    c.setFont("Helvetica-Bold", 17)
    c.drawString(158, y0 - card_h / 2 - 16, pill_text)

dot_nav(c, 9, 5, active_col=TEAL, inactive_col=HexColor("#0B6E8C55"))
c.showPage()


# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 7 – EMERGENCY AID GOT WET
# ═══════════════════════════════════════════════════════════════════════════════
draw_full_bg(c, HexColor("#2D0000"), RED)

c.setFillColor(HexColor("#FFFFFF08"))
c.circle(PT_W * 0.85, PT_H * 0.85, 220, fill=1, stroke=0)

tag_pill(c, "🚨  EMERGENCY GUIDE", cx(), PT_H - 130, HexColor("#FFFFFF30"), WHITE, 20)
center_text(c, "Your Aid Got Wet!", PT_H - 210, "Helvetica-Bold", 58, WHITE)
center_text(c, "Act immediately — follow these steps", PT_H - 272, "Helvetica", 26, HexColor("#FFCCCC"))

steps_e = [
    "Remove from water IMMEDIATELY",
    "Power OFF (hold power button for rechargeable)",
    "Do NOT press other buttons",
    "Wipe exterior with dry lint-free cloth",
    "Battery aid: remove battery, open door",
    "Place in drying box / desiccant jar",
    "Rechargeable: don't charge until fully dry",
    "Do NOT use rice, hairdryer or oven",
    "Still fails after 48 hrs? Call audiologist",
]

row_h = 90
sy = PT_H - 340

for i, step in enumerate(steps_e):
    y0 = sy - i * (row_h + 6)
    c.setFillColor(HexColor("#FFFFFF12"))
    c.roundRect(40, y0 - row_h, PT_W - 80, row_h, 10, fill=1, stroke=0)
    # Number badge
    c.setFillColor(RED)
    c.setStrokeColor(WHITE)
    c.setLineWidth(1.5)
    c.circle(74, y0 - row_h / 2, 20, fill=1, stroke=1)
    c.setLineWidth(1)
    c.setFillColor(WHITE)
    c.setFont("Helvetica-Bold", 18)
    c.drawCentredString(74, y0 - row_h / 2 - 7, str(i + 1))
    # Text
    c.setFillColor(WHITE)
    c.setFont("Helvetica", 21)
    c.drawString(106, y0 - row_h / 2 - 8, step)

dot_nav(c, 9, 6)
c.showPage()


# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 8 – DAILY CHECKLIST
# ═══════════════════════════════════════════════════════════════════════════════
draw_full_bg(c, HexColor("#F0FFF4"), HexColor("#C8EDD8"))

tag_pill(c, "📋  DAILY CHECKLIST", cx(), PT_H - 120, GREEN, WHITE, 22)
center_text(c, "Tick These Off Every Day", PT_H - 208, "Helvetica-Bold", 48, HexColor("#1B4332"))
center_text(c, "Screenshot & save this slide!", PT_H - 260, "Helvetica-Oblique", 26, GREY_MID)

checks = [
    ("Wipe aids with dry cloth",             "Both"),
    ("Brush microphone & sound ports",       "Both"),
    ("Open battery door fully at night",     "Battery"),
    ("Wipe charging contacts before charger","Rechargeable"),
    ("Place in drying box / charging case",  "Both"),
    ("Check/replace battery if weak",        "Battery"),
    ("Spare batteries in airtight container","Battery"),
    ("Wore protective sleeve outdoors",      "Both"),
    ("Did NOT store in bathroom",            "Both"),
    ("Skipped hairspray while wearing aids", "Both"),
]

row_h = 100
sy = PT_H - 310

for i, (task, type_) in enumerate(checks):
    y0 = sy - i * (row_h + 8)
    bg = HexColor("#FFFFFF") if i % 2 == 0 else HexColor("#E8F5E9")
    c.setFillColor(bg)
    c.roundRect(40, y0 - row_h, PT_W - 80, row_h, 10, fill=1, stroke=0)
    # Checkbox
    c.setStrokeColor(GREEN)
    c.setLineWidth(2)
    c.roundRect(60, y0 - row_h + row_h/2 - 18, 36, 36, 4, fill=0, stroke=1)
    # Type badge
    badge_col = ORANGE if type_ == "Battery" else (TEAL if type_ == "Rechargeable" else GREEN)
    bw = c.stringWidth(type_, "Helvetica-Bold", 15) + 12
    c.setFillColor(badge_col)
    c.roundRect(PT_W - 60 - bw, y0 - row_h + row_h/2 - 12, bw, 26, 5, fill=1, stroke=0)
    c.setFillColor(WHITE)
    c.setFont("Helvetica-Bold", 15)
    c.drawString(PT_W - 54 - bw, y0 - row_h + row_h/2 - 4, type_)
    # Task text
    c.setFillColor(GREY_DARK)
    c.setFont("Helvetica", 21)
    c.drawString(110, y0 - row_h + row_h/2 - 9, task)

dot_nav(c, 9, 7, active_col=GREEN, inactive_col=HexColor("#2E8B5755"))
c.showPage()


# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 9 – CLOSING / CTA
# ═══════════════════════════════════════════════════════════════════════════════
draw_full_bg(c, TEAL_DARK, HexColor("#0E3A50"))

c.setFillColor(HexColor("#FFFFFF08"))
c.circle(PT_W * 0.5, PT_H * 0.55, 320, fill=1, stroke=0)
c.circle(PT_W * 0.1, PT_H * 0.1, 100, fill=1, stroke=0)
c.circle(PT_W * 0.9, PT_H * 0.9, 130, fill=1, stroke=0)

# Big tick
icon_circle(c, cx(), PT_H * 0.62, 110, HexColor("#FFFFFF18"), "✓", 90, WHITE)

center_text(c, "You're All Set!", PT_H * 0.47, "Helvetica-Bold", 60, WHITE)

tips_final = [
    "5 mins of nightly care = months of extra life",
    "Share this guide with every family member",
    "Book a mid-monsoon audiologist check-up",
    "When in doubt, see your audiologist!",
]

sy = PT_H * 0.38
for tip in tips_final:
    center_text(c, "• " + tip, sy, "Helvetica", 24, TEAL_LIGHT)
    sy -= 50

# Divider
c.setStrokeColor(HexColor("#FFFFFF30"))
c.setLineWidth(1)
c.line(cx() - 200, sy - 20, cx() + 200, sy - 20)

# Save + Share CTA
c.setFillColor(ORANGE)
c.roundRect(cx() - 240, sy - 120, 480, 72, 36, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 28)
c.drawCentredString(cx(), sy - 88, "💾  Save · 🔁  Share · 🔔  Follow")

# Bottom note
c.setFillColor(HexColor("#AADDEE"))
c.setFont("Helvetica", 20)
c.drawCentredString(cx(), 80, "Guide by Orris · July 2026")
c.setFont("Helvetica", 17)
c.drawCentredString(cx(), 52, "Consult your audiologist for personalised advice")

dot_nav(c, 9, 8)
c.showPage()


# ── Save ──────────────────────────────────────────────────────────────────────
c.save()
print(f"Reel PDF saved: {out_path}")
Running Command

cd /tmp/workspace/hearing-aid-guide && python create_reel.py 2>&1

Running Command

ls -lh /tmp/workspace/hearing-aid-guide/

Your 9-slide Instagram carousel reel is ready:

Hearing Aid Monsoon Reel

PDF Document · PDF


Here's what each slide covers, formatted as a portrait (1080×1920) social media carousel:
SlideTitleTheme
1CoverDark teal gradient, title + "Swipe to protect your device ›" hook
2Why Monsoon Is Dangerous5 colour-coded risk cards (corrosion, blocked ports, battery drain, fungal growth, condensation)
3General Rules8 alternating-row checklist tiles — applies to all aids
4Battery-Operated CareOrange theme, 5 numbered step cards with nightly routine
5Rechargeable CareGreen theme, callout banner + 5 nightly steps
6Drying Tools GuideWhite card layout comparing 4 dryer types with "Both/Rechargeable" badges
7Emergency: Aid Got WetRed theme, 9-step numbered emergency action list
8Daily ChecklistGreen theme, 10 tick-box rows with Battery/Rechargeable/Both badges
9Closing CTATeal + save/share/follow button
How to use: Each page in the PDF = one carousel slide. Export individual pages as JPGs (most PDF apps can do this) for uploading to Instagram, WhatsApp Status, or Facebook as a carousel post.

Can you create a reel acc to this

It looks like you meant to attach an image or file as a reference — but nothing came through! Could you re-upload the image or file you'd like me to base the reel design on?

Tell me your preferred reel style (minimalist, animated, branded, etc.)

Asking for Preferences
Asking for Preferences
Writing File

~/hearing-aid-guide/create_branded_reel.py

"""
Branded Clinical Carousel – Hearing Aid Monsoon Care
9 slides · 1080 × 1920 px · Portrait · Professional teal/white palette
Includes clinic name placeholder on every slide.
"""

from reportlab.pdfgen import canvas
from reportlab.lib.colors import HexColor, white, black, Color
from reportlab.lib.units import mm

# ── Canvas dimensions (1080×1920 @ 96dpi → points) ──────────────────────────
W = 1080 * 72 / 96   # 810 pt
H = 1920 * 72 / 96   # 1440 pt

# ── Brand palette ─────────────────────────────────────────────────────────────
NAVY        = HexColor("#0A2540")   # deep navy – header bars
TEAL        = HexColor("#0B7285")   # primary teal
TEAL_MED    = HexColor("#1A9EBA")   # medium teal – accents
TEAL_PALE   = HexColor("#E8F7FA")   # very pale teal – card fills
SKY         = HexColor("#B2E0EC")   # sky – decorative
SLATE       = HexColor("#3D5A6C")   # slate – body text
WHITE_PURE  = white
OFF_WHITE   = HexColor("#F7FBFD")
ORANGE      = HexColor("#D95F00")   # warm orange – battery aid accent
ORANGE_PALE = HexColor("#FFF0E6")
GREEN       = HexColor("#1A7A4A")   # clinical green – rechargeable accent
GREEN_PALE  = HexColor("#E8F5EE")
RED         = HexColor("#B02020")   # alert red
RED_PALE    = HexColor("#FDF0F0")
GOLD        = HexColor("#C89B14")   # gold – star/highlight
MID_GREY    = HexColor("#8AA0AE")
RULE        = HexColor("#D0E8EF")   # thin rule lines

CLINIC_NAME = "[Your Clinic Name]"

# ── Helpers ───────────────────────────────────────────────────────────────────
def cx(): return W / 2

def set_font(c, name, size, color=None):
    c.setFont(name, size)
    if color:
        c.setFillColor(color)

def draw_text_centered(c, text, y, font, size, color):
    c.setFont(font, size)
    c.setFillColor(color)
    c.drawCentredString(cx(), y, text)

def draw_text_left(c, text, x, y, font, size, color):
    c.setFont(font, size)
    c.setFillColor(color)
    c.drawString(x, y, text)

def pill_tag(c, text, x, y, bg, fg=white, font_size=17, rx=12):
    c.setFont("Helvetica-Bold", font_size)
    tw = c.stringWidth(text, "Helvetica-Bold", font_size)
    pw = tw + 28
    ph = font_size + 16
    c.setFillColor(bg)
    c.roundRect(x - pw / 2, y - ph / 2, pw, ph, rx, fill=1, stroke=0)
    c.setFillColor(fg)
    c.drawCentredString(x, y - font_size * 0.36, text)

def horiz_rule(c, y, color=RULE, lw=1):
    c.setStrokeColor(color)
    c.setLineWidth(lw)
    c.line(48, y, W - 48, y)

def dot_row(c, total, active, y=34, r_active=8, r_dot=5, gap=24,
            col_active=TEAL, col_dot=None):
    if col_dot is None: col_dot = HexColor("#0B728540")
    total_w = (total - 1) * gap
    x0 = cx() - total_w / 2
    for i in range(total):
        c.setFillColor(col_active if i == active else col_dot)
        c.circle(x0 + i * gap,
                 y,
                 r_active if i == active else r_dot,
                 fill=1, stroke=0)

# ── Per-slide frame (header + footer shared structure) ────────────────────────
def draw_frame(c, slide_num, total=9, header_bg=NAVY, show_clinic=True):
    """
    Header bar  (top 110 pt)
    Footer bar  (bottom 80 pt)
    """
    # ── Header ────────────────────────────────────────────────────────────────
    c.setFillColor(header_bg)
    c.rect(0, H - 110, W, 110, fill=1, stroke=0)

    # Teal accent line below header
    c.setFillColor(TEAL_MED)
    c.rect(0, H - 118, W, 8, fill=1, stroke=0)

    # Clinic name (left of header)
    if show_clinic:
        c.setFont("Helvetica-Bold", 21)
        c.setFillColor(SKY)
        c.drawString(44, H - 74, CLINIC_NAME)

    # Slide counter (right of header)
    c.setFont("Helvetica", 19)
    c.setFillColor(HexColor("#AACEDD"))
    counter = f"{slide_num} / {total}"
    c.drawRightString(W - 44, H - 74, counter)

    # ── Footer ────────────────────────────────────────────────────────────────
    c.setFillColor(NAVY)
    c.rect(0, 0, W, 80, fill=1, stroke=0)
    c.setFillColor(TEAL_MED)
    c.rect(0, 76, W, 4, fill=1, stroke=0)

    # Footer text
    c.setFont("Helvetica", 17)
    c.setFillColor(HexColor("#7FAABD"))
    c.drawCentredString(cx(), 28, "Consult your audiologist for personalised advice")

    dot_row(c, total, slide_num - 1, y=56)


def card(c, x, y, w, h, fill=TEAL_PALE, stroke_col=RULE, radius=14, stroke_w=1):
    """Draw a rounded card."""
    c.setFillColor(fill)
    c.setStrokeColor(stroke_col)
    c.setLineWidth(stroke_w)
    c.roundRect(x, y, w, h, radius, fill=1, stroke=1)

def left_accent_card(c, x, y, w, h, accent_col, fill=WHITE_PURE, radius=12):
    """Card with a 6px left colour accent bar."""
    card(c, x, y, w, h, fill=fill, stroke_col=RULE)
    c.setFillColor(accent_col)
    c.roundRect(x, y, 8, h, 4, fill=1, stroke=0)

def icon_badge(c, x, y, r, bg, text, font_size=30, fg=WHITE_PURE):
    c.setFillColor(bg)
    c.circle(x, y, r, fill=1, stroke=0)
    c.setFillColor(fg)
    c.setFont("Helvetica-Bold", font_size)
    c.drawCentredString(x, y - font_size * 0.36, text)

# ── Word-wrap helpers ─────────────────────────────────────────────────────────
def multiline_centered(c, text, y, max_w, font, size, color, lh=None):
    if lh is None: lh = size * 1.5
    c.setFont(font, size); c.setFillColor(color)
    words = text.split(); line = ""; lines = []
    for w_ in words:
        t = (line + " " + w_).strip()
        if c.stringWidth(t, font, size) <= max_w: line = t
        else: lines.append(line); line = w_
    if line: lines.append(line)
    for ln in lines:
        c.drawCentredString(cx(), y, ln); y -= lh
    return y

def multiline_left(c, text, x, y, max_w, font, size, color, lh=None):
    if lh is None: lh = size * 1.5
    c.setFont(font, size); c.setFillColor(color)
    words = text.split(); line = ""; lines = []
    for w_ in words:
        t = (line + " " + w_).strip()
        if c.stringWidth(t, font, size) <= max_w: line = t
        else: lines.append(line); line = w_
    if line: lines.append(line)
    for ln in lines:
        c.drawString(x, y, ln); y -= lh
    return y


# ═══════════════════════════════════════════════════════════════════════════════
# BUILD PDF
# ═══════════════════════════════════════════════════════════════════════════════
out = "/tmp/workspace/hearing-aid-guide/Hearing_Aid_Monsoon_Branded_Reel.pdf"
cv = canvas.Canvas(out, pagesize=(W, H))


# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 1 – COVER
# ─────────────────────────────────────────────────────────────────────────────
# Full background
cv.setFillColor(OFF_WHITE)
cv.rect(0, 0, W, H, fill=1, stroke=0)

# Top navy header
draw_frame(cv, 1, show_clinic=True)

# Decorative teal arch shape behind centre
cv.setFillColor(HexColor("#0B728510"))
cv.ellipse(cx() - 310, H * 0.25, cx() + 310, H * 0.78, fill=1, stroke=0)

# Monsoon season badge
pill_tag(cv, "  MONSOON SEASON GUIDE  ", cx(), H - 170, TEAL, WHITE_PURE, 20)

# Central icon circle
cv.setFillColor(TEAL_PALE)
cv.circle(cx(), H * 0.56, 130, fill=1, stroke=0)
cv.setFillColor(TEAL_MED)
cv.circle(cx(), H * 0.56, 100, fill=1, stroke=0)
cv.setFillColor(WHITE_PURE)
cv.setFont("Helvetica", 80)
cv.drawCentredString(cx(), H * 0.56 - 28, "🎧")

# Title block
draw_text_centered(cv, "Hearing Aid", H * 0.41, "Helvetica-Bold", 66, NAVY)
draw_text_centered(cv, "Monsoon Care", H * 0.41 - 76, "Helvetica-Bold", 66, TEAL)

# Divider with teal circle ornaments
cv.setStrokeColor(RULE); cv.setLineWidth(1.5)
cv.line(80, H * 0.41 - 108, W - 80, H * 0.41 - 108)
cv.setFillColor(TEAL_MED)
cv.circle(80, H * 0.41 - 108, 5, fill=1, stroke=0)
cv.circle(W - 80, H * 0.41 - 108, 5, fill=1, stroke=0)

# Subtitle
draw_text_centered(cv, "Battery-Operated  &  Rechargeable", H * 0.41 - 150,
                   "Helvetica", 28, SLATE)

# Two feature pills
pill_tag(cv, "🔋  Battery-Operated", cx() - 148, H * 0.26, ORANGE_PALE,
         ORANGE, 19)
pill_tag(cv, "⚡  Rechargeable", cx() + 158, H * 0.26, GREEN_PALE, GREEN, 19)

# Swipe CTA
draw_text_centered(cv, "Swipe to learn how to protect your device  ›",
                   H * 0.19, "Helvetica-Oblique", 24, TEAL_MED)

cv.showPage()


# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 2 – WHY MONSOON IS RISKY
# ─────────────────────────────────────────────────────────────────────────────
cv.setFillColor(OFF_WHITE); cv.rect(0, 0, W, H, fill=1, stroke=0)
draw_frame(cv, 2)

# Section title area
cv.setFillColor(TEAL_PALE)
cv.roundRect(40, H - 270, W - 80, 130, 14, fill=1, stroke=0)
cv.setFillColor(TEAL)
cv.roundRect(40, H - 270, 6, 130, 3, fill=1, stroke=0)
draw_text_centered(cv, "Why Monsoon Is Dangerous", H - 190, "Helvetica-Bold", 42, NAVY)
draw_text_centered(cv, "5 threats to your hearing aid", H - 240, "Helvetica", 26, SLATE)

# Risk cards
risks = [
    (RED,    "💧", "Corrosion",
     "Moisture corrodes internal circuits & contacts, causing permanent failure"),
    (ORANGE, "🔇", "Blocked Ports",
     "Water clogs microphone & receiver openings, muffling sound"),
    (GOLD,   "🔋", "Battery Drain",
     "Humidity shortens disposable battery life by up to 50%"),
    (GREEN,  "🦠", "Fungal Growth",
     "Persistent moisture breeds mould inside tubing & ear moulds"),
    (TEAL,   "🌡", "Condensation",
     "Moving AC ↔ humid air creates condensation inside the shell"),
]
card_h = 154; gap = 12
start_y = H - 310

for i, (accent, emoji, title_, desc) in enumerate(risks):
    y0 = start_y - i * (card_h + gap)
    left_accent_card(cv, 40, y0 - card_h, W - 80, card_h, accent)
    # Emoji in tinted circle
    cv.setFillColor(HexColor(accent.hexval() + "22"))
    cv.circle(96, y0 - card_h / 2, 34, fill=1, stroke=0)
    cv.setFont("Helvetica", 32); cv.setFillColor(accent)
    cv.drawCentredString(96, y0 - card_h / 2 - 11, emoji)
    # Title
    draw_text_left(cv, title_, 148, y0 - card_h / 2 + 20, "Helvetica-Bold", 27, NAVY)
    # Desc (wrapped)
    multiline_left(cv, desc, 148, y0 - card_h / 2 - 8,
                   W - 80 - 148 - 20, "Helvetica", 20, SLATE, lh=26)

cv.showPage()


# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 3 – GENERAL RULES
# ─────────────────────────────────────────────────────────────────────────────
cv.setFillColor(OFF_WHITE); cv.rect(0, 0, W, H, fill=1, stroke=0)
draw_frame(cv, 3)

cv.setFillColor(TEAL_PALE)
cv.roundRect(40, H - 260, W - 80, 118, 14, fill=1, stroke=0)
cv.setFillColor(TEAL); cv.roundRect(40, H - 260, 6, 118, 3, fill=1, stroke=0)
draw_text_centered(cv, "General Care Rules", H - 186, "Helvetica-Bold", 44, NAVY)
draw_text_centered(cv, "Applies to ALL hearing aids — both types", H - 232,
                   "Helvetica", 24, SLATE)

rules = [
    ("01", "Daily Wipe-Down",
     "Wipe shell, mic ports & receiver with a soft dry lint-free cloth each evening"),
    ("02", "Brush the Ports",
     "Use your cleaning brush on mic openings daily to clear moisture & debris"),
    ("03", "No Bathroom Storage",
     "Never store aids in the bathroom — highest-humidity room in the house"),
    ("04", "Protective Sleeve",
     "Use a moisture-resistant hearing aid sleeve when outdoors in humid weather"),
    ("05", "Hat / Umbrella Rule",
     "Always cover ears in rain — direct rain harms even IP-rated devices"),
    ("06", "Remove Before Rain",
     "Remove aids before heavy rain, steam rooms or intense exercise"),
    ("07", "Products First",
     "Apply hairspray, sunscreen or insect repellent BEFORE inserting aids"),
    ("08", "Professional Check",
     "Schedule a clean at the start of monsoon and once mid-season"),
]
card_h = 118; gap = 9; start_y = H - 296

for i, (num, title_, desc) in enumerate(rules):
    y0 = start_y - i * (card_h + gap)
    bg = TEAL_PALE if i % 2 == 0 else WHITE_PURE
    card(cv, 40, y0 - card_h, W - 80, card_h, fill=bg, stroke_col=RULE, radius=10)
    # Number badge
    cv.setFillColor(TEAL_MED)
    cv.roundRect(54, y0 - card_h + card_h / 2 - 16, 44, 32, 6, fill=1, stroke=0)
    cv.setFillColor(WHITE_PURE); cv.setFont("Helvetica-Bold", 19)
    cv.drawCentredString(76, y0 - card_h + card_h / 2 - 4, num)
    # Title + desc
    draw_text_left(cv, title_, 114, y0 - card_h + card_h / 2 + 16,
                   "Helvetica-Bold", 24, NAVY)
    multiline_left(cv, desc, 114, y0 - card_h + card_h / 2 - 8,
                   W - 80 - 114 - 20, "Helvetica", 19, SLATE, lh=24)

cv.showPage()


# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 4 – BATTERY-OPERATED AID CARE
# ─────────────────────────────────────────────────────────────────────────────
cv.setFillColor(HexColor("#FFFAF6")); cv.rect(0, 0, W, H, fill=1, stroke=0)
draw_frame(cv, 4, header_bg=HexColor("#3D1800"))

# Section header
cv.setFillColor(ORANGE_PALE)
cv.roundRect(40, H - 268, W - 80, 118, 14, fill=1, stroke=0)
cv.setFillColor(ORANGE); cv.roundRect(40, H - 268, 6, 118, 3, fill=1, stroke=0)
pill_tag(cv, "🔋  BATTERY-OPERATED AIDS", cx(), H - 188, ORANGE, WHITE_PURE, 19)
draw_text_centered(cv, "Nightly Routine & Tips", H - 238, "Helvetica-Bold", 38, HexColor("#3D1800"))

steps = [
    ("1", "Open Battery Door Fully Each Night",
     "Allows air circulation — prevents moisture trapped against contacts"),
    ("2", "Place in Drying Box for 6–8 Hours",
     "Electronic dryer or desiccant jar — gold standard overnight routine"),
    ("3", "Store Spare Batteries Airtight",
     "Sealed container + silica gel packet; never in a damp pocket or bag"),
    ("4", "Change Batteries Every 5–6 Days",
     "Humidity shortens battery life; carry a spare pair at all times"),
    ("5", "Check Contacts for Corrosion",
     "White or green residue → clean gently with a dry cotton swab"),
    ("6", "Remove Batteries for Long Storage",
     "If unused for more than a day, remove batteries to prevent corrosion"),
]
card_h = 140; gap = 10; start_y = H - 302

for i, (num, title_, desc) in enumerate(steps):
    y0 = start_y - i * (card_h + gap)
    left_accent_card(cv, 40, y0 - card_h, W - 80, card_h, ORANGE,
                     fill=WHITE_PURE if i % 2 == 0 else ORANGE_PALE)
    icon_badge(cv, 86, y0 - card_h / 2, 26, ORANGE, num, font_size=22)
    draw_text_left(cv, title_, 130, y0 - card_h / 2 + 20, "Helvetica-Bold", 24,
                   HexColor("#3D1800"))
    multiline_left(cv, desc, 130, y0 - card_h / 2 - 6,
                   W - 80 - 130 - 20, "Helvetica", 19, SLATE, lh=24)

cv.showPage()


# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 5 – RECHARGEABLE AID CARE
# ─────────────────────────────────────────────────────────────────────────────
cv.setFillColor(HexColor("#F5FDF8")); cv.rect(0, 0, W, H, fill=1, stroke=0)
draw_frame(cv, 5, header_bg=HexColor("#0D2B1A"))

cv.setFillColor(GREEN_PALE)
cv.roundRect(40, H - 268, W - 80, 118, 14, fill=1, stroke=0)
cv.setFillColor(GREEN); cv.roundRect(40, H - 268, 6, 118, 3, fill=1, stroke=0)
pill_tag(cv, "⚡  RECHARGEABLE AIDS", cx(), H - 188, GREEN, WHITE_PURE, 19)
draw_text_centered(cv, "Nightly Routine & Tips", H - 238, "Helvetica-Bold", 38,
                   HexColor("#0D2B1A"))

# Important callout
cv.setFillColor(HexColor("#FFFBEA"))
cv.setStrokeColor(GOLD); cv.setLineWidth(1.5)
cv.roundRect(40, H - 340, W - 80, 54, 10, fill=1, stroke=1)
cv.setFillColor(GOLD); cv.setFont("Helvetica-Bold", 20)
cv.drawCentredString(cx(), H - 318,
    "⚠  Cannot open battery compartment — nightly drying is CRITICAL")

steps_r = [
    ("1", "Power OFF Before Placing in Charger",
     "Press and hold the power button until the device turns off"),
    ("2", "Wipe Charging Contacts Dry",
     "Metal contacts on the base must be moisture-free before charging"),
    ("3", "Use Charging Case Overnight",
     "Phonak, ReSound & Starkey cases often include a built-in dehumidifier"),
    ("4", "Separate Dryer if No Built-In",
     "Use electronic dryer for 30–60 min before placing in the charger"),
    ("5", "Never Charge While Wet",
     "Moisture on contacts causes short circuits and charging errors"),
    ("6", "No Hairdryer or Oven",
     "Heat damages lithium-ion battery — voids warranty and risks fire"),
]
card_h = 130; gap = 10; start_y = H - 372

for i, (num, title_, desc) in enumerate(steps_r):
    y0 = start_y - i * (card_h + gap)
    left_accent_card(cv, 40, y0 - card_h, W - 80, card_h, GREEN,
                     fill=WHITE_PURE if i % 2 == 0 else GREEN_PALE)
    icon_badge(cv, 86, y0 - card_h / 2, 26, GREEN, num, font_size=22)
    draw_text_left(cv, title_, 130, y0 - card_h / 2 + 18, "Helvetica-Bold", 23,
                   HexColor("#0D2B1A"))
    multiline_left(cv, desc, 130, y0 - card_h / 2 - 6,
                   W - 80 - 130 - 20, "Helvetica", 19, SLATE, lh=24)

cv.showPage()


# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 6 – DRYING TOOLS
# ─────────────────────────────────────────────────────────────────────────────
cv.setFillColor(OFF_WHITE); cv.rect(0, 0, W, H, fill=1, stroke=0)
draw_frame(cv, 6)

cv.setFillColor(TEAL_PALE)
cv.roundRect(40, H - 260, W - 80, 118, 14, fill=1, stroke=0)
cv.setFillColor(TEAL); cv.roundRect(40, H - 260, 6, 118, 3, fill=1, stroke=0)
draw_text_centered(cv, "Drying Tools Guide", H - 182, "Helvetica-Bold", 46, NAVY)
draw_text_centered(cv, "Choose the right dryer for your aid", H - 230,
                   "Helvetica", 25, SLATE)

tools = [
    (SLATE,  "🫙", "Silica Gel Desiccant Jar",
     "Passive moisture absorption. Budget-friendly option.",
     "Replace silica gel monthly.", "Both aids"),
    (TEAL,   "🔌", "Electronic Drying Box",
     "Gentle heat + airflow. Most effective daily dryer.",
     "Use for 6–8 hours overnight — gold standard.", "Both aids"),
    (GOLD,   "☀", "UV-C Drying Box",
     "UV light kills bacteria & fungi + desiccant drying.",
     "Best choice during monsoon due to infection risk.", "Both aids"),
    (GREEN,  "⚡", "Charging Case with Dryer",
     "Dries the hearing aid while it charges overnight.",
     "Check your model — not all charging cases include this.", "Rechargeable only"),
]

card_h = 192; gap = 14; start_y = H - 298

for i, (col, emoji, name, line1, line2, for_) in enumerate(tools):
    y0 = start_y - i * (card_h + gap)
    left_accent_card(cv, 40, y0 - card_h, W - 80, card_h, col,
                     fill=TEAL_PALE if i % 2 == 0 else WHITE_PURE)
    # Emoji circle
    cv.setFillColor(HexColor(col.hexval() + "20"))
    cv.circle(96, y0 - card_h / 2 + 6, 36, fill=1, stroke=0)
    cv.setFillColor(col); cv.setFont("Helvetica", 36)
    cv.drawCentredString(96, y0 - card_h / 2 - 5, emoji)
    # Name
    draw_text_left(cv, name, 150, y0 - card_h / 2 + 38, "Helvetica-Bold", 24, NAVY)
    draw_text_left(cv, line1, 150, y0 - card_h / 2 + 12, "Helvetica", 19, SLATE)
    draw_text_left(cv, line2, 150, y0 - card_h / 2 - 12, "Helvetica", 19, SLATE)
    # For badge
    badge_col = TEAL if for_ == "Both aids" else GREEN
    bw = cv.stringWidth(for_, "Helvetica-Bold", 16) + 18
    cv.setFillColor(badge_col)
    cv.roundRect(W - 60 - bw, y0 - card_h / 2 - 34, bw, 28, 6, fill=1, stroke=0)
    cv.setFillColor(WHITE_PURE); cv.setFont("Helvetica-Bold", 16)
    cv.drawRightString(W - 52, y0 - card_h / 2 - 20, for_)

cv.showPage()


# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 7 – EMERGENCY: AID GOT WET
# ─────────────────────────────────────────────────────────────────────────────
cv.setFillColor(HexColor("#FDF5F5")); cv.rect(0, 0, W, H, fill=1, stroke=0)
draw_frame(cv, 7, header_bg=HexColor("#4A0000"))

cv.setFillColor(RED_PALE)
cv.roundRect(40, H - 268, W - 80, 118, 14, fill=1, stroke=0)
cv.setFillColor(RED); cv.roundRect(40, H - 268, 6, 118, 3, fill=1, stroke=0)
pill_tag(cv, "🚨  EMERGENCY PROTOCOL", cx(), H - 192, RED, WHITE_PURE, 20)
draw_text_centered(cv, "Hearing Aid Got Wet?", H - 238, "Helvetica-Bold", 40,
                   HexColor("#4A0000"))

steps_e = [
    ("Remove from water/rain IMMEDIATELY",          "Do not delay even a few seconds"),
    ("Power OFF — hold power button",               "Prevents short circuit from active current"),
    ("Do NOT press other buttons",                  "Pushing buttons drives moisture deeper inside"),
    ("Wipe exterior with dry lint-free cloth",      "Gently dab all ports, contacts & seams"),
    ("Battery aid: remove battery, open door",      "Exposes the interior to air drying"),
    ("Place in drying box for 24–48 hours",         "Electronic dryer or desiccant jar"),
    ("Rechargeable: do NOT charge until fully dry", "Moisture on contacts = short circuit"),
    ("Do NOT use rice, hairdryer or oven",          "Rice clogs ports; heat destroys components"),
    ("Still fails at 48 hrs? Call audiologist",     "Internal moisture needs professional drying"),
]
card_h = 114; gap = 8; start_y = H - 304

for i, (step, note) in enumerate(steps_e):
    y0 = start_y - i * (card_h + gap)
    fill = RED_PALE if i % 2 == 0 else WHITE_PURE
    left_accent_card(cv, 40, y0 - card_h, W - 80, card_h, RED, fill=fill)
    icon_badge(cv, 82, y0 - card_h / 2, 22, RED, str(i + 1), font_size=19)
    draw_text_left(cv, step, 122, y0 - card_h / 2 + 16, "Helvetica-Bold", 22,
                   HexColor("#4A0000"))
    draw_text_left(cv, note, 122, y0 - card_h / 2 - 8, "Helvetica", 18, SLATE)

cv.showPage()


# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 8 – DAILY CHECKLIST
# ─────────────────────────────────────────────────────────────────────────────
cv.setFillColor(OFF_WHITE); cv.rect(0, 0, W, H, fill=1, stroke=0)
draw_frame(cv, 8)

cv.setFillColor(TEAL_PALE)
cv.roundRect(40, H - 260, W - 80, 118, 14, fill=1, stroke=0)
cv.setFillColor(TEAL); cv.roundRect(40, H - 260, 6, 118, 3, fill=1, stroke=0)
draw_text_centered(cv, "Daily Monsoon Checklist", H - 180, "Helvetica-Bold", 44, NAVY)
draw_text_centered(cv, "Screenshot & tick these off each evening", H - 228,
                   "Helvetica-Oblique", 23, TEAL_MED)

checks = [
    ("Wipe aids with a dry lint-free cloth",              "Both"),
    ("Brush microphone & sound ports",                    "Both"),
    ("Open battery door fully for the night",             "Battery"),
    ("Wipe charging contacts before placing in charger",  "Rechargeable"),
    ("Place aids in drying box / charging case",          "Both"),
    ("Checked battery & replaced if weak",                "Battery"),
    ("Spare batteries in airtight + silica gel container","Battery"),
    ("Wore protective sleeve when outdoors",              "Both"),
    ("Did NOT store aids in the bathroom",                "Both"),
    ("Applied hairspray/sunscreen before inserting aids", "Both"),
]
row_h = 104; gap = 8; start_y = H - 298

badge_cols = {"Both": TEAL, "Battery": ORANGE, "Rechargeable": GREEN}

for i, (task, type_) in enumerate(checks):
    y0 = start_y - i * (row_h + gap)
    bg = TEAL_PALE if i % 2 == 0 else WHITE_PURE
    card(cv, 40, y0 - row_h, W - 80, row_h, fill=bg, stroke_col=RULE, radius=10)
    # Checkbox
    cv.setStrokeColor(TEAL_MED); cv.setLineWidth(1.5)
    cv.setFillColor(WHITE_PURE)
    cv.roundRect(58, y0 - row_h + row_h / 2 - 16, 32, 32, 5, fill=1, stroke=1)
    # Tick mark inside
    cv.setStrokeColor(RULE); cv.setLineWidth(1)
    cv.line(64, y0 - row_h + row_h / 2 - 3, 68, y0 - row_h + row_h / 2 - 8)
    cv.line(68, y0 - row_h + row_h / 2 - 8, 82, y0 - row_h + row_h / 2 + 6)
    # Task
    draw_text_left(cv, task, 106, y0 - row_h + row_h / 2 - 8,
                   "Helvetica", 21, NAVY)
    # Type badge
    bc = badge_cols.get(type_, TEAL)
    bw = cv.stringWidth(type_, "Helvetica-Bold", 15) + 14
    cv.setFillColor(bc)
    cv.roundRect(W - 52 - bw, y0 - row_h + row_h / 2 - 14, bw, 28, 6, fill=1, stroke=0)
    cv.setFillColor(WHITE_PURE); cv.setFont("Helvetica-Bold", 15)
    cv.drawRightString(W - 44, y0 - row_h + row_h / 2 - 2, type_)

cv.showPage()


# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 9 – CLOSING / BRAND CTA
# ─────────────────────────────────────────────────────────────────────────────
# Full navy background
cv.setFillColor(NAVY); cv.rect(0, 0, W, H, fill=1, stroke=0)
# Teal accent strip at very top
cv.setFillColor(TEAL_MED); cv.rect(0, H - 8, W, 8, fill=1, stroke=0)

# Large decorative circles
cv.setFillColor(HexColor("#FFFFFF06"))
cv.circle(W * 0.15, H * 0.82, 200, fill=1, stroke=0)
cv.circle(W * 0.88, H * 0.18, 160, fill=1, stroke=0)
cv.circle(cx(), H * 0.5, 340, fill=1, stroke=0)

# Clinic name block at top
cv.setFillColor(HexColor("#0E3A54"))
cv.roundRect(60, H - 160, W - 120, 80, 14, fill=1, stroke=0)
cv.setFillColor(TEAL_MED); cv.setFont("Helvetica-Bold", 24)
cv.drawCentredString(cx(), H - 130, CLINIC_NAME)

# Big checkmark badge
cv.setFillColor(TEAL_MED)
cv.circle(cx(), H * 0.60, 110, fill=1, stroke=0)
cv.setFillColor(WHITE_PURE); cv.setFont("Helvetica-Bold", 90)
cv.drawCentredString(cx(), H * 0.60 - 32, "✓")

draw_text_centered(cv, "You're All Set!", H * 0.46, "Helvetica-Bold", 62, WHITE_PURE)
draw_text_centered(cv, "Keep your hearing aids safe", H * 0.46 - 72,
                   "Helvetica", 28, SKY)
draw_text_centered(cv, "this monsoon season.", H * 0.46 - 110, "Helvetica", 28, SKY)

horiz_rule(cv, H * 0.37, color=HexColor("#FFFFFF20"), lw=1)

# Takeaway bullets
bullets = [
    "5 minutes of nightly care = months of extra device life",
    "Nightly drying box is your best investment this season",
    "Share this guide with every family caregiver",
    "Book your mid-monsoon audiologist check-up today",
]
by = H * 0.34
for b in bullets:
    cv.setFont("Helvetica", 23); cv.setFillColor(SKY)
    cv.drawCentredString(cx(), by, "—  " + b + "  —")
    by -= 46

# CTA button
cv.setFillColor(TEAL_MED)
cv.roundRect(cx() - 260, H * 0.15, 520, 72, 36, fill=1, stroke=0)
cv.setFillColor(WHITE_PURE); cv.setFont("Helvetica-Bold", 26)
cv.drawCentredString(cx(), H * 0.15 + 26, "Save  ·  Share  ·  Follow for more tips")

# Footer note
cv.setFillColor(MID_GREY); cv.setFont("Helvetica", 18)
cv.drawCentredString(cx(), 30, "Consult your audiologist for personalised hearing care advice")

dot_row(cv, 9, 8)
cv.showPage()


# ── Save ──────────────────────────────────────────────────────────────────────
cv.save()
print(f"Saved: {out}")
Running Command

cd /tmp/workspace/hearing-aid-guide && python create_branded_reel.py 2>&1

Running Command

ls -lh /tmp/workspace/hearing-aid-guide/Hearing_Aid_Monsoon_Branded_Reel.pdf

Your Branded Clinical carousel reel is ready:

Hearing Aid Monsoon Branded Reel

PDF Document · PDF


Here's what the design looks like across all 9 slides:
SlideContentDesign Detail
1 - CoverTitle + battery/rechargeable pillsNavy header, teal central icon badge, swipe CTA
2 - Risk Factors5 threat cardsColour-coded left accent bars (red/orange/gold/green/teal)
3 - General Rules8 rules with numbered badgesAlternating teal-pale/white rows
4 - Battery Care6 nightly stepsWarm orange theme, orange numbered circles
5 - Rechargeable Care6 nightly steps + critical callout bannerClinical green theme, gold warning strip
6 - Drying Tools4 dryer types with "Both/Rechargeable" badgesWhite card layout, teal accents
7 - Emergency9-step protocolRed accent bars, red numbered badges
8 - Daily Checklist10 tick-box rows with type badgesOrange/Green/Teal type-coding
9 - Closing CTAFull navy, large ✓, takeaways + Save/Share buttonFull branded dark close
Consistent branding on every slide:
  • [Your Clinic Name] in the top-left header bar - just replace with your actual name
  • Slide counter (e.g. "3 / 9") top-right
  • Navigation dots at the bottom
  • Footer: "Consult your audiologist for personalised advice"
To post: Export each page as a JPG from any PDF viewer, then upload as a carousel on Instagram, Facebook, or WhatsApp.

Create a short video script to narrate each reel slide

Here's the complete video narration script for all 9 slides, written in a warm, professional clinical tone — short enough to match a 3–5 second swipe pace per slide.

🎬 Video Narration Script — Hearing Aid Monsoon Care Reel

Format: Instagram/Social Media Carousel Voiceover Total estimated read time: ~90–100 seconds Tone: Warm, professional, clinical — like an audiologist speaking to a patient

🎙 SLIDE 1 — COVER

"Monsoon season is here — and for hearing aid users, it's the most important time of year to take care of your device. Whether you use battery-operated or rechargeable hearing aids, this guide is for you. Swipe through — it could save your hearing aid."
~7 sec | 🎵 Soft upbeat intro music fades in

🎙 SLIDE 2 — Why Monsoon Is Dangerous

"Here's why monsoon is risky for your hearing aids. Moisture corrodes the internal circuits. Water blocks the microphone and receiver ports. High humidity drains your battery up to 50% faster. And persistent dampness can actually grow mould inside your ear mould. These are real, preventable problems — so let's fix them."
~12 sec | 🎵 Music settles to soft background

🎙 SLIDE 3 — General Rules (Both Types)

"First, the rules that apply to every hearing aid. Wipe your aids every evening with a dry cloth. Brush the microphone ports daily. Never — and I mean never — store your aids in the bathroom. Use a protective sleeve when stepping outside. And always wear a hat or carry an umbrella in the rain. These five habits alone will protect your device all season."
~14 sec

🎙 SLIDE 4 — Battery-Operated Aid Care

"If you use battery-operated aids, this slide is for you. Every single night, open the battery door completely — this allows air to circulate and stops moisture from building up on the contacts. Place your aids in a drying box for six to eight hours. Keep your spare batteries in an airtight container with a silica gel packet. And during monsoon, expect to change batteries every five to six days instead of the usual seven to ten."
~16 sec

🎙 SLIDE 5 — Rechargeable Aid Care

"Rechargeable users — listen carefully. You cannot open the battery compartment, which means your nightly drying routine is absolutely critical. Always power the device off before placing it in the charger. Wipe the charging contacts dry — every night. Many modern charging cases from Phonak, ReSound, and Starkey have a built-in dehumidifier — use it. And never, ever charge a wet hearing aid — it can short circuit."
~16 sec

🎙 SLIDE 6 — Drying Tools

"So which drying tool should you use? A silica gel jar is a great budget option — just replace the silica monthly. An electronic drying box with gentle heat and airflow is the gold standard — six to eight hours overnight. A UV-C drying box also kills bacteria and fungi, which is especially valuable during monsoon. And if your charging case has a built-in dryer — that's your best option if you're on rechargeables."
~14 sec

🎙 SLIDE 7 — Emergency: Aid Got Wet

"If your hearing aid gets wet — act fast. Remove it from the water immediately. Power it off. Do not press any other buttons. Wipe the outside dry gently. For battery aids, remove the battery and open the door. Then place it in a drying box for twenty-four to forty-eight hours. Rechargeable users — do not put it back in the charger until it's completely dry. And please — no rice, no hairdryer, no oven. If it still doesn't work after 48 hours, call your audiologist."
~18 sec | 🎵 Slight tension in tone, then reassuring

🎙 SLIDE 8 — Daily Checklist

"Here's your simple daily checklist. Screenshot this. Wipe your aids. Brush the ports. Open the battery door or wipe the charging contacts. Put them in the drying box or charging case. Check the battery level. Keep spares airtight. Wear a protective sleeve outdoors. Five minutes. Every night. That's all it takes."
~12 sec | 🎵 Pace picks up slightly — checklist rhythm

🎙 SLIDE 9 — Closing CTA

"That's your complete monsoon hearing aid care guide. Five minutes of care each night can add months — even years — to the life of your device. Save this reel, share it with a family member who wears hearing aids, and follow us for more tips from our clinic. And if you have any concerns this monsoon — our door is always open. Your hearing matters."
~14 sec | 🎵 Warm closing music swells and fades

📋 Production Notes

ElementRecommendation
SpeakerAudiologist on camera OR voiceover only
Background musicSoft, calm — Lo-fi or light clinical background track
Caption styleAuto-captions ON (accessibility + silent viewers)
Slide timing3–5 sec per slide; total reel ~45–60 sec at normal swipe pace
Hook text overlaySlide 1: "Is monsoon destroying your hearing aid? 👇"
CTA text overlaySlide 9: "Follow + Save for more hearing health tips"
Language optionScript can be recorded in Hindi/regional language over the same slides

Tip: Record the full narration as one continuous audio track, then time the slide transitions to match the pauses between sections. Most social media scheduling tools (CapCut, InShot, Canva) let you set custom slide durations to sync with the voiceover.

Create a downloadable PDF script version for team use

Writing File

~/hearing-aid-guide/create_script_pdf.py

"""
Branded Clinical Script PDF – Hearing Aid Monsoon Care Reel
Professional team-use format: script + production notes per slide
"""

from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, PageBreak
)
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.lib.colors import HexColor, white, black
from reportlab.platypus.flowables import Flowable

# ── Colours ───────────────────────────────────────────────────────────────────
NAVY        = HexColor("#0A2540")
TEAL        = HexColor("#0B7285")
TEAL_MED    = HexColor("#1A9EBA")
TEAL_PALE   = HexColor("#E8F7FA")
SLATE       = HexColor("#3D5A6C")
OFF_WHITE   = HexColor("#F7FBFD")
ORANGE      = HexColor("#D95F00")
ORANGE_PALE = HexColor("#FFF0E6")
GREEN       = HexColor("#1A7A4A")
GREEN_PALE  = HexColor("#E8F5EE")
RED         = HexColor("#B02020")
RED_PALE    = HexColor("#FDF0F0")
GOLD        = HexColor("#C89B14")
GOLD_PALE   = HexColor("#FFFBEA")
MID_GREY    = HexColor("#8AA0AE")
RULE        = HexColor("#D0E8EF")
LIGHT_GREY  = HexColor("#F0F4F7")
DARK_GREY   = HexColor("#333333")

W, H = A4

# ── Page callbacks ─────────────────────────────────────────────────────────────
def on_first_page(canvas, doc):
    _draw_header(canvas, is_first=True)
    _draw_footer(canvas, doc.page)

def on_later_pages(canvas, doc):
    _draw_header(canvas, is_first=False)
    _draw_footer(canvas, doc.page)

def _draw_header(canvas, is_first=False):
    if is_first:
        # Full navy banner
        canvas.setFillColor(NAVY)
        canvas.rect(0, H - 2.6*cm, W, 2.6*cm, fill=1, stroke=0)
        canvas.setFillColor(TEAL_MED)
        canvas.rect(0, H - 2.6*cm - 5, W, 5, fill=1, stroke=0)
        canvas.setFillColor(white)
        canvas.setFont("Helvetica-Bold", 13)
        canvas.drawString(1.8*cm, H - 1.5*cm, "[Your Clinic Name]")
        canvas.setFont("Helvetica", 10)
        canvas.setFillColor(HexColor("#AACEDD"))
        canvas.drawRightString(W - 1.8*cm, H - 1.5*cm, "INTERNAL USE ONLY · TEAM SCRIPT DOCUMENT")
    else:
        canvas.setFillColor(NAVY)
        canvas.rect(0, H - 1.4*cm, W, 1.4*cm, fill=1, stroke=0)
        canvas.setFillColor(TEAL_MED)
        canvas.rect(0, H - 1.4*cm - 4, W, 4, fill=1, stroke=0)
        canvas.setFillColor(white)
        canvas.setFont("Helvetica-Bold", 9)
        canvas.drawString(1.8*cm, H - 0.96*cm,
                          "Hearing Aid Monsoon Care — Video Narration Script")
        canvas.setFont("Helvetica", 9)
        canvas.setFillColor(HexColor("#AACEDD"))
        canvas.drawRightString(W - 1.8*cm, H - 0.96*cm,
                               f"[Your Clinic Name]  ·  TEAM USE")

def _draw_footer(canvas, page_num):
    canvas.setFillColor(NAVY)
    canvas.rect(0, 0, W, 1.1*cm, fill=1, stroke=0)
    canvas.setFillColor(TEAL_MED)
    canvas.rect(0, 1.1*cm, W, 3, fill=1, stroke=0)
    canvas.setFillColor(HexColor("#7FAABD"))
    canvas.setFont("Helvetica", 8)
    canvas.drawString(1.8*cm, 0.38*cm,
                      "Confidential · For internal team and clinical staff use only · July 2026")
    canvas.drawRightString(W - 1.8*cm, 0.38*cm, f"Page {page_num}")


# ── Custom flowable: slide header band ────────────────────────────────────────
class SlideHeader(Flowable):
    def __init__(self, slide_num, title, duration, accent_col=TEAL, width=None):
        super().__init__()
        self.num      = slide_num
        self.title    = title
        self.duration = duration
        self.accent   = accent_col
        self._w       = width
        self.height   = 52

    def wrap(self, aW, aH):
        self._bw = self._w or aW
        return self._bw, self.height + 4

    def draw(self):
        c = self.canv
        bw, bh = self._bw, self.height
        # Background
        c.setFillColor(self.accent)
        c.roundRect(0, 0, bw, bh, 8, fill=1, stroke=0)
        # Slide number badge
        c.setFillColor(HexColor("#FFFFFF30"))
        c.circle(bh / 2, bh / 2, bh / 2 - 4, fill=1, stroke=0)
        c.setFillColor(white)
        c.setFont("Helvetica-Bold", 18)
        c.drawCentredString(bh / 2, bh / 2 - 7, str(self.num))
        # Title
        c.setFillColor(white)
        c.setFont("Helvetica-Bold", 13)
        c.drawString(bh + 10, bh / 2 + 3, self.title)
        # Duration pill (right side)
        dur_text = f"⏱  {self.duration}"
        c.setFont("Helvetica", 10)
        dw = c.stringWidth(dur_text, "Helvetica", 10) + 16
        c.setFillColor(HexColor("#FFFFFF25"))
        c.roundRect(bw - dw - 8, bh / 2 - 11, dw, 22, 5, fill=1, stroke=0)
        c.setFillColor(white)
        c.drawString(bw - dw - 0, bh / 2 - 5, dur_text)


# ── Styles ─────────────────────────────────────────────────────────────────────
def make_styles():
    base = getSampleStyleSheet()

    doc_title = ParagraphStyle("DocTitle",
        fontName="Helvetica-Bold", fontSize=26, textColor=white,
        leading=32, alignment=TA_CENTER, spaceAfter=4)

    doc_subtitle = ParagraphStyle("DocSubtitle",
        fontName="Helvetica", fontSize=13, textColor=HexColor("#B2E0EC"),
        leading=18, alignment=TA_CENTER, spaceAfter=2)

    doc_meta = ParagraphStyle("DocMeta",
        fontName="Helvetica-Oblique", fontSize=10, textColor=HexColor("#7FAABD"),
        alignment=TA_CENTER, spaceAfter=0)

    section_label = ParagraphStyle("SectionLabel",
        fontName="Helvetica-Bold", fontSize=9, textColor=TEAL_MED,
        leading=12, spaceBefore=14, spaceAfter=2,
        textTransform="uppercase")

    script_text = ParagraphStyle("ScriptText",
        fontName="Helvetica-Oblique", fontSize=11, textColor=DARK_GREY,
        leading=17, spaceAfter=6, alignment=TA_JUSTIFY,
        leftIndent=10, rightIndent=10)

    body = ParagraphStyle("Body",
        fontName="Helvetica", fontSize=10, textColor=SLATE,
        leading=15, spaceAfter=4, alignment=TA_JUSTIFY)

    bold_body = ParagraphStyle("BoldBody",
        fontName="Helvetica-Bold", fontSize=10, textColor=NAVY,
        leading=14, spaceAfter=3)

    note_text = ParagraphStyle("NoteText",
        fontName="Helvetica", fontSize=9.5, textColor=SLATE,
        leading=14, spaceAfter=2)

    note_bold = ParagraphStyle("NoteBold",
        fontName="Helvetica-Bold", fontSize=9.5, textColor=NAVY,
        leading=14, spaceAfter=2)

    tip = ParagraphStyle("Tip",
        fontName="Helvetica", fontSize=9.5, textColor=HexColor("#1B5E20"),
        backColor=GREEN_PALE, leading=14,
        leftIndent=6, rightIndent=6, spaceBefore=2, spaceAfter=4,
        borderPad=5)

    warn = ParagraphStyle("Warn",
        fontName="Helvetica-Bold", fontSize=9.5, textColor=RED,
        backColor=RED_PALE, leading=14,
        leftIndent=6, rightIndent=6, spaceBefore=2, spaceAfter=4,
        borderPad=5)

    return dict(
        doc_title=doc_title, doc_subtitle=doc_subtitle, doc_meta=doc_meta,
        section_label=section_label, script_text=script_text,
        body=body, bold_body=bold_body,
        note_text=note_text, note_bold=note_bold,
        tip=tip, warn=warn,
    )


# ── Build ──────────────────────────────────────────────────────────────────────
out = "/tmp/workspace/hearing-aid-guide/Hearing_Aid_Monsoon_Video_Script.pdf"
doc = SimpleDocTemplate(
    out, pagesize=A4,
    leftMargin=1.8*cm, rightMargin=1.8*cm,
    topMargin=3.2*cm, bottomMargin=1.8*cm,
    title="Hearing Aid Monsoon Care — Video Narration Script",
    author="[Your Clinic Name]",
)
S = make_styles()
story = []

# ── COVER BLOCK ───────────────────────────────────────────────────────────────
# Navy cover card
cover_inner = [
    [Paragraph("Hearing Aid Monsoon Care", S["doc_title"])],
    [Paragraph("Video Narration Script", S["doc_title"])],
    [Spacer(1, 6)],
    [Paragraph("Slide-by-Slide Script · Production Notes · Team Reference",
               S["doc_subtitle"])],
    [Spacer(1, 4)],
    [Paragraph("[Your Clinic Name]  ·  July 2026  ·  Internal Team Document",
               S["doc_meta"])],
]
cover_table = Table(cover_inner,
    colWidths=[W - 3.6*cm],
    style=TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), NAVY),
        ("TOPPADDING",    (0,0), (-1,-1), 10),
        ("BOTTOMPADDING", (0,0), (-1,-1), 10),
        ("LEFTPADDING",   (0,0), (-1,-1), 20),
        ("RIGHTPADDING",  (0,0), (-1,-1), 20),
        ("ROUNDEDCORNERS", (0,0), (-1,-1), [12,12,12,12]),
    ]))
story.append(cover_table)
story.append(Spacer(1, 0.4*cm))

# Quick-reference metadata table
meta_rows = [
    ["Format", "Instagram / Facebook / YouTube Shorts Carousel Reel"],
    ["Total Slides", "9 slides"],
    ["Total Narration Time", "~90–100 seconds (full read-through)"],
    ["Recommended Slide Duration", "3–5 seconds per slide"],
    ["Tone", "Warm · Professional · Clinical · Patient-facing"],
    ["Speaker", "Audiologist on camera  OR  professional voiceover"],
    ["Background Music", "Soft lo-fi or light clinical background track"],
    ["Captions", "Auto-captions ON recommended (accessibility + silent viewers)"],
    ["Language Options", "Script may be translated and re-recorded in regional languages"],
]
meta_style = TableStyle([
    ("BACKGROUND",    (0,0), (0,-1), TEAL_PALE),
    ("FONTNAME",      (0,0), (0,-1), "Helvetica-Bold"),
    ("FONTNAME",      (1,0), (1,-1), "Helvetica"),
    ("FONTSIZE",      (0,0), (-1,-1), 9.5),
    ("TOPPADDING",    (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
    ("LEFTPADDING",   (0,0), (-1,-1), 8),
    ("GRID",          (0,0), (-1,-1), 0.4, RULE),
    ("TEXTCOLOR",     (0,0), (0,-1), NAVY),
    ("TEXTCOLOR",     (1,0), (1,-1), SLATE),
    ("ROWBACKGROUNDS",(0,0), (-1,-1), [white, OFF_WHITE]),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
])
story.append(Table(meta_rows,
    colWidths=[(W-3.6*cm)*0.3, (W-3.6*cm)*0.7],
    style=meta_style))
story.append(Spacer(1, 0.3*cm))

# How to use box
how_data = [[Paragraph(
    "<b>How to use this script:</b>  Each section below corresponds to one carousel slide. "
    "The NARRATION block is the exact script to read or record. The PRODUCTION NOTES "
    "block contains on-screen text suggestions, music cues, and visual direction. "
    "Highlighted boxes in <font color='#1A7A4A'>green</font> are speaker tips; "
    "boxes in <font color='#B02020'>red</font> are critical warnings to emphasise in delivery.",
    S["body"])]]
story.append(Table(how_data, colWidths=[W-3.6*cm],
    style=TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), GOLD_PALE),
        ("BOX",           (0,0), (-1,-1), 1, GOLD),
        ("TOPPADDING",    (0,0), (-1,-1), 8),
        ("BOTTOMPADDING", (0,0), (-1,-1), 8),
        ("LEFTPADDING",   (0,0), (-1,-1), 10),
        ("RIGHTPADDING",  (0,0), (-1,-1), 10),
    ])))
story.append(Spacer(1, 0.5*cm))
story.append(HRFlowable(width="100%", thickness=1, color=RULE))
story.append(Spacer(1, 0.3*cm))


# ── SLIDE BLOCK BUILDER ───────────────────────────────────────────────────────
def slide_block(num, title, duration, accent,
                narration, prod_notes, tip_text=None, warn_text=None):
    """Returns a KeepTogether list of flowables for one slide."""
    items = []

    items.append(SlideHeader(num, title, duration, accent_col=accent))
    items.append(Spacer(1, 0.2*cm))

    # Narration
    items.append(Paragraph("NARRATION", S["section_label"]))
    # Script in a shaded card
    script_rows = [[Paragraph(f'"{narration}"', S["script_text"])]]
    items.append(Table(script_rows, colWidths=[W-3.6*cm],
        style=TableStyle([
            ("BACKGROUND",    (0,0), (-1,-1), TEAL_PALE),
            ("BOX",           (0,0), (-1,-1), 1, RULE),
            ("TOPPADDING",    (0,0), (-1,-1), 10),
            ("BOTTOMPADDING", (0,0), (-1,-1), 10),
            ("LEFTPADDING",   (0,0), (-1,-1), 12),
            ("RIGHTPADDING",  (0,0), (-1,-1), 12),
        ])))
    items.append(Spacer(1, 0.15*cm))

    # Production notes
    items.append(Paragraph("PRODUCTION NOTES", S["section_label"]))
    note_data = [[Paragraph(note, S["note_text"])] for note in prod_notes]
    for row in note_data:
        items.append(Table([row], colWidths=[W-3.6*cm],
            style=TableStyle([
                ("TOPPADDING",    (0,0), (-1,-1), 3),
                ("BOTTOMPADDING", (0,0), (-1,-1), 3),
                ("LEFTPADDING",   (0,0), (-1,-1), 4),
            ])))

    if tip_text:
        items.append(Paragraph(f"💡  {tip_text}", S["tip"]))
    if warn_text:
        items.append(Paragraph(f"⚠  {warn_text}", S["warn"]))

    items.append(Spacer(1, 0.35*cm))
    items.append(HRFlowable(width="100%", thickness=0.5, color=RULE))
    items.append(Spacer(1, 0.3*cm))

    return KeepTogether(items)


# ── SLIDES ─────────────────────────────────────────────────────────────────────

story.append(slide_block(
    num=1, title="COVER SLIDE", duration="~7 sec", accent=TEAL,
    narration=(
        "Monsoon season is here — and for hearing aid users, it's the most important time of year "
        "to take care of your device. Whether you use battery-operated or rechargeable hearing aids, "
        "this guide is for you. Swipe through — it could save your hearing aid."
    ),
    prod_notes=[
        "🎵  Music: Soft, upbeat intro track fades in as narration begins.",
        "📱  On-screen hook text overlay:  \"Is monsoon destroying your hearing aid? 👇\"",
        "🎥  Visual: Clinic logo / name animates in; audiologist smiling to camera optional.",
        "🎨  Slide shows: Title + battery/rechargeable type pills.",
        "⏩  Transition: Smooth slide-in from left to next card.",
    ],
    tip_text="Deliver the opening line with energy — the hook must stop the scroll."
))

story.append(slide_block(
    num=2, title="WHY MONSOON IS DANGEROUS", duration="~12 sec", accent=RED,
    narration=(
        "Here's why monsoon is risky for your hearing aids. Moisture corrodes the internal circuits. "
        "Water blocks the microphone and receiver ports. High humidity drains your battery up to "
        "50% faster. And persistent dampness can actually grow mould inside your ear mould. "
        "These are real, preventable problems — so let's fix them."
    ),
    prod_notes=[
        "🎵  Music: Settles to soft, calm background throughout the rest of the reel.",
        "📱  Emphasise the word 'preventable' — reassures the viewer.",
        "🎨  Slide shows: 5 colour-coded risk cards (corrosion, blocked ports, battery, mould, condensation).",
        "🎥  Optional B-roll: Close-up of hearing aid in rain, condensation on glass.",
        "⏩  Transition: Each risk card can 'tick' in sequentially if using CapCut/video.",
    ],
    warn_text="Do not rush this slide. Let each risk land before moving on."
))

story.append(slide_block(
    num=3, title="GENERAL RULES — BOTH AID TYPES", duration="~14 sec", accent=TEAL,
    narration=(
        "First, the rules that apply to every hearing aid. Wipe your aids every evening with a dry cloth. "
        "Brush the microphone ports daily. Never — and I mean never — store your aids in the bathroom. "
        "Use a protective sleeve when stepping outside. And always wear a hat or carry an umbrella in the rain. "
        "These five habits alone will protect your device all season."
    ),
    prod_notes=[
        "📱  On-screen text: Highlight each rule as it is spoken (sequential text animation).",
        "🎨  Slide shows: 8 alternating-row rule tiles with numbered badges.",
        "🎥  Optional: Speaker holds up fingers to count the 5 habits — very engaging on-camera.",
        "⏱  Pause slightly after 'never store your aids in the bathroom' — let it land.",
        "🗣  Tone: Friendly but firm. Like a trusted clinician giving a quick debrief.",
    ],
    tip_text="The 'bathroom' rule surprises most people — give it a beat of emphasis."
))

story.append(slide_block(
    num=4, title="BATTERY-OPERATED AID CARE", duration="~16 sec", accent=ORANGE,
    narration=(
        "If you use battery-operated aids, this slide is for you. Every single night, open the battery "
        "door completely — this allows air to circulate and stops moisture from building up on the contacts. "
        "Place your aids in a drying box for six to eight hours. Keep your spare batteries in an airtight "
        "container with a silica gel packet. And during monsoon, expect to change batteries every five to "
        "six days instead of the usual seven to ten."
    ),
    prod_notes=[
        "📱  On-screen graphic: Animated arrow opening battery door is very effective here.",
        "🎨  Slide shows: Orange-themed 6-step card layout.",
        "🎥  B-roll suggestion: Hands demonstrating opening battery door and placing in drying jar.",
        "⏱  Slowdown at '6–8 hours' and '5–6 days' — these are concrete numbers viewers need to remember.",
        "🗣  Tone: Practical, instructional — like showing a patient during a fitting session.",
    ],
    tip_text="Use a physical drying box as a prop on camera if recording in-clinic."
))

story.append(slide_block(
    num=5, title="RECHARGEABLE AID CARE", duration="~16 sec", accent=GREEN,
    narration=(
        "Rechargeable users — listen carefully. You cannot open the battery compartment, which means "
        "your nightly drying routine is absolutely critical. Always power the device off before placing "
        "it in the charger. Wipe the charging contacts dry — every night. Many modern charging cases "
        "from Phonak, ReSound, and Starkey have a built-in dehumidifier — use it. And never, ever "
        "charge a wet hearing aid — it can short circuit."
    ),
    prod_notes=[
        "📱  On-screen callout box: 'Cannot open battery compartment!' — matches the slide design.",
        "🎨  Slide shows: Green-themed steps + gold warning banner.",
        "🎥  B-roll suggestion: Demonstrating wiping charging contacts, placing in charging case.",
        "⏱  Emphasise 'never, ever charge a wet hearing aid' — pause before and after.",
        "🗣  Tone: Slightly more urgent for the 'cannot open' callout, then reassuring for the steps.",
        "📌  Mention specific brands (Phonak, ReSound, Starkey) to build clinical credibility.",
    ],
    warn_text="'Never charge a wet hearing aid' must be the most emphatic line in this slide."
))

story.append(slide_block(
    num=6, title="DRYING TOOLS GUIDE", duration="~14 sec", accent=TEAL_MED,
    narration=(
        "So which drying tool should you use? A silica gel jar is a great budget option — just "
        "replace the silica monthly. An electronic drying box with gentle heat and airflow is the "
        "gold standard — six to eight hours overnight. A UV-C drying box also kills bacteria and "
        "fungi, which is especially valuable during monsoon. And if your charging case has a built-in "
        "dryer — that's your best option if you're on rechargeables."
    ),
    prod_notes=[
        "📱  On-screen text: Each tool name highlights as it is mentioned.",
        "🎨  Slide shows: 4 white cards with left-accent colour bars and 'Both / Rechargeable' badges.",
        "🎥  B-roll: Show physical products — silica jar, Phonak drying case, UV-C box.",
        "🗣  Tone: Informative, comparative — help the viewer make a choice.",
        "🛒  Optional CTA text overlay: 'Ask your audiologist which dryer suits your model'.",
    ],
    tip_text="If your clinic sells drying products, this slide is a natural, non-pushy product mention."
))

story.append(slide_block(
    num=7, title="EMERGENCY — AID GOT WET", duration="~18 sec", accent=RED,
    narration=(
        "If your hearing aid gets wet — act fast. Remove it from the water immediately. Power it off. "
        "Do not press any other buttons. Wipe the outside dry gently. For battery aids, remove the "
        "battery and open the door. Then place it in a drying box for twenty-four to forty-eight hours. "
        "Rechargeable users — do not put it back in the charger until it's completely dry. And please — "
        "no rice, no hairdryer, no oven. If it still doesn't work after 48 hours, call your audiologist."
    ),
    prod_notes=[
        "📱  Text overlay: Step numbers animate in one by one — pacing matches the narration.",
        "🎨  Slide shows: Red-accented 9-step emergency list.",
        "🎵  Music: Very slight tension cue, then returns to reassuring tone at 'call your audiologist'.",
        "🎥  On-camera: Urgent but calm expression — clinic is a trusted resource in a crisis.",
        "⏱  This is the longest slide — allow full 18–20 seconds; do not rush.",
        "🗣  'No rice, no hairdryer, no oven' — say this with a slight pause between each; it's memorable.",
    ],
    warn_text=(
        "The rice myth is very common — call it out clearly. Many patients damage aids further by using rice."
    )
))

story.append(slide_block(
    num=8, title="DAILY CHECKLIST", duration="~12 sec", accent=TEAL,
    narration=(
        "Here's your simple daily checklist. Screenshot this. Wipe your aids. Brush the ports. "
        "Open the battery door or wipe the charging contacts. Put them in the drying box or charging case. "
        "Check the battery level. Keep spares airtight. Wear a protective sleeve outdoors. "
        "Five minutes. Every night. That's all it takes."
    ),
    prod_notes=[
        "📱  Text overlay at start: 'SCREENSHOT THIS ↓' — drives save action.",
        "🎨  Slide shows: 10-item tick-box checklist with orange/green/teal type badges.",
        "🎵  Music: Pace picks up slightly to match the checklist rhythm.",
        "🎥  Consider pointing at phone or a printed checklist on camera for visual engagement.",
        "🗣  Tone: Brisk, confident, rhythmic — like reading a pre-flight checklist.",
        "⏱  Slow down on the final three words: 'Five. Minutes. Every night.' — maximum impact.",
    ],
    tip_text="'Screenshot this' is one of the highest-save CTAs on educational reels — always include it."
))

story.append(slide_block(
    num=9, title="CLOSING / BRAND CTA", duration="~14 sec", accent=NAVY,
    narration=(
        "That's your complete monsoon hearing aid care guide. Five minutes of care each night can add "
        "months — even years — to the life of your device. Save this reel, share it with a family "
        "member who wears hearing aids, and follow us for more tips from our clinic. And if you have "
        "any concerns this monsoon — our door is always open. Your hearing matters."
    ),
    prod_notes=[
        "📱  On-screen text: 'Save · Share · Follow' button matches the slide's CTA button.",
        "🎨  Slide shows: Full navy background, large ✓ badge, takeaway bullets, clinic name.",
        "🎵  Music: Warm closing music swells gently and fades out completely.",
        "🎥  End on a smile and a nod to camera — warm, reassuring close.",
        "🗣  'Your hearing matters' — final line, deliver with warmth and directness.",
        "📌  Replace '[Your Clinic Name]' with your actual clinic name before publishing.",
        "🔗  Add your clinic's contact details / website link in the post caption.",
    ],
    tip_text=(
        "Record a 2-second pause after the last line before cutting — makes editing cleaner "
        "and gives viewers time to process the CTA."
    )
))


# ── PRODUCTION SUMMARY PAGE ────────────────────────────────────────────────────
story.append(PageBreak())
story.append(Spacer(1, 0.3*cm))

# Page title
title_rows = [[Paragraph("Production Summary & Publishing Checklist",
    ParagraphStyle("PT", fontName="Helvetica-Bold", fontSize=18,
                   textColor=white, alignment=TA_CENTER))]]
story.append(Table(title_rows, colWidths=[W-3.6*cm],
    style=TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), NAVY),
        ("TOPPADDING",    (0,0), (-1,-1), 12),
        ("BOTTOMPADDING", (0,0), (-1,-1), 12),
        ("LEFTPADDING",   (0,0), (-1,-1), 10),
    ])))
story.append(Spacer(1, 0.3*cm))

# Timing table
story.append(Paragraph("SLIDE-BY-SLIDE TIMING BREAKDOWN",
    ParagraphStyle("SL", fontName="Helvetica-Bold", fontSize=9, textColor=TEAL_MED,
                   spaceBefore=6, spaceAfter=4)))

timing_rows = [
    ["Slide", "Title", "Duration", "Cumulative"],
    ["1",  "Cover",                       "~7 sec",  "0:07"],
    ["2",  "Why Monsoon Is Dangerous",    "~12 sec", "0:19"],
    ["3",  "General Rules",               "~14 sec", "0:33"],
    ["4",  "Battery-Operated Aid Care",   "~16 sec", "0:49"],
    ["5",  "Rechargeable Aid Care",       "~16 sec", "1:05"],
    ["6",  "Drying Tools Guide",          "~14 sec", "1:19"],
    ["7",  "Emergency — Aid Got Wet",     "~18 sec", "1:37"],
    ["8",  "Daily Checklist",             "~12 sec", "1:49"],
    ["9",  "Closing / Brand CTA",         "~14 sec", "~1:63"],
    ["",   "TOTAL NARRATION TIME",        "~103 sec","~1 min 43 sec"],
]
t_style = TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), TEAL),
    ("TEXTCOLOR",     (0,0), (-1,0), white),
    ("FONTNAME",      (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE",      (0,0), (-1,-1), 9.5),
    ("TOPPADDING",    (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
    ("LEFTPADDING",   (0,0), (-1,-1), 8),
    ("GRID",          (0,0), (-1,-1), 0.4, RULE),
    ("ROWBACKGROUNDS",(0,1), (-1,-2), [white, TEAL_PALE]),
    ("BACKGROUND",    (0,-1), (-1,-1), NAVY),
    ("TEXTCOLOR",     (0,-1), (-1,-1), white),
    ("FONTNAME",      (0,-1), (-1,-1), "Helvetica-Bold"),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
])
col_w = [(W-3.6*cm)*f for f in [0.08, 0.46, 0.23, 0.23]]
story.append(Table(timing_rows, colWidths=col_w, style=t_style))
story.append(Spacer(1, 0.4*cm))

# Pre-publish checklist
story.append(Paragraph("PRE-PUBLISH CHECKLIST",
    ParagraphStyle("SL2", fontName="Helvetica-Bold", fontSize=9, textColor=TEAL_MED,
                   spaceBefore=4, spaceAfter=4)))

publish_checks = [
    "Replace all '[Your Clinic Name]' placeholders with your actual clinic name on slides",
    "Record narration audio — full read-through should be ~90–105 seconds",
    "Add background music track (royalty-free recommended — see platforms below)",
    "Sync slide transitions to match narration pace (use CapCut / InShot / Canva)",
    "Enable auto-captions for accessibility and silent-viewing audiences",
    "Add hook text overlay on Slide 1: 'Is monsoon damaging your hearing aid? 👇'",
    "Add 'SCREENSHOT THIS' overlay on Slide 8 (checklist slide)",
    "Add clinic contact details / website in the post caption",
    "Include relevant hashtags in the caption (see below)",
    "Test the full reel on mobile before posting — check text readability",
    "Schedule post for high-engagement time slot (typically 7–9 AM or 7–9 PM)",
]
for chk in publish_checks:
    chk_row = [[
        Paragraph("☐", ParagraphStyle("CB", fontName="Helvetica-Bold", fontSize=11,
                                       textColor=TEAL, leading=14)),
        Paragraph(chk, ParagraphStyle("CT", fontName="Helvetica", fontSize=9.5,
                                       textColor=SLATE, leading=14))
    ]]
    story.append(Table(chk_row, colWidths=[0.5*cm, W-3.6*cm-0.5*cm],
        style=TableStyle([
            ("TOPPADDING",    (0,0), (-1,-1), 3),
            ("BOTTOMPADDING", (0,0), (-1,-1), 3),
            ("LEFTPADDING",   (0,0), (-1,-1), 2),
            ("VALIGN",        (0,0), (-1,-1), "TOP"),
        ])))
story.append(Spacer(1, 0.3*cm))

# Hashtag suggestions
story.append(Paragraph("SUGGESTED HASHTAGS",
    ParagraphStyle("SL3", fontName="Helvetica-Bold", fontSize=9, textColor=TEAL_MED,
                   spaceBefore=4, spaceAfter=4)))

hashtag_text = (
    "#HearingAidCare  #MonsoonCare  #HearingHealth  #HearingAid  #Audiology  "
    "#RechargeableHearingAid  #HearingLoss  #HearingAidTips  #EarCare  "
    "#ClinicalAudiology  #PatientEducation  #HearingAidMaintenance  "
    "#MonsoonSeason  #HearingCareTips  #AudiologyClinic"
)
story.append(Table([[Paragraph(hashtag_text,
    ParagraphStyle("HT", fontName="Helvetica", fontSize=9.5,
                   textColor=TEAL, leading=15))]],
    colWidths=[W-3.6*cm],
    style=TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), TEAL_PALE),
        ("BOX",           (0,0), (-1,-1), 1, RULE),
        ("TOPPADDING",    (0,0), (-1,-1), 8),
        ("BOTTOMPADDING", (0,0), (-1,-1), 8),
        ("LEFTPADDING",   (0,0), (-1,-1), 10),
        ("RIGHTPADDING",  (0,0), (-1,-1), 10),
    ])))
story.append(Spacer(1, 0.3*cm))

# Music sources
story.append(Paragraph("ROYALTY-FREE MUSIC SOURCES",
    ParagraphStyle("SL4", fontName="Helvetica-Bold", fontSize=9, textColor=TEAL_MED,
                   spaceBefore=4, spaceAfter=4)))
music_rows = [
    ["Platform", "URL", "Best For"],
    ["YouTube Audio Library", "studio.youtube.com/channel/music", "Free, no attribution required"],
    ["Pixabay Music",         "pixabay.com/music",               "Free, commercial use allowed"],
    ["Uppbeat",               "uppbeat.io",                       "Clinical/calm tracks, free tier"],
    ["Epidemic Sound",        "epidemicsound.com",               "Subscription, professional quality"],
]
m_style = TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), SLATE),
    ("TEXTCOLOR",     (0,0), (-1,0), white),
    ("FONTNAME",      (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE",      (0,0), (-1,-1), 9),
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 8),
    ("GRID",          (0,0), (-1,-1), 0.4, RULE),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [white, LIGHT_GREY]),
    ("TEXTCOLOR",     (0,1), (-1,-1), SLATE),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
])
m_widths = [(W-3.6*cm)*f for f in [0.22, 0.44, 0.34]]
story.append(Table(music_rows, colWidths=m_widths, style=m_style))
story.append(Spacer(1, 0.4*cm))

# Footer note
footer_note = [[Paragraph(
    "<b>Confidentiality note:</b>  This document is prepared for internal clinic and team use only. "
    "The narration script and production notes are intended to guide recording, editing, and "
    "publishing of the hearing aid monsoon care reel. Do not distribute externally without "
    "replacing all placeholder text with your clinic's details.",
    ParagraphStyle("FN", fontName="Helvetica", fontSize=9, textColor=SLATE,
                   leading=13, alignment=TA_JUSTIFY))]]
story.append(Table(footer_note, colWidths=[W-3.6*cm],
    style=TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), LIGHT_GREY),
        ("BOX",           (0,0), (-1,-1), 1, RULE),
        ("TOPPADDING",    (0,0), (-1,-1), 8),
        ("BOTTOMPADDING", (0,0), (-1,-1), 8),
        ("LEFTPADDING",   (0,0), (-1,-1), 10),
        ("RIGHTPADDING",  (0,0), (-1,-1), 10),
    ])))


# ── Build ──────────────────────────────────────────────────────────────────────
doc.build(story, onFirstPage=on_first_page, onLaterPages=on_later_pages)
print(f"Saved: {out}")
Running Command

cd /tmp/workspace/hearing-aid-guide && python create_script_pdf.py 2>&1

Running Command

ls -lh /tmp/workspace/hearing-aid-guide/

Your team script PDF is ready:

Hearing Aid Monsoon Video Script

PDF Document · PDF


Here's exactly what's inside the document:

Pages 1–10 — Slide-by-Slide Script Blocks

Each slide gets its own colour-coded section with:
ElementWhat it contains
Slide header bandSlide number, title, and estimated duration
NARRATION boxExact word-for-word script in a shaded teal card
PRODUCTION NOTESMusic cues, on-screen text overlays, B-roll suggestions, camera direction, tone guidance
Green tip boxesSpeaker coaching tips (e.g. "Use a drying box as a prop on camera")
Red warning boxesCritical delivery notes (e.g. "Never charge a wet aid — most emphatic line")

Final Page — Production Summary

  • Slide-by-slide timing table with cumulative timestamps (total ~1 min 43 sec)
  • Pre-publish checklist with 11 tick-boxes for your team to check off
  • 15 suggested hashtags ready to copy-paste
  • Royalty-free music source table (YouTube Audio Library, Pixabay, Uppbeat, Epidemic Sound)
  • Confidentiality footer noting it is for internal team use only

Your complete content kit now includes:
FilePurpose

Hearing Aid Monsoon Care Guide

PDF Document · PDF

Share with patients & family

Hearing Aid Monsoon Branded Reel

PDF Document · PDF

Post as Instagram carousel

Hearing Aid Monsoon Video Script

PDF Document · PDF

Internal team production guide
This is a shared conversation. Sign in to Orris to start your own chat.