//! 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. //! //! # 0.13.0: a modal, and two cues four ports were about to each invent //! //! [`Depth::Overlay`](makeover_layout::Depth::Overlay) arrives in //! makeover-layout 0.14.0 and needed nothing here: [`Palette::fill`] has //! answered `Fill::Overlay` since this crate had a palette, so what was missing //! was the route from a description rather than the drawing. A test asserts it, //! because a route nothing exercises is one a refactor can quietly lose. //! //! [`Theme::selection_on`] and [`Theme::focus_ring`] are the other half, and //! both are DERIVED rather than authored. Every consumer measured did selection //! with `REVERSED`, for want of an on-accent foreground; every one that wanted //! a focus ring either spent makeover's `border-strong` on it, which is a //! divider at 1.63:1 on Akari Dawn, or derived its own the way `alloy_tui` //! does. Four terminal ports were each about to answer that separately. //! //! Derived, not authored, because the direction is one-way. An authored key can //! fall back to a derivation and break no theme on disk; a key this crate //! started requiring would break every theme that lacks it. So the theme format //! does not change and nothing on disk grows, and the promotion stays available //! for a theme that ever needs to tune either. //! //! # 0.14.0: the first structural widget //! //! [`table`] is the first thing here that draws content rather than a surface, //! and it exists because 14 call sites across `mnw-cli` and `viewer` were //! already drawing one. `mnw-cli` had written the mapping layer by hand //! (`src/tui/widgets.rs`: a muted bold header, a selected row carried by the //! background alone) and `viewer` had written a smaller one, which is two //! answers to a question this crate is supposed to answer once. //! //! 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. //! //! # 0.19.0: `widget` is [`piece`], because the word went to the description //! //! `makeover-layout` 0.20.0 added `Region::Widget`, the third tier between a //! primitive and `Region::Bespoke`: a named assembly of primitives that each //! renderer draws its own way. That is host-agnostic and sits *above* every //! renderer. //! //! This crate's `widget` 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 wearing //! one word, and the collision would have been worst exactly here, in a crate //! that has to implement the tier. //! //! So this half moved and the description's half kept the word. That direction //! is not arbitrary: a second or third party naming a widget is naming the //! layout kind, and nothing outside this tree ever needed a word for a drawing //! routine. `WidgetStyle` is `PieceStyle`. //! //! # 0.27.0: a bar for a bounded number, and an option that is not offered yet //! //! `makeover-layout` 0.28.0's form findings, at the renderer that has the bar //! already. 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 now sits on its row. //! //! `Choice::detail` (makeover-layout 0.39.0) 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 -- a browser's `