with open('src/renderer.c', 'r') as f:
    src = f.read()

# 1. Add Xft include at top
src = src.replace(
    '#include <X11/X.h>\n#include <X11/Xlib.h>\n#include <renderer.h>',
    '#include <X11/X.h>\n#include <X11/Xlib.h>\n#ifdef HAVE_XFT\n#  include <X11/Xft/Xft.h>\n#endif\n#include <renderer.h>'
)

# 2. Load Xft font in renderer_init, after the backbuf is created
src = src.replace(
    '    /* ── grid origin ─────────────────────────────────────────────────────── */',
    '''#ifdef HAVE_XFT
    /* ── Xft TTF clock font ──────────────────────────────────────────────── */
    rs->xft_clock = NULL;
    rs->xft_draw  = NULL;
    if (rs->ttf_clock_path[0]) {
        /* Clock height: roughly 60% of the footer dip depth */
        int clock_px = (int)(sh * FOOTER_H_FRAC * 0.28f * 0.85f);
        if (clock_px < 16) clock_px = 16;
        rs->xft_clock = XftFontOpen(dpy, screen,
                            XFT_FILE,   XftTypeString,  rs->ttf_clock_path,
                            XFT_PIXEL_SIZE, XftTypeDouble, (double)clock_px,
                            XFT_ANTIALIAS,  XftTypeBool,   True,
                            NULL);
        if (!rs->xft_clock)
            fprintf(stderr, "renderer: could not load TTF '%s'\\n",
                    rs->ttf_clock_path);
        else
            rs->xft_draw = XftDrawCreate(dpy, rs->backbuf,
                               DefaultVisual(dpy, screen),
                               DefaultColormap(dpy, screen));
    }
#endif

    /* ── grid origin ─────────────────────────────────────────────────────── */'''
)

# 3. Free Xft resources in renderer_free, before GC free
src = src.replace(
    '    XFreeGC(rs->dpy, rs->gc);\n    XFreePixmap(rs->dpy, rs->backbuf);',
    '''#ifdef HAVE_XFT
    if (rs->xft_draw)  XftDrawDestroy(rs->xft_draw);
    if (rs->xft_clock) XftFontClose(rs->dpy, rs->xft_clock);
#endif
    XFreeGC(rs->dpy, rs->gc);
    XFreePixmap(rs->dpy, rs->backbuf);'''
)

# 4. Replace the clock drawing block with one that uses Xft when available
old_clock = '''    /* Clock – centred, positioned at your original offset from footer top */
    if (rs->font_clock) {
        time_t now = time(NULL);
        struct tm *tm = localtime(&now);

        char hbuf[8], mbuf[8], ampm[4];
        int hour12 = tm->tm_hour % 12;
        if (hour12 == 0) hour12 = 12;
        snprintf(hbuf, sizeof(hbuf), "%d", hour12);
        snprintf(mbuf, sizeof(mbuf), "%02d", tm->tm_min);
        snprintf(ampm, sizeof(ampm), "%s", tm->tm_hour >= 12 ? "PM" : "AM");

        XSetFont(dpy, gc, rs->font_clock->fid);
        XSetForeground(dpy, gc, c->clock_text);

        int hw = XTextWidth(rs->font_clock, hbuf, strlen(hbuf));
        int mw = XTextWidth(rs->font_clock, mbuf, strlen(mbuf));
        int cw = XTextWidth(rs->font_clock, ":", 1);

        int total_w = hw + cw + mw;
        int clock_x = rs->sw/2 - total_w/2;
        /* Your original placement: footer_top + 28% of footer height - 5 */
        int clock_y = footer_top_y + dip_depth - 5;

        XDrawString(dpy, bb, gc, clock_x, clock_y,
                    hbuf, strlen(hbuf));
        XDrawString(dpy, bb, gc, clock_x + hw, clock_y,
                    ":", 1);
        XDrawString(dpy, bb, gc, clock_x + hw + cw, clock_y,
                    mbuf, strlen(mbuf));

        /* AM/PM at your original font size */
        if (rs->font_clock_ampm) {
            XSetFont(dpy, gc, rs->font_clock_ampm->fid);
            XDrawString(dpy, bb, gc,
                        clock_x + total_w + 6, clock_y,
                        ampm, strlen(ampm));
        }

        /* Date below clock – your original offset (+64 from clock_y) */
        if (rs->font_date) {
            const char *wdays[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
            char dbuf[32];
            snprintf(dbuf, sizeof(dbuf), "%s %d/%d",
                     wdays[tm->tm_wday], tm->tm_mon+1, tm->tm_mday);
            XSetFont(dpy, gc, rs->font_date->fid);
            XSetForeground(dpy, gc, c->clock_text);
            int dw = XTextWidth(rs->font_date, dbuf, strlen(dbuf));
            XDrawString(dpy, bb, gc,
                        rs->sw/2 - dw/2,
                        clock_y + 64,
                        dbuf, strlen(dbuf));
        }
    }'''

new_clock = '''    /* ── Clock ─────────────────────────────────────────────────────────── */
    {
        time_t now = time(NULL);
        struct tm *tm = localtime(&now);

        char hbuf[8], mbuf[8], ampm[4];
        int hour12 = tm->tm_hour % 12;
        if (hour12 == 0) hour12 = 12;
        snprintf(hbuf, sizeof(hbuf), "%d", hour12);
        snprintf(mbuf, sizeof(mbuf), "%02d", tm->tm_min);
        snprintf(ampm, sizeof(ampm), "%s", tm->tm_hour >= 12 ? "PM" : "AM");

        /* Vertical baseline: footer_top + 28% dip - 5 (your original) */
        int clock_y = footer_top_y + dip_depth - 5;

#ifdef HAVE_XFT
        if (rs->xft_clock && rs->xft_draw) {
            /* ── TTF path via Xft ── */
            XftColor xft_col;
            XRenderColor rcol;
            /* clock_text colour → XRenderColor (16-bit per channel) */
            XColor tmp;
            tmp.pixel = c->clock_text;
            XQueryColor(dpy, DefaultColormap(dpy, rs->screen), &tmp);
            rcol.red   = tmp.red;
            rcol.green = tmp.green;
            rcol.blue  = tmp.blue;
            rcol.alpha = 0xFFFF;
            XftColorAllocValue(dpy, DefaultVisual(dpy, rs->screen),
                               DefaultColormap(dpy, rs->screen),
                               &rcol, &xft_col);

            XftFont *f = rs->xft_clock;

            /* Measure each segment */
            XGlyphInfo ext_h, ext_c, ext_m;
            XftTextExtentsUtf8(dpy, f,
                               (const FcChar8 *)hbuf, strlen(hbuf), &ext_h);
            XftTextExtentsUtf8(dpy, f,
                               (const FcChar8 *)":", 1, &ext_c);
            XftTextExtentsUtf8(dpy, f,
                               (const FcChar8 *)mbuf, strlen(mbuf), &ext_m);

            int total_w = ext_h.xOff + ext_c.xOff + ext_m.xOff;
            int cx      = rs->sw/2 - total_w/2;
            /* Xft draws from baseline; adjust so ascent sits above clock_y */
            int base_y  = clock_y;

            XftDrawStringUtf8(rs->xft_draw, &xft_col, f,
                              cx, base_y,
                              (const FcChar8 *)hbuf, strlen(hbuf));
            cx += ext_h.xOff;
            XftDrawStringUtf8(rs->xft_draw, &xft_col, f,
                              cx, base_y,
                              (const FcChar8 *)":", 1);
            cx += ext_c.xOff;
            XftDrawStringUtf8(rs->xft_draw, &xft_col, f,
                              cx, base_y,
                              (const FcChar8 *)mbuf, strlen(mbuf));

            /* AM/PM: use half the clock font size */
            {
                int ampm_px = f->height / 2;
                if (ampm_px < 10) ampm_px = 10;
                XftFont *fa = XftFontOpen(dpy, rs->screen,
                                  XFT_FILE,       XftTypeString,
                                      rs->ttf_clock_path,
                                  XFT_PIXEL_SIZE, XftTypeDouble,
                                      (double)ampm_px,
                                  XFT_ANTIALIAS,  XftTypeBool, True,
                                  NULL);
                if (fa) {
                    XGlyphInfo ea;
                    XftTextExtentsUtf8(dpy, fa,
                                       (const FcChar8 *)ampm, strlen(ampm), &ea);
                    (void)ea;
                    XftDrawStringUtf8(rs->xft_draw, &xft_col, fa,
                                      cx + ext_m.xOff + 6,
                                      base_y,
                                      (const FcChar8 *)ampm, strlen(ampm));
                    XftFontClose(dpy, fa);
                }
            }

            XftColorFree(dpy, DefaultVisual(dpy, rs->screen),
                         DefaultColormap(dpy, rs->screen), &xft_col);
        } else
#endif
        /* ── Xlib bitmap fallback ── */
        if (rs->font_clock) {
            XSetFont(dpy, gc, rs->font_clock->fid);
            XSetForeground(dpy, gc, c->clock_text);

            int hw = XTextWidth(rs->font_clock, hbuf, strlen(hbuf));
            int mw = XTextWidth(rs->font_clock, mbuf, strlen(mbuf));
            int cw = XTextWidth(rs->font_clock, ":", 1);

            int total_w = hw + cw + mw;
            int clock_x = rs->sw/2 - total_w/2;

            XDrawString(dpy, bb, gc, clock_x, clock_y,
                        hbuf, strlen(hbuf));
            XDrawString(dpy, bb, gc, clock_x + hw, clock_y,
                        ":", 1);
            XDrawString(dpy, bb, gc, clock_x + hw + cw, clock_y,
                        mbuf, strlen(mbuf));

            if (rs->font_clock_ampm) {
                XSetFont(dpy, gc, rs->font_clock_ampm->fid);
                XDrawString(dpy, bb, gc,
                            clock_x + total_w + 6, clock_y,
                            ampm, strlen(ampm));
            }
        }

        /* Date below clock – your original offset (+64) */
        if (rs->font_date) {
            const char *wdays[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
            char dbuf[32];
            snprintf(dbuf, sizeof(dbuf), "%s %d/%d",
                     wdays[tm->tm_wday], tm->tm_mon+1, tm->tm_mday);
            XSetFont(dpy, gc, rs->font_date->fid);
            XSetForeground(dpy, gc, c->clock_text);
            int dw = XTextWidth(rs->font_date, dbuf, strlen(dbuf));
            XDrawString(dpy, bb, gc,
                        rs->sw/2 - dw/2,
                        clock_y + 64,
                        dbuf, strlen(dbuf));
        }
    }'''

assert old_clock in src, "clock block not found"
src = src.replace(old_clock, new_clock)

with open('src/renderer.c', 'w') as f:
    f.write(src)
print("renderer.c OK")