/* ══════════════════════════════════════════════════════════════════
   THE PAGE SHELL'S FRAME — site/page.js.

   Generalised out of stage.css §6.19, which did this once for the
   Pokédex. Everything here keys on `.pg` (the surface) and
   `html[data-page]` (a page is up), so one block dresses the Pokédex,
   the leaderboard, the clans and the profile.

   It owns the FRAME only. The surfaces keep their own paint —
   profile.css, leaderboard.css and clan.css are untouched by this file —
   and what is removed is the modal chrome that makes a sheet a pop-up:
   the scrim, the centring, the rounded keyline plate, the pop-in.
   ══════════════════════════════════════════════════════════════════ */

/* ---- 1. the surface fills the frame ----------------------------- */
/* Pinned to the rail's right edge and the header's / the phone bars'
   real boxes (page.js place()). The box runs from the TOP of the window,
   behind the header, so the header cluster floats over the page the way
   it floats over the Pokédex — .fit is a fixed z-auto box and this sits
   at z 0 immediately before it. */
html[data-layout="stage"] .pg{
  position:fixed;
  /* `inset` first, because .ov sets inset:0 and the longhands below must
     win however the two files end up ordered */
  inset:auto;
  left:var(--pg-left,0px);top:var(--pg-top,0px);right:0;bottom:var(--pg-bottom,0px);
  z-index:0;display:block;padding:0;box-sizing:border-box;
  background:none;-webkit-backdrop-filter:none;backdrop-filter:none;
  /* AND NO FADE (Luke, 10 Sep: "anytime you click on it or off it ... it just
     flashes up with the pop-up for a split second. Same when you go into my
     profile"). .ov carries transition:opacity .22s,visibility .22s, and
     page.js strips .pg the moment it sets data-open="0" — so for the whole
     fade-out the element was a bare .ov again and painted as a MODAL: scrim
     rgba(11,15,24,.55) and backdrop-filter blur(6px), at full opacity.
     Measured before this: 14 frames of pop-up on a page-to-page change, 28 on
     a close. A page is a navigation, not a sheet; it has no business fading,
     and the Pokédex never did. */
  transition:none}

/* the plate stops being a plate: no keyline, no radius, no drop, no
   pop-in — it is the page's ground now and it runs to the edges.
   `background:none` is load-bearing and was MISSING from the first version of
   this rule, which is the whole of Luke's "on the Pokédex page the backgrounds
   don't meet up" (10 Sep). stage.css §6.19 had it; generalising the rule
   dropped it. .dexmodal__panel paints bg-plate.png itself, and the panel's box
   starts at the rail's right edge — so its `cover` crop is computed on a
   1263x982 box while the page's own .bg computes it on 1512x982. Two different
   crops of the same picture, meeting at a hard vertical line at x=249.
   The geometry harness could not have caught it: it compares position, not
   paint. */
html[data-layout="stage"] .pg .pg__panel{
  width:100%;max-width:none;height:100%;max-height:none;
  border:0;border-radius:0;box-shadow:none;transform:none;zoom:1;
  background:none}
/* AND NO GRIP. stage.css:1693 gives every .ov__panel a phone sheet's grab
   handle — a 46x5 bar at top:9px — and it was the one piece of the pop-up
   dress this rule never took off. On a page there is nothing to pull down,
   and once the bars slide away on scroll (§4b) the handle is the ONLY thing
   left on the screen: the grey stub at the top of Luke's 16 Sep screenshot,
   "the header doesnt vanis.... just the logo on the header it is shit". */
html[data-layout="stage"] .pg .pg__panel::before{display:none}

/* ---- 1b. THE LOBBY BEHIND A PAGE TAKES NO CLICKS ----------------------
   Luke, 14 Sep 2026: "not letting me click boards/chat in my clan". It was not the
   clan page: the lobby's pack ring row floats over every page and eats the click.
   MEASURED on demo.blockrips.com (14 Sep), clan page open, header and rail excluded
   because those two are meant to float over a page — the ONLY thing that hit-tests
   on top of the page is `#slCats .sl-cat`:
     1512x982  the centre pack's box is x 685-827 y 22-161 -> it owns the POKEDEX tab
               (tabs y 123-162); at 1280x800 it owns MEMBERS; at Luke's window BOARDS/CHAT
     paint     a screenshot of that band with the row visible and with it hidden is
               PIXEL-IDENTICAL: the row draws nothing over a page, it only steals
   Why it reaches: .pg is z-index:0 (rule above) while .sl-cat carries z-index:40/50
   inside a z-auto ancestor, so it is promoted past the page in the root stacking
   context. stage.css:2080 already made `.sl-cats` click-through for the rank pill's
   sake and re-enabled `.sl-cat` — that pair is right in the lobby and wrong here.
   Scoped to `html[data-page]`, which page.js sets for a page and nothing else, so
   the lobby behaves exactly as before the moment the page closes. The rail is NOT
   inside #stage (it hangs off div.fit), so navigation is untouched.
   !important IS LOAD-BEARING: stage.js:548 writes `e.style.pointerEvents` on every
   ring paint (it fades the far packs out and takes their clicks with them), and an
   inline style beats any rule that is only more specific. Measured: without it the
   cat still computed `auto` on the clan page and still ate the tab. */
html[data-layout="stage"][data-page] #slCats,
html[data-layout="stage"][data-page] #slCats .sl-cat{pointer-events:none!important}

/* anything the shell was told to drop (a modal-only bar or scrim) */
html[data-layout="stage"] .pg .pg__gone{display:none!important}

/* ---- 2a. .pg--panel: a fixed head, a scrolling body -------------- */
/* The leaderboard, the clans and the profile put their title, tabs and
   BACK/X above the scroll box, so the frame's top inset belongs to the
   PANEL: the head clears the site header and stays put while the body
   moves under it. */
html[data-layout="stage"] .pg--panel .pg__panel{padding-top:var(--pg-pad,120px)}
html[data-layout="stage"] .pg--panel .pg__body{scrollbar-width:thin;scrollbar-color:var(--acc) transparent}

/* THE SHEET'S OWN 64px INSET IS A POP-UP RULE, AND ON A PAGE IT DOUBLES UP.
   Luke, 10 Sep: "there's too much space between the title and the header."
   Measured before, header's bottom edge to the first ink, at 1147x655 and
   1512x982: Pokédex 58 / 58 — the one he approved and the reference — the
   leaderboard 78 / 87, the profile 122 / 122, the clans 127 / 127.
   (HANDOFF-178 §3.2 records the profile as 240; measured on the live build it
   is 122 at both sizes, so that figure is wrong and 122 is what was fixed.)

   The frame already holds a page's content clear of the header: --pg-pad is
   the header's bottom plus 58, and .pg--panel spends it as padding on the
   PANEL. Every one of these surfaces then adds the SHEET's version of the same
   idea on top of it — stage.css:2463 gives every .ov__body 64px of top padding
   on the desktop, and .ov--clan re-implements that same 64 as a margin on its
   first child (clan.css:24, because a sticky `top` inside a padded box lands at
   padding+top). Two insets, one gap, twice the size.

   So each page gives up its sheet inset and keeps the frame's. Scoped one
   surface at a time rather than blanketed over .pg--panel .pg__body: the
   leaderboard's 24px is NOT the same rule — it is the ramp its rows fade
   through as they slide under the tab strips (leaderboard.css:196), and it
   stays. Its own share of the gap was the <header>, and that is gone. */
html[data-layout="stage"] .pg--panel.ov--profile .pg__body{padding-top:0}
html[data-layout="stage"] .pg--panel.ov--clan{--cl-top:0px}
/* and the leaderboard's board tabs are its first row now that its <header> is
   gone. stage.css:1500 gives every .otabs 14px of top margin — that is the gap
   BETWEEN two strips (#lbPeriods keeps it), not a page's top inset. */
html[data-layout="stage"] .pg--panel #lbBoards{margin-top:0}
/* and the clans' title row stops reserving a gutter for buttons that are not
   beside it. .cl-head pads 108px left / 60px right so its <h2> sits BETWEEN
   BACK and the X (clan.css:45) — true in a centred modal, where both are pinned
   to the panel's own top corners. On a page they are not: the X is gone and
   BACK is up in the header's band, so the padding was holding "Clans" 108px in
   from the panel's edge with nothing at all to its left. */
html[data-layout="stage"] .pg--panel .cl-head{padding-left:0;padding-right:0}

/* BACK BELONGS TO THE PAGE, NOT TO THE WINDOW.
   profile.css:22 and clan.css:35 pin it to `top:12px` of the panel, which was
   the top of a centred modal. A page's panel starts at the window's own top —
   behind the header — so at 12px it landed ON the header cluster: measured at
   1147x655, the box overlapped the account avatar. Padding cannot move it (it
   is absolutely positioned, so it ignores it), so it is re-pinned to the band
   the frame already leaves clear between the header's bottom edge (--pg-hdr)
   and where the content rests (--pg-pad) — 58px on both desktop windows, 44px
   on the phone.

   NO X ON A PAGE (Luke, 10 Sep: "surely you don't need the X at the top or the
   back button. You only need the back button if you go into somewhere that
   isn't one of the pages on the left"). The three rules that used to place and
   resize .ov__x inside a .pg are gone with the buttons themselves —
   leaderboard.js and clan.js and profile.js no longer build one, and the
   Pokédex never had one. */
html[data-layout="stage"] .pg--panel .pf-nav,
html[data-layout="stage"] .pg--panel .cl-nav{top:calc(var(--pg-hdr,62px) + 7px)}

/* ---- 2b. .pg--scroll: everything scrolls under the header -------- */
/* The Pokédex. Luke, 6 Sep 23:10 and 7 Sep 01:50: the content rests at
   --pg-pad and fades out as it climbs under the header — the 14px
   feather ("option C") rather than the 58px ramp, which read as a smear
   on a big dark plate. The mask is fully clear through the header band
   (--pg-hdr) so nothing shows behind it. */
html[data-layout="stage"] .pg--scroll .pg__body{
  padding:var(--pg-pad,120px) 26px 96px 14px;
  -webkit-mask-image:linear-gradient(180deg,transparent 0,transparent var(--pg-hdr,62px),rgba(0,0,0,.5) calc(var(--pg-hdr,62px) + 7px),#000 calc(var(--pg-hdr,62px) + 14px));
  mask-image:linear-gradient(180deg,transparent 0,transparent var(--pg-hdr,62px),rgba(0,0,0,.5) calc(var(--pg-hdr,62px) + 7px),#000 calc(var(--pg-hdr,62px) + 14px));
  scrollbar-width:thin;scrollbar-color:var(--acc) transparent}

/* the scroll bar is on brand on every page (Luke, 6 Sep): a pink thumb in
   a key ring on no track */
html[data-layout="stage"] .pg .pg__body::-webkit-scrollbar{width:12px}
html[data-layout="stage"] .pg .pg__body::-webkit-scrollbar-track{background:transparent}
html[data-layout="stage"] .pg .pg__body::-webkit-scrollbar-thumb{
  background:linear-gradient(180deg,var(--acc-hi),var(--acc) 48%,var(--acc-lo));border:2px solid var(--key);border-radius:8px;
  box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.55)}
html[data-layout="stage"] .pg .pg__body::-webkit-scrollbar-thumb:hover{background:var(--acc-hi)}

/* ---- 3. the lobby steps back while a page is up ------------------ */
/* Not display:none — stage.js keeps measuring the ring and the packs, and
   it writes visibility inline on every slot, which beats an ancestor's
   hidden. .shell fades instead of hiding for the same reason. */
html[data-layout="stage"][data-page] .shell{opacity:0}
html[data-layout="stage"][data-page] #stageLayer,
html[data-layout="stage"][data-page] .sl-crate,
html[data-layout="stage"][data-page] .mdock{visibility:hidden}
html[data-layout="stage"][data-page] .strip{display:none}
html[data-layout="stage"][data-page] .sl-bg{opacity:0}
html[data-layout="stage"][data-page] .fit{pointer-events:none}
/* a rip's own furniture is part of the lobby, not of a page */
html[data-layout="stage"][data-page] .postrip,
html[data-layout="stage"][data-page] .poolrail,
html[data-layout="stage"][data-page] .postrip__share,
html[data-layout="stage"][data-page] .postrip__slabhit,
html[data-layout="stage"][data-page] .sl-dupnote{visibility:hidden}
/* .fit stops taking pointer events (above) and hands them back to the
   pieces that float over the page */
html[data-layout="stage"][data-page] .sl-side > *,
html[data-layout="stage"][data-page] .header__right,
html[data-layout="stage"][data-page] .sl-rank,
html[data-layout="stage"][data-page] .mhead{pointer-events:auto}

/* ---- 4. the phone ------------------------------------------------ */
@media (max-width:1023px){
  /* the panel is already full-screen on the phone (style.css:1091), so the
     page change here is the frame, not the plate. Both paddings that
     assumed a modal are dropped: --pg-bottom already stops the box above
     the bar, and --pg-pad already clears .mhead. */
  html[data-layout="stage"] .pg--panel .pg__panel{padding-bottom:0}
  html[data-layout="stage"] .pg--panel .pg__panel > .ov__head{padding-top:12px}
  /* the phone's clear band under .mhead is 44px, not 58 */
  html[data-layout="stage"] .pg--panel .pf-nav,
  html[data-layout="stage"] .pg--panel .cl-nav{top:calc(var(--pg-hdr,52px) + 3px)}
  html[data-layout="stage"] .pg--panel .pf-nav,
  html[data-layout="stage"] .pg--panel .cl-nav{height:38px}
  html[data-layout="stage"] .pg--scroll .pg__body{padding:var(--pg-pad,100px) 10px 32px}

  /* 4b. THE BARS GET OUT OF THE WAY WHILE THE PAGE SCROLLS (Mike, 7 Sep
     20:26; Luke 22:24 "yee ill add this"). page.js watches the page's
     scroll box and flags data-page-chrome; both bars slide out over .28s
     and the page's bottom edge follows the dock down so nothing is left
     stranded above a bar that has gone. */
  html[data-layout="stage"][data-page] .mhead,
  html[data-layout="stage"][data-page] .mnav{transition:transform .28s cubic-bezier(.2,.8,.3,1)}
  html[data-layout="stage"][data-page][data-page-chrome="hidden"] .mhead{transform:translateY(-110%)}
  html[data-layout="stage"][data-page][data-page-chrome="hidden"] .mnav{transform:translateY(calc(100% + 28px))}
  html[data-layout="stage"][data-page][data-page-chrome="hidden"] .pg{bottom:0!important}
  /* the header band of the fade goes with the header (Luke, 8 Sep 00:50, off
     the crop: the top of the grid still dissolved under where the header had
     been). --pg-hdr is written inline by place(), so the whole rule is
     replaced here rather than the variable changed: a 14px feather at the
     screen's own edge, which is the size he picked. */
  html[data-layout="stage"][data-page][data-page-chrome="hidden"] .pg--scroll .pg__body{
    -webkit-mask-image:linear-gradient(180deg,transparent 0,rgba(0,0,0,.5) 7px,#000 14px);
    mask-image:linear-gradient(180deg,transparent 0,rgba(0,0,0,.5) 7px,#000 14px)}

  /* ---- 4c. AND A .pg--panel PAGE DOES EXACTLY THE SAME --------------
     Luke, 16 Sep, of the clans page: "when i scroll down the header doesnt
     vanis.... just the logo on the header it is shit", then "the header
     disapearing needs to work the exact same way it works on the pokedex
     page".
     MEASURED, 390x844, both pages scrolled with the bars away:
       Pokédex   .pg__body box 0..844 — the grid runs to the screen's top edge
                 and dissolves into it over 14px
       clans     .pg__body box 96..844 — the list is cut dead at y96 and above
                 it sits 96px of bare background where the header used to be,
                 with the sheet grip (§1) floating in the middle of it
     The 96 is --pg-pad, and the whole difference is WHERE IT IS SPENT: the
     Pokédex gives it to the scroll box as padding, so the box is the screen
     and its content climbs to the edge; §2a gives it to the PANEL, so the
     box starts below the header and can never paint above it. So on the
     phone the panel hands it over, and every page gets the Pokédex's own
     mask: clear through the header band while the bars are home, a 14px
     feather at the screen's edge once they have gone.
     NOTHING INSIDE MOVES. The content box top is --pg-pad either way, and a
     sticky offset is measured from the scroll container's CONTENT box, not
     its padding box — checked in both engines, not assumed (a sticky top:60
     inside a 96-padded scroller: Chromium 156, WebKit 156). So .cl-tabs, the
     leaderboard's podium and the chat composer all pin exactly where they
     pinned before. */
  html[data-layout="stage"] .pg--panel .pg__panel{padding-top:0}
  html[data-layout="stage"] .pg--panel .pg__body{
    padding-top:var(--pg-pad,96px);
    --pg-fade-top:var(--pg-hdr,52px);
    --pg-mask:linear-gradient(180deg,transparent 0,transparent var(--pg-fade-top),
      rgba(0,0,0,.5) calc(var(--pg-fade-top) + 7px),#000 calc(var(--pg-fade-top) + 14px),
      #000 calc(100% - var(--pg-fade-bot,0px)),transparent 100%);
    -webkit-mask-image:var(--pg-mask);mask-image:var(--pg-mask)}
  html[data-layout="stage"][data-page][data-page-chrome="hidden"] .pg--panel .pg__body{--pg-fade-top:0px}

  /* EACH SURFACE KEEPS ITS OWN BOTTOM FADE AND GIVES UP ITS TOP RAMP.
     The three scroll-linked ramps — --cl-fade (clan.css:48), --pf-fade
     (profile.css:43), --lb-fade (leaderboard.css:314) — are all the same
     answer to the same thing: a body whose box top WAS its content top, so a
     static ramp dimmed the first row before anything had moved (Luke, 11 Sep
     07:11: "it's faded before I've even started scrolling"). With the inset
     on the body that is no longer true — the content rests at 96, well past
     the feather — so the frame takes the top back and the ramps, which would
     now smear at the screen's edge instead, stand down. Their bottoms are
     their own and stay: 34px on the clans, 40 on the other two.
     These rules only have to exist because each surface names itself in its
     own file and so outranks the generic one above. */
  html[data-layout="stage"] .pg--panel.ov--clan .pg__body{
    --pg-fade-bot:34px;padding-top:var(--pg-pad,96px);
    -webkit-mask-image:var(--pg-mask);mask-image:var(--pg-mask)}
  html[data-layout="stage"] .pg--panel.ov--clan[data-view="discover"] .pg__body,
  html[data-layout="stage"] .pg--panel.ov--clan[data-view="clan"] .pg__body{
    -webkit-mask-image:var(--pg-mask);mask-image:var(--pg-mask)}
  /* THE LEADERBOARD'S INSET IS ITS OWN AND IS NOT --pg-pad. It sets the panel
     to --pg-hdr + 16 rather than the frame's + 44, because Luke asked for the
     space over the tab strip to go (11 Sep: "there's loads of space between
     the actual header of the website ... and the tabs ... get rid of that
     space"); its body then adds the 10px the podium pins against
     (leaderboard.css:298 and :313). So the sum is what moves — hdr + 26 —
     not --pg-pad, or the strip would drop 28px down the page. */
  html[data-layout="stage"][data-page] .pg--panel.ov--lb .pg__panel{padding-top:0}
  html[data-layout="stage"] .pg--panel.ov--lb .pg__body{
    --pg-fade-bot:40px;padding-top:calc(var(--pg-hdr,52px) + 26px);
    -webkit-mask-image:var(--pg-mask);mask-image:var(--pg-mask)}
  html[data-layout="stage"][data-page] .pg--panel.ov--profile .pg__body{
    --pg-fade-bot:40px;padding-top:var(--pg-pad,96px);
    -webkit-mask-image:var(--pg-mask);mask-image:var(--pg-mask)}
}
