/* #region Dialog shell
   The size every configurator's dialog takes, so it belongs to no product's region — Lens has a stylesheet
   of its own, like Alibi and Art. */
.product-configurator-modal .configurator-modal-dialog {
    width: min(1280px, 100%);
    height: min(880px, calc(100dvh - clamp(2rem, 6vw, 6rem)));
    grid-template-columns: minmax(350px, .78fr) minmax(0, 1.55fr);
}

/* #endregion */

/* #region Space — the chosen address */
/* The address is chosen before this dialog opens, so the panel neither shows a picker nor asks for the
   choice again: what is left is the lease terms and a way out to the catalogue for the case where a link
   named an address we no longer hold. */
/* Two columns under the rule that closes the heading: what the subscription covers and what happens
   after the order. Both answer the same question, so they stand side by side and start at the same
   height — never one of them over in the column with the amount, on the other side of the dialog.

   auto-fit rather than a width query: these columns sit inside a dialog whose width depends on the
   screen and on how much room the amount's rail took, so the threshold here is a property of the
   content and not of the viewport. Below two such columns the grid lays them into one, with no rule
   of its own. */
.product-configurator-modal .cfg-space-terms {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
    gap: clamp(1.75rem, 4vw, 3.25rem);
    width: min(100%, 720px);
    margin: clamp(2rem, 4vw, 3.25rem) auto 0;
    padding-top: clamp(1.5rem, 3vw, 2.25rem);
    border-top: 1px solid var(--line);
    text-align: left;
}

    /* The authored display beats the browser's [hidden] rule; with no address there is no lease to
       enumerate, so the attribute has to win. */
    .product-configurator-modal .cfg-space-terms[hidden] {
        display: none;
    }

    /* The column's title sits on the rule above it: the air over these lists comes from the shared
       frame's padding, and a margin of .cfg-next-title's own adds to it — which is right only for a
       single list standing under another. Two titles side by side have to start at the same height. */
    .product-configurator-modal .cfg-space-terms .cfg-axis-title {
        margin-top: 0;
    }

    /* Air under both lists. Without it the dialog ends on the last line of the enumeration and the lease
       terms touch the panel's bottom edge — and this is the screen where somebody reads what they are
       taking and what it costs, not a form packed to the last pixel. On both columns, because they stand
       side by side and the longer of the two must not be the one left without a floor. */
    .product-configurator-modal .cfg-space-terms .cfg-included-list {
        margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
    }

.product-configurator-modal .cfg-space-empty {
    color: var(--text-muted);
    font-size: .65rem;
    text-align: center;
}

.product-configurator-modal .cfg-space-empty-state {
    margin: auto;
    padding: 2rem;
    border: 1px solid var(--hairline-mid);
    text-align: center;
}

/* #endregion */

/* #region Modal shell & wizard overrides */
.product-configurator-modal {
    overflow-y: auto;
    overscroll-behavior: contain;
}

    .product-configurator-modal .configurator-modal-intro {
        padding: clamp(2.5rem, 3.8vw, 4.2rem);
    }

        .product-configurator-modal .configurator-modal-intro h2 {
            max-width: 10ch;
            margin-bottom: 1.25rem;
            font-family: var(--font-display);
            font-size: clamp(2.5rem, 3.6vw, 4rem);
            font-weight: 200;
            line-height: 1.04;
        }

            .product-configurator-modal .configurator-modal-intro h2 i {
                font-weight: 200;
            }

    .product-configurator-modal .configurator-modal-content {
        display: block;
        height: 100%;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        scrollbar-gutter: stable;
    }

    .product-configurator-modal .cfg-wizard {
        min-height: min(760px, calc(100vh - clamp(2rem, 6vw, 6rem)));
        display: flex;
        flex-direction: column;
        padding: clamp(2.2rem, 3.5vw, 3.8rem);
    }

    .product-configurator-modal [data-wizard-steps="2"] .cfg-wizard-progress {
        grid-template-columns: repeat(2, 1fr);
    }

    .product-configurator-modal .cfg-wizard-panel[hidden] {
        display: none;
    }

    .product-configurator-modal .cfg-wizard-panel.is-active {
        flex: 1;
        display: flex;
        flex-direction: column;
    }

    .product-configurator-modal .cfg-wizard-heading {
        margin-bottom: clamp(2rem, 4vh, 3.2rem);
    }

    .product-configurator-modal .cfg-wizard-panel .cfg-axis {
        display: block;
        width: min(100%, 700px);
        margin: 0 auto;
        padding: 0;
        border: 0;
    }

    .product-configurator-modal .cfg-wizard-panel .cfg-edition-choices {
        grid-column: auto;
        gap: 1rem;
    }

    .product-configurator-modal .cfg-wizard-panel .cfg-choice {
        min-height: 220px;
        padding: 1.7rem;
        border-color: rgba(245, 245, 245, .16);
    }

    .product-configurator-modal .cfg-choice-name {
        font-family: var(--font-display);
        font-size: clamp(1.3rem, 1.7vw, 1.7rem);
        font-weight: 300;
        line-height: 1.15;
    }

    .product-configurator-modal .cfg-choice-description {
        font-size: .78rem;
        line-height: 1.65;
    }

    .product-configurator-modal .cfg-choice-features {
        display: flex;
        flex-direction: column;
        gap: .3rem;
        margin: .15rem 0 .6rem;
        padding: 0;
        list-style: none;
        color: rgba(245, 245, 245, .72);
        font-size: .68rem;
        line-height: 1.45;
    }

        .product-configurator-modal .cfg-choice-features li::before {
            content: "—";
            margin-right: .5rem;
            color: var(--gold);
        }

    .product-configurator-modal .cfg-choice-price {
        margin-top: auto;
        color: var(--gold);
        font-family: var(--font-display);
        font-size: clamp(1.25rem, 1.8vw, 1.65rem);
        font-weight: 300;
        letter-spacing: 0;
        line-height: 1.1;
        text-transform: none;
    }

        .product-configurator-modal .cfg-choice-price small {
            color: var(--text-muted);
            font-family: var(--font-sans);
            font-size: .62rem;
            letter-spacing: .08em;
            text-transform: uppercase;
        }

    /* Tiles side by side — the house's way of showing a thing you can order more or fewer of: a
       photograph, its name, what it is, its rate and a stepper. Soul stands three of them here and
       Lens two, so nothing in this block is named after either. They were full-width rows stacked
       one under another, so reading a composition meant scrolling past all of it. */
    .product-configurator-modal .cfg-pieces {
        width: 100%;
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: .85rem;
        margin: 0 auto;
    }

        /* Two of them take half each rather than two thirds of the row: a tile with an empty third
           beside it reads as a missing third tile. */
        .product-configurator-modal .cfg-pieces--two {
            grid-template-columns: repeat(2, minmax(0, 1fr));
        }

    .product-configurator-modal .cfg-piece {
        display: flex;
        flex-direction: column;
        gap: 1.1rem;
        padding: 1.35rem 1.4rem 1.25rem;
        border: 1px solid rgba(245, 245, 245, .14);
        background: rgba(245, 245, 245, .022);
        transition: border-color .35s ease, background .35s ease;
    }

        /* A form that is in the composition says so. Left identical whether they hold three pieces or
           none, the only way to read a composition is to compare the digits in three steppers. */
        .product-configurator-modal .cfg-piece.is-chosen {
            border-color: var(--gold-mid);
            background: rgba(var(--gold-rgb), .05);
        }

    /* One photograph per form, square like every other image in the house. A single product photograph
       on the rail shows a cube and says nothing about how a 5 cm one differs from a 10 cm one or from a
       bare chip. */
    .product-configurator-modal .cfg-piece-photo {
        position: relative;
        margin: 0;
        aspect-ratio: 1;
        overflow: hidden;
        border: 1px solid rgba(245, 245, 245, .07);
        background: #050505;
    }

        .product-configurator-modal .cfg-piece-photo img {
            width: 100%;
            height: 100%;
            display: block;
            object-fit: cover;
            filter: var(--photo-at-rest);
            transition: transform 1.8s var(--ease-house), filter var(--motion-slow) var(--ease-house);
        }

    /* The measurement, under the quality it belongs to — the italic the house gives a motto under a
       product name. Italic, not roman: the price at the foot of the tile is Playfair too, and the slope
       is what keeps the two apart at a glance. The price is the tile's one gold figure. */
    .product-configurator-modal .cfg-piece-spec {
        color: var(--white-soft);
        font-family: var(--font-display);
        font-size: .88rem;
        font-style: italic;
        font-weight: 300;
        line-height: 1.35;
    }

    /* The description stands away from the format line above it and the price below it — packed at
       the copy block's own .4rem it read as a third line of the heading. */
    .product-configurator-modal .cfg-piece .cfg-choice-description {
        margin: .5rem 0;
    }

    .product-configurator-modal .cfg-piece.is-chosen .cfg-piece-photo {
        border-color: var(--gold-border);
    }

        .product-configurator-modal .cfg-piece.is-chosen .cfg-piece-photo img {
            filter: var(--photo-lifted);
        }

    .product-configurator-modal .cfg-piece:hover .cfg-piece-photo img {
        transform: scale(1.025);
        filter: var(--photo-lifted);
    }

    /* flex:1 so the price falls to the bottom of the copy block and the three prices share one
       line. Without it the block is only as tall as its own text, so margin-top:auto has nothing to push
       against and the three amounts sit at three different heights — the descriptions differ by a line. */
    .product-configurator-modal .cfg-piece-copy {
        display: flex;
        min-width: 0;
        flex: 1;
        flex-direction: column;
        gap: .4rem;
    }

    .product-configurator-modal .cfg-piece .cfg-qty-control {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: .45rem;
        padding: .4rem;
        border: 1px solid var(--hairline-mid);
        transition: border-color .35s var(--ease-house);
    }

    .product-configurator-modal .cfg-piece.is-chosen .cfg-qty-control {
        border-color: var(--gold-mid);
    }

    .product-configurator-modal .cfg-piece .cfg-qty-btn {
        width: 42px;
        height: 42px;
        flex: none;
    }

    /* The figure takes whatever the two buttons leave. The wizard's own 58px floor, later in this file
       and of equal weight, made the stepper 171px wide and pushed „+" out of a tile narrower than that. */
    .product-configurator-modal .cfg-piece .cfg-qty-control .cfg-qty-value {
        min-width: 0;
        width: 100%;
        flex: 1 1 0;
        text-align: center;
    }

    .product-configurator-modal .cfg-piece.is-chosen .cfg-qty-value {
        color: var(--gold);
    }

    /* The micro-caps label that stands above each amount. */
    .product-configurator-modal .cfg-rail-payments small {
        color: var(--text-muted);
        font-family: var(--font-mono);
        font-size: .58rem;
        letter-spacing: .16em;
        text-transform: uppercase;
    }

    /* The line under an amount says what it buys, so it reads as a sentence, not as another label. */
    /* The note belongs to the amount above it, not to whatever follows. The column's own gap spaced
       all three the same, so the unit price floated exactly between the figure it explains and the
       line after it and could be read as either. A little air above and a little less below binds it
       upward — the same reason a caption sits closer to its picture than to the next paragraph. Small
       numbers on purpose: this is a nudge, not a new rhythm. */
    .product-configurator-modal .cfg-rail-payments .cfg-rail-price-note {
        margin-top: .3rem;
        margin-bottom: -.15rem;
        color: var(--white-soft);
        font-family: var(--font);
        font-size: .66rem;
        letter-spacing: .04em;
        line-height: 1.5;
        text-transform: none;
    }

    .product-configurator-modal .cfg-rail-payments {
        display: grid;
        grid-template-columns: 1fr;
        gap: 1rem;
    }

        .product-configurator-modal .cfg-rail-payments > span {
            display: flex;
            min-width: 0;
            flex-direction: column;
            gap: .35rem;
        }

        .product-configurator-modal .cfg-rail-payments b {
            display: block;
            color: var(--white);
            font-family: var(--font-display);
            font-size: clamp(1.65rem, 2.6vw, 2.4rem);
            font-weight: 300;
            line-height: 1.1;
        }

    .product-configurator-modal .cfg-wizard-panel .cfg-qty-row {
        grid-column: auto;
        justify-self: center;
        gap: .65rem;
        padding: .65rem;
    }

    .product-configurator-modal .cfg-wizard-panel .cfg-qty-btn {
        width: 42px;
        height: 42px;
    }

    .product-configurator-modal .cfg-wizard-panel .cfg-qty-value {
        min-width: 58px;
        font-size: 1.35rem;
    }

    .product-configurator-modal .cfg-review {
        width: min(100%, 740px);
    }

    .product-configurator-modal .cfg-review-actions {
        width: min(100%, 740px);
        justify-content: flex-start;
        margin: 1rem auto 0;
        padding-top: 0;
    }

    .product-configurator-modal .cfg-review .cfg-summary-card {
        display: flex;
        padding: 2rem;
    }

    .product-configurator-modal .cfg-price-onetime {
        font-size: clamp(2.5rem, 4vw, 3.7rem);
    }

/* #endregion */

/* #region Responsive */
@media (max-width: 900px) {
    .product-configurator-modal .configurator-modal-dialog {
        grid-template-columns: minmax(280px, .6fr) minmax(0, 1.5fr);
    }
}

@media (max-width: 760px) {
    .product-configurator-modal .configurator-modal-dialog {
        height: 100dvh;
    }

    /* This file loads after product.css, whose flat 2rem would otherwise erase the safe-area padding the
       summary card needs above the iOS home indicator. */
    .product-configurator-modal .cfg-review .cfg-summary-card {
        padding: 1.5rem 1.4rem max(1.5rem, env(safe-area-inset-bottom));
    }

    /* The stepper plus a Polish unit word does not fit 315px in one row. */
    .product-configurator-modal .cfg-wizard-panel .cfg-qty-row {
        flex-wrap: wrap;
        justify-content: center;
    }

    .product-configurator-modal .configurator-modal-content {
        height: auto;
        overflow: visible;
    }

    .product-configurator-modal .configurator-modal-intro {
        padding: 3.8rem 1.4rem 1.7rem;
    }

        .product-configurator-modal .configurator-modal-intro h2 {
            font-size: clamp(2rem, 10vw, 3rem);
        }

    .product-configurator-modal .cfg-wizard {
        min-height: calc(100dvh - 230px);
        padding: 1.8rem 1.4rem max(1.5rem, env(safe-area-inset-bottom));
    }

    .product-configurator-modal .cfg-wizard-panel .cfg-edition-choices,
    .product-configurator-modal .cfg-review {
        grid-template-columns: 1fr;
    }

    .product-configurator-modal .cfg-wizard-panel .cfg-choice {
        min-height: 185px;
    }

    .product-configurator-modal .cfg-piece {
        gap: 1rem;
    }

}

/* #endregion */

/* #region Quote errors & quantity limits */
/* An authored display beats the UA's [hidden] rule, and .cfg-included-list sets display:flex — so
   the per-edition lists all painted at once and the basket's rail promised a buyer of the standard
   edition the gilded cards of the dedicated one. The lists are swapped by the `hidden` attribute
   alone, which means the attribute has to win. */
.cfg-included-list[hidden] {
    display: none;
}

/* It stands under the button it belongs to, with a step above it: flush against the control, a sentence
   explaining a refusal reads as part of the control's own label. */
.cfg-quote-error {
    margin: .9rem 0 .7rem;
    padding: .6rem .8rem;
    border: 1px solid var(--gold);
    color: var(--gold);
    font-size: .72rem;
    line-height: 1.5;
}

    .cfg-quote-error.hidden {
        display: none;
    }

.cfg-qty-value.cfg-qty-limit {
    animation: cfg-qty-limit-flash .6s ease;
}

@keyframes cfg-qty-limit-flash {
    0%, 100% {
        color: inherit;
    }

    50% {
        color: var(--gold);
    }
}

/* The wizard's inline validation sentence (role="alert"): quiet gold, like the quote errors —
   the configurator never shouts, it states. */
.cfg-wizard-validation {
    margin: 1rem 0 0;
    color: var(--gold);
    font-size: .78rem;
    font-weight: 300;
    line-height: 1.6;
}
/* #endregion */

/* #region Composition sharing
   Built by configurator.js under the add-to-cart button: one quiet text button, and the link
   with its copy control once the composition is saved. */
/* Written as the house's underlined link rather than as a second control competing with the button
   it follows — the two sit together, and only one of them is the action. Centred under the
   full-width button, and set smaller than it. */
.cfg-share {
    margin-top: 1.2rem;
    text-align: center;
}

/* 44px of tap height, the text still standing on its rule at the bottom. */
.cfg-share-btn {
    min-height: 44px;
    display: inline-flex;
    align-items: flex-end;
    padding: 0 0 .35rem;
    border: 0;
    /* The rule is there from the start, quiet: a link that only underlines on hover reads as text
       until somebody happens to point at it. */
    border-bottom: 1px solid var(--hairline);
    background: none;
    color: var(--text-muted);
    font-family: var(--font-sans);
    font-size: .62rem;
    font-weight: 300;
    letter-spacing: .18em;
    text-transform: uppercase;
    cursor: pointer;
    transition: color var(--motion-quick) var(--ease-house), border-color var(--motion-quick) var(--ease-house);
}

    .cfg-share-btn:hover,
    .cfg-share-btn:focus-visible {
        border-bottom-color: var(--gold);
        color: var(--gold);
    }

    .cfg-share-btn:disabled {
        opacity: .55;
        cursor: default;
    }

.cfg-share-result {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .4rem .8rem;
    margin-top: .7rem;
    font-size: .78rem;
}

    /* The authored display above beats the UA's [hidden] rule, so [hidden] has to be restated here or the
       empty result renders before the composition is saved. */
    .cfg-share-result[hidden] {
        display: none;
    }

.cfg-share-label {
    color: var(--text-muted);
    font-weight: 300;
}

.cfg-share-link {
    color: var(--white);
    text-decoration: underline;
    text-decoration-color: var(--hairline-strong);
    text-underline-offset: .3em;
    word-break: break-all;
    transition: color var(--motion-quick) var(--ease-house), text-decoration-color var(--motion-quick) var(--ease-house);
}

    .cfg-share-link:hover,
    .cfg-share-link:focus-visible {
        color: var(--gold);
        text-decoration-color: var(--gold);
    }

.cfg-share-copy {
    min-height: 44px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--text-muted);
    font-size: .7rem;
    letter-spacing: .1em;
    text-decoration: underline;
    text-underline-offset: .3em;
    text-transform: uppercase;
    cursor: pointer;
}

    .cfg-share-copy:hover {
        color: var(--gold);
    }
/* #endregion */

/* #region Visual stage
   Static photographs with live overlays, and the note a stage writes under itself. Pure theatre —
   nothing here reaches the server. Art's own stage moved to art-configurator.css with the rest of
   that page's layer. */
/* The quiet line under a stage. Art's gallery writes its note in this class, which is why the rule stays in
   this shared file: moved into alibi-configurator.css, which the Art page does not load, the note renders
   unstyled. */
.cfg-engraving-note {
    margin-top: .7rem;
    color: var(--text-muted);
    font-size: .72rem;
    font-weight: 300;
    line-height: 1.6;
}

/* #endregion */

/* #region The summary rail
   All five products stand on it now, so nothing here is named after any of them: a one-step panel
   on the reading side, and one column beside it holding the action, the amounts and the
   conditions. */
/* The eyebrow sits closer to the heading it introduces than the site-wide 2.4vh, which is measured for a
   hero with a screen to fill. Its value is mirrored in --cfg-eyebrow-block below, where the rail uses it to
   stand its button level with that heading — change one and change the other. */
.product-configurator-modal .cfg-wizard-heading .h-tag {
    margin-bottom: 1rem;
}

/* A one-step panel spends its height on the thing being configured, so its heading is set a size
   down from the wizard's — where a heading opens a step of three it is the whole screen, and here
   it stands above tiles, a stepper and a field that all have to be reachable without scrolling. */
.configurator-modal-dialog--rail .cfg-wizard-heading {
    margin-bottom: clamp(1.5rem, 3vh, 2.4rem);
}

    .configurator-modal-dialog--rail .cfg-wizard-heading h3 {
        font-size: clamp(1.9rem, 2.7vw, 2.7rem);
    }

/* The dialog takes the height of what it holds, up to the screen. A fixed 880px column suits a three-step
   wizard; under the one-step composition this panel carries it leaves a hand's width of empty ground below
   the tiles. Bounded to the two-column layout on purpose — below 760px the dialog is the whole screen, and
   an auto height capped at 880px would reintroduce the gap this is here to remove. */
@media (min-width: 761px) {
    .product-configurator-modal .configurator-modal-dialog--rail {
        /* Named once, because both columns have to be bounded by exactly the same number. */
        --rail-max-height: min(940px, calc(100dvh - clamp(2rem, 6vw, 6rem)));
        height: auto;
        /* A cap, not a height: a rail dialog is as tall as it needs to be. 940 rather than 880, so a panel
           carrying tiles and a stepper has room to show both at once on a laptop; Soul's is shorter and
           simply does not reach it. */
        max-height: var(--rail-max-height);
        /* One row, and a bounded one. With the default `auto` the row is sized to the taller column and the
           dialog's own overflow:hidden cuts off whatever does not fit, so a column taller than the screen
           has nothing to scroll against and the panel cannot be scrolled at all: the tiles stay reachable
           and the stepper under them does not. */
        grid-template-rows: minmax(0, 1fr);
    }

        /* Belt and braces beside the bounded row: each column carries the same ceiling itself, so
           neither depends on `height: 100%` resolving against a grid area to become scrollable. */
        .configurator-modal-dialog--rail .configurator-modal-content,
        .configurator-modal-dialog--rail .configurator-modal-intro--rail {
            max-height: var(--rail-max-height);
        }

        .configurator-modal-dialog--rail .cfg-wizard {
            min-height: 0;
        }
}

/* The dialog's two columns swap on the rail: the tiles are what a buyer works on, so they take the
   reading side, and the other column carries everything that answers them — the amounts, what they
   cover and the button — rather than a single product photograph. The rail scrolls on its own, so
   the button stays reachable however long the list beside it grows. */
/* Two class names, because the responsive rules above target
   `.product-configurator-modal .configurator-modal-dialog` and would otherwise outrank this one
   below 900px — putting the tiles in the narrow column and the rail in the wide one. */
.product-configurator-modal .configurator-modal-dialog--rail {
    grid-template-columns: minmax(0, 1.6fr) minmax(330px, .85fr);
}

    .configurator-modal-dialog--rail .configurator-modal-content {
        order: 1;
    }

    /* The rail's first line is the button, and it stands level with the panel's heading opposite
       it. That heading sits below the wizard's own padding and below its eyebrow, so the rail
       repeats both terms rather than guessing a number: the same padding, plus the eyebrow's line
       box and the margin under it. Change the eyebrow and the two move together. */
    .configurator-modal-dialog--rail .configurator-modal-intro--rail {
        --cfg-wizard-padding: clamp(2.2rem, 3.5vw, 3.8rem);
        --cfg-eyebrow-block: calc(.65rem * 1.6 + 1rem);
        order: 2;
        display: flex;
        flex-direction: column;
        gap: clamp(1.4rem, 2.4vh, 2rem);
        padding: calc(var(--cfg-wizard-padding) + var(--cfg-eyebrow-block)) clamp(2rem, 2.6vw, 2.8rem) clamp(2rem, 2.6vw, 2.8rem);
        overflow-y: auto;
        overscroll-behavior: contain;
        border-right: 0;
        border-left: 1px solid var(--line);
    }

        /* The inset hairline frame belongs to a still column, not a scrolling one. */
        .configurator-modal-intro--rail::before {
            display: none;
        }

/* No frame of its own: inside a rail that is already a bordered column, a second box around the
   same content reads as a widget dropped into the panel rather than as the panel's own foot. */
/* Top-aligned: the button opens this column, so nothing pushes it down the page. */
.cfg-rail-summary {
    position: static;
    margin-top: 0;
}

    .cfg-rail-summary .cfg-summary-card {
        padding: 0;
        border: 0;
        background: none;
    }

    /* The panel's primary action, and it has to look like one: a full-width drawn block across the rail,
       the house button of --button-layers, framed a step stronger than anything else in the column.
       As the hero's underlined line it is the quietest element in the column — right for a link that leads
       somewhere, wrong for the button that places the order. The sizing is spelled out
       because the rule that gives every other configurator's button its size is scoped to
       `.configurator-modal-content`, and this button stands in the rail instead. */
    .cfg-rail-summary .cfg-add-btn {
        width: 100%;
        margin: 0;
        padding: 1.15rem 1rem;
        border: 1px solid var(--button-border);
        background: var(--button-layers);
        color: var(--white);
        font-family: var(--font-sans);
        /* Larger than the share link below it: set the action and the aside the other way round and the
           quieter of the two is the one shouting. */
        font-size: .72rem;
        font-weight: 400;
        letter-spacing: .18em;
        line-height: 1.5;
        text-transform: uppercase;
    }

        .cfg-rail-summary .cfg-add-btn:focus-visible:not(:disabled) {
            background-size: 100% 1px, 100% 100%;
            border-color: var(--button-border-hover);
        }

    /* Hover only where there is a pointer: a tap leaves :hover applied. */
    @media (hover: hover) {
        .cfg-rail-summary .cfg-add-btn:hover:not(:disabled) {
            background-size: 100% 1px, 100% 100%;
            border-color: var(--button-border-hover);
        }
    }

    /* Stacked, not side by side: in a rail this narrow two display amounts in one row wrap into
       four ragged lines. The gap between them is wide because they are two separate commitments —
       one paid once, one every month — and not two lines of one figure. */
    .cfg-rail-summary .cfg-rail-payments {
        gap: clamp(1.8rem, 3.2vh, 2.4rem);
        margin: clamp(2.6rem, 5vh, 3.6rem) 0 0;
    }

    .cfg-rail-summary .cfg-summary-note {
        margin: 1.1rem 0 0;
        font-size: .68rem;
        line-height: 1.65;
    }

/* What the monthly fee covers, under the price it is charged at — and well under it: the per-copy
   rate directly above belongs to the amount, not to this list. */
/* No rule above it. The rail already divides itself by spacing, and a hairline here cut the column
   into two halves that read as two separate panels — the list of what happens after the purchase
   belongs to the summary above it, not to a section of its own. */
.cfg-rail-included {
    margin-top: clamp(1.2rem, 2.2vh, 1.7rem);
}

    .cfg-rail-included .cfg-axis-title {
        display: block;
        margin-bottom: .7rem;
    }

    .cfg-rail-included .cfg-included-list {
        gap: .45rem;
        font-size: .74rem;
    }

/* The quote dims the amounts while it is in flight. The summary sits outside #configurator-root
   now, which is the element the script marks busy, so the dialog carries the state instead. */
.configurator-modal-dialog--rail:has(.configurator-modal-content[aria-busy="true"]) .cfg-summary-price {
    opacity: .45;
}
/* #endregion */

/* #region Piece tiles on narrow dialogs */
/* Between the tablet dialog and the full-width one each tile gets about 170px, which is less than
   the stepper needs beside 1.4rem of padding on both sides. The row keeps its count — seeing the
   whole choice at once is the point of it — and everything inside gets smaller instead. */
@media (min-width: 901px) and (max-width: 1024px) {
    .product-configurator-modal .cfg-piece {
        gap: .85rem;
        padding: 1.05rem 1rem;
    }

    .product-configurator-modal .cfg-piece .cfg-choice-name {
        font-size: 1.12rem;
    }

    .product-configurator-modal .cfg-piece .cfg-qty-control {
        gap: .3rem;
        padding: .3rem;
    }

    .product-configurator-modal .cfg-piece .cfg-qty-btn {
        width: 40px;
        height: 40px;
    }

}

/* Below this the dialog still stands in two columns and the wizard's own column is too narrow for
   three of anything: the tiles stack and take their full size back. */
@media (max-width: 900px) {
    .product-configurator-modal .cfg-pieces {
        grid-template-columns: 1fr;
    }

    /* Stacked, the photograph beside the words rather than above them — three square pictures at
       full column width would push the steppers off the screen. */
    .product-configurator-modal .cfg-piece {
        display: grid;
        grid-template-columns: 108px minmax(0, 1fr);
        align-items: center;
        column-gap: 1.2rem;
    }

        .product-configurator-modal .cfg-piece .cfg-piece-photo {
            grid-row: span 2;
        }

        .product-configurator-modal .cfg-piece .cfg-qty-control {
            justify-content: flex-start;
        }
}

/* On a phone the column beside a 108px photograph is too narrow for a sentence and a stepper: the
   stepper takes the tile's full width under both. */
@media (max-width: 480px) {
    .product-configurator-modal .cfg-piece .cfg-qty-control {
        grid-column: 1 / -1;
    }

    .product-configurator-modal .cfg-piece .cfg-piece-photo {
        grid-row: auto;
        align-self: start;
    }
}

/* Two tiles take half a wide panel each, and square photographs that size put the steppers below a
   laptop's fold. */
@media (min-width: 901px) {
    .product-configurator-modal .cfg-pieces--two .cfg-piece-photo {
        width: min(100%, 200px);
    }
}

@media (prefers-reduced-motion: reduce) {
    .product-configurator-modal .cfg-piece-photo img {
        transition: none;
    }

    .product-configurator-modal .cfg-piece:hover .cfg-piece-photo img {
        transform: none;
    }
}

/* The dialog stacks here, and a block container ignores `order` — so it becomes a flex column,
   which keeps the tiles above the summary that totals them instead of below it. */
@media (max-width: 760px) {
    .configurator-modal-dialog--rail {
        display: flex;
        flex-direction: column;
    }

        /* The column is exactly one screen tall and scrolls itself, and both halves carry min-height: 0
           from the two-column layout. Allowed to shrink, flex squeezes them into that one screen and their
           content spills out over each other: the rail's amounts and button painted across the tiles. Each
           half keeps its own height and the dialog scrolls instead. */
        .product-configurator-modal .configurator-modal-dialog--rail > .configurator-modal-content,
        .product-configurator-modal .configurator-modal-dialog--rail > .configurator-modal-intro--rail {
            flex: none;
        }

    /* A transform makes the dialog the containing block of its fixed children, so the close button
       scrolled away with the panel and a phone was left with no way out but the backdrop, which the
       full-screen dialog covers. Once the entrance has played the dialog carries no transform. */
    .product-configurator-modal.is-open .configurator-modal-dialog {
        transform: none;
    }

        /* The column already follows the panel on a phone, so a floor under the wizard only opens a gap
           between the last control and the price. */
        .configurator-modal-dialog--rail .cfg-wizard {
            min-height: 0;
        }

        .configurator-modal-dialog--rail .configurator-modal-intro--rail {
            overflow: visible;
            padding: 1.9rem 1.4rem max(1.5rem, env(safe-area-inset-bottom));
            border-left: 0;
            border-top: 1px solid var(--line);
        }
}
/* #endregion */
