/* ============================================================
   cart-page.css — Flex Europa · finaldesign
   The full-page shopping bag (§3.4).

   REUSE: the lines ARE the drawer's .cart-line — same markup, same
   .qty stepper, same .spec-row summary, same .skeleton-line loading
   state, same undo bar, all from css/shared/cart.css, and all driven by
   the same cart.js. This page is a second VIEW of one component, not a
   second implementation of it (§8).

   On a full-width page the line gets more room, so this file widens the
   media well and pulls the controls onto the same row. It changes the
   line's TRACK SIZES only — never its internals.
   ============================================================ */

.bag {
  padding-block: var(--space-2xl) var(--space-3xl);
  /* The stacked line's media well. Declared once and used by BOTH the grid
     track and the element, because setting them separately is exactly how
     the 96px thumbnail came to overflow a 72px track and draw over the
     product name. */
  --bag-media-stack: 72px;
}
.bag__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--bag-summary-inline);
  gap: var(--space-2xl);
  align-items: start;
}

.bag__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  padding-block-end: var(--space-md);
  border-block-end: var(--hairline-strong);
  /* Reserve the tallest thing this row will ever hold. The count starts as
     empty text and "Empty the bag" starts hidden — a 44px button. When both
     arrived the row grew from 18px to 44px and pushed the whole layout down,
     which was the entire measured CLS on this page (0.105 at 1440px). */
  min-block-size: calc(var(--step-size) + var(--space-md));
}
.bag__count {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.bag__count strong { color: var(--color-text); font-weight: var(--fw-semibold); }

/* ---------------------------------------------------------------- Lines
   On a wide page the bag is a TABLE: four labelled columns and a remove
   control. That is what the drawer cannot be at 420px, and it is the whole
   reason this second view exists.

   The geometry this replaces put .cart-line__controls and
   .cart-line__remove in ONE grid area, so the bin drew on top of the
   stepper's corner; and with only three content boxes it left a measured
   570px of dead space between the name and the controls at 1440px. Six
   tracks fix both: the void becomes the info column's own slack, and every
   control has its own cell.

   WHY 1200px AND NOT 768px. The five right-hand tracks are fixed, and with
   five --space-md gaps they come to 560px. The items column is the
   container minus the 340px summary rail, which measures 508px at 992 and
   716 at 1200 — so below about 1200 there is nothing left for the product
   name, and the first attempt at this (breaking at 768) drove the name to
   three lines and the row from 161px to 312px. The table appears exactly
   where a table fits; everywhere else the drawer's stacked line is already
   the right answer for a ~500px column, which is what it was designed for.
   ---------------------------------------------------------------- */
.bag__items { display: flex; flex-direction: column; }

/* ONE definition of the track list, shared by the header row, every line
   and the loading skeleton. Fixed widths on the five right-hand tracks are
   what let three separate grids line up. */
.bag__cols,
.bag__items .cart-line,
.bag__skeleton .skeleton-line {
  grid-template-columns:
    var(--bag-media-col) minmax(0, 1fr)
    var(--bag-num-col) var(--bag-qty-col) var(--bag-num-col) var(--step-size);
  grid-template-areas: "media info price qty total remove";
  align-items: center;
  gap: var(--space-md);
  padding-block: var(--space-lg);
}

/* Column headings. aria-hidden because they are decoration for a list that
   is already fully labelled: each line names its own product, and the
   figures carry their meaning in the copy below 768px. Announcing five
   more strings per row would only slow a screen reader down. */
.bag__cols {
  display: grid;
  padding-block: var(--space-sm);
  border-block-end: var(--hairline);
}
.bag__col {
  font-family: var(--font-mono);
  font-size: var(--fs-tiny);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--color-text-faint);
}
/* Each heading is PLACED, not auto-flowed. Four cells in a six-track grid
   auto-place into tracks 1-4 — the labels then sat one column to the left
   of the figures they name, which is worse than no labels at all. */
.bag__col--product { grid-area: info; }
.bag__col--price   { grid-area: price; text-align: end; }
.bag__col--qty     { grid-area: qty;   text-align: center; }
.bag__col--total   { grid-area: total; text-align: end; }

.bag__items .cart-line__media { inline-size: var(--bag-media-col); block-size: var(--bag-media-col); }

/* .cart-line__controls wraps the stepper and the line total so that ONE
   box carries both in the drawer and on a phone. Here they need to be two
   separate columns, so the wrapper is flattened out of the grid rather
   than duplicated in the markup.
   HAZARD: a display:contents box paints nothing, so the drawer's
   `.is-busy .cart-line__controls { opacity: .5 }` stops working. The busy
   rule below re-applies it to the children it flattened. */
.bag__items .cart-line__controls { display: contents; }
.bag__items .cart-line.is-busy .qty { opacity: .5; }

.bag__items .qty { grid-area: qty; justify-self: center; }
.bag__items .cart-line__total { grid-area: total; justify-self: end; }
.bag__items .cart-line__remove { grid-area: remove; justify-self: end; }

.bag__items .cart-line__price {
  grid-area: price;
  justify-self: end;
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-muted);
}
/* "each" only earns its place where there is no column heading to say so. */
.bag__items .cart-line__price-each { display: none; }

.bag__items .cart-line__name {
  font-size: var(--fs-lg);
  /* The product name is the line's link to its page. On two lines it came
     to 42px — just under the target floor. */
  display: inline-flex;
  align-items: center;
  min-block-size: var(--step-size);
}

/* ---------------------------------------------------------------- Summary */
.bag__summary {
  position: sticky;
  /* Clears the sticky site header on internal pages. */
  inset-block-start: var(--anchor-offset);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding: var(--space-lg);
  background: var(--color-surface);
  border: var(--hairline);
}
.bag__summary-title {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--color-text);
}
.bag__note { font-size: var(--fs-tiny); color: var(--color-text-muted); }
.bag__actions { display: grid; gap: var(--space-sm); }

/* Free-delivery progress — a real <progress> would not take the brand
   treatment, so this is a labelled bar with the figure stated in text.
   The text is the accessible source of truth; the bar is decoration. */
.bag__freeship { display: flex; flex-direction: column; gap: var(--space-xs); }
.bag__freeship-text { font-size: var(--fs-tiny); color: var(--color-text-muted); }
.bag__freeship-track {
  block-size: 4px;
  background: var(--color-border);
  overflow: hidden;
}
.bag__freeship-fill {
  display: block;
  block-size: 100%;
  inline-size: 0;
  background: var(--color-accent-strong);
  transition: inline-size var(--transition-base);
}

/* ---------------------------------------------------------------- Undo */
/* The drawer's undo bar, docked to the page instead of a panel. */
.bag__undo { margin-block-start: var(--space-md); }

/* ---------------------------------------------------------------- States */
.bag__state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  text-align: center;
  padding-block: var(--space-3xl);
}
.bag__state-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 64px;
  block-size: 64px;
  border: var(--hairline-strong);
  color: var(--color-text-faint);
}
.bag__state-icon .icon { inline-size: 28px; block-size: 28px; }
.bag__state-title {
  font-family: var(--font-heading);
  font-size: var(--fs-xl);
  font-weight: var(--fw-semibold);
  color: var(--color-text);
}
.bag__state-text { font-size: var(--fs-sm); color: var(--color-text-muted); max-inline-size: 46ch; }

/* ---------------------------------------------------------------- Loading
   The skeleton is the same grid as a real line at every width, so the
   loading state looks like the thing it is loading and every figure lands
   where its placeholder was. Height matches by construction: both are the
   media well plus this file's own padding-block, and the media well is the
   tallest thing in the row either way.
   ---------------------------------------------------------------- */
.bag__skeleton .skeleton-line { border-block-end: var(--hairline); }
.bag__skeleton .skeleton-line__media {
  inline-size: var(--bag-media-col);
  block-size: var(--bag-media-col);
}
.bag__skeleton .skeleton-line__bar--price { grid-area: price; justify-self: end; }
.bag__skeleton .skeleton-line__bar--qty   { grid-area: qty;   justify-self: center; }
.bag__skeleton .skeleton-line__bar--total { grid-area: total; justify-self: end; }
/* The price column has no counterpart in the drawer, so its bar is defined
   here — sized against the same token as the text it stands in for. */
.bag__skeleton .skeleton-line__bar--price {
  font-size: var(--fs-sm);
  block-size: 1.5em;
  inline-size: 88px;
}

/* ---------------------------------------------------------------- Breakpoints */
@media (max-width: 991px) {
  .bag__layout { grid-template-columns: minmax(0, 1fr); }
  .bag__summary { position: static; }
}

@media (max-width: 1199px) {
  /* Back to the drawer's own stacked geometry: six columns cannot survive a
     508px items column, and the drawer already solved this exact shape at
     420px. The unit price rejoins the info stack, where "each" tells you
     what it is now that the column heading is gone. */
  .bag__cols { display: none; }

  .bag__items .cart-line,
  .bag__skeleton .skeleton-line {
    grid-template-columns: var(--bag-media-stack) minmax(0, 1fr) auto;
    align-items: start;
    gap: var(--space-xs) var(--space-md);
    padding-block: var(--space-lg);
  }
  /* Two area maps, because here the two grids really do hold different
     children: the line keeps its controls wrapper, the skeleton's bars are
     flat. Both resolve to the same three rows and the same heights. */
  .bag__items .cart-line {
    grid-template-areas:
      "media info     remove"
      "media price    price"
      "media controls controls";
  }
  .bag__skeleton .skeleton-line {
    grid-template-areas:
      "media info  remove"
      "media price price"
      "media qty   total";
  }
  .bag__items .cart-line__media,
  .bag__skeleton .skeleton-line__media {
    inline-size: var(--bag-media-stack);
    block-size: var(--bag-media-stack);
  }

  /* The wrapper is a real box again, so the stepper and the total share one
     row exactly as they do in the drawer. */
  .bag__items .cart-line__controls {
    display: flex;
    grid-area: controls;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    margin-block-start: var(--space-xs);
  }
  .bag__items .cart-line__price {
    justify-self: start;
    font-size: var(--fs-tiny);
  }
  .bag__items .cart-line__price-each { display: inline; }
  .bag__items .cart-line__remove { align-self: start; }
  .bag__items .cart-line__name { font-size: var(--fs-md); }

  .bag__skeleton .skeleton-line__bar--price { justify-self: start; }
  .bag__skeleton .skeleton-line__bar--qty { justify-self: start; }
}

@media (min-width: 576px) and (max-width: 1199px) {
  /* The stacked line in a WIDE row. space-between is right in a 420px
     drawer; in a 691px row it threw the stepper and the total 470px apart,
     which is the same void the table was built to close — the two belong to
     each other and now read as one control. The media well matches the
     table's, so the thumbnail is not lost in the width. */
  .bag__items .cart-line__controls {
    justify-content: flex-start;
    gap: var(--space-md);
  }
  /* Matches the table's well, so the thumbnail is not lost in the width. */
  .bag { --bag-media-stack: var(--bag-media-col); }
}
