    /* ── round forty: the four steps that could not fail ───────────────
       `library-ambience`, `queue`, `lyrics` and `community` have been
       named phone steps with no key in this map since the rounds that
       wrote them. The driver reads `expect[s.name] ? expect[s.name](info)
       : true`, so each one was a screenshot that always passed — four of
       eighty-eight. All four have a mock expectation; none had a phone
       one. Each is written to hold against Kyle's own library rather than
       a fixture. */
    "library-ambience": (i) => i.title.startsWith("Your library") && i.amb.includes("on:img"),
    queue: (i) => i.sheet.includes("up") && i.qFace,
    /* the walked track may genuinely have no words on the device, so this
       asks for the face and any one of its three honest states */
    lyrics: (i) => i.sheet.includes("up") && (i.lyrLines >= 1 || !!i.lyrNote || i.lyrTools),
    /* tolerant of the sign-in card, which is what a signed-out phone shows
       here — but NOT of a toast: a sign-in that failed raises one on this
       screen, and that is a finding rather than a step to loosen */
    community: (i) => i.title.startsWith("Community") && !i.toast,
    /* ── the walk's own playlist, on real SQLite ─────────────────────
       The row count is stashed by the sheet step rather than assumed: the
       playlist is made out of whichever record the walk picked, so its
       length is his library's business — and a probe that read nothing
       would otherwise pass every clause below it. */
    "playlist-row-sheet": (i) => { globalThis.__plN = i.plrows; return i.half.includes("up") && /Remove from playlist/.test(i.halfText); },
    "playlist-removed": (i) => i.plrows === globalThis.__plN - 1 && /Removed/.test(i.notice) && /Undo/.test(i.announce),
    /* the undo stash round-tripped through the real backend for the first
       time: the row is back, in the place it was taken from. `__pl0` is
       the order `playlist-drag-arm` stashed before the two drags, which
       `playlist-dragged-back` has already put back. */
    "playlist-undone": (i) => i.plrows === globalThis.__plN && !i.notice && (globalThis.__plN < 2 || i.plOrder === globalThis.__pl0),
    /* CONDITIONAL: `lift()` refuses a list of fewer than two rows, so a
       one-track record — which makes a one-row playlist — has no press to
       release. The two drag steps above tolerate exactly the same thing. */
    "playlist-drag-held": (i) => globalThis.__plN < 2 || (i.half.includes("up") && /Remove from playlist/.test(i.halfText)),
    /* CONDITIONAL in its last clause: the drag-refusal note needs more
       than one row to drag. The note itself hangs off the UNFILTERED
       list, so a filter that matched nothing still shows it. */
    "playlist-filter": (i) => i.plrows === 0 && /Nothing here matches/.test(i.stubText) && (globalThis.__plN < 2 || /Clear the search/.test(i.plNote)),
    "playlist-filter-cleared": (i) => i.plrows === globalThis.__plN && !i.plNote,
    /* ── the review's Keep switch ────────────────────────────────────
       CONDITIONAL: the row renders only when something did not resolve,
       and a paste that resolved completely leaves `keepOn` false anyway.
       The second step is what guarantees `import-created` below still
       sees the three rows it has always seen. */
    "import-keep-off": (i) => !i.keepOn && /Create playlist \(\d+ tracks?\)/.test(i.impBtn),
    "import-keep-on": (i) => /Create playlist \(3 tracks\)/.test(i.impBtn) && i.imp === 3,
    /* ── the library's own shape, on the device for the first time ──── */
    /* `a11yBad` is left out for the reason `track-sheet` leaves it out: a
       card's name is [title, artist, badge] off his own tags, and `junk()`
       calls a name of nothing but digits bad — "1999, 311" is a real
       record. The mock asserts it against a fixture, where it belongs.
       The structural three stay: nameless, ghost and mis-stated. */
    library: (i) => i.title.startsWith("Your library") && i.fmtBadges >= 1 && /hours|min/.test(i.countline)
        && !i.a11yAnon && !i.a11yGhost && !i.a11yState,
    /* the sort lives on the Library entry (`c.sort`), not in the config,
       so it needs no putting back — the chip after it does that anyway.
       What a real library's top format IS cannot be asserted; that the
       grid re-sorted and still badges every card can be. */
    "library-by-format": (i) => !!i.firstBadge && i.fmtBadges >= 1 && !i.toast && !i.a11yState,
    artists: (i) => i.title.startsWith("Your library") && i.rowArt >= 1 && !i.toast,
    /* CONDITIONAL: follows live in the library folder and the phone's own
       folder starts without any, so a phone with no follows can only be
       asked for the stub */
    gaps: (i) => i.title.startsWith("Your library") && !i.toast && (i.gaplines >= 1 || !!i.stubText),
    /* a LOCAL track's sheet: the three things it offers, the file block
       underneath it off a real path, and the layer named and holding
       focus. `a11yBad` is left out deliberately — it reads the names of
       real rows, and a record of his is allowed to be called anything. */
    "track-sheet": (i) => i.half.includes("up") && /Play next/.test(i.halfText) && /Add to queue/.test(i.halfText)
        && /Add to playlist/.test(i.halfText) && /Format/.test(i.halfText) && /Folder/.test(i.halfText)
        && /^dialog\/true\/.+\/focus$/.test(i.dlg) && !i.a11yAnon && !i.a11yGhost,
    /* the recents are localStorage on the device, written by the walk's
       own earlier search when that screen was left */
    "search-recent": (i) => i.title.startsWith("Search") && i.sq === "" && i.recents >= 1,
    "search-recent-pick": (i) => i.title.startsWith("Search") && !!i.sq,
    "queue-face": (i) => i.sheet.includes("up") && i.qFace,
    /* CONDITIONAL: the walked track can be the last queueable row, and
       then there is nothing to press. Asserted exactly when there is. */
    "queue-row-sheet": (i) => !i.half.includes("up") || (/Remove from queue/.test(i.halfText) && /Play now/.test(i.halfText)),
    /* Home's feed on a phone whose library folder holds no follows: the
       store answered, and not one of its slots came back with an error */
    "home-feed": (i) => /^(Good |Still)/.test(i.title) && !i.toast && i.homeSlots >= 0 && i.homeErr === 0,
    "home-more": (i) => i.half.includes("up") && /Sleep timer/.test(i.halfText),
    "sleep-sheet": (i) => i.half.includes("up") && /Pause after/.test(i.halfText) && /1½ hours/.test(i.halfText),
    /* every chip in that sheet goes through `act()`, which closes it — so
       this says nothing at all about the timer. The step after it does. */
    "sleep-set": (i) => !i.half.includes("up") && /^(Good |Still)/.test(i.title),
    /* the proof: the More sheet's Sleep-timer subtitle IS `sleepLabel()`,
       and the only thing that can make it read "N min left" is a
       `player.sleepAt` in the future */
    "sleep-armed": (i) => i.half.includes("up") && /min left/.test(i.halfText),
    "sleep-off": (i) => !i.half.includes("up") && /^(Good |Still)/.test(i.title),
    "sleep-cleared": (i) => i.half.includes("up") && /Sleep timer/.test(i.halfText) && !/min left/.test(i.halfText),
    /* the retention chip: read, moved, put back. The harness's stash and
       the page's own (`window.__keep0`) hold the same value for the same
       reason the drag steps keep two — a step's script is fixed before
       the walk starts and cannot carry this one. */
    "you-keep-arm": (i) => { globalThis.__keepWas = i.keep; return !!i.keep; },
    /* CONDITIONAL: the step moves nothing when "Forever" is the chip that
       is on, because the way back writes the flag and not the number. The
       label is what says which case this is. */
    "you-keep": (i) => !!i.keep && (/^Forever/.test(globalThis.__keepWas) ? i.keep === globalThis.__keepWas : i.keep !== globalThis.__keepWas),
    "you-keep-back": (i) => i.keep === globalThis.__keepWas,
    /* the Wi-Fi-only guard, which exists only because this is a phone */
    "wifi-arm": (i) => { globalThis.__wifiWas = i.wifiOnly; return !!i.wifiOnly; },
    "wifi-on": (i) => i.wifiOnly === "on",
    "wifi-refused": (i) => /Wi-Fi/.test(i.toast),
    /* the shadow removed and the sentence taken off the bar, with the
       switch still where the step above put it */
    "wifi-cleared": (i) => !i.toast && i.wifiOnly === "on",
    "wifi-restored": (i) => i.wifiOnly === globalThis.__wifiWas,
    /* a port the core refuses: nothing written, and the number the walk
       already left standing still standing */
    "you-port-refused": (i) => !i.half.includes("up") && /between 1024 and 65535/.test(i.toast) && /^50300 /.test(i.port),
