/* ==========================================================================
   mobile.css — Mobile markup refactor (2026-06)

   Loaded AFTER main.css (see AppAsset) so equal-specificity rules win the
   cascade. Scope: the public storefront only (admin is out of scope).

   Guiding principle: full desktop -> mobile content parity. Nothing that is
   visible on desktop may be silently dropped on mobile — we reflow and
   progressively disclose (accordions / toggles / swipe rails) instead of
   hiding. References: Coursera (general pages) and Walmart (catalog + PDP).

   Sections:
     1. Type scale (replaces the blunt 80% root zoom)
     2. Reusable components (sticky action bar, disclosure/accordion, swipe rail,
        applied-filter chips)
     3. Parity restorations (un-hide the silent drops)
     4. Catalog PLP — two-up grid + bottom "Refine your search" bar
     5. Product PDP — sticky buy bar + collapsible info blocks
     6. Course detail — sticky enroll bar
     7. General reflow niceties
   ========================================================================== */

:root {
  /* Measured at runtime by mobile.js so sticky toolbars sit exactly under the
     mobile header instead of guessing. Default matches the two-row mobile
     header height for the first paint before JS measures the real value. */
  --mobile-header-h: 110px;
}

/* ==========================================================================
   1. TYPE SCALE
   main.css scales the whole document to 80% below 800px, which is the single
   biggest cause of the cramped feel — every rem shrinks uniformly, including
   body copy. Bump to 87.5% (~14px base) for readability. This is the one knob
   to tune if anything overflows; revert to 80% to fully restore prior sizing.
   ========================================================================== */
@media only screen and (max-width: 799px) {
  html {
    font-size: 87.5%;
  }
}

/* ==========================================================================
   2. REUSABLE COMPONENTS
   ========================================================================== */

/* --- 2a. Sticky action bar -------------------------------------------------
   A bottom-pinned bar for the page's primary action (Buy on Amazon / Enroll).
   Hidden on desktop; revealed on mobile by mobile.js once the user scrolls
   past the inline buy/enroll block. */
.sticky-action-bar {
  display: none;
}

@media (max-width: 799px) {
  .sticky-action-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 2500;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    padding: 14px 16px;
    padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px));
    background: #fff;
    border-top: 1px solid #ececf0;
    box-shadow: 0 -6px 22px rgba(20, 18, 40, 0.1);
  }

  .sticky-action-bar__price {
    display: flex;
    flex-direction: column;
    justify-content: center;
    line-height: 1;
    white-space: nowrap;
    /* Nudge up ~2px: the Money widget's superscript cents lift the box centre
       above the digits, so centring alone leaves the number sitting low. */
    transform: translateY(-4px);
  }

  .sticky-action-bar__price .product-view__price,
  .sticky-action-bar__price .course-card__price {
    font-size: 2.125rem;
    font-weight: 700;
  }

  .sticky-action-bar__price-old {
    font-size: 0.85rem;
    color: #131313;
    text-decoration: line-through;
  }

  .sticky-action-bar__cta {
    margin-left: 0;
    flex: 0 0 auto;
  }

  /* Room for this bar over the site footer is no longer reserved here. It used
     to be a page-level `body:has(.sticky-action-bar) { padding-bottom }`, which
     is a second, competing mechanism next to the lesson page's footer padding —
     and padding the body lands the reservation AFTER the footer, as a strip of
     page background. Both are now one site-wide rule that pads .footer__bottom
     by the measured height of whatever bottom bar a page happens to show; see
     "Sticky bottom bars vs the footer" in main.css and measureBottomBars() in
     mobile.js. */
}

/* --- 2b. Disclosure / accordion -------------------------------------------
   Desktop: everything is expanded and the header is a plain heading.
   Mobile: the header becomes a tap target that collapses its panel — content
   stays in the DOM (parity) but long pages stop being a wall of text. */
.disclosure__panel {
  display: block;
}

.disclosure__head {
  cursor: default;
}

@media (max-width: 799px) {
  .disclosure {
    border-bottom: 1px solid #ececf0;
  }

  .disclosure__head {
    display: flex !important;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    margin: 0;
    padding: 16px 2px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  .disclosure__head::after {
    content: "";
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    margin-right: 4px;
    border-right: 2px solid #1d1929;
    border-bottom: 2px solid #1d1929;
    transform: rotate(45deg);
    transition: transform 0.2s ease;
  }

  .disclosure.is-open > .disclosure__head::after {
    transform: rotate(-135deg);
  }

  .disclosure__panel {
    display: none;
    padding-bottom: 18px;
  }

  .disclosure.is-open > .disclosure__panel {
    display: block;
  }
}

/* --- 2c. Swipe rail --------------------------------------------------------
   Horizontal scroll-snap row for peripheral collections / chip lists, so they
   stay reachable on a narrow screen without wrapping into a tall block. */
.swipe-rail {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.swipe-rail::-webkit-scrollbar {
  display: none;
}

.swipe-rail > * {
  flex: 0 0 auto;
  scroll-snap-align: start;
}

/* --- 2d. Applied-filter chips ---------------------------------------------
   The set of active facets, each removable, shown above the grid so the
   filtered state is always visible (Walmart pattern). */
.applied-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin: 4px 0 14px;
}

.applied-filter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px 6px 12px;
  border-radius: 999px;
  background: #fce8f6;
  color: #b00684;
  font-size: 0.85rem;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
}

.applied-filter::after {
  content: "\00d7";
  font-size: 1.1rem;
  line-height: 0.8;
  opacity: 0.8;
}

.applied-filter:hover {
  background: #f8d6ee;
}

.applied-filter--clear {
  background: transparent;
  color: #131313;
  text-decoration: underline;
}

.applied-filter--clear::after {
  content: none;
}

/* ==========================================================================
   3. PARITY RESTORATIONS — un-hide what main.css silently dropped on mobile
   (decision: show on mobile). Each rule pairs with a finding from the audit.
   ========================================================================== */
@media only screen and (max-width: 799px) {
  /* ── Best-sellers slider card ─────────────────────────────────────────────
     The base mobile rules (main.css) reflow every ProductCard into a compact
     phone layout (8px head, head stock hidden, a left-aligned column price box,
     the below-price stock label, rem fonts shrunk by the 87.5% root zoom). Per
     the client request the homepage slider card keeps its desktop
     representation instead, so each rule below restores that look for
     `.main-new-items`.

     The catalog grid used to ride these same selectors (one full-width card per
     row, desktop internals). It no longer does: the grid is a two-up Walmart/
     Amazon-style layout now and deliberately KEEPS the compact base mobile card
     — see section 4 for its own tuning. Editing the rules below therefore only
     moves the homepage slider. */

  /* Structure — revert the base mobile overrides to their desktop values. */
  .main-new-items .card__head {
    padding: 16px;
  }
  .main-new-items .card__stock {
    display: flex; /* desktop shows the stock badge in the head row… */
  }
  .main-new-items .card__stock-mobile {
    display: none; /* …so the below-price mobile variant stays hidden */
  }
  .main-new-items .card__price-box {
    min-height: 0;
    -webkit-box-orient: horizontal;
    -webkit-box-direction: normal;
    -ms-flex-flow: row nowrap;
    flex-flow: row nowrap;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
  }
  .main-new-items .card__body-box {
    height: auto;
  }

  /* Fonts — aligned to the 16px mobile baseline (px values stay immune to the
     87.5% root zoom); the price stays prominent. */
  .main-new-items .card__sku {
    font-size: 16px;
  }
  .main-new-items .card__title {
    font-size: 16px;
    line-height: 24px;
    /* Drop the desktop row-alignment reservation so the price sits close under
       the title instead of after a large gap. */
    min-height: 0;
    margin-bottom: 12px;
  }
  .main-new-items .card__stock {
    font-size: 16px;
    line-height: 24px;
  }
  .main-new-items .card__price {
    font-size: 28px;
    line-height: 24px;
  }
  .main-new-items .card__oldprice {
    font-size: 16px;
  }

  /* A–Z / article index side rail (pro-tips, glossary, styles) was fully
     hidden on mobile — list, heading AND its toggle. Bring it back as a
     normal stacked block; the built-in "Show more" still caps the length. */
  .all-list,
  .all-list h2,
  .all-list .news__header {
    display: block !important;
  }

  .news__side,
  .articles__side {
    width: 100%;
    margin-top: 24px;
  }

  /* The list is shown directly now, so the redundant slide-toggle handle that
     used to gate it is no longer needed on mobile. */
  #show-products {
    display: none !important;
  }

  /* Course grades — attempt-history rows lost every value column on mobile
     (only the main row had a mobile reflow). Let the value cells wrap back in
     under the attempt label; drop the empty spacer column. */
  .grade-module__attempt {
    flex-wrap: wrap;
    row-gap: 4px;
  }

  .grade-module__attempt .grade-module__col {
    display: block;
    width: auto;
    min-width: 0;
  }

  .grade-module__attempt .grade-module__col.--w-4 {
    display: none;
  }

  .grade-module__attempt .grade-module__value {
    font-size: 0.85rem;
    color: #131313;
  }
}

/* ==========================================================================
   4. CATALOG PLP — two-up product grid + bottom "Refine your search" bar
   Mobile listing shape (client, 2026-07, Walmart / Amazon reference shots):
     - two cards per row, compact, edge-aligned to the page container;
     - NO sticky top toolbar at all — the Filter/Sort pills and the result
       count are gone (Sort is withdrawn entirely, markup removed from the
       view; its JS feature-detects the sheet and no-ops);
     - the only filter entry point is a rose "Refine your search" button in a
       bar pinned to the bottom of the viewport, reusing the shared
       .sticky-action-bar panel so it inherits the body bottom offset that
       keeps the footer clear of it.
   ========================================================================== */

/* Applied-filter chips are a mobile addition here (desktop keeps the sidebar). */
.catalog__chips {
  display: none;
}

@media (max-width: 799px) {
  .catalog__chips.applied-filters {
    display: flex;
    margin: 12px 0 14px;
  }

  /* --- 4a. Container alignment ---------------------------------------------
     .catalog already carries the page's 16px gutter — the same gutter the
     mobile header's burger and its right-hand action tiles sit on. .catalog__main
     stacked a SECOND 16px on top of it, insetting the grid to 32px so the cards
     sat visibly narrower than the header. Drop the inner gutter: the grid then
     spans 100% of the available container width, left card edge under the
     burger, right card edge under the header buttons. Not full-bleed — the
     container keeps its own 16px offsets. */
  .catalog__main {
    padding: 0;
  }

  /* --- 4b. Two-up grid ------------------------------------------------------
     Grid (not the legacy flex + negative margins) so the two columns are exactly
     half the container each and both cards in a row share one height. */
  .catalog__items {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    width: 100%;
    margin: 0;
  }

  .catalog__items .card--catalog {
    width: auto;
    margin: 0;
  }

  /* --- 4c. Half-width card internals ----------------------------------------
     The card keeps the compact BASE mobile layout from main.css (8px head, the
     stock label under the price, left-aligned price box); everything below just
     tightens it for a ~170px-wide tile. Deliberately scoped to .catalog__items
     so the homepage best-sellers slider (same widget) is untouched. */
  .catalog__items .card {
    /* Both cards in a row are equal height; the body fills the leftover space so
       the price/stock block sits at a consistent depth. */
    height: 100%;
  }

  .catalog__items .card__head {
    /* The head carries the code pill and the optional deal/best-seller peel.
       Let it wrap rather than overflow the narrow tile. */
    flex-flow: row wrap;
    row-gap: 4px;
    padding: 8px 8px 0;
  }

  .catalog__items .card__sku {
    padding: 0 7px;
    font-size: 11px;
    letter-spacing: 0.02em;
  }

  .catalog__items .card__badge {
    height: 18px;
    margin: 0 0 0 auto;
    padding: 2px 6px;
    font-size: 10px;
    line-height: 14px;
  }

  .catalog__items .card__body-box {
    /* Push the body to fill the card so equal-height rows stay tidy. */
    flex: 1 1 auto;
  }

  .catalog__items .card__body {
    align-items: flex-start;
    padding: 8px 10px 12px;
  }

  /* Title: two lines, then the shared trailing-edge fade (never an ellipsis,
     never -webkit-line-clamp). The fade needs left-aligned text so the cut lands
     on the box's right edge. */
  .catalog__items .card__title {
    --fade-lines: 2;
    --fade-size: 2em;
    margin-bottom: 6px;
    font-size: 14px;
    line-height: 18px;
    text-align: left;
  }

  /* Price block centred in the tile (client, 2026-07) — the title above it
     stays left-aligned, both because it is the scan anchor and because the
     shared text-fade clamp requires a left edge to fade from. Centring the box
     rather than just the price keeps the live price, the discount pair and the
     stock line on one axis instead of three. */
  /* The price block sits inside a <noindex> wrapper (a search-engine hint in
     the card markup). Being an unknown element it defaults to display:inline,
     but as a child of the flex .card__body it is blockified into a flex item —
     and .card__body is align-items:flex-start, so the wrapper shrink-wraps to
     the price text. `width:100%` on the box inside then resolves against that
     ~47px wrapper rather than the tile, which is why centring appears to do
     nothing. Stretch the wrapper first. */
  .catalog__items .card__body > noindex {
    display: block;
    width: 100%;
  }

  .catalog__items .card__price-box {
    row-gap: 2px;
    width: 100%;
    justify-content: center;
    align-items: center;
    text-align: center;
  }

  .catalog__items .card__price {
    font-size: 22px;
    line-height: 26px;
    text-align: center;
  }

  /* The struck list price + discount peel ride beside the live price on a
     narrow tile instead of hanging off its right edge. */
  .catalog__items .card__deal {
    flex-flow: row nowrap;
    align-items: center;
    gap: 6px;
    margin-left: 0;
  }

  .catalog__items .card__discount {
    padding: 2px 6px;
    font-size: 11px;
  }

  .catalog__items .card__oldprice {
    font-size: 12px;
  }

  .catalog__items .card__stock-mobile {
    font-size: 12px;
    line-height: 16px;
  }

  /* --- 4d. Bottom "Refine your search" bar ---------------------------------
     The bar itself is the shared .sticky-action-bar (section 2a): fixed to the
     bottom, white plate, and already covered by the body bottom offset that
     keeps the footer readable. Only the button geometry differs — one full-width
     rose CTA instead of a price + CTA pair. */
  .catalog__refine-bar .mobile-filter-btn {
    margin: 0;
  }

  /* The legacy inline filter button block is superseded by the bottom bar. */
  .catalog__mobile-filter-btn {
    display: none !important;
  }
}

/* ==========================================================================
   5. PRODUCT PDP — collapsible info blocks
   The sticky buy bar uses the shared .sticky-action-bar. Here we make the
   below-fold info blocks collapsible on mobile (mobile.js adds .disclosure).
   ========================================================================== */
@media (max-width: 799px) {
  /* main.css gives .product-view__title a uniform `margin: -7px` — an optical
     hack for the desktop buy column, where the title is nested inside padding
     that absorbs it. On a phone the heading is a direct child of the page grid
     (it now sits above the gallery), so that negative margin hangs the block
     7px outside the 16px gutter on BOTH sides: the box measured 9 -> 381 while
     every sibling — brand pills, gallery, thumb strip, benefits, breadcrumbs —
     sits at 16 -> 374. Drop the horizontal halves only; the vertical -7px is
     load-bearing for the heading's rhythm and stays. */
  .product-view__title {
    margin-left: 0;
    margin-right: 0;
  }

  /* mobile.js tags each .info-block in the columns area as a .disclosure and
     its title as the head. Give the title the head affordance. */
  .product-view__cols .info-block.disclosure .info-block__title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: 0;
    padding: 16px 2px;
    cursor: pointer;
  }

  .product-view__cols .info-block.disclosure .info-block__title::after {
    content: "";
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    margin-right: 4px;
    border-right: 2px solid #1d1929;
    border-bottom: 2px solid #1d1929;
    transform: rotate(45deg);
    transition: transform 0.2s ease;
  }

  .product-view__cols .info-block.disclosure.is-open .info-block__title::after {
    transform: rotate(-135deg);
  }

  .product-view__cols .info-block.disclosure {
    border-bottom: 1px solid #ececf0;
  }

  .product-view__cols .info-block.disclosure .info-block__prose,
  .product-view__cols .info-block.disclosure .key-features {
    display: none;
    padding-bottom: 18px;
  }

  .product-view__cols .info-block.disclosure.is-open .info-block__prose,
  .product-view__cols .info-block.disclosure.is-open .key-features {
    display: block;
  }
}

/* ==========================================================================
   5b. PRODUCT PDP — phone layout of the top half
   Scope: phones only (<= 799px). Desktop keeps the two-column buy box exactly
   as it is; every rule below lives inside the media query.

   Ordering trick: `.product-view__buy` becomes `display: contents`, so its
   children join the single-column `.product-view__top` grid as siblings of the
   gallery. `order` then lifts the H1 + SKU chip and the brand pills above the
   image viewer — no duplicated markup, no DOM restructuring.
   ========================================================================== */
@media (max-width: 799px) {
  .product-view__top {
    /* One shared rhythm now that the buy box's children are grid items; matches
       the 20px the buy column used for its own flex gap. */
    gap: 20px;
  }

  .product-view__buy {
    display: contents;
  }

  /* Product header above the image viewer: title + SKU chip first, then the
     brand / collection pills, then the gallery and the rest in document order. */
  .product-view__heading {
    order: -2;
  }

  .product-view__identity {
    order: -1;
  }

  /* Gallery stacks: the viewer on top, the thumbnail strip under it. */
  .product-view__gallery {
    grid-template-columns: 1fr;
  }

  .product-view__main {
    order: 1;
  }

  /* Thumbnail strip — exactly four per row, each an equal quarter of the strip
     width, inner gaps only: the first thumb's left edge and the last thumb's
     right edge sit flush with the strip's edges at any viewport width. */
  .product-view__thumbs {
    order: 2;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--thumb-gap);
  }

  .product-view__thumb {
    width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
  }

  /* The thumb is now fluid, so the image fills it from the frame rather than
     from a percentage height against an auto-sized box. */
  .product-view__thumb > img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
  }

  /* No hover blow-up on touch (also kept out of the flow above 640px now that
     the strip is horizontal across the whole phone range). */
  .product-view__thumb-preview {
    display: none;
  }

  /* The three featured benefits ride in ONE row; captions wrap to 2-3 lines,
     which is expected at this width. */
  .product-view__benefits {
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
  }

  .product-view__benefit {
    min-height: 0;
    padding: 10px 6px;
    font-size: 0.82rem;
    line-height: 1.25;
  }

  /* The sticky bottom bar already carries this price and "Buy on Amazon", so
     the in-flow block is a duplicate on a phone. Desktop has no sticky bar and
     therefore keeps it. */
  .product-view__purchase {
    display: none;
  }
}

/* ==========================================================================
   6. COURSE DETAIL — sticky enroll bar host spacing
   (the bar itself is .sticky-action-bar; nothing extra needed here beyond the
   body padding already handled in 2a).
   ========================================================================== */

/* ==========================================================================
   7. GENERAL REFLOW NICETIES
   ========================================================================== */
@media (max-width: 799px) {
  /* Let an A–Z letter index ride as a horizontal swipe rail instead of
     wrapping into a tall block. Opt-in via .swipe-rail on the markup. */
  .news__side-list.swipe-rail {
    padding-bottom: 6px;
  }

  /* main.css stacks a 24px padding-bottom AND a 24px margin-bottom under the
     breadcrumb nav, so on a phone the last crumb floats ~48px above the page
     title — a lot of dead space when the crumb has already wrapped to two
     lines. Halve both. On the PDP the title's own -7px vertical margin eats
     into this, landing the crumb-to-title gap at 17px (was 41px); on pages
     without that hack the gap is 24px (was 48px). The top inset is left alone:
     that one sets the distance from the header divider. */
  .breadcrumbs {
    padding-bottom: 12px;
    margin-bottom: 12px;
  }
}

/* --- 7a. Filter drawer density ---------------------------------------------
   Deliberately NOT media-scoped: `.mobile-filter__*` is drawer-only markup that
   main.css already hides on desktop, and the drawer's own reveal breakpoint
   differs per host (catalog vs courses grid). Scoping these to 799px would let
   the level-path picker's mobile rules apply at a width where these did not,
   re-opening the very gap they close.

   The first facet used to sit far below whatever preceded it: 32px of the
   wrapper's own padding-top on top of the preceding block's 16px margin (the
   level-path picker on the courses grid, the category tree on the catalog).
   Zero the wrapper's inset so the preceding block's 16px owns that space alone
   — one number to reason about, and it matches the 16px between facet groups
   below, which is what the client asked these gaps to line up with. */
.mobile-filter__filters {
  padding-top: 0;
}

/* Facet groups were 24px apart, which reads loose once the pills inside them
   are only 32px tall. */
.mobile-filter__filter {
  margin-bottom: 16px;
}
