/*
 * Page-with-sidebar — layout primitive that pairs a sidebar with a
 * main column. Sticky sidebar on desktop; off-canvas drawer + top bar
 * on mobile.
 *
 * Lives in its own file because it is a layout primitive, not a
 * sidebar style. The sidebar component (`sidebar.css`) and this
 * layout shell are always used together but are separate concerns —
 * the sidebar would happily render outside this shell, and the shell
 * would happily host a future non-sidebar nav surface.
 *
 * The desktop sidebar paints `slate-50` so the column recesses against
 * the white main column (no right border — the recess carries the
 * divide). The mobile pattern hides the column, shows a top bar, and
 * slides the column in from the left on demand via the
 * `sidebar_drawer_controller` Stimulus controller.
 */

@layer components {
  .page-with-sidebar {
    --page-with-sidebar-width: 17rem;
    --page-with-sidebar-mobile-topbar-height: var(--space-12);

    /* Hairline divider under the mobile top bar — same 1px the rest of
       the chrome uses for structural dividers. No system border-width
       scale yet, so it stays component-local (the same pattern other
       components use for their borders). */
    --page-with-sidebar-border-size: 1px;

    /* Scrim overlay colour when the mobile drawer is open. Derived
       from black so it's neutral against any main-column content; the
       alpha is the drop. Literal lives here in the token declaration
       — never in a rule body — per the design-system contract. */
    --page-with-sidebar-scrim-color: oklch(0% 0 0 / 35%);

    display: grid;
    grid-template-columns: var(--page-with-sidebar-width) minmax(0, 1fr);
    min-height: 100vh;
  }

  .page-with-sidebar > .sidebar {
    position: sticky;
    top: 0;
    align-self: start;
    height: 100vh;
    overflow-y: auto;
    background: var(--color-slate-50);
  }

  .page-with-sidebar__main {
    min-width: 0;
  }

  /* Mobile top bar — sibling of the sidebar inside .page-with-sidebar.
     Hidden by default (desktop); the mobile breakpoint shows it and
     anchors it to the top of the main column. Slate-50 to match the
     recessed sidebar so the nav surface reads as continuous between
     the desktop column and the mobile bar. */
  .page-with-sidebar__topbar {
    display: none;
    align-items: center;
    gap: var(--space-3);
    height: var(--page-with-sidebar-mobile-topbar-height);
    padding: 0 var(--space-3);
    background: var(--color-slate-50);
    border-bottom: var(--page-with-sidebar-border-size) solid var(--color-border);
    z-index: var(--z-nav);
  }

  .page-with-sidebar__topbar-trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--space-8);
    height: var(--space-8);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-slate-800);
    border: 0;
    cursor: pointer;
    padding: 0;
    transition: background-color var(--duration-base) var(--ease-out);
  }

  .page-with-sidebar__topbar-trigger:hover,
  .page-with-sidebar__topbar-trigger:focus-visible {
    background: var(--color-white);
  }

  .page-with-sidebar__topbar-trigger:focus-visible {
    outline: var(--focus-ring-size) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  .page-with-sidebar__topbar-trigger-icon {
    width: var(--space-5);
    height: var(--space-5);
  }

  /* Explicit `display: none` for the hidden icon. The UA stylesheet's
   * `[hidden] { display: none; }` rule competes with the inline-flex
   * layout on the parent button in some browser versions and the
   * hidden icon still flexes into the row — force it to collapse
   * cleanly. */
  .page-with-sidebar__topbar-trigger-icon[hidden] {
    display: none;
  }

  .page-with-sidebar__topbar-title {
    font-size: var(--text-13);
    font-weight: 600;
    color: var(--color-slate-800);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* Scrim — covers the main column area when the drawer is open. Sits
     below the top bar so the bar's title remains visible. Hidden by
     default; the drawer controller toggles the `hidden` attribute. */
  .page-with-sidebar__scrim {
    display: none;
  }

  /* Mobile — 900px and below. Single column; the sidebar becomes a
     fixed off-canvas drawer that slides in from the left. The top bar
     hosts the hamburger trigger. Literal media-query breakpoint is
     accepted — no system breakpoint scale exists yet (flagged in the
     slice report; lift to a token when a second consumer appears). */
  @media (max-width: 900px) {
    .page-with-sidebar {
      grid-template-columns: 1fr;
    }

    .page-with-sidebar__topbar {
      display: flex;
    }

    .page-with-sidebar > .sidebar {
      position: fixed;
      inset: var(--page-with-sidebar-mobile-topbar-height) auto 0 0;
      width: min(var(--page-with-sidebar-width), 86%);
      /* Explicit full-height drawer below the top bar. `100dvh` (dynamic
       * viewport height) respects mobile browser chrome that grows /
       * shrinks as the user scrolls; `height: auto` would let the
       * drawer collapse to content height and leave dead space below. */
      height: calc(100dvh - var(--page-with-sidebar-mobile-topbar-height));
      transform: translateX(-100%);
      transition: transform var(--duration-base) var(--ease-out);
      z-index: var(--z-nav);
    }

    .page-with-sidebar[data-drawer-open] > .sidebar {
      transform: translateX(0);
    }

    .page-with-sidebar__scrim {
      display: block;
      position: fixed;
      inset: var(--page-with-sidebar-mobile-topbar-height) 0 0 0;
      background: var(--page-with-sidebar-scrim-color);
      z-index: var(--z-base);
      opacity: 0;
      pointer-events: none;
      transition: opacity var(--duration-base) var(--ease-out);
    }

    .page-with-sidebar[data-drawer-open] .page-with-sidebar__scrim {
      opacity: 1;
      pointer-events: auto;
    }

    /* Company-switcher mobile rules (panel sizing, back-row, heading
       hide) live in `sidebar-company-switcher.css` so they sit in the
       same file as the desktop defaults. Otherwise alphabetic file
       load order silently overrides them — the desktop rules in the
       later file win the cascade tie. */
  }
}
