Make aesthetic mind map note for bams sanskrit 1st year

Asking for Preferences
Searching the Web

BAMS 1st year Sanskrit syllabus topics Laghu Siddhanta Kaumudi Amarakosha Vyakarana

Running Command

mkdir -p /home/daytona/workspace/bams-sanskrit-mindmap && ls /home/daytona/workspace/bams-sanskrit-mindmap/

Writing File

~/bams-sanskrit-mindmap/mindmap.py

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
import matplotlib.patheffects as pe
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages

# โ”€โ”€ Colour palette โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
BG        = "#1a1a2e"          # deep navy
CENTER_C  = "#e94560"          # crimson-rose  โ€“ centre node
BRANCH_C  = ["#0f3460","#16213e","#533483","#0f3460","#16213e"]
LEAF_PAL  = {
    "Laghu Siddhanta\nKaumudi": "#f5a623",
    "Vyakarana\n(Grammar)":     "#7ed957",
    "Amarakosha":               "#4fc3f7",
    "Vaidyakeeya\nSubhashitam": "#f06292",
    "Sanskrit\nLiterature":     "#ce93d8",
}
TEXT_LIGHT = "#f0f0f0"
TEXT_DARK  = "#1a1a2e"

# โ”€โ”€ Mind-map data โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
branches = {
    "Laghu Siddhanta\nKaumudi": [
        "Sanjรฑa Prakarana\n(Technical Terms)",
        "Hal Sandhi\n(Consonant Junction)",
        "Swar Sandhi\n(Vowel Junction)",
        "Visarga Sandhi\n(Visarga Rules)",
        "Karaka Prakarana\n(Case Relations)",
        "Samasodhanam\n(Translation Verses)",
    ],
    "Vyakarana\n(Grammar)": [
        "Ashtadhyayi\nBasics (Panini)",
        "Dhatu Paatha\n(Verb Roots)",
        "Vibhakti\n(7 Cases / Declensions)",
        "Lakara\n(10 Tenses & Moods)",
        "Krit & Taddhita\n(Suffixes)",
        "Samasa\n(Compound Words)",
    ],
    "Amarakosha": [
        "Swargadi Kanda\n(Heaven chapter)",
        "Bhuvargadi Kanda\n(Earth chapter)",
        "Samanya Kanda\n(General chapter)",
        "Dravya Names\n(Herbs & Substances)",
        "Anatomical Terms\n(Sharira Nama)",
        "Disease Names\n(Roga Nama)",
    ],
    "Vaidyakeeya\nSubhashitam": [
        "Subhashitas from\nCharaka Samhita",
        "Subhashitas from\nSushruta Samhita",
        "Subhashitas from\nAshtanga Hridayam",
        "Moral & Ethical\nVerses (Niti)",
        "Medical Aphorisms\n(Vaidya Vakya)",
    ],
    "Sanskrit\nLiterature": [
        "Devanagari Script\n& Pronunciation",
        "Shloka & Metre\n(Anushtup, Arya)",
        "Sandhi Rules\n(Review)",
        "Translation Practice\n(Sanskritโ†’English)",
        "Medical Texts\nIntroduction",
    ],
}

# โ”€โ”€ Layout helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def polar(r, deg):
    rad = np.deg2rad(deg)
    return r * np.cos(rad), r * np.sin(rad)

def draw_rounded_box(ax, x, y, text, width, height, facecolor, textcolor,
                     fontsize=9, zorder=3, bold=False):
    box = FancyBboxPatch((x - width/2, y - height/2), width, height,
                         boxstyle="round,pad=0.06", linewidth=1.4,
                         edgecolor="white", facecolor=facecolor,
                         zorder=zorder, alpha=0.93)
    ax.add_patch(box)
    weight = "bold" if bold else "normal"
    ax.text(x, y, text, ha='center', va='center', fontsize=fontsize,
            color=textcolor, fontweight=weight, zorder=zorder+1,
            multialignment='center',
            path_effects=[pe.withStroke(linewidth=1, foreground='black')])

def curved_arrow(ax, x0, y0, x1, y1, color, lw=1.5):
    ax.annotate("", xy=(x1, y1), xytext=(x0, y0),
                arrowprops=dict(arrowstyle="-", color=color, lw=lw,
                                connectionstyle="arc3,rad=0.15"),
                zorder=1)

# โ”€โ”€ Figure โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
fig, ax = plt.subplots(figsize=(22, 16))
fig.patch.set_facecolor(BG)
ax.set_facecolor(BG)
ax.set_xlim(-11, 11); ax.set_ylim(-8.5, 8.5)
ax.axis('off')

# โ”€โ”€ Decorative starfield โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
rng = np.random.default_rng(42)
sx = rng.uniform(-11, 11, 250); sy = rng.uniform(-8.5, 8.5, 250)
ss = rng.uniform(0.3, 2.5, 250)
ax.scatter(sx, sy, s=ss, color='white', alpha=0.35, zorder=0)

# โ”€โ”€ Title banner โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
ax.text(0, 8.0, "BAMS 1st Year  ยท  Sanskrit", ha='center', va='center',
        fontsize=20, color='#f5a623', fontweight='bold',
        path_effects=[pe.withStroke(linewidth=3, foreground='black')])
ax.text(0, 7.5, "Comprehensive Mind Map", ha='center', va='center',
        fontsize=13, color='#ce93d8', style='italic')

# โ”€โ”€ Centre node โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
draw_rounded_box(ax, 0, 0, "เคธเค‚เคธเฅเค•เฅƒเคค\nSanskrit", 2.4, 1.4,
                 CENTER_C, TEXT_LIGHT, fontsize=16, zorder=5, bold=True)

# โ”€โ”€ Branch angles โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
branch_angles = [150, 80, 10, 300, 220]   # degrees from centre for each branch

branch_r  = 4.2   # centre  โ†’ branch-node distance
leaf_r    = 3.3   # branch โ†’ leaf offset

branch_names = list(branches.keys())
branch_colors = list(LEAF_PAL.values())

for i, (bname, angle) in enumerate(zip(branch_names, branch_angles)):
    bc  = branch_colors[i]
    bx, by = polar(branch_r, angle)

    # line: centre โ†’ branch
    curved_arrow(ax, 0, 0, bx*0.85, by*0.85, color=bc, lw=2.2)

    # branch node
    draw_rounded_box(ax, bx, by, bname, 2.3, 1.1, bc, TEXT_DARK,
                     fontsize=10.5, zorder=4, bold=True)

    # leaves
    leaves = branches[bname]
    n = len(leaves)
    # spread leaves ยฑ35ยฐ around the branch direction, pushed further out
    spread = 38
    if n == 1:
        leaf_angles = [angle]
    else:
        leaf_angles = [angle + spread*(k - (n-1)/2)/(n-1)*2 for k in range(n)]

    for j, (leaf, la) in enumerate(zip(leaves, leaf_angles)):
        lx = bx + leaf_r * np.cos(np.deg2rad(la))
        ly = by + leaf_r * np.sin(np.deg2rad(la))

        # clamp to canvas
        lx = np.clip(lx, -10.0, 10.0)
        ly = np.clip(ly, -7.8,   7.8)

        # line: branch โ†’ leaf
        curved_arrow(ax, bx, by, lx, ly, color=bc, lw=1.3)

        # leaf node โ€“ lighter shade
        leaf_face = bc + "99"   # add alpha hex
        draw_rounded_box(ax, lx, ly, leaf, 2.1, 0.85, bc+"55", TEXT_LIGHT,
                         fontsize=8.5, zorder=3)

# โ”€โ”€ Footer โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
ax.text(0, -8.1, "ยฉ BAMS Sanskrit 1st Year  |  Mind Map Notes  |  2026",
        ha='center', va='center', fontsize=8, color='#888888')

plt.tight_layout(pad=0.3)

# โ”€โ”€ Save PDF โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
out = "/home/daytona/workspace/bams-sanskrit-mindmap/BAMS_Sanskrit_1stYear_MindMap.pdf"
with PdfPages(out) as pdf:
    pdf.savefig(fig, facecolor=BG, bbox_inches='tight', dpi=200)

print(f"Saved โ†’ {out}")
plt.close()
Running Command

cd /home/daytona/workspace/bams-sanskrit-mindmap && python mindmap.py 2>&1

Editing File

~/bams-sanskrit-mindmap/mindmap.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/bams-sanskrit-mindmap/mindmap.py'
Writing File

~/bams-sanskrit-mindmap/mindmap_v2.py

"""
BAMS 1st Year Sanskrit โ€“ Aesthetic Mind Map (PDF)
Dark theme ยท Coloured branches ยท Rounded nodes ยท Star background
"""
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, Circle, Wedge
import matplotlib.patheffects as pe
from matplotlib.backends.backend_pdf import PdfPages
import numpy as np

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# COLOUR PALETTE
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
BG       = "#12102b"   # deep indigo night
CENTER_C = "#e63946"   # vivid red
GLOW_C   = "#ff6b6b"   # glow ring

BRANCH_COLORS = {
    "Laghu Siddhanta\nKaumudi" : {"node": "#f4a261", "leaf": "#2d1a08"},
    "Vyakarana\n(Grammar)"     : {"node": "#06d6a0", "leaf": "#062d1e"},
    "Amarakosha"                : {"node": "#4cc9f0", "leaf": "#062030"},
    "Vaidyakeeya\nSubhashitam" : {"node": "#f72585", "leaf": "#2d0617"},
    "Sanskrit\nLiterature"     : {"node": "#a29bfe", "leaf": "#150d2e"},
}

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# MIND-MAP DATA
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
branches = {
    "Laghu Siddhanta\nKaumudi": {
        "desc": "Varadaraja's\ngrammar primer",
        "leaves": [
            "Sanjรฑa Prakarana\n(Technical Terms)",
            "Swar Sandhi\n(Vowel Junction)",
            "Hal Sandhi\n(Consonant Junction)",
            "Visarga Sandhi\n(Visarga Rules)",
            "Karaka Prakarana\n(Case Relations)",
            "Samasodhanam\n(Translation Verses)",
        ],
    },
    "Vyakarana\n(Grammar)": {
        "desc": "Paninian\ngrammar system",
        "leaves": [
            "Ashtadhyayi Basics\n(Panini's sutras)",
            "Dhatu Paatha\n(Verb Roots)",
            "Vibhakti\n(7 Case Endings)",
            "Lakara\n(10 Tenses & Moods)",
            "Krit & Taddhita\n(Suffixes)",
            "Samasa\n(Compound Words)",
        ],
    },
    "Amarakosha": {
        "desc": "Amarasimha's\nthesaurus",
        "leaves": [
            "Svargadi Kanda\n(Heavenly chapter)",
            "Bhuvargadi Kanda\n(Earth chapter)",
            "Samanya Kanda\n(General chapter)",
            "Herb & Drug Names\n(Dravya Naama)",
            "Anatomical Terms\n(Sharira Naama)",
            "Disease Names\n(Roga Naama)",
        ],
    },
    "Vaidyakeeya\nSubhashitam": {
        "desc": "Medical aphorisms\nfrom classics",
        "leaves": [
            "Charaka Samhita\nSubhashitas",
            "Sushruta Samhita\nSubhashitas",
            "Ashtanga Hridayam\nSubhashitas",
            "Niti (Ethics)\nVerses",
            "Vaidya Vakya\n(Physician Maxims)",
        ],
    },
    "Sanskrit\nLiterature": {
        "desc": "Script, metre\n& translation",
        "leaves": [
            "Devanagari Script\n& Pronunciation",
            "Shloka Metres\n(Anushtup, Arya)",
            "Sandhi Rules\n(Revision)",
            "Translation Practice\n(Sanskritโ†’English)",
            "Introduction to\nMedical Texts",
        ],
    },
}

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# HELPERS
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
def polar(r, deg):
    rad = np.deg2rad(deg)
    return r * np.cos(rad), r * np.sin(rad)

def draw_box(ax, x, y, text, w, h, face, text_col="#f0f0f0",
             fs=9, zorder=3, bold=False, alpha=0.92, radius=0.12):
    box = FancyBboxPatch((x - w/2, y - h/2), w, h,
                         boxstyle=f"round,pad={radius}",
                         linewidth=1.5, edgecolor="white",
                         facecolor=face, zorder=zorder, alpha=alpha)
    ax.add_patch(box)
    weight = "bold" if bold else "normal"
    ax.text(x, y, text, ha='center', va='center', fontsize=fs,
            color=text_col, fontweight=weight, zorder=zorder+1,
            multialignment='center', linespacing=1.4,
            path_effects=[pe.withStroke(linewidth=1.5, foreground='black')])

def draw_glow_circle(ax, x, y, r, color, alpha=0.18, zorder=2):
    for i in range(4):
        c = Circle((x, y), r * (1 + 0.35*i), color=color,
                   alpha=alpha * (0.7**i), zorder=zorder, linewidth=0)
        ax.add_patch(c)

def curved_line(ax, x0, y0, x1, y1, color, lw=1.6, rad=0.2):
    ax.annotate("", xy=(x1, y1), xytext=(x0, y0),
                arrowprops=dict(
                    arrowstyle="-",
                    color=color, lw=lw,
                    connectionstyle=f"arc3,rad={rad}",
                    alpha=0.75,
                ),
                zorder=1)

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# FIGURE SETUP
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
fig, ax = plt.subplots(figsize=(24, 17))
fig.patch.set_facecolor(BG)
ax.set_facecolor(BG)
ax.set_xlim(-12, 12); ax.set_ylim(-9, 9)
ax.axis('off')

# โ”€โ”€ Starfield โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
rng = np.random.default_rng(7)
sx = rng.uniform(-12, 12, 320); sy = rng.uniform(-9, 9, 320)
ss = rng.uniform(0.2, 3.5, 320)
ax.scatter(sx, sy, s=ss, color='white', alpha=0.28, zorder=0)

# โ”€โ”€ Background radial gradient rings โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
for r, a in [(8, 0.04), (6, 0.06), (4, 0.08), (2.5, 0.07)]:
    c = Circle((0, 0), r, color="#5e4fa2", alpha=a, zorder=0)
    ax.add_patch(c)

# โ”€โ”€ Title โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
ax.text(0, 8.5, "BAMS 1st Year  ยท  Sanskrit", ha='center',
        fontsize=24, color='#f4a261', fontweight='bold',
        path_effects=[pe.withStroke(linewidth=4, foreground='black')])
ax.text(0, 8.0, "Comprehensive Mind Map  ยท  2026", ha='center',
        fontsize=13, color='#a29bfe', style='italic')

# thin divider line
ax.plot([-8, 8], [7.65, 7.65], color='#a29bfe', lw=0.8, alpha=0.4, zorder=1)

# โ”€โ”€ Centre node โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
draw_glow_circle(ax, 0, 0, 1.4, CENTER_C, alpha=0.22, zorder=1)
draw_box(ax, 0, 0, "SANSKRIT\nBAMS 1st Year", 2.8, 1.5,
         CENTER_C, "#ffffff", fs=15, zorder=5, bold=True, alpha=0.97, radius=0.18)

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# BRANCHES & LEAVES
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
branch_angles = [145, 75, 5, 290, 215]   # one per branch
branch_r      = 4.5                       # centre โ†’ branch node
leaf_r_base   = 3.2                       # branch โ†’ leaf node

branch_names = list(branches.keys())

for i, (bname, angle) in enumerate(zip(branch_names, branch_angles)):
    palette  = BRANCH_COLORS[bname]
    nc       = palette["node"]
    lc       = palette["leaf"]
    data     = branches[bname]
    leaves   = data["leaves"]
    n        = len(leaves)

    bx, by = polar(branch_r, angle)

    # โ”€โ”€ Centre โ†’ Branch line
    curved_line(ax, 0, 0, bx * 0.80, by * 0.80, color=nc, lw=2.5,
                rad=0.12 * (1 if i % 2 == 0 else -1))

    # โ”€โ”€ Branch glow
    draw_glow_circle(ax, bx, by, 1.1, nc, alpha=0.15, zorder=2)

    # โ”€โ”€ Branch node
    draw_box(ax, bx, by, bname, 2.5, 1.15,
             nc, "#0d0d0d", fs=11, zorder=4, bold=True, alpha=0.95)

    # โ”€โ”€ Small description badge below branch node
    ax.text(bx, by - 0.78, data["desc"], ha='center', va='top',
            fontsize=7.5, color=nc, alpha=0.75, style='italic',
            multialignment='center', zorder=4)

    # โ”€โ”€ Leaf spread
    spread = 44
    if n == 1:
        leaf_angles = [angle]
    else:
        leaf_angles = [angle + spread * (k - (n-1)/2) / ((n-1)/2)
                       for k in range(n)]

    for j, (leaf, la) in enumerate(zip(leaves, leaf_angles)):
        lx = bx + leaf_r_base * np.cos(np.deg2rad(la))
        ly = by + leaf_r_base * np.sin(np.deg2rad(la))

        # clamp to canvas edges
        lx = np.clip(lx, -10.8, 10.8)
        ly = np.clip(ly, -8.0,   7.5)

        # โ”€โ”€ Branch โ†’ Leaf line
        curved_line(ax, bx, by, lx, ly, color=nc, lw=1.4,
                    rad=0.10 * (1 if j % 2 == 0 else -1))

        # โ”€โ”€ Leaf node (semi-transparent dark fill with coloured border)
        leaf_face = lc
        box = FancyBboxPatch((lx - 1.15, ly - 0.5), 2.3, 1.0,
                             boxstyle="round,pad=0.07",
                             linewidth=1.6, edgecolor=nc,
                             facecolor=leaf_face, zorder=3, alpha=0.88)
        ax.add_patch(box)
        ax.text(lx, ly, leaf, ha='center', va='center', fontsize=8.2,
                color="#e8e8e8", zorder=4, multialignment='center',
                linespacing=1.35,
                path_effects=[pe.withStroke(linewidth=1, foreground='black')])

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# LEGEND / KEY BOX
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
legend_x, legend_y = -11.5, -5.5
ax.text(legend_x, legend_y + 1.6, "BRANCH KEY", ha='left', fontsize=9,
        color='#cccccc', fontweight='bold',
        path_effects=[pe.withStroke(linewidth=1.5, foreground='black')])
for k, (bname, pal) in enumerate(BRANCH_COLORS.items()):
    label = bname.replace('\n', ' ')
    swatch = FancyBboxPatch((legend_x, legend_y + 1.1 - k*0.45 - 0.18),
                            0.3, 0.28, boxstyle="round,pad=0.03",
                            facecolor=pal["node"], edgecolor='white',
                            linewidth=0.7, zorder=4)
    ax.add_patch(swatch)
    ax.text(legend_x + 0.45, legend_y + 1.1 - k*0.45, label,
            ha='left', va='center', fontsize=8, color='#dddddd', zorder=4)

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# FOOTER
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
ax.text(0, -8.7,
        "BAMS Sanskrit Paper I: Laghu Siddhanta Kaumudi  ยท  Paper II: Vaidyakeeya Subhashitam  ยท  Amarakosha  ยท  2026",
        ha='center', fontsize=7.8, color='#666688', zorder=1)

plt.tight_layout(pad=0.2)

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# SAVE
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
out = "/home/daytona/workspace/bams-sanskrit-mindmap/BAMS_Sanskrit_1stYear_MindMap.pdf"
with PdfPages(out) as pdf:
    pdf.savefig(fig, facecolor=BG, bbox_inches='tight', dpi=220)

print(f"Saved -> {out}")
plt.close()
Running Command

cd /home/daytona/workspace/bams-sanskrit-mindmap && python mindmap_v2.py 2>&1

Running Command

ls -lh /home/daytona/workspace/bams-sanskrit-mindmap/

Your mind map is ready! ๐ŸŽ“

BAMS Sanskrit 1stYear MindMap

PDF Document ยท PDF

(388 KB, print-ready A3 landscape)

What's inside the mind map:

BranchColourSub-topics covered
Laghu Siddhanta Kaumudi๐ŸŸ  AmberSanjรฑa, Swar/Hal/Visarga Sandhi, Karaka, Samasodhanam
Vyakarana (Grammar)๐ŸŸข TealAshtadhyayi, Dhatu Paatha, Vibhakti, Lakara, Samasa
Amarakosha๐Ÿ”ต BlueSvargadi/Bhuvargadi/Samanya Kanda, Herb/Anatomy/Disease names
Vaidyakeeya Subhashitam๐Ÿฉท PinkCharaka, Sushruta, Ashtanga Hridayam subhashitas, Niti verses
Sanskrit Literature๐ŸŸฃ PurpleDevanagari, Shloka metres, Sandhi revision, Translation practice

Design features:

  • Deep indigo night background with starfield
  • Each branch has its own colour with glowing node rings
  • Curved connector lines between nodes
  • Branch key legend in the bottom-left corner
  • Paper I & Paper II footer reference

Make aesthetic notes for sanskrit bams chapter 1

Asking for Preferences
Searching the Web

BAMS Sanskrit 1st year Chapter 1 Sanjรฑa Prakarana Laghu Siddhanta Kaumudi syllabus content sutras

Reading Web Page

https://www.sanskritfromhome.org/course-details/laghu_siddhaโ€ฆ

Writing File

~/bams-sanskrit-mindmap/chapter1_notes.py

"""
BAMS 1st Year Sanskrit
Chapter 1 โ€“ Sanjรฑa Prakarana (Laghu Siddhanta Kaumudi)
Aesthetic Multi-Page PDF Notes
"""
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
import matplotlib.patheffects as pe
from matplotlib.backends.backend_pdf import PdfPages
import numpy as np

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# THEME
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
BG       = "#0f0e17"
CARD     = "#1a1a2e"
ACCENT1  = "#f4a261"   # gold-orange
ACCENT2  = "#4cc9f0"   # sky blue
ACCENT3  = "#06d6a0"   # mint green
ACCENT4  = "#f72585"   # hot pink
ACCENT5  = "#a29bfe"   # lavender
WHITE    = "#f0f0f0"
MUTED    = "#aaaacc"
DIVIDER  = "#2a2a4a"

HEADING_COLORS = [ACCENT1, ACCENT2, ACCENT3, ACCENT4, ACCENT5]

def star_bg(ax, n=200, seed=42):
    rng = np.random.default_rng(seed)
    ax.scatter(rng.uniform(0,1,n), rng.uniform(0,1,n),
               s=rng.uniform(0.2,2.8,n), color='white', alpha=0.22,
               transform=ax.transAxes, zorder=0, clip_on=False)

def gradient_rect(ax, x, y, w, h, color, alpha=0.18, zorder=1):
    box = FancyBboxPatch((x,y), w, h,
                         boxstyle="round,pad=0.01",
                         facecolor=color, edgecolor='none',
                         alpha=alpha, zorder=zorder)
    ax.add_patch(box)

def section_header(ax, x, y, text, color, fontsize=13):
    ax.text(x, y, text, fontsize=fontsize, color=color, fontweight='bold',
            va='top', ha='left', transform=ax.transAxes,
            path_effects=[pe.withStroke(linewidth=2, foreground='black')])
    # underline
    ax.axhline(y=y - 0.002, xmin=x, xmax=x+0.6,
               color=color, lw=1.2, alpha=0.5, transform=ax.transAxes)

def body_text(ax, x, y, text, color=WHITE, fontsize=9.5, style='normal'):
    ax.text(x, y, text, fontsize=fontsize, color=color,
            va='top', ha='left', transform=ax.transAxes,
            style=style, wrap=True,
            path_effects=[pe.withStroke(linewidth=1, foreground='black')])

def bullet(ax, x, y, text, color=ACCENT1, fontsize=9.2):
    ax.text(x, y, "โ—†", fontsize=7, color=color, va='top', ha='left',
            transform=ax.transAxes)
    ax.text(x+0.025, y, text, fontsize=fontsize, color=WHITE, va='top',
            ha='left', transform=ax.transAxes,
            path_effects=[pe.withStroke(linewidth=1, foreground='black')])

def card(ax, x, y, w, h, title, lines, hcolor, seed=0):
    """Draw a rounded card with title + bullet lines."""
    # background
    box = FancyBboxPatch((x, y), w, h,
                         boxstyle="round,pad=0.012",
                         facecolor=CARD, edgecolor=hcolor,
                         linewidth=1.5, alpha=0.92,
                         transform=ax.transAxes, zorder=3)
    ax.add_patch(box)
    # title bar
    tbar = FancyBboxPatch((x, y+h-0.065), w, 0.062,
                          boxstyle="round,pad=0.008",
                          facecolor=hcolor, edgecolor='none', alpha=0.85,
                          transform=ax.transAxes, zorder=4)
    ax.add_patch(tbar)
    ax.text(x + w/2, y+h-0.033, title,
            fontsize=9, color='#0d0d0d', fontweight='bold',
            ha='center', va='center', transform=ax.transAxes, zorder=5,
            path_effects=[pe.withStroke(linewidth=1, foreground='black')])
    for k, line in enumerate(lines):
        ax.text(x+0.014, y+h-0.09 - k*0.042, f"โ€ข {line}",
                fontsize=8.2, color=WHITE, va='top', ha='left',
                transform=ax.transAxes, zorder=5,
                path_effects=[pe.withStroke(linewidth=1, foreground='black')])

def page_frame(fig, title_main, title_sub, page_num, total_pages, color):
    fig.patch.set_facecolor(BG)
    ax = fig.add_axes([0, 0, 1, 1])
    ax.set_xlim(0,1); ax.set_ylim(0,1)
    ax.axis('off')
    ax.set_facecolor(BG)

    # stars
    star_bg(ax, n=220, seed=page_num*7)

    # top banner
    banner = FancyBboxPatch((0.0, 0.935), 1.0, 0.065,
                            boxstyle="square,pad=0",
                            facecolor=color, edgecolor='none', alpha=0.90,
                            transform=ax.transAxes, zorder=3)
    ax.add_patch(banner)
    ax.text(0.5, 0.968, title_main, fontsize=16, color='#0d0d0d',
            fontweight='bold', ha='center', va='center',
            transform=ax.transAxes, zorder=4)

    # subtitle bar
    subbar = FancyBboxPatch((0.0, 0.900), 1.0, 0.034,
                            boxstyle="square,pad=0",
                            facecolor=CARD, edgecolor='none', alpha=0.97,
                            transform=ax.transAxes, zorder=3)
    ax.add_patch(subbar)
    ax.text(0.5, 0.917, title_sub, fontsize=10, color=color,
            ha='center', va='center', style='italic',
            transform=ax.transAxes, zorder=4)

    # bottom footer
    foot = FancyBboxPatch((0.0, 0.0), 1.0, 0.032,
                          boxstyle="square,pad=0",
                          facecolor=CARD, edgecolor='none', alpha=0.97,
                          transform=ax.transAxes, zorder=3)
    ax.add_patch(foot)
    ax.text(0.5, 0.016,
            f"BAMS 1st Year  ยท  Sanskrit  ยท  Laghu Siddhanta Kaumudi  ยท  Page {page_num}/{total_pages}",
            fontsize=7.5, color=MUTED, ha='center', va='center',
            transform=ax.transAxes, zorder=4)

    # side accent lines
    ax.plot([0.008, 0.008], [0.035, 0.897], color=color, lw=2.5, alpha=0.35,
            transform=ax.transAxes, zorder=2)
    ax.plot([0.992, 0.992], [0.035, 0.897], color=color, lw=2.5, alpha=0.35,
            transform=ax.transAxes, zorder=2)

    return ax

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# PAGE DATA
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
out = "/home/daytona/workspace/bams-sanskrit-mindmap/BAMS_Sanskrit_Ch1_SanjรฑaPrakarana.pdf"
TOTAL = 5

with PdfPages(out) as pdf:

    # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    # PAGE 1 โ€“ OVERVIEW & INTRODUCTION
    # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    fig = plt.figure(figsize=(11.69, 8.27))  # A4 landscape
    ax = page_frame(fig,
                    "Chapter 1 ยท Sanjรฑa Prakarana (Sanjรฑa Prakaranam)",
                    "Laghu Siddhanta Kaumudi  ยท  BAMS 1st Year Sanskrit",
                    1, TOTAL, ACCENT1)

    # โ”€โ”€ Overview card (left) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    card(ax, 0.03, 0.66, 0.44, 0.22, "WHAT IS SANJร‘A PRAKARANA?",
         ["Sanjรฑa = Technical term / Name",
          "Prakarana = Chapter / Section",
          "Deals with technical terms used in Paninian grammar",
          "Foundation for understanding all grammar rules (sutras)",
          "From Laghu Siddhanta Kaumudi by Varadaraja"],
         ACCENT1)

    # โ”€โ”€ Author card (right) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    card(ax, 0.53, 0.66, 0.44, 0.22, "ABOUT THE TEXT",
         ["Laghu Siddhanta Kaumudi โ€“ by Varadaraja",
          "Varadaraja = student of Bhattoji Dikshita",
          "Condensed from Vaiyakarana Siddhanta Kaumudi",
          "Contains ~1270 sutras (approx. 30% of Ashtadhyayi)",
          "Best entry-level text for Paninian grammar"],
         ACCENT2)

    # โ”€โ”€ Importance โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    ax.text(0.03, 0.64, "WHY IS THIS CHAPTER IMPORTANT?",
            fontsize=11.5, color=ACCENT3, fontweight='bold',
            va='top', transform=ax.transAxes,
            path_effects=[pe.withStroke(linewidth=2, foreground='black')])
    ax.axhline(y=0.625, xmin=0.03, xmax=0.97,
               color=ACCENT3, lw=0.8, alpha=0.4, transform=ax.transAxes)

    reasons = [
        ("It-Sanjรฑa (เค‡เคคเฅเคธเค‚เคœเฅเคžเคพ)", "Markers used to indicate phonological operations โ€“ not pronounced but carry meaning"),
        ("Swara Classification",   "Classifies all vowels (Swaras) into short, long, pluta, and Anudatta/Udatta/Svarita"),
        ("Sthana & Prayatna",      "Place (Sthana) and effort (Prayatna) of articulation for every letter"),
        ("Savarna (เคธเคตเคฐเฅเคฃ)",        "Defines homogeneous sounds โ€“ critical for Sandhi and substitution rules"),
        ("Anubandhas",             "Auxiliary markers in sutras that trigger specific grammatical operations"),
    ]
    for k, (term, desc) in enumerate(reasons):
        ypos = 0.598 - k * 0.082
        # coloured pill
        pill = FancyBboxPatch((0.03, ypos-0.003), 0.22, 0.042,
                              boxstyle="round,pad=0.006",
                              facecolor=HEADING_COLORS[k], edgecolor='none',
                              alpha=0.85, transform=ax.transAxes, zorder=3)
        ax.add_patch(pill)
        ax.text(0.14, ypos+0.018, term, fontsize=8.5,
                color='#0d0d0d', fontweight='bold', ha='center', va='center',
                transform=ax.transAxes, zorder=4)
        ax.text(0.265, ypos+0.018, desc, fontsize=8.5,
                color=WHITE, va='center', ha='left',
                transform=ax.transAxes, zorder=3,
                path_effects=[pe.withStroke(linewidth=1, foreground='black')])

    pdf.savefig(fig, facecolor=BG, bbox_inches='tight')
    plt.close()

    # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    # PAGE 2 โ€“ IT-SANJร‘A (ANUBANDHA)
    # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    fig = plt.figure(figsize=(11.69, 8.27))
    ax = page_frame(fig,
                    "It-Sanjรฑa (เค‡เคคเฅเคธเค‚เคœเฅเคžเคพ) ยท Anubandha Markers",
                    "Chapter 1 ยท Sanjรฑa Prakarana",
                    2, TOTAL, ACCENT2)

    ax.text(0.05, 0.875, "DEFINITION  โ—†  Sutra: 1.3.2  โ€“  upadese'janunasika it",
            fontsize=10, color=ACCENT2, fontweight='bold',
            va='top', transform=ax.transAxes,
            path_effects=[pe.withStroke(linewidth=2, foreground='black')])

    body_text(ax, 0.05, 0.848,
              '"An anunasika (nasal) vowel in an upadesa (grammatical recitation) is called It."',
              color=MUTED, fontsize=9.5, style='italic')
    body_text(ax, 0.05, 0.818,
              "It-sanjรฑa letters are technical markers (anubandhas) added to roots, suffixes, and sutras.\n"
              "They are NEVER actually pronounced in the final word โ€” they serve only as grammatical signals.",
              color=WHITE, fontsize=9.2)

    # table of It markers
    headers = ["It Marker", "Type", "Location", "Function / Effect"]
    rows = [
        ["a (เค…)", "Short a", "End of verb root (Dhatu)", "Indicates the root takes Atmanepada endings"],
        ["i (เค‡)", "Short i", "End of Krit suffix", "Indicates Guna does NOT apply to the root vowel"],
        ["u (เค‰)", "Short u", "End of suffix", "Indicates the suffix is Nit โ€“ prevents Vriddhi"],
        ["n (เคฃเฅ)", "Consonant N", "After prefix", "Converts 'n' to retroflex 'N' (Natva rule)"],
        ["k (เค•เฅ)", "Consonant K", "End of suffix / sutra", "Kit suffix โ€“ prevents Guna/Vriddhi of root vowel"],
        ["p (เคชเฅ)", "Consonant P", "End of suffix", "Pit suffix โ€“ specific phonological behaviour"],
        ["m (เคฎเฅ)", "Consonant M", "End of taddhita suffix", "Mit suffix โ€“ indicates specific accent"],
        ["t (เคคเฅ)", "Consonant T", "End of suffix", "Tit suffix โ€“ inserted before final consonant of base"],
    ]
    col_widths = [0.14, 0.10, 0.21, 0.44]
    col_starts = [0.03, 0.18, 0.29, 0.51]
    row_h = 0.052

    # header row
    for j, (hdr, xs, wd) in enumerate(zip(headers, col_starts, col_widths)):
        hbox = FancyBboxPatch((xs, 0.71), wd-0.005, 0.038,
                              boxstyle="round,pad=0.005",
                              facecolor=ACCENT2, edgecolor='none', alpha=0.9,
                              transform=ax.transAxes, zorder=3)
        ax.add_patch(hbox)
        ax.text(xs + (wd-0.005)/2, 0.729, hdr,
                fontsize=8.5, color='#0d0d0d', fontweight='bold',
                ha='center', va='center', transform=ax.transAxes, zorder=4)

    for i, row in enumerate(rows):
        yrow = 0.704 - i * row_h
        rowcol = CARD if i % 2 == 0 else "#1f1f38"
        full_bg = FancyBboxPatch((0.03, yrow), 0.930, row_h-0.004,
                                 boxstyle="round,pad=0.004",
                                 facecolor=rowcol, edgecolor=DIVIDER,
                                 linewidth=0.5, alpha=0.88,
                                 transform=ax.transAxes, zorder=3)
        ax.add_patch(full_bg)
        for j, (cell, xs, wd) in enumerate(zip(row, col_starts, col_widths)):
            tc = ACCENT1 if j == 0 else WHITE
            ax.text(xs+0.008, yrow + row_h/2 - 0.003, cell,
                    fontsize=8.0, color=tc, va='center',
                    transform=ax.transAxes, zorder=4,
                    path_effects=[pe.withStroke(linewidth=1, foreground='black')])

    # Memory tip
    tip_box = FancyBboxPatch((0.03, 0.042), 0.94, 0.072,
                             boxstyle="round,pad=0.01",
                             facecolor="#1a2e1a", edgecolor=ACCENT3,
                             linewidth=1.5, alpha=0.92,
                             transform=ax.transAxes, zorder=3)
    ax.add_patch(tip_box)
    ax.text(0.05, 0.097, "MEMORY TIP:", fontsize=9, color=ACCENT3,
            fontweight='bold', va='center', transform=ax.transAxes, zorder=4)
    ax.text(0.19, 0.097,
            "It letters are like 'silent instructions' baked into the grammar code โ€“ they guide rules but never appear in the spoken or written word.",
            fontsize=8.8, color=WHITE, va='center', transform=ax.transAxes, zorder=4,
            path_effects=[pe.withStroke(linewidth=1, foreground='black')])

    pdf.savefig(fig, facecolor=BG, bbox_inches='tight')
    plt.close()

    # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    # PAGE 3 โ€“ SWARA CLASSIFICATION & VARNA SAMAMNAYA
    # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    fig = plt.figure(figsize=(11.69, 8.27))
    ax = page_frame(fig,
                    "Swara (Vowel) Classification & Varna Samamnaya",
                    "Chapter 1 ยท Sanjรฑa Prakarana",
                    3, TOTAL, ACCENT3)

    # Left column: Swara types
    ax.text(0.03, 0.878, "SWARA (VOWEL) CLASSIFICATION",
            fontsize=11, color=ACCENT3, fontweight='bold',
            va='top', transform=ax.transAxes,
            path_effects=[pe.withStroke(linewidth=2, foreground='black')])
    ax.axhline(y=0.868, xmin=0.03, xmax=0.50, color=ACCENT3,
               lw=0.8, alpha=0.4, transform=ax.transAxes)

    swara_data = [
        ("Hrasva (เคนเฅเคฐเคธเฅเคต)", "Short", "a, i, u, rฬฅ, lฬฅ", ACCENT1, "1 Matra (unit of time)"),
        ("Dirgha (เคฆเฅ€เคฐเฅเค˜)", "Long", "aa, ii, uu, rฬฅrฬฅ", ACCENT2, "2 Matras"),
        ("Pluta (เคชเฅเคฒเฅเคค)", "Prolonged", "a3, i3, u3", ACCENT4, "3 Matras โ€” Vedic chanting"),
        ("Udatta (เค‰เคฆเคพเคคเฅเคค)", "High tone", "Marked with acute โ€ฒ", ACCENT5, "High-pitched accent"),
        ("Anudatta (เค…เคจเฅเคฆเคพเคคเฅเคค)", "Low tone", "Marked with underscore _", ACCENT3, "Low-pitched accent"),
        ("Svarita (เคธเฅเคตเคฐเคฟเคค)", "Mixed tone", "Marked with vertical |", ACCENT1, "Rising-falling tone"),
    ]
    for k, (name, eng, eg, col, note) in enumerate(swara_data):
        y0 = 0.840 - k * 0.095
        pill = FancyBboxPatch((0.03, y0), 0.200, 0.060,
                              boxstyle="round,pad=0.008",
                              facecolor=col, edgecolor='none', alpha=0.82,
                              transform=ax.transAxes, zorder=3)
        ax.add_patch(pill)
        ax.text(0.130, y0+0.032, name, fontsize=8.8, color='#0d0d0d',
                fontweight='bold', ha='center', va='center',
                transform=ax.transAxes, zorder=4)
        ax.text(0.244, y0+0.042, f"({eng})", fontsize=8.2, color=col,
                fontweight='bold', va='center', transform=ax.transAxes, zorder=4,
                path_effects=[pe.withStroke(linewidth=1.2, foreground='black')])
        ax.text(0.244, y0+0.020, f"Eg: {eg}", fontsize=8.0, color=WHITE,
                va='center', transform=ax.transAxes, zorder=4,
                path_effects=[pe.withStroke(linewidth=1, foreground='black')])
        ax.text(0.244, y0+0.002, f"โ†’ {note}", fontsize=7.5, color=MUTED,
                va='center', transform=ax.transAxes, zorder=4)

    # Right column: Maheshvara Sutras
    ax.text(0.54, 0.878, "MAHESHVARA SUTRAS (Shiva Sutras)",
            fontsize=11, color=ACCENT4, fontweight='bold',
            va='top', transform=ax.transAxes,
            path_effects=[pe.withStroke(linewidth=2, foreground='black')])
    ax.axhline(y=0.868, xmin=0.54, xmax=0.98, color=ACCENT4,
               lw=0.8, alpha=0.4, transform=ax.transAxes)

    body_text(ax, 0.54, 0.850,
              "14 sutras revealed to Panini by Lord Shiva's drum (Damaru).\n"
              "They list all Sanskrit phonemes in a specific order\n"
              "enabling Panini to write shorthand notations (Pratyaharas).",
              color=WHITE, fontsize=9.0)

    sutras = [
        "1. a i u N",    "2. rฬฅ lฬฅ K",
        "3. e o N",      "4. ai au C",
        "5. ha ya va ra T",  "6. la N",
        "7. na ma na na nam M",  "8. jha bha N",
        "9. gha dha dha S",  "10. ja ba ga da da SH",
        "11. kha pha cha tha tha ca ta ta V",  "12. ka pa Y",
        "13. sha sha sa R",  "14. ha L",
    ]
    for k, s in enumerate(sutras):
        col_idx = k % 2
        xs_s = 0.54 + col_idx * 0.235
        ys_s = 0.720 - (k // 2) * 0.068
        sbox = FancyBboxPatch((xs_s, ys_s), 0.218, 0.055,
                              boxstyle="round,pad=0.006",
                              facecolor=CARD, edgecolor=ACCENT4,
                              linewidth=1.0, alpha=0.90,
                              transform=ax.transAxes, zorder=3)
        ax.add_patch(sbox)
        ax.text(xs_s + 0.109, ys_s + 0.027, s,
                fontsize=8.2, color=WHITE, ha='center', va='center',
                transform=ax.transAxes, zorder=4,
                path_effects=[pe.withStroke(linewidth=1, foreground='black')])

    # Pratyahara note
    note_box = FancyBboxPatch((0.54, 0.038), 0.425, 0.070,
                              boxstyle="round,pad=0.01",
                              facecolor="#1e1428", edgecolor=ACCENT5,
                              linewidth=1.5, alpha=0.93,
                              transform=ax.transAxes, zorder=3)
    ax.add_patch(note_box)
    ax.text(0.555, 0.090, "PRATYAHARA:", fontsize=9, color=ACCENT5,
            fontweight='bold', va='center', transform=ax.transAxes, zorder=4)
    ax.text(0.555, 0.063,
            "A Pratyahara is a shorthand for a group of phonemes.\n"
            "Eg: 'AC' = all vowels  |  'HAL' = all consonants  |  'AL' = all letters",
            fontsize=8.5, color=WHITE, va='center', transform=ax.transAxes, zorder=4,
            path_effects=[pe.withStroke(linewidth=1, foreground='black')])

    pdf.savefig(fig, facecolor=BG, bbox_inches='tight')
    plt.close()

    # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    # PAGE 4 โ€“ STHANA & PRAYATNA + SAVARNA
    # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    fig = plt.figure(figsize=(11.69, 8.27))
    ax = page_frame(fig,
                    "Sthana (Place) ยท Prayatna (Effort) ยท Savarna",
                    "Chapter 1 ยท Sanjรฑa Prakarana",
                    4, TOTAL, ACCENT4)

    # Sthana table
    ax.text(0.03, 0.878, "STHANA (Place of Articulation)",
            fontsize=11, color=ACCENT4, fontweight='bold',
            va='top', transform=ax.transAxes,
            path_effects=[pe.withStroke(linewidth=2, foreground='black')])
    ax.axhline(y=0.866, xmin=0.03, xmax=0.62, color=ACCENT4,
               lw=0.8, alpha=0.4, transform=ax.transAxes)

    sthana_data = [
        ("Kantha (เค•เคฃเฅเค )", "Throat / Velar",     "a, aa, ka-varga (k kh g gh ng), h, visarga", ACCENT1),
        ("Talu (เคคเคพเคฒเฅ)",   "Palatal",              "i, ii, ca-varga (c ch j jh รฑ), y, sh",       ACCENT2),
        ("Murdha (เคฎเฅ‚เคฐเฅเคงเคพ)", "Retroflex / Cerebral","rฬฅ, rฬฅrฬฅ, ta-varga (T Th D Dh N), r, Sh",     ACCENT4),
        ("Danta (เคฆเคจเฅเคค)",  "Dental",               "lฬฅ, ta-varga (t th d dh n), l, s",            ACCENT3),
        ("Oshtha (เค“เคทเฅเค )", "Labial",               "u, uu, pa-varga (p ph b bh m), Upadhmaniya",  ACCENT5),
        ("Kantha-Talu",   "Throat + Palate",      "e, ai",                                       ACCENT1),
        ("Kantha-Oshtha", "Throat + Lips",        "o, au",                                       ACCENT2),
        ("Danta-Oshtha",  "Teeth + Lips",         "v (labio-dental)",                            ACCENT3),
        ("Nasika (เคจเคพเคธเคฟเค•เคพ)","Nasal",               "All nasal consonants (ng รฑ N n m)",           ACCENT4),
    ]
    for k, (sth, eng, letters, col) in enumerate(sthana_data):
        y0 = 0.843 - k * 0.073
        bg = FancyBboxPatch((0.03, y0), 0.56, 0.062,
                            boxstyle="round,pad=0.005",
                            facecolor=CARD if k%2==0 else "#1f1f38",
                            edgecolor=col, linewidth=0.9, alpha=0.90,
                            transform=ax.transAxes, zorder=3)
        ax.add_patch(bg)
        ax.text(0.042, y0+0.032, sth, fontsize=8.5, color=col,
                fontweight='bold', va='center', transform=ax.transAxes,
                zorder=4,
                path_effects=[pe.withStroke(linewidth=1, foreground='black')])
        ax.text(0.220, y0+0.042, eng, fontsize=7.8, color=MUTED,
                va='center', transform=ax.transAxes, zorder=4)
        ax.text(0.220, y0+0.018, letters, fontsize=7.8, color=WHITE,
                va='center', transform=ax.transAxes, zorder=4,
                path_effects=[pe.withStroke(linewidth=1, foreground='black')])

    # Prayatna column
    ax.text(0.64, 0.878, "PRAYATNA (Effort of Articulation)",
            fontsize=11, color=ACCENT5, fontweight='bold',
            va='top', transform=ax.transAxes,
            path_effects=[pe.withStroke(linewidth=2, foreground='black')])
    ax.axhline(y=0.866, xmin=0.64, xmax=0.98, color=ACCENT5,
               lw=0.8, alpha=0.4, transform=ax.transAxes)

    prayatna_groups = {
        "BAHYA PRAYATNA\n(External Effort)": {
            "color": ACCENT2,
            "items": [
                ("Sprishta", "Complete contact โ€“ stops (k,c,T,t,pโ€ฆ)"),
                ("Ishat Sprishta", "Slight contact โ€“ semi-vowels (y,r,l,v)"),
                ("Vivrita", "Open โ€“ vowels & fricatives (h,sh,s)"),
            ]
        },
        "ABHYANTARA PRAYATNA\n(Internal Effort)": {
            "color": ACCENT4,
            "items": [
                ("Ghosa", "Voiced โ€“ vowels & voiced consonants"),
                ("Aghosa", "Voiceless โ€“ k,kh,c,ch,T,Th,t,th,p,ph,sh,Sh,s"),
                ("Alpaprana", "Unaspirated โ€“ 1st & 3rd in each varga"),
                ("Mahaprana", "Aspirated โ€“ 2nd & 4th in each varga"),
                ("Anunasika", "Nasal โ€“ 5th in each varga (ng,รฑ,N,n,m)"),
            ]
        },
    }
    yp = 0.843
    for grp, gdata in prayatna_groups.items():
        gc = gdata["color"]
        grp_box = FancyBboxPatch((0.64, yp - 0.018), 0.34, 0.052,
                                 boxstyle="round,pad=0.006",
                                 facecolor=gc, edgecolor='none', alpha=0.85,
                                 transform=ax.transAxes, zorder=3)
        ax.add_patch(grp_box)
        ax.text(0.81, yp+0.009, grp, fontsize=8.0, color='#0d0d0d',
                fontweight='bold', ha='center', va='center',
                transform=ax.transAxes, zorder=4, multialignment='center')
        yp -= 0.055
        for term, desc in gdata["items"]:
            row_bg = FancyBboxPatch((0.64, yp-0.004), 0.34, 0.046,
                                   boxstyle="round,pad=0.004",
                                   facecolor=CARD, edgecolor=gc,
                                   linewidth=0.8, alpha=0.88,
                                   transform=ax.transAxes, zorder=3)
            ax.add_patch(row_bg)
            ax.text(0.652, yp+0.030, term, fontsize=8.0, color=gc,
                    fontweight='bold', va='center', transform=ax.transAxes,
                    zorder=4,
                    path_effects=[pe.withStroke(linewidth=1, foreground='black')])
            ax.text(0.652, yp+0.008, desc, fontsize=7.8, color=WHITE,
                    va='center', transform=ax.transAxes, zorder=4,
                    path_effects=[pe.withStroke(linewidth=1, foreground='black')])
            yp -= 0.050

    # Savarna box
    sv = FancyBboxPatch((0.03, 0.038), 0.94, 0.078,
                        boxstyle="round,pad=0.012",
                        facecolor="#1a2b1a", edgecolor=ACCENT3,
                        linewidth=1.8, alpha=0.94,
                        transform=ax.transAxes, zorder=3)
    ax.add_patch(sv)
    ax.text(0.05, 0.100, "SAVARNA (เคธเคตเคฐเฅเคฃ) โ€” Homogeneous Sounds:",
            fontsize=9.5, color=ACCENT3, fontweight='bold',
            va='center', transform=ax.transAxes, zorder=4)
    ax.text(0.05, 0.070,
            "Two sounds are Savarna if they share the same Sthana (place) AND same Abhyantara Prayatna (internal effort).\n"
            "Eg: 'a' and 'aa' are Savarna  |  'i' and 'ii' are Savarna  |  Short & Long vowels of same place = Savarna.",
            fontsize=8.8, color=WHITE, va='center', transform=ax.transAxes, zorder=4,
            path_effects=[pe.withStroke(linewidth=1, foreground='black')])

    pdf.savefig(fig, facecolor=BG, bbox_inches='tight')
    plt.close()

    # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    # PAGE 5 โ€“ KEY SUTRAS, QUICK REVISION TABLE & EXAM TIPS
    # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    fig = plt.figure(figsize=(11.69, 8.27))
    ax = page_frame(fig,
                    "Key Sutras ยท Quick Revision ยท Exam Tips",
                    "Chapter 1 ยท Sanjรฑa Prakarana",
                    5, TOTAL, ACCENT5)

    # Key sutras
    ax.text(0.03, 0.878, "IMPORTANT SUTRAS TO MEMORISE",
            fontsize=11, color=ACCENT5, fontweight='bold',
            va='top', transform=ax.transAxes,
            path_effects=[pe.withStroke(linewidth=2, foreground='black')])
    ax.axhline(y=0.866, xmin=0.03, xmax=0.97, color=ACCENT5,
               lw=0.8, alpha=0.4, transform=ax.transAxes)

    key_sutras = [
        ("1.3.2",  "Upadese'janunasika it",         "Nasal vowel in upadesa = It (marker)"),
        ("1.3.3",  "Halantyam",                      "Final consonant of a sutra/suffix = It"),
        ("1.3.9",  "Tasya lopaแธฅ",                    "Lopa (deletion) of It letters โ€” they vanish"),
        ("1.1.69", "Anuditta atmanepade",             "Anudatta vowel in Dhatu = Atmanepada verb"),
        ("1.1.70", "Tapara stata-kala-sya",          "T-final marker = only that duration (Hrasva/Dirgha)"),
        ("1.1.68", "Svarasya",                       "Rule specifically about vowels (svaras)"),
        ("8.4.68", "A a",                             "Savarna = same Sthana and Prayatna"),
        ("1.1.60", "Adicante savarne dirgha",         "Two Savarna vowels merge into one long (Dirgha) vowel"),
    ]
    col_w = [0.075, 0.22, 0.60]
    col_x = [0.03, 0.115, 0.345]
    hdr_labels = ["Sutra No.", "Sutra (Transliterated)", "Meaning / Application"]
    # header
    for j, (hdr, xs, wd) in enumerate(zip(hdr_labels, col_x, col_w)):
        hb = FancyBboxPatch((xs, 0.808), wd-0.005, 0.040,
                            boxstyle="round,pad=0.004",
                            facecolor=ACCENT5, edgecolor='none', alpha=0.88,
                            transform=ax.transAxes, zorder=3)
        ax.add_patch(hb)
        ax.text(xs+(wd-0.005)/2, 0.828, hdr, fontsize=8.5,
                color='#0d0d0d', fontweight='bold', ha='center', va='center',
                transform=ax.transAxes, zorder=4)

    for i, (num, sutra, meaning) in enumerate(key_sutras):
        yr = 0.802 - i * 0.063
        bg2 = FancyBboxPatch((0.03, yr), 0.94, 0.053,
                             boxstyle="round,pad=0.004",
                             facecolor=CARD if i%2==0 else "#1f1f38",
                             edgecolor=DIVIDER, linewidth=0.5, alpha=0.88,
                             transform=ax.transAxes, zorder=3)
        ax.add_patch(bg2)
        ax.text(0.068, yr+0.026, num, fontsize=8.2, color=ACCENT5,
                fontweight='bold', ha='center', va='center',
                transform=ax.transAxes, zorder=4,
                path_effects=[pe.withStroke(linewidth=1, foreground='black')])
        ax.text(0.120, yr+0.026, sutra, fontsize=8.2, color=ACCENT2,
                va='center', transform=ax.transAxes, zorder=4, style='italic',
                path_effects=[pe.withStroke(linewidth=1, foreground='black')])
        ax.text(0.350, yr+0.026, meaning, fontsize=8.2, color=WHITE,
                va='center', transform=ax.transAxes, zorder=4,
                path_effects=[pe.withStroke(linewidth=1, foreground='black')])

    # Exam tips cards (bottom row)
    tips = [
        ("EXAM TIPS", ACCENT1, [
            "Define Sanjรฑa, It-Sanjรฑa in your own words",
            "List all Sthanas with examples of letters",
            "Distinguish Savarna vs. non-Savarna",
            "State any 3 key sutras with meaning",
        ]),
        ("COMMON MISTAKES", ACCENT4, [
            "Confusing Sthana with Prayatna",
            "Forgetting that It letters are deleted (Lopa)",
            "Mixing up Hrasva/Dirgha/Pluta durations",
            "Not knowing Ghosa vs Aghosa distinction",
        ]),
        ("CONNECTIONS", ACCENT3, [
            "Sanjรฑa โ†’ foundation for Sandhi rules (Ch 2-4)",
            "Savarna โ†’ used in Savarna-Dirgha Sandhi",
            "Sthana-Prayatna โ†’ used in Shcutva & Stutva Sandhi",
            "It-Sanjรฑa โ†’ used throughout Dhatu Paatha",
        ]),
    ]
    for k, (title, col, items) in enumerate(tips):
        tx = 0.03 + k * 0.325
        card(ax, tx, 0.038, 0.310, 0.250, title, items, col)

    pdf.savefig(fig, facecolor=BG, bbox_inches='tight')
    plt.close()

print(f"Saved -> {out}")
Your credits are exhausted. Your daily credits reset tomorrow, or you can purchase a top-up for more.
This is a shared conversation. Sign in to Orris to start your own chat.