/* ============================================================
   CC UI — the product card (site-wide)
   Consumes tokens.css. Loaded on every front page, because this card is shared
   by the homepage blocks, category listings, search results and related-product
   rails — one card, one look, everywhere.

   READ THE RENDERED DOM, NOT THE TPL. Every <article.product-miniature> ships
   FOUR complete copies of the product markup and toggles between them:
       .tvproduct-wrapper.grid     ← the one actually shown
       .tvproduct-wrapper.grid-2   ← display:none
       .tvproduct-wrapper.list     ← display:none (category "list view")
       .tvproduct-wrapper.catelog  ← display:none
   Everything below is scoped to `.grid`; styling the <article> itself would hit
   all four copies and leak into list view.

   Selectors carry BOTH classes (.product-miniature.js-product-miniature) on
   purpose. The theme's custom.css uses the very same selectors at the same
   specificity (e.g. `.product-miniature .thumbnail-container {border:1px solid
   #e8e8e8}`) and loads AFTER cc_ui, so an equal-specificity rule of ours loses on
   source order alone — no !important involved. The extra class wins it cleanly.

   Structure inside .grid:
       .tvproduct-image
           a.thumbnail.product-thumbnail > img
           ul.tvproduct-flags.tvproduct-online-new-wrapper   (New)
           ul.tvproduct-flags.tvproduct-sale-pack-wrapper    (Sale / Pack)
           .tvproduct-hover-btn
               .tvproduct-quick-btn  > a.quick-view (icon only)
               .tvproduct-cart-btn   > form > button[data-button-action=add-to-cart]
                                       (icon only; qty is a HIDDEN input, value 1)
       .tvproduct-info-box-wrapper > .product-description
           .tvproduct-name.product-title
           .tv-product-price

   The action row is NOT hover-gated (hover hides the primary action and doesn't
   exist on touch at all): quantity + add-to-cart sit permanently at the foot of
   the card. The stepper and the button label are injected by card-actions.js —
   the theme ships neither. Quick-view keeps its hover, on the image.
   ============================================================ */

/* ---------------------------------------------------------------- the card
   DIRECTION B — "no chrome". There is no card: no panel, no border, no shadow.
   The photo sits on its own white tile against the page's grey (#f2f2f2), the
   text is quiet underneath, and the products carry the grid. Chosen over the
   panelled version because the shop reads calmer and less templated. */
.product-miniature.js-product-miniature .thumbnail-container {
  border: 0;
  border-radius: 0;
  background: none;              /* the theme's white panel — gone */
  box-shadow: none;
  height: 100%;
}
/* The theme lifts and shadows the CARD on hover:
       .product-miniature .thumbnail-container:hover {
         transform: translateY(-4px); box-shadow: 0 8px 20px rgba(0,0,0,.08) }
   With the panel gone that card is transparent, so the shadow was being drawn
   around nothing — floating behind text and buttons that share the page's colour.
   Kill it; the elevation belongs to the tile (below), which is a real surface. */
.product-miniature.js-product-miniature .thumbnail-container:hover {
  transform: none;
  box-shadow: none;
}

/* The wrapper is the positioning context for the flags and the action row —
   NOT .tvproduct-image, which only spans the picture. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid {
  position: relative;
  display: flex; flex-direction: column;
  height: 100%;
  padding-bottom: 60px;          /* reserves the action row's space */
  background: none;
  border-radius: 0;
  overflow: visible;             /* nothing to clip now the panel is gone */
}

/* ------------------------------------------------------------------- image */
/* Costume photos come in every aspect ratio and mostly on white. The image sits
   ON a neutral tile, contained not cropped (no heads cut off), and multiply
   blends the white photo box away. */
/* The photo's tile IS the card in direction B: white, rounded, sitting on the
   page's grey. Everything else is naked.
   NB the tile's colour and elevation live on the <a>, not on .tvproduct-image.
   .tvproduct-image must stay untransformed: the flags and the action row are its
   DOM children but are positioned against .grid, and a transform here would make
   THIS element their containing block and yank them onto the photo. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-image {
  position: static;              /* so its absolute children anchor to .grid */
  background: none;
  /* THE crop. custom.css pins this wrapper at `height: 220px; overflow: hidden`.
     Our square tile inside it is ~338px tall, so the parent sliced the bottom
     third off every photo — chins, shoes, the hem of every costume. The tile's own
     `overflow: hidden` (for the hover zoom) is fine and stays; it's this fixed
     height that has to go, or the box can never be square. */
  height: auto;
  overflow: visible;
}
/* The theme hangs a tint on this element — `.tvproduct-image::after { position:
   absolute; inset:0; background: rgba(31,28,61,.08) }`. Harmless while the element
   was position:relative (it only veiled the photo), but the moment we made it
   static — so the flags and action row could anchor to the card — the veil's
   containing block became the whole card and it washed EVERYTHING grey: a pure
   white tile painted as rgb(237,237,240), i.e. white × 8% black. It's a hover
   tint we don't want at all. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-image::after {
  content: none !important;
}
/* Two images live in here: img.tvproduct-defult-img and, when the product has a
   second picture, img.tvproduct-hover-img (12 of 100 cards on a typical category).
   The theme stacks them by absolutely positioning the hover one — which sized it
   to the padding box while the default sized to the content box, so they landed
   misaligned and, multiplied together, ghosted through each other.
   A single-cell grid stacks them exactly, whatever their intrinsic size. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-image .product-thumbnail {
  position: relative;
  /* !important because theme.css claims this with an ID — `#products
     .product-thumbnail { display:block }` — which outranks any class chain we can
     write. Without grid here the two images stack vertically instead of sharing
     one cell, which is exactly the "both images collide" bug. */
  display: grid !important;      /* one cell; both images occupy it */
  place-items: center;
  /* height:auto is what makes the tile SQUARE. custom.css sets
     `.product-miniature .tvproduct-image a { height:100% }`, and an explicit
     height beats aspect-ratio (which only applies when height is auto) — so the
     tile stayed 250×220 and a square 239×239 photo was contained down to 192×192,
     stranded between 30px bands of empty white on each side. It was never
     cropped, just shrunk. Square box + small padding = the photo fills the tile. */
  height: auto;
  aspect-ratio: 1 / 1;
  padding: 8px;
  overflow: hidden;              /* clips the hover zoom */
  /* the tile itself: the only real surface on the card */
  background: var(--cc-surface);
  border-radius: 12px;
  transition: box-shadow .18s ease, transform .18s ease;
}
/* elevate the TILE on hover, not the (transparent) card */
.product-miniature.js-product-miniature:hover .tvproduct-wrapper.grid .tvproduct-image .product-thumbnail {
  box-shadow: var(--cc-shadow-card);
  transform: translateY(-3px);
}
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-image img {
  grid-area: 1 / 1;              /* same cell → pixel-aligned, no offset */
  position: static;              /* undo the theme's absolute hover image */
  width: 100%; height: 100%;
  /* min-*: 0 is load-bearing for NON-SQUARE photos. A grid item's default
     `min-height: auto` is its min-content size — the image's intrinsic height —
     so a 345×452 portrait refused to shrink below 452px, stretched the row, and
     dragged the tile off its 1/1 ratio; `height: 100%` then resolved against the
     inflated box and the photo spilled out of `overflow: hidden` = a real crop.
     With min-height: 0 the item is free to fit the square cell and `contain`
     letterboxes it against the white tile, which is invisible. Square thumbnails
     hid this bug: the intrinsic height never exceeded the cell. */
  min-width: 0; min-height: 0;
  object-fit: contain;
  mix-blend-mode: multiply;      /* dissolves the white photo boxes into the tile */
  transition: opacity .25s ease, transform .25s ease;
}
/* cross-fade, only where there IS a second image — otherwise hovering a
   single-image card would fade its only picture to nothing */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-hover-img { opacity: 0; }
.product-miniature.js-product-miniature:hover .tvproduct-wrapper.grid .tvproduct-hover-img { opacity: 1; }
.product-miniature.js-product-miniature:hover .tvproduct-wrapper.grid .product-thumbnail:has(.tvproduct-hover-img) .tvproduct-defult-img { opacity: 0; }
.product-miniature.js-product-miniature:hover .tvproduct-wrapper.grid .tvproduct-image img { transform: scale(1.04); }

/* ------------------------------------------------------------------- flags */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-flags {
  position: absolute; top: 10px; left: 10px; z-index: 2;
  /* opacity:1 !important — the theme keeps this column at opacity:0 and fades it in
     on HOVER. That silently makes "Nuevo" and "-20%" invisible to anyone who never
     hovers (i.e. every phone), which is a marketing bug on its own; it also swallowed
     our stock badge whole. Flags are information, not decoration: they show. */
  opacity: 1 !important;
  /* the stock badge joins this column and is as wide as its sentence — without a
     ceiling, "Ya tienes las 29 disponibles" would run off the edge of the photo */
  max-width: calc(100% - 20px);
  margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px;
  align-items: flex-start;
}
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-sale-pack-wrapper { left: auto; right: 10px; }
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-flags li {
  display: inline-flex; align-items: center;
  padding: 4px 9px; border-radius: 999px;
  font-size: .68rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  background: var(--cc-surface-deep); color: #fff; line-height: 1.4;
}
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-flags li.on-sale,
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-flags li.discount { background: var(--cc-pink); }
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-flags li.new { background: var(--cc-brand); }
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-flags:empty { display: none; }

/* -------------------------------------------------------------------- text */
/* B: the text is not inside a panel, so it aligns to the tile's edge, not to a
   card's padding. */
/* the theme paints this white; in B the text sits on the page, not on a panel */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-info-box-wrapper {
  padding: 13px 2px 8px; background: none;
}
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .product-description { text-align: left; }

/* Name: clamped to 2 lines with a reserved height, so a 1-line and a 3-line
   title still leave their prices on the same baseline across a row. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-name,
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-name a {
  text-align: left;
  font-size: .9rem; font-weight: 400; line-height: 1.35;
  color: var(--cc-ink-soft); text-decoration: none;
}
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-name {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 2.7em; margin: 0 0 8px;
}
.product-miniature.js-product-miniature:hover .tvproduct-wrapper.grid .tvproduct-name a { color: var(--cc-brand); }

/* Price: the loudest thing on the card. tabular-nums so a row of prices lines up. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tv-product-price {
  display: flex; align-items: baseline; gap: 8px; text-align: left; margin: 0;
}
/* B: the price is ink, not brand blue — with no card chrome, blue-on-white for
   both the price AND the button was two competing accents in a small space. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tv-product-price .price {
  font-size: 1rem; font-weight: 700; color: var(--cc-ink);
  font-variant-numeric: tabular-nums;
}
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tv-product-price .regular-price {
  font-size: .85rem; font-weight: 400; color: var(--cc-ink-faint);
  text-decoration: line-through; font-variant-numeric: tabular-nums;
}
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tv-product-price .discount-percentage,
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tv-product-price .discount-amount {
  font-size: .75rem; font-weight: 700; color: var(--cc-pink);
}

/* ----------------------------------------------------------- quick view: gone.
   It only ever appeared on hover (so never on touch), and now that quantity and
   add-to-cart are permanent it was a third control competing with the two that
   matter. The card itself already links to the product. One line to bring back. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-quick-btn { display: none; }

/* -------------------------------------- action row: quantity + add to cart */
/* Pinned to the foot of the card, always visible. The wrapper reserves its
   height above (padding-bottom), so it never overlaps the price. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-hover-btn {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: 0 2px 2px;
  background: none; opacity: 1; transform: none;
}
/* custom.css draws a white rounded box WITH ITS OWN SHADOW behind every direct
   child of the action row:
       .product-miniature .tvproduct-hover-btn > div {
         background:#fff; border-radius:4px; box-shadow:0 1px 4px rgba(0,0,0,.1) }
   (the radius has since been overridden to 50px elsewhere). That box sits behind
   our pill and is why the live card never matched the mockup — a faint second
   shadow hugging the button. Nothing of ours wants it. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-hover-btn > div {
  background: none; box-shadow: none; border-radius: 0; padding: 0;
}
/* The theme sizes the cart wrapper to a single icon button, so the row and the
   wrapper both have to be told to stretch before the button can fill it. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-hover-btn {
  display: flex; align-items: center;
}
/* transform:none is the one that actually un-hides the button. The theme parks
   the cart at `translateY(60px)` — 60px BELOW the card, clipped by the wrapper's
   overflow — and slides it up only on :hover. Clearing opacity alone left the
   row "visible" while the button still sat off-card. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-cart-btn {
  flex: 1 1 auto; width: auto; min-width: 0; max-width: none;
  transform: none;
}
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-cart-btn form {
  display: flex; align-items: center; gap: 8px; margin: 0; width: 100%;
}

/* quantity stepper (injected by card-actions.js, bound to the form's hidden qty).
   B: outlined, not filled — a grey pill next to an outlined button read as two
   different kinds of control. */
.cc-qty {
  display: flex; align-items: center; flex: 0 0 auto;
  height: 42px; border-radius: 999px;
  background: none; border: 1.5px solid var(--cc-hairline);
  overflow: hidden;
}
.cc-qty__btn {
  width: 30px; height: 42px; padding: 0;
  border: 0; background: none; cursor: pointer;
  color: var(--cc-ink-soft); font-size: 1rem; font-weight: 700; line-height: 1;
  transition: color .15s ease, background .15s ease;
}
.cc-qty__btn:hover { color: var(--cc-brand); background: var(--cc-surface-2); }
.cc-qty__btn:disabled { color: var(--cc-ink-faint); cursor: default; background: none; }
.cc-qty__input {
  width: 26px; padding: 0; border: 0; background: none;
  text-align: center; font: inherit; font-weight: 700; font-size: .9rem;
  color: var(--cc-ink); font-variant-numeric: tabular-nums;
  -moz-appearance: textfield;
}
.cc-qty__input::-webkit-outer-spin-button,
.cc-qty__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.cc-qty__input:focus-visible { outline: 2px solid var(--cc-brand-bright); outline-offset: 1px; border-radius: 4px; }

/* add to cart — B: outlined at rest, filling with brand on hover. Keeps the grid
   quiet (28 solid blue buttons on a category page shouted), while still being
   unmistakably the primary action, and it fills the moment you reach for it. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid button.add-to-cart {
  flex: 1 1 auto; min-width: 0;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: 42px; padding: 0 12px;
  border: 1.5px solid var(--cc-brand); border-radius: 999px;
  background: none; color: var(--cc-brand);
  font-size: .85rem; font-weight: 700; white-space: nowrap;
  cursor: pointer; box-shadow: none;
  transition: background .15s ease, color .15s ease;
}
.product-miniature.js-product-miniature .tvproduct-wrapper.grid button.add-to-cart:hover {
  background: var(--cc-brand); color: #fff;
}
/* The glyph must follow the BUTTON's colour, in every state. The theme gives the
   icon a hard colour of its own (black in the card, white in other skins), so it
   ignored the button entirely: black on the brand-blue hover fill, and — worst —
   white on the white resting button, i.e. an invisible cart. currentColor makes it
   brand at rest, white on hover/busy/done, and faint grey when out of stock,
   automatically, with no per-state rules. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid button.add-to-cart i,
.product-miniature.js-product-miniature .tvproduct-wrapper.grid button.add-to-cart i.material-icons {
  color: currentColor !important;
  font-size: 18px;
  line-height: 1;
}
/* the theme hides <span>s inside this button, so the label needs display, not just font */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid button.add-to-cart .cc-cart-label {
  display: inline-block; font: inherit; color: inherit;
}

/* THREE states, and they must not look alike:
   1. busy — PrestaShop DISABLES the button for ~1s while its add-to-cart AJAX
      runs. Styling plain :disabled as "unavailable" made a perfectly good click
      look like the button had broken (it greyed out and the icon fell away).
      Busy keeps the brand fill and just dims; card-actions.js says "Añadiendo…".
   2. done — a moment of "yes, that worked", then back to normal.
   3. out of stock — genuinely unavailable, and it says so. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid button.add-to-cart:disabled:not(.cc-oos),
.product-miniature.js-product-miniature .tvproduct-wrapper.grid button.add-to-cart[data-cc-busy] {
  background: var(--cc-brand); border-color: var(--cc-brand); color: #fff; opacity: .72; cursor: progress;
}
.product-miniature.js-product-miniature .tvproduct-wrapper.grid button.add-to-cart.cc-done {
  background: var(--cc-green, #2e9e4f); border-color: var(--cc-green, #2e9e4f); color: #fff; opacity: 1;
}
.product-miniature.js-product-miniature .tvproduct-wrapper.grid button.add-to-cart.cc-oos {
  background: var(--cc-surface-2); border-color: transparent;
  color: var(--cc-ink-faint); cursor: not-allowed; opacity: 1;
}
/* the theme's ⊘ glyph adds nothing next to the words — the label carries it */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid button.add-to-cart.cc-oos i { display: none; }

/* 4. maxed out — there IS stock, it's just all in this shopper's cart already.
   Shares the disabled treatment of cc-oos (it can't be clicked either) but keeps
   the cart glyph and reads in brand ink, because this is a GOOD state: you have
   them all. "Sin stock" here would be a lie, and a silently-refused click worse. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid button.add-to-cart.cc-maxed {
  background: none; border-color: var(--cc-hairline);
  color: var(--cc-brand); opacity: .8;
}
.product-miniature.js-product-miniature .tvproduct-wrapper.grid button.add-to-cart.cc-maxed i { display: inline-block; }
/* the stepper is hidden when maxed, so the button takes the whole row */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .cc-qty[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .product-miniature.js-product-miniature .thumbnail-container,
  .product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-image img,
  .product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-quick-btn { transition: none; }
  .product-miniature.js-product-miniature:hover .thumbnail-container { transform: none; }
  .product-miniature.js-product-miniature:hover .tvproduct-wrapper.grid .tvproduct-image img { transform: none; }
}

/* stock ceiling hint — appears under the row when the stepper hits the real
   available quantity (card-actions.js reads it from module/cc_ui/stock). Without
   it, asking for more than the stock did nothing at all: PrestaShop refuses the
   add and says nothing, which reads as a broken button. */
/* The stock callout ("Solo quedan 3", "Ya tienes 3 en el carrito").
   ABSOLUTE, and that's the whole point. The action row is positioned against the
   card's bottom edge, so a hint in normal flow ADDS to the row's height and — being
   bottom-anchored — shoves the stepper and the button up ~20px. Cards visibly
   jumped the moment you hit the ceiling. Out of flow, it costs the row nothing and
   drops into the dead ~24px between the price and the buttons, which was empty on
   every card anyway. The row is the containing block (it's the nearest positioned
   ancestor), so `bottom: 100%` parks it directly above the buttons. */
/* The stock badge — the card's THIRD flag, in the theme's own top-left column,
   under "Nuevo".
   It costs the card no height, which none of the alternatives managed: in flow it
   grew the bottom-anchored action row and shoved the buttons up; as a bubble above
   the buttons it clipped the price; as a bar at the foot it forced a 26px reserved
   strip onto every card in the shop just so the rare one with a message wouldn't be
   taller than its neighbours. Riding the flag column, it is free AND collision-proof:
   the column is a flex stack with a gap, so Nuevo and this can never land on top of
   each other, whatever the product carries.
   The selector has to out-specify our own `.tvproduct-flags li` (navy pill) rule
   above — same list, different flag. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-flags li.cc-qty-hint {
  max-width: 100%;
  padding: 4px 10px;
  border-radius: 999px;
  background: #fdead0;                     /* amber: scarcity, a nudge — not alarm */
  color: #7a4a0c;
  font-size: .68rem; font-weight: 800; letter-spacing: .01em;
  text-transform: none;                    /* the flags are UPPERCASE; a sentence isn't */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block;
  box-shadow: 0 1px 4px rgba(31, 28, 61, .12);
  pointer-events: none;                    /* never eat a click meant for the product */
}
/* Not scarcity — reassurance ("you already hold these"). Same badge, brand colour, so
   the two facts never read as the same warning. */
.product-miniature.js-product-miniature .tvproduct-wrapper.grid .tvproduct-flags li.cc-qty-hint.cc-qty-hint--cart {
  background: #e3eefa;
  color: var(--cc-brand);
}

/* ============================================================================
   THE "ADDED TO CART" MODAL (#blockcart-modal, ps_shoppingcart + theme)

   Site-wide on purpose: it fires from every add-to-cart button in the shop, so it
   is the one screen a shopper is guaranteed to see, and it was the last piece still
   wearing the theme's clothes — a near-full-width white slab with UPPERCASE
   headings, square black and blue buttons, and the shop's signature nowhere in
   sight.

   The template belongs to the theme (shared with shop 1), so this is CSS only. Every
   selector hangs off the #blockcart-modal ID, which comfortably out-ranks the theme's
   class chains — no !important needed anywhere below.
   ============================================================================ */

#blockcart-modal.modal { background: rgba(15, 36, 64, .55); backdrop-filter: blur(3px); }

/* .modal on the ID as well: something later in the cascade ships the very same
   `#blockcart-modal .modal-dialog` selector with `max-width: 1140px; width: 100%`, so
   matching it only ties and loses on source order. */
#blockcart-modal.modal .modal-dialog {
  max-width: 720px;                /* it ran nearly the full width of the screen */
  width: auto;
  margin: 6vh auto;
}
#blockcart-modal .modal-content {
  position: relative;
  border: 0;
  border-radius: 16px;
  box-shadow: var(--cc-shadow-lift);
  overflow: hidden;                /* so the signature bar follows the rounded top */
}
/* THE SIGNATURE. The same seven-band spectrum from the logo that runs under the
   topbar, under every section heading and on the CMS pages — here as the lid of the
   modal. It is the one moment of the brand in an otherwise transactional box. */
#blockcart-modal .modal-content::before {
  content: "";
  position: absolute; top: 0; left: 0; 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%);
}

/* ------------------------------------------------------------------- header */
#blockcart-modal .modal-header {
  display: flex; align-items: center; gap: 12px;
  padding: 22px 22px 16px;
  border: 0;
}
#blockcart-modal .modal-title {
  display: flex; align-items: center; gap: 10px;
  margin: 0;
  font-size: 1rem; font-weight: 800; color: var(--cc-ink);
  text-align: left; text-transform: none;
}
/* the bare ✓ glyph becomes a green pill — "it worked", said in one look */
#blockcart-modal .modal-title i.material-icons {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
  width: 26px; height: 26px;
  border-radius: 999px;
  background: var(--cc-green, #2e9e4f);
  color: #fff; font-size: 17px;
}
#blockcart-modal .close {
  display: flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; margin: 0 0 0 auto; padding: 0;
  border: 0; border-radius: 999px;
  background: var(--cc-surface-2); color: var(--cc-ink-soft);
  font-size: 1.2rem; line-height: 1; opacity: 1;
  transition: background .15s ease, color .15s ease;
}
#blockcart-modal .close:hover { background: var(--cc-ink); color: #fff; opacity: 1; }

/* --------------------------------------------------------------------- body */
#blockcart-modal .modal-body { padding: 0 22px 22px; }
#blockcart-modal .divide-right { border: 0; }
#blockcart-modal .divide-right::after {   /* hairline between product and summary */
  content: ""; position: absolute; top: 6px; bottom: 6px; right: 0;
  border-right: 1px solid var(--cc-hairline);
}
#blockcart-modal .col-md-6 { position: relative; }

/* THE PRODUCT BLOCK — one row: photo, then name/price/quantity beside it.
   The theme nests bootstrap columns (col-md-6 inside col-md-6), which on a phone
   collapse into a centred photo floating above left-aligned text, with the picture
   marooned in the middle of the dialog. A flex row reads the same on every screen and
   keeps the photo next to the thing it is a photo of. */
#blockcart-modal .tv-addtocart-image-name-wrapper {
  display: flex; align-items: center; gap: 16px;
  margin: 0;
}
#blockcart-modal .tv-addtocart-product-image,
#blockcart-modal .tv-addtocart-product-name {
  width: auto; max-width: none; flex: 0 1 auto; padding: 0;
}
#blockcart-modal .tv-addtocart-product-image { flex: 0 0 auto; }
#blockcart-modal .tv-addtocart-product-name { flex: 1 1 auto; min-width: 0; }

/* the photo: a square tile, exactly like the card's */
#blockcart-modal img.product-image {
  width: 110px; height: 110px;
  object-fit: contain;
  padding: 6px;
  background: var(--cc-surface);
  border: 1px solid var(--cc-hairline);
  border-radius: 12px;
  mix-blend-mode: multiply;
}
#blockcart-modal .product-name {
  margin: 0 0 6px;
  font-size: .95rem; font-weight: 600; line-height: 1.35;
  color: var(--cc-ink);
}
#blockcart-modal .tv-addtocart-price {
  margin: 0 0 4px;
  font-size: 1.15rem; font-weight: 800; color: var(--cc-brand);
}
#blockcart-modal .tv-addtocart-product-name span,
#blockcart-modal .tv-addtocart-product-name strong {
  font-size: .82rem; font-weight: 400; color: var(--cc-ink-soft);
}

/* the summary */
/* .cart-content in the chain: there's another `#blockcart-modal .cart-products-count`
   rule (uppercase, 1.125rem) later in the cascade — same specificity, so we have to
   outrank it, not match it. */
#blockcart-modal .cart-content .cart-products-count {
  margin: 0 0 12px;
  font-size: .95rem; font-weight: 800; color: var(--cc-ink);
  /* the theme SHOUTS it ("HAY 1 ARTÍCULO EN SU CARRITO."). Same treatment as the nav
     and the section headings: lowercase, first letter back. */
  text-transform: lowercase;
}
#blockcart-modal .cart-content .cart-products-count::first-letter { text-transform: uppercase; }
/* :not(.cart-products-count) is load-bearing. This flex rule was hitting the count
   line too — and ::first-letter DOES NOT APPLY to a flex container, only to a block
   one. So "Hay 1 artículo…" lowercased correctly and then never got its capital back:
   it rendered as "hay 1 artículo en su carrito.". (Same trap as the mobile drawer.) */
#blockcart-modal .cart-content p:not(.cart-products-count) {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  margin: 0 0 7px;
  font-size: .87rem; color: var(--cc-ink-soft);
}
#blockcart-modal .cart-content p strong { font-weight: 600; color: var(--cc-ink-soft); }
/* the total is the number that matters: give it the weight */
#blockcart-modal .cart-content p:last-of-type:not(.cart-products-count) {
  margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--cc-hairline);
  font-size: 1rem; color: var(--cc-ink);
}
#blockcart-modal .cart-content p:last-of-type strong { font-weight: 800; color: var(--cc-ink); }

/* ------------------------------------------------------------------ buttons */
/* Pills, like every other call to action in the shop. "Continuar comprando" is the
   quiet one (it's the way OUT), "Pasar por caja" is the brand-filled one. They were a
   black rectangle and a blue rectangle of equal weight, which asked the shopper to
   read both before choosing. */
/* A rule with this EXACT selector — `#blockcart-modal .cart-content .cart-content-btn
   { display: inline-flex }` — exists further down the cascade, so matching it only
   ties and loses. .modal-body breaks the tie. Inline-flex is what made the row shrink
   to its content: the two pills came out 315px and 320px and neither was centred in
   the dialog on a phone. */
#blockcart-modal .modal-body .cart-content .cart-content-btn {
  display: flex; flex-wrap: wrap; gap: 10px;
  width: 100%;
  margin-top: 18px;
}
/* The `button, a` tail is not decoration: the rule we're fighting is
   `#blockcart-modal .cart-content .cart-content-btn button { margin-right: .3125rem }`,
   and a chain ending in an ELEMENT outranks one ending in `> *`. That stray 5px is
   exactly why the two pills measured 280px and 285px and sat off the dialog's centre. */
#blockcart-modal .modal-body .cart-content .cart-content-btn button,
#blockcart-modal .modal-body .cart-content .cart-content-btn a {
  margin: 0;
  flex: 1 1 auto;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 0 18px;
  border-radius: 999px;
  font-size: .9rem; font-weight: 700; text-transform: none;
  cursor: pointer; text-decoration: none;
  transition: background .15s ease, color .15s ease, transform .15s ease;
}
#blockcart-modal .cart-content-btn button {
  border: 1.5px solid var(--cc-hairline);
  background: none; color: var(--cc-ink-soft);
}
#blockcart-modal .cart-content-btn button:hover {
  border-color: var(--cc-ink); color: var(--cc-ink); background: none;
}
#blockcart-modal .cart-content-btn a {
  border: 1.5px solid var(--cc-brand);
  background: var(--cc-brand); color: #fff;
}
#blockcart-modal .cart-content-btn a:hover {
  background: var(--cc-surface-deep); border-color: var(--cc-surface-deep); color: #fff;
  transform: translateY(-1px);
}
#blockcart-modal .cart-content-btn i.material-icons { font-size: 18px; color: currentColor; }
/* The theme paints the label inside these buttons WHITE (`.tvall-inner-btn span
   { color: #fff; font-size: 13px }`) because both of its buttons were dark. Ours
   isn't: "Continuar comprando" is a ghost pill, so its white text was invisible —
   an empty white capsule. Inherit the button's own colour and size instead. */
#blockcart-modal .cart-content-btn > * span {
  display: inline; color: inherit; font-size: inherit; font-weight: inherit;
  /* the SPAN is what's shouting, not the button: the theme uppercases it, so
     text-transform:none on the button alone changed nothing */
  text-transform: none; letter-spacing: normal;
}

@media (max-width: 767px) {
  #blockcart-modal.modal .modal-dialog { max-width: none; margin: 12px; }
  #blockcart-modal .divide-right::after { content: none; }
  #blockcart-modal .tv-addtocart-content { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--cc-hairline); }
  /* one pill per row on a phone — and it has to carry the same full chain as the rule
     above, or the desktop `flex: 1 1 auto` out-specifies it and the two pills sit side
     by side at 179px and 131px */
  #blockcart-modal .modal-body .cart-content .cart-content-btn button,
  #blockcart-modal .modal-body .cart-content .cart-content-btn a { flex: 1 1 100%; }
}

@media (prefers-reduced-motion: reduce) {
  #blockcart-modal .cart-content-btn > * { transition: none; }
  #blockcart-modal .cart-content-btn a:hover { transform: none; }
}
