#!/usr/bin/env python3
"""
Generate Complete Standalone Architectural PDF for 1:12 Scale Backyard Garden Tool Shed (6" x 8").
Workshop practice project on a single 2' x 4' plywood sheet.
"""

import os
from reportlab.lib.pagesizes import letter, landscape
from reportlab.lib import colors
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    Image as RLImage, PageBreak, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.pdfgen import canvas

PDF_FILENAME = "1-12_Scale_Small_Shed_Plans.pdf"
WORKSPACE_PDF = os.path.join(r"c:\code2026\house", PDF_FILENAME)
ARTIFACT_PDF = os.path.join(r"C:\Users\Hack\.gemini\antigravity\brain\be34cacd-367e-4ed7-819c-8f861ebb0996", PDF_FILENAME)
BLUEPRINT_IMG = os.path.join(r"c:\code2026\house\images", "shed_practice_cut_blueprint.png")

class ShedNumberedCanvas(canvas.Canvas):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._saved_page_states = []

    def showPage(self):
        self._saved_page_states.append(dict(self.__dict__))
        self._startPage()

    def save(self):
        num_pages = len(self._saved_page_states)
        for state in self._saved_page_states:
            self.__dict__.update(state)
            self.draw_page_decorations(num_pages)
            canvas.Canvas.showPage(self)
        canvas.Canvas.save(self)

    def draw_page_decorations(self, page_count):
        if self._pageNumber == 1:
            return  # Suppress running header/footer on cover page

        self.saveState()
        self.setFont("Helvetica-Bold", 8)
        self.setFillColor(colors.HexColor("#065f46")) # Dark Emerald
        
        # Running Header
        self.drawString(36, 582, "1:12 SCALE BACKYARD GARDEN TOOL SHED (6\" × 8\")")
        self.setFont("Helvetica", 8)
        self.setFillColor(colors.HexColor("#64748b"))
        self.drawRightString(756, 582, "WORKSHOP JOINERY PRACTICE & CALIBRATION GUIDE")
        
        self.setStrokeColor(colors.HexColor("#cbd5e1"))
        self.setLineWidth(0.75)
        self.line(36, 576, 756, 576)

        # Running Footer
        self.setStrokeColor(colors.HexColor("#cbd5e1"))
        self.setLineWidth(0.75)
        self.line(36, 40, 756, 40)

        self.setFont("Helvetica", 8)
        self.setFillColor(colors.HexColor("#64748b"))
        self.drawString(36, 28, "Size: 8\" W × 6\" D × 9-1/2\" H  |  Scale 1:12  |  Single 2' × 4' Sheet of 1/4\" Plywood  |  Joinery: 1/8\" Dados & Rabbets")
        
        page_str = f"Page {self._pageNumber} of {page_count}"
        self.setFont("Helvetica-Bold", 8)
        self.setFillColor(colors.HexColor("#065f46"))
        self.drawRightString(756, 28, page_str)
        self.restoreState()


def build_shed_pdf():
    doc = SimpleDocTemplate(
        WORKSPACE_PDF,
        pagesize=landscape(letter),
        leftMargin=36,
        rightMargin=36,
        topMargin=42,
        bottomMargin=46
    )

    PRIMARY = colors.HexColor("#064e3b")      # Deep Emerald 900
    SECONDARY = colors.HexColor("#0f766e")    # Teal 700
    BORDER_COL = colors.HexColor("#cbd5e1")   # Slate 300
    BG_LIGHT = colors.HexColor("#f8fafc")     # Slate 50
    TEXT_DARK = colors.HexColor("#0f172a")    # Slate 900
    TEXT_MUTED = colors.HexColor("#475569")   # Slate 600

    style_cover_title = ParagraphStyle(
        'CoverTitle',
        fontName='Helvetica-Bold',
        fontSize=28,
        leading=34,
        textColor=colors.HexColor("#ffffff"),
        alignment=1
    )
    style_cover_sub = ParagraphStyle(
        'CoverSub',
        fontName='Helvetica',
        fontSize=13,
        leading=18,
        textColor=colors.HexColor("#a7f3d0"),
        alignment=1
    )
    style_cover_badge = ParagraphStyle(
        'CoverBadge',
        fontName='Helvetica-Bold',
        fontSize=10,
        leading=14,
        textColor=colors.HexColor("#ffffff"),
        alignment=1
    )

    style_h1 = ParagraphStyle(
        'Heading1_Custom',
        fontName='Helvetica-Bold',
        fontSize=15,
        leading=19,
        textColor=PRIMARY,
        spaceBefore=12,
        spaceAfter=6,
        keepWithNext=True
    )
    style_h2 = ParagraphStyle(
        'Heading2_Custom',
        fontName='Helvetica-Bold',
        fontSize=11,
        leading=15,
        textColor=SECONDARY,
        spaceBefore=8,
        spaceAfter=3,
        keepWithNext=True
    )
    style_body = ParagraphStyle(
        'Body_Custom',
        fontName='Helvetica',
        fontSize=8.5,
        leading=12,
        textColor=TEXT_DARK,
        spaceAfter=5
    )
    style_body_bold = ParagraphStyle(
        'BodyBold_Custom',
        fontName='Helvetica-Bold',
        fontSize=8.5,
        leading=12,
        textColor=TEXT_DARK,
        spaceAfter=5
    )
    style_callout = ParagraphStyle(
        'Callout_Custom',
        fontName='Helvetica',
        fontSize=8,
        leading=11,
        textColor=TEXT_MUTED,
        spaceAfter=4
    )
    style_th = ParagraphStyle(
        'TableHeader',
        fontName='Helvetica-Bold',
        fontSize=8,
        leading=10,
        textColor=colors.white,
        alignment=1
    )
    style_td = ParagraphStyle(
        'TableCell',
        fontName='Helvetica',
        fontSize=7.5,
        leading=10,
        textColor=TEXT_DARK
    )
    style_td_center = ParagraphStyle(
        'TableCellCenter',
        fontName='Helvetica',
        fontSize=7.5,
        leading=10,
        textColor=TEXT_DARK,
        alignment=1
    )
    style_td_bold = ParagraphStyle(
        'TableCellBold',
        fontName='Helvetica-Bold',
        fontSize=7.5,
        leading=10,
        textColor=TEXT_DARK
    )

    story = []

    # =========================================================================
    # PAGE 1: COVER PAGE
    # =========================================================================
    story.append(Spacer(1, 15))
    cover_data = [
        [Paragraph("1:12 SCALE BACKYARD GARDEN TOOL SHED", style_cover_title)],
        [Spacer(1, 4)],
        [Paragraph("Workshop Practice Project  •  Tool Calibration & Joinery Manual  •  6\" × 8\" Structure", style_cover_sub)],
        [Spacer(1, 10)],
        [Paragraph("<b>CUT FROM A SINGLE 2' × 4' SHEET OF 1/4\" PLYWOOD  •  INCLUDES 32\" × 24\" CALIBRATION SCRAP</b>", style_cover_badge)],
    ]
    cover_table = Table(cover_data, colWidths=[720])
    cover_table.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), PRIMARY),
        ('ALIGN', (0,0), (-1,-1), 'CENTER'),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 18),
        ('BOTTOMPADDING', (0,0), (-1,-1), 18),
        ('LEFTPADDING', (0,0), (-1,-1), 20),
        ('RIGHTPADDING', (0,0), (-1,-1), 20),
    ]))
    story.append(cover_table)
    story.append(Spacer(1, 20))

    spec_cards = [
        [
            Paragraph("<b>PRACTICE SPECIFICATIONS</b>", style_body_bold),
            Paragraph("<b>SCALE & GEOMETRY</b>", style_body_bold),
            Paragraph("<b>STOCK TAKE-OFF</b>", style_body_bold),
            Paragraph("<b>TRAINING VALUE</b>", style_body_bold),
        ],
        [
            Paragraph("• <b>Type:</b> Garden Tool / Potting Shed<br/>• <b>Width:</b> 8.00\" (8 inches)<br/>• <b>Depth:</b> 6.00\" (6 inches)<br/>• <b>Eave Height:</b> 6.50\" (6-1/2 inches)<br/>• <b>Peak Height:</b> 9.50\" (9-1/2 inches)<br/>• <b>Pitch:</b> 45.0° (12/12 standard pitch)", style_body),
            Paragraph("• <b>Scale:</b> 1:12 (1\" = 1'0\" Real Life)<br/>• <b>Real-Life Size:</b> 8'0\" W × 6'0\" D × 9'6\" H<br/>• <b>Doorway:</b> 2-1/2\" W × 5-1/2\" H<br/>• <b>Window:</b> 2\" × 2\" Potting Window<br/>• <b>Bench:</b> 7-3/4\" × 2\" Sliding Shelf<br/>• <b>Overhangs:</b> 1/2\" Rafter Eaves", style_body),
            Paragraph("• <b>Sheet Size:</b> ONE (1) 2' × 4' (24\" × 48\")<br/>• <b>Thickness:</b> 1/4\" (0.250\") Plywood<br/>• <b>Shed Area:</b> 16\" × 24\" (Takes 1/3 of sheet)<br/>• <b>Test Scrap:</b> 32\" × 24\" (2/3 of sheet!)<br/>• <b>Joinery:</b> 1/8\" Dados & 1/4\" Rabbets<br/>• <b>Assembly:</b> PVA Wood Glue & Clamps", style_body),
            Paragraph("• <b>Zero Risk:</b> Low-stakes throwaway build<br/>• <b>Calibration:</b> Dial in 1/8\" blade height<br/>• <b>Dado Fit:</b> Practice two-pass 1/4\" channels<br/>• <b>Rabbeting:</b> Master sacrificial sub-fences<br/>• <b>Companion Model:</b> Sits on lawn plinth!<br/>• <b>Readiness:</b> 100% prepared for dollhouse", style_body),
        ]
    ]
    card_table = Table(spec_cards, colWidths=[180, 180, 180, 180])
    card_table.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), BG_LIGHT),
        ('BOX', (0,0), (-1,-1), 1, BORDER_COL),
        ('INNERGRID', (0,0), (-1,-1), 0.5, BORDER_COL),
        ('TOPPADDING', (0,0), (-1,-1), 8),
        ('BOTTOMPADDING', (0,0), (-1,-1), 8),
        ('LEFTPADDING', (0,0), (-1,-1), 10),
        ('RIGHTPADDING', (0,0), (-1,-1), 10),
    ]))
    story.append(card_table)
    story.append(Spacer(1, 20))

    meta_text = (
        "<b>DOCUMENTATION SET:</b> 1:12 Garden Shed Workshop Practice Plan  |  "
        "<b>MATERIAL:</b> Single 2' × 4' Sheet (1/4\" Plywood)  |  "
        "<b>DATE:</b> October 2026  |  "
        "<b>SYSTEM:</b> Google DeepMind Antigravity Advanced Agentic Coding"
    )
    story.append(Paragraph(meta_text, style_callout))
    story.append(PageBreak())

    # =========================================================================
    # PAGE 2: DIMENSIONS & 2x4 SHEET BREAKDOWN
    # =========================================================================
    story.append(Paragraph("1. Executive Dimensions & 2' × 4' Sheet Stock Breakdown", style_h1))
    story.append(Paragraph(
        "This project is mathematically scaled to represent an authentic 8 ft × 6 ft backyard tool shed at 1:12 scale. "
        "All shed components are nested into a <b>16\" × 24\" section</b> of your 2' × 4' sheet, leaving the remaining <b>32\" × 24\" section</b> "
        "as an enormous calibration board for risk-free test cuts.",
        style_body
    ))
    story.append(Spacer(1, 4))

    dim_headers = [
        Paragraph("Feature", style_th),
        Paragraph("Decimal", style_th),
        Paragraph("Ruler Fraction", style_th),
        Paragraph("1:12 Real Scale", style_th),
        Paragraph("Engineering & Shop Purpose", style_th),
    ]
    dim_rows = [
        dim_headers,
        [Paragraph("Overall Shed Width", style_td_bold), Paragraph("8.000\"", style_td_center), Paragraph("8\"", style_td_center), Paragraph("8 ft 0 in", style_td_center), Paragraph("Front Wall S3 and Floor Deck S1", style_td)],
        [Paragraph("Overall Shed Depth", style_td_bold), Paragraph("6.000\"", style_td_center), Paragraph("6\"", style_td_center), Paragraph("6 ft 0 in", style_td_center), Paragraph("Gable Walls S2-A & S2-B depth", style_td)],
        [Paragraph("Wall Eave Height", style_td_bold), Paragraph("6.500\"", style_td_center), Paragraph("6-1/2\"", style_td_center), Paragraph("6 ft 6 in", style_td_center), Paragraph("Baseline to eave line on all 4 walls", style_td)],
        [Paragraph("Gable Peak Rise", style_td_bold), Paragraph("3.000\"", style_td_center), Paragraph("3\"", style_td_center), Paragraph("3 ft 0 in", style_td_center), Paragraph("Rise above 6-1/2\" eave line to ridge", style_td)],
        [Paragraph("Total Ridge Height", style_td_bold), Paragraph("9.500\"", style_td_center), Paragraph("9-1/2\"", style_td_center), Paragraph("9 ft 6 in", style_td_center), Paragraph("Baseline to apex (6.50\" eave + 3.00\" rise)", style_td)],
        [Paragraph("Roof Pitch Angle", style_td_bold), Paragraph("45.000°", style_td_center), Paragraph("45°", style_td_center), Paragraph("12 / 12 Pitch", style_td_center), Paragraph("arctan(3.00\" rise / 3.00\" run) = 45.0°", style_td)],
        [Paragraph("Rafter Slope Run", style_td_bold), Paragraph("4.243\"", style_td_center), Paragraph("4-1/4\"", style_td_center), Paragraph("4 ft 3 in", style_td_center), Paragraph("True slope length across rafters", style_td)],
        [Paragraph("Roof Slope Panels (2)", style_td_bold), Paragraph("9.00\" × 4.75\"", style_td_center), Paragraph("9\" × 4-3/4\"", style_td_center), Paragraph("9 ft × 4 ft 9 in", style_td_center), Paragraph("Includes 1/2\" eave and side overhangs", style_td)],
        [Paragraph("Shed Door Opening", style_td_bold), Paragraph("2.50\" × 5.50\"", style_td_center), Paragraph("2-1/2\" × 5-1/2\"", style_td_center), Paragraph("2 ft 6 in × 5 ft 6 in", style_td_center), Paragraph("Flush with floor; left side of front wall", style_td)],
        [Paragraph("Shed Window Opening", style_td_bold), Paragraph("2.00\" × 2.00\"", style_td_center), Paragraph("2\" × 2\"", style_td_center), Paragraph("2 ft 0 in × 2 ft 0 in", style_td_center), Paragraph("Centered on right half of front wall", style_td)],
        [Paragraph("Potting Bench / Shelf", style_td_bold), Paragraph("7.75\" × 2.00\"", style_td_center), Paragraph("7-3/4\" × 2\"", style_td_center), Paragraph("7 ft 9 in × 2 ft 0 in", style_td_center), Paragraph("Slides into 1/8\" wall dados at Y = 2-1/2\"", style_td)],
        [Paragraph("Dado & Groove Depth", style_td_bold), Paragraph("0.125\"", style_td_center), Paragraph("1/8\"", style_td_center), Paragraph("1.5 in", style_td_center), Paragraph("Leaves 1/8\" core in 1/4\" plywood", style_td)],
        [Paragraph("Corner Rabbet Width", style_td_bold), Paragraph("0.250\"", style_td_center), Paragraph("1/4\"", style_td_center), Paragraph("3.0 in", style_td_center), Paragraph("Conceals raw front plywood edges", style_td)],
    ]
    t_dim = Table(dim_rows, colWidths=[120, 75, 75, 75, 375])
    t_dim.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), PRIMARY),
        ('BOX', (0,0), (-1,-1), 1, BORDER_COL),
        ('INNERGRID', (0,0), (-1,-1), 0.5, BORDER_COL),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.white, BG_LIGHT]),
        ('TOPPADDING', (0,0), (-1,-1), 2.5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 2.5),
        ('LEFTPADDING', (0,0), (-1,-1), 5),
        ('RIGHTPADDING', (0,0), (-1,-1), 5),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ]))
    story.append(t_dim)
    story.append(Spacer(1, 10))

    story.append(Paragraph("<b>2' × 4' Plywood Sheet Cut Allocation:</b>", style_h2))
    alloc_data = [
        [Paragraph("Sheet Section", style_th), Paragraph("Dimensions", style_th), Paragraph("Components Included", style_th), Paragraph("Workshop Purpose", style_th)],
        [Paragraph("<b>Section A</b> (Shed Parts)", style_td_bold), Paragraph("16\" × 24\" (16.00\" × 24.00\")", style_td_center), Paragraph("S1 (Floor Deck), S2-A & S2-B (Gables), S3 (Front), S4 (Shelf), S5-A & S5-B (Roof)", style_td), Paragraph("Contains 100% of all finished shed components.", style_td)],
        [Paragraph("<b>Section B</b> (Test Scrap)", style_td_bold), Paragraph("32\" × 24\" (32.00\" × 24.00\")", style_td_center), Paragraph("Large untouched test-cut reservoir", style_td), Paragraph("Used for the 4 pre-flight calibration drills below.", style_td)],
    ]
    t_alloc = Table(alloc_data, colWidths=[120, 130, 260, 210])
    t_alloc.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), SECONDARY),
        ('BOX', (0,0), (-1,-1), 1, BORDER_COL),
        ('INNERGRID', (0,0), (-1,-1), 0.5, BORDER_COL),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.white, BG_LIGHT]),
        ('TOPPADDING', (0,0), (-1,-1), 3),
        ('BOTTOMPADDING', (0,0), (-1,-1), 3),
        ('LEFTPADDING', (0,0), (-1,-1), 5),
        ('RIGHTPADDING', (0,0), (-1,-1), 5),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ]))
    story.append(t_alloc)
    story.append(PageBreak())

    # =========================================================================
    # PAGE 3: 4 PRE-FLIGHT CALIBRATION DRILLS
    # =========================================================================
    story.append(Paragraph("2. The 4 Pre-Flight Machine Calibration Drills", style_h1))
    story.append(Paragraph(
        "<b>The Golden Rule of Miniature Joinery:</b> NEVER cut your project panels until your scrap test joints slide together smoothly and stand square on their own! "
        "Cut a 6\" × 12\" board from Section B and perform these 4 calibration drills:",
        style_body
    ))
    story.append(Spacer(1, 4))

    drills_data = [
        [Paragraph("Drill # & Name", style_th), Paragraph("Tooling Setup", style_th), Paragraph("Execution Procedure", style_th), Paragraph("Pass/Fail Acceptance Criteria", style_th)],
        [
            Paragraph("<b>Drill 1: Dial in 1/8\" (0.125\") Blade Depth</b>", style_td_bold),
            Paragraph("Table Saw or Router Table. 1/8\" brass setup gauge or steel ruler.", style_td),
            Paragraph("1. Unplug tool. Set blade/bit height to 1/8\" above table surface.<br/>2. Lock arbor/collet. Run 4\" test cut across scrap board.", style_td),
            Paragraph("<b>PASS:</b> Leaves exactly 1/8\" core plywood thickness below groove.<br/><b>FAIL:</b> If >1/8\", weakens panel; if <1/8\", panel bottoms out.", style_td)
        ],
        [
            Paragraph("<b>Drill 2: Two-Pass 1/4\" (0.250\") Dado Width</b>", style_td_bold),
            Paragraph("Table saw with standard 1/8\" blade (or 1/4\" spiral router bit).", style_td),
            Paragraph("1. Pass 1: Cut test groove at Fence = F.<br/>2. Pass 2: Nudge fence over by ~1/8\" (blade kerf).<br/>3. Test-fit offcut of actual 1/4\" plywood into groove.", style_td),
            Paragraph("<b>PASS (Thumb Pressure Rule):</b> Panel slides in smoothly with light thumb pressure and <b>stands upright on its own at 90°</b> without wobbling or falling!", style_td)
        ],
        [
            Paragraph("<b>Drill 3: 1/4\" W × 1/8\" D Edge Rabbet</b>", style_td_bold),
            Paragraph("Auxiliary 3/4\" sacrificial wooden fence clamped to rip fence.", style_td),
            Paragraph("1. Set blade height to 1/8\".<br/>2. Slide fence over until blade teeth bury slightly into wood, leaving exactly 1/4\" exposed.<br/>3. Feed scrap with push block.", style_td),
            Paragraph("<b>PASS:</b> Yields crisp, flat 1/4\" W × 1/8\" D shoulder in a single pass. Conceals raw front plywood edges completely!", style_td)
        ],
        [
            Paragraph("<b>Drill 4: Window / Door Plunge Cuts</b>", style_td_bold),
            Paragraph("Cordless drill with 3/8\" brad point bit + scroll saw / jigsaw.", style_td),
            Paragraph("1. Mark opening with sharp 0.5mm pencil.<br/>2. Drill pilot holes inside two diagonal waste corners.<br/>3. Cut 1/16\" inside line; file flat to pencil line.", style_td),
            Paragraph("<b>PASS:</b> Clean, square 90° inside corners with zero tearout on face veneer.", style_td)
        ],
    ]
    t_drills = Table(drills_data, colWidths=[120, 140, 240, 220])
    t_drills.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), PRIMARY),
        ('BOX', (0,0), (-1,-1), 1, BORDER_COL),
        ('INNERGRID', (0,0), (-1,-1), 0.5, BORDER_COL),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.white, BG_LIGHT]),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('RIGHTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ]))
    story.append(t_drills)
    story.append(PageBreak())

    # =========================================================================
    # PAGE 4: FULL-PAGE BLUEPRINT DRAWING
    # =========================================================================
    story.append(Paragraph("3. Workshop Blueprint: 1:12 Scale Backyard Garden Tool Shed (6\" × 8\")", style_h1))
    story.append(Paragraph("Full architectural cut sheet and machining details for Parts S1 through S5, including calibration drills.", style_callout))
    story.append(Spacer(1, 4))

    if os.path.exists(BLUEPRINT_IMG):
        img_rl = RLImage(BLUEPRINT_IMG, width=690, height=440)
        story.append(img_rl)
    story.append(PageBreak())

    # =========================================================================
    # PAGE 5: PART SCHEDULE & 6-PHASE BUILD FLOW
    # =========================================================================
    story.append(Paragraph("4. Itemized Component Cut List & 6-Phase Construction Order", style_h1))
    story.append(Paragraph(
        "Complete component schedule and step-by-step assembly sequence for the garden tool shed. "
        "All parts cut from Section A (16\" × 24\") of your 2' × 4' panel.",
        style_body
    ))
    story.append(Spacer(1, 4))

    cut_headers = [
        Paragraph("Part ID", style_th),
        Paragraph("Part Name", style_th),
        Paragraph("Qty", style_th),
        Paragraph("Ruler Dimensions", style_th),
        Paragraph("Decimal", style_th),
        Paragraph("Machining Operations & Practice Notes", style_th),
    ]
    cut_rows = [
        cut_headers,
        [Paragraph("<b>S1</b>", style_td_bold), Paragraph("Floor Deck", style_td), Paragraph("1", style_td_center), Paragraph("8\" Wide × 6\" Deep", style_td_center), Paragraph("8.00\" × 6.00\"", style_td_center), Paragraph("Route 1/4\" W × 1/8\" D end rabbets on left/right ends; test dado at center (X=4\")", style_td)],
        [Paragraph("<b>S2-A</b>", style_td_bold), Paragraph("Left Gable Wall", style_td), Paragraph("1", style_td_center), Paragraph("6\" Wide × 9-1/2\" Height", style_td_center), Paragraph("6.00\" × 9.50\"", style_td_center), Paragraph("6-1/2\" eave + 3\" peak (45° pitch); 1/4\" front corner rabbet; bottom deck dado (Y=0); shelf dado (Y=2-1/2\")", style_td)],
        [Paragraph("<b>S2-B</b>", style_td_bold), Paragraph("Right Gable Wall", style_td), Paragraph("1", style_td_center), Paragraph("6\" Wide × 9-1/2\" Height", style_td_center), Paragraph("6.00\" × 9.50\"", style_td_center), Paragraph("Mirror of S2-A; shelf dado at Y = 2-1/2\"", style_td)],
        [Paragraph("<b>S3</b>", style_td_bold), Paragraph("Front Wall", style_td), Paragraph("1", style_td_center), Paragraph("8\" Wide × 6-1/2\" Height", style_td_center), Paragraph("8.00\" × 6.50\"", style_td_center), Paragraph("Pierced cutouts for Shed Door (2-1/2\" W × 5-1/2\" H) and Window (2\" × 2\")", style_td)],
        [Paragraph("<b>S4</b>", style_td_bold), Paragraph("Potting Bench / Shelf", style_td), Paragraph("1", style_td_center), Paragraph("7-3/4\" Wide × 2\" Deep", style_td_center), Paragraph("7.75\" × 2.00\"", style_td_center), Paragraph("Interior workbench; slides into 1/8\" dados on gable walls at Y = 2-1/2\"", style_td)],
        [Paragraph("<b>S5-A</b>", style_td_bold), Paragraph("Front Roof Slope", style_td), Paragraph("1", style_td_center), Paragraph("9\" Wide × 4-3/4\" Slope", style_td_center), Paragraph("9.00\" × 4.75\"", style_td_center), Paragraph("45° slope; provides 1/2\" overhang all around", style_td)],
        [Paragraph("<b>S5-B</b>", style_td_bold), Paragraph("Rear Roof Slope", style_td), Paragraph("1", style_td_center), Paragraph("9\" Wide × 4-3/4\" Slope", style_td_center), Paragraph("9.00\" × 4.75\"", style_td_center), Paragraph("Matching slope (solid roof or open back for interior access)", style_td)],
    ]
    t_cuts = Table(cut_rows, colWidths=[45, 110, 25, 110, 85, 345])
    t_cuts.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), PRIMARY),
        ('BOX', (0,0), (-1,-1), 1, BORDER_COL),
        ('INNERGRID', (0,0), (-1,-1), 0.5, BORDER_COL),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.white, BG_LIGHT]),
        ('TOPPADDING', (0,0), (-1,-1), 2.5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 2.5),
        ('LEFTPADDING', (0,0), (-1,-1), 4),
        ('RIGHTPADDING', (0,0), (-1,-1), 4),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ]))
    story.append(t_cuts)
    story.append(Spacer(1, 8))

    story.append(Paragraph("<b>Master 6-Phase Build Flow:</b>", style_h2))
    flow_data = [
        [Paragraph("Phase", style_th), Paragraph("Title", style_th), Paragraph("Step-by-Step Workshop Assembly Instructions", style_th)],
        [Paragraph("<b>Phase 1</b>", style_td_center), Paragraph("<b>Blanks Breakdown</b>", style_td_bold), Paragraph("Cut 7 rectangular blanks on table saw. Mark 3\" peak on gables S2-A/S2-B (eave at Y=6.5\", peak at Y=9.5\"); cut 45° angles cleanly.", style_td)],
        [Paragraph("<b>Phase 2</b>", style_td_center), Paragraph("<b>Bench Dados & Rabbets</b>", style_td_bold), Paragraph("Cut 1/4\" W × 1/8\" D vertical corner rabbets on front edges of S2-A/B. Cut bottom deck dados (Y=0) and potting bench dados (Y=2-1/2\"). Cut end rabbets on Floor Deck S1.", style_td)],
        [Paragraph("<b>Phase 3</b>", style_td_center), Paragraph("<b>Door & Window Piercing</b>", style_td_bold), Paragraph("On Front Wall S3, mark 2-1/2\" × 5-1/2\" door and 2\" × 2\" window. Drill pilot holes, cut out with scroll saw / jigsaw, and sand edges square.", style_td)],
        [Paragraph("<b>Phase 4</b>", style_td_center), Paragraph("<b>Carcass Assembly</b>", style_td_bold), Paragraph("Dry-fit S1, S2-A, S2-B, and S3. Apply PVA wood glue into bottom dados and front corner rabbets. Clamp square (diagonal = 10.00\").", style_td)],
        [Paragraph("<b>Phase 5</b>", style_td_center), Paragraph("<b>Potting Bench Slide-In</b>", style_td_bold), Paragraph("Apply glue into side shelf dados at Y = 2-1/2\". Slide potting bench S4 in from open rear. It locks the two walls together with immense strength!", style_td)],
        [Paragraph("<b>Phase 6</b>", style_td_center), Paragraph("<b>Roof Installation</b>", style_td_bold), Paragraph("Glue Roof Slopes S5-A and S5-B across gables with 1/2\" overhangs. Optional: Frame door with rustic wood battens and miniature latch.", style_td)],
    ]
    t_flow = Table(flow_data, colWidths=[55, 120, 545])
    t_flow.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), SECONDARY),
        ('BOX', (0,0), (-1,-1), 1, BORDER_COL),
        ('INNERGRID', (0,0), (-1,-1), 0.5, BORDER_COL),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.white, BG_LIGHT]),
        ('TOPPADDING', (0,0), (-1,-1), 2.5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 2.5),
        ('LEFTPADDING', (0,0), (-1,-1), 5),
        ('RIGHTPADDING', (0,0), (-1,-1), 5),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ]))
    story.append(t_flow)

    doc.build(story, canvasmaker=ShedNumberedCanvas)
    print(f"Shed Practice PDF built successfully: {WORKSPACE_PDF}")

    if os.path.exists(WORKSPACE_PDF):
        import shutil
        shutil.copyfile(WORKSPACE_PDF, ARTIFACT_PDF)
        print(f"Copied to Artifact directory: {ARTIFACT_PDF}")

if __name__ == "__main__":
    build_shed_pdf()
