/* ============================================================================
   Augurea · cart.css — shopping cart page (line items, qty steppers, summary aside).
   Migrated from the legacy stylesheet with the Slice-4 palette (house label → warm-grey).
   ============================================================================ */

.cart-page{padding-block:var(--page-top) 0}
.cart-crumb{font-size:11px;letter-spacing:.04em;color:var(--warm-grey)}
.cart-title{margin:14px 0 24px}
.cart-wrap{display:grid;grid-template-columns:1fr 340px;gap:48px;align-items:start}
.cart-lines{display:flex;flex-direction:column}
.cart-line{display:grid;grid-template-columns:96px 1fr auto;gap:20px;padding:22px 0;border-top:1px solid var(--line);align-items:start}
.cart-line:last-child{border-bottom:1px solid var(--line)}
.cart-thumb{display:block;aspect-ratio:4/5;background:linear-gradient(150deg,var(--cream-2),var(--ph-2));overflow:hidden}
.cart-meta .house{font-weight:500;font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--warm-grey);margin-bottom:5px}
.cart-name{display:block;font-size:21px;line-height:1.1;margin-bottom:6px;transition:color var(--dur-fast) var(--ease-out)}
.cart-name:hover,.cart-name:focus-visible{color:var(--burgundy)}
.cart-sub{font-size:12px;color:var(--muted);margin-bottom:12px}
.cart-preorder{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:-2px 0 12px;
  font-size:12px;color:var(--muted);line-height:1.4}
.qty{display:flex;align-items:center;gap:16px;font-family:var(--mono);font-size:13px}
.qty-stepper{display:inline-flex;align-items:center;border:1px solid var(--line-ui);background:var(--surface)}
.qty-stepper .qty-btn{width:34px;height:34px;border:0;background:none;cursor:pointer;font-size:16px;line-height:1;color:var(--ink);transition:background var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),transform var(--dur-fast) var(--ease-out)}
/* FX-5.3: 34x34 is under the 44px touch-target floor on mobile. Grow the
   +/- hit areas and give the stepper a little internal gap so enlarged
   buttons don't crowd the qty number between them. Desktop stays 34px. */
@media(max-width:600px){
  .qty-stepper{gap:4px}
  .qty-stepper .qty-btn{width:44px;height:44px}
  .qty-n{min-width:36px}
}
.qty-stepper .qty-btn:hover:not(:disabled),.qty-stepper .qty-btn:focus-visible:not(:disabled){background:var(--cream-2);color:var(--burgundy)}
.qty-stepper .qty-btn:active:not(:disabled){transform:scale(.88)}
.qty-stepper .qty-btn:disabled{color:var(--line-ui);cursor:not-allowed}
.qty-n{min-width:32px;text-align:center;font-size:14px;color:var(--ink)}
.qty .cart-rm{border:0;background:none;color:var(--warm-grey);text-decoration:underline;text-underline-offset:2px;cursor:pointer;font-size:11px;letter-spacing:.04em}
.qty .cart-rm:hover:not(:disabled),.qty .cart-rm:focus-visible:not(:disabled){color:var(--burgundy)}
.qty .cart-rm:disabled{opacity:.5;cursor:not-allowed}
.cart-line-total{font-family:var(--sans);font-weight:500;font-size:17px;font-variant-numeric:tabular-nums lining-nums}

/* a line is dimmed while its qty/remove POST is in flight (transform/opacity only) */
.cart-line.is-busy{opacity:.55;transition:opacity var(--dur-fast) var(--ease-out)}

/* removing a line fades + slides it out instead of an instant DOM delete
   (transform/opacity only; cart.js holds the actual splice until this plays) */
.cart-line.is-leaving{opacity:0;transform:translateX(-8px);
  transition:opacity var(--dur-mid) var(--ease-out),transform var(--dur-mid) var(--ease-out)}

/* summary aside — the .sum-* rows are the shared summary component (components.css) */
.cart-summary{position:sticky;top:88px;background:var(--surface);border:1px solid var(--line);padding:24px}
.cart-cont{display:block;text-align:center;font-size:12px;color:var(--warm-grey);margin-top:16px;
  transition:color var(--dur-fast,.2s) var(--ease-out,ease)}
.cart-cont:hover,.cart-cont:focus-visible{color:var(--burgundy)}

/* ---------- FX-5.2: pinned checkout bar (mobile) ----------
   Below 1000px the cart drops to one column, so a static summary sinks the
   checkout CTA under every line item on long carts. Pin the summary to the
   viewport bottom instead, full-bleed like the PDP FX-5.1 buy bar.
   .cart-wrap gets matching bottom padding so the fixed bar never covers the
   last line item. Entrance is transform/opacity only, one-time, and killed
   (shown at rest instantly) under reduced motion below. Desktop untouched.

   D1 (QA E2E 2026-09-13) — WHAT CHANGED AND WHY. The original bar was a single
   row that kept ONLY the total and the CTA, on the stated theory that
   "subtotal/IVA/shipping notes/msi/continue link stay in normal flow above it,
   still reachable by scrolling". They did not: the whole summary IS this bar, so
   `display:none` on those children deleted them from the page. Measured at 390px
   on 2026-09-13, the entire money story of the cart was the four words
   "Total $1,299 MXN" — no subtotal, no IVA, no shipping, not even the "Te faltan
   $201 para envío gratis" nudge that would have explained the $150 the checkout
   then added. A condensed bar may drop navigation chrome; it may not drop the
   price breakdown. The bar is now a compact COLUMN carrying every money row and
   the CTA, capped and scrollable so a long breakdown can never push the CTA past
   the viewport, with only the "seguir comprando" link and the MSI footnote
   condensed away (both are reachable elsewhere and neither is an amount). */
@media(max-width:1000px){
  /* The bar is pinned, so the last cart line needs room to clear it. That
     room is MEASURED, not guessed: the same `--cart-bar-h` cart.js publishes
     for the banner. A review on 2026-09-13 caught the hardcoded 250px next
     to a height the file had just learned to measure - today the bar weighs
     212-213px with the free-shipping nudge showing, so the number happens to
     be generous, but a nudge that wrapped to two lines (longer copy, 320px
     wide, a larger system font) would put the last line under the bar. The
     250px survives only as the reserve for the very first paint, before the
     script has measured anything. */
  .cart-wrap{grid-template-columns:minmax(0,1fr);
    padding-bottom:calc(var(--cart-bar-h,250px) + 24px)}
  .cart-summary{
    /* `top:auto` is LOAD-BEARING, and its absence was a defect of its own,
       measured in the browser on 2026-09-13 while proving D4. The desktop rule
       above pins the sticky summary with `top:88px`, and that declaration
       survives into this block: a fixed box with BOTH offsets and an auto
       height is stretched between them, so the "condensed bar" was in fact a
       756px opaque panel running from just under the header to the bottom of a
       844px phone — the cart lines behind it unreadable, and its CTA pushed
       down to the very bottom edge, which is precisely where it met the consent
       banner (QA capture 16-C1-carrito.png shows the panel; QA measured the CTA
       at y=805..853 of an 864px window, i.e. the bottom of that stretched box).
       Reset the inherited offset and the bar is the height of its own content. */
    position:fixed;left:0;right:0;top:auto;bottom:0;z-index:40;
    display:flex;flex-direction:column;align-items:stretch;gap:0;
    padding:10px 20px calc(10px + env(safe-area-inset-bottom));
    box-shadow:var(--shadow-sheet);
    max-height:62vh;max-height:62dvh;overflow-y:auto;overscroll-behavior:contain;
    animation:cartBarIn var(--dur-mid) var(--ease-out) both;
  }
  /* condensed: the continue-shopping link and the MSI footnote only */
  .cart-summary>.mono:not(.sum-ship),
  .cart-summary>.cart-cont{display:none}
  .cart-summary>.sum-row{font-size:13px;padding:2px 0}
  .cart-summary .sum-total{border-top:1px solid var(--line);margin-top:4px;padding-top:7px;font-size:18px}
  /* la nota «Incluye IVA» viaja pegada al total también en la barra condensada */
  .cart-summary>.sum-iva{font-size:12px;padding-top:0}
  .cart-summary>.sum-ship{margin-top:4px}
  .cart-summary .btn{width:100%!important;margin-top:10px!important;padding:12px 22px;flex:0 0 auto;white-space:nowrap}
  /* the loading skeleton keeps its original in-flow, stacked look */
  .cart-summary-sk{position:static;padding:24px;box-shadow:none;animation:none;
    max-height:none;overflow:visible}

  /* ---------- D4 (QA E2E 2026-09-13): the two bars stop sharing the edge ----
     Measured at 399x864 in a session with consent unanswered: the CTA occupied
     y=805..853 and document.elementFromPoint at its exact centre returned
     DIV#consent-banner. Both are position:fixed;bottom:0 and the banner is the
     higher layer (consent.css, z-index 55 below the burger breakpoint, against
     this bar's 40), so it simply ate the taps — the buyer could not reach
     checkout at all until answering a cookie question.

     They are stacked instead: this bar keeps bottom:0, where the thumb already
     is, and the banner is lifted by exactly the bar's MEASURED height, which
     cart.js publishes as --cart-bar-h on the root element (0 whenever the bar
     is not a pinned, visible bar — desktop, the loading skeleton, an empty
     cart — so the banner is untouched on every other page of the site).

     Why lift the BANNER and not the bar: the banner grows to 85vh with
     Preferencias open, so a bar pushed above it would leave the viewport
     entirely. Lifting the banner keeps both reachable, and its own cap follows
     the same variable so its top can never be pushed off-screen either — the
     QA-F5 defect consent.css already paid for once.

     No :has() anywhere: a custom property works in every engine, including
     Safari before 15.4, so there is no degraded path back into the bug. This
     block sits in cart.css, which base.html links AFTER consent.css and only on
     this page, so it wins at equal specificity without !important. */
  .consent-banner{
    bottom:var(--cart-bar-h,0px);
    /* The cap has to follow the lift, or the banner's own top row leaves the
       top of the screen - the QA-F5 defect consent.css already paid for once.
       It has to follow it ONCE, though. `calc(85vh - var(--cart-bar-h))`
       charges the bar TWICE: the lift already took that room away, and then
       the cap took it again. An adversarial review measured the price on
       2026-09-13: with Preferencias open on a 399x683 phone the granular panel
       was left a 49px slit for 306px of switches, and `save_preferences` sat
       under the cart bar; the same page with `--cart-bar-h:0px` (main's
       geometry) gave it 262px. The room the banner may honestly use is the
       screen minus the bar, capped by the 85vh consent.css already allows -
       which is what min() says. The two plain calc() lines stay FIRST as the
       fallback for an engine without min() (Safari before 11.1): they are
       merely tighter than necessary, never clipped. Residual, measured and
       accepted: on a SHORT phone the panel still scrolls inside itself
       (measured 150px of 306 at 390x667), because 213px of bar plus the
       611px the open banner wants do not fit in 667px of screen - main
       scrolls there too (262 of 306); it just scrolled less by covering
       the bar, which is the bug. At 390x844, the phone of the QA run, the
       panel is whole and needs no scrolling at all: 306 of 306. */
    max-height:calc(85vh - var(--cart-bar-h,0px));
    max-height:calc(85dvh - var(--cart-bar-h,0px));
    max-height:min(85vh,calc(100vh - var(--cart-bar-h,0px)));
    max-height:min(85dvh,calc(100dvh - var(--cart-bar-h,0px)));
    overflow-y:auto;overscroll-behavior:contain;
  }
}
@keyframes cartBarIn{from{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}

/* ============================================================================
   Slice 4d beautification — cart thumbs, summary, branded skeletons, states.
   Single accent = --burgundy; motion is transform/opacity only (reduced-motion
   handled at the bottom). No gold on this page.
   ============================================================================ */

/* ---- line-item thumbnail: fill the frame + gentle hover zoom ---- */
.cart-thumb img{width:100%;height:100%;object-fit:contain;background:#FFFFFF}

/* ---- sticky summary: thin accent cap + emphasized total ---- */
.cart-summary{border-top:2px solid var(--burgundy)}
.cart-summary .sum-total{color:var(--ink)}

/* ---- designed empty / error states (composed, on-brand) ---- */
.state-msg{padding:76px 0}
.state-mark{width:64px;height:64px;margin:0 auto 22px;display:grid;place-items:center;
  font-family:var(--serif);font-size:32px;line-height:1;color:var(--burgundy);
  background:var(--surface);border:1px solid var(--line-2);border-radius:50%}
.state-msg p{max-width:40ch;margin-left:auto;margin-right:auto}
.state-cta{margin-top:22px}

/* ---- branded loading skeletons (shimmer, matching the cart-line shape) ---- */
.cart-line-sk{align-items:center}
.sk-shim,.sk-bar{background:linear-gradient(100deg,var(--cream-2) 30%,var(--sk-1) 50%,var(--cream-2) 70%);
  background-size:200% 100%;animation:sh 1.2s infinite;border-radius:2px}
.cart-thumb.sk-shim{aspect-ratio:4/5}
.sk-bar-xs{height:9px;width:34%;margin-bottom:10px}
.sk-bar-lg{height:20px;width:66%;margin-bottom:10px}
.sk-bar-sm{height:12px;width:46%}
.sk-bar-total{height:16px;width:64px}
.cart-summary-sk{display:flex;flex-direction:column;gap:16px}
.sk-bar-row{height:13px;width:100%}
.sk-bar-total-row{height:22px;width:60%;margin-top:6px}

/* ---- L1/C-12: interest-free line under the summary. Was an inline style on the
   element; moved here unchanged (same size, colour, centring and top margin) so
   the node can be conditional without carrying presentation in the template. ---- */
.cart-msi{font-size:12px;line-height:1.55;color:var(--muted);text-align:center;margin-top:12px}

/* ---- L4 (`modo-catalogo-3`, `promesas-11`): la línea que ocupa el lugar del
   botón de pagar mientras la tienda es catálogo. Mismo registro que la nota de
   meses sin intereses (tamaño, color y centrado ya existentes); sin la clase
   `mono`, para que la barra condensada del móvil —que oculta
   `.cart-summary>.mono:not(.sum-ship)`— NO se la lleve por delante: es
   precisamente la pantalla donde el resumen se queda sin salida. ---- */
.cart-open-note{font-size:12px;line-height:1.55;color:var(--muted);text-align:center;margin-top:16px}

/* ---- reduced motion: no thumb zoom, mobile bar appears at rest (opacity only),
   no leaving fade (JS splices immediately) ---- */
@media(prefers-reduced-motion:reduce){
  .cart-thumb img,.cart-thumb:hover img{transition:none;transform:none}
  .cart-summary{animation:none!important}
  .cart-line.is-leaving{transition:none;opacity:1;transform:none}
}

/* ---- Narrow phones: the page measured 399px wide at a 375px viewport (the
   line grid's fixed columns plus the total pushed past the edge). Below 600px
   the total drops under the title column and the quantity row may wrap; no
   money row is hidden. ---- */
@media(max-width:600px){
  .cart-line{grid-template-columns:72px minmax(0,1fr);gap:14px}
  .cart-meta{min-width:0}
  .cart-meta .house{font-size:11px;letter-spacing:.1em}
  .cart-line-total{grid-column:2;justify-self:start;white-space:nowrap;margin-top:4px}
  .qty{flex-wrap:wrap;row-gap:8px}
  .qty .cart-rm{min-height:44px;padding:12px 6px}
  .cart-line-sk .sk-bar-total{grid-column:2}
}

@media(min-width:601px) and (max-width:1000px){.qty-stepper{gap:4px}.qty-stepper .qty-btn{width:44px;height:44px}.qty-n{min-width:36px}.qty .cart-rm{min-height:44px;padding:12px 6px}.cart-summary{padding-inline:max(20px,calc((100% - 560px) / 2))}}
