/* ── Shared background confetti ──────────────────────────────────────────
   Used alongside top-nav.css/left-sidebar.css by every employee-facing
   page. Sits behind everything -- including the top nav and every card --
   so it only ever reads in the gaps between cards; cards stay solid white.
   See src/shared/confetti-bg.ts for the generated markup. */

.hb-confetti-bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  /* The page's real content sits in a max-width:1296px column, centered
     once the viewport is wider than that -- not the full viewport this
     layer spans. Every piece's `left` (below) is placed as a fraction of
     this block, not of 100vw, so the field spreads across the content
     people actually look at instead of clustering in the empty margin
     outside it on wide screens. */
  --hb-confetti-gutter: max(0px, (100vw - 1296px) / 2);
  --hb-confetti-content-w: min(100vw, 1296px);
}

.hb-confetti-piece {
  position: absolute;
  border-radius: 50%;
  left: calc(var(--hb-confetti-gutter) + var(--hb-confetti-frac) * var(--hb-confetti-content-w));
  animation-name: hbConfettiFall;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}
.hb-confetti-ring {
  background: transparent !important;
}

/* On pages that also render the shared left sidebar (renderConfettiBg is
   called with { hasSidebar: true }), clip confetti out of the sidebar's
   nav text specifically -- not its whole column -- so a piece can still
   drift through the column's genuinely empty space (below its last link,
   between groups) without ever landing behind/next to the text itself,
   which sits directly on the page background rather than in a card.
   Scoped to the same 810px breakpoint left-sidebar.css hides the sidebar
   at (below that there's no sidebar text on screen to protect).

   --hb-confetti-sidebar-right/-safe-y are set by
   public/js/shared/confetti-sidebar.js, which measures the actual
   rendered .hb-sidebar-link elements (their vertical extent shifts while
   the sidebar's position:sticky settles during the initial scroll, and
   differs per page -- e.g. ScrappyPulse's 2-link sidebar vs. the hub's
   full 4-group one -- so this can't be a fixed value). The polygon clips
   away only the rectangle from the sidebar's left edge to its right edge,
   and from the top of the page down to the last nav item's bottom (plus a
   margin) -- everywhere else, including the rest of that column below the
   last link, stays visible. The --sidebar-safe-y default (100vh, i.e. the
   whole column) is what's in effect for the brief moment before that
   script's first measurement runs, so nothing can flash in behind real
   text before JS catches up. */
@media (min-width: 901px) {
  .hb-confetti-bg--with-sidebar {
    --hb-confetti-sidebar-right: calc(var(--hb-confetti-gutter) + 23.4px + 187.2px);
    --hb-confetti-sidebar-safe-y: 100vh;
    clip-path: polygon(
      var(--hb-confetti-sidebar-right) 0,
      100% 0,
      100% 100%,
      0 100%,
      0 var(--hb-confetti-sidebar-safe-y),
      var(--hb-confetti-sidebar-right) var(--hb-confetti-sidebar-safe-y)
    );
  }
}

/* ── Bare page-header text (title, subtitle, back-link) ───────────────────
   Same underlying problem as the sidebar block above, but for text that
   sits directly on the page background near the top of the main content
   column -- page title/description rows and "← Back to..."/"← Return
   to..." links -- rather than inside a card or a colored hero banner
   (cards and heroes already have their own opaque background, so confetti
   never shows through those).

   Unlike the sidebar, these elements don't need a JS-measured safe zone:
   they're simple, tightly-wrapping blocks whose height is just their own
   content, so giving them a flat background that exactly matches the page
   background (--hb-page-bg, from top-nav.css) is enough to block confetti
   from showing through -- and since the fill color matches the page
   exactly, it reads as no box at all.

   Scoped with the general sibling combinator so this only ever applies on
   pages that actually render this confetti layer (renderConfettiBg's
   output is always a sibling immediately before .hb-shell, give or take
   an impersonation banner) -- other pages that happen to reuse the same
   class names (e.g. admin pages using .sh-back-link/.page-title-row) are
   untouched. */
.hb-confetti-bg ~ .hb-shell .sh-back-link,
.hb-confetti-bg ~ .hb-shell .profile-org-return,
.hb-confetti-bg ~ .hb-shell .sp-page-title-row,
.hb-confetti-bg ~ .hb-shell .sp-page-body > .sp-section-sub,
.hb-confetti-bg ~ .hb-shell .aw-page-title-row,
.hb-confetti-bg ~ .hb-shell .page-title-row,
.hb-confetti-bg ~ .hb-shell .props-header,
.hb-confetti-bg ~ .hb-shell .props-breadcrumb {
  background: var(--hb-page-bg);
}

/* Gentle falling snow -- a slow, continuous downward drift with a side-to-
   side sway, not a bob in a fixed spot. Translates from 0 to 120vh (well
   past the bottom of the viewport, which .hb-confetti-bg clips via
   overflow:hidden) over the piece's full animation-duration, so at the
   loop point every piece is already off-screen and the instant reset back
   to translate(0,0) is invisible -- it reappears to "fall from the top"
   without an actual visible jump. Sway direction alternates via the
   per-piece --hb-confetti-sway custom property (set inline in
   confetti-bg.ts, sign flips at each step) while the vertical fall stays
   monotonic throughout. Per-piece duration/delay (also inline) are what
   keep every piece out of sync and falling at its own pace. */
@keyframes hbConfettiFall {
  0% { transform: translate(0, 0); }
  20% { transform: translate(var(--hb-confetti-sway), 24vh); }
  40% { transform: translate(calc(var(--hb-confetti-sway) * -1), 48vh); }
  60% { transform: translate(var(--hb-confetti-sway), 72vh); }
  80% { transform: translate(calc(var(--hb-confetti-sway) * -1), 96vh); }
  100% { transform: translate(0, 120vh); }
}

@media (prefers-reduced-motion: reduce) {
  .hb-confetti-piece {
    animation: none;
  }
}

/* Wraps the top nav/sidebar/main content on every page that renders the
   confetti background -- its z-index draws real page content above the
   fixed, z-index:0 confetti layer. */
.hb-shell {
  position: relative;
  z-index: 1;
}
