@layer components {
    /*
     * The component itself draws nothing: it is a mount point for the controller, and the bar
     * inside it is what is seen. Without `display: contents` the hidden bar would still take the
     * grid gap of whatever wraps it.
     */
    .sw-update {
        display: contents;
    }

    /*
     * Sticky and in the flow, which is what kalendarik does and what works on a real phone.
     *
     * It was `position: fixed; inset-block-start: 0` first, and that is the version the reviewer
     * reported as a button that could not be pressed. The page sets `viewport-fit=cover`, so it
     * genuinely extends under the status bar — a fixed bar at offset zero puts its first rows
     * where the system, not the page, takes the touch. Repeating `env(safe-area-inset-top)` here
     * is not a fix either, because that value is 0 on plenty of Android devices that still paint a
     * status bar over the page.
     *
     * In the flow, under <body>'s own safe-area padding, the question cannot arise. The cost is
     * that it takes up space rather than floating over the page — which is the right trade for a
     * bar that appears a few times a year and leaves as soon as it is answered.
     *
     * Top and not bottom, which is where the cookie banner sits (kept from recenzovac, where the
     * bottom of the screen was the player's pause button).
     */
    /*
     * **This rule is why the bar exists at all, and deleting it puts it back on every page.**
     *
     * The template hides the bar with the `hidden` attribute, which works through the browser's own
     * `[hidden] { display: none }`. Author CSS beats the user-agent sheet, so the `display: flex`
     * below silently cancelled it: the bar rendered on every page, from the first load, with no
     * update to offer and nothing anybody could press to make it go away. It was reported three
     * times before anyone looked at the pixels instead of at `barTarget.hidden`, which reads `true`
     * the whole time.
     *
     * kalendarik does not need this because its bar sets no `display` of its own. Setting one here
     * is deliberate (the text and the buttons lay out on this element), so the guard comes with it.
     */
    .sw-update__bar[hidden] {
        display: none;
    }

    .sw-update__bar {
        position: sticky;
        inset-block-start: 0;
        z-index: 20;
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: var(--space-s);
        padding: var(--space-s) var(--space-m);
        border-block-end: 1px solid var(--color-border);
        background-color: var(--color-surface);
        color: var(--color-text);
        box-shadow: 0 8px 24px rgb(0 0 0 / 25%);
    }

    /*
     * In the editor's fixed app shell the bar floats over the shell instead: in the flow it pushed
     * the whole one-viewport editor down and cut its bottom off. It floats as a card *below* the
     * editor's own top bar (3rem, plus the safe area) — never at offset zero, where the status bar
     * takes the touches (see above). Fixed, so its appearing shifts nothing.
     */
    body.app-shell .sw-update__bar {
        position: fixed;
        inset-block-start: calc(env(safe-area-inset-top, 0px) + 3rem + var(--space-xs));
        inset-inline: var(--space-m);
        z-index: 50;
        max-inline-size: 40rem;
        margin-inline: auto;
        border: 1px solid var(--color-border);
        border-radius: var(--radius-m);
    }

    .sw-update__text {
        flex: 1 1 12rem;
        margin: 0;
        font-size: var(--text-s);
    }

    .sw-update__actions {
        display: flex;
        gap: var(--space-xs);
    }

    /*
     * Small, because this is an offer and not an alert — but not smaller than a thumb: 2.75rem is
     * a comfortable floor for a touch target, even when the right answer is "later".
     */
    .sw-update__action {
        min-block-size: 2.75rem;
        padding-inline: var(--space-m);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-full);
        background-color: transparent;
        color: inherit;
        font-size: var(--text-s);
        cursor: pointer;
    }

    .sw-update__action--primary {
        border-color: transparent;
        background-color: var(--color-accent);
        color: var(--color-accent-contrast);
        font-weight: 600;
    }

    /* The press has landed and the page is about to reload. Visible rather than gone, so the
       half-second of waiting does not read as "nothing happened". */
    .sw-update__action[disabled] {
        opacity: 0.5;
    }
}
