            /* ── the queue window, across the bridge ───────────────────
               Round forty-six put a bounded window of the queue into every
               card update — the current item and ten either side, each with
               its id, title, artist, album, duration and art key, plus where
               the current one sits among them — and left MediaService
               ignoring every bit of it, because media3's
               SimpleBasePlayer.getState() will want a playlist and an index,
               and that data should be a round old before anything depends on
               it. Which means every check above this one is blind to it: a
               window that arrived empty, an index off by one, or a field the
               bridge dropped because a key was spelled the wrong way would
               each look exactly like success.

               So: what the phone SENT — __ss.card, the mirror
               media.svelte.js keeps beside xfernote's — against what the
               plugin LOGGED on the far side, field for field, through a next
               and a previous. Field for field is the point: a camelCase key
               spelled snake_case arrives as nothing at all on both hops of
               this bridge, with no error anywhere, so `art` (the only
               camelCase field an entry has) is compared as well as the size
               and the index.

               ARMED TO A KNOWN ROW, index one, rather than to wherever the
               walk left off. Three things fall out of that and every one of
               them is load-bearing: there is a row on either side, so next()
               steps instead of stopping at the end and prev() steps instead
               of seeking to zero at the top; the track starts at zero, so
               prev() is still a step two and a half seconds later rather
               than the seek it becomes past five, and no track ends
               underneath the three readings; and while the queue index is
               under ten the window's own index IS the queue index, because
               the slice starts at zero and nothing is clamped off the front
               — which is what makes `got.i` comparable to `base` below
               without recomputing the arithmetic here. Nothing is added,
               removed or reordered: this is the queue the walk has been
               playing all along, stepped one row forward and one row back
               inside itself.

               Not skipped when it cannot be armed: a queue shorter than
               three rows, or repeat-one — under which next() seeks to zero
               instead of stepping — FAILS, with `armed` in the message
               saying which. A check that passes by not running is the thing
               this walk is most careful never to be. */
            const CARD = `(function () { var s = window.__ss; if (!s || !s.card || !s.player) return null; var c = s.card, p = s.player; return { u: c.updates, n: c.window, i: c.index, art: c.art, at: c.at, qi: p.qi, title: p.track ? p.track.title : '' }; })()`;
            const armed = await cdp.evaluate(`(function () { var p = window.__ss && __ss.player; return p ? { n: p.queue.length, qi: p.qi, rep: p.repeat } : null; })()`);
            const base = 1;
            const room = (armed?.n ?? 0) >= 3 && armed.rep !== 2;
            const wins = [];
            if (room) {
                await cdp.evaluate(`__ss.playQueueAt(${base})`);
                await sleep(2500);
                wins.push(["here", await cdp.evaluate(CARD), mediaWindow()]);
                await cdp.evaluate(`__ss.next()`);
                await sleep(2500);
                wins.push(["next", await cdp.evaluate(CARD), mediaWindow()]);
                await cdp.evaluate(`__ss.prev()`);
                await sleep(2500);
                wins.push(["prev", await cdp.evaluate(CARD), mediaWindow()]);
            }
            /* each reading: the window SENT is a real one — at least two
               entries, the index inside it, and the entry AT the index is the
               track on the bar, which is what an off-by-one fails even when
               the counts agree — and what the plugin LOGGED is that same
               window, field for field. */
            const sane = ([, sent, got]) => !!sent && sent.n >= 2 && sent.i >= 0 && sent.i < sent.n
                && !!sent.at && sent.at === sent.title
                && got.n === sent.n && got.i === sent.i && got.art === sent.art
                && got.at === String(sent.at).trim();
            const winOk = room && wins.length === 3 && wins.every(sane)
                /* and it MOVED. The queue index steps forward and back; the
                   LOGGED window index steps with it, which is the assertion
                   an off-by-one or a frozen index dies on. And each reading
                   is a FRESH one at both ends — the phone pushed again
                   (`u`) and the plugin logged again (`lines`) — because a
                   prev() that lands back on the row it started from reads
                   identically to a stale line otherwise. */
                && wins[0][1].qi === base && wins[1][1].qi === base + 1 && wins[2][1].qi === base
                && wins[0][2].i === base && wins[1][2].i === base + 1 && wins[2][2].i === base
                && wins[1][1].u > wins[0][1].u && wins[2][1].u > wins[1][1].u
                && wins[1][2].lines > wins[0][2].lines && wins[2][2].lines > wins[1][2].lines;
            if (!winOk) problems.push("EXPECT queue-window " + JSON.stringify({ armed, base, wins }));
            console.log((winOk ? "  ok  " : " FAIL ") + "queue-window".padEnd(16) + " "
                + JSON.stringify({ armed, seen: wins.map(([k, sent, got]) => [k, sent && sent.qi, got.n, got.i, got.art, got.at]) }));
