"""Render the homepage's simple native tab symbols from editable vector geometry. Run with Python + Pillow. No external images or fonts are used. """ from pathlib import Path from PIL import Image, ImageDraw DEST = Path(__file__).resolve().parents[1] / 'src/static/tab' SIZE, SCALE = 81, 24 FACTOR = SIZE * 4 / SCALE def render(name, active): image = Image.new('RGBA', (SIZE * 4, SIZE * 4)) draw = ImageDraw.Draw(image) color = '#6b8276' if active else '#99948e' weight = round(1.35 * FACTOR) def box(coords): return tuple(round(value * FACTOR) for value in coords) def line(points, width=weight): points = [box(point) for point in points] draw.line(points, fill=color, width=width, joint='curve') r = width / 2 for x, y in (points[0], points[-1]): draw.ellipse((x-r, y-r, x+r, y+r), fill=color) if name == 'home': roof = [(3.8,10), (12,3.2), (20.2,10)] if active: draw.polygon([box(p) for p in roof + [(20.2,20.4),(14.6,20.4),(14.6,13.2),(9.4,13.2),(9.4,20.4),(3.8,20.4)]], fill=color) else: line(roof) line([(5.2,9.5),(5.2,20.4),(9.4,20.4),(9.4,13.2),(14.6,13.2),(14.6,20.4),(18.8,20.4),(18.8,9.5)]) elif name == 'booking': draw.rounded_rectangle(box((4.2,5.7,19.8,21)), radius=round(3*FACTOR), outline=color, width=weight) line([(4.5,10.5),(19.5,10.5)]) line([(8,3.2),(8,7.8)]) line([(16,3.2),(16,7.8)]) if active: line([(8.5,15.8),(11,18),(15.8,13.8)]) elif name == 'learn': draw.ellipse(box((3,3,21,21)), outline=color, width=weight) points = [(15.8,8.2),(13.7,13.7),(8.2,15.8),(10.3,10.3),(15.8,8.2)] if active: draw.polygon([box(p) for p in points], fill=color) else: line(points, round(1.1*FACTOR)) elif name == 'profile': draw.ellipse(box((8,2.8,16,10.8)), outline=color, width=weight) draw.rounded_rectangle(box((4.2,14,19.8,21.5)), radius=round(3.6*FACTOR), outline=color, width=weight) if active: draw.ellipse(box((9.2,4,14.8,9.6)), fill=color) image = image.resize((SIZE,SIZE), Image.Resampling.LANCZOS) image.save(DEST / f"{name}{'-active' if active else ''}.png", optimize=True) for name in ['home','booking','learn','profile']: for active in [False,True]: render(name,active) print('Rendered 8 tab icons, 81×81px, sage active / warm-gray inactive.')