﻿/* ===== Olleco eCommerce: surface + motion theme layer =====
   Loaded AFTER site.css + ecommerce.css.

   Marketing sign-off (Aug 2026) retired the glassmorphism direction: the
   ambient teal→lime gradient burst, the drifting blobs and the translucent
   frosted surfaces are gone, because Olleco don't use gradient backgrounds.
   The page is now plain white, and what were "glass" surfaces are ordinary
   white cards with a light-grey border and a soft shadow. The --glass-*
   tokens are kept (rather than renamed across ~40 rules) and simply
   redefined as white/grey, so this file stays a single place to retune
   surface treatment. */

:root {
  --spring: cubic-bezier(.16, 1, .3, 1);          /* expo-out "spring" feel */
  --glass: #fff;
  --glass-strong: #fff;
  --glass-border: var(--line);
  --glass-shadow: 0 24px 60px -22px rgba(9, 55, 51, .18);
  --glass-shadow-sm: 0 8px 24px -14px rgba(9, 55, 51, .16);
  --glass-blur: 16px;
  /* Combined height of the sticky header + the cut-off banner that now sticks
     with it. Anything that pins itself below the header (sticky galleries, the
     summary card, the cookie bar) offsets by this. */
  --sticky-top: 112px;
}
@media (max-width: 900px) { :root { --sticky-top: 104px; } }
@media (max-width: 560px) { :root { --sticky-top: 96px; } }

/* Plain white canvas: no gradient burst, no ambient blobs. */
html { background: #fff; }
body { background: #fff; }

/* ===== Header → solid white bar ===== */
.header {
  background: #fff;
  border-bottom: 1px solid var(--line);
}
.header.shrink {
  background: #fff;
  box-shadow: var(--glass-shadow-sm);
}

/* Cut-off banner → solid teal (no translucency now the page behind is white) */
.cutoff-banner { background: var(--teal); }

/* Page head band → white, with no separating rule at all (Marketing asked for
   the white line under the title to go). */
.page-head { background: #fff; border-bottom: none; }

/* ===== Product cards → frosted glass with fluid hover =====
   NOTE: no backdrop-filter on any surface that hosts product imagery. In
   Chromium, a child's mix-blend-mode does not composite through an ancestor
   with backdrop-filter, which resurrects the shots' white backgrounds. The
   page gradient behind these is smooth, so the blur added nothing anyway. */
.product-card {
  background: var(--glass);
  border: 1px solid var(--glass-border);
  box-shadow: var(--glass-shadow-sm);
  border-radius: var(--r-lg);
  transition: transform .45s var(--spring), box-shadow .45s var(--spring), border-color .3s;
}
.product-card:hover {
  transform: translateY(-8px) scale(1.015);
  box-shadow: var(--glass-shadow);
  border-color: rgba(193, 215, 46, .75);
}
/* The pack shots carry their own studio-grey backdrop, so the tile behind them
   stays out of the way (no wash, no padding). */
.product-card .media { background: none; }
.product-card .media img { transition: transform .6s var(--spring); }
.product-card:hover .media img { transform: scale(1.05); }

/* Staggered entrance for the catalogue grid (30-50ms per card) */
.product-grid .product-card { animation: card-in .55s var(--spring) both; }
.product-grid .product-card:nth-child(1)  { animation-delay: 0ms; }
.product-grid .product-card:nth-child(2)  { animation-delay: 40ms; }
.product-grid .product-card:nth-child(3)  { animation-delay: 80ms; }
.product-grid .product-card:nth-child(4)  { animation-delay: 120ms; }
.product-grid .product-card:nth-child(5)  { animation-delay: 160ms; }
.product-grid .product-card:nth-child(6)  { animation-delay: 200ms; }
.product-grid .product-card:nth-child(7)  { animation-delay: 240ms; }
.product-grid .product-card:nth-child(8)  { animation-delay: 280ms; }
.product-grid .product-card:nth-child(n+9){ animation-delay: 320ms; }
@keyframes card-in { from { opacity: 0; transform: translateY(22px) scale(.98); } }

/* ===== Buttons → glass depth + press feedback ===== */
.btn {
  transition: transform .3s var(--spring), box-shadow .3s var(--spring), background .2s;
  box-shadow: 0 6px 18px -8px rgba(168, 189, 34, .55);
}
.btn:hover { transform: translateY(-3px); }
.btn:active { transform: translateY(0) scale(.97); transition-duration: .12s; }
.btn-ghost {
  background: rgba(255, 255, 255, .4);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  box-shadow: none;
}

/* ===== Form surfaces → frosted glass ===== */
.form-card, .summary-card, .buy-box, .info-box, .cutoff-card, .pay-mock {
  background: var(--glass);
  -webkit-backdrop-filter: blur(var(--glass-blur));
  backdrop-filter: blur(var(--glass-blur));
  border: 1px solid var(--glass-border);
  box-shadow: var(--glass-shadow-sm);
}
/* Fields are outlined in grey, not white: these carried a near-white border
   from the glass look, which was invisible once the background went white, so
   the inputs read as floating labels with no box at all. */
select, .field-input,
.form-card input, .form-card select, .form-card textarea {
  background: #fff;
  border: 1px solid var(--dot);
  transition: background .2s, border-color .2s, box-shadow .25s var(--spring);
}
select:hover, .field-input:hover,
.form-card input:hover, .form-card select:hover, .form-card textarea:hover {
  border-color: #adb2a7;
}
select:focus, .field-input:focus,
.form-card input:focus, .form-card select:focus, .form-card textarea:focus {
  background: #fff;
  box-shadow: 0 0 0 4px rgba(193, 215, 46, .35);
  outline: none; border-color: var(--lime);
}
/* "Choose a size first" highlight. Defined here, in the last-loaded sheet, and
   repeated for :focus, otherwise the generic select styling above (which also
   fires on focus, since showSizeError() focuses the field) paints over it. */
select.needs-pick, select.needs-pick:focus {
  border: 1px solid #b3261e;
  box-shadow: 0 0 0 4px rgba(179, 38, 30, .16);
}

/* Quantity stepper → glass pill */
.qty {
  background: rgba(255, 255, 255, .6);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-color: var(--glass-border);
}
.qty button { transition: background .18s, transform .18s var(--spring); }
.qty button:active { transform: scale(.9); }

/* ===== PDP gallery + accordions ===== */
.pdp .gallery {
  border: 1px solid var(--glass-border);
  box-shadow: var(--glass-shadow-sm);
}
.accordion .panel { transition: max-height .4s var(--spring); }

/* Basket thumbnails: same tinted wash as the big imagery (shots are
   transparent PNGs, so no blend tricks needed) */
.cart-table .prod img { background: rgba(230, 237, 195, .55); }

/* ===== Basket table / stacked rows ===== */
.cart-table {
  /* no backdrop-filter: see product-card note (breaks the white knockout) */
  background: var(--glass);
  border: 1px solid var(--glass-border);
  box-shadow: var(--glass-shadow-sm);
}
@media (max-width: 640px) {
  .cart-table { background: transparent; border: none; box-shadow: none; }
  .cart-table tr {
    background: var(--glass);
    border: 1px solid var(--glass-border);
  }
}

/* Delivery option + segmented toggle */
.delivery-opt {
  background: rgba(238, 244, 207, .65);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.seg {
  background: rgba(255, 255, 255, .5);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-color: var(--glass-border);
}
.seg label { transition: background .25s var(--spring), color .2s; }

/* Address lookup dropdown → floating glass */
.lookup-results {
  background: rgba(255, 255, 255, .8);
  -webkit-backdrop-filter: blur(var(--glass-blur));
  backdrop-filter: blur(var(--glass-blur));
  border: 1px solid var(--glass-border);
  box-shadow: var(--glass-shadow);
}

/* ===== Confirmation tick: springy pop ===== */
.confirm-hero .tick { animation: tick-pop .6s var(--spring) both .15s; box-shadow: 0 14px 34px -12px rgba(168, 189, 34, .7); }
@keyframes tick-pop { from { opacity: 0; transform: scale(.4); } 60% { transform: scale(1.08); } to { opacity: 1; transform: scale(1); } }

/* ===== Footer → deep teal with glass panels ===== */
footer { background: linear-gradient(160deg, #093733 0%, #0b423d 100%); }
.socials a, .badge-pill {
  background: rgba(255, 255, 255, .07);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, .14);
  transition: transform .3s var(--spring), background .2s, border-color .2s;
}
.socials a:hover, .badge-pill:hover { transform: translateY(-3px); }

/* Basket badge pulse when count changes (class re-added by JS is optional; run on load) */
.basket-count { transition: transform .3s var(--spring); }
.basket-link:hover .basket-count { transform: scale(1.15); }

/* Empty state breathing room on glass */
.empty-state {
  background: var(--glass);
  -webkit-backdrop-filter: blur(var(--glass-blur));
  backdrop-filter: blur(var(--glass-blur));
  border: 1px solid var(--glass-border);
  border-radius: var(--r-lg);
}

/* ═════════════════════════════════════════════════════════════════════════
   PREMIUM LAYER: editorial serif display, liquid-glass sheen, choreographed
   reveals. Durations 400-600ms with the same spring curve for a slower, more
   deliberate "expensive" rhythm.
   ═════════════════════════════════════════════════════════════════════════ */

:root {
  --sheen: linear-gradient(115deg, transparent 30%, rgba(255, 255, 255, .55) 48%, rgba(233, 236, 214, .35) 52%, transparent 70%);
}

/* ===== Display type: Gotham Rounded per brand guidelines, scaled up ===== */
h1, .page-head h1, .pdp h1, .confirm-hero h1 {
  font-weight: 700;
  letter-spacing: -.025em;
  line-height: 1.06;
}
.page-head h1 { font-size: clamp(2.2rem, 4.2vw, 3.4rem); }
.pdp h1 { font-size: clamp(2rem, 3.6vw, 3rem); }
.page-head .lead { font-size: clamp(1.02rem, 1.5vw, 1.18rem); color: var(--muted); }

/* refined small-caps eyebrow rhythm on breadcrumbs */
.breadcrumb {
  text-transform: uppercase; letter-spacing: .16em; font-size: .68rem; font-weight: 700;
}

/* Prices: larger, confident numerals (Gotham) */
.buy-box .price, .product-card .price, .pay-mock .amount {
  font-weight: 700;
  letter-spacing: -.01em;
  font-variant-numeric: lining-nums tabular-nums;
}
.buy-box .price { font-size: 2.4rem; }
.product-card .price { font-size: 1.35rem; }

/* ===== Logo: left-aligned in the top bar, matching olleco.co.uk =====
   (Was absolutely centred; Marketing asked for it to line up with the main
   website, i.e. hard left against the content gutter.) */
.header .bar { position: relative; }
.header .brand {
  display: inline-flex; align-items: center; align-self: center;
  /* site.css ships the marketing header's logo-on-the-right rules
     (order:3, margin-left:20px); reset both so the logo leads the bar. */
  order: 0; margin: 0; z-index: 2;
}
.header .brand img { height: 46px; width: auto; transition: height .3s var(--ease); }
.header.shrink .brand img { height: 38px; }
@media (max-width: 1400px) {
  .header .brand img { height: 40px; }
}

/* Align the header's content box with the page content (.wrap) so the basket
   icon lines up with the right edge of the cards/summary below it, and make the
   basket the right-most control (the mobile menu burger sits to its left). */
.header > .wrap {
  max-width: var(--max);
  padding-left: clamp(20px, 4vw, 40px);
  padding-right: clamp(20px, 4vw, 40px);
}
.header .bar-right .burger { order: -1; }

/* ===== Cookie consent (Civic Cookie Control) =====
   Civic's notify bar and re-open handle were previously forced to the TOP of the
   viewport, because the old oil-pool animation occupied the bottom strip. That
   animation is gone, and top-pinning was actively harmful on phones: the notify
   panel covered the hero and pushed the page content out of view on first visit.
   Civic's own bottom-anchored default is left in place. */
/* "Accept all cookies" as the clear primary CTA: same lime/teal pairing as the
   site's other primary buttons (e.g. "Browse the oils"), not Civic's default
   outline styling shared with Reject/Manage settings. */
#ccc-notify-accept, #ccc-content-accept, #ccc button.ccc-accept-button {
  background: var(--lime) !important;
  border-color: var(--lime) !important;
  color: var(--teal) !important;
  font-weight: 700 !important;
}
#ccc-notify-accept:hover, #ccc-content-accept:hover, #ccc button.ccc-accept-button:hover {
  background: var(--lime-dark) !important;
  border-color: var(--lime-dark) !important;
}


/* ===== Page-head choreography: title rises out of a clip, lead follows ===== */
.page-head { padding: clamp(40px, 6vw, 72px) 0; }
.page-head .breadcrumb { animation: lux-fade .8s var(--spring) both; }
.page-head h1, .page-head .lead { opacity: 0; animation: lux-rise .9s var(--spring) both; }
.page-head h1 { animation-delay: .08s; }
.page-head .lead { animation-delay: .22s; }
@keyframes lux-rise { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }
@keyframes lux-fade { from { opacity: 0; } to { opacity: 1; } }

/* ===== Liquid sheen sweep: cards & primary buttons catch the light ===== */
.product-card, .btn, .pdp .gallery { position: relative; isolation: isolate; overflow: hidden; }
.product-card::after, .pdp .gallery::after, .btn::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: var(--sheen);
  background-size: 250% 100%;
  background-position: 130% 0;
  opacity: 0;
  transition: opacity .3s;
}
.product-card:hover::after, .pdp .gallery:hover::after, .btn:hover::after {
  opacity: 1;
  animation: lux-sheen .9s var(--spring) both;
}
@keyframes lux-sheen { from { background-position: 130% 0; } to { background-position: -60% 0; } }

/* slower, weightier card lift (premium = unhurried) */
.product-card { transition: transform .6s var(--spring), box-shadow .6s var(--spring), border-color .45s; }
.product-card:hover {
  transform: translateY(-10px) scale(1.02);
  box-shadow: 0 34px 80px -28px rgba(9, 55, 51, .45);
}
.product-card .media img { transition: transform .9s var(--spring); }
.product-card:hover .media img { transform: scale(1.07) translateY(-4px); }

/* iridescent edge glow on glass hover: liquid-glass signature */
.product-card, .buy-box, .form-card, .summary-card { background-clip: padding-box; }
.product-card:hover {
  border-color: transparent;
  background-image:
    linear-gradient(var(--glass), var(--glass)),
    linear-gradient(130deg, rgba(193, 215, 46, .8), rgba(255, 255, 255, .9) 40%, rgba(14, 79, 73, .35) 75%, rgba(193, 215, 46, .8));
  background-origin: border-box;
  background-clip: padding-box, border-box;
}

/* ===== Buttons: slower lift, sheen, letterspaced confidence ===== */
.btn {
  letter-spacing: .02em;
  transition: transform .45s var(--spring), box-shadow .45s var(--spring), background .25s;
}
.btn:hover { transform: translateY(-3px); box-shadow: 0 20px 44px -14px rgba(168, 189, 34, .65); }
.btn:active { transform: translateY(0) scale(.97); transition-duration: .12s; }

/* ===== Header: quieter, more rarefied ===== */
.header { border-bottom-color: var(--line); }
.nav-item>a { letter-spacing: .08em; text-transform: uppercase; font-size: .74rem; font-weight: 600; }

/* cut-off banner: lighter-touch luxury concierge note */
.cutoff-banner { font-size: .86rem; letter-spacing: .02em; }

/* ===== Scroll reveals (elements tagged .lux-reveal by js/site.js) ===== */
.lux-reveal { opacity: 0; transform: translateY(30px); transition: opacity .8s var(--spring), transform .8s var(--spring); transition-delay: var(--lux-delay, 0ms); }
.lux-reveal.in { opacity: 1; transform: none; }

/* ═════════════════════════════════════════════════════════════════════════
   HERO (catalogue page): asymmetric editorial split. Left-aligned statement
   with a self-drawing lime underline; floating glass packshot on a golden
   disc to the right. GSAP (js/motion.js) choreographs the load sequence and
   parallax; the CSS here is the resting state.
   ═════════════════════════════════════════════════════════════════════════ */

.hero-shop { padding: clamp(44px, 7vw, 96px) 0 clamp(20px, 3vw, 44px); overflow: hidden; }
.hero-shop-grid {
  display: grid; grid-template-columns: 1.08fr .92fr;
  gap: clamp(28px, 5vw, 72px); align-items: center;
}
.hero-copy .eyebrow { margin-bottom: 6px; }
.hero-title {
  font-size: clamp(2.5rem, 5.4vw, 4.2rem);
  font-weight: 700; letter-spacing: -.03em; line-height: 1.04;
  margin: 14px 0 0;
}
.hero-title .line { display: block; overflow: hidden; padding-bottom: .08em; margin-bottom: -.08em; }
.hero-title .line-inner { display: inline-block; will-change: transform; }
.hl-draw { position: relative; font-style: normal; white-space: nowrap; }
.hl-draw .stroke {
  position: absolute; left: -2%; right: -2%; bottom: -.12em; width: 104%; height: .32em;
  overflow: visible; pointer-events: none;
}
.hl-draw .stroke path {
  fill: none; stroke: var(--lime); stroke-width: 5; stroke-linecap: round;
  opacity: .9;
}
.hero-copy .lead { margin-top: 22px; max-width: 46ch; font-size: clamp(1.05rem, 1.6vw, 1.2rem); }
.hero-ctas { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 32px; }
.hero-marks {
  list-style: none; display: flex; gap: clamp(16px, 2.5vw, 34px); flex-wrap: wrap;
  /* light-grey dotted rule, not the old white line */
  margin: 38px 0 0; padding: 22px 0 0; border-top: 1px dotted var(--dot);
}
.hero-marks li {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: .82rem; font-weight: 600; color: var(--teal);
  letter-spacing: .02em;
}
.hero-marks svg { width: 20px; height: 20px; color: var(--lime-dark); flex: none; }

/* Small print qualifying the "at your door tomorrow" headline. Deliberately
   legible rather than hidden: it is the thing that makes the claim accurate.
   Originally lived inside the narrow hero-copy column (hence the 60ch reading
   width); now sits under the full product listing, so it spans the page width
   like everything else there, with room below before the footer. */
.hero-caveat {
  margin: 18px 0 48px; max-width: none;
  font-size: .78rem; line-height: 1.6; color: var(--muted);
}
.hero-caveat a { text-decoration: underline; }
.hero-caveat a:hover { color: var(--teal); }
/* Footnote marker on the headline itself, so the claim is visibly qualified. */
.claim-ref {
  font-size: .42em; vertical-align: super; line-height: 0;
  color: var(--lime-dark); text-decoration: none; margin-left: .06em;
  /* the glyph is tiny; pad the hit area out to something tappable */
  display: inline-block; padding: 14px; margin: -14px -14px -14px calc(.06em - 14px);
}
.claim-ref:hover { color: var(--teal); }

.hero-visual { position: relative; justify-self: center; width: min(100%, 430px); }
/* The blurred golden "disc" glow behind the packshot was part of the gradient
   look Marketing asked us to drop; removed from the markup, rule kept out. */
.visual-card {
  position: relative; z-index: 1;
  background: #f7f8f6;
  border: 1px solid var(--glass-border);
  border-radius: var(--r-xl);
  box-shadow: var(--glass-shadow);
  padding: clamp(24px, 4vw, 44px);
  aspect-ratio: 1/1; display: grid; place-items: center;
  /* Sits square: the old rotate(-1.5deg) read as the card "tilting to the
     left", which Marketing flagged as an alignment fault. */
  transform: none;
}
.visual-card img { max-width: 100%; max-height: 100%; object-fit: contain; }

/* Hero product showcase: slides stack in the card's single grid cell and
   crossfade with a gentle rise; js/site.js cycles them and syncs the chip. */
.visual-card .slide {
  grid-area: 1 / 1;
  opacity: 0; transform: translateY(12px) scale(.96);
  transition: opacity .65s ease, transform .9s var(--spring);
}
.visual-card .slide.active { opacity: 1; transform: none; }
.visual-card .dots {
  grid-area: 1 / 1; align-self: end; justify-self: center;
  display: flex; gap: 7px; padding-bottom: 2px;
}
.visual-card .dots span {
  width: 6px; height: 6px; border-radius: 50%;
  background: rgba(31, 76, 61, .18);
  transition: background .3s, transform .3s;
}
.visual-card .dots span.on { background: var(--lime-dark); transform: scale(1.3); }
.visual-chip { transition: opacity .22s ease, transform .22s ease; }
.visual-chip.swap { opacity: 0; transform: translateY(6px); }
@media (prefers-reduced-motion: reduce) {
  .visual-card .slide { transition: none; }
}
.visual-chip {
  position: absolute; z-index: 2; right: -6%; top: 7%;
  display: flex; flex-direction: column; gap: 1px;
  background: rgba(255, 255, 255, .8);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border: 1px solid var(--glass-border);
  border-radius: 16px; padding: 12px 18px;
  box-shadow: var(--glass-shadow-sm), inset 0 1px 0 rgba(255, 255, 255, .7);
}
.visual-chip strong { font-size: .88rem; color: var(--teal); }
.visual-chip span { font-size: .8rem; font-weight: 700; color: var(--lime-dark); }

.range-head { margin: clamp(28px, 4vw, 48px) 0 6px; }
.range-head h2 { font-size: clamp(1.7rem, 3.2vw, 2.4rem); letter-spacing: -.025em; margin-top: 12px; }
/* Shared with the warrant section heading (Marketing: match "Eight oils, one
   quick checkout" exactly) so the two font-size values can't drift apart. */
.range-head-size { font-size: clamp(1.7rem, 3.2vw, 2.4rem); letter-spacing: -.025em; }

/* When GSAP owns the entrances, the CSS load-stagger stands down */
.gsap-on .product-grid .product-card { animation: none; }

@media (max-width: 900px) {
  .hero-shop-grid { grid-template-columns: 1fr; }
  .hero-visual { width: min(78vw, 340px); margin-top: 8px; }
  .visual-chip { right: 0; }
}

/* ===== Footer: editorial signature (Gotham) ===== */
.signup h4 { font-weight: 700; font-size: 1.5rem; }
/* "Find out more about Olleco" reads as a link inside the brand blurb */
.foot-inline-link { color: var(--lime); text-decoration: underline; white-space: nowrap; }
.foot-inline-link:hover { color: #fff; }
/* App badges now sit under the social links in the brand column */
.foot-brand .app-badges { margin-top: 18px; }
.foot-col h5 { letter-spacing: .14em; text-transform: uppercase; font-size: .78rem; }

/* ===== Reduced motion: kill the ambient + entrance animation (site.css already
   zeroes transitions globally; this covers the fixed blobs + keyframes here) ===== */
@media (prefers-reduced-motion: reduce) {
  .product-grid .product-card { animation: none; }
  .confirm-hero .tick { animation: none; }
  .page-head h1, .page-head .lead, .page-head .breadcrumb { animation: none; opacity: 1; transform: none; }
  .product-card::after, .btn::after, .pdp .gallery::after { display: none; }
  .lux-reveal { opacity: 1; transform: none; transition: none; }
}

/* Cookie re-open handle: Civic writes width/height inline on both the button and
   its image, so overriding needs !important. The icon is square (160x160 source),
   so width and height are kept equal and the image is contained rather than
   stretched, which keeps it in ratio at every size. */
#ccc #ccc-icon {
  width: 52px !important;
  height: 52px !important;
}
#ccc #ccc-icon img {
  width: 100% !important;
  height: 100% !important;
  object-fit: contain !important;
}
/* Phones have far less room, and this floats over the content, so scale it down. */
@media (max-width: 560px) {
  #ccc #ccc-icon { width: 40px !important; height: 40px !important; }
}

/* ===== Disabled buttons: actually look disabled =====
   .btn's --bg/--fg custom properties default to lime/teal-deep regardless of the
   disabled attribute, so a disabled "Add to basket" (no size chosen) rendered
   with full colour, cursor:pointer and a working hover lift — indistinguishable
   from a live button. A customer would click it, the browser correctly refuses
   to fire anything on a disabled control, and nothing happened: no basket
   change, no error, no visual cue why. Placed here (last-loaded sheet) so it
   wins over the hover/sheen rules declared earlier in this same file. */
.btn:disabled, .btn[disabled] {
  --bg: var(--line);
  --fg: var(--muted);
  cursor: not-allowed;
  box-shadow: none;
}
.btn:disabled:hover, .btn[disabled]:hover {
  transform: none;
  box-shadow: none;
}
.btn:disabled::after, .btn[disabled]::after {
  display: none; /* kill the lux-sheen hover sweep */
}
