@layer components {
    /* U.S. Graphics / Control Room action button.
       Flat black-bordered rectangle; no radius; borrows surface behind it.
       Both `btn btn--subtle` (uses --btn-* tokens on the base .btn rule) and
       standalone `btn--subtle` work — the concrete fallbacks below cover
       the standalone case. Modifiers:
         .btn--subtle--primary — filled primary (Arpedon Blue CTA)
         .btn--subtle--dashed  — dashed border (for + Add affordances)      */
    .btn--subtle {
        --btn-background: transparent;
        --btn-border-color: var(--ink);
        --btn-border-radius: 0;
        --btn-border-size: 1px;
        --btn-color: var(--ink);
        --btn-font-weight: 500;
        --btn-gap: 0.5ch;
        --btn-hover-brightness: 1;
        --btn-padding: 0.18rem 0.55rem;

        align-items: center;
        background: var(--btn-background);
        border: var(--btn-border-size) solid var(--btn-border-color);
        border-radius: var(--btn-border-radius);
        color: var(--btn-color);
        cursor: pointer;
        display: inline-flex;
        font-family: var(--font-body);
        font-size: 0.8125rem;
        font-weight: var(--btn-font-weight);
        gap: var(--btn-gap);
        letter-spacing: -0.005em;
        line-height: 1.4;
        padding: var(--btn-padding);
        text-decoration: none;
        transition: background-color 100ms ease-out, color 100ms ease-out;

        @media (any-hover: hover) {
            &:hover {
                --btn-background: var(--ink);
                --btn-color: var(--color-ink-inverted, #fff);
            }
        }

        /* Kbd inside stays its own bordered pill; sit level with the baseline */
        > kbd {
            align-self: center;
        }
    }

    /* Filled primary variant — solid Arpedon Blue rectangle, bright text on
       strong bg. Used for CTAs that commit to an action (save measurement,
       submit, etc). Blue, not red: red on Mechbase means alarm. */
    .btn--subtle--primary {
        --btn-background: var(--primary);
        --btn-border-color: var(--primary);
        --btn-color: var(--on-primary);

        @media (any-hover: hover) {
            &:hover {
                /* Toward --ink: darker in light mode, lighter in dark, so the
                   --on-primary text keeps its contrast in both. */
                --btn-background: color-mix(in oklch, var(--primary) 85%, var(--ink));
                --btn-color: var(--on-primary);
            }
        }
    }

    .btn--subtle--dashed {
        --btn-border-color: var(--ink-faint);
        border-style: dashed;

        @media (any-hover: hover) {
            &:hover {
                --btn-background: transparent;
                --btn-border-color: var(--ink);
                --btn-color: var(--ink);
            }
        }
    }

    /* Destructive variant — outlined red, fills on hover. Matches the
       .btn--subtle family so it sits cleanly next to Save/Cancel in
       .form-actions or .form-hero__actions, but reads as dangerous. */
    .btn--subtle--negative {
        --btn-border-color: var(--status-crit-fg);
        --btn-color: var(--status-crit-fg);

        @media (any-hover: hover) {
            &:hover {
                --btn-background: var(--status-crit-fg);
                --btn-border-color: var(--status-crit-fg);
                --btn-color: #fff;
            }
        }
    }

    .btn {
        --icon-size: var(--btn-icon-size, 1.3em);
        --btn-border-radius: 0;
        --btn-hover-brightness: 0.9;

        align-items: center;
        background-color: var(--btn-background, var(--color-canvas));
        border-radius: var(--btn-border-radius);
        border: var(--btn-border-size, 1px) solid var(--btn-border-color, var(--color-ink-light));
        color: var(--btn-color, var(--color-ink));
        cursor: pointer;
        display: inline-flex;
        font-size: 1em;
        font-weight: var(--btn-font-weight, 600);
        gap: var(--btn-gap, 0.5em);
        justify-content: center;
        padding: var(--btn-padding, 0.5em 1.1em);
        pointer-events: auto;
        position: relative;
        transition: 100ms ease-out;
        transition-property: background-color, border, box-shadow, color, filter, opacity, scale;

        @media (any-hover: hover) {
            &:hover {
                filter: brightness(var(--btn-hover-brightness));
            }
        }

        html[data-theme="dark"] & {
            --btn-hover-brightness: 1.25;
        }

        @media screen and (prefers-color-scheme: dark) {
            html:not([data-theme]) & {
                --btn-hover-brightness: 1.25;
            }
        }

        &[disabled],
        &:has([disabled]),
        [disabled] &[type=submit],
        &[type=submit]:disabled {
            cursor: not-allowed;
            opacity: 0.3;
            pointer-events: none;
        }

        form[aria-busy] &:disabled {
            position: relative;

            >* {
                visibility: hidden;
            }

            &::after {
                --mask: no-repeat radial-gradient(#000 68%, #0000 71%);
                --size: 1.25em;

                -webkit-mask: var(--mask), var(--mask), var(--mask);
                -webkit-mask-size: 28% 45%;
                animation: submitting 1s infinite linear;
                aspect-ratio: 8/5;
                background: currentColor;
                content: "";
                inline-size: var(--size);
                inset: 50%;
                margin-block: calc((var(--size) / 3) * -1);
                margin-inline: calc((var(--size) / 2) * -1);
                position: absolute;
            }
        }
    }

    /* Variants
  /* ------------------------------------------------------------------------ */

    .btn--link {
        --btn-background: var(--color-link);
        --btn-border-color: var(--color-canvas);
        --btn-color: var(--color-ink-inverted);
        --focus-ring-color: var(--color-link);
    }

    .btn--circle,
    .btn[aria-label]:where(:has(.icon)),
    .btn:where(:has(.for-screen-reader):has(.icon)) {
        --btn-border-radius: 50%;
        --btn-padding: 0;
        --icon-size: 75%;

        aspect-ratio: 1;
        block-size: var(--btn-size);
        display: grid;
        inline-size: var(--btn-size);
        justify-content: normal;
        /* FF fix */
        place-items: center;

        >* {
            grid-area: 1/1;
        }
    }

    .btn--negative {
        --btn-background: var(--color-negative);
        --btn-border-color: var(--color-negative);
        --btn-color: var(--color-ink-inverted);
        --focus-ring-color: var(--color-negative);
    }

    /* Toggleable buttons
  /* ------------------------------------------------------------------------ */

    .btn {
        &:has(input[type=radio], input[type=checkbox]) {
            position: relative;

            :is(input[type=radio], input[type=checkbox]) {
                appearance: none;
                border-radius: var(--btn-border-radius);
                cursor: pointer;
                display: flex;
                inset: 0;
                margin: 0;
                padding: 0;
                position: absolute;

                &:focus-visible {
                    outline: none;
                }
            }

            .checked {
                display: none;
            }
        }

        &:has(input:checked) {
            --btn-background: var(--color-ink);
            --btn-border-color: var(--color-ink);
            --btn-color: var(--color-ink-inverted);
            --focus-ring-color: var(--color-ink);

            .checked {
                display: block;
            }
        }

        &:has(input:focus-visible) {
            outline: var(--focus-ring-size) solid var(--focus-ring-color);
            outline-offset: var(--focus-ring-offset);
        }
    }

    .btn--back {
        --btn-background: transparent;
        --btn-border-size: 0;
        --btn-padding: 0;

        align-items: center;
        color: var(--ink-soft);
        font-family: var(--font-data);
        font-size: 0.625rem;
        font-weight: 700;
        gap: 0.5ch;
        letter-spacing: 0.14em;
        text-transform: uppercase;

        /* Control Room: unicode ◂ replaces the old SVG chevron across all
           breakpoints. The destination name (no "Back to") follows. */
        &::before {
            color: var(--ink-mute);
            content: "◂";
            margin-inline-end: 0.25ch;
        }

        /* "Back" + the destination as a quieter suffix: "Back · LPG Terminal".
           Below 100ch the row wraps inside a one-line box, so a suffix that
           does not fit falls to line two and is clipped; "Back" never goes.
           At 100ch+ it stays on one line and a long name ellipsises. */
        .btn--back__label {
            column-gap: 0.75ch;
            display: flex;
            flex-wrap: wrap;
            max-block-size: 1lh;
        }

        .btn--back__to {
            color: var(--ink-mute);
            font-weight: 400;
            letter-spacing: 0.04em;
            min-inline-size: 0;
            overflow: hidden;
            text-overflow: ellipsis;
            text-transform: none;

            &::before {
                content: "· ";
            }
        }

        @media (min-width: 100ch) {
            .btn--back__label {
                flex-wrap: nowrap;
                max-inline-size: 40ch;
            }
        }

        /* Hide the legacy SVG icon — unicode ::before supplants it.
           Kept in markup for backwards-compat during the migration. */
        .icon--arrow-left {
            display: none;
        }

        @media (any-hover: hover) {
            &:hover {
                color: var(--ink);
            }
        }

        /* Phones: keep the label visible and give it a 44px tap target
           (the ◂ glyph alone was a ~10px target nobody saw). Only the ESC
           hint drops; a long referrer label ellipsises instead of
           crowding the breadcrumb on the right. */
        @media (max-width: 639px) {
            max-inline-size: 50vw;
            min-block-size: 44px;
            min-inline-size: 44px;

            > .overflow-ellipsis {
                min-inline-size: 0;
            }

            kbd {
                display: none;
            }
        }
    }

    /* Floating Action Button – scroll to top */
    /* Lifts clear of the pin tray geometrically: the tray publishes its own   */
    /* rendered height as --pin-tray-height (pin_tray_controller.js), and the  */
    /* FAB adds that on top of its resting offset. Defaults to 0px so any page */
    /* without a tray renders identically to before.                          */
    .fab-scroll-top {
        bottom: calc(1.25rem + var(--pin-tray-height, 0px));
        box-shadow: var(--shadow);
        opacity: 0;
        pointer-events: none;
        position: fixed;
        right: 1.25rem;
        transform: translateY(0.5rem);
        transition: bottom 200ms ease-out, opacity 200ms ease-out, transform 200ms ease-out;
        z-index: 50;
    }

    .fab-scroll-top--visible {
        opacity: 1;
        pointer-events: auto;
        transform: translateY(0);
    }

    /* An OPEN compare drawer (registry/static/registry/css/analysis.css        */
    /* .point-analysis) occupies exactly the space this FAB lifts into -- the   */
    /* same stranding bug the --pin-tray-height fix above solved, in a new      */
    /* costume (#248 review). Hide rather than offset: the drawer already       */
    /* covers the lower viewport the FAB would scroll toward, and offsetting    */
    /* risks pushing the FAB off-screen above a tall drawer. Collapsed, the     */
    /* drawer is scoped out by data-state and the FAB returns on its own.       */
    /*                                                                          */
    /* `data-state` on .point-analysis is closed | collapsed | open, written    */
    /* ONLY by compare_panel_controller#_syncState (#250). analysis.css holds   */
    /* the other two rules that read it. It is JS-maintained: the server ships  */
    /* `closed`, everything after that comes from the controller.               */
    /* Composed like the .point-detail rule in analysis.css (#250 review):      */
    /* data-state says a comparison exists, [open] says it is expanded RIGHT     */
    /* NOW. <details> fires `toggle` a task after flipping `open`, so reading    */
    /* expansion from the mirrored attribute alone would draw the FAB over the   */
    /* drawer for a frame on every expand.                                       */
    body:has(.point-analysis:not([data-state="closed"])[open]) .fab-scroll-top {
        display: none;
    }

    /* COLLAPSED, the drawer shrinks to just its handle -- but the FAB's        */
    /* resting offset assumes nothing is docked there, so the handle clips the  */
    /* bottom of the button (drawer review fix wave: measured 19px of the      */
    /* FAB's 47px height sitting behind the handle bar). --drawer-handle-height */
    /* is MEASURED from the <summary> and published on :root by                 */
    /* compare_panel_controller#_publishHandleHeight (#250, same idiom as       */
    /* --pin-tray-height), so this offset tracks the handle's real height even  */
    /* when its label wraps. It is absent until the drawer is visible -- hence  */
    /* the `, 2.75em` fallback below, which also covers the pre-JS frame.       */
    body:has(.point-analysis:not([data-state="closed"]):not([open])) .fab-scroll-top {
        bottom: calc(1.25rem + var(--pin-tray-height, 0px) + var(--drawer-handle-height, 2.75em));
    }
}
