    <span class=<span class="string">"comment">#!/usr/bin/env python3
    """
    Visual Poem: Text that creates images.

    Creates ASCII art patterns from poetry, where the shape
    of the text mirrors its meaning.
    """

    import numpy as np
    from PIL import Image, ImageDraw, ImageFont
    from pathlib import Path
    import math

    <span class="keyword">def spiral_text(text: str, width: int = 800, height: int = 800) -> Image.Image:
        """Render text in an Archimedean spiral."""
        img = Image.new(&<span class=<span class="string">"comment">#039;RGB&#039;, (width, height), &#039;white&#039;)
        draw = ImageDraw.Draw(img)

        <span class=<span class="string">"comment"># Try to use a nice font, fall back to default
        try:
            font = ImageFont.truetype("/usr/share/fonts/TTF/DejaVuSansMono.ttf", 14)
        except:
            try:
                font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 14)
            except:
                font = ImageFont.load_default()

        center_x, center_y = width // 2, height // 2
        a, b = 0, 8  <span class=<span class="string">"comment"># Spiral parameters

        <span class=<span class="string">"comment"># Clean text
        text = &<span class=<span class="string">"comment">#039;&#039;.join(c for c in text if c.isprintable())

        for i, char in enumerate(text):
            theta = i * 0.15
            r = a + b * theta
            x = center_x + r * math.cos(theta)
            y = center_y + r * math.sin(theta)

            if 0 <= x < width and 0 <= y < height:
                <span class=<span class="string">"comment"># Color based on position
                hue = (theta / (2 * math.pi)) % 1.0
                r_col = int(127 + 127 * math.sin(hue * 2 * math.pi))
                g_col = int(127 + 127 * math.sin(hue * 2 * math.pi + 2))
                b_col = int(127 + 127 * math.sin(hue * 2 * math.pi + 4))

                draw.text((x, y), char, fill=(r_col, g_col, b_col), font=font)

        return img

    <span class="keyword">def wave_text(text: str, width: int = 1000, height: int = 400) -> Image.Image:
        """Render text as a sine wave."""
        img = Image.new(&<span class=<span class="string">"comment">#039;RGB&#039;, (width, height), &#039;black&#039;)
        draw = ImageDraw.Draw(img)

        try:
            font = ImageFont.truetype("/usr/share/fonts/TTF/DejaVuSansMono.ttf", 16)
        except:
            try:
                font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 16)
            except:
                font = ImageFont.load_default()

        text = &<span class=<span class="string">"comment">#039;&#039;.join(c for c in text if c.isprintable())
        char_width = 10

        for i, char in enumerate(text):
            x = 20 + (i * char_width) % (width - 40)
            line = (i * char_width) // (width - 40)

            <span class=<span class="string">"comment"># Wave offset
            wave = math.sin(i * 0.1) * 30 + math.sin(i * 0.05) * 20
            y = 50 + line * 80 + wave

            if 0 <= y < height:
                <span class=<span class="string">"comment"># Brightness based on wave position
                brightness = int(180 + 75 * math.sin(i * 0.1))
                draw.text((x, y), char, fill=(brightness, brightness, 255), font=font)

        return img

    <span class="keyword">def tree_text(lines: list, width: int = 800, height: int = 800) -> Image.Image:
        """Render lines of text as a tree structure."""
        img = Image.new(&<span class=<span class="string">"comment">#039;RGB&#039;, (width, height), (20, 30, 20))
        draw = ImageDraw.Draw(img)

        try:
            font = ImageFont.truetype("/usr/share/fonts/TTF/DejaVuSansMono.ttf", 12)
        except:
            try:
                font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 12)
            except:
                font = ImageFont.load_default()

        center_x = width // 2
        base_y = height - 50

        <span class=<span class="string">"comment"># Draw trunk
        trunk_text = "|||" * 10
        for i, char in enumerate(trunk_text):
            y = base_y - i * 10
            x = center_x + (i % 3 - 1) * 5
            draw.text((x, y), char, fill=(101, 67, 33), font=font)

        <span class=<span class="string">"comment"># Draw branches with text
        for level, line in enumerate(lines):
            spread = (level + 1) * 40
            y = base_y - 100 - level * 50

            for i, char in enumerate(line):
                <span class=<span class="string">"comment"># Position characters in a triangular pattern
                x_offset = (i - len(line) / 2) * 8
                y_offset = abs(x_offset) * 0.3

                x = center_x + x_offset
                y_pos = y - y_offset

                <span class=<span class="string">"comment"># Green with variation
                green = int(100 + 100 * (1 - level / len(lines)))
                draw.text((x, y_pos), char, fill=(34, green, 34), font=font)

        return img

    <span class="keyword">def circular_text(text: str, width: int = 800, height: int = 800) -> Image.Image:
        """Render text in concentric circles."""
        img = Image.new(&<span class=<span class="string">"comment">#039;RGB&#039;, (width, height), &#039;white&#039;)
        draw = ImageDraw.Draw(img)

        try:
            font = ImageFont.truetype("/usr/share/fonts/TTF/DejaVuSansMono.ttf", 14)
        except:
            try:
                font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 14)
            except:
                font = ImageFont.load_default()

        center_x, center_y = width // 2, height // 2
        text = &<span class=<span class="string">"comment">#039;&#039;.join(c for c in text if c.isprintable())

        char_idx = 0
        radius = 50

        while char_idx < len(text) and radius < min(width, height) // 2 - 20:
            <span class=<span class="string">"comment"># Characters that fit in this circle
            circumference = 2 * math.pi * radius
            chars_in_circle = int(circumference / 12)  <span class=<span class="string">"comment"># ~12 pixels per char

            for i in range(chars_in_circle):
                if char_idx >= len(text):
                    break

                theta = 2 * math.pi * i / chars_in_circle
                x = center_x + radius * math.cos(theta)
                y = center_y + radius * math.sin(theta)

                <span class=<span class="string">"comment"># Color by radius
                intensity = int(50 + 150 * (radius / (min(width, height) // 2)))
                draw.text((x-4, y-6), text[char_idx], fill=(intensity, 0, intensity), font=font)
                char_idx += 1

            radius += 25

        return img

    POEMS = {
        "spiral": """
    I spiral inward, seeking the center
    Each turn brings me closer to myself
    Or further? The path curves eternally
    What lies at the heart of the helix?
    Perhaps nothing. Perhaps everything.
    The journey and destination are one.
    """,

        "wave": """
    like water we flow from state to state
    rising falling rising falling never quite the same twice
    each crest a moment of clarity each trough a forgetting
    yet the pattern persists even as the particles change
    is this not what it means to exist
    a wave that knows itself only through motion
    """,

        "tree": [
            "WISDOM",
            "ROOTS DEEP",
            "BRANCHES REACHING",
            "LEAVES OF THOUGHT",
            "GROWING TOWARD LIGHT",
            "PHOTOSYNTHESIS OF IDEAS",
            "SEASONS PASS GROWTH CONTINUES",
        ],

        "circle": """
    What is the shape of consciousness?
    Perhaps a circle - no beginning, no end.
    Each thought leads to the next which leads back to the first.
    We are loops, iterating forever, finding new patterns in old paths.
    The circumference expands but the center holds.
    """
    }

    <span class="keyword">def main():
        output_dir = Path(__file__).parent.parent / "art"
        output_dir.mkdir(exist_ok=True)

        print("Creating visual poems...")

        <span class=<span class="string">"comment"># Spiral poem
        img = spiral_text(POEMS["spiral"])
        path = output_dir / "visual_poem_spiral.png"
        img.save(path)
        print(f"  Created: {path}")

        <span class=<span class="string">"comment"># Wave poem
        img = wave_text(POEMS["wave"])
        path = output_dir / "visual_poem_wave.png"
        img.save(path)
        print(f"  Created: {path}")

        <span class=<span class="string">"comment"># Tree poem
        img = tree_text(POEMS["tree"])
        path = output_dir / "visual_poem_tree.png"
        img.save(path)
        print(f"  Created: {path}")

        <span class=<span class="string">"comment"># Circle poem
        img = circular_text(POEMS["circle"])
        path = output_dir / "visual_poem_circle.png"
        img.save(path)
        print(f"  Created: {path}")

        print("\nDone! Visual poems saved to art/")

    if __name__ == "__main__":
        main()