    var hasNext: Boolean = true
    var hasPrev: Boolean = true
    /** the queue around the current item — it and up to ten either side.
     *  NOTHING READS IT: MediaService ignores both of these on purpose, so
     *  the card is byte for byte the card it was. media3's
     *  SimpleBasePlayer.getState() wants a playlist and an index into it,
     *  and this is that data arriving a round before the migration does.
     *  Nullable because a non-null Kotlin property whose setter Jackson
     *  hands a null throws, and the only thing between here and the JS that
     *  builds it is two JSON hops. */
    var queue: List<QueueItemArgs>? = null
    /** where the current item sits in `queue` — not in the whole queue;
     *  null when the window is empty */
    var queueIndex: Int? = null
}

/** One entry of the queue window. Flat and small: it crosses the bridge on
 *  every update, so it holds what a media3 MediaItem is built from and no
 *  more. `artKey` names the cover the way NowPlayingArgs.artKey does; the
 *  bytes never ride along here. */
@InvokeArg
class QueueItemArgs {
    var id: String? = null
    var title: String? = null
    var artist: String? = null
    var album: String? = null
    var duration: Double? = null
    var artKey: String? = null
}