/* ============================================================
   KEEYNET — sticky shell
   ------------------------------------------------------------
   The top header and the left rail hold their place while the
   middle column scrolls.

   WHY IT WAS NOT WORKING

   Two separate causes, neither of them a missing rule.

   1. app.css argues with itself about the header.

        app.css:47     position: sticky
        app.css:3975   position: relative
        app.css:13635  position: sticky !important
        app.css:13780  position: relative !important

      Two !important declarations at the same specificity, so
      the later one wins and the header computed to relative.
      The intent was always sticky; the file just overruled
      itself twice on the way down.

   2. Sticky needs a scrolling ancestor, and both candidates
      had been turned into scroll containers that never scroll.

        body                      overflow-x: hidden
        #dashboard-view.dashboard overflow: hidden !important

      An element with overflow other than visible becomes the
      scroll container for its sticky descendants. Neither of
      these ever scrolls -- the document does -- so the rail
      and the header were sticking to a box that never moved,
      which looks exactly like not sticking at all.

   THE FIX

   overflow: clip clips exactly like hidden but does NOT create
   a scroll container, so the two rules above keep doing their
   real job (stopping sideways overflow) and stop breaking
   position: sticky. Nothing is restructured and no element
   leaves the flow, so the grid columns, the device drawer and
   the dialogs all behave as before.

   To remove: delete the <link> tag. Nothing else references it.
   ============================================================ */


/* ---------- 1. stop clipping ancestors from scrolling -------- */

/*
 * Still clips horizontally; no longer a scroll container.
 * Supported everywhere current (Chrome 90+, Firefox 81+,
 * Safari 16+). An older browser ignores the declaration and
 * keeps the previous behaviour rather than breaking.
 */
body {
  overflow-x: clip;
}

#dashboard-view.dashboard {
  overflow: clip !important;
}


/* ---------- 2. the header ------------------------------------ */

.site-header {
  position: sticky !important;
  top: 0 !important;
  /*
   * Above the rail, which also sticks now, and above the page
   * content. Below the device drawer's scrim, which sits at
   * 1000 in device-drawer-r1.css.
   */
  z-index: 60 !important;
}

/*
 * The header needs a floor now that content passes underneath.
 *
 * --header-bg is deliberately translucent in every theme
 * (rgba(242,247,244,.88) in Green, .96 in Black) because the
 * header used to scroll away, so nothing was ever behind it.
 * Pinned, that 12% let whole device rows read through the bar.
 *
 * A blurred translucent header would have been the nicer
 * answer, but backdrop-filter computes to none here -- so the
 * design depends on a filter that is not being applied, and
 * "mostly opaque with no blur" is just unreadable.
 *
 * So the theme's tint is painted as an image over an opaque
 * background-color. The bar keeps exactly the colour it was
 * designed to have, with no alpha left for content to show
 * through, and no reliance on a filter.
 */
.site-header {
  background-color: var(--surface, #fff) !important;
  background-image:
    linear-gradient(
      var(--header-bg, transparent),
      var(--header-bg, transparent)
    ) !important;
  border-bottom: 1px solid var(--line, #D5E2D9);
}

/*
 * The rail is pinned too, and the content column scrolls
 * behind its right edge, so it needs the same treatment.
 */
#dashboard-view .sidebar {
  background-color: var(--surface, #fff);
}


/* ---------- 3. the left rail --------------------------------- */

/*
 * align-self must leave "stretch". A stretched grid item is
 * already as tall as its row, so a sticky one has nowhere to
 * travel and never appears to stick.
 *
 * The rail is taller than the viewport on a short window, so it
 * gets its own scrollbar rather than being cut off, and
 * overscroll-behavior keeps that scroll from chaining into the
 * page when it reaches the end.
 */
/*
 * Pinning the rail applies at every width: below 900px the
 * portal turns it into a horizontal nav strip, and a pinned
 * strip under a pinned header is exactly right there too.
 */
#dashboard-view .sidebar {
  position: sticky !important;
  top: var(--kc-header-h, 60px) !important;
  z-index: 30;
}

/*
 * The column treatment, only where it IS a column. 900px is
 * where this codebase already switches the layout
 * (chrome-polish.css uses min-width: 901px for the same
 * reason), so the two agree rather than nearly agreeing.
 *
 * min-height fills the column when the nav is short -- without
 * it the rail's background stopped at the last nav item and the
 * page canvas showed through below, which reads as the rail
 * having fallen short rather than as a design. max-height plus
 * its own scrollbar keeps a long nav reachable on a short
 * window instead of being cut off.
 */
@media (min-width: 901px) {
  #dashboard-view .sidebar {
    align-self: start !important;
    /*
     * !important is not decoration here. app.css:5296
     * carries
     *
     *   #dashboard-view > .sidebar {
     *     height: auto !important;
     *     min-height: 0 !important;
     *     max-height: none !important;
     *   }
     *
     * which is the same specificity as this rule, so a plain
     * declaration loses to it however late it is loaded. The
     * rail stayed at its content height -- 456px of nav in an
     * 860px column -- and the page canvas showed through
     * underneath. In Black the rail and the canvas are both
     * dark so the join is invisible; in Green the white rail
     * against the dotted grey makes it obvious. Same bug, one
     * theme hid it.
     */
    min-height: calc(100dvh - var(--kc-header-h, 60px)) !important;
    max-height: calc(100dvh - var(--kc-header-h, 60px)) !important;
    height: auto !important;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

/* A quieter scrollbar; the rail is chrome, not content. */
#dashboard-view .sidebar {
  scrollbar-width: thin;
  scrollbar-color: var(--line, #D5E2D9) transparent;
}

#dashboard-view .sidebar::-webkit-scrollbar { width: 8px; }
#dashboard-view .sidebar::-webkit-scrollbar-thumb {
  border: 2px solid transparent;
  border-radius: 99px;
  background-clip: content-box;
  background-color: var(--line, #D5E2D9);
}


/* ---------- 4. anchors land below the header ----------------- */

/*
 * The page navigates by hash. Without this an anchored section
 * scrolls to the top of the viewport and the header covers its
 * heading.
 */
#dashboard-view .page-view,
#dashboard-view [id] {
  scroll-margin-top: calc(var(--kc-header-h, 60px) + 12px);
}


/* ---------- 5. short windows --------------------------------- */

/*
 * Under about 560px of height a sticky header and a sticky rail
 * leave almost nothing for the content. Both release and the
 * page scrolls normally, which is the better trade on a laptop
 * with a browser console open or a phone in landscape.
 */
@media (max-height: 560px) {
  .site-header { position: relative !important; }
  #dashboard-view .sidebar {
    position: static !important;
    max-height: none;
    overflow-y: visible;
  }
}

/*
 * The device drawer already locks the page behind its scrim.
 * The rail's own scrollbar would still react to the wheel, so
 * it is pinned while the drawer is open.
 */
body.kd-drawer-open #dashboard-view .sidebar {
  overflow-y: hidden;
}
