Mucogingival surgery
mucogingival surgery periodontics classification procedures techniques
mucogingival surgery periodontal plastic surgery root coverage
https://pocketdentistry.com/63-periodontal-plastic-and-esthe…
mucogingival surgery gingival recession Miller classification Cairo classification techniques free gingival graft connective tissue graft coronally advanced flap
"Surgical procedures performed to correct or eliminate anatomic, developmental, or traumatic deformities of the gingiva or alveolar mucosa."
| Class | Description | Root Coverage Expectation |
|---|---|---|
| I | Recession does not reach the MGJ; no interdental bone/soft tissue loss | 100% |
| II | Recession reaches or extends beyond the MGJ; no interdental bone/soft tissue loss | 100% |
| III | Recession extends to/beyond MGJ; interdental bone/soft tissue loss present, or tooth malposition | Partial coverage only |
| IV | Recession extends to/beyond MGJ; severe interdental bone/soft tissue loss or severe tooth malposition | No root coverage expected |
| Recession Type | Criteria |
|---|---|
| RT1 | No interproximal CAL loss (same as Miller I & II) |
| RT2 | Interproximal CAL loss ≤ buccal CAL loss |
| RT3 | Interproximal CAL loss > buccal CAL loss |
| Favorable | Unfavorable |
|---|---|
| Miller Class I or II / Cairo RT1 | Miller Class III-IV / Cairo RT3 |
| Shallow recession | Deep recession |
| Wide recession | Narrow keratinized band |
| Good plaque control | Smoking |
| No cervical abrasion/restoration | Non-carious cervical lesion |
| Young patient | Thin gingival biotype |
Gingival recession present?
↓
Classify: Miller / Cairo
↓
Miller I or II (RT1)? → Root coverage possible (100%)
Miller III (RT2)? → Partial coverage expected
Miller IV (RT3)? → Gingival augmentation only
↓
Root coverage goal?
├─ Single tooth, adequate adjacent gingiva → Laterally positioned flap OR CAF + CTG
├─ Multiple adjacent teeth → CAF + CTG or Tunnel + CTG
├─ Esthetics most important → SCTG (best color match)
└─ Patient morbidity concern → Consider collagen matrix substitute
↓
Widening KT only?
└─ Free gingival autograft (apical placement) or APF
↓
Frenum problem? → Frenectomy ± graft
Make a presentation on mucogingival surgical technique selection
ls -la /tmp/workspace/ 2>/dev/null || echo "workspace empty"
mkdir -p /tmp/workspace/mucogingival-pptx
~/mucogingival-pptx/build_pptx.py
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from pptx.enum.shapes import MSO_CONNECTOR
from io import BytesIO
# ── Colour palette ────────────────────────────────────────────────────────────
TEAL_DARK = RGBColor(0x00, 0x6D, 0x77) # deep teal – titles / accents
TEAL_MED = RGBColor(0x83, 0xC5, 0xBE) # mid teal – section bg
TEAL_LIGHT = RGBColor(0xEF, 0xF9, 0xF7) # near-white teal – slide bg
CORAL = RGBColor(0xE2, 0x94, 0x78) # warm coral – highlights
CORAL_DARK = RGBColor(0xC8, 0x6B, 0x4A) # darker coral
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
DARK_TEXT = RGBColor(0x1A, 0x1A, 0x2E) # near-black body text
GRAY_LIGHT = RGBColor(0xD6, 0xE8, 0xE5) # light gray-teal dividers
YELLOW_HL = RGBColor(0xFF, 0xD1, 0x66) # yellow highlight band
W = Inches(13.333)
H = Inches(7.5)
prs = Presentation()
prs.slide_width = W
prs.slide_height = H
blank = prs.slide_layouts[6] # fully blank
# ── Helper utilities ──────────────────────────────────────────────────────────
def bg(slide, color=TEAL_LIGHT):
"""Fill slide background."""
bg_shp = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, W, H)
bg_shp.fill.solid(); bg_shp.fill.fore_color.rgb = color
bg_shp.line.fill.background()
bg_shp.shadow.inherit = False
return bg_shp
def rect(slide, x, y, w, h, fill, line=None, lw=1):
s = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, x, y, w, h)
s.fill.solid(); s.fill.fore_color.rgb = fill
if line: s.line.color.rgb = line; s.line.width = Pt(lw)
else: s.line.fill.background()
s.shadow.inherit = False
return s
def rrect(slide, x, y, w, h, fill, line=None, lw=1):
s = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, w, h)
s.fill.solid(); s.fill.fore_color.rgb = fill
if line: s.line.color.rgb = line; s.line.width = Pt(lw)
else: s.line.fill.background()
s.shadow.inherit = False
return s
def tb(slide, x, y, w, h, text, size=18, bold=False, color=DARK_TEXT,
align=PP_ALIGN.LEFT, italic=False, wrap=True, font="Calibri",
valign=MSO_ANCHOR.TOP):
box = slide.shapes.add_textbox(x, y, w, h)
tf = box.text_frame
tf.word_wrap = wrap
tf.vertical_anchor = valign
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
p = tf.paragraphs[0]
p.alignment = align
r = p.add_run()
r.text = text
r.font.name = font
r.font.size = Pt(size)
r.font.bold = bold
r.font.italic = italic
r.font.color.rgb = color
return box
def tb_lines(slide, x, y, w, h, lines, size=16, bold_first=False,
color=DARK_TEXT, align=PP_ALIGN.LEFT, font="Calibri",
line_color=None, spacing=1.15):
"""Multi-line textbox; lines = list of (text, bold, size_override_or_None)"""
from pptx.util import Pt as pt2
from pptx.oxml.ns import qn
from lxml import etree
box = slide.shapes.add_textbox(x, y, w, h)
tf = box.text_frame
tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
for i, item in enumerate(lines):
if isinstance(item, str):
text, bold_flag, sz = item, (bold_first and i==0), size
else:
text = item[0]
bold_flag = item[1] if len(item) > 1 else False
sz = item[2] if len(item) > 2 else size
if i == 0:
p = tf.paragraphs[0]
else:
p = tf.add_paragraph()
p.alignment = align
r = p.add_run()
r.text = text
r.font.name = font
r.font.size = Pt(sz)
r.font.bold = bold_flag
r.font.color.rgb = line_color if line_color else color
return box
def header_bar(slide, title, subtitle=None):
"""Standard slide header: dark teal bar + title."""
rect(slide, 0, 0, W, Inches(1.25), TEAL_DARK)
# accent stripe
rect(slide, 0, Inches(1.25), W, Inches(0.07), CORAL)
tb(slide, Inches(0.45), Inches(0.15), Inches(12.4), Inches(0.9),
title, size=30, bold=True, color=WHITE, align=PP_ALIGN.LEFT,
valign=MSO_ANCHOR.MIDDLE, font="Calibri")
if subtitle:
tb(slide, Inches(0.45), Inches(0.85), Inches(12.4), Inches(0.35),
subtitle, size=16, bold=False, color=TEAL_LIGHT,
align=PP_ALIGN.LEFT, font="Calibri")
def dot(slide, x, y, r=0.1, color=CORAL):
s = slide.shapes.add_shape(MSO_SHAPE.OVAL,
x - Inches(r), y - Inches(r/2),
Inches(r*2), Inches(r*2))
s.fill.solid(); s.fill.fore_color.rgb = color
s.line.fill.background(); s.shadow.inherit = False
def card(slide, x, y, w, h, title, bullets, title_size=17, bullet_size=14,
card_color=WHITE, title_color=TEAL_DARK, bullet_color=DARK_TEXT,
accent=TEAL_DARK):
"""Rounded card with title band and bullet list."""
rrect(slide, x, y, w, h, card_color, GRAY_LIGHT, 1)
# title band
rect(slide, x, y, w, Inches(0.45), accent)
tb(slide, x + Inches(0.15), y + Inches(0.04),
w - Inches(0.3), Inches(0.37),
title, size=title_size, bold=True, color=WHITE,
align=PP_ALIGN.LEFT, valign=MSO_ANCHOR.MIDDLE)
# bullets
bx = x + Inches(0.18)
by = y + Inches(0.52)
bw = w - Inches(0.36)
bh = h - Inches(0.6)
lines = [(f" {b}", False, bullet_size) for b in bullets]
tb_lines(slide, bx, by, bw, bh, lines, color=bullet_color)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 1 – TITLE SLIDE
# ═══════════════════════════════════════════════════════════════════════════════
s1 = prs.slides.add_slide(blank)
bg(s1, TEAL_DARK)
# decorative shapes
for i, (cx, cy, r, col) in enumerate([
(12.8, 0.6, 1.2, TEAL_MED),
(13.1, 2.0, 0.7, CORAL),
(0.0, 7.0, 1.0, TEAL_MED),
]):
c = s1.shapes.add_shape(MSO_SHAPE.OVAL,
Inches(cx - r), Inches(cy - r),
Inches(r*2), Inches(r*2))
c.fill.solid(); c.fill.fore_color.rgb = col; c.line.fill.background()
c.shadow.inherit = False
rect(s1, Inches(0), Inches(3.2), W, Inches(0.08), CORAL)
tb(s1, Inches(1.0), Inches(1.0), Inches(11.3), Inches(1.0),
"MUCOGINGIVAL SURGERY", size=22, bold=False, color=TEAL_LIGHT,
align=PP_ALIGN.LEFT, font="Calibri")
tb(s1, Inches(1.0), Inches(1.7), Inches(11.3), Inches(1.6),
"Surgical Technique Selection", size=44, bold=True, color=WHITE,
align=PP_ALIGN.LEFT, font="Calibri")
tb(s1, Inches(1.0), Inches(3.4), Inches(11.3), Inches(0.55),
"A systematic approach to choosing the right procedure", size=20,
bold=False, color=TEAL_LIGHT, align=PP_ALIGN.LEFT, italic=True)
# bottom bar
rect(s1, 0, Inches(6.8), W, Inches(0.7), RGBColor(0x00, 0x4E, 0x58))
tb(s1, Inches(1.0), Inches(6.82), Inches(11), Inches(0.55),
"Periodontology | Periodontal Plastic Surgery | Clinical Decision Framework",
size=15, color=TEAL_MED, align=PP_ALIGN.LEFT)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 2 – OVERVIEW / AGENDA
# ═══════════════════════════════════════════════════════════════════════════════
s2 = prs.slides.add_slide(blank)
bg(s2)
header_bar(s2, "Overview", "What this presentation covers")
items = [
("1", "Definition & Scope of Mucogingival Surgery"),
("2", "Anatomy: Mucogingival Junction & Attached Gingiva"),
("3", "Classification of Gingival Recession"),
("4", "Decision Framework: How to Select a Technique"),
("5", "Pedicle Soft Tissue Graft Procedures"),
("6", "Free Soft Tissue Graft Procedures"),
("7", "Tunnel Technique & Minimally Invasive Approaches"),
("8", "Gingival Augmentation & Frenectomy"),
("9", "Biologics & Adjuncts"),
("10","Summary & Evidence-Based Recommendations"),
]
col_w = Inches(5.8)
col1_x = Inches(0.6)
col2_x = Inches(7.0)
top_y = Inches(1.5)
gap = Inches(0.52)
for i, (num, label) in enumerate(items):
col = 0 if i < 5 else 1
row = i if i < 5 else i - 5
x = col1_x if col == 0 else col2_x
y = top_y + row * gap
# number badge
nb = s2.shapes.add_shape(MSO_SHAPE.OVAL, x, y + Inches(0.04),
Inches(0.38), Inches(0.38))
nb.fill.solid(); nb.fill.fore_color.rgb = TEAL_DARK
nb.line.fill.background(); nb.shadow.inherit = False
tf_nb = nb.text_frame
tf_nb.margin_left = tf_nb.margin_right = tf_nb.margin_top = tf_nb.margin_bottom = 0
p_nb = tf_nb.paragraphs[0]; p_nb.alignment = PP_ALIGN.CENTER
r_nb = p_nb.add_run(); r_nb.text = num
r_nb.font.name = "Calibri"; r_nb.font.size = Pt(13)
r_nb.font.bold = True; r_nb.font.color.rgb = WHITE
# label
tb(s2, x + Inches(0.48), y, col_w - Inches(0.5), Inches(0.45),
label, size=17, color=DARK_TEXT, valign=MSO_ANCHOR.MIDDLE)
# underline
ln = s2.shapes.add_connector(MSO_CONNECTOR.STRAIGHT,
x + Inches(0.48), y + Inches(0.43),
x + col_w - Inches(0.1), y + Inches(0.43))
ln.line.color.rgb = GRAY_LIGHT; ln.line.width = Pt(0.75)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 3 – DEFINITION & SCOPE
# ═══════════════════════════════════════════════════════════════════════════════
s3 = prs.slides.add_slide(blank)
bg(s3)
header_bar(s3, "Definition & Scope")
# Quote box
rect(s3, Inches(0.55), Inches(1.45), Inches(12.2), Inches(1.5), RGBColor(0xE8,0xF5,0xF3), TEAL_MED, 1)
rect(s3, Inches(0.55), Inches(1.45), Inches(0.12), Inches(1.5), TEAL_DARK)
tb(s3, Inches(0.82), Inches(1.55), Inches(11.7), Inches(1.3),
'"Surgical procedures performed to correct or eliminate anatomic, developmental, or traumatic deformities of the gingiva or alveolar mucosa."',
size=17, italic=True, color=TEAL_DARK, wrap=True)
tb(s3, Inches(0.82), Inches(2.8), Inches(8), Inches(0.35),
"— AAP / 1996 World Workshop in Clinical Periodontics", size=13,
color=CORAL_DARK, italic=True)
# Two-column layout
col_data = [
("Traditional Mucogingival Surgery (Friedman, 1957)", [
"Widening inadequate attached gingiva",
"Deepening shallow vestibules",
"Resecting aberrant frena",
], TEAL_DARK),
("Periodontal Plastic Surgery (Miller, 1993 / AAP 1996)", [
"Root coverage of denuded surfaces",
"Crown lengthening & ridge augmentation",
"Papilla reconstruction",
"Esthetic corrections around implants",
"Surgical exposure for orthodontics",
], CORAL_DARK),
]
xs = [Inches(0.55), Inches(6.9)]
for ci, (title, bullets, accent_col) in enumerate(col_data):
x = xs[ci]
card(s3, x, Inches(3.2), Inches(6.2), Inches(3.95),
title, bullets, title_size=15, bullet_size=14, accent=accent_col)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 4 – ANATOMY
# ═══════════════════════════════════════════════════════════════════════════════
s4 = prs.slides.add_slide(blank)
bg(s4)
header_bar(s4, "Key Anatomy", "Mucogingival Junction & Attached Gingiva")
# anatomy diagram (schematic bar)
diagram_x = Inches(7.2)
diagram_y = Inches(1.55)
diagram_w = Inches(5.7)
diagram_h = Inches(5.5)
bg_d = rrect(s4, diagram_x, diagram_y, diagram_w, diagram_h,
RGBColor(0xF0,0xF8,0xF7), GRAY_LIGHT, 1)
# layers of the periodontium (vertical cross-section schematic)
layers = [
(0.18, 0.55, RGBColor(0xFF,0xE0,0xCC), "Gingival Margin"),
(0.73, 0.65, RGBColor(0xFF,0xC8,0xA8), "Free Gingiva (~1 mm)"),
(1.38, 0.8, RGBColor(0xA8,0xD8,0xC8), "Attached Gingiva (1-9 mm)"),
(2.18, 0.5, RGBColor(0x83,0xC5,0xBE), "Mucogingival Junction (MGJ)"),
(2.68, 1.2, RGBColor(0xD4,0xE8,0xFF), "Alveolar Mucosa"),
]
bar_x = diagram_x + Inches(0.25)
bar_w = Inches(1.4)
for (rel_y, h, col, label) in layers:
ly = diagram_y + Inches(rel_y + 0.3)
lh = Inches(h)
rect(s4, bar_x, ly, bar_w, lh, col)
# label
tb(s4, bar_x + bar_w + Inches(0.15), ly + lh/2 - Inches(0.18),
Inches(3.5), Inches(0.36), label, size=13.5, color=DARK_TEXT,
valign=MSO_ANCHOR.MIDDLE)
# connector line
ln = s4.shapes.add_connector(MSO_CONNECTOR.STRAIGHT,
bar_x + bar_w, ly + lh/2,
bar_x + bar_w + Inches(0.12), ly + lh/2)
ln.line.color.rgb = TEAL_MED; ln.line.width = Pt(1)
# left column – clinical facts
facts = [
("MGJ Location", [
"~3 mm apical to alveolar bone crest (radicular)",
"~5 mm interdentally",
"Fixed landmark – does not move with inflammation",
]),
("Attached Gingiva", [
"Keratinized; bound to cementum & alveolar bone",
"Normal width: 1–9 mm (greatest at incisors)",
"Minimum adequate width: 1 mm (controversial)",
"Identified by the 'roll test'",
]),
("Clinical Significance", [
"Loss → mobility, plaque retention, recession",
"Measurement: distance from MGJ to gingival margin",
"minus probing depth = attached gingiva width",
]),
]
fy = Inches(1.45)
for (ftitle, fbullets) in facts:
card(s4, Inches(0.45), fy, Inches(6.5), Inches(5.6/3 - 0.05),
ftitle, fbullets, title_size=15, bullet_size=13, accent=TEAL_DARK)
fy += Inches(5.6/3 + 0.04)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 5 – CLASSIFICATION (Miller + Cairo)
# ═══════════════════════════════════════════════════════════════════════════════
s5 = prs.slides.add_slide(blank)
bg(s5)
header_bar(s5, "Classification of Gingival Recession",
"Miller (1985) vs Cairo (2011)")
# Miller table
rect(s5, Inches(0.45), Inches(1.45), Inches(6.2), Inches(0.5), TEAL_DARK)
for ci, (cw, label) in enumerate([
(Inches(0.7), "Class"), (Inches(2.8), "Description"), (Inches(2.7), "Root Coverage")
]):
cx = Inches(0.45) + sum(Inches(v) for v in ([0, 0.7, 3.5][:ci]))
tb(s5, cx + Inches(0.08), Inches(1.47), cw - Inches(0.1), Inches(0.46),
label, size=14, bold=True, color=WHITE, valign=MSO_ANCHOR.MIDDLE)
miller_rows = [
("I", "Does not extend to MGJ\nNo interdental tissue loss", "100% expected", TEAL_LIGHT),
("II", "Reaches or beyond MGJ\nNo interdental tissue loss", "100% expected", WHITE),
("III", "Extends to/beyond MGJ\nInterdental tissue loss / malposition", "Partial only", TEAL_LIGHT),
("IV", "Extends to/beyond MGJ\nSevere interdental loss / malposition", "Not expected", WHITE),
]
col_xs = [Inches(0.45), Inches(1.15), Inches(3.95)]
col_ws = [Inches(0.7), Inches(2.8), Inches(2.7)]
row_h = Inches(0.72)
for ri, (cls, desc, cov, bg_c) in enumerate(miller_rows):
ry = Inches(1.95) + ri * row_h
rect(s5, Inches(0.45), ry, Inches(6.2), row_h, bg_c, GRAY_LIGHT, 0.5)
for ci, (cx, cw, txt) in enumerate(zip(col_xs, col_ws,
[cls, desc, cov])):
bold_flag = (ci == 0)
col_c = CORAL_DARK if ci == 2 else (TEAL_DARK if ci == 0 else DARK_TEXT)
tb(s5, cx + Inches(0.08), ry + Inches(0.05),
cw - Inches(0.1), row_h - Inches(0.08),
txt, size=13, bold=bold_flag, color=col_c,
wrap=True, valign=MSO_ANCHOR.MIDDLE)
tb(s5, Inches(0.45), Inches(5.88), Inches(6.2), Inches(0.3),
"Miller PD Jr., Int J Periodontics Restorative Dent, 1985", size=11,
italic=True, color=RGBColor(0x80,0x80,0x80))
# Cairo table
rect(s5, Inches(7.0), Inches(1.45), Inches(6.0), Inches(0.5), CORAL_DARK)
for ci, (cw, label) in enumerate([
(Inches(0.8), "Type"), (Inches(2.6), "Criteria"), (Inches(2.6), "Corresponds to")
]):
cx = Inches(7.0) + sum([Inches(v) for v in ([0, 0.8, 3.4][:ci])])
tb(s5, cx + Inches(0.08), Inches(1.47), cw - Inches(0.1), Inches(0.46),
label, size=14, bold=True, color=WHITE, valign=MSO_ANCHOR.MIDDLE)
cairo_rows = [
("RT1", "No interproximal CAL loss",
"Miller Class I & II", TEAL_LIGHT),
("RT2", "Interproximal CAL loss\n≤ buccal CAL loss",
"Miller Class III", WHITE),
("RT3", "Interproximal CAL loss\n> buccal CAL loss",
"Miller Class IV", TEAL_LIGHT),
]
col_xs2 = [Inches(7.0), Inches(7.8), Inches(10.4)]
col_ws2 = [Inches(0.8), Inches(2.6), Inches(2.6)]
row_h2 = Inches(0.95)
for ri, (rtype, crit, corr, bg_c) in enumerate(cairo_rows):
ry = Inches(1.95) + ri * row_h2
rect(s5, Inches(7.0), ry, Inches(6.0), row_h2, bg_c, GRAY_LIGHT, 0.5)
for ci, (cx, cw, txt) in enumerate(zip(col_xs2, col_ws2,
[rtype, crit, corr])):
bold_flag = (ci == 0)
col_c = CORAL_DARK if ci == 0 else (TEAL_DARK if ci == 2 else DARK_TEXT)
tb(s5, cx + Inches(0.08), ry + Inches(0.08),
cw - Inches(0.1), row_h2 - Inches(0.1),
txt, size=13, bold=bold_flag, color=col_c,
wrap=True, valign=MSO_ANCHOR.MIDDLE)
tb(s5, Inches(7.0), Inches(4.92), Inches(6.0), Inches(0.3),
"Cairo F et al., J Clin Periodontol, 2011", size=11,
italic=True, color=RGBColor(0x80,0x80,0x80))
# comparison note
note_y = Inches(5.3)
rect(s5, Inches(0.45), note_y, Inches(12.55), Inches(1.75),
RGBColor(0xFF,0xF5,0xE8), CORAL, 1)
rect(s5, Inches(0.45), note_y, Inches(0.12), Inches(1.75), CORAL)
tb_lines(s5, Inches(0.72), note_y + Inches(0.15), Inches(12.1), Inches(1.5),
[("Key Differences", True, 15),
("Cairo RT1/RT2/RT3 replaces Miller I-IV; based on interproximal CAL (not bone radiographs) — more objective & reproducible.", False, 14),
("Both systems guide prognosis: RT1 (Miller I/II) = 100% coverage possible | RT2 (Miller III) = partial | RT3 (Miller IV) = augmentation only.", False, 14)],
color=DARK_TEXT)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 6 – DECISION FRAMEWORK
# ═══════════════════════════════════════════════════════════════════════════════
s6 = prs.slides.add_slide(blank)
bg(s6)
header_bar(s6, "Technique Selection Framework",
"Step-by-step clinical decision approach")
# flowchart boxes
def fc_box(slide, x, y, w, h, text, fill, tcolor=WHITE, sz=14, bold=True, rr=False):
fn = rrect if rr else rect
shp = fn(slide, x, y, w, h, fill)
tf = shp.text_frame
tf.word_wrap = True
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
tf.margin_left = Inches(0.1)
tf.margin_right = Inches(0.1)
tf.margin_top = Pt(4)
tf.margin_bottom = Pt(4)
p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER
r = p.add_run(); r.text = text
r.font.name = "Calibri"; r.font.size = Pt(sz)
r.font.bold = bold; r.font.color.rgb = tcolor
return shp
def arrow_down(slide, x, y, h, color=TEAL_DARK):
ln = slide.shapes.add_connector(MSO_CONNECTOR.STRAIGHT,
x, y, x, y + h)
ln.line.color.rgb = color; ln.line.width = Pt(2)
def arrow_right(slide, x, y, w, color=TEAL_DARK):
ln = slide.shapes.add_connector(MSO_CONNECTOR.STRAIGHT,
x, y, x + w, y)
ln.line.color.rgb = color; ln.line.width = Pt(2)
# Start box
bw = Inches(2.8); bh = Inches(0.52)
center_x = (W - bw) / 2
fc_box(s6, center_x, Inches(1.42), bw, bh,
"Gingival Recession Present?", TEAL_DARK, sz=15)
arrow_down(s6, W/2, Inches(1.94), Inches(0.25))
# Classify box
fc_box(s6, center_x, Inches(2.19), bw, bh,
"Classify: Miller / Cairo RT", TEAL_MED, DARK_TEXT, sz=14)
arrow_down(s6, W/2, Inches(2.71), Inches(0.22))
# Diamond: root coverage possible?
diam_x = center_x - Inches(0.15)
diam = s6.shapes.add_shape(MSO_SHAPE.DIAMOND,
diam_x, Inches(2.93), bw + Inches(0.3), bh + Inches(0.1))
diam.fill.solid(); diam.fill.fore_color.rgb = CORAL
diam.line.fill.background(); diam.shadow.inherit = False
tf_d = diam.text_frame; tf_d.word_wrap = True
tf_d.vertical_anchor = MSO_ANCHOR.MIDDLE
tf_d.margin_left = tf_d.margin_right = Inches(0.1)
tf_d.margin_top = tf_d.margin_bottom = Pt(2)
pd = tf_d.paragraphs[0]; pd.alignment = PP_ALIGN.CENTER
rd = pd.add_run(); rd.text = "Root coverage\ngoal? (RT1 / RT2)"
rd.font.name = "Calibri"; rd.font.size = Pt(13)
rd.font.bold = True; rd.font.color.rgb = WHITE
# Left branch – YES
arrow_right(s6, diam_x - Inches(0.12), Inches(3.18), -Inches(2.2))
tb(s6, Inches(0.35), Inches(3.0), Inches(2.0), Inches(0.35),
"YES", size=13, bold=True, color=TEAL_DARK)
# Sub-diamond: single or multiple?
sub_d = s6.shapes.add_shape(MSO_SHAPE.DIAMOND,
Inches(0.3), Inches(3.4), Inches(2.4), Inches(0.6))
sub_d.fill.solid(); sub_d.fill.fore_color.rgb = TEAL_DARK
sub_d.line.fill.background(); sub_d.shadow.inherit = False
tf_sd = sub_d.text_frame; tf_sd.vertical_anchor = MSO_ANCHOR.MIDDLE
tf_sd.margin_left = tf_sd.margin_right = Inches(0.05)
tf_sd.margin_top = tf_sd.margin_bottom = Pt(2)
psd = tf_sd.paragraphs[0]; psd.alignment = PP_ALIGN.CENTER
rsd = psd.add_run(); rsd.text = "Single or\nMultiple teeth?"
rsd.font.name = "Calibri"; rsd.font.size = Pt(12)
rsd.font.bold = True; rsd.font.color.rgb = WHITE
arrow_down(s6, Inches(1.5), Inches(4.0), Inches(0.2))
fc_box(s6, Inches(0.3), Inches(4.2), Inches(2.4), Inches(0.48),
"Single tooth", TEAL_MED, DARK_TEXT, sz=12, rr=True)
arrow_down(s6, Inches(1.5), Inches(4.68), Inches(0.2))
fc_box(s6, Inches(0.3), Inches(4.88), Inches(2.4), Inches(0.48),
"Laterally\nPositioned Flap\nor CAF + CTG", TEAL_DARK, sz=11, rr=True)
# Multiple arrow going right
arrow_right(s6, Inches(2.7), Inches(3.7), Inches(0.5))
tb(s6, Inches(2.6), Inches(3.52), Inches(0.8), Inches(0.35),
"Multiple", size=11, bold=True, color=TEAL_DARK)
fc_box(s6, Inches(3.2), Inches(3.4), Inches(2.4), Inches(0.6),
"CAF + CTG\nor Tunnel + CTG", CORAL_DARK, sz=12, rr=True)
# Right branch – NO (RT3)
arrow_right(s6, diam_x + bw + Inches(0.25), Inches(3.18), Inches(1.8))
tb(s6, diam_x + bw + Inches(0.28), Inches(3.0), Inches(1.5), Inches(0.35),
"NO (RT3)", size=13, bold=True, color=CORAL_DARK)
fc_box(s6, Inches(9.6), Inches(3.4), Inches(2.9), Inches(0.6),
"Gingival\nAugmentation Only", CORAL_DARK, sz=12, rr=True)
arrow_down(s6, Inches(11.05), Inches(4.0), Inches(0.2))
fc_box(s6, Inches(9.6), Inches(4.2), Inches(2.9), Inches(0.55),
"Free Gingival Autograft\nor APF", TEAL_DARK, sz=11, rr=True)
# middle path – esthetics concern
fc_box(s6, Inches(5.5), Inches(2.19), Inches(2.7), bh,
"Esthetics priority?", TEAL_MED, DARK_TEXT, sz=13, rr=True)
arrow_right(s6, Inches(6.65), Inches(2.45), Inches(0.9))
fc_box(s6, Inches(7.6), Inches(2.19), Inches(2.9), bh,
"SCTG (best color match)", TEAL_DARK, sz=12, rr=True)
# Bottom additional boxes
fc_box(s6, Inches(3.5), Inches(4.9), Inches(2.6), Inches(0.55),
"Donor site morbidity\nconcern?", RGBColor(0xF0,0xE8,0xFF), DARK_TEXT, sz=12, rr=True)
arrow_right(s6, Inches(6.1), Inches(5.175), Inches(0.35))
fc_box(s6, Inches(6.45), Inches(4.9), Inches(2.9), Inches(0.55),
"Collagen Matrix\n(Mucograft) substitute", TEAL_MED, DARK_TEXT, sz=12, rr=True)
# Frenum box
fc_box(s6, Inches(3.5), Inches(5.65), Inches(2.6), Inches(0.55),
"Aberrant frenum?", RGBColor(0xF0,0xE8,0xFF), DARK_TEXT, sz=12, rr=True)
arrow_right(s6, Inches(6.1), Inches(5.925), Inches(0.35))
fc_box(s6, Inches(6.45), Inches(5.65), Inches(2.9), Inches(0.55),
"Frenectomy ±\nGingival Graft", TEAL_MED, DARK_TEXT, sz=12, rr=True)
# Legend note
rect(s6, Inches(0.3), Inches(6.7), Inches(12.7), Inches(0.45),
RGBColor(0xE8,0xF5,0xF3), TEAL_MED, 0.5)
tb(s6, Inches(0.45), Inches(6.72), Inches(12.5), Inches(0.38),
"CAF = Coronally Advanced Flap | CTG = Connective Tissue Graft | "
"SCTG = Subepithelial CTG | APF = Apically Positioned Flap | RT = Recession Type (Cairo)",
size=12, color=TEAL_DARK)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 7 – PEDICLE SOFT TISSUE GRAFTS
# ═══════════════════════════════════════════════════════════════════════════════
s7 = prs.slides.add_slide(blank)
bg(s7)
header_bar(s7, "Pedicle Soft Tissue Graft Procedures",
"Tissue from adjacent site — maintains blood supply")
pedicle_cards = [
("Laterally Positioned (Sliding) Flap",
"Grupe & Warren, 1956",
TEAL_DARK,
["Pedicle rotated from adjacent donor tooth",
"Indication: isolated recession, adequate adjacent gingiva",
"Advantage: single-stage, good color match",
"Risk: recession at donor site",
"Best for: buccal surface, single tooth"]),
("Double Papilla Flap",
"Cohen & Ross, 1968",
TEAL_DARK,
["Papillae from BOTH sides of recession united over root",
"Good when lateral donor site is inadequate",
"Risk of sloughing if papilla blood supply compromised",
"Limited to shallow/narrow recessions"]),
("Coronally Advanced Flap (CAF)",
"Bernimoulin, 1975 / Tarnow, 1986",
TEAL_DARK,
["Most widely used technique today",
"Flap advanced coronally to cover exposed root",
"Used for single AND multiple adjacent teeth",
"Often combined with CTG (gold standard combination)",
"Requires ≥3 mm keratinized tissue coronal to recession"]),
("Semilunar Coronally Repositioned Flap",
"Tarnow, 1986",
CORAL_DARK,
["Semicircular incision apical to recession",
"No vertical releasing incisions needed",
"Simpler technique; less invasive",
"Limited indication: small, shallow recessions",
"Good blood supply; predictable healing"]),
]
cw = Inches(6.0); ch = Inches(2.55)
positions = [(Inches(0.45), Inches(1.42)),
(Inches(6.85), Inches(1.42)),
(Inches(0.45), Inches(4.1)),
(Inches(6.85), Inches(4.1))]
for (x, y), (title, author, accent_col, bullets) in zip(positions, pedicle_cards):
card(s7, x, y, cw, ch, title, bullets,
title_size=14, bullet_size=13, accent=accent_col)
tb(s7, x + Inches(0.15), y + Inches(0.46), cw - Inches(0.3), Inches(0.28),
author, size=12, italic=True, color=CORAL_DARK)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 8 – FREE SOFT TISSUE GRAFTS
# ═══════════════════════════════════════════════════════════════════════════════
s8 = prs.slides.add_slide(blank)
bg(s8)
header_bar(s8, "Free Soft Tissue Graft Procedures",
"Tissue harvested from palate — no vascular pedicle attachment")
# Gold standard callout
rect(s8, Inches(0.45), Inches(1.42), Inches(12.45), Inches(0.75),
RGBColor(0xFF,0xF0,0xD0), YELLOW_HL, 1.5)
rect(s8, Inches(0.45), Inches(1.42), Inches(0.15), Inches(0.75), YELLOW_HL)
tb(s8, Inches(0.75), Inches(1.48), Inches(12.0), Inches(0.62),
"GOLD STANDARD: CAF + SCTG (Subepithelial Connective Tissue Graft) — "
"Highest complete root coverage rates; best esthetic outcomes (Cochrane, 2018 / AAP Network Meta-analysis, 2022)",
size=15, bold=True, color=RGBColor(0x7A,0x50,0x00),
valign=MSO_ANCHOR.MIDDLE)
# FGG card
fgg_bullets = [
"Epithelialized graft from palate (Sullivan & Atkins, 1968)",
"Placed directly over root OR apical to recession (2-step: Bernimoulin)",
"Best for: widening keratinized tissue, not root coverage",
"Disadvantage: poor esthetics (color mismatch); donor site discomfort",
"Heals by primary intention (recipient) + secondary (donor palate)",
]
card(s8, Inches(0.45), Inches(2.32), Inches(5.9), Inches(4.75),
"Free Gingival Autograft (FGG)", fgg_bullets,
title_size=15, bullet_size=14, accent=TEAL_DARK)
# SCTG card
sctg_bullets = [
"Connective tissue harvested BENEATH palatal epithelium (Langer & Langer, 1985)",
"Placed under coronally advanced or envelope flap",
"Dual blood supply: periosteum + overlying flap",
"Superior esthetics: graft covered by flap → color match",
"Most effective for root coverage (Miller Class I & II / Cairo RT1)",
"Harvest: single incision / trap-door / double parallel incision technique",
]
card(s8, Inches(6.58), Inches(2.32), Inches(6.32), Inches(4.75),
"Subepithelial Connective Tissue Graft (SCTG / CTG)", sctg_bullets,
title_size=15, bullet_size=14, accent=CORAL_DARK)
# comparison footnote
tb(s8, Inches(0.45), Inches(7.12), Inches(12.5), Inches(0.3),
"CTG may be replaced by xenogeneic collagen matrices (Mucograft) when reducing donor site morbidity is a priority — slightly lower complete root coverage predictability.",
size=12, italic=True, color=RGBColor(0x60,0x60,0x60))
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 9 – TUNNEL TECHNIQUE
# ═══════════════════════════════════════════════════════════════════════════════
s9 = prs.slides.add_slide(blank)
bg(s9)
header_bar(s9, "Tunnel Technique & Minimally Invasive Approaches",
"Papilla-preserving, submarginal access")
# Main tunnel card
tun_bullets = [
"No papilla incisions — papillae remain intact",
"Subperiosteal tunnel created from recession to recession",
"CTG inserted through the tunnel beneath the flap",
"Flap and graft advanced coronally and sutured",
"Excellent for: multiple adjacent recessions in anterior region",
"Better healing, less scarring compared to CAF in some cases",
]
card(s9, Inches(0.45), Inches(1.42), Inches(6.15), Inches(4.3),
"Tunnel Technique (Allen, 1994 / Zabalegui, 1999)", tun_bullets,
title_size=15, bullet_size=14, accent=TEAL_DARK)
# Modifications
mod_cards = [
("Modified Tunnel (MCAT)", TEAL_DARK, [
"Microsurgical approach",
"Smaller incisions, magnification used",
"Reduced trauma to papillae",
"Higher complete root coverage in recent trials",
]),
("Laterally Closed Tunnel (LCT)", CORAL_DARK, [
"Sculean & Allen, 2018",
"Designed for deep isolated mandibular recessions",
"No vertical incisions; lateral releasing approach",
"Avoids tension on the flap",
]),
("VISTA Technique", TEAL_DARK, [
"Vestibular Incision Subperiosteal Tunnel Access",
"Remote access via vestibular incision",
"Excellent for anterior maxilla",
"Can combine with CTG or collagen matrix",
]),
]
for i, (mname, macc, mbullets) in enumerate(mod_cards):
my = Inches(1.42) + i * Inches(1.8)
card(s9, Inches(6.85), my, Inches(6.1), Inches(1.72),
mname, mbullets, title_size=14, bullet_size=13, accent=macc)
# Advantages vs Disadvantages
adv_y = Inches(5.9)
rect(s9, Inches(0.45), adv_y, Inches(5.9), Inches(1.25),
RGBColor(0xE8,0xF5,0xF3), TEAL_MED, 1)
tb_lines(s9, Inches(0.6), adv_y + Inches(0.1), Inches(5.6), Inches(1.1),
[("Advantages", True, 14),
("Preserved papillae | Less scarring | Good esthetics | Suits anterior maxilla", False, 13)],
color=DARK_TEXT)
rect(s9, Inches(6.85), adv_y, Inches(6.1), Inches(1.25),
RGBColor(0xFF,0xF0,0xEE), CORAL, 1)
tb_lines(s9, Inches(7.0), adv_y + Inches(0.1), Inches(5.8), Inches(1.1),
[("Limitations", True, 14),
("Technically demanding | Limited access for bone defects | Learning curve | Not ideal for posterior teeth", False, 13)],
color=DARK_TEXT)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 10 – GINGIVAL AUGMENTATION & FRENECTOMY
# ═══════════════════════════════════════════════════════════════════════════════
s10 = prs.slides.add_slide(blank)
bg(s10)
header_bar(s10, "Gingival Augmentation & Frenectomy",
"When root coverage is not the goal")
aug_cards = [
("Free Gingival Autograft (Augmentation)", TEAL_DARK, [
"Palatal epithelialized graft placed APICAL to existing gingiva",
"Increases keratinized tissue width without moving the gingival margin",
"Indication: inadequate attached gingiva (<1 mm) before orthodontics or restorations",
"Heals by epithelialization over 4-6 weeks",
"Color mismatch — acceptable in posterior regions",
]),
("Apically Positioned Flap (APF)", TEAL_DARK, [
"Partial-thickness (split) flap sutured apically",
"Periosteum exposed = stimulus for new keratinized gingiva",
"Also used for: crown lengthening, vestibuloplasty",
"Advantage: can treat multiple teeth simultaneously",
"Heals by secondary intention over exposed periosteum",
]),
("Vestibuloplasty / Gingival Extension", CORAL_DARK, [
"Deepens shallow vestibule by repositioning frenum/muscle attachments",
"Methods: denudation, periosteal retention, split flap",
"Important for complete denture stability",
"Often combined with FGG for long-term stability",
]),
]
for i, (atitle, aacc, abullets) in enumerate(aug_cards):
ay = Inches(1.42) + i * Inches(2.0)
card(s10, Inches(0.45), ay, Inches(5.9), Inches(1.9),
atitle, abullets, title_size=14, bullet_size=13, accent=aacc)
# Frenectomy section
fren_y = Inches(1.42)
card(s10, Inches(6.85), fren_y, Inches(6.1), Inches(5.75),
"Frenectomy / Frenuloplasty", [
"Indication: frenal pull on gingival margin causing recession",
"Midline diastema with thick maxillary labial frenum",
"Denture instability due to frenum",
"",
"Techniques:",
" Simple excision (scalpel)",
" Z-plasty — redirects the frenum, lengthens mucosa",
" Electrosurgery or laser (Er:YAG, diode)",
"",
"Often combined with:",
" Vestibuloplasty (deepens sulcus)",
" Free gingival graft (stabilizes result)",
"",
"Post-op: sutures at 7-10 days; stretching exercises",
],
title_size=15, bullet_size=13, accent=CORAL_DARK)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 11 – BIOLOGICS & ADJUNCTS
# ═══════════════════════════════════════════════════════════════════════════════
s11 = prs.slides.add_slide(blank)
bg(s11)
header_bar(s11, "Biologics & Adjuncts in Mucogingival Surgery",
"Evidence-based adjunctive therapies")
bio_data = [
("Enamel Matrix Derivative (EMD / Emdogain)", TEAL_DARK,
["Amelogenin proteins promote periodontal regeneration",
"Combined with CAF → improved root coverage in RT1 recessions",
"Possible new attachment formation (vs. long junctional epithelium)",
"Supported by multiple RCTs and meta-analyses"]),
("Platelet-Rich Fibrin (PRF / L-PRF)", CORAL_DARK,
["Autologous — concentrated growth factors (PDGF, TGF-β, VEGF)",
"Used as membrane or adjunct to CTG/CAF",
"Accelerates wound healing; reduces post-op pain",
"PRF + CAF = comparable to CTG + CAF in some trials"]),
("Collagen Matrix (Mucograft / ADMA)", TEAL_DARK,
["Xenogeneic porcine bilayer matrix",
"Substitute for FGG or CTG — eliminates second surgical site",
"Slightly less predictable complete root coverage vs autologous CTG",
"Best for: low-risk recessions (RT1) when patient declines palatal harvest",
"AAP 2022 network meta-analysis: good evidence for augmentation"]),
("rhPDGF-BB (Gem 21S)", CORAL_DARK,
["Recombinant human platelet-derived growth factor",
"Combined with beta-TCP scaffold",
"FDA-approved for periodontal osseous defects",
"Emerging evidence for mucogingival augmentation"]),
]
cw2 = Inches(5.9); ch2 = Inches(2.4)
bpos = [(Inches(0.45), Inches(1.42)),
(Inches(6.85), Inches(1.42)),
(Inches(0.45), Inches(4.0)),
(Inches(6.85), Inches(4.0))]
for (x, y), (btitle, bacc, bbullets) in zip(bpos, bio_data):
card(s11, x, y, cw2, ch2, btitle, bbullets,
title_size=14, bullet_size=13, accent=bacc)
# evidence note
rect(s11, Inches(0.45), Inches(6.62), Inches(12.45), Inches(0.55),
RGBColor(0xE8,0xF5,0xF3), TEAL_MED, 0.75)
tb(s11, Inches(0.6), Inches(6.65), Inches(12.2), Inches(0.48),
"Key Evidence: Chambrone et al. 2022 (J Periodontol, AAP Best Evidence Network Meta-analysis, PMID 36279123) | "
"Shanbhag et al. 2026 (J Periodontal Res, Histological Outcomes, PMID 41017258)",
size=12, color=TEAL_DARK)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 12 – TECHNIQUE COMPARISON TABLE
# ═══════════════════════════════════════════════════════════════════════════════
s12 = prs.slides.add_slide(blank)
bg(s12)
header_bar(s12, "Technique Comparison Summary",
"Quick reference — indication, coverage, difficulty, esthetics")
headers = ["Technique", "Indication", "Root\nCoverage", "Esthetics", "Difficulty", "Donor Site"]
col_ws3 = [Inches(2.8), Inches(2.9), Inches(1.3), Inches(1.35), Inches(1.55), Inches(1.6)]
col_xs3 = [Inches(0.3)]
for cw3 in col_ws3[:-1]:
col_xs3.append(col_xs3[-1] + cw3 + Inches(0.02))
h_y = Inches(1.42)
for ci, (cx, cw3, htext) in enumerate(zip(col_xs3, col_ws3, headers)):
rect(s12, cx, h_y, cw3, Inches(0.55), TEAL_DARK)
tb(s12, cx + Inches(0.06), h_y + Inches(0.04),
cw3 - Inches(0.1), Inches(0.47),
htext, size=13, bold=True, color=WHITE,
align=PP_ALIGN.CENTER, valign=MSO_ANCHOR.MIDDLE)
rows12 = [
["Laterally Positioned Flap", "Single recession + adequate adjacent gingiva", "++", "Good", "Moderate", "None"],
["Double Papilla Flap", "Isolated, narrow recession", "+", "Moderate", "Moderate", "None"],
["CAF alone", "RT1, adequate KT coronal to recession", "++", "Very Good", "Moderate", "None"],
["CAF + CTG (Gold Standard)", "RT1/RT2, single or multiple teeth", "+++", "Excellent", "High", "Palate"],
["Tunnel + CTG", "Multiple adjacent RT1/RT2 recessions", "+++", "Excellent", "Very High", "Palate"],
["Free Gingival Autograft", "Gingival augmentation (not root coverage)", "++", "Fair", "Moderate", "Palate"],
["Collagen Matrix (Mucograft)", "RT1, low morbidity preference", "++", "Good", "High", "None"],
["Frenectomy", "Aberrant frenum; diastema; denture instability","N/A", "Good", "Easy", "None"],
]
row_h12 = Inches(0.58)
accent_cols_r = [CORAL, CORAL, TEAL_MED, TEAL_DARK, TEAL_DARK,
CORAL_DARK, TEAL_MED, RGBColor(0x80,0x80,0x80)]
for ri, (row_data, ac) in enumerate(zip(rows12, accent_cols_r)):
ry = h_y + Inches(0.55) + ri * row_h12
bg_c = TEAL_LIGHT if ri % 2 == 0 else WHITE
rect(s12, Inches(0.3), ry, sum(col_ws3) + Inches(0.18), row_h12, bg_c, GRAY_LIGHT, 0.5)
for ci, (cx, cw3, cell_text) in enumerate(zip(col_xs3, col_ws3, row_data)):
bold_flag = (ci == 0)
fsz = 12.5 if ci == 0 else 12
col_c = TEAL_DARK if ci == 0 else (
CORAL_DARK if cell_text in ["+++", "Excellent", "Very High"] else
TEAL_DARK if cell_text in ["++", "Good", "Moderate", "High"] else
DARK_TEXT)
tb(s12, cx + Inches(0.06), ry + Inches(0.04),
cw3 - Inches(0.1), row_h12 - Inches(0.06),
cell_text, size=fsz, bold=bold_flag, color=col_c,
align=PP_ALIGN.CENTER if ci > 0 else PP_ALIGN.LEFT,
wrap=True, valign=MSO_ANCHOR.MIDDLE)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 13 – SUMMARY & RECOMMENDATIONS
# ═══════════════════════════════════════════════════════════════════════════════
s13 = prs.slides.add_slide(blank)
bg(s13)
header_bar(s13, "Summary & Evidence-Based Recommendations")
key_points = [
("1", "Classify before treating",
"Always classify recession using Miller (1985) or Cairo RT system before selecting a technique. Classification determines root coverage expectations.",
TEAL_DARK),
("2", "CAF + CTG = Gold Standard",
"For root coverage, CAF combined with subepithelial CTG achieves the highest rates of complete root coverage and best esthetic outcomes — supported by Cochrane reviews and AAP 2022 network meta-analysis.",
CORAL_DARK),
("3", "Multiple recessions → Tunnel",
"Tunnel technique + CTG is preferred for multiple adjacent recession defects — preserves papillae, reduces scarring, excellent esthetic outcome.",
TEAL_DARK),
("4", "RT3 (Miller IV) = Augmentation only",
"Advanced recession with interdental tissue loss cannot be fully covered. Goal shifts to increasing keratinized tissue using FGG or APF.",
CORAL_DARK),
("5", "Biologics as adjuncts",
"EMD, PRF, and collagen matrices improve outcomes or reduce morbidity. Collagen matrix is an effective alternative when patient declines palatal harvest.",
TEAL_DARK),
("6", "Patient factors matter",
"Smoking significantly reduces root coverage predictability. Oral hygiene must be optimized before surgery. Thin biotype = higher risk of re-recession.",
CORAL_DARK),
]
col_w6 = Inches(5.9)
top_y6 = Inches(1.42)
gap6 = Inches(1.85)
for i, (num, kp_title, kp_body, accent_c) in enumerate(key_points):
col6 = i % 2
row6 = i // 2
x6 = Inches(0.45) if col6 == 0 else Inches(6.9)
y6 = top_y6 + row6 * gap6
rrect(s13, x6, y6, col_w6, Inches(1.75), WHITE, GRAY_LIGHT, 0.75)
# accent left stripe
rect(s13, x6, y6, Inches(0.12), Inches(1.75), accent_c)
# number badge
nb2 = s13.shapes.add_shape(MSO_SHAPE.OVAL,
x6 + Inches(0.25), y6 + Inches(0.2),
Inches(0.45), Inches(0.45))
nb2.fill.solid(); nb2.fill.fore_color.rgb = accent_c
nb2.line.fill.background(); nb2.shadow.inherit = False
tf_nb2 = nb2.text_frame
tf_nb2.margin_left = tf_nb2.margin_right = tf_nb2.margin_top = tf_nb2.margin_bottom = 0
p_nb2 = tf_nb2.paragraphs[0]; p_nb2.alignment = PP_ALIGN.CENTER
r_nb2 = p_nb2.add_run(); r_nb2.text = num
r_nb2.font.name = "Calibri"; r_nb2.font.size = Pt(16)
r_nb2.font.bold = True; r_nb2.font.color.rgb = WHITE
# title
tb(s13, x6 + Inches(0.82), y6 + Inches(0.18), col_w6 - Inches(0.98),
Inches(0.42), kp_title, size=15, bold=True, color=accent_c,
valign=MSO_ANCHOR.MIDDLE)
# body
tb(s13, x6 + Inches(0.28), y6 + Inches(0.68), col_w6 - Inches(0.45),
Inches(1.0), kp_body, size=12.5, color=DARK_TEXT, wrap=True)
# ═══════════════════════════════════════════════════════════════════════════════
# SAVE
# ═══════════════════════════════════════════════════════════════════════════════
out_path = "/tmp/workspace/mucogingival-pptx/Mucogingival_Surgery_Technique_Selection.pptx"
buf = BytesIO()
prs.save(buf)
with open(out_path, "wb") as f:
f.write(buf.getvalue())
print(f"Saved: {out_path}")
print(f"Slides: {len(prs.slides)}")
cd /tmp/workspace/mucogingival-pptx && python build_pptx.py 2>&1
Mucogingival Surgery Technique Selection
Presentation · PPTX
| Slide | Content |
|---|---|
| 1 | Title slide |
| 2 | Overview / Agenda |
| 3 | Definition & Scope — traditional vs. expanded (AAP 1996) |
| 4 | Key Anatomy — MGJ, attached gingiva, clinical significance |
| 5 | Classification — Miller (1985) Class I-IV + Cairo (2011) RT1-RT3, side-by-side tables with color coding |
| 6 | Decision Framework — visual flowchart: classify → root coverage goal? → single/multiple → technique selection |
| 7 | Pedicle Soft Tissue Graft Procedures — LPF, Double Papilla, CAF, Semilunar flap |
| 8 | Free Soft Tissue Graft Procedures — FGG vs SCTG/CTG with gold standard callout |
| 9 | Tunnel Technique & Minimally Invasive Approaches — MCAT, LCT, VISTA |
| 10 | Gingival Augmentation & Frenectomy — APF, vestibuloplasty, Z-plasty |
| 11 | Biologics & Adjuncts — EMD, PRF, Mucograft, rhPDGF-BB with evidence citations |
| 12 | Technique Comparison Table — all procedures rated on coverage, esthetics, difficulty, donor site |
| 13 | Summary & 6 Evidence-Based Key Points |