/* Styles for index.html. Split out of a 240-line <style> block so the sheet can be edited, diffed
   and cached on its own. Load order matters: this comes before the modules, so the layout is
   settled by the time app.js measures anything (frameWorld reads the stage rect on boot).
   Not versioned with ?v=<commit>, matching src/*.js -- the HTML that names them is fetched
   no-store, so a deploy picks both up together. */
/* ---- tokens ------------------------------------------------------------------------------------
   Only values the sheet ACTUALLY repeats, substituted by exact value, so nothing here changes how
   the page looks. The three blues stay three names rather than one: they are the selected-panel
   fill, its border and the map-symbol accent, and collapsing them would silently restyle two of
   the three. Bare geometry (most px) is deliberately NOT tokenised -- a shared name for two
   numbers that merely happen to be equal is a false claim about the design. */
:root {
    --ink: #e8e8e8;                 /* body text on the dark chrome */
    --ink-dim: #cbd5e1;             /* the same text, one step back: unselected controls */
    --ink-link: #7fa8ff;            /* links and the boot line */
    --bg: #04070c;                  /* the page, and the sea behind a sparse pyramid */

    --accent: #3b6fd4;              /* the map-symbol / selected-outline blue */
    --accent-bg: #2d6cdf;           /* fill of a control that IS the current choice */
    --accent-line: #5b8ee8;         /* its border, and the hover hairline */

    /* Floating chrome: one glass recipe for the fabs, the cards, the map picker and the tile. */
    --glass: rgba(22,24,28,.86);
    --glass-hover: rgba(42,46,54,.94);
    --glass-blur: blur(8px);
    --shadow: 0 2px 12px rgba(0,0,0,.5);

    /* Hairlines, at the three alphas the sheet distinguishes: edge, panel, divider. */
    --line: rgba(255,255,255,.14);
    --line-soft: rgba(255,255,255,.12);
    --line-faint: rgba(255,255,255,.09);

    --inset: 12px;                  /* every floating control's distance from its corner */

    /* Corner radius, three steps and nothing between. The sheet had eleven values from 4 to 20 px,
       assigned per element, which read as eleven slightly different shapes rather than one family.
       Every value also comes DOWN: the chrome was too round. A checkbox at 12 px was almost a
       circle, and #prep's 20 px pill was rounder than the panels it sat over.
         sm  a control inside a panel: inputs, list rows, small buttons
         md  a panel or a floating control: cards, fabs, the readout, the map picker
         lg  the one large object, the base-map tile
       50% is not part of the scale: a marker dot and a radio are circles, not rounded boxes. */
    --r-sm: 3px;
    --r-md: 6px;
    --r-lg: 8px;
}

* {
    box-sizing: border-box;
}

html,body {
    margin: 0;
    height: 100%;
    height: 100dvh;
    overflow: hidden;
    overscroll-behavior: none;
    background: #04070c;
    color: var(--ink);
    -webkit-text-size-adjust: 100%;
    font: 13px system-ui,sans-serif;
}

/* touch-action:none — pan/pinch are ours (pointer events). Without it the browser claims the
   gesture, cancels the pointer stream mid-drag, and a downward pan triggers pull-to-refresh. */
#stage {
    position: absolute;
    inset: 0;
    overflow: hidden;
    user-select: none;
    cursor: crosshair;
    touch-action: none;
    -webkit-touch-callout: none;
}

#view {
    position: absolute;
    transform-origin: 0 0;
}

#view img,#view canvas {
    position: absolute;
    top: 0;
    left: 0;
    image-rendering: auto;
    -webkit-user-drag: none;
    user-select: none;
}

/* the world square is a fixed D x D box; it used to be sized by the base <img> that lived in it */
#view {
    width: var(--d);
    height: var(--d);
    background: var(--sea,#04070c);
}

#sat-tiles,#map-tiles {
    position: absolute;
    top: 0;
    left: 0;
    display: none;
}

/* tile pyramids over their base */
#sat-tiles.on,#map-tiles.on {
    display: block;
}

#sat-tiles img,#map-tiles img {
    position: absolute;
    -webkit-user-drag: none;
    user-select: none;
    image-rendering: auto;
}

/* Relief: a hillshade + hypsometric tint + sea tint, computed in GL from the world tiles the app
   already holds, and blended over the imagery by the COMPOSITOR rather than baked into it. Doing
   it here rather than in the tile bake keeps it off the panorama, which takes its colour from the
   same satellite tiles and would otherwise get a fixed top-down light painted into a horizon view.
   soft-light because relief has to both brighten and darken; multiply could only darken. */
#relief {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
    z-index: 10;
    mix-blend-mode: soft-light;
    display: none;
}

#relief.on {
    display: block;
}

#obj-tiles {
    position: absolute;
    top: 0;
    left: 0;
    display: none;
}

/* world-objects overlay pyramid */
#obj-tiles.on {
    display: block;
}

#obj-tiles canvas {
    position: absolute;
    -webkit-user-drag: none;
    user-select: none;
    image-rendering: pixelated;
}

#ov,#mk {
    pointer-events: none;
}

/* transform-origin pinned to the centre (the default, but load-bearing here): apply() counter-
   scales this against the map zoom so it stays 14 px, and any other origin would drift it. */
#mk {
    position: absolute;
    width: 14px;
    height: 14px;
    margin: -7px 0 0 -7px;
    border: 2px solid #ff3;
    border-radius: 50%;
    background: rgba(255,255,0,.3);
    display: none;
    transform-origin: 50% 50%;
}

/* The pano's view cone. Centred on the pin and rotated by fovMark; the wedge itself starts outside
   the 14 px dot, so the marker still reads as a pin with a beam on it. */
#mk-fov {
    position: absolute;
    left: 50%;
    top: 50%;
    margin: -50px 0 0 -50px;
    overflow: visible;
    display: none;
}

#boot {
    position: absolute;
    inset: 0;
    z-index: 30;
    background: #04070c;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #8ab4ff;
    font: 12px ui-monospace,monospace;
}

/* floating controls */
#dock {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 20;
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: flex-end;
}

/* Map picker: one button per baked map, top LEFT, opposite the tool dock. Half again the size of
   a dock control -- it names where you are, which is read at a glance and pressed rarely.
   Hidden while only one map is built. */
#mapsel {
    position: absolute;
    top: 12px;
    left: 12px;
    z-index: 20;
    display: flex;
    gap: 8px;
}

#mapsel:empty {
    display: none;
}

#mapsel button {
    padding: 7px 17px;
    border-radius: var(--r-md);
    cursor: pointer;
    background: var(--glass);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: 1px solid var(--line-soft);
    box-shadow: var(--shadow);
    color: var(--ink-dim);
    font: 600 18px system-ui;
}

@media (hover:hover) {
    #mapsel button:hover {
        background: var(--glass-hover);
        color: #fff;
    }

}

#mapsel button.on {
    background: var(--accent-bg);
    border-color: var(--accent-line);
    color: #fff;
    cursor: default;
}

/* Base-map toggle: ONE tile, showing the layer you would switch TO. Two layers, so a picker would
   always be one redundant choice wide, and the thumbnail carries it -- no caption. */
/* Bottom left, riding above the pano/profile strip like the readouts do, so a taller strip never
   covers it. 93 px: half again the old dock tile, now that it stands on its own. */
#basetile {
    position: absolute;
    left: 12px;
    bottom: calc(var(--strip,0px) + 12px);
    z-index: 20;
    width: 93px;
    cursor: pointer;
    border-radius: var(--r-lg);
    overflow: hidden;
    border: 1px solid var(--line);
    box-shadow: var(--shadow);
    background: #222;
}

#basetile:empty {
    display: none;
}

#basetile img {
    width: 100%;
    aspect-ratio: 1/1;
    object-fit: cover;
    display: block;
}

@media (hover:hover) {
    #basetile:hover {
        border-color: var(--accent-line);
    }

}

.fab {
    width: 42px;
    height: 42px;
    border-radius: var(--r-md);
    background: var(--glass);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    color: var(--ink);
    border: 1px solid var(--line-soft);
    box-shadow: var(--shadow);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* hover styling only where a pointer can actually hover — on touch it sticks after a tap */
@media (hover:hover) {
    .fab:hover {
        background: var(--glass-hover);
        color: #fff;
    }

}

/* .on = this button's panel is showing */
.fab.on {
    background: #2c3d5e;
    color: #fff;
    border-color: var(--accent);
}

.fab svg {
    width: 22px;
    height: 22px;
    fill: currentColor;
    display: block;
}

/* both cards share one anchor and flow in a column: open cards stack, hidden ones take no space */
#cards {
    position: absolute;
    z-index: 19;
    top: 12px;
    right: 64px;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 8px;
    pointer-events: none;
}

.card {
    pointer-events: auto;
    min-width: 246px;
    padding: 11px 13px 13px;
    border-radius: var(--r-md);
    background: rgba(18,20,24,.92);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    border: 1px solid rgba(255,255,255,.1);
    box-shadow: 0 8px 28px rgba(0,0,0,.55);
}

.card.hidden {
    display: none;
}

/* about / info card — a bit of pop */
#card-info {
    max-width: 296px;
}

.info-hdr {
    display: block;
    text-align: center;
    text-decoration: none;
    color: inherit;
    cursor: pointer;
}

@media (hover:hover) {
    .info-hdr:hover .info-logo {
        transform: scale(1.03);
        box-shadow: 0 6px 22px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.16),0 0 40px rgba(224,178,58,.4);
    }

    .info-hdr:hover .info-sub b {
        color: #ffbf3a;
    }

}

.info-logo {
    display: block;
    width: 140px;
    height: 140px;
    margin: 0 auto 10px;
    border-radius: 50%;
    transition: box-shadow .15s,transform .15s;
    box-shadow: 0 6px 22px rgba(0,0,0,.55),0 0 0 1px var(--line-faint),0 0 30px rgba(224,178,58,.15);
}

.info-hd {
    font: 800 27px system-ui;
    letter-spacing: -.5px;
    margin: 0 0 3px;
    line-height: 1;
    background: linear-gradient(90deg,#ffbf3a,#ff6a4d);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

.info-hd span {
    -webkit-text-fill-color: var(--ink-link);
    color: var(--ink-link);
}

.info-sub {
    margin: 0 0 11px;
    color: #cfd5de;
    font-size: 12.5px;
    line-height: 1.55;
}

.info-sub b {
    color: #fff;
}

.info-cta {
    display: inline-block;
    margin: 0 0 4px;
    padding: 7px 14px;
    border-radius: var(--r-sm);
    font: 600 12px system-ui;
    color: #fff;
    text-decoration: none;
    background: linear-gradient(90deg,var(--accent),#6a5ae0);
    box-shadow: 0 3px 12px rgba(74,90,224,.45);
    transition: filter .12s,transform .12s;
}

@media (hover:hover) {
    .info-cta:hover {
        filter: brightness(1.12);
        transform: translateY(-1px);
    }

}

#card-info h4 {
    margin: 14px 0 5px;
    font: 700 10px system-ui;
    letter-spacing: .8px;
    text-transform: uppercase;
    color: var(--ink-link);
}

.info-src {
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: 12px;
    line-height: 1.75;
    color: #c2c8d1;
}

.info-src b {
    color: #eef1f5;
}

.info-src a,.info-sub a {
    color: #8ab4ff;
    text-decoration: none;
}

@media (hover:hover) {
    .info-src a:hover,.info-sub a:hover {
        text-decoration: underline;
    }

}

.info-foot {
    margin: 13px 0 0;
    padding-top: 10px;
    font-size: 11.5px;
    color: #9aa3ad;
    border-top: 1px solid var(--line-faint);
}

.info-foot b {
    color: #ffbf3a;
}

.info-ver {
    margin: 8px 0 0;
    font: 11px ui-monospace,monospace;
    color: #6b7480;
    text-align: center;
}

/* search */
#card-search {
    width: min(300px,calc(100vw - 88px));
}

#q {
    width: 100%;
    background: #1b1e24;
    color: #eee;
    border: 1px solid rgba(255,255,255,.16);
    border-radius: var(--r-sm);
    padding: 7px 9px;
    font: 13px system-ui;
    outline: none;
}

#q:focus {
    border-color: var(--accent);
}

#q::-webkit-search-cancel-button {
    filter: invert(.6);
}

#q-list {
    list-style: none;
    margin: 8px 0 0;
    padding: 0;
    max-height: 44vh;
    overflow-y: auto;
}

#q-list li {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 6px 7px;
    border-radius: var(--r-sm);
    cursor: pointer;
    color: #dfe3e8;
    font-size: 12.5px;
    line-height: 1.25;
}

#q-list li .t {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

#q-list li .k {
    flex: none;
    font: 10px system-ui;
    letter-spacing: .3px;
    text-transform: uppercase;
    color: #7b838d;
}

#q-list li svg {
    flex: none;
    width: 16px;
    height: 16px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
    color: #8ab4ff;
}

#q-list li.on {
    background: var(--accent);
    color: #fff;
}

#q-list li.on .k {
    color: #cfe0ff;
}

#q-list li.on svg {
    color: #fff;
}

@media (hover:hover) {
    #q-list li:not(.on):hover {
        background: rgba(255,255,255,.07);
    }

}

#q-none {
    margin-top: 9px;
    color: #7b838d;
    font-size: 12px;
}

.card h3 {
    margin: 2px 0 7px;
    font: 600 10.5px system-ui;
    letter-spacing: .7px;
    text-transform: uppercase;
    color: var(--ink-link);
}

.card .row {
    display: flex;
    align-items: center;
    gap: 7px;
    margin: 9px 0 0;
}

.card label {
    color: #d2d2d2;
    margin: 0;
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    white-space: nowrap;
}

.card input[type=number] {
    width: 58px;
    background: #222;
    color: #eee;
    border: 1px solid #444;
    border-radius: var(--r-sm);
    padding: 3px 5px;
}

/* checkboxes -> toggle sliders (matches the blue accent of the segmented controls) */
.card input[type=checkbox] {
    appearance: none;
    -webkit-appearance: none;
    flex: none;
    position: relative;
    width: 40px;
    height: 23px;
    border-radius: var(--r-sm);
    background: #3a3f47;
    border: 1px solid var(--line);
    cursor: pointer;
    transition: background .15s;
    margin: 0;
}

.card input[type=checkbox]::before {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 17px;
    height: 17px;
    border-radius: 50%;
    background: #cdd3dc;
    box-shadow: 0 1px 2px rgba(0,0,0,.5);
    transition: transform .15s,background .15s;
}

.card input[type=checkbox]:checked {
    background: var(--accent);
    border-color: var(--accent);
}

.card input[type=checkbox]:checked::before {
    transform: translateX(17px);
    background: #fff;
}

.card label:has(input[type=checkbox]) {
    justify-content: space-between;
    width: 100%;
}

.seg {
    display: flex;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    overflow: hidden;
    margin-top: 2px;
}

.seg label {
    flex: 1;
    justify-content: center;
    padding: 6px 4px;
    color: #bbb;
    font-size: 12px;
}

@media (hover:hover) {
    .seg label:hover {
        background: rgba(255,255,255,.06);
    }

}

.seg label:has(input:checked) {
    background: var(--accent);
    color: #fff;
}

.seg input {
    display: none;
}

/* vehicle picker: icons rather than words — four labels do not fit as text at this card
   width, and the glyphs are read faster than "Truck". currentColor so the checked state
   inherits the same white the text labels get. */
.seg label svg {
    width: 22px;
    height: 22px;
    display: block;
    margin: 0 auto;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

#prep {
    position: absolute;
    left: 50%;
    top: 16px;
    transform: translateX(-50%);
    z-index: 16;
    display: none;
    align-items: center;
    gap: 9px;
    padding: 8px 15px;
    border-radius: var(--r-md);
    background: rgba(18,20,24,.92);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: 1px solid rgba(224,178,58,.4);
    color: #e0b23a;
    font: 12px system-ui;
    box-shadow: 0 4px 16px rgba(0,0,0,.5);
}

#prep.on {
    display: flex;
}

#prep .dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #e0b23a;
    animation: prep-pulse 1s ease-in-out infinite;
}

@keyframes prep-pulse {
    0%,100% {
        opacity: .25;
        transform: scale(.8);
    }

    50% {
        opacity: 1;
        transform: scale(1);
    }

}

/* The pano and the elevation profile share the bottom strip. Only one tool is open at a time,
   so they can never both want it. */
#pano,#prof {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 180px;
    z-index: 14;
    display: none;
    touch-action: none;
    background: #0a0d12;
    border-top: 1px solid var(--line);
    box-shadow: 0 -6px 22px rgba(0,0,0,.55);
}

#pano {
    cursor: grab;
}

#pano:active {
    cursor: grabbing;
}

/* the pano/map separator: drag to change how much vertical angle the strip shows */
#pano-grip {
    position: absolute;
    left: 0;
    right: 0;
    height: 9px;
    z-index: 15;
    display: none;
    cursor: ns-resize;
    background: rgba(255,255,255,.10);
    border-top: 1px solid rgba(255,255,255,.18);
}

#pano-grip:hover {
    background: rgba(255,255,255,.22);
}

#pano-grip.on {
    display: block;
}

#prof {
    cursor: crosshair;
}

#pano.on,#prof.on {
    display: block;
}

/* route planner */
.prefrow {
    display: flex;
    align-items: center;
    gap: 9px;
    margin: 6px 0 0;
}

.prefrow input[type=range] {
    flex: 1;
    accent-color: var(--accent);
    min-width: 0;
}

/* Both preference sliders are nameless, with their anchor labels above the track
   (roads · fields · forest / easy · rough). Mid-track is neutral on each. */
.coverhdr {
    display: flex;
    justify-content: space-between;
    margin: 9px 2px -1px;
    font: 11px system-ui;
    letter-spacing: .3px;
    color: #aeb6bf;
}

.coverrow {
    margin: 0;
}

.coverrow input[type=range] {
    flex: 1;
    accent-color: var(--accent);
    min-width: 0;
}

/* Fixed width: the status line changes length on every plan ("planning…" -> a full
   readout -> an error), and a shrink-to-fit card visibly flaps as it does. Clamped on
   narrow screens so it still clears the 64 px dock offset. */
#card-route {
    width: min(300px,calc(100vw - 88px));
}

/* debug overlay: sequential ramp, dark->light, single hue (orange — blue is the route) */
#route-dbg {
    position: absolute;
    left: 0;
    top: 0;
    image-rendering: pixelated;
    pointer-events: none;
    z-index: 11;
}

/* the route tool's panel is closed: hide what it drew without forgetting it. A class on #view
   rather than inline styles, so it composes with route-dbg's own hidden attribute. */
/* Closing the panel hides the DEBUG layer only. The measurement/route line and its two dots stay
   on the map until explicitly cleared: they are a result you asked for, not a property of a panel
   being open, and needing the tool open to keep seeing your own measurement is backwards. */
#view.route-off #route-dbg {
    display: none;
}

/* Visible but INERT while the tool is closed: the dots keep their fat invisible hit targets, and
   with the flashlight open a click near one would grab a dot instead of placing an observer. */
#view.route-off #route-svg circle {
    pointer-events: none;
}

#dbg-legend {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 7px;
    font: 10.5px ui-monospace,monospace;
    color: #8b949e;
}

#dbg-legend i {
    flex: 1;
    height: 8px;
    border-radius: var(--r-sm);
    border: 1px solid var(--line);
    background: linear-gradient(90deg,#6b2710,#a8421d,#d95926,#ec8760,#f5b79f,#fbdfd4);
}

#route-status {
    margin-top: 11px;
    padding-top: 9px;
    border-top: 1px solid var(--line-faint);
    font: 12px ui-monospace,monospace;
    color: var(--ink-dim);
    line-height: 1.5;
    overflow-wrap: anywhere;
}

#route-status.warn {
    color: #e0b23a;
}

#route-status .dim {
    color: #8b949e;
}

#route-model {
    margin-top: 9px;
    padding-top: 7px;
    border-top: 1px solid var(--line-faint);
}

table.rm {
    width: 100%;
    border-collapse: collapse;
    font: 10.5px ui-monospace,monospace;
    color: #9aa9b8;
}

table.rm td {
    padding: 1px 0;
    vertical-align: top;
}

table.rm td:first-child {
    color: #6b7480;
    white-space: nowrap;
    padding-right: 8px;
    width: 1%;
}

table.rm .rm-sec td {
    color: #7fd39a;
    font-weight: 600;
    padding-top: 5px;
}

table.rm .rm-sec:first-child td {
    padding-top: 0;
}

.rm-p {
    color: #7fd39a;
}

.rm-a {
    color: #d98f6b;
}

#route-acts {
    display: flex;
    gap: 6px;
    margin: 0 0 10px;
}

#route-ctl.off {
    display: none;
}

/* vehicle picker and Reverse share a line: Reverse is a route input like the vehicle is, and it
   is an icon so it costs no width worth giving its own row. */
.vehrow {
    display: flex;
    align-items: stretch;
    gap: 6px;
    margin-top: 2px;
}

.vehrow .seg {
    flex: 1;
    margin-top: 0;
}

#ra-reverse {
    appearance: none;
    flex: none;
    width: 38px;
    background: #2a2f38;
    border: 1px solid #3a414d;
    border-radius: var(--r-sm);
    color: #bbb;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

#ra-reverse:hover {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

#ra-reverse svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
    display: block;
}

#route-acts:empty,#route-acts.off {
    display: none;
}

#route-acts button {
    appearance: none;
    flex: 1;
    background: #2a2f38;
    border: 1px solid #3a414d;
    border-radius: var(--r-sm);
    color: var(--ink);
    padding: 6px 8px;
    font: inherit;
    font-size: 12px;
    cursor: pointer;
}

#route-acts button:hover {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

/* the view you are already looking at: shown as selected, and inert */
#route-acts button.on {
    background: #2c3d5e;
    border-color: var(--accent);
    color: #fff;
    cursor: default;
}

/* nothing placed yet: disabled rather than hidden, so the row keeps its height and does not reflow */
#route-acts button:disabled {
    opacity: .4;
    cursor: default;
}

#route-acts button:disabled:hover {
    background: #2a2f38;
    border-color: #3a414d;
    color: var(--ink);
}

#readout {
    position: absolute;
    left: 117px;
    bottom: calc(var(--strip,0px) + 12px);
    z-index: 15;
    padding: 6px 10px;
    border-radius: var(--r-md);
    background: rgba(18,20,24,.82);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: 1px solid rgba(255,255,255,.1);
    font: 12px ui-monospace,monospace;
    color: var(--ink-dim);
    display: none;
}

/* The two ?dbg readouts: one line each, same dark bar, each along the BOTTOM of the panel it
   describes -- the map's rides up with the strip (panoResize keeps --strip in sync) so the strip
   never covers it, the pano's sits on the strip's own bottom edge. The pano line used to be
   painted onto the pano canvas in bright green, which put it halfway up the panel, at texture
   scale, and inside the pixels readPixels copies back. */
#dbg-readout,#pano-dbg {
    position: absolute;
    left: 0;
    right: 0;
    z-index: 16;
    padding: 4px 10px;
    pointer-events: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    background: rgba(8,10,14,.85);
    font: 11px ui-monospace,monospace;
    color: #8fd3a0;
    letter-spacing: .02em;
    display: none;
}

#dbg-readout {
    bottom: var(--strip,0px);
}

#pano-dbg {
    bottom: 0;
}
