# The default face A generic CPU renderer in `mrlyui::face`: any app's view - state, actions, canvas - becomes pixels, then a PNG. Terminal-esque, uniform, deliberately plain. It is the agent's eyes: a screenshot of any app on any tick, no browser in the loop. ## The two shot kinds - **Canvas shot** (`Os::snapshot`, `sys.shot`, cli `shot`) - the app's own `frame` fact rendered raw. Apps define availability: no frame fact, no shot. Frameless apps fail with "nothing to shoot here". Unchanged. - **Face shot** (`mrlynet::face::face_png`, cli `face`) - works for every app. Renders the whole view and embeds the canvas raster in its body when one exists. ## Geometry 320x452 fixed - the sheet. 452/320 tracks the square root of 2 within 0.2%, so a sheet halves into two sheets of the same shape: 320x452 -> 226x320 -> 160x226 -> 113x160. Body fills from the top, the action bar anchors to the bottom, slack in between stays board-colored. Rendered at scale 3 - PNGs are 960x1356. Pure function of the input: no clock, no RNG, byte-identical across runs. ## Layout - **Title bar** (20px): 8x8 accent chip (emoji stand-in), title at scale 2, beat verb right-aligned muted, hairline rule. - **Body**: route params, then the canvas embed (integer scale fitting 308x192; undecodable, oversized, or empty facts degrade to a muted `frame WxH` row), then state rows in map order (`frame`, `shade`, `md` skipped): scalars as key/value rows, all-scalar arrays inline, number grids as `key 16x16` summaries, object arrays listed capped at 12 with `+ n more`, nested objects one indent level then brief summaries, `data:` strings as `[png Nb]` tokens. A `md` string renders text-only: H1 scale 2, H2 accent, paragraphs pixel-wrapped, lists with hanging indent, code lines on a faint backdrop; emphasis and links strip to plain text. - **Action bar** (pinned bottom): accent verb names with muted arg hints, capped at 8 plus `+ n more`; zero actions reads `no actions`. ## Theme Board and ink follow darkmode; muted and faint are mixes between them. The accent is `ROLLABLE[hash(route) % 13]` - deterministic per app. Text uses the bitmap font; unsupported glyphs (emoji included) draw a hollow box, never blank. No emoji atlas yet - the sprite atlas is a later phase. ## Totality The face never fails: null state renders `no state`, hostile or oversized state truncates with `..` and `+ n more` against the height budget, and every string passes through the same per-char engine. `face_png` is total over anything `peek` returns. ## Surfaces - Rust: `mrlyui::face::{face, face_png, decode}` over a plain `FaceInput`; glue in `mrlynet::face::{face_frame, face_rgba, face_png, canvas_rgba}`. - CLI: `mrlycli face --out f.png` (replay script, focused app), repl `:face [path]`. `shot` is the canvas kind and is untouched. - Python: `mrlypy.peek/capture/capture_png/face/face_png`; ndarrays via `np.frombuffer(buf, np.uint8).reshape(h, w, 4)`. - Example: `cargo run -p mrlynet --example face` writes every route plus six lived-in gauntlet shots to `data/face/`. One pixel pin guards the whole stack (`face_pixels_are_pinned` in mrlyui); re-record it on deliberate layout changes.