//! The terminal renderer for [`makeover_layout`]. //! //! //! //! Named for the target and not for ratatui, the same way //! `makeover-immediate` is named for the mode and not for egui. //! //! # What a terminal actually costs you //! //! Not colour. That was the original assumption here and it is wrong on any //! terminal built this decade. Measured across the 31 shipped themes //! (`makeover`'s `well_fidelity` example): //! //! | | ANSI-16 | ANSI-256 | truecolor | //! |---|---|---|---| //! | a well collapses onto its face | 18/31 | 4/31 | 2/31 | //! | at least one bevel edge vanishes into its face | 31/31 | 4/31 | 0 | //! //! The threshold is 256, not 24-bit, and the two failures that survive at //! truecolor are not terminal failures at all: they are the themes whose //! raised surface is already white, so the lightening clamps and the well //! lands exactly on its face. Those render identically in a browser. //! `makeover`'s own `well_is_distinct_from_its_face` test already names them. //! //! **What a terminal costs is geometry, and no amount of colour fixes it.** //! An edge occupies a whole cell on each side. A cell is roughly 8x17 pixels, //! so a one-pixel bevel becomes something an order of magnitude heavier, which //! is why [`frame`] hands back a shrunk [`Rect`] instead of pretending the //! region survived intact. There is nowhere to put a corner radius, so //! `radius_control` and `radius_container` mean the same thing here. A fill //! can only begin and end on a cell boundary. //! //! That is the constraint worth designing against. It does not improve, it is //! not detectable, and it applies equally to the best terminal ever written. //! //! What it does not mean is that the shape inside the cell stops mattering. //! Half of a cell is still addressable, and a bevel drawn in half-blocks reads //! as a lit edge where the same bevel in box-drawing reads as a line: `─` and //! `│` are one stroke through the middle, identical on all four sides, saying //! nothing about where the light is. Half-blocks also make the two corners //! where light meets shadow expressible, since a glyph that fills half a cell //! leaves the other half to the second tone. //! //! # Where fidelity does matter //! //! At [`Fidelity::Ansi16`] the depth vocabulary collapses outright: a well //! cannot be filled distinctly on most themes *and* a bevel loses an edge on //! every one of them, so a raised card and a well both read as a single-tone //! box. Colour cannot carry the distinction, so [`frame`] carries it with the //! glyphs instead. //! //! Above that, colour carries it and the glyph fallback never fires. //! //! [`Palette::shows`] is worth reading correctly in light of the numbers: it //! is **not** a low-colour workaround. It is a correctness check that a fill //! will be visible against what is behind it, and at truecolor it fires on //! exactly the two clamping themes, which is precisely when it should. //! //! # Overlays, selection and the focus ring //! //! [`Palette::fill`] answers `Fill::Overlay`, so //! [`Depth::Overlay`](makeover_layout::Depth::Overlay) needs nothing beyond the //! route from a description. A test asserts that route, because a route nothing //! exercises is one a refactor can quietly lose. //! //! [`Theme::selection_on`] and [`Theme::focus_ring`] are DERIVED rather than //! authored, and the direction is one-way: an authored key can fall back to a //! derivation and break no theme on disk, while a key this crate started //! requiring would break every theme that lacks it. So the theme format does not //! change, and the promotion stays available for a theme that ever needs to tune //! either. Without them a port does selection with `REVERSED` for want of an //! on-accent foreground, and spends makeover's `border-strong` on a focus ring, //! which is a divider at 1.63:1 on Akari Dawn. //! //! # The table //! //! [`table`] is the one thing here that draws content rather than a surface. It //! is a mapping layer over [`ratatui::widgets::Table`] rather than a table //! implementation, because ratatui already lays tracks out, draws a header, //! highlights a row and scrolls. What it has no answer for is content //! measurement and narrowing, and those are what the module is. //! //! # `piece`, not `widget` //! //! `makeover-layout` owns `Region::Widget`, the tier between a primitive and //! `Region::Widget`: a named assembly of primitives that each renderer draws //! its own way. That is host-agnostic and sits *above* every renderer. //! //! This crate's [`piece`] module is the opposite end of the same stack: //! renderer-local, the answer to what a meter looks like in cells, taking a //! description plus what only a terminal knows. Two different things must not //! wear one word, least of all in a crate that has to implement the tier. The //! style type is [`piece::PieceStyle`]. //! //! # A bounded number, and an option that is not offered yet //! //! A [`makeover_layout::FieldKind::Range`] is drawn as [`piece::meter`]'s cells //! with its two ends read out either side, because the ends are what the //! question means and a terminal is where it would be easiest to quietly show a //! figure instead. An unbounded range falls back to the text path rather than to //! bounds this crate invented. //! //! `Choice::unavailable` is the one place the three-tone convention's muted is //! the truth rather than the lie it warns about: that option will not answer, //! and the reason it will not sits on its row. //! //! `Choice::detail` takes a row of its own under the option, inset by the width //! of the mark and muted for the same reason: the line is not a thing to press. //! This is the host with the most room of the three, so unlike a browser's //! `