Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-map/src/paint_order.rs

//! **THE declared paint order — one key, both lanes.**
//!
//! # The defect this closes
//!
//! Reported by the owner on the live 2D map, 2026-08-22: the basemap "draws in the order
//! things were read in, and paints over what should be on top". Four independent
//! mechanisms produced that, and none of them was a bug in any single line of code —
//! the order was simply never *declared* anywhere a painter could sort on:
//!
//! 1. **Class order was a LAYER-PUSH convention.** korp pushes one `WaysLayer` per
//!    feature class in `map_paint::OSM_WAY_LAYER_IDS` order, and the painter's only
//!    class signal was the order those layers happen to sit in the facet. *Within* a
//!    class the order was the input order — whatever the tile merge appended last won
//!    every overlap. Two adjacent buildings, a lake and the park it sits in, a road and
//!    the service road beside it: all decided by decode order, and therefore different
//!    on the next fetch.
//! 2. **`z` was per KIND, not per class.** `LayerKind::default_z()` gives every polygon
//!    `10` and every line `20`, and `MapFacet::features_for_cpu` sorted on exactly that
//!    — a *stable* sort, so class order survived only as the tie-break inside one kind.
//!    `DrawFeature::z`'s own doc claimed "a wider way (motorway) draws over a thinner
//!    one at the same tier". It never did: every line carried the identical `20`.
//! 3. **The GPU lane broke the stack — CLOSED 2026-08-22, and this text is history.**
//!    `MapFacet::ui` painted in three buckets — CPU features below a hardcoded
//!    `LayerKind::Line.default_z()`, the GPU callback, then the CPU tail — while the
//!    lane owns `GpuOwns { lines, fills }`. A **fill** the GPU took was therefore drawn
//!    in the LINE slot, above every CPU-painted fill whatever its class.
//!
//!    **Do not go looking for this one: the hardcoded slot is gone.** `MapFacet::ui`
//!    now splits on `gpu_lane_rank_floor` — the lowest [`PaintKey::rank`] the lane will
//!    actually draw this frame (layer.rs:2565) — and
//!    `tests/paint_order_pixels.rs::the_gpu_slot_lands_in_the_declared_stack` holds it
//!    there. VERIFIED 2026-08-31 (oden, RTX 4090): the device-lane pixel claims in
//!    `tests/gpu_lane_paint_order.rs` — a tunnel under a lake, and the two tile
//!    arrangements — pass on this tree; both were RED when they were written.
//! 4. **OSM's own z-order tags were read NOWHERE.** `layer`, `bridge` and `tunnel` did
//!    not appear in `facett-map`, `facett-osm` or `korp/src/map_paint.rs` at all
//!    (grep, 2026-08-22). A bridge over a river and a tunnel under a street had no
//!    order to go on beyond their class, so a motorway viaduct sank under the water it
//!    crosses whenever the water happened to decode later.
//! 5. **The floor was not a floor — and closing #4 is what opened it.**
//!    [`LANDMASS_BAND`] was a *band* (`-1_000`) in a rank whose dominant term is
//!    `effective_layer * LAYER_STEP`. So the moment `layer`/`tunnel` started being read,
//!    a single `tunnel=yes` way ranked ~97 800 units under the land silhouette, dragged
//!    the GPU lane's one opaque callback slot below it, and the **white land painted
//!    over the whole map** — varying with what had been loaded, exactly like #3, which
//!    is why it was mistaken for #3 not being fixed. See [`LANDMASS_BAND`] for the
//!    measurement and [`WAY_RANK_FLOOR`] for the const assertion that now forbids it.
//!    Reported by the owner 2026-08-30 (*"vita marken tar över allt"*), closed 2026-08-31.
//!
//! # The shape of the cure (LAW 5)
//!
//! ONE key, [`PaintKey`], computed by ONE function, [`way_paint_key`], from the way
//! itself — never from where it landed in a layer vector and never from when it was
//! read. Everything that paints sorts on it:
//!
//! * the CPU painter (`MapFacet::features_for_cpu` → `DrawFeature::order`),
//! * the GPU legacy lane (`gpu_lane_ways` / `gpu_lane_fills`),
//! * the GPU tile lane (each group's lines + fills).
//!
//! …and the CPU/GPU **seam** sorts on it too, which the list above used to leave out:
//! the GPU callback is ONE opaque slot, so `MapFacet::ui` places it at the lane's own
//! [`PaintKey::rank`] floor and paints the CPU features below that rank before it. That
//! makes every band constant here load-bearing across the seam and not merely inside one
//! painter's sort — which is the whole content of defect 5.
//!
//! Because the key is a pure function of the `Way`, **swapping the input order cannot
//! change a pixel** — which is the property `tests/paint_order_pixels.rs` asserts on
//! the rendered framebuffer rather than on the sorted vector.
//!
//! # The key, term by term
//!
//! ```text
//! rank = effective_layer * LAYER_STEP + band + class + tier
//! ```
//!
//! * **`effective_layer`** — the OSM `layer` tag, clamped to [`LAYER_CLAMP`]. It
//!   dominates every other term, which is the OSM data model: `layer` is the
//!   cartographer's explicit statement about what is above what. `bridge`/`tunnel`
//!   *imply* ±1 only when `layer` is absent (the osm-carto rule — an explicit
//!   `layer=2` on a bridge means 2, not 3).
//! * **`band`** — areas under lines under points under labels ([`AREA_BAND`] …
//!   [`LABEL_BAND`]). The old `LayerKind::default_z()` ladder, kept as the coarse tier
//!   so a themed basemap looks the way it did.
//! * **`class`** — water < landuse/park < buildings < (unclassified area) inside the
//!   area band; coastline < water lines < paths < rail/roads < (unclassified line)
//!   inside the line band — the rail INTERLEAVED with the road tiers, see [`RAIL_CLASS`].
//!   This is korp's `OSM_WAY_LAYER_IDS` order, moved from a push convention to a
//!   declared per-way value.
//! * **`tier`** — the way's [`Lod`]: a `Country` motorway paints OVER a `City`
//!   cul-de-sac. This is the hierarchy `DrawFeature::z` documented and never had.
//!
//! Ties on `rank` are broken by **area, largest first** — so a building sitting inside
//! a landuse polygon of the same rank draws on top of it — and finally by the stable
//! `osm_id`, so two identical frames stack identically and no overlap is ever decided
//! by decode order.

use crate::{Lod, Way, WayKind};

/// One OSM `layer` step, in rank units. Large enough that no combination of band,
/// class and tier can climb out of its own layer.
pub const LAYER_STEP: i32 = 100_000;

/// `layer` is clamped to `-CLAMP ..= CLAMP`. Real OSM data lives in `-5..=5`; the
/// clamp keeps a vandalised `layer=99999` from overflowing the rank.
pub const LAYER_CLAMP: i32 = 8;

/// **The lowest rank [`way_rank`] can ever produce** — the deepest OSM `layer` with the
/// lowest class and the deepest tier. Nothing below this is a way, so this is where a
/// base band has to go to be a base band.
///
/// `tier_rank`'s minimum is `0` and `class_rank`'s is `AREA_BAND + 100` (a water fill), so
/// the whole floor is the `layer` term at full negative clamp. `AREA_BAND` is used rather
/// than that `+ 100`, deliberately: a floor may be conservative (a hundred units of slack)
/// but must never be optimistic, and the class offsets are the thing most likely to be
/// re-tuned. MEASURED slack, `tests::no_way_can_sink_below_the_landmass`: the deepest way
/// real classification produces is **-799 870** against this **-800 000** — 130 units, and
/// the test fails if that gap ever grows past one [`LAYER_STEP`], so "conservative" cannot
/// quietly become "a number that happens to be small".
///
/// Written as an expression off the constants that produce it rather than as a literal,
/// because a literal is exactly what let the landmass sit 799 000 rank units ABOVE it (see
/// [`LANDMASS_BAND`]).
pub const WAY_RANK_FLOOR: i32 = -LAYER_CLAMP * LAYER_STEP + AREA_BAND;

/// The **landmass base fill** — the floor, under every other band, so the land
/// silhouette paints first and land-vs-sea reads instantly. A dedicated band (not
/// `AREA_BAND - something`) so a future aerial-raster base can still slot under it.
///
/// # THE DEFECT THIS NUMBER WAS (owner, 2026-08-30: *"vita marken tar över allt"*)
///
/// It was **`-1_000`**, and the doc line above it — *"the floor, under every other
/// band"* — was false the moment [`OsmZ`] landed. A band is not a floor: [`way_rank`] is
/// `effective_layer * LAYER_STEP + band + class + tier`, and [`LAYER_STEP`] is 100 000,
/// so **one `tunnel=yes` / `layer=-1` way ranks at about −98 800** — 97 800 units BELOW a
/// landmass at −1 000.
///
/// That is not merely an ordering curiosity inside the CPU list, where the landmass
/// would still have been under every *positive*-layer feature. It decides the CPU/GPU
/// seam: `MapFacet::ui` inserts the GPU callback as ONE opaque slot at the lane's own
/// rank FLOOR (`gpu_lane_rank_floor` — the minimum `way_rank` over every way the lane
/// draws, scanned with **no viewport cull**). A single tunnel anywhere in the loaded set
/// dropped that slot below the landmass, the landmass fell into the CPU **tail**, and
/// the white country silhouette painted over the entire GPU-rendered map.
///
/// Both halves of the report, from one constant: it covers everything (the silhouette is
/// the country), and it varies with what has been loaded (whether a negative-`layer` way
/// is in the set at all).
///
/// MEASURED, that this is a live data shape and not a corner case: on a real Sweden
/// pyramid tile (`z9/288/125.parquet`, 2026-08-31) **11 of 1 493 ways (0.74 %)** carry
/// `tunnel=*` and 11 carry `layer < 0`.
///
/// MEASURED, the pixels (`tests/gpu_lane_paint_order.rs`,
/// `a_tunnel_in_the_loaded_set_cannot_put_the_white_land_over_the_map`, oden / RTX 4090,
/// 2026-08-31): two renders differing by exactly that one tag disagreed on **91 212 of
/// 208 000 pixels (43.9 %)** and the pane centre went from water `[18, 58, 90]` to land
/// `[242, 239, 233]`.
///
/// So the value is now derived from [`WAY_RANK_FLOOR`] — one clear `LAYER_STEP` under
/// the deepest way there can be — and the const assertion below makes "the landmass is
/// the floor" a build failure to break rather than a sentence to trust.
pub const LANDMASS_BAND: i32 = WAY_RANK_FLOOR - LAYER_STEP;

/// **The landmass really is under every way.** The claim [`LANDMASS_BAND`]'s doc makes,
/// asserted at build time against the arithmetic that produces a way's rank instead of
/// being restated in prose — which is how it stayed false for eight days.
const _: () = assert!(
    LANDMASS_BAND < WAY_RANK_FLOOR,
    "LANDMASS_BAND is no longer under the lowest rank a way can have: a `tunnel=yes` or a \
     `layer=-1` way now sorts BELOW the land silhouette, which drags the GPU lane's callback \
     slot under it and paints the white land over the whole map."
);

/// Area fills — the bottom band.
pub const AREA_BAND: i32 = 0;
/// Stroked lines (coastline, roads, paths) — above every fill of the same layer.
pub const LINE_BAND: i32 = 1_000;
/// Point markers.
pub const POINT_BAND: i32 = 2_000;
/// Labels — always the top band.
pub const LABEL_BAND: i32 = 3_000;

/// The rank a single [`Lod`] step is worth. See [`CLASS_STEP`] for the budget it
/// spends.
pub const TIER_STEP: i32 = 10;

/// **The tightest gap between two adjacent class offsets** — the budget the whole tier
/// ladder has to fit inside.
///
/// The AREA band steps by 100 (water 100, park 200, building 300, other 400) and that
/// is the number `tier_rank` used to quote. The LINE band does not: coastline `0`,
/// **water 50**, path 100, road 200, other 400. The headroom is therefore HALF what was
/// written, and the tier at which a sub-rank climbs into the class above is a 6th, not
/// an 11th. `tests::the_tier_ladder_fits_under_the_measured_class_gap` measures this
/// off `class_rank` rather than trusting it to stay true.
pub const CLASS_STEP: i32 = 50;

/// **A sixth tier does not fit, and this is where it fails.**
///
/// The coarsest tier's sub-rank is `(LOD_COUNT-1) * TIER_STEP`; it must be strictly
/// under [`CLASS_STEP`], because *equal* puts the coarsest tier of one class exactly on
/// the finest tier of the next and the collision resolves through the area tie-break —
/// a look defect with nothing pointing back here. Five tiers fit with 10 to spare.
const _: () = assert!(
    (crate::style::LOD_COUNT as i32 - 1) * TIER_STEP < CLASS_STEP,
    "LOD_COUNT tiers x TIER_STEP no longer fits under CLASS_STEP: the coarsest tier of      one class now collides with the finest tier of the next. Either widen the class      offsets in `class_rank` (and CLASS_STEP with them) or shrink TIER_STEP."
);

/// **Where a RAILWAY sits: inside the road ladder, not beside it** — GG audit row 28.
///
/// # The defect
///
/// `class_rank` had no arm for [`WayKind::Rail`] because there was no such kind:
/// `classify_with`'s `railway` arm stamped `WayKind::Other`, and `Other`'s line offset is
/// the OVERLAY slot, `LINE_BAND + 400`. So every `railway=rail` in Sweden ranked 1440
/// against the motorway's 1240 and painted over the E4 at every crossing, and
/// [`line_kind_outranks_roads`] told the 3D extruder the same lie.
///
/// # Why this is not `LINE_BAND + 150` or `+ 250`
///
/// The class offsets step by [`CLASS_STEP`] = 50 and the tier ladder spends 40 of that,
/// which is the right shape for classes that do not interleave. A railway DOES: the
/// order every reference agrees on — osm2pgsql's default `z_order` (rail 35, level with
/// `secondary`, under `primary`/`trunk`/`motorway`, over `tertiary`/`residential`) and the
/// Garmin look korp is after — puts trunk rail between the primary and the secondary
/// road network, i.e. BETWEEN two tiers of one class. No offset 50 apart from `Road`
/// can express that: `+150` is under every road including `service`, `+250` is over
/// the motorway.
///
/// So the rail offset is the road offset **minus half a tier step**: five units under
/// the road ladder, which puts each rail tier exactly midway between two road tiers and
/// never ON one (the const assertion below forbids the tie, which would fall through to
/// the bbox-area tie-break — decode-order luck at every level crossing):
///
/// ```text
/// Road·Country  1240  motorway, trunk, primary
/// Rail·Country  1235  railway=rail, narrow_gauge          ← the national network
/// Road·Region   1230  secondary, primary_link, motorway_link
/// Road·District 1220  tertiary
/// Rail·District 1215  light_rail, subway, tram, funicular  ← urban rail
/// Road·City     1210  residential, unclassified
/// Road·Detail   1200  service, track
/// Path·Country  1140  (the path ladder tops out here)
/// ```
///
/// This is the ONE class that interleaves, and
/// `tests::the_tier_ladder_fits_under_the_measured_class_gap` deliberately leaves it out
/// of the gap measurement for that reason; its own order is pinned by
/// `tests::a_railway_ranks_under_the_motorway_and_over_the_residential_street`.
pub const RAIL_CLASS: i32 = ROAD_CLASS - TIER_STEP / 2;

/// The road class offset inside the LINE band — named so [`RAIL_CLASS`] can be written
/// as an expression off it rather than as a literal that drifts.
const ROAD_CLASS: i32 = 200;

/// **No rail tier may land ON a road tier.** Half a tier step is not a multiple of one,
/// which is the whole property; spelled out so a retuned `TIER_STEP` cannot silently make
/// it one.
const _: () = assert!(
    (ROAD_CLASS - RAIL_CLASS) % TIER_STEP != 0,
    "RAIL_CLASS is a whole number of tier steps off ROAD_CLASS: some rail tier now TIES a \
     road tier and the tie resolves through the bbox-area fallback at every level crossing"
);

/// Per-[`Lod`] sub-rank: `Country` (the trunk network, the big water) sits **highest**
/// inside its class, the deepest tier (footway furniture) lowest.
///
/// Derived from [`LOD_COUNT`](crate::style::LOD_COUNT) rather than the literal `3` it
/// used to hardcode, so adding a tier moves the ladder instead of folding two tiers
/// onto one rank — the same defect `LOD_COUNT`'s own doc was written about.
fn tier_rank(lod: Lod) -> i32 {
    let last = crate::style::LOD_COUNT as i32 - 1;
    (last - (lod as i32).clamp(0, last)) * TIER_STEP
}

/// The class offset inside a band — korp's `OSM_WAY_LAYER_IDS` order, declared here
/// per way instead of being implied by which layer vector the way landed in.
fn class_rank(kind: WayKind, is_area: bool) -> i32 {
    if is_area {
        AREA_BAND
            + match kind {
                WayKind::Water => 100,
                WayKind::Park => 200,
                WayKind::Building => 300,
                // An unclassified closed ring: above the classified fills, still under
                // every line. This is the half of korp's `osm-other` layer that used to
                // paint over the ROADS purely because that layer is pushed last.
                _ => 400,
            }
    } else {
        LINE_BAND
            + match kind {
                WayKind::Coastline => 0,
                // A `waterway=river`/`stream`/`ditch` is a LINE, not a fill, and it
                // belongs with the shore — under the road network, not above it. It fell
                // into the catch-all below while it was the only line class with no arm,
                // which put every river over every motorway.
                WayKind::Water => 50,
                WayKind::Path => 100,
                // INSIDE the road ladder, half a tier step under it — see `RAIL_CLASS`.
                // It was the catch-all below, i.e. overlay ink above every road (GG #28).
                WayKind::Rail => RAIL_CLASS,
                WayKind::Road => ROAD_CLASS,
                _ => 400,
            }
    }
}

/// **Does a LINE of this class paint above the road network?** — lane GG #4.
///
/// The one question a second painter has to ask the declared order, exported so it cannot
/// be answered twice. `true` for [`WayKind::Glow`], [`WayKind::Overprint`] and
/// [`WayKind::Other`] — overlay ink, at `LINE_BAND + 400`; `false` for
/// [`Coastline`](WayKind::Coastline) `+ 0`, [`Water`](WayKind::Water) `+ 50`,
/// [`Path`](WayKind::Path) `+ 100`, [`Rail`](WayKind::Rail) `+ 195` and
/// [`Road`](WayKind::Road) `+ 200`, which are the basemap. A railway answered `true`
/// until GG #28, because it had no kind and rode `Other`.
///
/// It exists because the 3D extruder had its own, coarser stack (`GroundLayer`) and made
/// the opposite call: `facett-map3d`'s `line_feature` gave a road three stacked sub-passes
/// and laid **everything else** at the lowest of them, so a case glow or a graph edge sat
/// *under* the road it crossed. That is the same defect `class_rank`'s `Glow` doc already
/// names — *"a trail belongs above the roads it crosses, not among them"* — arriving in
/// the lane that did not ask.
///
/// Area kinds are not a question this answers: it reads the LINE band, where the ordering
/// argument is about ribbons on the ground.
#[must_use]
pub fn line_kind_outranks_roads(kind: WayKind) -> bool {
    class_rank(kind, false) > class_rank(WayKind::Road, false)
}

/// The OSM z-order tags a way carries: `layer`, `bridge`, `tunnel`. Default (all zero /
/// false) is "ground level", which is what every untagged way and every synthetic way
/// gets — byte-identical ordering to before this type existed.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct OsmZ {
    /// The `layer` tag, already clamped to ±[`LAYER_CLAMP`]. `0` = absent or ground.
    pub layer: i8,
    /// `bridge=*` (anything but `no`).
    pub bridge: bool,
    /// `tunnel=*` (anything but `no`).
    pub tunnel: bool,
}

impl OsmZ {
    /// The layer this way actually paints on. `layer` is authoritative when present;
    /// `bridge`/`tunnel` only *imply* one when it is absent.
    #[must_use]
    pub fn effective_layer(self) -> i32 {
        if self.layer != 0 {
            i32::from(self.layer)
        } else if self.bridge {
            1
        } else if self.tunnel {
            -1
        } else {
            0
        }
    }

    /// **[`effective_layer`](Self::effective_layer) for an AREA** — lane GG #6.
    ///
    /// # The defect a bare `layer` on a polygon causes
    ///
    /// [`effective_layer`](Self::effective_layer) is the dominant term of [`way_rank`],
    /// multiplied by [`LAYER_STEP`] = `100_000` — a step chosen so no combination of band,
    /// class and tier can climb out of its own layer. That is exactly right for what
    /// `layer` exists to say: a deck over a river, a street under a square.
    ///
    /// It is a disaster for a **mis-tag**. One careless `layer=1` on an opaque polygon
    /// lifts it a hundred thousand rank units, past every road, path and label — and OSM
    /// is full of them. `landuse=grass layer=1` then paints over the motorway crossing it
    /// and no class order can answer, because the declared order genuinely says the grass
    /// is on top. That is a "terrain over roads" symptom that survives every fix to the
    /// GPU depth stack, because it is not a depth bug.
    ///
    /// # The rule
    ///
    /// An area honours `layer` **only when it also says why**. `bridge=*` or `tunnel=*`
    /// alongside the `layer` is a polygon declaring what it is — a deck, a passage, an
    /// underground car park — and those are the cases `layer` is for. A **bare** `layer`
    /// on an area says only *"put me somewhere else"* without saying what it is, and that
    /// is the shape of the mis-tag.
    ///
    /// LINES are deliberately untouched and keep [`effective_layer`](Self::effective_layer):
    /// a `layer=1` road really is a flyover and a `layer=-1` one really is a tunnel, which
    /// is what `paint_order_pixels::a_bridge_paints_over_the_water_and_a_tunnel_under_it`
    /// holds. The asymmetry is the point — a line with a `layer` is describing its own
    /// geometry, an area with a bare one is usually describing nothing.
    #[must_use]
    pub fn effective_layer_for_area(self) -> i32 {
        if self.bridge || self.tunnel {
            self.effective_layer()
        } else {
            0
        }
    }
}

/// A truthy OSM flag: present and not `no`/`false`/`0`.
fn flag_set(v: &str) -> bool {
    let v = v.trim();
    !v.is_empty() && !v.eq_ignore_ascii_case("no") && !v.eq_ignore_ascii_case("false") && v != "0"
}

/// Read `layer` / `bridge` / `tunnel` off a way's raw OSM tags.
///
/// Tolerant of the spellings that occur: `layer=+1`, `layer=1;2` (first wins),
/// `bridge=viaduct`, `tunnel=building_passage`. Anything unparsable is ground level —
/// a bad `layer` must never move a way, only fail to move it.
pub fn parse_osm_z<K: AsRef<str>, V: AsRef<str>>(tags: &[(K, V)]) -> OsmZ {
    let get = |k: &str| {
        tags.iter().find(|(tk, _)| tk.as_ref() == k).map(|(_, tv)| tv.as_ref())
    };
    let layer = get("layer")
        .and_then(|v| {
            let head = v.trim().split(';').next().unwrap_or("").trim();
            head.strip_prefix('+').unwrap_or(head).parse::<i32>().ok()
        })
        .map_or(0, |l| l.clamp(-LAYER_CLAMP, LAYER_CLAMP) as i8);
    OsmZ {
        layer,
        bridge: get("bridge").is_some_and(flag_set),
        tunnel: get("tunnel").is_some_and(flag_set),
    }
}

/// **The paint order of one drawable.** Sorted ascending: a larger key draws LATER,
/// i.e. on top.
///
/// The field order IS the comparison order (derived `Ord`), and every field is a pure
/// function of the feature — never of its position in an input vector. That is what
/// makes "swap the input order, get identical pixels" true by construction rather than
/// by review.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PaintKey {
    /// Layer · band · class · tier — see the module docs.
    pub rank: i32,
    /// **Area, largest first.** `!f32::to_bits(area)` of the way's Mercator bbox: for
    /// a non-negative `f32` the bit pattern is monotone in the value, so the
    /// complement sorts descending. A small footprint therefore paints over the big
    /// polygon it sits inside — the standard cartographic fallback for two fills that
    /// have nothing else to separate them, and the one that used to be "whoever was
    /// decoded last".
    pub area_desc: u32,
    /// Final, fully deterministic tie-break. Two ways with the same rank and the same
    /// bbox area still stack the same way on every frame and in every process.
    pub id: i64,
}

impl PaintKey {
    /// A key for a non-way AREA drawable (a landmass base polygon): band + the same
    /// largest-first area fallback a way gets, so two overlapping land polygons stack
    /// by size rather than by the order they were decoded in.
    #[must_use]
    pub fn area(band: i32, merc_area: f32, id: i64) -> Self {
        Self { rank: band, area_desc: !merc_area.max(0.0).to_bits(), id }
    }

    /// A key for a non-way drawable (a point marker, a label): band + tier only, with
    /// no area to compare.
    #[must_use]
    pub fn simple(band: i32, lod: Lod, id: i64) -> Self {
        Self { rank: band + tier_rank(lod), area_desc: u32::MAX, id }
    }
}

/// **The rank of one way** — the `rank` half of [`way_paint_key`], exposed because the
/// GPU/CPU seam has to ask "what is the lowest rank the GPU lane owns this frame?"
/// without building keys.
#[must_use]
pub fn way_rank(w: &Way) -> i32 {
    // **A rank the producer already computed wins** — lane GG #17. This is not a second
    // opinion about the paint order: the only way to fill `Way::rank` is to have called
    // THIS function, so the answer is the same answer, just not derived twice. korp's
    // server fills it (proto `MapPolyline.rank`) because every client was re-deriving it
    // per way per landing on the UI thread — `parse_osm_z` walking the tag list, then the
    // two arms below. Measured on oden: 9.77 ms of serial tag parse per 20 000-way
    // landing.
    if let Some(r) = w.rank {
        return r;
    }
    let is_area = w.fill.is_some();
    layer_term(w, is_area) + class_rank(w.style.kind, is_area) + tier_rank(w.style.lod)
}

/// **The `layer` term of a rank — the ONE place either rank function reads it** (lane
/// GG #6). `way_rank` and `way_draw_band` both computed
/// `effective_layer() * LAYER_STEP` inline, so the area rule had two places to land in
/// and one of them would eventually be missed. See
/// [`OsmZ::effective_layer_for_area`] for why an area is asked a different question.
fn layer_term(w: &Way, is_area: bool) -> i32 {
    let l = if is_area { w.z_order.effective_layer_for_area() } else { w.z_order.effective_layer() };
    l * LAYER_STEP
}

/// **The DRAW BAND of one way** — [`way_rank`] with the per-[`Lod`] tier term removed.
///
/// # Why a hybrid renderer needs this and not the rank
///
/// A GPU lane's draw is not a painter with a z; it is a *submission order*. `PaintKey`
/// decides the order **inside one submitted stream** (the compaction is ordered — see
/// `tests/cull_order.rs`) and has no way to reach across two of them. The lane therefore
/// has to submit one draw per *band*, and the band is the coarsest unit that loses
/// nothing: the tier, the area fallback and the id tie-break all still decide the order
/// within the band, because the stream inside a band is still sorted on the whole
/// [`PaintKey`].
///
/// MEASURED, oden / RTX 4090, 2026-08-23 (`tests/gpu_lane_paint_order.rs`): with the
/// lane submitting three fixed buckets instead — all fills, then all outlines, then all
/// lines — moving the SAME lake and building between two tiles changed **9 660 of 208 000
/// pixels (4.64 %)** and in one of the two arrangements the building was **not on screen
/// at all**. A `tunnel=yes` road under a lake painted on top of the lake in both.
///
/// Note what is deliberately NOT in the band: the tier. Splitting on the full rank would
/// give one draw per (layer, class, tier) triple — 4× the draws for an ordering the
/// stream already carries.
#[must_use]
pub fn way_draw_band(w: &Way) -> i32 {
    let is_area = w.fill.is_some();
    layer_term(w, is_area) + class_rank(w.style.kind, is_area)
}

/// **THE declared paint key of one way.** The single writer every lane sorts on.
#[must_use]
pub fn way_paint_key(w: &Way) -> PaintKey {
    // Mercator-unit bbox area. `[x0, y0, x1, y1]`, always non-negative.
    let area = (((w.bbox[2] - w.bbox[0]).max(0.0)) * ((w.bbox[3] - w.bbox[1]).max(0.0))) as f32;
    PaintKey { rank: way_rank(w), area_desc: !area.to_bits(), id: w.osm_id }
}

// ═════════════════════════════════════════════════════════════════════════════
// RANK AS DEPTH — lane MP-a, 2026-09-05.
//
// `PaintKey` orders the stream INSIDE one submitted stream and has no way to
// reach across two of them (see `way_draw_band`). The lane submits one
// `draw_indirect` per chunk and the tiled path iterates per tile, so a later
// tile's dark casing lands on an earlier tile's bright fill. MEASURED on an
// RTX 4090 2026-09-05, `gpu_lane_paint_order::
// which_tile_a_road_landed_in_cannot_decide_which_road_is_on_top`: the crossing
// pixel of a motorway and a residential came back [56, 78, 92] — neither the
// motorway [70, 198, 224] nor the residential [85, 98, 117], but the
// residential's CASING over the motorway's fill.
//
// No submission order fixes that in general: which tiles a camera holds is not
// known when the rank is assigned. Depth is the only thing that reaches across
// submissions — the rank rides in Z, the depth test decides, and which pass drew
// first stops mattering.
// ═════════════════════════════════════════════════════════════════════════════

/// The highest rank the ladder can produce: the top OSM layer, the label band.
const RANK_CEILING: i32 = LAYER_CLAMP * LAYER_STEP + LABEL_BAND;

/// **How far behind its own fill a casing sits, in depth units.**
///
/// Small on purpose, and asserted against the tightest CLASS gap by
/// `tests/paint_depth.rs`: a bias as wide as a class gap would sort a road's casing past
/// the class below it, which is the same defect this lane is fixing with the roles
/// swapped.
pub const CASING_DEPTH_BIAS: f32 = 1.0e-6;

/// **A [`way_rank`] as a depth in `0.0 ..= 1.0`**, for a `Less` depth test against a
/// buffer cleared to `1.0`: a HIGHER rank yields a SMALLER depth and therefore paints
/// closer.
///
/// `casing` pushes the value one [`CASING_DEPTH_BIAS`] further back, so a line's dark
/// outline sits behind the bright fill it outlines and still in front of the next rank
/// down.
///
/// The mapping is linear over the whole reachable rank range —
/// [`LANDMASS_BAND`] up to the top layer's [`LABEL_BAND`] — and **clamped**. A depth
/// outside the clip range is dropped by the rasteriser, and a way that silently vanishes
/// is worse than one in the wrong order: nothing on screen points back here.
#[must_use]
pub fn depth_of(rank: i32, casing: bool) -> f32 {
    let lo = f64::from(LANDMASS_BAND);
    let hi = f64::from(RANK_CEILING);
    let t = (f64::from(rank) - lo) / (hi - lo);
    // Inverted: rank up ⇒ depth down ⇒ closer.
    let d = 1.0 - t;
    let d = d as f32 + if casing { CASING_DEPTH_BIAS } else { 0.0 };
    d.clamp(0.0, 1.0)
}

/// **The depth a FILL's own ring outline is drawn at** — lane GG #1.
///
/// # Why this is not `depth_of(way_rank(w), true)`
///
/// A fill's outline is not a casing and does not belong behind the thing it outlines: it
/// **is** that fill's edge, and on this lane it is also the fill's only anti-aliasing
/// (`tests/fill_outline_aa.rs`). Put it one [`CASING_DEPTH_BIAS`] *behind* its own fill
/// and `Less` rejects it wherever the fill already wrote depth, which is everywhere the
/// ring is filled — the shoreline loses its edge and the polygon loses its AA.
///
/// So it sits one bias **in front**, and the band is [`way_draw_band`], not [`way_rank`].
/// That is the load-bearing half: the tile lane pins a whole band run of fills to
/// `depth_of(band, false)` through `set_viewport`, deliberately dropping the tier, and an
/// outline computed from the rank would carry a tier term its own fill does not have. The
/// two would disagree by up to a tier's worth of depth — enough for a coarse-tier ring's
/// outline to fall *behind* its fill and vanish, and for a fine-tier one to climb toward
/// the band above. The outline follows the plane its fill was actually pinned to.
///
/// The bias is the same magnitude a casing uses, for the same reason: the smallest step
/// that separates two things of one rank without reaching the rank next door.
///
/// # What it replaced
///
/// `0.0` — the CLOSEST plane the clip volume has, passed as the "no rank to give"
/// default of [`crate::gpu::line::LineExpander::push_pts`]. Harmless while the lane had
/// no depth buffer; the moment MP-a's depth pass landed it made every lake, park and
/// building outline the highest-priority ink on the map, beating every road drawn after
/// it. OSM landuse rings share their geometry with the road that bounds them, so that
/// edge lands ON the road's axis: lane GG #1, and the mechanism behind "roads overwritten
/// by landcover".
#[must_use]
pub fn fill_outline_depth(band: i32) -> f32 {
    (depth_of(band, false) - CASING_DEPTH_BIAS).clamp(0.0, 1.0)
}

/// **Pack a `side` (±1) and a depth (`0..=1`) into one `f32`** — lane MP-a.
///
/// # Why the vertex cannot simply grow
///
/// Depth has to be **per way**. The tile lane's draw is already band-major, so bands
/// order correctly across tiles — and the two-tile oracle still failed, because
/// [`way_draw_band`] deliberately drops the tier: a motorway and a residential share one
/// band. Inside a band the draw walks TILES, so a later tile's casing lands on an earlier
/// tile's fill. A per-draw uniform therefore cannot carry it.
///
/// And a new vertex field is not available: `LineVertex` is exactly 48 B, asserted at
/// compile time, and that size is load-bearing — the vertex layout, the chunk
/// partition and the bake format all rest on it.
///
/// `side` is `+1.0` or `-1.0`: **one bit of information in a whole `f32`**. So the depth
/// rides in its magnitude, `sign(side) · (1 + depth)`, and the shader pays one
/// `sign`/`abs` pair.
///
/// **Precision, checked rather than assumed:** in `[1, 2)` an `f32` step is
/// `2^-23 ≈ 1.19e-7`, so a depth survives to about that — comfortably finer than
/// [`CASING_DEPTH_BIAS`] (`1e-6`), which is what keeps a casing distinguishable from the
/// fill it outlines. `tests/side_carries_depth.rs` asserts it.
///
/// The magnitude starts at `1.0`, so the packed value never reaches `0`, where a sign
/// cannot be recovered.
#[must_use]
pub fn pack_side_depth(side: f32, depth: f32) -> f32 {
    let s = if side < 0.0 { -1.0f32 } else { 1.0 };
    s * (1.0 + depth.clamp(0.0, 1.0))
}

/// The `side` half of a [`pack_side_depth`] value: `+1.0` or `-1.0`.
#[must_use]
pub fn unpack_side(packed: f32) -> f32 {
    if packed < 0.0 { -1.0 } else { 1.0 }
}

/// The depth half of a [`pack_side_depth`] value, back in `0..=1`.
#[must_use]
pub fn unpack_depth(packed: f32) -> f32 {
    (packed.abs() - 1.0).clamp(0.0, 1.0)
}

#[cfg(test)]
mod tests {
    use super::*;

    fn tags(pairs: &[(&str, &str)]) -> Vec<(String, String)> {
        pairs.iter().map(|(k, v)| ((*k).to_string(), (*v).to_string())).collect()
    }

    /// **THE TIER SUB-RANK MUST FIT UNDER THE TIGHTEST CLASS GAP, and the number in
    /// the comment was not the tightest one.**
    ///
    /// `tier_rank`'s doc claimed "4 tiers × 10 fits inside the 100-unit class spacing".
    /// The AREA band does step by 100 (water 100, park 200, building 300, other 400).
    /// The LINE band does not: coastline `0`, water `50`. The real spacing is **50**, so
    /// the headroom is half what the comment says, and the point at which a tier
    /// sub-rank climbs into the class above is a 6th tier, not an 11th.
    ///
    /// A collision here is SILENT — a coastline of the coarsest tier and a river of the
    /// finest would simply share a rank and fall through to the area tie-break, which
    /// is a look defect nobody would trace back to this function. So the gap is measured
    /// off `class_rank` itself rather than restated, and the const assertion beside
    /// `TIER_STEP` turns a 6th tier into a build failure.
    #[test]
    fn the_tier_ladder_fits_under_the_measured_class_gap() {
        // Measured, not recited: the smallest step between adjacent class offsets that
        // `class_rank` actually produces, in either band.
        //
        // `WayKind::Rail` is deliberately NOT in this list. It is the one class that sits
        // INSIDE another's tier ladder — half a tier step under `Road`, so its gap to the
        // road offset is 5 by design and not a ladder that has to fit anything. Its order
        // is pinned by `a_railway_ranks_under_the_motorway_and_over_the_residential_street`.
        let mut ranks: Vec<i32> = Vec::new();
        for kind in [
            WayKind::Water,
            WayKind::Park,
            WayKind::Building,
            WayKind::Coastline,
            WayKind::Path,
            WayKind::Road,
            WayKind::Other,
        ] {
            for is_area in [true, false] {
                ranks.push(class_rank(kind, is_area));
            }
        }
        ranks.sort_unstable();
        ranks.dedup();
        let measured = ranks
            .windows(2)
            .map(|w| w[1] - w[0])
            // Band boundaries are not class gaps: AREA_BAND..LINE_BAND is 1000 apart and
            // the step across it says nothing about how much room a tier has.
            .filter(|d| *d < LINE_BAND - AREA_BAND)
            .min()
            .expect("class_rank produces more than one distinct offset");
        assert_eq!(
            measured, CLASS_STEP,
            "the declared class spacing ({CLASS_STEP}) is not the one `class_rank` \
             produces ({measured}) — the tier sub-rank's headroom is whatever the \
             TIGHTEST gap is, and the comment used to say 100 when the coastline→water \
             step is {measured}"
        );

        // …and the ladder that has to fit under it. The deepest tier is 0 and the
        // coarsest is `(LOD_COUNT-1) * TIER_STEP`, so THAT is the span, and it must be
        // strictly under the gap: equal would put the coarsest tier of one class exactly
        // on the finest tier of the next.
        let span = (crate::style::LOD_COUNT as i32 - 1) * TIER_STEP;
        assert_eq!(span, tier_rank(Lod::Country), "the span IS the coarsest tier's rank");
        assert_eq!(tier_rank(Lod::ALL[crate::style::LOD_COUNT - 1]), 0, "the deepest tier is the floor");
        assert!(
            span < CLASS_STEP,
            "{} tiers x {TIER_STEP} = {span} does not fit under a class gap of \
             {CLASS_STEP} — the coarsest tier of one class collides with the finest of \
             the next, silently",
            crate::style::LOD_COUNT
        );
    }

    #[test]
    fn layer_tag_dominates_class() {
        // A tunnel-layer road (layer = -2) must sink under the water it crosses, and a
        // bridge road must climb over it — whatever their classes say.
        // The `layer` term of a rank (`effective_layer * LAYER_STEP`, as `layer_term`
        // computes it) plus the class term.
        let rank = |layer: i32, kind: WayKind, is_area: bool| layer * LAYER_STEP + class_rank(kind, is_area);
        let ground_water = rank(0, WayKind::Water, true);
        let tunnel_road = rank(-2, WayKind::Road, false);
        let bridge_road = rank(1, WayKind::Road, false);
        assert!(tunnel_road < ground_water, "layer=-2 road belongs UNDER ground water");
        assert!(bridge_road > ground_water, "layer=1 road belongs OVER ground water");
    }

    #[test]
    fn bridge_implies_a_layer_only_when_layer_is_absent() {
        assert_eq!(parse_osm_z(&tags(&[("bridge", "yes")])).effective_layer(), 1);
        assert_eq!(parse_osm_z(&tags(&[("tunnel", "yes")])).effective_layer(), -1);
        // Explicit layer WINS — a bridge tagged layer=2 is on 2, not 3.
        assert_eq!(parse_osm_z(&tags(&[("bridge", "yes"), ("layer", "2")])).effective_layer(), 2);
        // `bridge=no` is not a bridge.
        assert_eq!(parse_osm_z(&tags(&[("bridge", "no")])).effective_layer(), 0);
        // Spellings that occur in real extracts.
        assert_eq!(parse_osm_z(&tags(&[("layer", "+1")])).layer, 1);
        assert_eq!(parse_osm_z(&tags(&[("layer", "-1;0")])).layer, -1);
        assert_eq!(parse_osm_z(&tags(&[("layer", "banana")])).layer, 0);
        assert_eq!(parse_osm_z(&tags(&[("layer", "99999")])).layer, LAYER_CLAMP as i8);
    }

    #[test]
    fn class_ladder_is_the_declared_one() {
        // Areas below lines; korp's OSM_WAY_LAYER_IDS order inside each band.
        let w = class_rank(WayKind::Water, true);
        let p = class_rank(WayKind::Park, true);
        let b = class_rank(WayKind::Building, true);
        let o_area = class_rank(WayKind::Other, true);
        let coast = class_rank(WayKind::Coastline, false);
        let road = class_rank(WayKind::Road, false);
        assert!(w < p && p < b && b < o_area, "water < landuse < buildings < other-area");
        assert!(o_area < coast, "every fill under every line of the same layer");
        assert!(coast < road, "coastline under roads");
    }

    #[test]
    fn a_country_road_outranks_a_city_road() {
        // The hierarchy `DrawFeature::z` documented and never produced: at the same
        // class, the more important tier paints ON TOP.
        assert!(tier_rank(Lod::Country) > tier_rank(Lod::City));
        assert!(tier_rank(Lod::City) > tier_rank(Lod::Detail));
        // ... and it stays inside its own class, never climbing into the next one.
        assert!(
            class_rank(WayKind::Road, false) + tier_rank(Lod::Country)
                < class_rank(WayKind::Other, false),
            "a tier bump must not promote a road out of its class"
        );
    }

    /// **A RAILWAY RUNS UNDER THE MOTORWAY AND OVER THE RESIDENTIAL STREET** — GG #28.
    ///
    /// # The defect
    ///
    /// `class_rank` had no arm for a railway. `classify_with` grew its `railway` arm in
    /// `railtier-1` (the ink, the tier) but stamped the style `WayKind::Other`, so every
    /// `railway=rail` in the country ranked at `LINE_BAND + 400` — the OVERLAY offset,
    /// above every road there is. On korp's "sweden · roads+rails" the Västra stambanan
    /// painted over the E4 at every crossing, and `line_kind_outranks_roads` answered
    /// `true` for it, so the 3D extruder laid it over the roads too.
    ///
    /// # The order, with its neighbours named
    ///
    /// osm2pgsql's default `z_order` puts `railway=rail` at 35 — level with `secondary`,
    /// under `primary`/`trunk`/`motorway`, over `tertiary` and `residential`. That is the
    /// Garmin look too, and it is INSIDE the road class's tier ladder, so a rail cannot
    /// be a class offset 50 apart from `Road`: it is [`RAIL_CLASS`], five units off the
    /// road ladder, and lands
    ///
    /// * trunk rail (`Lod::Country`) at `LINE_BAND + 235`, between Road·Region (1230:
    ///   `secondary`, `primary_link`, `motorway_link`) and Road·Country (1240:
    ///   `motorway`, `trunk`, `primary`);
    /// * urban rail (`Lod::District`) at `LINE_BAND + 215`, between Road·City (1210:
    ///   `residential`) and Road·District (1220: `tertiary`).
    ///
    /// RED before the arm: `railway=rail` measured 1440 against the motorway's 1240.
    #[test]
    fn a_railway_ranks_under_the_motorway_and_over_the_residential_street() {
        let pal = crate::MapPalette::cartographic(false);
        let mk = |id: i64, t: &[(&str, &str)]| {
            crate::Way::from_lonlat_with(id, &[(18.0, 59.0), (18.01, 59.0)], &tags(t), &pal)
                .expect("a 2-vertex line is a way")
        };
        let rail = mk(1, &[("railway", "rail")]);
        let motorway = mk(2, &[("highway", "motorway")]);
        let primary = mk(3, &[("highway", "primary")]);
        let secondary = mk(4, &[("highway", "secondary")]);
        let tertiary = mk(5, &[("highway", "tertiary")]);
        let residential = mk(6, &[("highway", "residential")]);
        let tram = mk(7, &[("railway", "tram")]);
        let footway = mk(8, &[("highway", "footway")]);
        let river = mk(9, &[("waterway", "river")]);

        // The claim of the row, then the exact neighbours.
        assert!(
            way_rank(&rail) < way_rank(&motorway),
            "a railway ({}) must run UNDER the motorway ({}) — it ranked in the overlay \
             offset above every road",
            way_rank(&rail),
            way_rank(&motorway)
        );
        assert!(
            way_rank(&rail) > way_rank(&residential),
            "a railway ({}) must run OVER a residential street ({})",
            way_rank(&rail),
            way_rank(&residential)
        );
        assert_eq!(way_rank(&motorway), way_rank(&primary), "fixture: motorway and primary share Road·Country");
        assert!(
            way_rank(&secondary) < way_rank(&rail) && way_rank(&rail) < way_rank(&motorway),
            "trunk rail ({}) sits between Road·Region ({}) and Road·Country ({})",
            way_rank(&rail),
            way_rank(&secondary),
            way_rank(&motorway)
        );
        assert!(
            way_rank(&residential) < way_rank(&tram) && way_rank(&tram) < way_rank(&tertiary),
            "urban rail ({}) sits between Road·City ({}) and Road·District ({})",
            way_rank(&tram),
            way_rank(&residential),
            way_rank(&tertiary)
        );
        // No rail tier ever TIES a road tier: a tie falls through to the bbox-area
        // tie-break, which is decode-order-shaped luck at every level crossing.
        for r in [&rail, &tram] {
            for road in [&motorway, &primary, &secondary, &tertiary, &residential] {
                assert_ne!(way_rank(r), way_rank(road), "a rail rank collided with a road rank");
            }
        }
        // Still a line of the basemap: over every path and every river, and NOT overlay
        // ink — the extruder's question, answered the same way.
        assert!(way_rank(&tram) > way_rank(&footway), "every rail runs over the footpath network");
        assert!(way_rank(&tram) > way_rank(&river), "every rail runs over the rivers");
        assert!(
            !line_kind_outranks_roads(rail.style.kind),
            "a railway is basemap, not overlay ink — `line_kind_outranks_roads` must say so"
        );
    }

    /// **The draw band is the rank WITHOUT the tier** — and both halves of that matter
    /// to the GPU lane, which submits one draw per band.
    ///
    /// RED, both ways:
    /// * add the tier back into `way_draw_band` and the first assertion fires — the lane
    ///   would then mint one group per (layer, class, TIER) triple, four times the draws
    ///   and four times the VRAM entries for an order the stream already carries;
    /// * drop the `effective_layer() * LAYER_STEP` term and the second fires — a tunnel
    ///   road would share a band with a ground road and land back above the water.
    #[test]
    fn the_draw_band_is_the_rank_with_the_tier_stripped() {
        let ll = vec![(18.0, 59.0), (18.01, 59.0)];
        let mk = |id: i64, tags: &[(&str, &str)]| {
            let t: Vec<(String, String)> =
                tags.iter().map(|(k, v)| ((*k).to_string(), (*v).to_string())).collect();
            crate::Way::from_lonlat_with(id, &ll, &t, &crate::MapPalette::cartographic(false))
                .expect("a 2-vertex line is a way")
        };
        // Same class, DIFFERENT tier: a motorway is `Country`, a residential street is
        // `City` (style.rs). They must share one band.
        let trunk = mk(1, &[("highway", "motorway")]);
        let street = mk(2, &[("highway", "residential")]);
        assert_ne!(trunk.style.lod, street.style.lod, "fixture: the two tiers must really differ");
        assert_eq!(
            way_draw_band(&trunk),
            way_draw_band(&street),
            "two tiers of the same class must share ONE band, or the lane pays 4x the draws"
        );
        // ... while the RANK still separates them, so nothing is lost inside the band.
        assert!(way_rank(&trunk) > way_rank(&street), "the tier still orders them by rank");

        // A tunnel road's band sinks below a ground WATER FILL's band. This is the pair
        // the GPU lane could not express while it submitted three fixed buckets.
        let tunnel = mk(3, &[("highway", "motorway"), ("tunnel", "yes")]);
        let lake = crate::Way::from_lonlat_with(
            4,
            &[(18.0, 59.0), (18.01, 59.0), (18.01, 59.01), (18.0, 59.01), (18.0, 59.0)],
            &[("natural".to_string(), "water".to_string())],
            &crate::MapPalette::cartographic(false),
        )
        .expect("a closed ring is a way");
        assert!(lake.fill.is_some(), "fixture: the lake must be a FILL");
        assert!(
            way_draw_band(&tunnel) < way_draw_band(&lake),
            "a tunnel road's band ({}) must sit UNDER a ground water fill's ({})",
            way_draw_band(&tunnel),
            way_draw_band(&lake)
        );
        // And a bridge's band sits above it, so the two are not merely both negative.
        let bridge = mk(5, &[("highway", "motorway"), ("bridge", "yes")]);
        assert!(way_draw_band(&bridge) > way_draw_band(&lake), "a bridge's band sits over the water");
    }

    /// **THE LANDMASS IS UNDER EVERY WAY THERE CAN BE — measured off `way_rank`, not
    /// off the constant it is supposed to bound.**
    ///
    /// The const assertion beside [`LANDMASS_BAND`] compares two constants. That is a
    /// real gate, but it is also exactly the shape LAW 2 warns about: if
    /// [`WAY_RANK_FLOOR`]'s expression ever stops matching what `way_rank` actually
    /// computes, both sides move together and the assertion stays green while the map
    /// goes white again.
    ///
    /// So this walks REAL ways through the real `way_rank`: every class, in both bands,
    /// at every tier, at the full negative `layer` clamp and as a `tunnel`. The number it
    /// compares against is the minimum those ways produce — never the constant.
    ///
    /// RED: put `LANDMASS_BAND` back to `-1_000` (the value that shipped 2026-08-22 to
    /// 2026-08-31) and the deepest way measures −799 890 against a landmass at −1 000.
    #[test]
    fn no_way_can_sink_below_the_landmass() {
        let pal = crate::MapPalette::cartographic(false);
        let ring = |id: i64, t: &[(&str, &str)]| {
            let t: Vec<(String, String)> =
                t.iter().map(|(k, v)| ((*k).to_string(), (*v).to_string())).collect();
            crate::Way::from_lonlat_with(
                id,
                &[(18.0, 59.0), (18.01, 59.0), (18.01, 59.01), (18.0, 59.01), (18.0, 59.0)],
                &t,
                &pal,
            )
            .expect("a closed ring is a way")
        };
        let ln = |id: i64, t: &[(&str, &str)]| {
            let t: Vec<(String, String)> =
                t.iter().map(|(k, v)| ((*k).to_string(), (*v).to_string())).collect();
            crate::Way::from_lonlat_with(id, &[(18.0, 59.0), (18.01, 59.0)], &t, &pal)
                .expect("a 2-vertex line is a way")
        };
        // Every class this crate can classify, as a fill AND as a line, sunk as deep as
        // OSM lets a way go: the full negative clamp, and the `tunnel` that implies −1.
        let classes: &[&[(&str, &str)]] = &[
            &[("natural", "water")],
            &[("landuse", "forest")],
            &[("building", "yes")],
            &[("natural", "coastline")],
            &[("highway", "motorway")],
            &[("highway", "footway")],
            &[("waterway", "river")],
            // `boundary=administrative` used to stand here as the CATCH-ALL case. It no
            // longer builds a way at all: `boundary` is not a key `classify_with` reads,
            // so `has_nothing_to_draw` refuses it at the constructor (lane SI — an
            // untagged kommungräns was being stroked in road ink across Riddarfjärden).
            // `railway=rail` takes its place: a real class, and the one whose ink korp
            // re-stamps from the network column.
            &[("railway", "rail")],
        ];
        let sinkers: &[&[(&str, &str)]] = &[
            &[("tunnel", "yes")],
            &[("layer", "-1")],
            &[("layer", "-8")],
            // Past the clamp: a vandalised value must not be able to reach further down
            // than `LAYER_CLAMP` says it can.
            &[("layer", "-99999")],
        ];
        let mut deepest = i32::MAX;
        let mut id = 1;
        for c in classes {
            for s in sinkers {
                let tags: Vec<(&str, &str)> = c.iter().chain(s.iter()).copied().collect();
                for w in [ring(id, &tags), ln(id + 1, &tags)] {
                    deepest = deepest.min(way_rank(&w));
                }
                id += 2;
            }
        }
        assert_ne!(deepest, i32::MAX, "the fixture must have ranked at least one way");
        // NON-VACUOUS: the sinkers must really sink. Without this the claim would pass
        // on a `parse_osm_z` that had stopped reading the tags at all — the state the
        // whole `layer`/`bridge`/`tunnel` term was introduced to leave.
        let ground = way_rank(&ring(999, &[("natural", "water")]));
        assert!(
            deepest < ground - LAYER_STEP / 2,
            "fixture: the negative-layer ways must really sink (deepest {deepest}, a \
             ground water fill {ground}) — otherwise this test bounds nothing"
        );
        assert!(
            LANDMASS_BAND < deepest,
            "the landmass ({LANDMASS_BAND}) must sit UNDER the deepest way `way_rank` can \
             produce ({deepest}). It did not between 2026-08-22 and 2026-08-31, and the \
             cost was the GPU lane's callback slot dropping below the land silhouette: one \
             `tunnel=yes` in the loaded set and the white land painted over the whole map."
        );
        // …and the declared floor is the measured one, not merely below it. A
        // `WAY_RANK_FLOOR` that drifted far under the truth would keep the assertion
        // above green while quietly meaning nothing.
        assert!(
            WAY_RANK_FLOOR <= deepest && deepest - WAY_RANK_FLOOR < LAYER_STEP,
            "WAY_RANK_FLOOR ({WAY_RANK_FLOOR}) must be the tight floor under the deepest \
             measured way ({deepest}), within one LAYER_STEP — otherwise it is a number \
             that happens to be small, not the floor it claims to be"
        );
    }

    #[test]
    fn larger_area_sorts_under_smaller() {
        let big = !1.0_f32.to_bits();
        let small = !0.001_f32.to_bits();
        assert!(big < small, "the bigger polygon must sort FIRST, i.e. be painted under");
        // And zero-area degenerates still sort last rather than panicking.
        assert!(small < !0.0_f32.to_bits());
    }
}