diff --git a/src/component.rs b/src/component.rs
index f7a1b46d277d4650c443e92631f5e09ed5c21b10..5dfb4bb76406604feec6bd004522c8162c73b4ca 100644
--- a/src/component.rs
+++ b/src/component.rs
@@ -1 +1,2 @@
+pub mod code;
 pub mod grid;
diff --git a/src/component/code.rs b/src/component/code.rs
new file mode 100644
index 0000000000000000000000000000000000000000..bea7172485e82c75efc7688dc68142c58c5cfde0
--- /dev/null
+++ b/src/component/code.rs
@@ -0,0 +1,48 @@
+use eframe::egui::{Align2, Color32, Context, Vec2, Window};
+
+#[derive(Clone)]
+pub struct Code {
+    /// Must be unique.
+    pub name: &'static str,
+    /// Horizontal offset from middle.
+    pub offset_x: f32,
+    /// Vertical offset from middle.
+    pub offset_y: f32,
+    /// How tall and wide.
+    pub size_pixels: f32,
+    /// Background color. Transparent disables background.
+    pub background: Color32,
+    /// Code.
+    pub code: String,
+}
+
+impl Default for Code {
+    fn default() -> Self {
+        Self {
+            name: "grid",
+            offset_x: 0.0,
+            offset_y: 0.0,
+            size_pixels: 400.0,
+            background: Color32::from_rgb(230, 230, 230),
+            code: String::from(r#"println!("Hello world!");"#),
+        }
+    }
+}
+
+impl Code {
+    /// Render to UI.
+    pub fn show(&self, ctx: &Context) {
+        Window::new(self.name)
+            .title_bar(false)
+            //.frame(Frame::none())
+            .anchor(
+                Align2::CENTER_CENTER,
+                Vec2::new(self.offset_x, self.offset_y),
+            )
+            .fixed_size(Vec2::splat(self.size_pixels))
+            .show(ctx, |ui| {
+                //let (_id, _rect) = ui.allocate_space(Vec2::splat(self.size_pixels));
+                ui.code_editor(&mut self.code.as_str());
+            });
+    }
+}
diff --git a/src/component/grid.rs b/src/component/grid.rs
index 229157e5c2c7db9f8787e112d0272a4c3ab13b74..fe1144e57d3e16ae0db74cbb23584c52baae7b0f 100644
--- a/src/component/grid.rs
+++ b/src/component/grid.rs
@@ -1,19 +1,26 @@
-use eframe::egui::{
-    Align2, Color32, Context, Pos2, Rect, Rounding, Shape, Stroke, Ui, Vec2, Window,
-};
+use eframe::egui::{Align2, Color32, Context, Pos2, Rect, Rounding, Shape, Stroke, Vec2, Window};
 use eframe::emath;
 use eframe::epaint::RectShape;
 
 #[derive(Clone)]
 pub struct Grid {
+    /// Must be unique.
     pub name: &'static str,
+    /// Horizontal offset from middle.
     pub offset_x: f32,
+    /// Vertical offset from middle.
     pub offset_y: f32,
+    /// How many rows and columns.
     pub size_cells: usize,
+    /// How tall and wide.
     pub size_pixels: f32,
+    /// Stroke color. Transparent disables stroke.
     pub stroke: Color32,
+    /// Stroke width. Zero disables stroke.
     pub stroke_width: f32,
+    /// Background color. Transparent disables background.
     pub background: Color32,
+    /// Fill color of each pixel (use getters and setters).
     fill: Vec<Color32>,
 }
 
@@ -34,12 +41,14 @@ impl Default for Grid {
 }
 
 impl Grid {
+    /// X and y coordinate of a cell to its index in [`self.fill`].
     fn index(&self, x: usize, y: usize) -> usize {
         assert!(x < self.size_cells);
         assert!(y < self.size_cells);
         x + y * self.size_cells
     }
 
+    /// Gets the fill color at a cell, which defaults to transparent.
     pub fn fill(&self, x: usize, y: usize) -> Color32 {
         self.fill
             .get(self.index(x, y))
@@ -47,28 +56,56 @@ impl Grid {
             .unwrap_or(Color32::TRANSPARENT)
     }
 
-    pub fn set_fill(&mut self, x: usize, y: usize, fill: Color32) {
+    /// Gets mutable reference to the fill color at a cell, which defaults to transparent.
+    pub fn fill_mut(&mut self, x: usize, y: usize) -> &mut Color32 {
         let idx = self.index(x, y);
         loop {
             match self.fill.get_mut(idx) {
-                Some(f) => {
-                    *f = fill;
-                    return;
+                // TODO: Fix lifetime issue.
+                Some(_) => break,
+                None => {
+                    self.fill.push(Color32::TRANSPARENT);
                 }
-                None => self.fill.push(Color32::TRANSPARENT),
             }
         }
+        self.fill.get_mut(idx).unwrap()
     }
 
+    /// Sets the fill color at a cell.
+    pub fn set_fill(&mut self, x: usize, y: usize, fill: Color32) {
+        *self.fill_mut(x, y) = fill;
+    }
+
+    /// Reset all cell fill colors to transparent.
     pub fn clear_fill(&mut self) {
         self.fill.clear();
     }
 
+    pub fn iter(&self) -> impl Iterator<Item = (usize, usize, Color32)> + '_ {
+        (0..self.size_cells)
+            .flat_map(move |x| (0..self.size_cells).map(move |y| (x, y, self.fill(x, y))))
+    }
+
+    pub fn iter_mut(&mut self) -> impl Iterator<Item = (usize, usize, &mut Color32)> + '_ {
+        // Ensure fill is populated.
+        self.fill_mut(self.size_cells - 1, self.size_cells - 1);
+
+        self.fill
+            .iter_mut()
+            .take(self.size_cells.pow(2))
+            .enumerate()
+            .map(|(i, c)| (i % self.size_cells, i / self.size_cells, c))
+    }
+
+    /// Render to UI.
     pub fn show(&self, ctx: &Context) {
         Window::new(self.name)
             .title_bar(false)
             //.frame(Frame::none())
-            .anchor(Align2::CENTER_CENTER, Vec2::ZERO)
+            .anchor(
+                Align2::CENTER_CENTER,
+                Vec2::new(self.offset_x, self.offset_y),
+            )
             .fixed_size(Vec2::splat(self.size_pixels))
             .show(ctx, |ui| {
                 let (_id, rect) = ui.allocate_space(Vec2::splat(self.size_pixels));
@@ -93,10 +130,11 @@ impl Grid {
                         if let Some(fill) = self.fill.get(idx) {
                             if fill.a() > 0 {
                                 let x_coord = x as f32 / self.size_cells as f32;
+                                const TOLERANCE: f32 = 0.001;
                                 ui.painter().add(Shape::Rect(RectShape::filled(
                                     to_screen.transform_rect(Rect::from_x_y_ranges(
-                                        x_coord..=x_coord + cell_width,
-                                        y_coord..=y_coord + cell_width,
+                                        x_coord - TOLERANCE..=x_coord + cell_width + TOLERANCE,
+                                        y_coord - TOLERANCE..=y_coord + cell_width + TOLERANCE,
                                     )),
                                     Rounding::none(),
                                     *fill,
diff --git a/src/main.rs b/src/main.rs
index e37c8908ebb7ba53c498d75ae89da5825cd0cb23..f30a73b3c55e5f8cc67d4e7c1c6f160c4d578854 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,15 +9,13 @@ pub mod slide;
 use crate::slide::s1_title::Title;
 use crate::slide::s2_introduction::Introduction;
 use crate::slide::s3_complexity::Complexity;
-use crate::slide::s4_conway::Conway;
+use crate::slide::s4_automata::Automata;
+use crate::slide::s5_fractals::Fractals;
 use crate::slide::Slide;
-use eframe::egui::style::{Margin, Widgets};
-use eframe::egui::{
-    Align, Direction, FontFamily, Key, Layout, Pos2, Rect, Style, TextStyle, Vec2, Visuals,
-};
+use eframe::egui::style::Margin;
+use eframe::egui::{Key, Style, TextStyle, Visuals};
 use eframe::epi::{Frame, Storage};
 use eframe::{egui, epi};
-use std::collections::VecDeque;
 
 fn main() {
     let app = Cartoon::default();
@@ -60,7 +58,8 @@ fn create_slides() -> Vec<Box<dyn Slide>> {
         Box::new(Title::default()) as Box<dyn Slide>,
         Box::new(Introduction::default()),
         Box::new(Complexity::default()),
-        Box::new(Conway::default()),
+        Box::new(Automata::default()),
+        Box::new(Fractals::default()),
     ]
 }
 
@@ -90,7 +89,7 @@ impl epi::App for Cartoon {
     }
 
     /// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
-    fn update(&mut self, ctx: &egui::Context, frame: &epi::Frame) {
+    fn update(&mut self, ctx: &egui::Context, _frame: &epi::Frame) {
         // For inspiration and more examples, go to https://emilk.github.io/egui
 
         /*
diff --git a/src/slide.rs b/src/slide.rs
index de7d7f2f8fc37cacce6cf76e3c2ae8916d03f815..a3620978bbac48ed6100f396863ecb97c8faff22 100644
--- a/src/slide.rs
+++ b/src/slide.rs
@@ -1,16 +1,16 @@
 use eframe::egui::{Context, Ui};
-use eframe::{egui, epi};
 
 pub mod s1_title;
 pub mod s2_introduction;
 pub mod s3_complexity;
-pub mod s4_conway;
+pub mod s4_automata;
+pub mod s5_fractals;
 
 pub trait Slide {
     fn show(&mut self, ui: &mut Ui, ctx: &Context);
     /// Returns whether "done."
     /// Repaint automatically requested.
-    fn transition(&mut self, ctx: &Context) -> bool {
+    fn transition(&mut self, _ctx: &Context) -> bool {
         true
     }
 }
diff --git a/src/slide/s1_title.rs b/src/slide/s1_title.rs
index 90f7cd2c017388369bbb7ffd34b9e1f121f8553f..a6a2375db5277e818ddcc58e1278f24b21e27546 100644
--- a/src/slide/s1_title.rs
+++ b/src/slide/s1_title.rs
@@ -1,8 +1,7 @@
 use crate::egui::{Align2, Context};
 use crate::{ctx_img, img, Margin, Slide};
 use eframe::egui;
-use eframe::egui::{Align, Color32, Frame, Layout, ScrollArea, Style, Ui, Vec2, Window};
-use rand::Rng;
+use eframe::egui::{Frame, Ui, Vec2, Window};
 
 #[derive(Default)]
 pub struct Title {
diff --git a/src/slide/s2_introduction.rs b/src/slide/s2_introduction.rs
index ca13b1139a429422850fdfcaae378022678ac1cc..56753da9e8d910a0bc0613a412bddbd352d48c73 100644
--- a/src/slide/s2_introduction.rs
+++ b/src/slide/s2_introduction.rs
@@ -1,6 +1,5 @@
 use crate::{Margin, Slide};
 use eframe::egui::{Context, Frame, Ui};
-use eframe::{egui, epi};
 
 #[derive(Default)]
 pub struct Introduction {
@@ -8,7 +7,7 @@ pub struct Introduction {
 }
 
 impl Slide for Introduction {
-    fn transition(&mut self, ctx: &Context) -> bool {
+    fn transition(&mut self, _ctx: &Context) -> bool {
         let done = self.strengths;
         self.strengths = true;
         done
diff --git a/src/slide/s3_complexity.rs b/src/slide/s3_complexity.rs
index 9886bd0df577d0fa8b739e39a1c68d991ca7a6e2..c208e48a9e70c15e8a57463a1750014f516a605b 100644
--- a/src/slide/s3_complexity.rs
+++ b/src/slide/s3_complexity.rs
@@ -1,9 +1,8 @@
 use crate::egui::{Context, Ui, Window};
-use crate::{Key, Slide};
-use eframe::egui::text_edit::{CCursorRange, CursorRange, TextEditState};
-use eframe::egui::{Align, Align2, Frame, Layout, TextEdit, Vec2};
-use eframe::epaint::text::cursor::{CCursor, Cursor};
-use std::ops::RangeInclusive;
+use crate::Slide;
+use eframe::egui::text_edit::{CCursorRange, TextEditState};
+use eframe::egui::{Align2, Frame, TextEdit, Vec2};
+use eframe::epaint::text::cursor::CCursor;
 
 #[derive(Default)]
 pub struct Complexity {
@@ -21,7 +20,7 @@ enum ComplexityState {
 }
 
 impl Slide for Complexity {
-    fn transition(&mut self, ctx: &Context) -> bool {
+    fn transition(&mut self, _ctx: &Context) -> bool {
         if self.state == ComplexityState::Before {
             self.state = ComplexityState::Selecting(0);
             false
@@ -30,7 +29,7 @@ impl Slide for Complexity {
         }
     }
 
-    fn show(&mut self, ui: &mut Ui, ctx: &Context) {
+    fn show(&mut self, _ui: &mut Ui, ctx: &Context) {
         Window::new("complexity")
             .title_bar(false)
             .resizable(false)
diff --git a/src/slide/s4_conway.rs b/src/slide/s4_automata.rs
similarity index 90%
rename from src/slide/s4_conway.rs
rename to src/slide/s4_automata.rs
index 2e2babcef23c0c0ccfecbf1c11e8c622e4502a09..67b625cc48ecd0c295a6a01f36d831cae612594d 100644
--- a/src/slide/s4_conway.rs
+++ b/src/slide/s4_automata.rs
@@ -2,19 +2,18 @@ use crate::component::grid::Grid;
 use crate::governor::Governor;
 use crate::Slide;
 use eframe::egui::style::Margin;
-use eframe::egui::{Align2, Color32, Context, Frame, Pos2, Rect, Shape, Stroke, Ui, Vec2, Window};
-use eframe::emath;
+use eframe::egui::{Color32, Context, Frame, Ui};
 use rand::Rng;
 
-pub struct Conway {
+pub struct Automata {
     life: Grid,
     governor: Governor,
 }
 
-impl Default for Conway {
+impl Default for Automata {
     fn default() -> Self {
         let mut life = Grid::default();
-
+        life.name = "life";
         for y in 0..life.size_cells {
             for x in 0..life.size_cells {
                 if rand::thread_rng().gen_bool(0.5) {
@@ -37,7 +36,7 @@ impl Default for Conway {
     }
 }
 
-impl Slide for Conway {
+impl Slide for Automata {
     fn show(&mut self, ui: &mut Ui, ctx: &Context) {
         Frame::none().margin(Margin::same(20.0)).show(ui, |ui| {
             ui.vertical_centered(|ui| {
@@ -47,13 +46,13 @@ impl Slide for Conway {
 
         ctx.request_repaint();
         if self.governor.ready(ctx.input().time, 0.2) {
-            self.life = conway(&self.life);
+            self.life = conways_game_of_life(&self.life);
         }
         self.life.show(ctx);
     }
 }
 
-fn conway(grid: &Grid) -> Grid {
+fn conways_game_of_life(grid: &Grid) -> Grid {
     let mut new = grid.clone();
     new.clear_fill();
 
diff --git a/src/slide/s5_fractals.rs b/src/slide/s5_fractals.rs
new file mode 100644
index 0000000000000000000000000000000000000000..5535ac8703a49996b2933981089b2f04f1272dc7
--- /dev/null
+++ b/src/slide/s5_fractals.rs
@@ -0,0 +1,100 @@
+use crate::component::code::Code;
+use crate::component::grid::Grid;
+use crate::egui::{Color32, Context, Frame, Ui};
+use crate::Slide;
+use eframe::egui::style::Margin;
+
+pub struct Fractals {
+    code: Code,
+    grid: Grid,
+}
+
+impl Default for Fractals {
+    fn default() -> Self {
+        const HORIZONTAL_OFFSET: f32 = 275.0;
+
+        let mut code = Code::default();
+
+        code.code = String::from(
+            r###"
+fn mandelbrot(x0, y0) -> color {
+    MAX := 512
+    x := 0.0;
+    y := 0.0;
+    i := 0;
+
+    while x^2 + y^2 <= 4 and i < MAX {
+        x_temp := x^2 - y^2 + x0
+        y = 2.0 * x * y + y0
+        x = x_temp
+        i += 1
+    }
+
+    if i == MAX {
+        return black;
+    } else {
+        return white;
+    }
+}
+"###,
+        );
+
+        code.offset_x = -HORIZONTAL_OFFSET;
+
+        let mut grid = Grid::default();
+
+        const RESOLUTION: usize = 256;
+
+        grid.name = "fractal";
+        grid.size_cells = RESOLUTION;
+        grid.stroke_width = 0.0;
+        grid.offset_x = HORIZONTAL_OFFSET;
+
+        for (gx, gy, c) in grid.iter_mut() {
+            // 0 to 1.
+            let nx = (gx as f32 + 0.5) / RESOLUTION as f32;
+            let ny = (gy as f32 + 0.5) / RESOLUTION as f32;
+
+            // -4 to 4.
+            let x = nx * 4.0 - 2.0;
+            let y = ny * 4.0 - 2.0;
+
+            *c = if mandelbrot(x, y) {
+                Color32::BLACK
+            } else {
+                Color32::TRANSPARENT
+            };
+        }
+
+        Self { code, grid }
+    }
+}
+
+impl Slide for Fractals {
+    fn show(&mut self, ui: &mut Ui, ctx: &Context) {
+        Frame::none().margin(Margin::same(20.0)).show(ui, |ui| {
+            ui.vertical_centered(|ui| {
+                ui.heading("Fractals");
+            });
+        });
+
+        self.code.show(ctx);
+        self.grid.show(ctx);
+    }
+}
+
+fn mandelbrot(x0: f32, y0: f32) -> bool {
+    const MAX_ITERATIONS: usize = 512;
+
+    let mut x = 0f32;
+    let mut y = 0f32;
+    let mut i = 0usize;
+    while x.powi(2) + y.powi(2) <= 2f32.powi(2) && i < MAX_ITERATIONS {
+        let x_tmp = x.powi(2) - y.powi(2) + x0;
+        y = 2.0 * x * y + y0;
+        x = x_tmp;
+        i += 1;
+    }
+
+    i == MAX_ITERATIONS
+}