/* ============================================================
   CC UI — the product page
   Loaded on the product controller only. Restyles the THEME's product layout
   (tv-product-1.tpl, already rearranged by us) plus the hooks our own modules drop
   into it — cc_stockdisplay, cc_storeavailability, cc_sizeguide, cc_socialshare,
   cc_productaccordions, cc_relatedproducts — so the whole page reads as one design
   instead of six modules each with their own idea.

   The heavy lifting the page already does is kept: the info panel, the size chips,
   the stock + delivery line, the accordions. What changes is that they now share the
   shop's tokens, its pills, and its signature.
   ============================================================ */

/* ------------------------------------------------------------------- panel */
/* THE CARD IS .tvproduct-page-wrapper — it already exists.
   custom.css gives it `background: #ffffff; padding: 2rem`, so it is ALREADY a white
   padded box wrapping the whole hero. Every card we added inside it was therefore a
   white card inside a white box. Nothing new gets added here: the wrapper is simply
   finished — a hairline, the bottom rounding, a soft shadow — and the photo and the
   info sit straight on it. */
.tvproduct-page-wrapper {
  position: relative;
  border: 1px solid var(--cc-hairline);
  border-radius: 0 0 var(--cc-radius, 14px) var(--cc-radius, 14px);
  box-shadow: var(--cc-shadow-card);
  overflow: hidden;
}
/* The signature, over the INFO half only. The info column is a col-md-6, so it starts
   at exactly 50% of the wrapper — measured at 1200, 1440 and 1920, it is 50.00% every
   time — which lets the bar hang off the wrapper itself and still land precisely where
   the column begins. It runs to the card's right edge; top corners squared, because a
   straight bar and a rounded corner never agree.
   Over the photo as well it would stop being a heading and become a stripe. */
.tvproduct-page-wrapper::before {
  content: "";
  position: absolute;
  top: 0; left: 50%; right: 0;
  height: 4px;
  background: linear-gradient(90deg,
    var(--cc-accent-1)   0 14.2857%,
    var(--cc-accent-2) 14.2857% 28.5714%,
    var(--cc-accent-3) 28.5714% 42.8571%,
    var(--cc-accent-4)  42.8571% 57.1428%,
    var(--cc-accent-5)   57.1428% 71.4285%,
    var(--cc-accent-6)   71.4285% 85.7142%,
    var(--cc-accent-7) 85.7142% 100%);
}

/* the row inside it is just a row — no surface of its own */
.tvprduct-image-info-wrapper.product-1 {
  position: relative;
  display: flex; align-items: center;
  margin: 0 !important;
  padding: 0 !important;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  overflow: visible;
}
.tvprduct-image-info-wrapper.product-1::before { content: none; }

/* the info column: no card of its own either */
div.col-md-6.tv-product-page-content,
.tvproduct-page-wrapper div.col-md-6.tv-product-page-content {
  position: relative;
  padding: 0 0 0 34px !important;
  background: none !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  overflow: visible;
}
div.col-md-6.tv-product-page-content::before { content: none !important; }

/* --------------------------------------------------------------- the title */
/* The theme Title-Cases it ("Disfraz Ninja Blue Dragon Para Niño"); the data says
   "Disfraz Ninja blue dragon para niño". Product names are data — print them as typed,
   the same rule we applied in the cart drawer. */
/* .tvproduct-title-brandimage in the chain: the theme styles the title as
   `.tvproduct-title-brandimage h1.h1 { font-size: clamp(…); color: #0a0a0a }`, which
   ties with a two-class selector of ours and wins on source order. */
.tv-product-page-content .tvproduct-title-brandimage h1.h1 {
  margin: 0 0 6px;
  font-size: 1.75rem; font-weight: 800; line-height: 1.2;
  letter-spacing: -.015em;
  color: var(--cc-ink);
  text-transform: none;
}
.tv-product-page-content .product-reference {
  margin: 0 0 18px;
  font-size: .8rem; color: var(--cc-ink-faint);
}
.tv-product-page-content .product-reference .label { font-weight: 600; }

/* --------------------------------------------------------------- the price */
.tv-product-page-content .product-prices { margin: 0 0 16px; }
.tv-product-page-content .product-price,
.tv-product-page-content .current-price span {
  font-size: 2rem !important; font-weight: 800;
  color: var(--cc-brand) !important;
  letter-spacing: -.02em;
}
/* The tax note is `.tvproduct-tax-label` (inside .product-price), NOT the
   .tax-shipping-delivery-label I first reached for — that one isn't what renders. And
   the words are typed "Impuestos Incluidos" in the string itself, so this is the usual
   lowercase-then-restore-the-capital treatment, not a text-transform to undo. */
.tv-product-page-content .tvproduct-tax-label {
  margin: 2px 0 0;
  font-size: .78rem !important; font-weight: 400 !important;
  color: var(--cc-ink-faint) !important;
  letter-spacing: 0 !important;
  text-transform: lowercase;
}
.tv-product-page-content .tvproduct-tax-label::first-letter { text-transform: uppercase; }

/* ------------------------------------------------------------ size / chips */
.tv-product-page-content .product-variants { margin: 0 0 16px; }
/* The row is a flex line with `align-items: center`, and the label carried a bottom
   margin left over from when it sat ABOVE the chips — in a centred flex row that margin
   is counted in the label's box, so it rode 4px high. Margin to the right, not below. */
.tv-product-page-content .product-variants .control-label {
  display: inline-flex; align-items: center;
  margin: 0 12px 0 0;
  font-size: .74rem; font-weight: 700; letter-spacing: .06em;
  color: var(--cc-ink-faint);
  text-transform: uppercase;
  white-space: nowrap;
}
.tv-product-page-content .product-variants ul { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.tv-product-page-content .product-variants li.input-container { float: none !important; margin: 0; }
/* the radio is the control; the label is the chip */
.tv-product-page-content .product-variants li label { margin: 0; cursor: pointer; }
.tv-product-page-content .product-variants li label .radio-label {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 62px; min-height: 40px; padding: 0 14px;
  border: 1.5px solid var(--cc-hairline); border-radius: 999px;
  background: var(--cc-surface);
  font-size: .84rem; font-weight: 600; color: var(--cc-ink-soft);
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.tv-product-page-content .product-variants li label:hover .radio-label {
  border-color: var(--cc-ink-soft); color: var(--cc-ink);
}
/* ---- the DROPDOWN variant ----
   Not every attribute group is chips: COLOR, NUMERO, MODELO and TALLA CALZADO are
   `select` groups in the back office (~300 products), and PrestaShop renders them as a
   <select>. It was shipping raw: 38px tall, 3px corners, a grey 1px border and 16px
   text — nothing like the chips beside it. Same pill language, plus a chevron of our
   own (the native arrow is hidden by `appearance: none`, which the theme already sets
   and then never replaces — so on some browsers there was no arrow at all). */
.tv-product-page-content .product-variants select.form-control {
  /* 40px, not 44: the chips beside it are 40, and a dropdown that is 2px taller than
     the chips in the same row is the kind of thing you can't unsee. !important because
     the theme pins its form-controls to 38px. */
  height: 40px !important;
  min-width: 110px;      /* a floor, not a width: the select sizes to its value */
  max-width: 100%;
  padding: 0 42px 0 16px;
  border: 1.5px solid var(--cc-hairline);
  border-radius: 999px;
  background-color: var(--cc-surface);
  color: var(--cc-ink);
  font-size: .88rem; font-weight: 600;
  cursor: pointer;
  box-shadow: none;
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23565d6b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  transition: border-color .15s ease;
}
.tv-product-page-content .product-variants select.form-control:hover { border-color: var(--cc-ink-soft); }
.tv-product-page-content .product-variants select.form-control:focus,
.tv-product-page-content .product-variants select.form-control:focus-visible {
  border-color: var(--cc-brand);
  outline: 2px solid var(--cc-brand-bright);
  outline-offset: 2px;
}

/* the selected size has to be unmistakable — it decides what goes in the cart */
.tv-product-page-content .product-variants li input.input-radio:checked + .radio-label {
  border-color: var(--cc-brand);
  background: var(--cc-brand);
  color: #fff;
}
.tv-product-page-content .product-variants li input.input-radio:focus-visible + .radio-label {
  outline: 2px solid var(--cc-brand-bright); outline-offset: 2px;
}

/* --------------------------------------------------- stock + delivery line */
/* No rails. Two hairlines around a single line of text fenced it off from the page for
   no reason — it's a fact about the product, not a section. (cc_stockdisplay's own CSS
   draws a bottom border at the same specificity and loads later, hence !important.) */
.tv-product-page-content .cc-stock-delivery-wrapper {
  display: flex; align-items: center; gap: 18px;
  margin: 0 0 18px; padding: 0;
  border: 0 !important;
  font-size: .87rem; color: var(--cc-ink-soft);
}
.tv-product-page-content .cc-stock-delivery-content {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
}

/* The stock state becomes a PILL — the same green the store-availability modal uses for
   "you can buy this right now", so the two agree at a glance. */
.tv-product-page-content .cc-stock-side {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px 6px 15px;      /* left > right: the dot must clear the pill's cap */
  border-radius: 999px;
  background: #e6f4ea;
  font-size: .8rem; font-weight: 700;
  color: #1f7a3d;
}
.tv-product-page-content .cc-stock-side .cc-stock-status-label { color: inherit; font: inherit; }
/* out of stock is grey, not red: it's a fact, not an error */
.tv-product-page-content .cc-stock-delivery-wrapper:has(.cc-dot-out) .cc-stock-side,
.tv-product-page-content .cc-stock-delivery-wrapper:has(.cc-dot-no) .cc-stock-side {
  background: var(--cc-surface-2);
  color: var(--cc-ink-faint);
}
/* low stock turns the pill amber — same scarcity language as PrestaShop's box below. The
   pill now carries the live count ("¡Solo quedan N!"), so it becomes the scarcity signal
   and the generic PS message is hidden (see the dedup rule further down). */
.tv-product-page-content .cc-stock-delivery-wrapper:has(.cc-dot-low) .cc-stock-side {
  background: #fdead0;
  color: #7a4a0c;
}
/* Out of stock reuses the exact in-stock pill (.cc-stock-side), so the two badges are
   pixel-identical — the :has(.cc-dot-out) rule above just recolours it grey (a fact, not an
   error). Only cc_stockdisplay's leftover .cc-oos-label margin needs zeroing so the label
   sits on the pill's 8px gap like the in-stock label does. The specific reason ("Sin stock
   para esta combinación") lives in the badge's title tooltip, not inline. */
.tv-product-page-content .cc-oos-text-wrapper .cc-oos-label { margin: 0; }

/* the delivery promise: quiet, but it's the second-best thing on the page after the
   price, so it keeps the truck and prints the date in ink */
.tv-product-page-content .cc-delivery-side {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: .85rem; color: var(--cc-ink-soft);
}
.tv-product-page-content .cc-delivery-side strong,
.tv-product-page-content .cc-delivery-side b { color: var(--cc-ink); font-weight: 700; }

/* DEDUPLICATION. At low stock two scarcity messages want to appear: PrestaShop's generic
   "Últimas unidades en stock" box and cc_stockdisplay's amber pill — which now carries the
   live count ("¡Solo quedan N!"). Keep OURS (it says more) and hide PrestaShop's, but only
   when our low pill is actually present (if the merchant turned the stock pill off, PS's
   message must stay as the sole scarcity signal). */
.tv-product-page-content:has(.cc-stock-side .cc-dot-low) #product-availability:has(.product-last-items) {
  display: none !important;
}

/* ------------------------------------------------------------ the buy line */
/* The stepper and the button are NOT siblings inside one row: the button lives in
   .tvcart-btn-model, the stepper in .product-quantity, and each carried its own
   margins — which is why they sat 6px out of line with each other. Make their common
   wrapper the flex row, centre them on it, and zero the margins that were doing the
   nudging. */
.tv-product-page-content .tv-product-page-add-to-cart-wrapper {
  display: flex; align-items: center; gap: 12px;
  margin: 0 0 12px;
}
.tv-product-page-content .tv-product-page-add-to-cart-wrapper .tvcart-btn-model {
  flex: 1 1 auto; margin: 0 !important;
}
.tv-product-page-content .product-add-to-cart .product-quantity {
  display: flex; align-items: center;
  flex: 0 0 auto;
  margin: 0 !important;
}
.tv-product-page-content .product-quantity > .control-label { display: none; }   /* the stepper says it */

/* quantity: the same stepper as the card, at product-page size */
.tv-product-page-content .product-quantity .qty { margin: 0; flex: 0 0 auto; }
/* The stepper reads "− 1 +", like the card's. The theme nests both buttons inside a
   `.input-group-btn-vertical` span, so their `order` was invisible to the outer flex
   row — `display: contents` dissolves that wrapper and lets the two buttons take their
   place around the number. */
/* four classes: custom.css keeps this wrapper `display: flex` with a three-class
   selector of its own, and a tie goes to whoever loads last */
.tv-product-page-content .product-add-to-cart .product-quantity .input-group-btn-vertical {
  display: contents !important;
}
.tv-product-page-content .product-add-to-cart .product-quantity .bootstrap-touchspin-down { order: 1 !important; }
.tv-product-page-content .product-add-to-cart .product-quantity input#quantity_wanted { order: 2 !important; }
.tv-product-page-content .product-add-to-cart .product-quantity .bootstrap-touchspin-up { order: 3 !important; }
/* the empty prefix/suffix addons the theme ships just add a hairline in the middle */
.tv-product-page-content .product-quantity .input-group-addon:empty { display: none !important; }

/* custom.css: `.tvproduct-page-wrapper .product-quantity .qty div.input-group
   { border: 1px solid #232323 !important; border-radius: 0 !important }` — three
   classes, an element and !important. Four classes + the element to beat it. */
.tv-product-page-content .product-add-to-cart .product-quantity .qty div.input-group {
  display: flex !important; align-items: center;
  height: 52px !important; width: auto;
  border: 1.5px solid var(--cc-hairline) !important;
  border-radius: 999px !important;
  overflow: hidden; background: var(--cc-surface);
}
/* custom.css draws two black rules INSIDE the pill:
     `.tvproduct-page-wrapper .product-quantity input[type="text"]#quantity_wanted
       { border-left: 1px solid #232323 !important; border-right: 1px solid #232323 !important }`
   — an ID, two classes, an attribute selector and !important. Out-rank it, and match
   the importance, or the number keeps its cell borders. */
.tvproduct-page-wrapper .product-add-to-cart .product-quantity input[type="text"]#quantity_wanted,
.tv-product-page-content .product-quantity input#quantity_wanted {
  width: 46px !important;
  /* SHORTER than the pill, and transparent. At the pill's full height its white
     background painted straight over the top and bottom border across its own width —
     which is why the outline had two gaps in the middle and the whole thing looked
     like it had no border at all. The gaps were the number field, not the +/− buttons. */
  height: 38px !important;
  min-height: 0 !important; max-height: none !important;
  align-self: center !important;
  padding: 0; margin: 0;
  border: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
  text-align: center; font-size: 1rem; font-weight: 700; color: var(--cc-ink);
}
.tv-product-page-content .product-quantity .bootstrap-touchspin-up,
.tv-product-page-content .product-quantity .bootstrap-touchspin-down {
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 50px; padding: 0;
  border: 0; background: none;
  color: var(--cc-ink-soft); font-size: 1rem; cursor: pointer;
}
.tv-product-page-content .product-quantity .bootstrap-touchspin-up:hover,
.tv-product-page-content .product-quantity .bootstrap-touchspin-down:hover { color: var(--cc-brand); }

/* ADD TO CART — the primary action of the page, and it should look like it. It was an
   outlined button of the same weight as "Consultar disponibilidad en tienda". */
/* The buy button is defended by custom.css with THREE classes and !important:
   `.tv-product-page-add-to-cart-wrapper .tvall-inner-btn.add-to-cart
     { background: #ffffff !important; border: 1px solid #232323 !important;
       border-radius: 0 !important }`
   — which is why it stayed a white square while its own text was white (invisible).
   Importance we can match; specificity we have to beat: three classes + the element. */
.tv-product-page-content .tv-product-page-add-to-cart-wrapper button.add-to-cart {
  flex: 1 1 auto;
  display: inline-flex !important; align-items: center; justify-content: center; gap: 10px;
  min-height: 52px; padding: 0 26px;
  border: 1.5px solid var(--cc-brand) !important;
  border-radius: 999px !important;
  background: var(--cc-brand) !important;
  color: #fff !important;
  font-size: .95rem; font-weight: 700; text-transform: none;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, transform .15s ease;
}
.tv-product-page-content .tv-product-page-add-to-cart-wrapper button.add-to-cart:hover:not(:disabled) {
  background: var(--cc-surface-deep) !important; border-color: var(--cc-surface-deep) !important;
  transform: translateY(-1px);
}
.tv-product-page-content .tv-product-page-add-to-cart-wrapper button.add-to-cart:disabled {
  background: var(--cc-surface-2) !important;
  border-color: transparent !important;
  color: var(--cc-ink-faint) !important;
  cursor: not-allowed;
}
.tv-product-page-content .tv-product-page-add-to-cart-wrapper button.add-to-cart i,
.tv-product-page-content .tv-product-page-add-to-cart-wrapper button.add-to-cart .material-icons {
  color: currentColor !important; font-size: 20px;
}
/* The SPAN inside is what shouts ("AÑADIR AL CARRITO") — and custom.css also paints it
   `color: #232323 !important`, which was written for the white button it used to be.
   On our brand-filled pill that's near-black text on dark blue. Both need answering
   with !important; plain `color: inherit` loses to importance every time. */
.tv-product-page-content .tv-product-page-add-to-cart-wrapper button.add-to-cart span {
  text-transform: none !important;
  letter-spacing: 0 !important;
  color: #fff !important;
  font: inherit;
}
.tv-product-page-content .tv-product-page-add-to-cart-wrapper button.add-to-cart:disabled span {
  color: var(--cc-ink-faint) !important;
}

/* ----------------------------------------------- secondary actions (ghost) */
/* Store availability (cc_storeavailability), size guide (cc_sizeguide) and share
   (cc_socialshare): three separate modules, three different button styles. One quiet
   ghost pill each — they are alternatives to buying, not competitors of it. */
.cc-sa-btn,
.cc-sg-btn,
.cc-socialshare__trigger {
  display: inline-flex !important; align-items: center; justify-content: center; gap: 8px;
  min-height: 46px; padding: 0 18px;
  border: 1.5px solid var(--cc-hairline) !important;
  border-radius: 999px !important;
  background: none !important;
  color: var(--cc-ink-soft) !important;
  font-size: .87rem; font-weight: 600; text-transform: none !important;
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
}
.cc-sa-btn:hover,
.cc-sg-btn:hover,
.cc-socialshare__trigger:hover {
  border-color: var(--cc-brand) !important;
  color: var(--cc-brand) !important;
}
.cc-socialshare__trigger { width: 46px; padding: 0 !important; }
.cc-sa-btn i, .cc-sg-btn i, .cc-socialshare__trigger i,
.cc-sa-btn svg, .cc-sg-btn svg, .cc-socialshare__trigger svg { color: currentColor; }

/* ------------------------------------------------------------- accordions */
/* Same again: the accordion's own CSS uppercases the title INSIDE the summary, so the
   summary's text-transform never reached it. The titles are typed sentence-case in the
   module config ("Envíos y entregas") — print them that way. */
.tv-product-page-content .cc-accordion__summary,
.tv-product-page-content .cc-accordion__summary * {
  font-size: .87rem; font-weight: 700; color: var(--cc-ink);
  text-transform: none !important;
  letter-spacing: 0;
}
.tv-product-page-content .cc-accordion__summary {
  padding: 16px 0;
  cursor: pointer;
}
.tv-product-page-content .cc-accordion__content {
  padding: 0 0 16px;
  font-size: .87rem; line-height: 1.6; color: var(--cc-ink-soft);
}

/* ---------------------------------------------------------------- gallery */
/* The photo gets the same white tile as every product image in the shop, so the
   product page and the card it was clicked from agree with each other. */
/* No tile, no frame: a bordered box on a white card is a box inside a box. The photo
   sits straight on the card, centred in its column so a short picture doesn't leave the
   white space reading as a hole. */
.tv-product-page-image { display: flex; align-items: center; justify-content: center; }
.tv-product-page-image .product-cover {
  background: none;
  border: 0;
  border-radius: 0;
  overflow: hidden;
}
.tv-product-page-image img.js-qv-product-cover { mix-blend-mode: multiply; }
/* Thumbnails only — `.product-images` is the THUMB strip. On a phone the gallery
   collapses and the main cover picked these rules up too, which is why the costume was
   sitting in a blue-bordered box. Scope them to the strip, and never to the cover. */
.tv-product-page-image .product-images li img,
.tv-product-page-image .product-images .thumb {
  border: 1px solid var(--cc-hairline) !important;
  border-radius: 10px;
  background: var(--cc-surface);
  mix-blend-mode: multiply;
}
.tv-product-page-image .product-images li.selected img,
.tv-product-page-image .product-images img.selected { border-color: var(--cc-brand) !important; }
.tv-product-page-image img.js-qv-product-cover { border: 0 !important; }

/* ------------------------------------------- related products ("Puede que…") */
.cc-relatedproducts__title {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  margin: 0 0 30px;
  font-size: 1.6rem !important; font-weight: 800 !important;
  color: var(--cc-ink) !important;
  text-align: center;
}
/* the signature, like every other section heading in the shop */
.cc-relatedproducts__title::after {
  content: "";
  width: 96px; height: 4px; border-radius: 3px;
  background: linear-gradient(90deg,
    var(--cc-accent-1)   0 14.2857%,
    var(--cc-accent-2) 14.2857% 28.5714%,
    var(--cc-accent-3) 28.5714% 42.8571%,
    var(--cc-accent-4)  42.8571% 57.1428%,
    var(--cc-accent-5)   57.1428% 71.4285%,
    var(--cc-accent-6)   71.4285% 85.7142%,
    var(--cc-accent-7) 85.7142% 100%);
}

/* ------------------------------------------------------- sticky buy bar */
/* Mobile only. On a phone the buy button scrolls away the moment you read anything —
   the description, the size guide, the related products — and coming back to it means
   scrolling up past the whole gallery. The bar keeps the price and the button one tap
   away. Injected by product.js, which mirrors the real button rather than replacing
   it: one add-to-cart flow, not two. */
.cc-buybar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 1000;
  display: none;                      /* shown by product.js, mobile only */
  align-items: center; gap: 12px;
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
  background: var(--cc-surface);
  border-top: 1px solid var(--cc-hairline);
  box-shadow: 0 -6px 24px rgba(15, 36, 64, .12);
  transform: translateY(110%);
  transition: transform .22s ease;
}
.cc-buybar.is-visible { transform: translateY(0); }
.cc-buybar__price {
  flex: 0 0 auto;
  font-size: 1.05rem; font-weight: 800; color: var(--cc-brand);
  white-space: nowrap;
}
.cc-buybar__btn {
  flex: 1 1 auto;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 46px; padding: 0 18px;
  border: 0; border-radius: 999px;
  background: var(--cc-brand); color: #fff;
  font-size: .92rem; font-weight: 700;
  cursor: pointer;
}
.cc-buybar__btn:disabled { background: var(--cc-surface-2); color: var(--cc-ink-faint); cursor: not-allowed; }
.cc-buybar__btn span { white-space: nowrap; }
/* The floating contact bubble lives bottom-right. When a bottom sticky bar is ACTUALLY on
   screen, lift the trigger and its panel clear of it — but never the backdrop, which has to
   keep covering the whole viewport (inset:0).
   The old rule was `body.cc-has-buybar [class*="contactpopup"] { bottom:88px }`. Two faults:
   the wildcard swept in the backdrop, so its bottom edge rose 88px and left an undimmed strip
   of page along the bottom when the panel was open; and it hung on cc-has-buybar, which we set
   on every product page — so the bubble sat lifted even with no bar showing. Now it keys off a
   bar being visible: our buy bar slid up (mobile) or the theme's product sticky shown (desktop),
   and only the TRIGGER moves — not the modal. The modal only shows once you tap the trigger,
   and by then the backdrop covers the bar, so the panel has nothing to clear; lifting a panel
   that can be nearly viewport-tall would only risk pushing its top (and the signature) off the
   top edge. So: lift the bubble, leave the panel where it opens. */
body:has(.cc-buybar.is-visible) .cc-contactpopup-trigger { bottom: 84px !important; }
body:has(.tvfooter-product-sticky-bottom.sticky) .cc-contactpopup-trigger { bottom: 110px !important; }

/* The columns stack below 768px, so a bar that starts at 50% would be a stripe over
   nothing. Full width when there is only one column. */
@media (max-width: 767px) {
  .tvproduct-page-wrapper::before { left: 0; }

  /* Size label ABOVE the CHIPS on a phone: they wrap onto two rows, so a label beside
     them centres against the whole block and lines up with nothing. Stacked, it reads
     as the heading it is.
     A DROPDOWN is different — it's one short control, so label and select stay on one
     line, exactly as they do on desktop. Stacking that one just made two rows out of
     something that comfortably fits in one. */
  .tv-product-page-content .product-variants-item {
    flex-direction: column;
    align-items: flex-start;
  }
  .tv-product-page-content .product-variants-item:has(select.form-control) {
    flex-direction: row;
    align-items: center;
  }
  .tv-product-page-content .product-variants-item:has(select.form-control) .control-label {
    margin: 0 12px 0 0;
    align-self: center;
  }
  /* align-self, not the container's align-items: something later sets
     `align-items: center` on the row, so in a COLUMN flex EVERY child gets centred
     horizontally — the label floated above left-aligned chips, and the <select> sat
     indented in the middle of the column. Both need pinning to the left. */
  .tv-product-page-content .product-variants .control-label {
    margin: 0 0 8px;
    align-self: flex-start;
  }
  .tv-product-page-content .product-variants ul {
    align-self: stretch;
    width: 100%;
  }
  /* the dropdown sizes to its value, it does not stretch: a full-width pill for the
     word "AMARILLO" is a very long way to say very little */
  .tv-product-page-content .product-variants select.form-control {
    align-self: flex-start;
    width: auto;
  }

  /* "Consultar disponibilidad en tienda" is 33 characters in a 208px button — it wrapped
     onto THREE lines and made a 77px-tall pill. The words shrink; the meaning doesn't. */
  .cc-sa-btn span {
    font-size: 0;
  }
  .cc-sa-btn span::after {
    content: "Disponibilidad en tienda";
    font-size: .84rem; font-weight: 600;
    white-space: nowrap;
  }

  /* custom.css turns the stepper into a full-width black square on phones:
       `.tvproduct-page-wrapper .product-quantity .qty.tv-product-qty-mobile
         { width: 100% !important; border: 1px solid #232323 !important;
           border-radius: 0 !important }`
     The pill lives on .input-group INSIDE it, so all this outer box does is draw a
     black rectangle around a rounded one. Blank it and let the pill show. */
  .tvproduct-page-wrapper .product-add-to-cart .product-quantity .qty.tv-product-qty-mobile {
    width: auto !important; max-width: none !important;
    margin: 0 !important;
    border: 0 !important;
    border-radius: 999px !important;
    overflow: visible !important;
  }
  /* …and it also stands the stepper on its end (`flex-direction: column !important` on
     the input-group), which is why − 1 + came out as a 52×104 tower. Put it back in a
     row, and dissolve the button wrapper again so the order survives. */
  /* The mobile rules hang off `.qty.tv-product-qty-mobile` — TWO classes on the same
     element — so a chain of ours with the same class count ties and loses on order.
     Match their hook and add one more class. */
  .tvproduct-page-wrapper .tv-product-page-content .product-add-to-cart .product-quantity .qty.tv-product-qty-mobile div.input-group,
  .tvproduct-page-wrapper .tv-product-page-content .product-add-to-cart .product-quantity .qty.tv-product-qty-mobile .bootstrap-touchspin {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    width: auto !important;
  }
  .tvproduct-page-wrapper .tv-product-page-content .product-add-to-cart .product-quantity .qty.tv-product-qty-mobile .input-group-btn-vertical {
    display: contents !important;
  }

  /* Stepper + button on ONE row. The element that stacks them on a phone is
     .tv-product-add-to-cart-action-wrapper (a flex COLUMN) — not the
     .tv-product-page-add-to-cart-wrapper we align on desktop; they are different
     boxes, nested, with confusingly similar names. */
  .tv-product-page-content .tv-product-add-to-cart-action-wrapper {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: center;
    gap: 10px;
  }
  .tv-product-page-content .tv-product-add-to-cart-action-wrapper .product-quantity {
    flex: 0 0 auto; width: auto !important;
  }
  .tv-product-page-content .tv-product-add-to-cart-action-wrapper .tvwishlist-compare-wrapper-page,
  .tv-product-page-content .tv-product-add-to-cart-action-wrapper .tvcart-btn-model {
    flex: 1 1 auto; min-width: 0; width: auto !important; margin: 0 !important;
  }
  /* The pill border, which the mobile rule strips
     (`.qty.tv-product-qty-mobile div.input-group { border: none !important }`) — the
     stepper must look the same as it does on desktop. */
  .tvproduct-page-wrapper .tv-product-page-content .product-add-to-cart .product-quantity .qty.tv-product-qty-mobile div.input-group {
    border: 1.5px solid var(--cc-hairline) !important;
    border-radius: 999px !important;
    background: var(--cc-surface) !important;
    height: 52px !important;
    /* the mobile rule clips this box (`overflow: hidden`), which is how a button that
       overflowed it could vanish without trace */
    overflow: visible !important;
    justify-content: center;
  }
  /* And the two buttons must not PAINT OVER it. custom.css gives them
     `background: #ffffff; width: 44px !important; height: 44px !important;
      border-radius: 0`, so a white 44px square sat on the pill: it covered the border
     along the top and bottom (the outline looked broken — "no border") and its hover
     tint spilled past the rounded ends. Transparent at rest, a circle on hover, and
     small enough to live inside the pill. */
  /* The rule that actually hides the "+" on a phone hangs off `.input-group-btn-vertical
     .btn` — five classes — and gives each button `width: 50% !important`. Two 50%
     buttons plus the number field don't fit, and the overflow is clipped, so the
     second one simply disappears. Match that exact hook and go one deeper. */
  .tvproduct-page-wrapper .tv-product-page-content .product-add-to-cart .product-quantity .qty.tv-product-qty-mobile .input-group-btn-vertical .btn,
  .tvproduct-page-wrapper .tv-product-page-content .product-add-to-cart .product-quantity .btn-touchspin,
  .tvproduct-page-wrapper .tv-product-page-content .product-add-to-cart .product-quantity .bootstrap-touchspin-up,
  .tvproduct-page-wrapper .tv-product-page-content .product-add-to-cart .product-quantity .bootstrap-touchspin-down {
    /* `flex: 0 0 38px` is the load-bearing one. The mobile rule sets
       `flex: 1 1 50%; min-height: 52px` on these buttons, and for a FLEX ITEM the
       flex-basis beats `width` — which is why a `width: 38px !important` kept
       computing to 18px, and min-height stretched them to the pill's full 52px so
       their white square covered its border. Basis, not width; and no min-height. */
    flex: 0 0 38px !important;
    width: 38px !important;
    height: 38px !important;
    min-height: 0 !important; max-height: none !important;
    align-self: center !important;
    margin: 0 3px !important;
    background: none !important;
    border: 0 !important;
    border-radius: 999px !important;
  }
  .tvproduct-page-wrapper .tv-product-page-content .product-add-to-cart .product-quantity input[type="text"]#quantity_wanted {
    /* min-height: 0 is the one that matters — the mobile rule pins the field at
       `min-height: 52px; height: 52px`, and a minimum beats a height. Without it the
       field stayed the full height of the pill and kept painting over its border. */
    height: 38px !important;
    min-height: 0 !important; max-height: none !important;
    background: transparent !important;
    align-self: center !important;
  }
  .tvproduct-page-wrapper .tv-product-page-content .product-add-to-cart .product-quantity .btn-touchspin:hover,
  .tvproduct-page-wrapper .tv-product-page-content .product-add-to-cart .product-quantity .btn-touchspin:active {
    background: var(--cc-surface-2) !important;
  }
  .tv-product-page-content .tv-product-add-to-cart-action-wrapper button.add-to-cart {
    width: 100% !important;
    height: 52px; min-height: 52px; padding: 0 14px;
    gap: 8px;
  }
  .tv-product-page-content .tv-product-add-to-cart-action-wrapper button.add-to-cart i,
  .tv-product-page-content .tv-product-add-to-cart-action-wrapper button.add-to-cart .material-icons {
    display: inline-flex !important;
    font-size: 18px !important;
  }
  /* "Añadir", not "Añadir al carrito".
     The long label is what forced the squeeze: to fit it beside the stepper I had been
     shrinking the stepper, and a 76px-wide box with a full pill radius stops reading as
     a pill and starts reading as a lozenge. Shorten the words instead — the product
     card already says just "Añadir", and on a phone the cart glyph carries the rest of
     the meaning. Now the stepper keeps its proper width and its proper shape. */
  .tv-product-page-content .tv-product-add-to-cart-action-wrapper button.add-to-cart span {
    font-size: 0;
    white-space: nowrap;
  }
  .tv-product-page-content .tv-product-add-to-cart-action-wrapper button.add-to-cart span::after {
    content: "Añadir";
    font-size: .92rem; font-weight: 700;
  }
}

@media (max-width: 991px) {
  .cc-buybar { display: flex; }
  .tv-product-page-content { padding: 22px 18px 20px !important; }
  .tv-product-page-content h1.h1 { font-size: 1.4rem; }
  .tv-product-page-content .product-price,
  .tv-product-page-content .current-price span { font-size: 1.6rem !important; }
  /* the page's own buy button stays where it is; the bar is the shortcut, not a
     replacement — but leave room so the bar never covers the last accordion */
  body.cc-has-buybar #footer { padding-bottom: 72px; }
}

@media (prefers-reduced-motion: reduce) {
  .cc-buybar { transition: none; }
  .tv-product-page-content .tv-product-page-add-to-cart-wrapper button.add-to-cart:hover:not(:disabled) { transform: none; }
}

/* ------------------------------------------------- PrestaShop's availability box */
/* #product-availability is PrestaShop's own message, and it is NOT only about low
   stock: it renders "En stock" / "Últimas unidades en stock" / "Fuera de stock" —
   whatever the shop's availability labels say. So it can't simply be deleted.
   But when the product IS available it just repeats what cc_stockdisplay already says
   one line below ("En stock" + the delivery date), so that state is hidden and only the
   two states that carry NEW information survive: scarcity and unavailability. They get
   the same amber/grey language as the card's stock badge, so the two agree. */
#product-availability:has(.product-available) { display: none !important; }

/* custom.css already styles this box (`.tvproduct-page-wrapper #product-availability
   { background:#fef3c7; border-left: 2px solid #fcd34d }`) — an ID plus a class, so our
   ID-only rule lost. Same amber as the card's scarcity badge, and a pill instead of a
   left-barred box, so the two speak with one voice. */
.tvproduct-page-wrapper .tv-product-page-content #product-availability,
#product-availability {
  display: inline-flex; align-items: center; gap: 7px;
  margin: 0 0 18px; padding: 6px 12px;
  border: 0 !important; border-radius: 999px !important;
  background: #fdead0 !important;            /* amber: scarcity, a nudge, not an alarm */
  color: #7a4a0c !important;
  font-size: .8rem; font-weight: 700;
}
#product-availability i.material-icons { font-size: 16px; color: currentColor !important; }
/* genuinely unavailable reads grey, not amber: nothing to hurry for */
.tvproduct-page-wrapper .tv-product-page-content #product-availability:has(.product-unavailable),
#product-availability:has(.product-unavailable) {
  background: var(--cc-surface-2) !important;
  color: var(--cc-ink-faint) !important;
}

/* --------------------------------------------------- the stepper's own buttons */
/* custom.css gives these a square white box:
     `.tvproduct-page-wrapper .product-quantity .btn-touchspin
       { background:#fff; border-radius:0; width:44px !important; height:44px !important }`
   Inside our 52px pill that square is what flashed at the corners on hover — a
   rectangle poking out of a rounded box. Round them, and let the hover be a circle. */
.tv-product-page-content .product-add-to-cart .product-quantity .btn-touchspin,
.tv-product-page-content .product-add-to-cart .product-quantity .bootstrap-touchspin-up,
.tv-product-page-content .product-add-to-cart .product-quantity .bootstrap-touchspin-down {
  width: 40px !important; height: 40px !important;
  margin: 0 4px !important;
  border: 0 !important;
  border-radius: 999px !important;
  background: none !important;
  color: var(--cc-ink-soft) !important;
  transition: background .15s ease, color .15s ease;
}
.tv-product-page-content .product-add-to-cart .product-quantity .btn-touchspin:hover {
  background: var(--cc-surface-2) !important;
  color: var(--cc-brand) !important;
}

/* ------------------------------------------------------- gallery, on a phone */
/* Under 768px the theme HIDES the big cover (media-mobile.css: `.tvprduct-image-info-wrapper
   .product-cover { display:none }`) and promotes the THUMB STRIP to be the gallery. So on a
   phone `.product-images` is not a strip of thumbnails any more — it is the product photo.
   Everything below follows from that. */
@media (max-width: 768px) {
  /* THE runaway bug. This column is a flex container (see the gallery section above), so its
     flex item is sized by its CONTENT — and slick sizes its track from that same width. Each
     fed the other: the track grew to 324,764px, then DOUBLED on every autoplay tick until it
     hit 33 million px, and `justify-content:center` centred that monster, parking every image
     millions of pixels off-screen. That is the blank gallery with dots underneath.
     No flex on a phone — one column, nothing to centre — so the loop cannot form. */
  .tv-product-page-image { display: block; }

  /* the strip is the gallery: give it the full width, not a thumbnail's slice of it */
  .tv-product-page-image .tvvertical-slider { width: 100%; }
  .tv-product-page-image .product-images img.thumb { width: 100%; height: auto; }

  /* slick's OWN stylesheet is not loaded on this site — the theme hand-rolled the handful of
     rules its vertical strip needed, and a vertical strip needs no float. So a HORIZONTAL
     slick has nothing laying its slides out in a row: they stack in a column while slick
     translates the track sideways, which is why the photo sat half off the left edge and the
     gallery read as empty. These are the four rules slick.css would have supplied, scoped to
     our slider so no other carousel on the site can feel them. */
  .tv-product-page-image .cc-mobile-gallery .slick-list { position: relative; display: block; overflow: hidden; }
  .tv-product-page-image .cc-mobile-gallery .slick-track { position: relative; display: block; top: 0; left: 0; }
  .tv-product-page-image .cc-mobile-gallery .slick-track::before,
  .tv-product-page-image .cc-mobile-gallery .slick-track::after { content: ""; display: table; }
  .tv-product-page-image .cc-mobile-gallery .slick-track::after { clear: both; }
  .tv-product-page-image .cc-mobile-gallery .slick-slide { float: left; height: auto; min-height: 1px; }
  .tv-product-page-image .cc-mobile-gallery .slick-slide img { display: block; }

  /* ...and drop the thumbnail chrome. These borders are right for a 86px thumb and wrong for
     a full-width photo — this is the blue-bordered box the costume was sitting in. */
  .tv-product-page-image .product-images li img,
  .tv-product-page-image .product-images .thumb,
  .tv-product-page-image .product-images img.selected {
    border: 0 !important;
    border-radius: 0;
    background: none;
  }

  /* the up/down arrows steer the VERTICAL desktop strip; there is no vertical strip here */
  .tv-product-page-image .tvvertical-slider .arrows { display: none; }

  /* --- dots ----------------------------------------------------------------------
     Left where the THEME puts them: absolutely positioned, inside the gallery, in the 30px
     the theme reserves under the strip. We only restyle them — the active one wears the
     brand colour as a pill, the rest are hairline dots. We do NOT touch `position`: taking
     them out of `absolute` moved them into the flow, and in any state where our slider isn't
     the one on the page they landed behind the product title.
     Scoped to `.cc-mobile-gallery` (the class our JS puts on the slider it builds), so if our
     JS ever fails to run, the theme's dots keep the theme's own styling instead of half of
     ours. */
  .tv-product-page-image .cc-mobile-gallery .slick-dots {
    display: flex; justify-content: center; align-items: center; gap: 8px;
    margin: 14px 0 0; padding: 0;
    list-style: none;
  }
  .tv-product-page-image .cc-mobile-gallery .slick-dots li { width: auto; height: auto; margin: 0; }
  .tv-product-page-image .cc-mobile-gallery .slick-dots li button {
    width: 8px; height: 8px; padding: 0;
    border: 0; border-radius: 999px;
    background: var(--cc-hairline);
    text-indent: -9999px;              /* slick prints the slide number inside the button */
    overflow: hidden;
    cursor: pointer;
    transition: background .15s ease, width .15s ease;
  }
  .tv-product-page-image .cc-mobile-gallery .slick-dots li button::before { display: none; }  /* slick's own bullet glyph */
  .tv-product-page-image .cc-mobile-gallery .slick-dots li.slick-active button {
    width: 22px;
    background: var(--cc-brand);
  }
}

/* ===================================================== desktop sticky buy bar
   The theme's `.tvfooter-product-sticky-bottom` — DESKTOP ONLY (custom.js builds it above
   the mobile breakpoint; our own .cc-buybar covers phones). It clones the product actions
   into #bottom_sticky_data when you scroll past the hero. The theme leaves it generic: a
   flat white strip, an UPPERCASED grey title, a square button. This brings it into the shop's
   design system — the signature over the top, the name as typed, the brand price, the pill
   button and pill stepper — so scrolling down doesn't drop you onto a bar from another site.
   Everything is scoped to .tvfooter-product-sticky-bottom; the page's own actions are
   untouched. */
.tvfooter-product-sticky-bottom {
  border-top: 0 !important;
  box-shadow: 0 -8px 30px -12px rgba(16, 28, 52, .22) !important;
  padding: 10px 0 !important;
}
/* the signature, full width across the top — the same spectrum every heading and the
   product card wear */
.tvfooter-product-sticky-bottom::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg,
    var(--cc-accent-1)   0 14.2857%,
    var(--cc-accent-2) 14.2857% 28.5714%,
    var(--cc-accent-3) 28.5714% 42.8571%,
    var(--cc-accent-4)  42.8571% 57.1428%,
    var(--cc-accent-5)   57.1428% 71.4285%,
    var(--cc-accent-6)   71.4285% 85.7142%,
    var(--cc-accent-7) 85.7142% 100%);
}

/* thumbnail: our rounded tile + hairline, `contain` so a costume cut-out isn't cropped */
.tvfooter-product-sticky-bottom .product-image {
  width: 54px; height: 54px;
  border-radius: var(--cc-radius-sm) !important;
  border: 1px solid var(--cc-hairline) !important;
  background: var(--cc-surface);
}
.tvfooter-product-sticky-bottom .product-image img { object-fit: contain !important; }

/* title: as typed, not shouted; one line with an ellipsis so a long name can't push the
   button off the row */
.tvfooter-product-sticky-bottom .tvtitle-price h1,
.tvfooter-product-sticky-bottom .tvtitle-price .h1 {
  text-transform: none !important;
  font-size: 15px !important; font-weight: 700 !important;
  color: var(--cc-ink) !important;
  margin: 0 0 2px !important;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* price in the brand blue, like the product page */
.tvfooter-product-sticky-bottom .product-price-and-shipping .price,
.tvfooter-product-sticky-bottom .current-price .price,
.tvfooter-product-sticky-bottom .product-price {
  font-size: 18px !important; font-weight: 800 !important;
  color: var(--cc-brand) !important;
}

/* the add-to-cart: the brand pill, matching the one on the page */
.tvfooter-product-sticky-bottom #bottom_sticky_data .tvcart-btn-model,
.tvfooter-product-sticky-bottom #bottom_sticky_data button.add-to-cart,
.tvfooter-product-sticky-bottom #bottom_sticky_data .tvall-inner-btn.add-to-cart {
  min-height: 48px;
  border: 0 !important;
  border-radius: 999px !important;
  background: var(--cc-brand) !important;
  color: #fff !important;
  font-weight: 700 !important;
  text-transform: none !important;
  box-shadow: none !important;
  transition: background .16s ease !important;
}
/* The label and icon live in a `span`/`i` that custom.css paints #232323 by default and
   only flips to white on :hover (custom.css ~16001) — so on our blue pill the text read
   black until you hovered. That rule is `.tv-product-page-add-to-cart-wrapper
   .tvall-inner-btn.add-to-cart span` and it reaches the cloned actions in here too. The
   `#bottom_sticky_data` id out-ranks it; white at rest, not only on hover. */
.tvfooter-product-sticky-bottom #bottom_sticky_data .tvall-inner-btn.add-to-cart span,
.tvfooter-product-sticky-bottom #bottom_sticky_data .tvall-inner-btn.add-to-cart i {
  color: #fff !important;
}
.tvfooter-product-sticky-bottom #bottom_sticky_data button.add-to-cart:hover,
.tvfooter-product-sticky-bottom #bottom_sticky_data .tvcart-btn-model:hover {
  background: var(--cc-brand-bright) !important;
}
.tvfooter-product-sticky-bottom #bottom_sticky_data .tvall-inner-btn.add-to-cart {
  background: none !important;      /* the blue lives on the model wrapper; keep the inner clear */
  color: #fff !important;
}

/* quantity: the same pill stepper as the page (see the product-page stepper block above —
   this repeats it for the cloned markup, which lives under a different ancestor) */
.tvfooter-product-sticky-bottom #bottom_sticky_data .product-quantity { margin: 0 !important; }
.tvfooter-product-sticky-bottom #bottom_sticky_data .product-quantity > .control-label { display: none; }
.tvfooter-product-sticky-bottom #bottom_sticky_data .input-group-btn-vertical { display: contents !important; }
.tvfooter-product-sticky-bottom #bottom_sticky_data .bootstrap-touchspin-down { order: 1 !important; }
.tvfooter-product-sticky-bottom #bottom_sticky_data input#quantity_wanted { order: 2 !important; }
.tvfooter-product-sticky-bottom #bottom_sticky_data .bootstrap-touchspin-up { order: 3 !important; }
.tvfooter-product-sticky-bottom #bottom_sticky_data .input-group-addon:empty { display: none !important; }
.tvfooter-product-sticky-bottom #bottom_sticky_data .product-quantity .qty div.input-group {
  display: flex !important; align-items: center;
  height: 48px !important; width: auto;
  border: 1.5px solid var(--cc-hairline) !important;
  border-radius: 999px !important;
  overflow: hidden; background: var(--cc-surface);
}
.tvfooter-product-sticky-bottom #bottom_sticky_data input#quantity_wanted {
  border: 0 !important; background: none !important;
  width: 40px !important; text-align: center;
  font-weight: 700; color: var(--cc-ink);
}
.tvfooter-product-sticky-bottom #bottom_sticky_data .btn-touchspin,
.tvfooter-product-sticky-bottom #bottom_sticky_data .bootstrap-touchspin-up,
.tvfooter-product-sticky-bottom #bottom_sticky_data .bootstrap-touchspin-down {
  width: 38px !important; height: 38px !important;
  border: 0 !important; border-radius: 999px !important;
  background: none !important; color: var(--cc-ink-soft) !important;
  transition: background .15s ease, color .15s ease;
}
.tvfooter-product-sticky-bottom #bottom_sticky_data .btn-touchspin:hover {
  background: var(--cc-surface-2) !important; color: var(--cc-brand) !important;
}
