diff --git a/lib/xmet/spc.py b/lib/xmet/spc.py
index 4cad492..47ec1a4 100644
--- a/lib/xmet/spc.py
+++ b/lib/xmet/spc.py
@@ -2,9 +2,11 @@ import re
 import enum
 import shapely
 import datetime
+import cairo
 
 from xmet.db    import DatabaseTable
 from xmet.coord import COORD_SYSTEM
+from xmet.map   import EquirectMap, MAP_SCREEN_DIMENSIONS, MAP_BOUNDS
 from xmet.afos  import MONTHS, TIMEZONES
 
 from pyiem.nws.products._outlook_util import (
@@ -114,7 +116,7 @@ def each_poly(parts: list[str]):
     polygons, interiors, linestrings = convert_segments(segments)
 
     #
-    # we do our winding logic now
+    # We do our winding logic now
     #
     polygons.extend(winding_logic(linestrings))
 
@@ -123,10 +125,12 @@ def each_poly(parts: list[str]):
     #
     for interior in interiors:
         for i, polygon in enumerate(polygons):
-            if not polygon.intersection(interior).is_empty:
-                current = list(polygon.interiors)
-                current.append(interior)
-                polygons[i] = shapely.Polygon(polygon.exterior, current)
+            if polygon.intersection(interior).is_empty:
+                continue
+
+            current = list(polygon.interiors)
+            current.append(interior)
+            polygons[i] = shapely.Polygon(polygon.exterior, current)
 
     #
     # Buffer zero any invalid polygons
@@ -165,6 +169,9 @@ class SPCOutlookArea(DatabaseTable):
         self.outlook_id = None
         self.poly       = None
 
+    def sort_value(self):
+        raise NotImplementedError
+
 class SPCOutlookProbabilityArea(SPCOutlookArea):
     __slots__ = (
         'hazard', 'probability', 'sig',
@@ -177,6 +184,12 @@ class SPCOutlookProbabilityArea(SPCOutlookArea):
         'id', 'outlook_id', 'hazard', 'probability', 'sig', 'poly'
     )
 
+    def sort_value(self):
+        if self.probability == 'SIGN':
+            return 1.0
+
+        return float(self.probability)
+
 class SPCOutlookCategoryArea(SPCOutlookArea):
     __slots__ = (
         'category'
@@ -189,6 +202,18 @@ class SPCOutlookCategoryArea(SPCOutlookArea):
         'id', 'outlook_id', 'category', 'poly'
     )
 
+    __category_levels__ = {
+        'TSTM': 0,
+        'MRGL': 1,
+        'SLGT': 2,
+        'ENH':  3,
+        'MDT':  4,
+        'HIGH': 5
+    }
+
+    def sort_value(self):
+        return self.__category_levels__[self.category]
+
 class SPCOutlook():
     __slots__ = (
         'id', 'timestamp_issued', 'timestamp_start', 'timestamp_end', 'day',
@@ -216,6 +241,12 @@ class SPCOutlook():
         self.probabilities = list()
         self.categories    = list()
 
+    def sorted_probabilities(self) -> list[SPCOutlookProbabilityArea]:
+        return sorted(self.probabilities, key=lambda p: p.sort_value())
+
+    def sorted_categories(self) -> list[SPCOutlookCategoryArea]:
+        return sorted(self.categories, key=lambda p: p.sort_value())
+
 class SPCOutlookParserState(enum.Enum):
     HEADER      = 1
     OFFICE      = enum.auto()
@@ -455,3 +486,66 @@ class SPCOutlookParser():
                 self.parse_body(line)
 
         return self.outlook
+
+class SPCOutlookMap(EquirectMap):
+    TEXT_FONT = 'Muli'
+
+    LOGO_RATIO  = 75.0 / 275.0
+    LOGO_WIDTH  = 360
+    LOGO_HEIGHT = LOGO_RATIO * LOGO_WIDTH
+    LOGO_MARGIN = 16
+
+    __category_colors__ = {
+        'TSTM': (212, 240, 213),
+        'MRGL': ( 80, 201, 134),
+        'SLGT': (255, 255,  81),
+        'ENH':  (255, 192, 108),
+        'MDT':  (255,  80,  80),
+        'HIGH': (255,  80, 255)
+    }
+
+    def __init__(self):
+        super().__init__(*MAP_SCREEN_DIMENSIONS, MAP_BOUNDS)
+
+    def draw_logo(self, cr: cairo.Context, path: str):
+        width  = self.LOGO_WIDTH
+        height = self.LOGO_HEIGHT
+        margin = self.LOGO_MARGIN
+
+        x = margin
+        y = self.height - height - margin
+
+        self.draw_from_file(cr, path, x, y, width, height)
+
+    def draw_annotation(self, cr: cairo.Context, text: str):
+        cr.select_font_face('Muli')
+        cr.set_font_size(28)
+
+        extents = cr.text_extents(text)
+
+        cr.move_to(self.width  - extents.width  - 48,
+                   self.height - extents.height - 16)
+
+        cr.show_text(text)
+
+    def draw_categories(self,
+                        cr: cairo.Context,
+                        outlook: SPCOutlook):
+        cr.save()
+
+        for category in outlook.sorted_categories():
+            color = self.__category_colors__[category.category]
+
+            r = color[0] / 255.0
+            g = color[1] / 255.0
+            b = color[2] / 255.0
+
+            cr.set_source_rgba(r, g, b, 0.35)
+            self.draw_polygon(cr, category.poly)
+            cr.fill()
+
+            cr.set_source_rgba(r*0.75, g*0.75, b*0.75, 0.8)
+            self.draw_polygon(cr, category.poly)
+            cr.stroke()
+
+        cr.restore()