#!/usr/bin/env python3
"""Check that every text label fits inside its parent box.
JetBrains Mono advance width at N px ~ 0.60 * N (empirical for this font).
"""

# Each parent box inner text area: (xmin, xmax, y_top, y_bottom, name)
boxes = {
    "user":     (30,   130,  430,  480),
    "cli":      (170,  305,  400,  510),
    "kernel":   (340,  530,  90,   470),
    "sqlite":   (570,  700,  90,   145),
    "ws":       (570,  700,  260,  470),
    "compiler": (770,  1020, 90,   670),
    "types":    (430,  850,  770,  830),
    "claude":   (1080, 1190, 420,  475),
}

# Text labels as (parent_box, x_anchor, y, font_size, text_anchor, text)
# Only need middle/start anchored ones that might overflow
labels = [
    # CLI
    ("cli", 237, 422, 12, "middle", "@ico/cli"),
    ("cli", 237, 436, 9,  "middle", "Commander · bin: ico"),
    ("cli", 237, 459, 8,  "middle", "init · mount · ingest"),
    ("cli", 237, 471, 8,  "middle", "compile · ask · render"),
    ("cli", 237, 483, 8,  "middle", "research · promote"),
    ("cli", 237, 495, 8,  "middle", "lint · inspect · eval"),
    # Kernel — longest lines
    ("kernel", 356, 156, 9, "start", "• workspace / state"),
    ("kernel", 356, 188, 9, "start", "• tasks (state machine)"),
    ("kernel", 356, 204, 9, "start", "• provenance / traces"),
    ("kernel", 356, 236, 9, "start", "• wiki-index · FTS5"),
    ("kernel", 356, 252, 9, "start", "• promotion / unpromote"),
    ("kernel", 356, 284, 9, "start", "• logger / config / procfs"),
    ("kernel", 356, 334, 8, "start", "• SHA-256 chained traces"),
    ("kernel", 356, 404, 8, "start", "• 3 anti-pattern detectors"),
    # Compiler — longest lines
    ("compiler", 788, 258, 8, "start", "• orchestrator (5-stage FSM)"),
    ("compiler", 788, 432, 8, "start", "• web-clip (turndown)"),
    ("compiler", 788, 502, 8, "start", "• analyze · generate · verify"),
    ("compiler", 788, 560, 8, "start", "• task-renderer · artifact-meta"),
    ("compiler", 788, 606, 8, "start", "• api/claude-client (injected)"),
    ("compiler", 788, 618, 8, "start", "• ingest-pipeline · token-tracker"),
    # WS
    ("ws", 635, 444, 8, "middle", "provenance demands"),
    # Types
    ("types", 640, 823, 8, "middle", "implicitly imported by @ico/cli · @ico/kernel · @ico/compiler (workspace:* deps)"),
]

def advance(text, font_px):
    return len(text) * font_px * 0.60

def rendered_x_extent(x_anchor, text, font_px, anchor_mode):
    w = advance(text, font_px)
    if anchor_mode == "middle":
        return (x_anchor - w/2, x_anchor + w/2)
    if anchor_mode == "end":
        return (x_anchor - w, x_anchor)
    return (x_anchor, x_anchor + w)  # start

PAD = 4  # pixels of desired margin from box edge
print("="*78)
print(f"  TEXT OVERFLOW CHECK  (inner margin: {PAD}px)")
print("="*78)
issues = 0
for box, x, y, fs, anchor, text in labels:
    bxmin, bxmax, _, _ = boxes[box]
    txmin, txmax = rendered_x_extent(x, text, fs, anchor)
    if txmin < bxmin + PAD:
        print(f"  LEFT    {box:<8} {fs}px '{text[:30]}...' extends to x={txmin:.0f} (box left={bxmin}+{PAD})")
        issues += 1
    if txmax > bxmax - PAD:
        over = txmax - (bxmax - PAD)
        print(f"  RIGHT   {box:<8} {fs}px '{text[:50]}' extends to x={txmax:.0f} (box right={bxmax}-{PAD}, over by {over:.0f}px)")
        issues += 1
print(f"\n  {issues} overflow issue(s)" if issues else "  clean — all checked labels fit inside their parent boxes")
