"""The Alexandria mark: the software's mark, not Keystone's.

SINGLE SOURCE. This file is the only place the geometry lives. Three surfaces
draw it, in three different containers:

  rack-runtime/auth/oauth_service.py    the rack's sign-in / consent screens,
                                        and the favicon every brain host serves
  rack-runtime/signup/signup_service.py the license redemption page
  rack-runtime/console/srv/index.html   the admin console's sign-in page

Those services ship as one-file images and cannot import the app package, so
their Dockerfiles COPY *this file* next to the service instead — which is why
each imports it with a two-branch import: ``from brand import ...`` inside the
image, falling back to ``from alexandria_vault.brand import ...`` in a checkout,
where the tests load the service by path. If you add a surface, COPY this file
and do the same rather than pasting the paths again.

The console's page is the awkward one and worth understanding before you add
another like it: Caddy serves it *statically*, so nothing can import anything at
request time. It ships as a template with a placeholder and is rendered once at
image build time by ``rack-runtime/console/signin_page.py``. It got here by
pasting the arc in, which then sat in brass for a release after every other
surface moved to ink — the drift guard in ``tests/test_rack_oauth.py`` only
globbed ``*.py``. It globs markup now.

The geometry was previously duplicated in all three, guarded by tests that
asserted the copies matched. Those tests now assert single-sourcing instead: a
guard against drift is worth having, but not having anything to drift is
better.

Drawn as a mask over a solid rect rather than as strokes: the counters (the
inner archway, the lintel band, the two rays) are knocked OUT of the fill, so
the whole glyph is a single colour and stays crisp at tab size instead of
thinning to invisibility the way a 2px-stroke mark does at 16px.

Stdlib only, and deliberately dependency-free — it is copied into images that
contain nothing but python and one service file.
"""

from __future__ import annotations

from urllib.parse import quote

#: The Alexandria accent. FUNCTIONAL ONLY — primary action, focus ring. It is not
#: a brand colour and the mark is never drawn in it. See :func:`alexandria_mark`.
#:
#: This is the LIGHT-theme value. Every page also carries a lighter dark-theme
#: pair (``#6d9eff``), because one accent cannot clear 4.5:1 on both a #f6f7f9
#: and a #0d1017 background — see the ``--accent`` blocks in signup_service.py.
ACCENT = "#1c62d6"

#: The former accent, Keystone's brass, retired in v2.109.0. Kept as an alias so
#: an import from an older checkout does not explode; it now holds the new value
#: deliberately — a name that still resolved to brass would repaint one surface
#: gold the moment somebody used it.
BRASS = ACCENT

#: The tab icon: black mark on its own white tile. These are keystone.computer's
#: ``--foreground``, ``--background`` and ``--border``, so a brain host, the
#: sign-in page, the redemption page and the marketing site all show the same
#: icon. Why a tile rather than a bare glyph: :func:`favicon_svg`.
INK = "#0a0a0b"
TILE = "#ffffff"
TILE_EDGE = "#e6e8ec"


def _mask(mask_id: str) -> str:
    """The counters, as a mask. THE geometry — every surface routes through here.

    Drawn as a mask over a solid rect rather than as strokes: the counters (the
    inner archway, the lintel band, the two rays) are knocked OUT of the fill,
    so the whole glyph is a single colour and stays crisp at tab size instead of
    thinning to invisibility the way a 2px-stroke mark does at 16px.
    """
    return (
        f"<mask id='{mask_id}'>"
        "<path fill='#fff' d='M16.7 49 V32 A15.3 15.3 0 0 1 47.3 32 V49 Z'/>"
        "<path fill='#000' d='M23.2 49 V32 A8.8 8.8 0 0 1 40.8 32 V49 Z'/>"
        "<rect x='21.7' y='33.5' width='20.6' height='6' fill='#fff'/>"
        "<g fill='none' stroke='#000' stroke-width='1.6'>"
        "<path d='M27.05 15.5 L29.75 24.5'/>"
        "<path d='M36.95 15.5 L34.25 24.5'/>"
        "</g></mask>")


_OPEN = ("<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64' role='img' "
         "aria-label='Alexandria'>")


def alexandria_mark(color: str = "currentColor",
                    mask_id: str = "alexandria-mask") -> str:
    """The mark as inline SVG, for embedding IN a page.

    THE MARK IS MONOCHROME. Black on light surfaces, white on dark — never
    brass, never any other colour. A logo that changes hue between the tab
    icon, the sign-in screen and the console reads as three vendors; one that
    is only ever ink reads as one. Callers should pass the surface's
    foreground token (``var(--ink)``, ``var(--fg)``), not ``var(--accent)``:
    :data:`ACCENT` is the functional accent for buttons and focus rings and has
    no claim on the mark.

    ``color`` defaults to ``currentColor`` so the page tints it from CSS.

    ``mask_id`` is a parameter because two copies on one page would otherwise
    collide on the id and the second would render as a bare square.
    """
    return (f"{_OPEN}{_mask(mask_id)}"
            f"<rect width='64' height='64' fill='{color}' "
            f"mask='url(#{mask_id})'/></svg>")


def favicon_svg() -> str:
    """The tab icon: the black mark on its own white tile.

    The tile is the whole point, and it is the second answer to this problem —
    the first two were wrong in instructive ways. A favicon is its own document
    and inherits no colour, so a bare glyph has to guess what is behind it.
    Brass guessed "something, but not too dark or too light" and was visible
    everywhere at the cost of not being the mark the website shows. Black plus a
    ``prefers-color-scheme`` flip looked like the fix and is worse: the query
    resolves against the CLIENT's scheme, not the surface the icon actually sits
    on, so an icon on a light card inside a dark-mode app — which is exactly
    where an MCP client lists a connector — flips to white and disappears.
    Measured in a browser, both ways round, before this was written.

    Carrying its own background removes the guess. Black on white is legible on
    any surface, in any scheme, in any client, and it is the same mark
    keystone.computer shows. The hairline edge keeps the tile from dissolving
    into a white page.

    Short ids, no whitespace: this string is URL-encoded into a data URI, where
    every byte becomes three characters.
    """
    # viewBox is the mark's own bounds (x 16.7–47.3, y 16.7–49) grown to a square
    # with ~19% margin, so the glyph is inset in the tile rather than bleeding to
    # its edges. Framing the tile in the viewBox avoids a transform, which would
    # have to scale the mask with the rect and is easy to get subtly wrong.
    return (
        "<svg xmlns='http://www.w3.org/2000/svg' viewBox='6 6.85 52 52' "
        "role='img' aria-label='Alexandria'>"
        f"<rect x='6' y='6.85' width='52' height='52' rx='11' fill='{TILE}'/>"
        f"<rect x='6.5' y='7.35' width='51' height='51' rx='10.5' fill='none' "
        f"stroke='{TILE_EDGE}'/>"
        f"{_mask('a')}"
        f"<rect width='64' height='64' fill='{INK}' mask='url(#a)'/></svg>")


def favicon_href() -> str:
    """The mark as a ``data:`` URI, for a page's ``<link rel=icon>``.

    A page that handles a credential makes no external request for its own tab
    icon, and this needs no second endpoint to route.
    """
    return "data:image/svg+xml," + quote(favicon_svg(), safe="")


#: Precomputed, since every page that wants it wants the same one.
FAVICON_HREF = favicon_href()

#: The bytes served at ``/favicon.ico`` and ``/icon.svg`` on every brain host.
FAVICON_SVG = favicon_svg()

#: Content type for :data:`FAVICON_SVG`. The path says ``.ico`` because that is
#: what clients probe for; the type header is what actually decides how it is
#: parsed, so the two disagree on purpose.
FAVICON_CONTENT_TYPE = "image/svg+xml"
