/* ==========================================================================
   CREATE YOUR OWN GIFT
   --------------------------------------------------------------------------
   Two screens: choosing a box, and filling it.

   The filling screen is the one that matters. It has to make a form with
   thirty radio buttons feel like arranging things in a box, so the inputs are
   hidden and their labels become the surface - the tick, the lift and the
   ring all key off :checked and :focus-visible on the real input, which keeps
   the whole thing keyboard-navigable and screen-reader correct for free.
   ========================================================================== */

/* ==========================================================================
   1. HERO  (box chooser)
   ========================================================================== */

.bx-hero {
    background: linear-gradient(160deg, var(--tbs-green) 0%, var(--tbs-green-deep) 100%);
    color: var(--white);
    padding: var(--sp-8) 0 var(--sp-7);
    text-align: center;
}

.bx-hero__eyebrow {
    display: inline-block;
    font-size: var(--fs-eyebrow);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--gold);
    margin-bottom: var(--sp-3);
}

.bx-hero__title {
    font-family: var(--font-display);
    font-size: var(--fs-h1);
    line-height: var(--lh-heading);
    letter-spacing: var(--tracking-display);
    margin: 0 0 var(--sp-3);
    color: var(--white);
}

.bx-hero__intro {
    max-width: 56ch;
    margin: 0 auto;
    color: rgba(255, 255, 255, .82);
    line-height: var(--lh-body);
}

.bx-steps {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: var(--sp-5);
    list-style: none;
    margin: var(--sp-6) 0 0;
    padding: 0;
    font-size: var(--fs-small);
    color: rgba(255, 255, 255, .78);
}

.bx-steps li {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
}

.bx-steps span {
    display: grid;
    place-items: center;
    width: 24px;
    height: 24px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--gold);
    color: var(--gold);
    font-size: .75rem;
    font-weight: 700;
}

.bx-wrap { padding: var(--sp-7) 0 var(--sp-8); }

.bx-note {
    margin: var(--sp-6) auto 0;
    max-width: 66ch;
    font-size: .82rem;
    line-height: 1.6;
    color: var(--ink-mute);
}

.bx-empty {
    text-align: center;
    padding: var(--sp-8) var(--sp-4);
    max-width: 46ch;
    margin: 0 auto;
}

.bx-empty h2 { font-family: var(--font-display); margin: 0 0 var(--sp-3); }
.bx-empty p  { color: var(--ink-mute); margin: 0 0 var(--sp-5); }

/* ==========================================================================
   2. BOX CARDS
   ========================================================================== */

.bx-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: var(--sp-5);
}

.bx-grid > * { min-width: 0; max-width: 100%; }

.bx-box {
    display: flex;
    flex-direction: column;
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    transition: box-shadow var(--dur-component) var(--ease-brand),
                transform var(--dur-component) var(--ease-brand),
                border-color var(--dur-micro) var(--ease-brand);
}

.bx-box:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-lift);
    border-color: var(--tbs-green);
}

.bx-box:focus-visible {
    outline: 2px solid var(--tbs-green);
    outline-offset: 3px;
}

.bx-box__media {
    position: relative;
    aspect-ratio: 1 / 1;
    background: var(--cream-deep);
    overflow: hidden;
}

.bx-box__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform var(--dur-section) var(--ease-brand);
}

.bx-box:hover .bx-box__media img { transform: scale(1.04); }

.bx-box__ph {
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(45deg,
        var(--cream-deep) 0 12px, var(--cream) 12px 24px);
}

.bx-box__slots {
    position: absolute;
    left: var(--sp-3);
    bottom: var(--sp-3);
    background: rgba(0, 48, 31, .88);
    color: var(--white);
    font-size: .72rem;
    letter-spacing: .04em;
    padding: 5px 10px;
    border-radius: var(--radius-pill);
}

/* Tells the customer there is more to see before they commit to opening it. */
.bx-box__photos {
    position: absolute;
    right: var(--sp-3);
    bottom: var(--sp-3);
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: rgba(255, 255, 255, .92);
    color: var(--tbs-green);
    font-size: .7rem;
    font-weight: 600;
    padding: 4px 9px;
    border-radius: var(--radius-pill);
}

.bx-box__body {
    padding: var(--sp-4);
    display: flex;
    flex-direction: column;
    flex: 1;
}

.bx-box__name {
    font-family: var(--font-display);
    font-size: 1.0625rem;
    line-height: 1.3;
    margin: 0 0 var(--sp-2);
    color: var(--tbs-green);
}

.bx-box__blurb {
    font-size: var(--fs-small);
    color: var(--ink-mute);
    line-height: 1.5;
    margin: 0 0 var(--sp-4);
    flex: 1;
}

.bx-box__foot {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-3);
    padding-top: var(--sp-3);
    border-top: 1px solid var(--line);
}

.bx-box__price { font-weight: 700; color: var(--ink); font-size: .9rem; }

.bx-box__go {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: .8rem;
    color: var(--tbs-green);
    font-weight: 600;
}

.bx-box__go svg { transition: transform var(--dur-micro) var(--ease-brand); }
.bx-box:hover .bx-box__go svg { transform: translateX(3px); }

/* ==========================================================================
   3. CONFIGURE LAYOUT
   ========================================================================== */

.bx-cfg { padding: var(--sp-5) 0 var(--sp-9); }

.bx-cfg__grid {
    display: grid;

    /* minmax(0, 1fr), never plain 1fr.
       A grid item's default min-width is auto, which means it refuses to be
       narrower than its contents. The rails and the jump nav are wide flex rows,
       so with 1fr the column grew past the viewport and the whole page scrolled
       sideways on a phone. This is the fix for that. */
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sp-6);
    align-items: start;
}

/* Belt and braces: any child of the grid, whatever it turns out to be. */
.bx-cfg__grid > * { min-width: 0; }

.bx-cfg__main { min-width: 0; }

@media (min-width: 900px) {
    .bx-cfg__grid { grid-template-columns: minmax(0, 1fr) 320px; gap: var(--sp-7); }
}

.bx-cfg__head { margin-bottom: var(--sp-6); }

.bx-cfg__head h1 {
    font-family: var(--font-display);
    font-size: var(--fs-h2);
    color: var(--tbs-green);
    margin: 0 0 var(--sp-2);
}

.bx-cfg__head p { color: var(--ink-mute); margin: 0; font-size: var(--fs-small); }

.bx-alert {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-3);
    background: #FBEEEE;
    border: 1px solid rgba(176, 65, 62, .3);
    border-left: 3px solid var(--danger);
    color: #7A2C2A;
    padding: var(--sp-4);
    border-radius: var(--radius-card);
    margin-bottom: var(--sp-5);
    font-size: var(--fs-small);
}

.bx-alert svg { flex: none; margin-top: 1px; }

/* ==========================================================================
   4. THE FILL METER
   The one thing on the page that answers "how much room is left?", so it
   sticks below the header and stays visible while the customer scrolls the
   product list.
   ========================================================================== */

.bx-meter {
    position: sticky;
    top: 68px;
    z-index: 2;
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    padding: var(--sp-4);
    margin-bottom: var(--sp-6);
    box-shadow: var(--shadow-card);
}

.bx-meter__head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--sp-3);
    margin-bottom: var(--sp-3);
    font-size: var(--fs-small);
}

.bx-meter__label { font-weight: 600; color: var(--ink); }
.bx-meter__left  { color: var(--ink-mute); font-size: .8rem; }
.bx-meter__left.is-full { color: var(--tbs-green); font-weight: 700; }

.bx-meter__track {
    height: 8px;
    border-radius: var(--radius-pill);
    background: var(--cream-deep);
    overflow: hidden;
}

.bx-meter__fill {
    display: block;
    height: 100%;
    width: 0;
    border-radius: var(--radius-pill);
    background: linear-gradient(90deg, var(--gold) 0%, var(--tbs-green) 100%);
    transition: width var(--dur-component) var(--ease-brand);
}

.bx-meter__fill.is-full { background: var(--tbs-green); }

.bx-meter.is-shake { animation: bxShake 420ms var(--ease-brand); }

@keyframes bxShake {
    0%, 100% { transform: translateX(0); }
    25%      { transform: translateX(-5px); }
    75%      { transform: translateX(5px); }
}

/* ==========================================================================
   5. FORMAT TABS, PANELS AND SEARCH
   Only one format is shown at a time. The hidden panels still contain their
   inputs so the form posts everything, but the browser never lays them out.
   ========================================================================== */

/* ---- Jump nav ----
   Not tabs any more: every format is on the page at once, so these scroll to
   one rather than swapping panels. They keep the running count per format,
   which is the part that was genuinely useful. */

.bx-tabs {
    display: flex;
    gap: var(--sp-2);
    overflow-x: auto;
    padding-bottom: var(--sp-2);
    margin-bottom: var(--sp-4);
    scrollbar-width: thin;
    -webkit-overflow-scrolling: touch;
}

.bx-tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    flex: none;
    padding: 9px 14px;
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
    background: var(--white);
    font: inherit;
    font-size: .84rem;
    color: var(--ink);
    cursor: pointer;
    white-space: nowrap;
    transition: border-color var(--dur-micro) var(--ease-brand),
                background var(--dur-micro) var(--ease-brand);
}

.bx-tab:hover { border-color: var(--ink-mute); }

/* Filled in only once something from that format is in the box. */
.bx-tab.has-picks {
    background: var(--tbs-green);
    border-color: var(--tbs-green);
    color: var(--white);
}

.bx-tab:focus-visible { outline: 2px solid var(--tbs-green); outline-offset: 2px; }

.bx-tab__name { font-weight: 600; }

.bx-tab__meta { font-size: .72rem; opacity: .6; }

.bx-tab__badge[hidden] { display: none; }

.bx-tab__badge {
    min-width: 19px;
    height: 19px;
    display: grid;
    place-items: center;
    padding: 0 5px;
    border-radius: var(--radius-pill);
    background: var(--gold);
    color: #3A2C10;
    font-size: .68rem;
    font-weight: 700;
}

.bx-tab.has-picks .bx-tab__badge { background: var(--white); color: var(--tbs-green); }

.bx-tab__must { color: var(--gold); font-size: 1.1rem; line-height: 0; }
.bx-tab.has-picks .bx-tab__must { color: var(--gold-soft); }

/* ---- One format = one scrolling line ---- */

.bx-panel { margin: 0 0 var(--sp-6); scroll-margin-top: 150px; }
.bx-panel[hidden] { display: none; }

/* An off-screen rail is skipped by layout and paint, which is what keeps a
   long catalogue cheap now that every format is on the page together. */
.bx-panel {
    content-visibility: auto;
    contain-intrinsic-size: auto 320px;
}

.bx-panel__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-3);
    flex-wrap: wrap;
    padding-bottom: var(--sp-3);
    margin-bottom: var(--sp-4);
    border-bottom: 1px solid var(--line);
}

.bx-panel__title {
    font-family: var(--font-display);
    font-size: 1.0625rem;
    color: var(--tbs-green);
    margin: 0;
}

.bx-panel__rules {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex-wrap: wrap;
    font-size: .78rem;
    color: var(--ink-mute);
}

.bx-panel__cost { font-weight: 600; }

/* ---- The rail itself ---- */

.bx-railwrap { position: relative; }

.bx-rail {
    display: flex;
    gap: var(--sp-3);
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scroll-behavior: smooth;
    scrollbar-width: thin;
    -webkit-overflow-scrolling: touch;

    /* Room for the card lift and focus ring, which would otherwise be clipped
       by the scroll container. */
    padding: 4px 2px 12px;
    margin: -4px -2px 0;
}

.bx-rail > .bx-pick {
    flex: 0 0 132px;
    scroll-snap-align: start;
}

@media (max-width: 560px) {
    .bx-rail > .bx-pick { flex-basis: 118px; }
}

.bx-rail::-webkit-scrollbar { height: 6px; }
.bx-rail::-webkit-scrollbar-thumb { background: var(--line); border-radius: var(--radius-pill); }

.bx-railbtn {
    position: absolute;
    top: 50px;                 /* centred on the image, not the whole card */
    z-index: 2;
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
    background: var(--white);
    color: var(--tbs-green);
    cursor: pointer;
    box-shadow: var(--shadow-card);
    transition: opacity var(--dur-micro) var(--ease-brand);
}

/* Inside the panel box, not hanging off it.
   .bx-panel carries content-visibility:auto, which implies paint containment —
   anything positioned outside the panel's own box gets clipped away. These used
   to sit at -14px and simply vanished. */
.bx-railbtn--prev { left: 0; }
.bx-railbtn--next { right: 0; }

.bx-railbtn:disabled { opacity: 0; pointer-events: none; }

/* They overlay the end cards, so a soft fade sits behind each one - otherwise
   the button floats on top of a bottle and both are hard to read. */
.bx-railwrap::before,
.bx-railwrap::after {
    content: "";
    position: absolute;
    top: 4px;
    bottom: 12px;
    width: 46px;
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--dur-micro) var(--ease-brand);
    z-index: 1;
}

.bx-railwrap::before {
    left: 0;
    background: linear-gradient(90deg, var(--cream) 35%, transparent);
}

.bx-railwrap::after {
    right: 0;
    background: linear-gradient(270deg, var(--cream) 35%, transparent);
}

.bx-railwrap.can-prev::before,
.bx-railwrap.can-next::after { opacity: 1; }

.bx-railbtn:focus-visible { outline: 2px solid var(--tbs-green); outline-offset: 2px; }

/* Touch scrolls natively and the buttons only get in the way of a thumb. */
@media (hover: none), (max-width: 700px) {
    .bx-railbtn { display: none; }
}

/* ---- Search ---- */

.bx-search {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    padding: 0 var(--sp-3);
    margin-bottom: var(--sp-5);
    border: 1px solid var(--line);
    border-radius: var(--radius-pill);
    background: var(--white);
    color: var(--ink-mute);
}

.bx-search:focus-within { border-color: var(--tbs-green); }

.bx-search input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: none;
    padding: 10px 0;
    font-family: inherit;
    font-size: var(--fs-body);   /* 16px, or iOS zooms on focus */
    color: var(--ink);
}

.bx-search input:focus { outline: none; }
.bx-search input::-webkit-search-cancel-button { display: none; }

.bx-search__clear {
    flex: none;
    border: 0;
    background: none;
    font-size: 1.25rem;
    line-height: 1;
    color: var(--ink-mute);
    cursor: pointer;
    padding: 0 2px;
}

.bx-noresult {
    padding: var(--sp-5);
    margin: 0 0 var(--sp-5);
    background: var(--cream);
    border-radius: var(--radius-card);
    font-size: var(--fs-small);
    color: var(--ink-mute);
    text-align: center;
}

.link-like {
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
    color: var(--tbs-green);
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}

.bx-group__meta {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex-wrap: wrap;
    font-size: .76rem;
    color: var(--ink-mute);
}

.bx-group__rule {
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    background: var(--cream-deep);
    color: var(--ink-mute);
    font-size: .7rem;
    letter-spacing: .03em;
}

.bx-group__rule--must { background: var(--gold-soft); color: #7A5A1E; font-weight: 600; }

.bx-group__count {
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    background: var(--tbs-green);
    color: var(--white);
    font-size: .7rem;
    font-weight: 700;
}

.bx-group.is-capped .bx-group__rule { background: var(--tbs-green-soft); color: var(--tbs-green); }

/* ==========================================================================
   6. A PRODUCT
   ========================================================================== */

.bx-picks {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: var(--sp-3);
}

.bx-picks > * { min-width: 0; }

.bx-pick {
    display: flex;
    flex-direction: column;
    position: relative;
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    background: var(--white);
    overflow: hidden;
    transition: border-color var(--dur-micro) var(--ease-brand),
                box-shadow var(--dur-micro) var(--ease-brand),
                opacity var(--dur-micro) var(--ease-brand);
}

/* display:flex above beats the browser's own [hidden] rule, so search would
   filter nothing without this. Same trap as .bx-panel. */
.bx-pick[hidden] { display: none; }

.bx-pick.is-chosen {
    border-color: var(--tbs-green);
    box-shadow: inset 0 0 0 1px var(--tbs-green), var(--shadow-card);
}

/* Nothing left it could fit into. Dimmed rather than removed, so the page does
   not reflow under the customer's finger every time they add something. */
.bx-pick.is-blocked { opacity: .42; }

/* Tapping a card that will not fit. Without this the tap reads as a dead
   button rather than a refusal. */
.bx-pick__add.is-refused { animation: bxRefuse 380ms var(--ease-brand); }

@keyframes bxRefuse {
    0%, 100% { transform: translateX(0); }
    30%      { transform: translateX(-4px); }
    70%      { transform: translateX(4px); }
}

.bx-pick__media {
    position: relative;
    display: block;
    aspect-ratio: 1 / 1;
    background: var(--cream);
    /* Nothing escapes the square: the zoom control, the quantity badge and the
       add button are all pinned to its edges. */
    overflow: hidden;
}


/* display:grid beats the browser's own [hidden] rule, which is why the badge
   sat there as an empty green disc on every unchosen card. */
.bx-pick__chosen[hidden] { display: none; }

.bx-pick__chosen {
    position: absolute;
    top: 6px;
    right: 6px;
    min-width: 24px;
    height: 24px;
    display: grid;
    place-items: center;
    padding: 0 6px;
    border-radius: var(--radius-pill);
    background: var(--tbs-green);
    color: var(--white);
    font-size: .74rem;
    font-weight: 700;
    animation: bxPop var(--dur-micro) var(--ease-brand);
}

/* Product shots are bottles and tubes: tall subjects photographed on a plain
   ground. cover crops to fill, which takes the cap off a shower gel and the
   base off a lotion tube — so these are contained, with a little breathing
   room. The card is a picker; the customer needs to recognise the product, not
   admire it. */
.bx-pick__media img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: 8%;
    display: block;
}

.bx-pick__swatch,
.bx-pick__ph { position: absolute; inset: 0; }

.bx-pick__ph {
    background: repeating-linear-gradient(45deg,
        var(--cream-deep) 0 8px, var(--cream) 8px 16px);
}

/* ---- The image is the add button ----
   One tap adds one. Tapping again adds another. This is the whole selection
   interaction; the stepper below is for taking one back out. */

/* Absolutely filling the media box, not sitting inside it.

   As a static block the button had auto height, so the image's height:100%
   resolved against nothing and fell back to the picture's own proportions.
   Portrait bottle shots then made every card tall, the square crop was lost,
   and the + badge pinned to the button's bottom edge ended up outside the
   frame. Making the button the same box as .bx-pick__media restores all three. */
.bx-pick__add {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
}

.bx-pick__add:focus-visible { outline: 2px solid var(--tbs-green); outline-offset: -2px; }

.bx-pick__plus {
    position: absolute;
    left: 6px;
    bottom: 6px;
    display: grid;
    place-items: center;
    width: 24px;
    height: 24px;
    border-radius: var(--radius-pill);
    background: var(--tbs-green);
    color: var(--white);
    font-size: 1rem;
    line-height: 1;
    opacity: 0;
    transform: scale(.75);
    transition: opacity var(--dur-micro) var(--ease-brand),
                transform var(--dur-micro) var(--ease-brand);
}

/* Shown on hover and focus for pointers; always visible on touch, where there
   is no hover to reveal it with. */
.bx-pick:hover .bx-pick__plus,
.bx-pick__add:focus-visible .bx-pick__plus { opacity: 1; transform: none; }

@media (hover: none) {
    .bx-pick__plus { opacity: .9; transform: none; }
}

.bx-pick.is-chosen .bx-pick__plus { background: var(--gold); color: #3A2C10; }

/* ---- Enlarge ---- */

.bx-pick__zoom {
    position: absolute;
    top: 5px;
    left: 5px;
    z-index: 1;
    display: grid;
    place-items: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 0;
    border-radius: var(--radius-pill);
    background: rgba(255, 255, 255, .9);
    color: var(--tbs-green);
    cursor: zoom-in;
    opacity: 0;
    transition: opacity var(--dur-micro) var(--ease-brand);
}

.bx-pick:hover .bx-pick__zoom,
.bx-pick__zoom:focus-visible { opacity: 1; }

@media (hover: none) {
    .bx-pick__zoom { opacity: .85; }
}

/* ---- Text: two lines, no more ---- */

.bx-pick__text {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 6px;
    padding: 7px 8px 8px;
    flex: 1;
}

.bx-pick__name {
    font-size: .76rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--ink);
    min-width: 0;

    /* Two lines then ellipsis: a long name must not make one card in the rail
       taller than the rest, because flex stretch would grow every card with it. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.bx-pick__price {
    flex: none;
    font-size: .74rem;
    font-weight: 700;
    color: var(--tbs-green);
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   The stepper.
   The number input is the real control - it is what posts, what a keyboard
   reaches and what a screen reader announces. The buttons only drive it.
   -------------------------------------------------------------------------- */

.bx-qty {
    display: flex;
    align-items: stretch;
    border-top: 1px solid var(--line);
}

/* With JavaScript the stepper is only needed once something has been added —
   until then the image itself is the control, and hiding it takes ~40px off
   every card on the page.

   Gated on .js-on so that with scripting unavailable the stepper is always
   visible and the whole builder still works as a plain form. */
.js-on .bx-pick:not(.is-chosen) .bx-qty { display: none; }

.bx-qty__btn {
    flex: none;
    width: 34px;
    min-height: 34px;
    border: 0;
    background: var(--cream);
    color: var(--tbs-green);
    font-size: 1.125rem;
    line-height: 1;
    cursor: pointer;
    transition: background var(--dur-micro) var(--ease-brand);
}

.bx-qty__btn:hover:not(:disabled) { background: var(--tbs-green-soft); }

.bx-qty__btn:disabled {
    opacity: .3;
    cursor: not-allowed;
}

.bx-qty__btn:focus-visible {
    outline: 2px solid var(--tbs-green);
    outline-offset: -2px;
}

.bx-qty__in {
    flex: 1;
    min-width: 0;
    width: 100%;
    border: 0;
    border-left: 1px solid var(--line);
    border-right: 1px solid var(--line);
    text-align: center;
    font-family: inherit;
    font-size: var(--fs-body);   /* 16px: anything smaller and iOS zooms the page */
    font-weight: 700;
    padding: 0;
    color: var(--ink);
    background: var(--white);
    -moz-appearance: textfield;
}

/* The native spinners duplicate the buttons either side of them. */
.bx-qty__in::-webkit-outer-spin-button,
.bx-qty__in::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.bx-qty__in:focus-visible {
    outline: 2px solid var(--tbs-green);
    outline-offset: -2px;
}

.bx-pick.is-chosen .bx-qty__in { color: var(--tbs-green); }

/* ==========================================================================
   7. RUNNING SUMMARY
   ========================================================================== */

.bx-sum__inner {
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    padding: var(--sp-5);
}

@media (min-width: 900px) {
    .bx-sum__inner { position: sticky; top: 96px; }
}

/* ---- Packaging gallery -------------------------------------------------
   The box is half of what the customer is choosing, so every photograph the
   merchandiser uploaded is reachable rather than only the primary one. */

.bx-gal { margin: 0 0 var(--sp-4); }

.bx-gal__main {
    position: relative;
    display: block;
    width: 100%;
    padding: 0;
    border: 0;
    border-radius: var(--radius-card);
    overflow: hidden;
    background: var(--cream-deep);
    cursor: zoom-in;
}

.bx-gal__main img {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
}

.bx-gal__main:focus-visible { outline: 2px solid var(--tbs-green); outline-offset: 2px; }

.bx-gal__zoom {
    position: absolute;
    right: 8px;
    bottom: 8px;
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: var(--radius-pill);
    background: rgba(0, 48, 31, .82);
    color: var(--white);
}

.bx-gal__strip {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    margin-top: 6px;
    padding-bottom: 4px;
    scrollbar-width: thin;
}

.bx-gal__thumb {
    flex: none;
    width: 52px;
    height: 52px;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    overflow: hidden;
    background: var(--cream);
    cursor: pointer;
    opacity: .72;
    transition: opacity var(--dur-micro) var(--ease-brand),
                border-color var(--dur-micro) var(--ease-brand);
}

.bx-gal__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

.bx-gal__thumb:hover { opacity: 1; }

.bx-gal__thumb.is-on {
    opacity: 1;
    border-color: var(--tbs-green);
    box-shadow: inset 0 0 0 1px var(--tbs-green);
}

.bx-gal__thumb:focus-visible { outline: 2px solid var(--tbs-green); outline-offset: 1px; }

.bx-gal__cap {
    margin: 6px 0 0;
    font-size: .74rem;
    color: var(--ink-mute);
    text-align: center;
}

/* ---- Lightbox ---- */

.bx-lightbox {
    border: 0;
    padding: 0;
    max-width: min(92vw, 900px);
    max-height: 92vh;
    background: transparent;
    overflow: visible;
}

.bx-lightbox::backdrop { background: rgba(0, 48, 31, .8); }

.bx-lightbox img {
    display: block;
    width: 100%;
    height: auto;
    max-height: 92vh;
    object-fit: contain;
    border-radius: var(--radius-card);
}

.bx-lightbox__close {
    position: absolute;
    top: -14px;
    right: -14px;
    z-index: 1;
    width: 36px;
    height: 36px;
    border: 0;
    border-radius: var(--radius-pill);
    background: var(--white);
    color: var(--ink);
    font-size: 1.375rem;
    line-height: 1;
    cursor: pointer;
    box-shadow: var(--shadow-card);
}

@media (max-width: 600px) {
    .bx-lightbox__close { top: 8px; right: 8px; }
}

.bx-sum__img {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: var(--radius-card);
    margin-bottom: var(--sp-4);
}

.bx-sum__box {
    font-family: var(--font-display);
    font-size: 1.0625rem;
    color: var(--tbs-green);
    margin: 0;
}

.bx-sum__boxprice {
    font-size: .78rem;
    color: var(--ink-mute);
    margin: 4px 0 0;
}

.bx-sum__list {
    list-style: none;
    margin: var(--sp-4) 0 0;
    padding: 0;
    font-size: var(--fs-small);
}

.bx-sum__list li {
    display: flex;
    justify-content: space-between;
    gap: var(--sp-3);
    padding: 7px 0;
    border-bottom: 1px dashed var(--line);
    animation: bxIn var(--dur-micro) var(--ease-brand);
}

.bx-sum__list li span:first-child { min-width: 0; overflow-wrap: anywhere; }
.bx-sum__list li span:last-child  { flex: none; color: var(--ink-mute); }

@keyframes bxIn {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: none; }
}

.bx-sum__empty {
    font-size: .8rem;
    color: var(--ink-mute);
    margin: var(--sp-4) 0 0;
    font-style: italic;
}

.bx-sum__total {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--sp-3);
    margin-top: var(--sp-4);
    padding-top: var(--sp-4);
    border-top: 1px solid var(--line);
    font-size: var(--fs-small);
}

.bx-sum__total strong { font-size: 1.25rem; color: var(--tbs-green); }

.bx-sum__qty {
    display: block;
    margin: var(--sp-5) 0 var(--sp-4);
    font-size: .8rem;
    color: var(--ink-mute);
}

.bx-sum__qty input {
    display: block;
    width: 100%;
    margin-top: var(--sp-2);
    padding: 10px 12px;
    font-size: var(--fs-body);   /* 16px: anything smaller and iOS zooms the page */
    font-family: inherit;
    color: var(--ink);
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius-input);
}

.bx-sum__qty input:focus-visible {
    outline: 2px solid var(--tbs-green);
    outline-offset: 1px;
}

.bx-sum__note {
    font-size: .74rem;
    line-height: 1.55;
    color: var(--ink-mute);
    margin: var(--sp-3) 0 0;
    text-align: center;
}

.bx-sum__note.is-warn { color: var(--warning); font-weight: 600; }

/* ==========================================================================
   8. MOBILE STICKY BAR
   ========================================================================== */

.bx-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: var(--z-sticky);
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    padding-bottom: calc(var(--sp-3) + env(safe-area-inset-bottom, 0px));
    background: var(--white);
    border-top: 1px solid var(--line);
    box-shadow: var(--shadow-sticky);
}

.bx-bar[hidden] { display: none; }

@media (min-width: 900px) {
    .bx-bar { display: none !important; }
}

.bx-bar__info { flex: 1; min-width: 0; line-height: 1.3; }
.bx-bar__label { display: block; font-size: .74rem; color: var(--ink-mute); }
.bx-bar__total { font-size: 1.0625rem; color: var(--tbs-green); }
.bx-bar .b { flex: none; min-height: 46px; }

/* ==========================================================================
   9. CONFIRMATION
   ========================================================================== */

.bx-done {
    max-width: 640px;
    padding: var(--sp-8) var(--sp-4) var(--sp-9);
    text-align: center;
}

.bx-done__mark {
    display: grid;
    place-items: center;
    width: 58px;
    height: 58px;
    margin: 0 auto var(--sp-5);
    border-radius: var(--radius-pill);
    background: var(--tbs-green);
    color: var(--white);
    animation: bxPop var(--dur-component) var(--ease-brand);
}

@keyframes bxPop {
    from { opacity: 0; transform: scale(.7); }
    to   { opacity: 1; transform: none; }
}

.bx-done h1 {
    font-family: var(--font-display);
    font-size: var(--fs-h2);
    color: var(--tbs-green);
    margin: 0 0 var(--sp-3);
}

.bx-done__lede {
    color: var(--ink-mute);
    line-height: var(--lh-body);
    margin: 0 auto var(--sp-6);
    max-width: 50ch;
}

.bx-done__card {
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    text-align: left;
    overflow: hidden;
}

.bx-done__box {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    padding: var(--sp-4);
    background: var(--cream);
    border-bottom: 1px solid var(--line);
}

.bx-done__box img {
    width: 68px;
    height: 68px;
    object-fit: cover;
    border-radius: var(--radius-card);
    flex: none;
}

.bx-done__box h2 {
    font-family: var(--font-display);
    font-size: 1.0625rem;
    color: var(--tbs-green);
    margin: 0;
}

.bx-done__box p { font-size: .8rem; color: var(--ink-mute); margin: 3px 0 0; }

.bx-done__items { list-style: none; margin: 0; padding: 0; }

.bx-done__items li {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--line);
}

.bx-done__items img,
.bx-done__ph {
    width: 42px;
    height: 42px;
    flex: none;
    object-fit: cover;
    border-radius: var(--radius-card);
    background: var(--cream-deep);
}

.bx-done__item-text { flex: 1; min-width: 0; }
.bx-done__item-text strong { display: block; font-size: .86rem; font-weight: 600; }
.bx-done__item-text span   { display: block; font-size: .72rem; color: var(--ink-mute); }

.bx-done__qty   { font-size: .8rem; color: var(--ink-mute); flex: none; }
.bx-done__price { font-size: .86rem; font-weight: 600; flex: none; }

.bx-done__totals { padding: var(--sp-4); font-size: var(--fs-small); }

.bx-done__totals div {
    display: flex;
    justify-content: space-between;
    gap: var(--sp-3);
    padding: 4px 0;
    color: var(--ink-mute);
}

.bx-done__grand {
    margin-top: var(--sp-3);
    padding-top: var(--sp-3) !important;
    border-top: 1px solid var(--line);
    color: var(--ink) !important;
}

.bx-done__grand strong { font-size: 1.1875rem; color: var(--tbs-green); }

.bx-done__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--sp-3);
    margin-top: var(--sp-6);
}

/* ==========================================================================
   10. PHONE LAYOUT
   The desktop arrangement puts the box in a right-hand column. Stacked, that
   column lands underneath every product, so the customer would fill a box they
   cannot see. Below 900px it moves to the top and turns compact.
   ========================================================================== */

@media (max-width: 899px) {

    /* Room for the sticky bar, plus the phone's own home indicator. */
    .bx-cfg {
        padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px));
    }

    .bx-sum { order: -1; }

    /* The gallery and the box's details sit side by side rather than stacking,
       which is what keeps this to about 130px instead of 450px. */
    .bx-sum__inner {
        display: grid;
        grid-template-columns: 104px minmax(0, 1fr);
        column-gap: var(--sp-4);
        align-items: start;
        padding: var(--sp-4);
    }

    .bx-gal {
        grid-column: 1;
        grid-row: 1 / span 2;
        margin: 0;
    }

    .bx-gal__thumb { width: 30px; height: 30px; }
    .bx-gal__cap { display: none; }

    .bx-sum__box     { grid-column: 2; }
    .bx-sum__boxprice { grid-column: 2; }

    /* Everything below the box header runs full width beneath it. */
    .bx-sum__list,
    .bx-sum__empty,
    .bx-sum__total,
    .bx-sum__qty,
    .bx-sum__note,
    #bxSubmit {
        grid-column: 1 / -1;
    }

    /* The sticky bar already carries a submit button, and two of them a
       thumb-length apart is a way to make someone tap the wrong thing. */
    #bxSubmit { display: none; }

    .bx-sum__qty { margin: var(--sp-4) 0 0; }

    /* Header is shorter on a phone, so the meter sits higher. */
    .bx-meter { top: 56px; padding: var(--sp-3); }
    .bx-meter__head { font-size: .8rem; }

    .bx-cfg__head { margin-bottom: var(--sp-4); }

    /* Rails run to the screen edges. A card half-cut at the edge is the clearest
       possible signal that the row scrolls; boxed-in rails read as complete.

       --bleed tracks .container's own padding, which steps up at 768px — hard
       coding one value would leave an 8px gutter on tablets. */
    .bx-cfg { --bleed: var(--sp-4); }

    .bx-railwrap { margin-inline: calc(var(--bleed) * -1); }

    .bx-rail {
        padding-inline: var(--bleed);
        scroll-padding-inline: var(--bleed);
    }
}

@media (min-width: 768px) and (max-width: 899px) {
    .bx-cfg { --bleed: var(--sp-5); }
}

@media (max-width: 899px) {

    .bx-panel { margin-bottom: var(--sp-5); }
    .bx-panel__head { margin-bottom: var(--sp-3); }
    .bx-panel__title { font-size: 1rem; }

    .bx-tabs { margin-bottom: var(--sp-3); }
    .bx-tab { padding: 7px 12px; font-size: .8rem; }
}

/* ==========================================================================
   11. REDUCED MOTION
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
    .bx-box,
    .bx-box__media img,
    .bx-pick,
    .bx-meter__fill,
    .bx-qty__btn,
    .bx-box__go svg { transition: none; }

    .bx-box:hover { transform: none; }

    .bx-sum__list li,
    .bx-pick__chosen,
    .bx-meter.is-shake,
    .bx-pick__add.is-refused,
    .bx-done__mark { animation: none; }

    .bx-pick__plus,
    .bx-pick__zoom { transition: none; opacity: 1; transform: none; }
}
