**PROFESSIONAL MASTER PROMPT FOR 10 HEALTH AWARENESS POSTS** Create a series of **10 Premium Medical Awareness Posts** in **Urdu** for social media sharing (1080x1080 px). ### OBJECTIVE: Design educational healthcare awareness posts about the most common and currently increasing health issues. Each post must provide: * Disease Name * Brief Introduction * Common Signs & Symptoms * Possible Causes * Prevention & Safety Measures * When to Consult a Doctor * Short Professional Disclaimer ### DESIGN STYLE: * Premium Hospital Branding * Modern Medical Infographic Style * Clean Healthcare Layout * White, Blue, Teal, and Green Color Theme * Professional Medical Icons and 3D Elements * Easy-to-read Urdu Typography * High Trust and Healthcare Authority Appearance * Suitable for WhatsApp Groups, Facebook, Instagram, and WhatsApp Status ### POST TOPICS: **Post 1:** مثانے کا انفیکشن (Bladder Infection) **Post 2:** گردوں کی پتھری (Kidney Stones) **Post 3:** بانجھ پن / اولاد نہ ہونا (Infertility) **Post 4:** ہائی بلڈ پریشر (High Blood Pressure) **Post 5:** ذیابیطس / شوگر (Diabetes) **Post 6:** کان، ناک اور گلے کی الرجی (ENT Allergies) **Post 7:** جوڑوں اور کمر کا درد (Joint & Back Pain) **Post 8:** پیشاب میں جلن اور انفیکشن (Urinary Tract Infection) **Post 9:** معدے کی تیزابیت اور گیس (Acidity & Gastric Problems) **Post 10:** موسمی بخار، نزلہ اور کھانسی (Seasonal Flu & Cough) ### FOOTER ON EVERY POST: **شفا آن لائن کنسلٹیشن** ✔ ماہر ڈاکٹروں سے آن لائن مشاورت ✔ گھر بیٹھے رہنمائی حاصل کریں ✔ Paid Consultation Services Available 📱 WhatsApp: +92XXXXXXXXXX ⏰ Appointment Required 💳 Paid Medical Consultation Service ### DISCLAIMER: "یہ معلومات صرف آگاہی کے لیے ہیں۔ تشخیص اور علاج کے لیے مستند ڈاکٹر سے مشورہ کریں۔" ### CONTENT REQUIREMENT: * Simple and Correct Urdu * Medically Accurate Information * Maximum 80-120 words per post * Professional Healthcare Tone * No Fear-Based Language * Focus on Awareness, Prevention, Safety, and Early Consultation

Running Command

mkdir -p /home/daytona/workspace/shifa-health-posts && ls /home/daytona/workspace/shifa-health-posts/

Writing File

~/shifa-health-posts/generate_posts.py

#!/usr/bin/env python3
"""
Generate 10 Premium Urdu Health Awareness Posts (1080x1080px)
Shifa Online Consultation - Medical Infographic Series
"""

from PIL import Image, ImageDraw, ImageFont
import os, sys, math, textwrap

OUTPUT_DIR = "/home/daytona/workspace/shifa-health-posts/output"
os.makedirs(OUTPUT_DIR, exist_ok=True)

# ── Color Palette ──────────────────────────────────────────────
C_BG         = (245, 250, 255)        # very light blue-white bg
C_HEADER_TOP = (0, 86, 150)           # deep medical blue
C_HEADER_BOT = (0, 140, 160)          # teal
C_ACCENT     = (0, 168, 120)          # green accent
C_CARD       = (255, 255, 255)        # white card
C_CARD_BD    = (210, 235, 245)        # card border
C_TITLE_TXT  = (255, 255, 255)        # white on header
C_SECTION_HD = (0, 100, 140)          # section heading
C_BODY_TXT   = (40,  55,  70)         # dark blue-grey body
C_FOOTER_BG  = (0, 86, 150)           # deep blue footer
C_FOOTER_TXT = (255, 255, 255)
C_DISC_BG    = (230, 245, 240)
C_DISC_TXT   = (50,  90,  80)
C_BADGE      = (0, 168, 120)
C_WHITE      = (255, 255, 255)
C_LIGHT_TEAL = (220, 245, 245)

W, H = 1080, 1080

# ── Font Setup ─────────────────────────────────────────────────
# We'll try system fonts with Urdu / Arabic support
def load_font(size, bold=False):
    candidates = [
        "/usr/share/fonts/truetype/noto/NotoNaskhArabic-Bold.ttf" if bold else
        "/usr/share/fonts/truetype/noto/NotoNaskhArabic-Regular.ttf",
        "/usr/share/fonts/truetype/noto/NotoNastaliqUrdu-Regular.ttf",
        "/usr/share/fonts/truetype/noto/NotoSansArabic-Bold.ttf" if bold else
        "/usr/share/fonts/truetype/noto/NotoSansArabic-Regular.ttf",
        "/usr/share/fonts/truetype/lohit-urdu/Lohit-Urdu.ttf",
        "/usr/share/fonts/truetype/freefont/FreeSans.ttf",
        "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
    ]
    for path in candidates:
        if os.path.exists(path):
            try:
                return ImageFont.truetype(path, size)
            except Exception:
                continue
    return ImageFont.load_default()

def list_arabic_fonts():
    import glob
    fonts = glob.glob("/usr/share/fonts/**/*.ttf", recursive=True)
    arabic = [f for f in fonts if any(k in f.lower() for k in ["arabic","urdu","nastaliq","naskh","noto"])]
    return arabic

print("Available Arabic/Urdu fonts:", list_arabic_fonts()[:10])

# ── Text helpers ───────────────────────────────────────────────
def draw_text_centered(draw, text, font, y, color, width=W, x_offset=0):
    """Draw centered text, returns bottom y."""
    bbox = draw.textbbox((0, 0), text, font=font)
    tw = bbox[2] - bbox[0]
    x = (width - tw) // 2 + x_offset
    draw.text((x, y), text, font=font, fill=color)
    return y + (bbox[3] - bbox[1]) + 4

def draw_text_right(draw, text, font, x_right, y, color):
    bbox = draw.textbbox((0, 0), text, font=font)
    tw = bbox[2] - bbox[0]
    draw.text((x_right - tw, y), text, font=font, fill=color)
    return y + (bbox[3] - bbox[1]) + 4

def text_height(draw, text, font):
    bbox = draw.textbbox((0, 0), text, font=font)
    return bbox[3] - bbox[1]

def draw_wrapped_rtl(draw, text, font, x_left, x_right, y, color, line_spacing=8):
    """Simple right-aligned wrapped text block for RTL languages."""
    words = text.split()
    lines = []
    current = []
    max_w = x_right - x_left
    for word in words:
        test = " ".join(current + [word])
        bbox = draw.textbbox((0, 0), test, font=font)
        if bbox[2] - bbox[0] <= max_w:
            current.append(word)
        else:
            if current:
                lines.append(" ".join(current))
            current = [word]
    if current:
        lines.append(" ".join(current))

    for line in lines:
        bbox = draw.textbbox((0, 0), line, font=font)
        tw = bbox[2] - bbox[0]
        th = bbox[3] - bbox[1]
        draw.text((x_right - tw, y), line, font=font, fill=color)
        y += th + line_spacing
    return y

# ── Shape helpers ──────────────────────────────────────────────
def rounded_rect(draw, xy, radius, fill, outline=None, outline_width=2):
    x1, y1, x2, y2 = xy
    draw.rounded_rectangle([x1, y1, x2, y2], radius=radius, fill=fill,
                            outline=outline, width=outline_width)

def gradient_rect(img, x1, y1, x2, y2, color_top, color_bot):
    """Vertical gradient by drawing horizontal lines."""
    draw = ImageDraw.Draw(img)
    height = y2 - y1
    for i in range(height):
        t = i / max(height - 1, 1)
        r = int(color_top[0] + (color_bot[0] - color_top[0]) * t)
        g = int(color_top[1] + (color_bot[1] - color_top[1]) * t)
        b = int(color_top[2] + (color_bot[2] - color_top[2]) * t)
        draw.line([(x1, y1 + i), (x2, y1 + i)], fill=(r, g, b))

def draw_circle(draw, cx, cy, r, fill, outline=None, ow=2):
    draw.ellipse([cx-r, cy-r, cx+r, cy+r], fill=fill, outline=outline, width=ow)

def draw_icon_medical_cross(draw, cx, cy, size, color):
    """Draw a simple medical cross."""
    t = size // 4
    draw.rectangle([cx - t, cy - size//2, cx + t, cy + size//2], fill=color)
    draw.rectangle([cx - size//2, cy - t, cx + size//2, cy + t], fill=color)

def draw_decorative_bg(img):
    """Add subtle decorative circles to background."""
    draw = ImageDraw.Draw(img)
    # Large faint circle top-right
    draw_circle(draw, 980, 80, 120, (0, 140, 160, 30))
    draw_circle(draw, 100, 200, 80, (0, 168, 120, 20))
    draw_circle(draw, 950, 500, 60, (0, 86, 150, 15))

# ── Section icon emoji-style symbols ──────────────────────────
ICONS = {
    "intro":     "📋",
    "symptoms":  "🩺",
    "causes":    "🔬",
    "prevention":"🛡",
    "doctor":    "👨‍⚕️",
}

# ── Post Data ──────────────────────────────────────────────────
POSTS = [
    {
        "num": 1,
        "emoji": "🫀",
        "title_ur": "مثانے کا انفیکشن",
        "title_en": "Bladder Infection (UTI)",
        "color_accent": (0, 130, 180),
        "intro": "مثانے کا انفیکشن ایک عام بیماری ہے جو بیکٹیریا کی وجہ سے ہوتی ہے اور بروقت علاج سے ٹھیک ہو جاتی ہے۔",
        "symptoms": "پیشاب میں جلن، بار بار پیشاب آنا، پیٹ کے نچلے حصے میں درد، بدبودار یا دھندلا پیشاب",
        "causes": "بیکٹیریا (E. coli)، صفائی کا خیال نہ رکھنا، پانی کم پینا، ذیابیطس",
        "prevention": "کافی پانی پئیں، صفائی کا خیال رکھیں، پیشاب روکنے سے گریز کریں، قوت مدافعت بڑھائیں",
        "doctor": "اگر بخار ہو، کمر میں درد ہو، یا علامات 2 دن سے زیادہ رہیں تو فوری ڈاکٹر سے رجوع کریں",
    },
    {
        "num": 2,
        "emoji": "🪨",
        "title_ur": "گردوں کی پتھری",
        "title_en": "Kidney Stones",
        "color_accent": (0, 120, 170),
        "intro": "گردوں میں معدنی نمکیات جمع ہو کر پتھری بناتے ہیں۔ یہ بہت تکلیف دہ لیکن قابل علاج مسئلہ ہے۔",
        "symptoms": "کمر یا پہلو میں شدید درد، پیشاب میں خون، متلی، الٹی، پیشاب میں رکاوٹ",
        "causes": "کم پانی پینا، کیلشیم / آکسیلیٹ والی غذائیں زیادہ کھانا، موروثی عوامل، بیٹھا رہنا",
        "prevention": "روزانہ 8-10 گلاس پانی پئیں، نمک کم کھائیں، متوازن غذا اپنائیں، ورزش کریں",
        "doctor": "پیٹ یا کمر میں شدید درد، پیشاب میں خون یا پیشاب بند ہو جائے تو فوری ڈاکٹر سے ملیں",
    },
    {
        "num": 3,
        "emoji": "👶",
        "title_ur": "بانجھ پن / اولاد نہ ہونا",
        "title_en": "Infertility",
        "color_accent": (0, 150, 130),
        "intro": "بانجھ پن کوئی لاعلاج بیماری نہیں۔ جدید طبی علاج سے بہت سے جوڑے اولاد کی نعمت پا سکتے ہیں۔",
        "symptoms": "ایک سال کوشش کے باوجود حمل نہ ہونا، ماہواری کی بے ترتیبی، ہارمون کی خرابی",
        "causes": "ہارمون کا عدم توازن، PCOS، فیلوپین ٹیوب میں رکاوٹ، مردوں میں سپرم کی کمی، تناؤ",
        "prevention": "صحت مند وزن برقرار رکھیں، تناؤ کم کریں، سگریٹ و شراب سے پرہیز، بروقت معائنہ کروائیں",
        "doctor": "اگر ایک سال سے حمل نہ ہو تو ماہر ڈاکٹر سے رجوع کریں۔ جلد تشخیص بہتر نتائج دیتی ہے",
    },
    {
        "num": 4,
        "emoji": "❤️",
        "title_ur": "ہائی بلڈ پریشر",
        "title_en": "High Blood Pressure (Hypertension)",
        "color_accent": (180, 50, 60),
        "intro": "ہائی بلڈ پریشر کو 'خاموش قاتل' کہا جاتا ہے۔ باقاعدہ چیک اپ اور علاج سے اسے قابو کیا جا سکتا ہے۔",
        "symptoms": "سر درد، چکر آنا، دھندلی نظر، سینے میں درد، سانس لینے میں دشواری، ناک سے خون",
        "causes": "نمک زیادہ کھانا، موٹاپا، ورزش نہ کرنا، تناؤ، موروثی، ذیابیطس، سگریٹ نوشی",
        "prevention": "نمک کم کریں، ورزش کریں، وزن کنٹرول کریں، تناؤ سے بچیں، باقاعدہ BP چیک کروائیں",
        "doctor": "اگر BP 140/90 سے زیادہ ہو، سر درد شدید ہو یا سینے میں درد ہو تو فوری ڈاکٹر سے ملیں",
    },
    {
        "num": 5,
        "emoji": "🩸",
        "title_ur": "ذیابیطس / شوگر",
        "title_en": "Diabetes (Sugar Disease)",
        "color_accent": (0, 140, 100),
        "intro": "ذیابیطس ایک دائمی بیماری ہے جو خون میں شکر کی سطح بڑھا دیتی ہے۔ طرز زندگی بدل کر اسے قابو کریں۔",
        "symptoms": "بار بار پیشاب، زیادہ پیاس، وزن میں کمی، تھکاوٹ، زخم دیر سے بھرنا، نظر کمزور ہونا",
        "causes": "موٹاپا، ورزش نہ کرنا، غیر صحت بخش کھانا، موروثی، ہارمون کی خرابی",
        "prevention": "میٹھا کم کھائیں، ورزش کریں، وزن کنٹرول کریں، باقاعدہ بلڈ شوگر ٹیسٹ کروائیں",
        "doctor": "اگر بلڈ شوگر بار بار زیادہ آئے، چکر آئے یا علامات ظاہر ہوں تو فوری ڈاکٹر سے ملیں",
    },
    {
        "num": 6,
        "emoji": "🤧",
        "title_ur": "کان، ناک اور گلے کی الرجی",
        "title_en": "ENT Allergies",
        "color_accent": (0, 120, 180),
        "intro": "ENT الرجی بہت عام مسئلہ ہے۔ دھول، دھواں اور موسمی تبدیلیاں اس کی بڑی وجوہات ہیں۔",
        "symptoms": "چھینکیں، ناک بند یا بہنا، آنکھوں میں خارش، گلے میں خراش، کان میں بھاری پن",
        "causes": "دھول، جرگ، پالتو جانور، کیمیکل، موسمی تبدیلی، کمزور قوت مدافعت",
        "prevention": "دھول سے بچیں، ماسک پہنیں، گھر صاف رکھیں، الرجی کا ٹیسٹ کروائیں، قوت مدافعت بڑھائیں",
        "doctor": "اگر سانس لینے میں دشواری ہو، علامات 2 ہفتے سے زیادہ رہیں تو ENT ماہر سے ملیں",
    },
    {
        "num": 7,
        "emoji": "🦴",
        "title_ur": "جوڑوں اور کمر کا درد",
        "title_en": "Joint & Back Pain",
        "color_accent": (100, 80, 160),
        "intro": "جوڑوں اور کمر کا درد روزمرہ زندگی متاثر کرتا ہے۔ بروقت علاج اور ورزش سے بہتری ممکن ہے۔",
        "symptoms": "جوڑوں میں سوجن و اکڑن، کمر میں درد، حرکت میں دشواری، صبح کے وقت اکڑن",
        "causes": "آرتھرائٹس، یورک ایسڈ، موٹاپا، غلط بیٹھنے کا انداز، کیلشیم کی کمی، چوٹ",
        "prevention": "ورزش کریں، وزن کم کریں، کیلشیم / وٹامن D لیں، صحیح بیٹھیں، بھاری وزن نہ اٹھائیں",
        "doctor": "اگر درد شدید ہو، سوجن آئے یا چلنا مشکل ہو جائے تو آرتھوپیڈک ڈاکٹر سے ملیں",
    },
    {
        "num": 8,
        "emoji": "💧",
        "title_ur": "پیشاب میں جلن اور انفیکشن",
        "title_en": "Urinary Tract Infection (UTI)",
        "color_accent": (0, 140, 160),
        "intro": "UTI خواتین میں بہت عام ہے۔ بروقت علاج نہ ہو تو گردوں تک پہنچ سکتا ہے۔",
        "symptoms": "پیشاب میں جلن، بار بار آنا، رنگ غیر معمولی، بدبو، پیٹ کے نچلے حصے میں درد",
        "causes": "بیکٹیریا، صفائی نہ رکھنا، پانی کم پینا، ذیابیطس، قوت مدافعت کی کمزوری",
        "prevention": "پانی خوب پئیں، صفائی کا خیال رکھیں، نرم کپڑے پہنیں، پیشاب روکنے سے گریز کریں",
        "doctor": "اگر بخار، ٹھنڈ یا کمر درد کے ساتھ جلن ہو تو فوری ڈاکٹر سے رجوع کریں",
    },
    {
        "num": 9,
        "emoji": "🫁",
        "title_ur": "معدے کی تیزابیت اور گیس",
        "title_en": "Acidity & Gastric Problems",
        "color_accent": (180, 110, 20),
        "intro": "معدے کی تیزابیت آج کل بہت عام ہے۔ غلط کھانا اور بے ترتیب زندگی اس کی بڑی وجہ ہے۔",
        "symptoms": "سینے میں جلن، ڈکار، پیٹ پھولنا، متلی، منہ میں کھٹاس، کھانے کے بعد تکلیف",
        "causes": "مسالہ دار کھانا، چائے / کافی زیادہ، کھانے میں بے ترتیبی، تناؤ، سگریٹ نوشی",
        "prevention": "کم مسالہ کھائیں، بروقت کھانا کھائیں، پانی پئیں، تناؤ کم کریں، تھوڑا تھوڑا کھائیں",
        "doctor": "اگر سینے میں شدید جلن، خون آئے یا وزن کم ہو تو فوری ڈاکٹر سے ملیں",
    },
    {
        "num": 10,
        "emoji": "🌡️",
        "title_ur": "موسمی بخار، نزلہ اور کھانسی",
        "title_en": "Seasonal Flu & Cough",
        "color_accent": (0, 130, 160),
        "intro": "موسم کی تبدیلی میں نزلہ، بخار اور کھانسی بہت عام ہیں۔ احتیاط اور صفائی سے بچاؤ ممکن ہے۔",
        "symptoms": "بخار، ناک بہنا یا بند ہونا، گلے میں خراش، کھانسی، جسم درد، کمزوری",
        "causes": "وائرس / بیکٹیریا، موسمی تبدیلی، کمزور قوت مدافعت، بھیڑ میں رہنا",
        "prevention": "ہاتھ دھوئیں، ماسک پہنیں، گرم پانی پئیں، قوت مدافعت بڑھائیں، فلو ویکسین لگوائیں",
        "doctor": "اگر بخار 3 دن سے زیادہ رہے، سانس لینے میں دشواری ہو تو فوری ڈاکٹر سے ملیں",
    },
]

SECTION_LABELS = [
    ("intro",      "تعارف"),
    ("symptoms",   "علامات"),
    ("causes",     "وجوہات"),
    ("prevention", "احتیاط و بچاؤ"),
    ("doctor",     "ڈاکٹر سے کب ملیں"),
]

SECTION_ICONS = {
    "intro":      "📋",
    "symptoms":   "🩺",
    "causes":     "🔬",
    "prevention": "🛡️",
    "doctor":     "👨‍⚕️",
}

FOOTER_LINES = [
    "شفا آن لائن کنسلٹیشن",
    "✔ ماہر ڈاکٹروں سے آن لائن مشاورت    ✔ گھر بیٹھے رہنمائی حاصل کریں",
    "📱 WhatsApp: +92XXXXXXXXXX    ⏰ Appointment Required",
    "💳 Paid Consultation Services Available",
]

DISCLAIMER = "یہ معلومات صرف آگاہی کے لیے ہیں۔ تشخیص اور علاج کے لیے مستند ڈاکٹر سے مشورہ کریں۔"

def make_post(post):
    img = Image.new("RGB", (W, H), C_BG)
    draw = ImageDraw.Draw(img)

    accent = post["color_accent"]

    # ── Background decorative circles ──────────────────────────
    for cx, cy, r, alpha in [(960, 60, 110, 18), (120, 180, 70, 15), (940, 540, 55, 12)]:
        overlay = Image.new("RGBA", (W, H), (0, 0, 0, 0))
        od = ImageDraw.Draw(overlay)
        od.ellipse([cx-r, cy-r, cx+r, cy+r], fill=(*C_HEADER_BOT, alpha))
        img.paste(Image.alpha_composite(img.convert("RGBA"), overlay).convert("RGB"))
        draw = ImageDraw.Draw(img)

    # ── Header gradient ─────────────────────────────────────────
    gradient_rect(img, 0, 0, W, 180, C_HEADER_TOP, C_HEADER_BOT)
    draw = ImageDraw.Draw(img)

    # Header decorative arc (top right)
    draw.ellipse([780, -80, 1160, 260], outline=(255,255,255,40), width=3)
    draw.ellipse([820, -60, 1120, 220], outline=(255,255,255,25), width=2)

    # Post number badge
    badge_r = 28
    draw_circle(draw, 60, 60, badge_r, C_ACCENT)
    fnt_badge = load_font(22, bold=True)
    num_str = str(post["num"])
    b = draw.textbbox((0,0), num_str, font=fnt_badge)
    draw.text((60 - (b[2]-b[0])//2, 60 - (b[3]-b[1])//2), num_str, font=fnt_badge, fill=C_WHITE)

    # Medical cross icon (top left area)
    draw_icon_medical_cross(draw, 115, 60, 28, (255,255,255,180))

    # Emoji icon (large, right side of header)
    fnt_emoji_large = load_font(64)
    emoji = post["emoji"]
    eb = draw.textbbox((0,0), emoji, font=fnt_emoji_large)
    draw.text((W - 100 - (eb[2]-eb[0])//2, 58 - (eb[3]-eb[1])//2), emoji, font=fnt_emoji_large, fill=C_WHITE)

    # Title Urdu
    fnt_title_big = load_font(52, bold=True)
    fnt_title_sm  = load_font(24)
    tb = draw.textbbox((0,0), post["title_ur"], font=fnt_title_big)
    tw = tb[2] - tb[0]
    draw.text(((W - tw)//2, 26), post["title_ur"], font=fnt_title_big, fill=C_WHITE)

    # Title English subtitle
    eb2 = draw.textbbox((0,0), post["title_en"], font=fnt_title_sm)
    draw.text(((W - (eb2[2]-eb2[0]))//2, 104), post["title_en"], font=fnt_title_sm, fill=(200, 235, 255))

    # Divider line under header
    draw.rectangle([40, 182, W-40, 185], fill=C_ACCENT)

    # ── Content cards ───────────────────────────────────────────
    card_x1, card_x2 = 30, W - 30
    card_y = 196
    card_gap = 8

    fnt_sec_hd  = load_font(26, bold=True)
    fnt_body    = load_font(22)
    fnt_icon    = load_font(22)

    section_data = [
        ("intro",      "تعارف",         post["intro"]),
        ("symptoms",   "علامات",         post["symptoms"]),
        ("causes",     "وجوہات",         post["causes"]),
        ("prevention", "احتیاط و بچاؤ",  post["prevention"]),
        ("doctor",     "ڈاکٹر سے کب ملیں", post["doctor"]),
    ]

    # We need to pre-compute card heights to fit everything
    # Estimate lines per section
    def estimate_lines(text, font, max_w):
        words = text.split()
        lines, current_w = 0, 0
        for w in words:
            wb = draw.textbbox((0,0), w+" ", font=font)[2]
            if current_w + wb > max_w:
                lines += 1
                current_w = wb
            else:
                current_w += wb
        return lines + 1

    # Fixed heights for cards - calculate remaining space
    # Header = 185, Footer ~= 175, Disclaimer ~= 40, gaps
    available_h = H - 185 - 175 - 48 - card_gap * 6
    # 5 cards
    card_h_each = available_h // 5  # approx 95px

    inner_pad = 10
    for key, label, text in section_data:
        ch = card_h_each
        # Draw card background
        rounded_rect(draw, [card_x1, card_y, card_x2, card_y + ch], 14,
                     fill=C_CARD, outline=C_CARD_BD, outline_width=1)

        # Left accent bar with section color
        draw.rounded_rectangle([card_x1, card_y, card_x1+6, card_y+ch],
                                radius=8, fill=accent)

        # Section icon + label on right
        icon_str = SECTION_ICONS.get(key, "•")
        icon_x = W - 55
        ib = draw.textbbox((0,0), icon_str, font=fnt_icon)
        draw.text((icon_x, card_y + inner_pad), icon_str, font=fnt_icon, fill=accent)

        # Section heading
        lb = draw.textbbox((0,0), label, font=fnt_sec_hd)
        lw = lb[2] - lb[0]
        draw.text((W - 70 - lw, card_y + inner_pad - 2), label, font=fnt_sec_hd, fill=C_SECTION_HD)

        # Body text (right-aligned, wrapped)
        text_y = card_y + inner_pad + (lb[3]-lb[1]) + 6
        text_max_w = card_x2 - card_x1 - 20
        draw_wrapped_rtl(draw, text, fnt_body,
                         card_x1 + 14, card_x2 - 14,
                         text_y, C_BODY_TXT, line_spacing=4)

        card_y += ch + card_gap

    # ── Disclaimer strip ────────────────────────────────────────
    disc_y = card_y + 4
    disc_h = 38
    rounded_rect(draw, [30, disc_y, W-30, disc_y+disc_h], 10,
                 fill=C_DISC_BG, outline=(0,168,120), outline_width=1)
    fnt_disc = load_font(18)
    db = draw.textbbox((0,0), DISCLAIMER, font=fnt_disc)
    dw = db[2] - db[0]
    draw.text(((W - dw)//2, disc_y + (disc_h - (db[3]-db[1]))//2),
              DISCLAIMER, font=fnt_disc, fill=C_DISC_TXT)

    # ── Footer ──────────────────────────────────────────────────
    footer_y = disc_y + disc_h + 6
    footer_h = H - footer_y - 2
    gradient_rect(img, 0, footer_y, W, H, C_FOOTER_BG, (0, 50, 100))
    draw = ImageDraw.Draw(img)

    # Footer top divider
    draw.rectangle([0, footer_y, W, footer_y+3], fill=C_ACCENT)

    fnt_footer_big = load_font(30, bold=True)
    fnt_footer_sm  = load_font(19)
    fnt_footer_xs  = load_font(16)

    fy = footer_y + 10
    # Line 1: Brand name
    fl1b = draw.textbbox((0,0), FOOTER_LINES[0], font=fnt_footer_big)
    draw.text(((W - (fl1b[2]-fl1b[0]))//2, fy), FOOTER_LINES[0],
              font=fnt_footer_big, fill=C_WHITE)
    fy += (fl1b[3]-fl1b[1]) + 6

    # Line 2
    fl2b = draw.textbbox((0,0), FOOTER_LINES[1], font=fnt_footer_sm)
    draw.text(((W - (fl2b[2]-fl2b[0]))//2, fy), FOOTER_LINES[1],
              font=fnt_footer_sm, fill=(200, 235, 255))
    fy += (fl2b[3]-fl2b[1]) + 5

    # Line 3
    fl3b = draw.textbbox((0,0), FOOTER_LINES[2], font=fnt_footer_sm)
    draw.text(((W - (fl3b[2]-fl3b[0]))//2, fy), FOOTER_LINES[2],
              font=fnt_footer_sm, fill=(200, 235, 255))
    fy += (fl3b[3]-fl3b[1]) + 5

    # Line 4
    fl4b = draw.textbbox((0,0), FOOTER_LINES[3], font=fnt_footer_xs)
    draw.text(((W - (fl4b[2]-fl4b[0]))//2, fy), FOOTER_LINES[3],
              font=fnt_footer_xs, fill=(180, 220, 255))

    # Save
    fn = f"post_{post['num']:02d}_{post['title_en'].replace(' ','_').replace('(','').replace(')','')}.png"
    out_path = os.path.join(OUTPUT_DIR, fn)
    img.save(out_path, "PNG", dpi=(150,150))
    print(f"  Saved: {fn}")
    return out_path

print("\n=== Generating 10 Health Awareness Posts ===\n")
saved = []
for p in POSTS:
    print(f"Post {p['num']}: {p['title_ur']}")
    path = make_post(p)
    saved.append(path)

print(f"\n✅ All {len(saved)} posts generated in: {OUTPUT_DIR}")
Running Command

cd /home/daytona/workspace/shifa-health-posts && python3 generate_posts.py 2>&1

Running Command

fc-list | grep -i "noto\|arabic\|urdu\|nastaliq\|naskh" | head -20; echo "---"; find /usr/share/fonts -name "*.ttf" | grep -i "noto" | head -20

Running Command

fc-list | head -30; find /usr/share/fonts -name "*.ttf" | head -20; ls /usr/share/fonts/ 2>/dev/null | head -20

Running Command

pip install --user arabic-reshaper python-bidi 2>&1 | tail -5; python3 -c "import arabic_reshaper; print('arabic_reshaper OK')" 2>&1

Running Command

# Download a proper Arabic/Urdu font - Amiri (beautiful Naskh style) mkdir -p /home/daytona/workspace/shifa-health-posts/fonts wget -q "https://github.com/aliftype/amiri/releases/download/1.000/Amiri-1.000.zip" -O /tmp/amiri.zip && \ unzip -q /tmp/amiri.zip -d /tmp/amiri_extracted/ && \ find /tmp/amiri_extracted -name "*.ttf" | head -5 echo "exit: $?"

Running Command

cp /tmp/amiri_extracted/Amiri-1.000/Amiri-Regular.ttf /home/daytona/workspace/shifa-health-posts/fonts/ cp /tmp/amiri_extracted/Amiri-1.000/Amiri-Bold.ttf /home/daytona/workspace/shifa-health-posts/fonts/ ls /home/daytona/workspace/shifa-health-posts/fonts/

Writing File

~/shifa-health-posts/generate_posts_v2.py

#!/usr/bin/env python3
"""
Generate 10 Premium Urdu Health Awareness Posts (1080x1080px)
Shifa Online Consultation - Medical Infographic Series v2
Uses: Amiri font + arabic_reshaper + bidi for proper Urdu rendering
"""

from PIL import Image, ImageDraw, ImageFont
import arabic_reshaper
from bidi.algorithm import get_display
import os, sys, textwrap

OUTPUT_DIR  = "/home/daytona/workspace/shifa-health-posts/output"
FONT_DIR    = "/home/daytona/workspace/shifa-health-posts/fonts"
FONT_REG    = os.path.join(FONT_DIR, "Amiri-Regular.ttf")
FONT_BOLD   = os.path.join(FONT_DIR, "Amiri-Bold.ttf")
os.makedirs(OUTPUT_DIR, exist_ok=True)

W, H = 1080, 1080

# ── Palette ────────────────────────────────────────────────────
C_BG          = (243, 249, 255)
C_HDR_TOP     = (4,   78, 148)
C_HDR_BOT     = (0,  145, 165)
C_ACCENT      = (0,  175, 125)
C_ACCENT2     = (0,  140, 200)
C_WHITE       = (255, 255, 255)
C_CARD        = (255, 255, 255)
C_CARD_BD     = (210, 232, 245)
C_SEC_HD      = (4,   78, 148)
C_BODY        = (35,  55,  75)
C_FOOTER_TOP  = (4,   78, 148)
C_FOOTER_BOT  = (0,   35,  80)
C_DISC_BG     = (224, 246, 238)
C_DISC_TXT    = (30,  90,  65)
C_LIGHT_BLUE  = (220, 240, 255)
C_GOLD        = (220, 160,  10)


# ── Font loader ────────────────────────────────────────────────
_font_cache = {}
def fnt(size, bold=False):
    key = (size, bold)
    if key not in _font_cache:
        path = FONT_BOLD if bold else FONT_REG
        _font_cache[key] = ImageFont.truetype(path, size)
    return _font_cache[key]


# ── RTL text shaper ────────────────────────────────────────────
def ur(text):
    """Shape Urdu/Arabic text for correct RTL rendering."""
    reshaped = arabic_reshaper.reshape(text)
    return get_display(reshaped)


# ── Gradient helper ────────────────────────────────────────────
def vgrad(img, x1, y1, x2, y2, c_top, c_bot):
    draw = ImageDraw.Draw(img)
    h = y2 - y1
    for i in range(h):
        t = i / max(h - 1, 1)
        r = int(c_top[0] + (c_bot[0] - c_top[0]) * t)
        g = int(c_top[1] + (c_bot[1] - c_top[1]) * t)
        b = int(c_top[2] + (c_bot[2] - c_top[2]) * t)
        draw.line([(x1, y1+i), (x2, y1+i)], fill=(r, g, b))


def hgrad(img, x1, y1, x2, y2, c_left, c_right):
    draw = ImageDraw.Draw(img)
    w = x2 - x1
    for i in range(w):
        t = i / max(w - 1, 1)
        r = int(c_left[0] + (c_right[0] - c_left[0]) * t)
        g = int(c_left[1] + (c_right[1] - c_left[1]) * t)
        b = int(c_left[2] + (c_right[2] - c_left[2]) * t)
        draw.line([(x1+i, y1), (x1+i, y2)], fill=(r, g, b))


# ── Drawing helpers ────────────────────────────────────────────
def rr(draw, x1, y1, x2, y2, radius, fill=None, outline=None, ow=1):
    draw.rounded_rectangle([x1, y1, x2, y2], radius=radius,
                            fill=fill, outline=outline, width=ow)


def circ(draw, cx, cy, r, fill=None, outline=None, ow=2):
    draw.ellipse([cx-r, cy-r, cx+r, cy+r], fill=fill, outline=outline, width=ow)


def cross(draw, cx, cy, size, color):
    t = max(size // 4, 4)
    draw.rounded_rectangle([cx-t, cy-size//2, cx+t, cy+size//2], radius=3, fill=color)
    draw.rounded_rectangle([cx-size//2, cy-t, cx+size//2, cy+t], radius=3, fill=color)


def text_wh(draw, text, font):
    b = draw.textbbox((0,0), text, font=font)
    return b[2]-b[0], b[3]-b[1]


def draw_centered(draw, text, font, cy, color, cx=W//2):
    tw, th = text_wh(draw, text, font)
    draw.text((cx - tw//2, cy - th//2), text, font=font, fill=color)
    return cy + th//2


def draw_rtl_wrapped(draw, raw_text, font, x_right, x_left, y_start, color,
                     line_sp=6, max_lines=None):
    """
    Draw RTL-shaped text, right-aligned, word-wrapped within [x_left, x_right].
    Returns the y position after the last line.
    """
    shaped = ur(raw_text)
    max_w  = x_right - x_left
    # Split into words and wrap
    words = shaped.split()
    lines = []
    current = []
    for word in words:
        test = " ".join(current + [word])
        tw, _ = text_wh(draw, test, font)
        if tw <= max_w:
            current.append(word)
        else:
            if current:
                lines.append(" ".join(current))
            current = [word]
    if current:
        lines.append(" ".join(current))

    if max_lines:
        lines = lines[:max_lines]

    y = y_start
    for line in lines:
        tw, th = text_wh(draw, line, font)
        draw.text((x_right - tw, y), line, font=font, fill=color)
        y += th + line_sp
    return y


def draw_rtl_single(draw, raw_text, font, x_right, y, color):
    """Draw a single RTL line right-aligned at x_right."""
    shaped = ur(raw_text)
    tw, th = text_wh(draw, shaped, font)
    draw.text((x_right - tw, y), shaped, font=font, fill=color)
    return y + th


def draw_rtl_centered(draw, raw_text, font, y, color, cx=W//2):
    shaped = ur(raw_text)
    tw, th = text_wh(draw, shaped, font)
    draw.text((cx - tw//2, y), shaped, font=font, fill=color)
    return y + th


# ── Post Content ───────────────────────────────────────────────
POSTS = [
    dict(num=1, emoji="🫀",
         title_ur="مثانے کا انفیکشن", title_en="Bladder Infection",
         accent=(0, 130, 195),
         intro="مثانے کا انفیکشن بیکٹیریا کی وجہ سے ہوتا ہے۔ بروقت علاج سے مکمل صحتیابی ممکن ہے۔",
         symptoms="پیشاب میں جلن، بار بار پیشاب آنا، پیٹ کے نچلے حصے میں درد، بدبودار یا دھندلا پیشاب",
         causes="بیکٹیریا (E. coli)، صفائی کا خیال نہ رکھنا، پانی کم پینا، ذیابیطس",
         prevention="کافی پانی پئیں، صفائی رکھیں، پیشاب روکنے سے گریز کریں، قوت مدافعت بڑھائیں",
         doctor="بخار، کمر درد یا علامات 2 دن سے زیادہ رہیں تو فوری ڈاکٹر سے ملیں"),

    dict(num=2, emoji="🪨",
         title_ur="گردوں کی پتھری", title_en="Kidney Stones",
         accent=(0, 115, 175),
         intro="گردوں میں معدنی نمکیات جمع ہو کر پتھری بناتے ہیں۔ یہ تکلیف دہ لیکن قابل علاج مسئلہ ہے۔",
         symptoms="کمر یا پہلو میں شدید درد، پیشاب میں خون، متلی، الٹی، پیشاب میں رکاوٹ",
         causes="کم پانی پینا، زیادہ کیلشیم / آکسیلیٹ والی غذا، موروثی عوامل، بیٹھا رہنا",
         prevention="روزانہ 8-10 گلاس پانی، نمک کم کریں، متوازن غذا، باقاعدہ ورزش کریں",
         doctor="کمر میں شدید درد، پیشاب میں خون یا پیشاب بند ہو تو فوری ڈاکٹر سے ملیں"),

    dict(num=3, emoji="👶",
         title_ur="بانجھ پن / اولاد نہ ہونا", title_en="Infertility",
         accent=(0, 155, 130),
         intro="بانجھ پن لاعلاج نہیں۔ جدید علاج سے بہت سے جوڑے اولاد کی نعمت پا سکتے ہیں۔",
         symptoms="ایک سال کوشش کے باوجود حمل نہ ہونا، ماہواری کی بے ترتیبی، ہارمون کی خرابی",
         causes="PCOS، ہارمون عدم توازن، فیلوپین ٹیوب میں رکاوٹ، مردوں میں سپرم کی کمی، تناؤ",
         prevention="صحت مند وزن رکھیں، تناؤ کم کریں، سگریٹ سے پرہیز، بروقت طبی معائنہ کروائیں",
         doctor="اگر ایک سال سے حمل نہ ہو تو ماہر ڈاکٹر سے رجوع کریں - جلد تشخیص بہتر ہے"),

    dict(num=4, emoji="❤️",
         title_ur="ہائی بلڈ پریشر", title_en="High Blood Pressure",
         accent=(190, 45, 55),
         intro="ہائی بلڈ پریشر کو 'خاموش قاتل' کہتے ہیں۔ باقاعدہ چیک اپ اور علاج سے اسے قابو کریں۔",
         symptoms="سر درد، چکر، دھندلی نظر، سینے میں درد، سانس لینے میں دشواری، ناک سے خون",
         causes="نمک زیادہ، موٹاپا، ورزش نہ کرنا، تناؤ، موروثی بیماری، سگریٹ نوشی",
         prevention="نمک کم کریں، ورزش کریں، وزن قابو رکھیں، تناؤ سے بچیں، BP باقاعدہ چیک کروائیں",
         doctor="BP 140/90 سے زیادہ ہو، سر درد شدید ہو یا سینے میں درد آئے تو فوری ڈاکٹر سے ملیں"),

    dict(num=5, emoji="🩸",
         title_ur="ذیابیطس / شوگر", title_en="Diabetes",
         accent=(0, 145, 100),
         intro="ذیابیطس میں خون میں شکر بڑھ جاتی ہے۔ طرز زندگی بدل کر اسے قابو میں رکھیں۔",
         symptoms="بار بار پیشاب، زیادہ پیاس، وزن میں کمی، تھکاوٹ، زخم دیر سے بھرنا، نظر کمزور ہونا",
         causes="موٹاپا، ورزش نہ کرنا، غیر صحت بخش غذا، موروثی، ہارمون کی خرابی",
         prevention="میٹھا کم کھائیں، ورزش کریں، وزن قابو رکھیں، باقاعدہ بلڈ شوگر ٹیسٹ کروائیں",
         doctor="بلڈ شوگر بار بار زیادہ آئے، چکر یا بے ہوشی ہو تو فوری ڈاکٹر سے ملیں"),

    dict(num=6, emoji="🤧",
         title_ur="کان، ناک اور گلے کی الرجی", title_en="ENT Allergies",
         accent=(0, 125, 185),
         intro="ENT الرجی بہت عام مسئلہ ہے۔ دھول، دھواں اور موسمی تبدیلیاں اس کی بڑی وجوہات ہیں۔",
         symptoms="چھینکیں، ناک بند یا بہنا، آنکھوں میں خارش، گلے میں خراش، کان میں بھاری پن",
         causes="دھول، جرگ، پالتو جانور، کیمیکل، موسمی تبدیلی، کمزور قوت مدافعت",
         prevention="دھول سے بچیں، ماسک پہنیں، گھر صاف رکھیں، الرجی ٹیسٹ کروائیں",
         doctor="سانس لینے میں دشواری یا علامات 2 ہفتے سے زیادہ رہیں تو ENT ماہر سے ملیں"),

    dict(num=7, emoji="🦴",
         title_ur="جوڑوں اور کمر کا درد", title_en="Joint & Back Pain",
         accent=(110, 75, 165),
         intro="جوڑوں اور کمر کا درد روزمرہ زندگی متاثر کرتا ہے۔ بروقت علاج اور ورزش سے بہتری ممکن ہے۔",
         symptoms="جوڑوں میں سوجن و اکڑن، کمر میں درد، حرکت میں دشواری، صبح کے وقت اکڑن",
         causes="آرتھرائٹس، یورک ایسڈ، موٹاپا، غلط بیٹھنے کا انداز، کیلشیم کی کمی، چوٹ",
         prevention="ورزش، وزن کم کریں، کیلشیم / وٹامن D لیں، صحیح بیٹھیں، بھاری وزن نہ اٹھائیں",
         doctor="درد شدید ہو، سوجن آئے یا چلنا مشکل ہو تو آرتھوپیڈک ڈاکٹر سے فوری ملیں"),

    dict(num=8, emoji="💧",
         title_ur="پیشاب میں جلن اور انفیکشن", title_en="Urinary Tract Infection",
         accent=(0, 145, 165),
         intro="UTI خواتین میں بہت عام ہے۔ بروقت علاج نہ ہو تو انفیکشن گردوں تک پہنچ سکتا ہے۔",
         symptoms="پیشاب میں جلن، بار بار آنا، رنگ غیر معمولی، بدبو، پیٹ کے نچلے حصے میں درد",
         causes="بیکٹیریا، صفائی نہ رکھنا، پانی کم پینا، ذیابیطس، قوت مدافعت کی کمزوری",
         prevention="پانی خوب پئیں، صفائی رکھیں، نرم کپڑے پہنیں، پیشاب روکنے سے گریز کریں",
         doctor="بخار، ٹھنڈ یا کمر درد کے ساتھ جلن ہو تو فوری ڈاکٹر سے رجوع کریں"),

    dict(num=9, emoji="🫁",
         title_ur="معدے کی تیزابیت اور گیس", title_en="Acidity & Gastric Problems",
         accent=(185, 110, 15),
         intro="معدے کی تیزابیت آج کل بہت عام ہے۔ غلط کھانا اور بے ترتیب زندگی اس کی بڑی وجہ ہے۔",
         symptoms="سینے میں جلن، ڈکار، پیٹ پھولنا، متلی، منہ میں کھٹاس، کھانے کے بعد تکلیف",
         causes="مسالہ دار کھانا، زیادہ چائے / کافی، کھانے میں بے ترتیبی، تناؤ، سگریٹ نوشی",
         prevention="کم مسالہ کھائیں، بروقت کھانا کھائیں، پانی پئیں، تناؤ کم کریں، تھوڑا تھوڑا کھائیں",
         doctor="سینے میں شدید جلن، قے میں خون یا وزن کم ہو تو فوری ڈاکٹر سے ملیں"),

    dict(num=10, emoji="🌡️",
         title_ur="موسمی بخار، نزلہ اور کھانسی", title_en="Seasonal Flu & Cough",
         accent=(0, 135, 165),
         intro="موسمی تبدیلی میں نزلہ، بخار اور کھانسی بہت عام ہیں۔ احتیاط اور صفائی سے بچاؤ ممکن ہے۔",
         symptoms="بخار، ناک بہنا یا بند ہونا، گلے میں خراش، کھانسی، جسم درد، کمزوری",
         causes="وائرس / بیکٹیریا، موسمی تبدیلی، کمزور قوت مدافعت، بھیڑ والی جگہوں پر رہنا",
         prevention="ہاتھ دھوئیں، ماسک پہنیں، گرم پانی پئیں، قوت مدافعت بڑھائیں، فلو ویکسین لگوائیں",
         doctor="بخار 3 دن سے زیادہ رہے یا سانس لینے میں دشواری ہو تو فوری ڈاکٹر سے ملیں"),
]

SECTIONS = [
    ("intro",      "تعارف",         "📋"),
    ("symptoms",   "علامات",         "🩺"),
    ("causes",     "وجوہات",         "🔬"),
    ("prevention", "احتیاط و بچاؤ",  "🛡"),
    ("doctor",     "ڈاکٹر سے کب ملیں","👨‍⚕️"),
]

FOOTER_BRAND   = "شفا آن لائن کنسلٹیشن"
FOOTER_L1      = "✔ ماہر ڈاکٹروں سے آن لائن مشاورت   ✔ گھر بیٹھے رہنمائی حاصل کریں"
FOOTER_L2      = "📱 WhatsApp: +92XXXXXXXXXX   ⏰ Appointment Required"
FOOTER_L3      = "💳 Paid Medical Consultation Service"
DISCLAIMER     = "یہ معلومات صرف آگاہی کے لیے ہیں۔ تشخیص اور علاج کے لیے مستند ڈاکٹر سے مشورہ کریں۔"


def make_post(post):
    img  = Image.new("RGB", (W, H), C_BG)
    acc  = post["accent"]
    acc2 = (max(acc[0]-30,0), min(acc[1]+20,255), min(acc[2]+30,255))

    # ── Background subtle grid pattern ─────────────────────────
    draw = ImageDraw.Draw(img)
    for gx in range(0, W, 60):
        draw.line([(gx, 0), (gx, H)], fill=(220, 235, 248), width=1)
    for gy in range(0, H, 60):
        draw.line([(0, gy), (W, gy)], fill=(220, 235, 248), width=1)

    # ── Header (gradient) ───────────────────────────────────────
    HDR_H = 200
    vgrad(img, 0, 0, W, HDR_H, C_HDR_TOP, C_HDR_BOT)
    draw = ImageDraw.Draw(img)

    # Decorative circles in header
    circ(draw, 950, -20, 130, fill=(*C_ACCENT, 0), outline=(255,255,255,25), ow=2)
    circ(draw, 880, 230, 80,  fill=None, outline=(255,255,255,15), ow=1)
    circ(draw, 130, 220, 90,  fill=None, outline=(255,255,255,12), ow=1)

    # Post number circle (top-left)
    circ(draw, 55, 48, 30, fill=C_ACCENT)
    cross(draw, 55, 48, 22, C_WHITE)
    num_f = fnt(20, bold=True)
    ns = str(post["num"])
    nw, nh = text_wh(draw, ns, num_f)
    draw.text((55 - nw//2 - 14, 48 - nh//2 + 1), ns, font=num_f, fill=C_WHITE)

    # Emoji (top right)
    ef = fnt(72)
    ew, eh = text_wh(draw, post["emoji"], ef)
    draw.text((W - ew - 38, (HDR_H - eh)//2 - 10), post["emoji"], font=ef, fill=C_WHITE)

    # Title Urdu (large, centered)
    tf = fnt(58, bold=True)
    title_shaped = ur(post["title_ur"])
    tw, th = text_wh(draw, title_shaped, tf)
    draw.text(((W - tw)//2, 22), title_shaped, font=tf, fill=C_WHITE)

    # English subtitle
    ef2 = fnt(24)
    ew2, eh2 = text_wh(draw, post["title_en"], ef2)
    draw.text(((W - ew2)//2, 22 + th + 8), post["title_en"], font=ef2, fill=(195, 230, 255))

    # Accent bar below header
    draw.rectangle([0, HDR_H, W, HDR_H+5], fill=C_ACCENT)

    # ── Content Area ────────────────────────────────────────────
    # Layout: 5 content cards, disclaimer, footer
    # Footer ~= 165px, Disclaimer ~= 42px, top pad 8
    # Available for cards: 1080 - 200 - 5 - 8 - 42 - 6 - 165 = 454px
    # 5 cards + 4 gaps(6) = 454 → each card ~ 87px

    CARD_X1   = 28
    CARD_X2   = W - 28
    CARD_GAP  = 6
    CONTENT_START = HDR_H + 5 + 8

    # Dynamically size each card
    FOOTER_H  = 168
    DISC_H    = 40
    DISC_GAP  = 6
    available = H - CONTENT_START - DISC_H - DISC_GAP - FOOTER_H - CARD_GAP*(len(SECTIONS)-1) - 6
    card_h    = available // len(SECTIONS)

    sec_hd_f  = fnt(26, bold=True)
    body_f    = fnt(21)
    icon_f    = fnt(20)

    card_y = CONTENT_START
    for key, label, icon in SECTIONS:
        text_content = post[key]

        # Card shadow (subtle)
        rr(draw, CARD_X1+3, card_y+3, CARD_X2+3, card_y+card_h+3,
           12, fill=(200, 220, 235))
        # Card body
        rr(draw, CARD_X1, card_y, CARD_X2, card_y+card_h,
           12, fill=C_CARD, outline=C_CARD_BD, ow=1)
        # Left accent bar
        draw.rounded_rectangle([CARD_X1, card_y, CARD_X1+7, card_y+card_h],
                                radius=12, fill=acc)
        # Top accent dot
        circ(draw, CARD_X1+7, card_y + card_h//2, 5, fill=acc2)

        # Icon on right
        ix = CARD_X2 - 14
        iy = card_y + 8
        iw, ih = text_wh(draw, icon, icon_f)
        draw.text((ix - iw, iy), icon, font=icon_f, fill=acc)

        # Section heading (right-aligned, shaped)
        lh_y = card_y + 8
        lbl_shaped = ur(label)
        lw, lh = text_wh(draw, lbl_shaped, sec_hd_f)
        draw.text((CARD_X2 - 14 - iw - 8 - lw, lh_y), lbl_shaped,
                  font=sec_hd_f, fill=C_SEC_HD)

        # Thin divider under heading
        div_y = lh_y + lh + 4
        draw.line([(CARD_X1+12, div_y), (CARD_X2-12, div_y)], fill=C_CARD_BD, width=1)

        # Body text
        body_y = div_y + 5
        draw_rtl_wrapped(draw, text_content, body_f,
                         CARD_X2 - 12, CARD_X1 + 12,
                         body_y, C_BODY, line_sp=5, max_lines=3)

        card_y += card_h + CARD_GAP

    # ── Disclaimer ──────────────────────────────────────────────
    disc_y = card_y + DISC_GAP
    rr(draw, 28, disc_y, W-28, disc_y+DISC_H, 10,
       fill=C_DISC_BG, outline=C_ACCENT, ow=1)
    disc_f = fnt(18)
    disc_shaped = ur(DISCLAIMER)
    dw, dh = text_wh(draw, disc_shaped, disc_f)
    draw.text(((W-dw)//2, disc_y + (DISC_H-dh)//2), disc_shaped,
              font=disc_f, fill=C_DISC_TXT)

    # ── Footer ──────────────────────────────────────────────────
    footer_y = disc_y + DISC_H + 4
    vgrad(img, 0, footer_y, W, H, C_FOOTER_TOP, C_FOOTER_BOT)
    draw = ImageDraw.Draw(img)
    draw.rectangle([0, footer_y, W, footer_y+4], fill=C_ACCENT)

    # Decorative circles in footer
    circ(draw, 80, footer_y + 80, 55, fill=None, outline=(255,255,255,15), ow=1)
    circ(draw, W-70, footer_y+60, 45, fill=None, outline=(255,255,255,12), ow=1)

    fb_f  = fnt(34, bold=True)
    fl_f  = fnt(20)
    fxs_f = fnt(17)

    fy = footer_y + 12
    # Brand
    brand_shaped = ur(FOOTER_BRAND)
    bw, bh = text_wh(draw, brand_shaped, fb_f)
    draw.text(((W-bw)//2, fy), brand_shaped, font=fb_f, fill=C_WHITE)
    # Gold underline
    draw.line([((W-bw)//2, fy+bh+2), ((W+bw)//2, fy+bh+2)], fill=C_GOLD, width=2)
    fy += bh + 10

    l1_shaped = ur(FOOTER_L1)
    l1w, l1h = text_wh(draw, l1_shaped, fl_f)
    draw.text(((W-l1w)//2, fy), l1_shaped, font=fl_f, fill=(195, 230, 255))
    fy += l1h + 6

    l2_shaped = ur(FOOTER_L2)
    l2w, l2h = text_wh(draw, l2_shaped, fl_f)
    draw.text(((W-l2w)//2, fy), l2_shaped, font=fl_f, fill=(195, 230, 255))
    fy += l2h + 5

    l3_shaped = ur(FOOTER_L3)
    l3w, l3h = text_wh(draw, l3_shaped, fxs_f)
    draw.text(((W-l3w)//2, fy), l3_shaped, font=fxs_f, fill=(175, 215, 255))

    # ── Save ────────────────────────────────────────────────────
    safe_en = post["title_en"].replace(" ", "_").replace("/","").replace("&","and")
    fn  = f"post_{post['num']:02d}_{safe_en}.png"
    out = os.path.join(OUTPUT_DIR, fn)
    img.save(out, "PNG", dpi=(150, 150))
    print(f"  ✓ Post {post['num']:02d}: {post['title_ur']}  →  {fn}")
    return out


print("=" * 60)
print("  SHIFA ONLINE - 10 Health Awareness Posts Generator v2")
print("=" * 60)
saved = []
for p in POSTS:
    path = make_post(p)
    saved.append(path)

print()
print(f"✅ All {len(saved)} posts saved to: {OUTPUT_DIR}")
Running Command

cd /home/daytona/workspace/shifa-health-posts && python3 generate_posts_v2.py 2>&1

Running Command

cd /home/daytona/workspace/shifa-health-posts/output && ls -lh *.png && echo "---" && cd /home/daytona/workspace/shifa-health-posts && zip -j shifa_health_posts_10x.zip output/*.png && ls -lh shifa_health_posts_10x.zip

Running Command

# Copy the v2 posts to a clean folder then zip mkdir -p /home/daytona/workspace/shifa-health-posts/final cp /home/daytona/workspace/shifa-health-posts/output/post_01_Bladder_Infection.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_02_Kidney_Stones.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_03_Infertility.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_04_High_Blood_Pressure.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_05_Diabetes.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_06_ENT_Allergies.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_07_Joint_and_Back_Pain.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_08_Urinary_Tract_Infection.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_09_Acidity_and_Gastric_Problems.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_10_Seasonal_Flu_and_Cough.png /home/daytona/workspace/shifa-health-posts/final/ ls -lh /home/daytona/workspace/shifa-health-posts/final/

Running Command

python3 -c " import zipfile, os files = [f'/home/daytona/workspace/shifa-health-posts/final/post_{str(i).zfill(2)}_{n}.png' for i,n in [(1,'Bladder_Infection'),(2,'Kidney_Stones'),(3,'Infertility'), (4,'High_Blood_Pressure'),(5,'Diabetes'),(6,'ENT_Allergies'), (7,'Joint_and_Back_Pain'),(8,'Urinary_Tract_Infection'), (9,'Acidity_and_Gastric_Problems'),(10,'Seasonal_Flu_and_Cough')]] zip_path = '/home/daytona/workspace/shifa-health-posts/Shifa_Health_Posts_10x_1080p.zip' with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zf: for f in files: zf.write(f, os.path.basename(f)) print(f' added: {os.path.basename(f)}') import os print(f'ZIP size: {os.path.getsize(zip_path)//1024} KB') print(f'Path: {zip_path}') "

Running Command

python3 -c " from PIL import Image import os final_dir = '/home/daytona/workspace/shifa-health-posts/final/' for f in sorted(os.listdir(final_dir)): img = Image.open(final_dir + f) print(f'{f}: {img.size} mode={img.mode} size={os.path.getsize(final_dir+f)//1024}KB') "

Reading File
Reading File

✅ تمام 10 پوسٹس تیار ہیں - All 10 Posts Ready!

All posts are 1080x1080px, premium Urdu medical infographics with proper RTL Amiri calligraphic font, Blue/Teal/Green hospital branding, and the complete Shifa Online Consultation footer.

📥 Individual Post Downloads

#TopicDownload Link
1مثانے کا انفیکشن

post 01 Bladder Infection

Image · PNG

2گردوں کی پتھری

post 02 Kidney Stones

Image · PNG

3بانجھ پن / اولاد نہ ہونا

post 03 Infertility

Image · PNG

4ہائی بلڈ پریشر

post 04 High Blood Pressure

Image · PNG

5ذیابیطس / شوگر

post 05 Diabetes

Image · PNG

6کان، ناک اور گلے کی الرجی

post 06 ENT Allergies

Image · PNG

7جوڑوں اور کمر کا درد

post 07 Joint and Back Pain

Image · PNG

8پیشاب میں جلن اور انفیکشن

post 08 Urinary Tract Infection

Image · PNG

9معدے کی تیزابیت اور گیس

post 09 Acidity and Gastric Problems

Image · PNG

10موسمی بخار، نزلہ اور کھانسی

post 10 Seasonal Flu and Cough

Image · PNG


✨ Design Features Delivered

  • Font: Amiri Naskh - professional Arabic/Urdu calligraphy
  • RTL text shaping: arabic_reshaper + bidi for correct Urdu ligatures
  • Layout: 5 color-coded content cards per post (تعارف، علامات، وجوہات، احتیاط، ڈاکٹر سے کب ملیں)
  • Colors: Deep Blue gradient header, Teal accent, Green badges, White cards
  • Footer: شفا آن لائن کنسلٹیشن branding with WhatsApp, gold underline
  • Disclaimer: Light green strip on every post
  • Size: Exactly 1080x1080px - ready for WhatsApp, Facebook, Instagram

all files are damaged fix the issue

Running Command

python3 -c " from PIL import Image import os final_dir = '/home/daytona/workspace/shifa-health-posts/final/' for f in sorted(os.listdir(final_dir)): try: img = Image.open(final_dir + f) img.verify() print(f'OK: {f}') except Exception as e: print(f'DAMAGED: {f} -> {e}') "

Running Command

python3 -c " from PIL import Image import os, shutil src = '/home/daytona/workspace/shifa-health-posts/final/' dst = '/home/daytona/workspace/shifa-health-posts/fixed/' os.makedirs(dst, exist_ok=True) for f in sorted(os.listdir(src)): if not f.endswith('.png'): continue img = Image.open(src + f) img = img.convert('RGB') out = dst + f img.save(out, format='PNG', optimize=False, compress_level=1) size = os.path.getsize(out) print(f'Saved: {f} ({size//1024} KB)') print('Done.') "

Running Command

which wkhtmltoimage wkhtmltopdf chromium-browser chromium google-chrome 2>/dev/null; python3 -c "from playwright.sync_api import sync_playwright; print('playwright ok')" 2>/dev/null; which cutycapt 2>/dev/null; echo "---done"

Running Command

chromium --headless --disable-gpu --screenshot=/tmp/test.png --window-size=100,100 about:blank 2>&1 | head -5; ls -la /tmp/test.png 2>/dev/null && echo "chromium screenshot works" || echo "chromium screenshot failed"

Writing File

~/shifa-health-posts/build_html_posts.py

#!/usr/bin/env python3
"""
Build 10 premium Urdu health posts as HTML files,
then render each with Chromium headless to 1080x1080 PNG.
Uses Google Fonts (Noto Nastaliq Urdu) embedded via base64 or CDN.
"""
import os, subprocess, time

HTML_DIR = "/home/daytona/workspace/shifa-health-posts/html"
OUT_DIR  = "/home/daytona/workspace/shifa-health-posts/fixed"
os.makedirs(HTML_DIR, exist_ok=True)
os.makedirs(OUT_DIR,  exist_ok=True)

FONT_PATH_REG  = "/home/daytona/workspace/shifa-health-posts/fonts/Amiri-Regular.ttf"
FONT_PATH_BOLD = "/home/daytona/workspace/shifa-health-posts/fonts/Amiri-Bold.ttf"

POSTS = [
    dict(num=1, icon="🫀",
         title="مثانے کا انفیکشن", subtitle="Bladder Infection",
         color="#0456A0", accent="#00AF7D",
         intro="مثانے کا انفیکشن بیکٹیریا کی وجہ سے ہوتا ہے۔ بروقت علاج سے مکمل صحتیابی ممکن ہے۔",
         symptoms="پیشاب میں جلن • بار بار پیشاب آنا • پیٹ کے نچلے حصے میں درد • بدبودار یا دھندلا پیشاب",
         causes="بیکٹیریا (E. coli) • صفائی کا خیال نہ رکھنا • پانی کم پینا • ذیابیطس",
         prevention="کافی پانی پئیں • صفائی رکھیں • پیشاب روکنے سے گریز • قوت مدافعت بڑھائیں",
         doctor="بخار، کمر درد یا علامات 2 دن سے زیادہ رہیں تو فوری ڈاکٹر سے ملیں"),

    dict(num=2, icon="🪨",
         title="گردوں کی پتھری", subtitle="Kidney Stones",
         color="#006FA8", accent="#0096C8",
         intro="گردوں میں معدنی نمکیات جمع ہو کر پتھری بناتے ہیں۔ یہ تکلیف دہ لیکن قابل علاج مسئلہ ہے۔",
         symptoms="کمر یا پہلو میں شدید درد • پیشاب میں خون • متلی اور الٹی • پیشاب میں رکاوٹ",
         causes="کم پانی پینا • زیادہ کیلشیم والی غذا • موروثی عوامل • بیٹھا رہنا",
         prevention="روزانہ 8-10 گلاس پانی • نمک کم • متوازن غذا • باقاعدہ ورزش",
         doctor="کمر میں شدید درد، پیشاب میں خون یا پیشاب بند ہو تو فوری ڈاکٹر سے ملیں"),

    dict(num=3, icon="👶",
         title="بانجھ پن / اولاد نہ ہونا", subtitle="Infertility",
         color="#007B6E", accent="#00B890",
         intro="بانجھ پن لاعلاج نہیں۔ جدید علاج سے بہت سے جوڑے اولاد کی نعمت پا سکتے ہیں۔",
         symptoms="ایک سال کوشش کے باوجود حمل نہ ہونا • ماہواری کی بے ترتیبی • ہارمون کی خرابی",
         causes="PCOS • ہارمون عدم توازن • فیلوپین ٹیوب میں رکاوٹ • مردوں میں سپرم کی کمی",
         prevention="صحت مند وزن • تناؤ کم • سگریٹ سے پرہیز • بروقت طبی معائنہ",
         doctor="اگر ایک سال سے حمل نہ ہو تو ماہر ڈاکٹر سے رجوع کریں — جلد تشخیص بہتر"),

    dict(num=4, icon="❤️",
         title="ہائی بلڈ پریشر", subtitle="High Blood Pressure",
         color="#A0192A", accent="#D43040",
         intro="ہائی بلڈ پریشر کو 'خاموش قاتل' کہتے ہیں۔ باقاعدہ چیک اپ اور علاج سے اسے قابو کریں۔",
         symptoms="سر درد • چکر آنا • دھندلی نظر • سینے میں درد • سانس لینے میں دشواری",
         causes="نمک زیادہ • موٹاپا • ورزش نہ کرنا • تناؤ • موروثی بیماری • سگریٹ نوشی",
         prevention="نمک کم • ورزش • وزن قابو • تناؤ سے بچیں • BP باقاعدہ چیک کروائیں",
         doctor="BP 140/90 سے زیادہ ہو یا سینے میں درد آئے تو فوری ڈاکٹر سے ملیں"),

    dict(num=5, icon="🩸",
         title="ذیابیطس / شوگر", subtitle="Diabetes",
         color="#006845", accent="#00A06A",
         intro="ذیابیطس میں خون میں شکر کی سطح بڑھ جاتی ہے۔ طرز زندگی بدل کر اسے قابو میں رکھیں۔",
         symptoms="بار بار پیشاب • زیادہ پیاس • وزن میں کمی • تھکاوٹ • زخم دیر سے بھرنا",
         causes="موٹاپا • ورزش نہ کرنا • غیر صحت بخش غذا • موروثی • ہارمون کی خرابی",
         prevention="میٹھا کم • ورزش • وزن قابو • باقاعدہ بلڈ شوگر ٹیسٹ",
         doctor="بلڈ شوگر بار بار زیادہ آئے یا چکر و بے ہوشی ہو تو فوری ڈاکٹر سے ملیں"),

    dict(num=6, icon="🤧",
         title="کان، ناک اور گلے کی الرجی", subtitle="ENT Allergies",
         color="#005A8C", accent="#0082BE",
         intro="ENT الرجی بہت عام مسئلہ ہے۔ دھول، دھواں اور موسمی تبدیلیاں اس کی بڑی وجوہات ہیں۔",
         symptoms="چھینکیں • ناک بند یا بہنا • آنکھوں میں خارش • گلے میں خراش • کان میں بھاری پن",
         causes="دھول • جرگ • پالتو جانور • کیمیکل • موسمی تبدیلی • کمزور قوت مدافعت",
         prevention="دھول سے بچیں • ماسک پہنیں • گھر صاف رکھیں • الرجی ٹیسٹ کروائیں",
         doctor="سانس لینے میں دشواری یا علامات 2 ہفتے سے زیادہ رہیں تو ENT ماہر سے ملیں"),

    dict(num=7, icon="🦴",
         title="جوڑوں اور کمر کا درد", subtitle="Joint & Back Pain",
         color="#5A3E9A", accent="#7A5EC0",
         intro="جوڑوں اور کمر کا درد روزمرہ زندگی متاثر کرتا ہے۔ بروقت علاج اور ورزش سے بہتری ممکن ہے۔",
         symptoms="جوڑوں میں سوجن و اکڑن • کمر میں درد • حرکت میں دشواری • صبح کے وقت اکڑن",
         causes="آرتھرائٹس • یورک ایسڈ • موٹاپا • غلط بیٹھنے کا انداز • کیلشیم کی کمی",
         prevention="ورزش • وزن کم • کیلشیم / وٹامن D • صحیح بیٹھیں • بھاری وزن نہ اٹھائیں",
         doctor="درد شدید ہو، سوجن آئے یا چلنا مشکل ہو تو آرتھوپیڈک ڈاکٹر سے فوری ملیں"),

    dict(num=8, icon="💧",
         title="پیشاب میں جلن اور انفیکشن", subtitle="Urinary Tract Infection",
         color="#006878", accent="#0096A8",
         intro="UTI خواتین میں بہت عام ہے۔ بروقت علاج نہ ہو تو انفیکشن گردوں تک پہنچ سکتا ہے۔",
         symptoms="پیشاب میں جلن • بار بار آنا • رنگ غیر معمولی • بدبو • پیٹ کے نچلے حصے میں درد",
         causes="بیکٹیریا • صفائی نہ رکھنا • پانی کم پینا • ذیابیطس • قوت مدافعت کی کمزوری",
         prevention="پانی خوب پئیں • صفائی رکھیں • نرم کپڑے • پیشاب روکنے سے گریز",
         doctor="بخار، ٹھنڈ یا کمر درد کے ساتھ جلن ہو تو فوری ڈاکٹر سے رجوع کریں"),

    dict(num=9, icon="🫁",
         title="معدے کی تیزابیت اور گیس", subtitle="Acidity & Gastric Problems",
         color="#8A5500", accent="#C07800",
         intro="معدے کی تیزابیت آج کل بہت عام ہے۔ غلط کھانا اور بے ترتیب زندگی اس کی بڑی وجہ ہے۔",
         symptoms="سینے میں جلن • ڈکار • پیٹ پھولنا • متلی • منہ میں کھٹاس • کھانے کے بعد تکلیف",
         causes="مسالہ دار کھانا • زیادہ چائے / کافی • کھانے میں بے ترتیبی • تناؤ • سگریٹ",
         prevention="کم مسالہ • بروقت کھانا • پانی • تناؤ کم • تھوڑا تھوڑا کھائیں",
         doctor="سینے میں شدید جلن، قے میں خون یا وزن کم ہو تو فوری ڈاکٹر سے ملیں"),

    dict(num=10, icon="🌡️",
         title="موسمی بخار، نزلہ اور کھانسی", subtitle="Seasonal Flu & Cough",
         color="#005A78", accent="#0086A8",
         intro="موسمی تبدیلی میں نزلہ، بخار اور کھانسی بہت عام ہیں۔ احتیاط اور صفائی سے بچاؤ ممکن ہے۔",
         symptoms="بخار • ناک بہنا یا بند ہونا • گلے میں خراش • کھانسی • جسم درد • کمزوری",
         causes="وائرس / بیکٹیریا • موسمی تبدیلی • کمزور قوت مدافعت • بھیڑ والی جگہیں",
         prevention="ہاتھ دھوئیں • ماسک پہنیں • گرم پانی • قوت مدافعت بڑھائیں • فلو ویکسین",
         doctor="بخار 3 دن سے زیادہ رہے یا سانس لینے میں دشواری ہو تو فوری ڈاکٹر سے ملیں"),
]

HTML_TEMPLATE = """<!DOCTYPE html>
<html lang="ur" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1080">
<style>
  @font-face {{
    font-family: 'Amiri';
    src: url('file://{font_reg}') format('truetype');
    font-weight: normal;
  }}
  @font-face {{
    font-family: 'Amiri';
    src: url('file://{font_bold}') format('truetype');
    font-weight: bold;
  }}

  * {{ margin: 0; padding: 0; box-sizing: border-box; }}

  body {{
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    font-family: 'Amiri', serif;
    direction: rtl;
    background: #F3F9FF;
  }}

  /* Background grid */
  .bg {{
    position: absolute;
    width: 1080px;
    height: 1080px;
    background-image:
      linear-gradient(to right, #DCF0FF 1px, transparent 1px),
      linear-gradient(to bottom, #DCF0FF 1px, transparent 1px);
    background-size: 60px 60px;
  }}

  .container {{
    position: relative;
    width: 1080px;
    height: 1080px;
    display: flex;
    flex-direction: column;
  }}

  /* ── HEADER ── */
  .header {{
    background: linear-gradient(135deg, {color} 0%, #0096A5 100%);
    padding: 18px 40px 14px 40px;
    position: relative;
    overflow: hidden;
    min-height: 188px;
    flex-shrink: 0;
  }}

  .header::before {{
    content: '';
    position: absolute;
    top: -50px; left: -50px;
    width: 220px; height: 220px;
    border-radius: 50%;
    background: rgba(255,255,255,0.07);
  }}
  .header::after {{
    content: '';
    position: absolute;
    top: -30px; right: 60px;
    width: 180px; height: 180px;
    border-radius: 50%;
    border: 2px solid rgba(255,255,255,0.15);
  }}

  .header-accent-bar {{
    position: absolute;
    bottom: 0; left: 0; right: 0;
    height: 5px;
    background: {accent};
  }}

  .post-badge {{
    position: absolute;
    top: 16px;
    left: 36px;
    width: 52px; height: 52px;
    border-radius: 50%;
    background: {accent};
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    font-weight: bold;
    color: #fff;
    font-family: Arial, sans-serif;
    box-shadow: 0 3px 10px rgba(0,0,0,0.3);
    z-index: 10;
  }}

  .header-icon {{
    position: absolute;
    top: 18px;
    right: 36px;
    font-size: 72px;
    line-height: 1;
    filter: drop-shadow(2px 3px 6px rgba(0,0,0,0.25));
    z-index: 10;
  }}

  .header-titles {{
    text-align: center;
    padding: 8px 120px 0 120px;
  }}

  .title-ur {{
    font-size: 54px;
    font-weight: bold;
    color: #FFFFFF;
    line-height: 1.2;
    text-shadow: 1px 2px 6px rgba(0,0,0,0.4);
    letter-spacing: 0.5px;
  }}

  .title-en {{
    font-size: 21px;
    color: #C8E8FF;
    font-family: 'Segoe UI', Arial, sans-serif;
    margin-top: 4px;
    letter-spacing: 1px;
  }}

  /* ── CONTENT ── */
  .content {{
    flex: 1;
    padding: 7px 24px 4px 24px;
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-height: 0;
  }}

  .card {{
    background: #FFFFFF;
    border-radius: 12px;
    border: 1px solid #D2E8F5;
    box-shadow: 2px 3px 8px rgba(0,86,160,0.08);
    padding: 8px 16px 8px 16px;
    position: relative;
    overflow: hidden;
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }}

  .card::before {{
    content: '';
    position: absolute;
    top: 0; right: 0;
    width: 6px;
    height: 100%;
    background: {color};
    border-radius: 0 12px 12px 0;
  }}

  .card-header {{
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    margin-bottom: 4px;
  }}

  .card-icon {{
    font-size: 20px;
    line-height: 1;
  }}

  .card-label {{
    font-size: 23px;
    font-weight: bold;
    color: {color};
    line-height: 1;
  }}

  .card-divider {{
    height: 1px;
    background: #D2E8F5;
    margin: 3px 0 5px 0;
  }}

  .card-body {{
    font-size: 19px;
    color: #233547;
    line-height: 1.55;
    text-align: right;
    padding-left: 14px;
  }}

  /* ── DISCLAIMER ── */
  .disclaimer {{
    margin: 0 24px 4px 24px;
    background: #E0F6EE;
    border: 1px solid #00AF7D;
    border-radius: 10px;
    padding: 7px 16px;
    text-align: center;
    font-size: 16px;
    color: #1E5A40;
    flex-shrink: 0;
  }}

  /* ── FOOTER ── */
  .footer {{
    background: linear-gradient(to bottom, {color} 0%, #001E4A 100%);
    padding: 12px 30px 10px 30px;
    text-align: center;
    flex-shrink: 0;
    position: relative;
    overflow: hidden;
  }}

  .footer::before {{
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 4px;
    background: {accent};
  }}

  .footer-brand {{
    font-size: 30px;
    font-weight: bold;
    color: #FFFFFF;
    line-height: 1.2;
  }}

  .footer-brand-underline {{
    width: 220px;
    height: 2px;
    background: #DCAA00;
    margin: 3px auto 7px auto;
    border-radius: 2px;
  }}

  .footer-line {{
    font-size: 18px;
    color: #C3E2FF;
    margin-bottom: 3px;
    line-height: 1.4;
  }}

  .footer-line-sm {{
    font-size: 15px;
    color: #A0C8F0;
    margin-top: 2px;
  }}
</style>
</head>
<body>
<div class="bg"></div>
<div class="container">

  <!-- HEADER -->
  <div class="header">
    <div class="post-badge">{num}</div>
    <div class="header-icon">{icon}</div>
    <div class="header-titles">
      <div class="title-ur">{title}</div>
      <div class="title-en">{subtitle}</div>
    </div>
    <div class="header-accent-bar"></div>
  </div>

  <!-- CONTENT CARDS -->
  <div class="content">

    <div class="card">
      <div class="card-header">
        <span class="card-label">تعارف</span>
        <span class="card-icon">📋</span>
      </div>
      <div class="card-divider"></div>
      <div class="card-body">{intro}</div>
    </div>

    <div class="card">
      <div class="card-header">
        <span class="card-label">علامات</span>
        <span class="card-icon">🩺</span>
      </div>
      <div class="card-divider"></div>
      <div class="card-body">{symptoms}</div>
    </div>

    <div class="card">
      <div class="card-header">
        <span class="card-label">وجوہات</span>
        <span class="card-icon">🔬</span>
      </div>
      <div class="card-divider"></div>
      <div class="card-body">{causes}</div>
    </div>

    <div class="card">
      <div class="card-header">
        <span class="card-label">احتیاط و بچاؤ</span>
        <span class="card-icon">🛡️</span>
      </div>
      <div class="card-divider"></div>
      <div class="card-body">{prevention}</div>
    </div>

    <div class="card">
      <div class="card-header">
        <span class="card-label">ڈاکٹر سے کب ملیں</span>
        <span class="card-icon">👨‍⚕️</span>
      </div>
      <div class="card-divider"></div>
      <div class="card-body">{doctor}</div>
    </div>

  </div><!-- /content -->

  <!-- DISCLAIMER -->
  <div class="disclaimer">
    ⚠️ یہ معلومات صرف آگاہی کے لیے ہیں۔ تشخیص اور علاج کے لیے مستند ڈاکٹر سے مشورہ کریں۔
  </div>

  <!-- FOOTER -->
  <div class="footer">
    <div class="footer-brand">شفا آن لائن کنسلٹیشن</div>
    <div class="footer-brand-underline"></div>
    <div class="footer-line">✔ ماہر ڈاکٹروں سے آن لائن مشاورت &nbsp;&nbsp; ✔ گھر بیٹھے رہنمائی حاصل کریں</div>
    <div class="footer-line">📱 WhatsApp: +92XXXXXXXXXX &nbsp;&nbsp; ⏰ Appointment Required</div>
    <div class="footer-line-sm">💳 Paid Medical Consultation Services Available</div>
  </div>

</div>
</body>
</html>
"""

print("Generating HTML files...")
html_paths = []
for p in POSTS:
    html_content = HTML_TEMPLATE.format(
        font_reg  = FONT_PATH_REG,
        font_bold = FONT_PATH_BOLD,
        num       = p["num"],
        icon      = p["icon"],
        title     = p["title"],
        subtitle  = p["subtitle"],
        color     = p["color"],
        accent    = p["accent"],
        intro     = p["intro"],
        symptoms  = p["symptoms"],
        causes    = p["causes"],
        prevention= p["prevention"],
        doctor    = p["doctor"],
    )
    html_path = os.path.join(HTML_DIR, f"post_{p['num']:02d}.html")
    with open(html_path, "w", encoding="utf-8") as f:
        f.write(html_content)
    html_paths.append((p["num"], p["title"], html_path))
    print(f"  HTML {p['num']:02d}: {html_path}")

print("\nRendering PNGs with Chromium...")
for num, title, html_path in html_paths:
    safe_title = {
        1:"Bladder_Infection", 2:"Kidney_Stones", 3:"Infertility",
        4:"High_Blood_Pressure", 5:"Diabetes", 6:"ENT_Allergies",
        7:"Joint_and_Back_Pain", 8:"Urinary_Tract_Infection",
        9:"Acidity_and_Gastric_Problems", 10:"Seasonal_Flu_and_Cough"
    }[num]
    out_png = os.path.join(OUT_DIR, f"post_{num:02d}_{safe_title}.png")

    cmd = [
        "chromium",
        "--headless",
        "--disable-gpu",
        "--no-sandbox",
        "--disable-dev-shm-usage",
        f"--window-size=1080,1080",
        f"--screenshot={out_png}",
        f"file://{html_path}"
    ]
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
    if os.path.exists(out_png) and os.path.getsize(out_png) > 5000:
        print(f"  ✓ Post {num:02d}: {title}  ({os.path.getsize(out_png)//1024} KB)")
    else:
        print(f"  ✗ Post {num:02d} FAILED. stderr: {result.stderr[:200]}")

print("\nDone! Files in:", OUT_DIR)
Running Command

cd /home/daytona/workspace/shifa-health-posts && python3 build_html_posts.py 2>&1

Reading File
Reading File
Running Command

python3 -c " # Fix: reduce card padding/gaps and ensure footer shows completely # We'll patch the HTML template CSS values import os html_dir = '/home/daytona/workspace/shifa-health-posts/html/' for f in sorted(os.listdir(html_dir)): path = html_dir + f with open(path, 'r') as fh: content = fh.read() # Tighten up the content area to give footer more room # Change: content padding-top from 7px to 5px, gap from 5px to 4px content = content.replace('padding: 7px 24px 4px 24px;', 'padding: 5px 22px 3px 22px;') content = content.replace('gap: 5px;', 'gap: 4px;') # Reduce card padding content = content.replace('padding: 8px 16px 8px 16px;', 'padding: 6px 14px 6px 14px;') # Reduce card-body font from 19px to 18px content = content.replace('font-size: 19px;', 'font-size: 18px;') # Reduce card-label from 23px to 22px content = content.replace('font-size: 23px;', 'font-size: 22px;') # Reduce header min-height content = content.replace('min-height: 188px;', 'min-height: 178px;') content = content.replace('padding: 18px 40px 14px 40px;', 'padding: 14px 40px 10px 40px;') content = content.replace('font-size: 54px;', 'font-size: 50px;') with open(path, 'w') as fh: fh.write(content) print('Patched', len(os.listdir(html_dir)), 'HTML files') "

Running Command

python3 -c " import os, subprocess html_dir = '/home/daytona/workspace/shifa-health-posts/html/' out_dir = '/home/daytona/workspace/shifa-health-posts/fixed/' name_map = { 1:'Bladder_Infection', 2:'Kidney_Stones', 3:'Infertility', 4:'High_Blood_Pressure', 5:'Diabetes', 6:'ENT_Allergies', 7:'Joint_and_Back_Pain', 8:'Urinary_Tract_Infection', 9:'Acidity_and_Gastric_Problems', 10:'Seasonal_Flu_and_Cough' } for num in range(1, 11): html_path = os.path.join(html_dir, f'post_{num:02d}.html') out_png = os.path.join(out_dir, f'post_{num:02d}_{name_map[num]}.png') cmd = [ 'chromium', '--headless', '--disable-gpu', '--no-sandbox', '--disable-dev-shm-usage', '--window-size=1080,1080', f'--screenshot={out_png}', f'file://{html_path}' ] r = subprocess.run(cmd, capture_output=True, text=True, timeout=30) sz = os.path.getsize(out_png) if os.path.exists(out_png) else 0 print(f'Post {num:02d}: {sz//1024} KB') print('All done.') "

Reading File
Running Command

python3 -c " import os, subprocess from PIL import Image html_dir = '/home/daytona/workspace/shifa-health-posts/html/' out_dir = '/home/daytona/workspace/shifa-health-posts/fixed/' tmp_dir = '/tmp/shifa_tmp/' os.makedirs(tmp_dir, exist_ok=True) # Render at 1080x1200 (taller) then crop to 1080x1080 name_map = { 1:'Bladder_Infection', 2:'Kidney_Stones', 3:'Infertility', 4:'High_Blood_Pressure', 5:'Diabetes', 6:'ENT_Allergies', 7:'Joint_and_Back_Pain', 8:'Urinary_Tract_Infection', 9:'Acidity_and_Gastric_Problems', 10:'Seasonal_Flu_and_Cough' } for num in range(1, 11): html_path = os.path.join(html_dir, f'post_{num:02d}.html') tmp_png = os.path.join(tmp_dir, f'post_{num:02d}_tall.png') out_png = os.path.join(out_dir, f'post_{num:02d}_{name_map[num]}.png') # Render with taller window so nothing gets cut cmd = [ 'chromium', '--headless', '--disable-gpu', '--no-sandbox', '--disable-dev-shm-usage', '--window-size=1080,1200', f'--screenshot={tmp_png}', f'file://{html_path}' ] subprocess.run(cmd, capture_output=True, text=True, timeout=30) if os.path.exists(tmp_png) and os.path.getsize(tmp_png) > 5000: # Crop top 1080px img = Image.open(tmp_png) print(f' Post {num:02d} raw size: {img.size}') cropped = img.crop((0, 0, 1080, 1080)) cropped.save(out_png, 'PNG', optimize=False, compress_level=1) print(f' ✓ Saved {name_map[num]}.png ({os.path.getsize(out_png)//1024} KB)') else: print(f' ✗ Post {num:02d} render failed') "

Reading File
Reading File
Running Command

python3 -c " from PIL import Image import os d = '/home/daytona/workspace/shifa-health-posts/fixed/' files = sorted([f for f in os.listdir(d) if f.startswith('post_0') or f.startswith('post_1')]) all_ok = True for f in files: img = Image.open(d+f) img.verify() size = os.path.getsize(d+f) print(f'✓ {f} {img.size[0]}x{img.size[1]} {size//1024}KB') print(f'\nTotal: {len(files)} posts — ALL OK' if len(files)==10 else f'WARNING: only {len(files)} posts') "


✅ تمام 10 پوسٹس مکمل طور پر ٹھیک ہو گئیں!

مسئلہ کیا تھا: پہلے Pillow (Python image library) سے بنے پنگ فائلز صرف ڈاؤنلوڈ کرنے پر خراب لگتے تھے کیونکہ Urdu text ٹھیک سے render نہیں ہو رہی تھی۔
حل: تمام 10 پوسٹس کو HTML + CSS (RTL layout + Amiri Naskh font) سے نئے سرے سے بنایا اور Chromium browser سے pixel-perfect 1080×1080 PNG render کیا۔

📥 Download All 10 Fixed Posts

#موضوعDownload
1مثانے کا انفیکشن

post 01 Bladder Infection

Image · PNG

2گردوں کی پتھری

post 02 Kidney Stones

Image · PNG

3بانجھ پن / اولاد نہ ہونا

post 03 Infertility

Image · PNG

4ہائی بلڈ پریشر

post 04 High Blood Pressure

Image · PNG

5ذیابیطس / شوگر

post 05 Diabetes

Image · PNG

6کان، ناک اور گلے کی الرجی

post 06 ENT Allergies

Image · PNG

7جوڑوں اور کمر کا درد

post 07 Joint and Back Pain

Image · PNG

8پیشاب میں جلن اور انفیکشن

post 08 Urinary Tract Infection

Image · PNG

9معدے کی تیزابیت اور گیس

post 09 Acidity and Gastric Problems

Image · PNG

10موسمی بخار، نزلہ اور کھانسی

post 10 Seasonal Flu and Cough

Image · PNG

سائز: ہر فائل 1080×1080px - 200-270 KB - WhatsApp، Facebook، Instagram کے لیے بالکل تیار ✅

all pictured are not visiable. convert all files in to jpg file

Running Command

python3 -c " from PIL import Image import os src = '/home/daytona/workspace/shifa-health-posts/fixed/' dst = '/home/daytona/workspace/shifa-health-posts/jpg/' os.makedirs(dst, exist_ok=True) files = sorted([f for f in os.listdir(src) if f.endswith('.png')]) for f in files: img = Image.open(src + f).convert('RGB') out_name = f.replace('.png', '.jpg') out_path = dst + out_name img.save(out_path, 'JPEG', quality=95, optimize=True) size = os.path.getsize(out_path) print(f'✓ {out_name} ({size//1024} KB)') print(f'\nDone: {len(files)} JPG files saved to {dst}') "

Reading File
Crystal clear. Here are all 10 JPG download links:

✅ تمام 10 فائلز JPG میں تبدیل - Download کریں

#موضوعDownload
1مثانے کا انفیکشن

post 01 Bladder Infection

Image · JPG

2گردوں کی پتھری

post 02 Kidney Stones

Image · JPG

3بانجھ پن / اولاد نہ ہونا

post 03 Infertility

Image · JPG

4ہائی بلڈ پریشر

post 04 High Blood Pressure

Image · JPG

5ذیابیطس / شوگر

post 05 Diabetes

Image · JPG

6کان، ناک اور گلے کی الرجی

post 06 ENT Allergies

Image · JPG

7جوڑوں اور کمر کا درد

post 07 Joint and Back Pain

Image · JPG

8پیشاب میں جلن اور انفیکشن

post 08 Urinary Tract Infection

Image · JPG

9معدے کی تیزابیت اور گیس

post 09 Acidity and Gastric Problems

Image · JPG

10موسمی بخار، نزلہ اور کھانسی

post 10 Seasonal Flu and Cough

Image · JPG

Format: JPG • Size: 1080×1080px • Quality: 95% • File size: 146-159 KB each - WhatsApp، Facebook، Instagram پر آسانی سے share کریں ✅
This is a shared conversation. Sign in to Orris to start your own chat.