"""
AAhead Shell — Design Tokens ("Ink" palette).

Single source of truth for every visual constant in the discovery shell.
Mirrors the Ink tokens in the Claude Design handoff (near-black neutral so
cover art stays true-color; the chrome recedes, the art is the hero).

API-compatible with port/gui/design/tokens.py (Twilight) so the shared
primitives (render/fonts/icons) work unchanged — only the values differ.
The accent triad (rose/cyan/peach) is IDENTICAL across both palettes, so
the rose→cyan focus signature is shared.

Coordinate system: native pygame, top-left origin (0, 0).
Color format: (r, g, b) or (r, g, b, a) ints 0–255.
"""

from __future__ import annotations

from dataclasses import dataclass


# ─── helpers ──────────────────────────────────────────────────────────


def hex_rgb(value: str) -> tuple[int, int, int]:
    v = value.lstrip("#")
    return (int(v[0:2], 16), int(v[2:4], 16), int(v[4:6], 16))


def with_alpha(rgb: tuple[int, int, int], alpha: float) -> tuple[int, int, int, int]:
    return (rgb[0], rgb[1], rgb[2], max(0, min(255, int(alpha * 255))))


# ─── viewport ────────────────────────────────────────────────────────


VIEWPORT_WIDTH = 640
VIEWPORT_HEIGHT = 480
ASPECT_RATIO = VIEWPORT_WIDTH / VIEWPORT_HEIGHT


# ─── color tokens — "Ink" (neutral, content-forward) ─────────────────


class Color:
    # base — near-black canvas so covers are true-color
    BG_DEEP = hex_rgb("#0B0C0E")       # canvas base
    BG_MID = hex_rgb("#0E1013")        # between base and elevated
    BG_UP = hex_rgb("#131519")         # elevated background

    # surfaces
    SURFACE_BASE = hex_rgb("#16181C")
    SURFACE_ELEVATED = hex_rgb("#20242B")  # focus / hover surface
    SURFACE_GLASS = hex_rgb("#16181C")     # glass tint base, paired w/ alpha

    # borders
    BORDER_SOFT = hex_rgb("#24272E")
    BORDER_BRIGHT = hex_rgb("#33373F")

    # text
    TEXT_PRIMARY = hex_rgb("#F4F6FA")
    TEXT_SECONDARY = hex_rgb("#AAB1BD")
    TEXT_MUTED = hex_rgb("#6B7280")
    TEXT_DISABLED = hex_rgb("#444A53")

    # signature accent triad — used together as brand identity
    ACCENT_ROSE = hex_rgb("#E89FD3")       # focus primary
    ACCENT_CYAN = hex_rgb("#7DCEDD")       # status / progress
    ACCENT_PEACH = hex_rgb("#F5C19B")      # highlight / warning

    # status colors — muted, never bright/saturated
    SUCCESS = hex_rgb("#93D9B2")
    WARNING = hex_rgb("#F5C19B")
    ERROR = hex_rgb("#E89090")             # dusty rose, never red
    INFO = hex_rgb("#7DCEDD")


# ─── typography ──────────────────────────────────────────────────────


SPACE_GROTESK_BOLD = "SpaceGrotesk-Bold.ttf"
SPACE_GROTESK_SEMIBOLD = "SpaceGrotesk-SemiBold.ttf"
INTER_REGULAR = "Inter-Regular.ttf"
INTER_MEDIUM = "Inter-Medium.ttf"
INTER_SEMIBOLD = "Inter-SemiBold.ttf"
JETBRAINS_MONO = "JetBrainsMono-Regular.ttf"


@dataclass(frozen=True)
class TextStyle:
    font: str
    size: int
    weight: str = ""        # informational; embodied in font filename
    tracking: float = 0.0   # additional letter-spacing in px


class Type:
    # ── display / titles (Space Grotesk) — v3 scale (+1 step, ≥12px) ──
    HERO = TextStyle(SPACE_GROTESK_BOLD, 34, "Bold", -0.8)        # home hero title
    HERO_LIB = TextStyle(SPACE_GROTESK_BOLD, 32, "Bold", -0.7)    # library featured
    HERO_CARD = TextStyle(SPACE_GROTESK_BOLD, 30, "Bold", -0.7)   # game-card title
    DISPLAY = TextStyle(SPACE_GROTESK_BOLD, 22, "Bold", -0.5)
    TITLE = TextStyle(SPACE_GROTESK_SEMIBOLD, 20, "SemiBold", -0.3)
    ROW_TITLE = TextStyle(SPACE_GROTESK_SEMIBOLD, 16, "SemiBold", -0.2)  # rail / section
    SECTION = TextStyle(SPACE_GROTESK_SEMIBOLD, 14, "SemiBold", -0.2)
    OVERLAY_NAME = TextStyle(SPACE_GROTESK_BOLD, 15, "Bold", -0.2)   # focused-tile name
    OVERLAY_NAME_SM = TextStyle(SPACE_GROTESK_BOLD, 14, "Bold", -0.2)

    # ── body / UI (Inter) ──
    BODY = TextStyle(INTER_REGULAR, 15, "Regular", 0.0)
    BODY_STRONG = TextStyle(INTER_MEDIUM, 15, "Medium", 0.0)
    CLERK = TextStyle(INTER_REGULAR, 15, "Regular", 0.0)          # clerk quote/desc
    CLERK_STRONG = TextStyle(INTER_MEDIUM, 15, "Medium", 0.0)     # emphasis in quote
    CAPTION = TextStyle(INTER_REGULAR, 14, "Regular", 0.1)
    LABEL = TextStyle(INTER_SEMIBOLD, 14, "SemiBold", -0.1)
    TILE_NAME = TextStyle(INTER_SEMIBOLD, 14, "SemiBold", -0.1)
    BTN = TextStyle(INTER_SEMIBOLD, 13, "SemiBold", 0.0)
    EYEBROW = TextStyle(INTER_SEMIBOLD, 12, "SemiBold", 1.6)      # all-caps clerk eyebrow
    GP = TextStyle(INTER_SEMIBOLD, 11, "SemiBold", 0.0)          # gamepad glyph letter

    # ── mono (clock, counts, ids) ──
    MONO = TextStyle(JETBRAINS_MONO, 13, "Regular", 0.0)
    MONO_TECH = TextStyle(JETBRAINS_MONO, 13, "Regular", 0.0)
    TILE_SUB = TextStyle(JETBRAINS_MONO, 11, "Regular", 0.3)
    META_SM = TextStyle(JETBRAINS_MONO, 11, "Regular", 0.3)
    OVERLAY_META = TextStyle(INTER_REGULAR, 12, "Regular", 0.1)
    KBD = TextStyle(JETBRAINS_MONO, 11, "Regular", 0.0)


# ─── spacing (4px grid) ──────────────────────────────────────────────


class Space:
    XS = 4
    S = 8
    M = 12
    L = 16
    XL = 20
    XXL = 24
    XXXL = 32

    SAFE_AREA = L      # 16px side margins
    GUTTER = M

    STATUS_BAR_HEIGHT = 28          # v3: quiet, content gets the height
    FOOTER_HINT_HEIGHT = 28


# ─── radius ──────────────────────────────────────────────────────────


class Radius:
    HERO = 14
    CARD = 12
    BUTTON = 8
    TILE = 8
    CHIP = 6
    PILL = 999


# ─── stroke widths ────────────────────────────────────────────────────


class Stroke:
    HAIRLINE = 1
    BORDER_DEFAULT = 1
    BORDER_FOCUSED = 2
    DIVIDER = 1


# ─── focus state metrics (THE signature) ─────────────────────────────


class Focus:
    SCALE = 1.03
    BORDER_PX = Stroke.BORDER_FOCUSED
    OUTER_GLOW_PX = 12
    OUTER_GLOW_ALPHA = 0.30
    BG_BRIGHTEN_FROM = Color.SURFACE_BASE
    BG_BRIGHTEN_TO = Color.SURFACE_ELEVATED


# ─── motion (durations in ms) ─────────────────────────────────────────


class Dur:
    MICRO = 100
    FAST = 180
    BASE = 280
    SLOW = 400


def freeze() -> None:
    """No-op. The module is read-only by convention."""
    return None
