/* =============================================================================
   98-shelf-sticky-header.css — v16.122
   THE SHELF'S CATEGORY STRIP + STATUS ROW STAY PUT WHILE THE CARDS SCROLL.

   Owner spec: a user deep in a long list should be able to switch category,
   switch status, search or sort without scrolling back to the top. So only
   #cards-grid moves; #mylist-header (GAMES · ANIME · MUSIC · MOVIES · TV) and
   #mylist-toolbar (the status tabs + search + sort chips) pin under the island.

   ---------------------------------------------------------------------------
   THE ONE THING THAT MAKES THIS HARD

   `position: sticky` is SILENTLY KILLED by `contain: paint` on an ancestor —
   no error, no warning, the element just scrolls away. #mylist-view carries
   `contain: paint` as a scroll-perf hint, and #mylist-header carries it too, so
   both are released below. This is the same trap documented for the discovery
   hub in SETUP MEMORY; it is why the first attempt at a sticky shelf header
   would appear to do nothing at all.

   The identity `transform: translate3d(0,0,0)` on those elements is FINE and is
   left alone — a transform creates a containing block for `fixed`, but does not
   break `sticky`.

   ---------------------------------------------------------------------------
   THE TWO OFFSETS

   The rows pin one under the other, so the toolbar's `top` is the header's `top`
   plus the header's height. That height is measured live into
   `--shelfd-mylist-header-h` by js/98-shelf-sticky-header.js rather than
   hardcoded, because the header row is 52px on your own shelf and a different
   height on a viewed one (the edit controls are owner-only).

   `--shelfd-safe-top` is paired with `env(safe-area-inset-top)` via max(): env()
   resolves to 0 inside the Capacitor webview, so env() alone would pin the rows
   under the Dynamic Island instead of below it.
   ============================================================================= */

body.main-tab-mylist {
  --shelfd-mylist-sticky-top: max(var(--shelfd-safe-top, 0px), env(safe-area-inset-top, 0px));
}

/* 1) Release only the containment that kills sticky.

      `contain: paint` is the specific offender — it clips, which makes the
      element the sticky container and the rows scroll away inside it. `layout`
      and `style` do neither, so the browser keeps those optimisations.

      MEASURED, counterbalanced, on an 87-card list: baseline `paint`,
      `none`, and `layout style` all scroll at a 2.8ms median / 5.6ms p95 with
      zero frames over the 8.3ms 120Hz budget. An earlier reading that showed a
      regression was warm-up from freshly appending 87 cards, not containment. */
body.main-tab-mylist #mylist-view,
body.main-tab-mylist #mylist-header {
  contain: layout style !important;
}

/* The pin sentinel (js/98). 1px, above the header, watched by an
   IntersectionObserver — it must occupy real space to be observable, so it is
   sized rather than hidden, and pulled back out of the layout with a margin. */
.shelfd-mylist-header-sentinel {
  height: 1px;
  margin-bottom: -1px;
  pointer-events: none;
}

/* -----------------------------------------------------------------------------
   SPECIFICITY NOTE — why these selectors carry a :not() that excludes nothing.

   35-shelf-banner.css already declares
     body.main-tab-mylist:not(.viewing-other-user) #mylist-view
       #mylist-header.mylist-section-card { position: relative !important }
   at (2,3,0). A plain `body.main-tab-mylist #mylist-view #mylist-header` is
   (2,1,0) and loses the tie no matter how many !importants it carries — the
   rows simply kept scrolling away with no error to explain it.

   `:not(.shelfd-no-sticky-header)` brings this to (2,3,0), and this file loads
   after 35, so the later rule wins. It is also a real escape hatch: put that
   class on <body> and the shelf header goes back to scrolling, which is a
   cheaper way to rule the sticky header in or out of a bug report than editing
   CSS.
   -------------------------------------------------------------------------- */

/* 2) The category strip pins first. */
body.main-tab-mylist:not(.shelfd-no-sticky-header) #mylist-view #mylist-header.mylist-section-card {
  position: sticky !important;
  /* !important because 35-shelf-banner.css sets `top: 9px !important` on this
     same element — an offset for the non-sticky layout that would otherwise pin
     the strip 9px down and, worse, apply the SAME 9px to the toolbar so the two
     rows stacked on top of each other. */
  top: var(--shelfd-mylist-sticky-top, 0px) !important;
  z-index: 40;
}

/* 3) The status row pins directly beneath it. */
body.main-tab-mylist:not(.shelfd-no-sticky-header) #mylist-view #mylist-toolbar.toolbar {
  position: sticky !important;
  /* + --shelf-midline-row: the hairline between the two rows occupies a 1px row
     of its own, which is this element's top MARGIN in normal flow
     (100-shelf-header.css). Sticky positioning replaces that margin, so without
     adding it back the row pins 1px high and the line clears the category text
     by 2px pinned vs 3px unpinned. */
  top: calc(var(--shelfd-mylist-sticky-top, 0px) + var(--shelfd-mylist-header-h, 52px) + var(--shelf-midline-row, 1px)) !important;
  z-index: 39;
}

/* -----------------------------------------------------------------------------
   v16.131 — THE PINNED CHROME: full-bleed fill + a full-bleed divider per row.

   Only once `body.shelfd-mylist-header-pinned` is set. Unpinned, both rows are
   transparent and sit in the page exactly as they always did — that class is what
   stopped a black band appearing above the page before any scrolling.

   WHY ::after AND NOT A BACKGROUND ON THE ROW

   Two problems the row's own `background` cannot solve:

     1. `.container` insets these rows 9px from each screen edge, so a background
        on the row leaves the cards visible sliding through the gutters.
     2. A divider drawn as a border sits inside that same inset, so it stops 9px
        short of both edges — and the spec is edge to edge.

   A 100vw `::after`, pinned behind the row's own content, solves both: it spans
   the full viewport, and the LAST 0.9px of it is the divider, painted with a
   hard-stop gradient rather than a border so the line is part of the same
   full-bleed box. The row keeps no background of its own, or it would cover the
   line everywhere except the gutters.

   ::after, not ::before: `#mylist-toolbar::before` is already the page's existing
   divider (13-e2ee-activity-post.css, every declaration !important) and taking it
   over is what made the dividers vanish in the first place.

   v16.151 — ONE FILL, BOTH SHELVES.

   The header half of this rule used to carry `:not(.viewing-other-user)`, so a
   shelf you were VIEWING pinned its category strip with no ground under it and
   poster art scrolled through GAMES · ANIME · MUSIC · MOVIES · TV while the
   status row below sat on solid black. The exclusion was not a design decision —
   35-shelf-banner.css was blanking this exact pseudo-element on viewed shelves
   (`content: none !important`), left over from a decorative ::after that no
   longer exists, and this selector had been narrowed to route around it rather
   than delete it. That kill rule is gone now, so the branch is gone with it and
   the two shelves share one fill.

   Nothing else needs a viewed-shelf branch: the toolbar half never had one, and
   the two hairlines are drawn unbranched in 100-shelf-header.css.
   -------------------------------------------------------------------------- */
body.shelfd-mylist-header-pinned.main-tab-mylist #mylist-view #mylist-header.mylist-section-card::after,
body.shelfd-mylist-header-pinned.main-tab-mylist #mylist-view #mylist-toolbar.toolbar::after {
  content: '' !important;
  display: block !important;
  position: absolute !important;
  /* -1px, not 0: each row's hairline is drawn ABOVE that row (100-shelf-header.css),
     i.e. outside this fill. Pinned, that strip is covered by neither row's fill, so
     the cards scrolled visibly behind a semi-transparent line. Starting the fill
     higher puts an opaque ground under the hairline without moving it. This is the
     default for the toolbar, whose midline is at -1px; the header overrides it
     below because its line has been lifted further. */
  top: -1px !important;
  bottom: 0 !important;
  left: 50% !important;
  width: 100vw !important;
  margin-left: -50vw !important;
  z-index: -1 !important;
  pointer-events: none !important;
  background: #0E0E0E !important;
}

/* v16.148: the category strip's own hairline sits --shelf-topline-lift above it,
   not 1px, so its fill has to reach that far up or the lift re-opens exactly the
   bleed the -1px above was added to close. Read from the same variable that
   positions the line (100-shelf-header.css) rather than restated, so the two
   cannot be changed apart. */
body.shelfd-mylist-header-pinned.main-tab-mylist #mylist-view #mylist-header.mylist-section-card::after {
  top: calc(-1 * var(--shelf-topline-lift, 1px)) !important;
}

/* v16.136 — ONE HEADER, ONE BOTTOM EDGE.

   Both rows used to draw their own divider, so a line ran between the category
   strip and the status row. That is what made the pinned chrome read as two
   stacked bars with a seam rather than one header — the seam WAS the "gap".
   With the 6px margin gone (12-pwa-header-continuity.css) the two fills are
   contiguous, so the only line that should exist is the one under the pair.

   The divider is a hard-stopped gradient rather than a border because it has to
   be part of the same full-bleed 100vw box; a border would sit inside the row's
   9px container inset and stop short of both screen edges. */
body.shelfd-mylist-header-pinned.main-tab-mylist #mylist-view #mylist-toolbar.toolbar::after {
  background: linear-gradient(
    to bottom,
    #0E0E0E calc(100% - 0.9px),
    rgba(196, 181, 253, 0.18) calc(100% - 0.9px)
  ) !important;
}

/* The existing divider above the toolbar (top: -10px) lands INSIDE the pinned
   header, which sits a layer above it — so once pinned it is covered and the
   header's own bottom line above takes over. Hidden rather than left to fight. */
body.shelfd-mylist-header-pinned.main-tab-mylist #mylist-view #mylist-toolbar.toolbar::before {
  opacity: 0 !important;
}

/* 5) The island strip above the pinned header. Without this the cards show in
      the safe-area band as they scroll past. `body::after` because body has no
      transform or containment, so `fixed` locks to the real viewport — and
      because `body::before` is globally disabled in file 17. */
body.shelfd-mylist-header-pinned.main-tab-mylist::after {
  content: '';
  display: block;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: max(var(--shelfd-safe-top, 0px), env(safe-area-inset-top, 0px));
  background: #0E0E0E;
  z-index: 50;
  pointer-events: none;
}

body.light-mode.shelfd-mylist-header-pinned.main-tab-mylist::after {
  background: #ffffff !important;
}
body.light-mode.shelfd-mylist-header-pinned.main-tab-mylist #mylist-view #mylist-header.mylist-section-card::after,
body.light-mode.shelfd-mylist-header-pinned.main-tab-mylist #mylist-view #mylist-toolbar.toolbar::after {
  background: #ffffff !important;
}
/* the pair's single bottom edge, light mode */
body.light-mode.shelfd-mylist-header-pinned.main-tab-mylist #mylist-view #mylist-toolbar.toolbar::after {
  background: linear-gradient(
    to bottom,
    #ffffff calc(100% - 0.9px),
    rgba(20, 18, 28, 0.14) calc(100% - 0.9px)
  ) !important;
}
