/* ----------------------------------------------------------------------- */
/* Sidebar shell                                                            */
/* ----------------------------------------------------------------------- */
/* Left-rail nav for the signed-in surface. Replaces the earlier top-bar
   layout once the project crossed ~10 admin items and started growing
   sub-apps (Compliance / Support / Admin today; /sales tomorrow).
   Sub-apps each get their own group so adding a fourth doesn't crowd
   anything. Brand at the top, user widget pinned at the bottom; nav
   sits in the middle and scrolls independently of the content pane. */

/* Compound `.site.site--sidebar` — TWO classes — so this rule's
   specificity (0,0,2,0) beats `.site`'s flex-column rule (0,0,1,0)
   in site.css. Necessary because Propshaft's stylesheet_link_tag
   `data-turbo-track="reload"` emits a separate <link> per CSS file
   in alphabetical order, which puts sidebar.css BEFORE site.css in
   the document and reverses my intended @import-order cascade.

   The sidebar width is a CSS variable so the collapsed-state rule
   only has to redefine the variable, not re-declare the full grid
   template. Width transitions are animated for a 200ms slide
   feel on toggle. */
.site.site--sidebar {
  --sidebar-width: 16rem;
  /* Tightened from 2.5rem → 2.25rem. With the typical sub-app having
     5–7 items, the previous row height pushed the user widget below
     the fold on a 13" laptop. 2.25rem keeps the cluster legible while
     reclaiming ~70px of vertical space across the nav. */
  --sidebar-row-height: 2.25rem;
  --sidebar-icon-size: 1.4rem;
  display: grid;
  grid-template-columns: var(--sidebar-width) 1fr;
  min-height: 100vh;
  transition: grid-template-columns 200ms ease;
}
.site.site--sidebar.sidebar--collapsed {
  --sidebar-width: 4.75rem;
}

.sidebar {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  z-index: 10;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border-right: 1px solid var(--rule);
  padding: var(--gap-5) var(--gap-4);
  font-family: var(--sans);
  font-size: 0.92rem;
  /* Center column for the rail */
  min-width: 0;
}

/* Brand + toggle button share the top row of the sidebar. When the
   sidebar collapses, the brand label hides and the toggle button
   takes the whole row (still right-aligned via flex). */
.sidebar__top {
  display: flex;
  align-items: center;
  gap: var(--gap-2);
  margin-bottom: var(--gap-5);
  min-width: 0;
}
.sidebar__brand {
  flex: 1 1 auto;
  font-family: var(--serif);
  font-weight: 700;
  font-size: 1.2rem;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
  padding: 0 var(--gap-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar__brand:hover { color: var(--accent); }

.sidebar__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 1.85rem;
  height: 1.85rem;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--ink-muted);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.sidebar__toggle:hover { background: rgba(28, 27, 24, 0.06); color: var(--ink); }
.sidebar__toggle svg { width: 1.05rem; height: 1.05rem; }

/* Show "collapse" chevron when expanded, "expand" chevron when
   collapsed. Hiding via display:none keeps the SR-only label clean. */
.sidebar__toggle-icon--expand { display: none; }
.sidebar--collapsed .sidebar__toggle-icon--collapse { display: none; }
.sidebar--collapsed .sidebar__toggle-icon--expand { display: inline-flex; }

.sidebar__nav {
  flex: 1 1 auto;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding-inline-end: 0.65rem;
  scrollbar-gutter: stable;
  /* No `gap` on the nav itself — `gap` would orphan the top-level
     Dashboard link with ~24px of empty space below it, while the
     in-section items sit in tight clusters. We want Dashboard to
     read as just-another-link, so spacing goes on the sections
     instead (see below). */

  /* Thin custom scrollbar so the nav doesn't lose 15px of width to a
     chunky default. Firefox honors scrollbar-width / -color; WebKit
     uses the pseudo-element rules below. */
  scrollbar-width: thin;
  scrollbar-color: rgba(28, 27, 24, 0.2) transparent;
}
.sidebar__nav::-webkit-scrollbar             { width: 6px; }
.sidebar__nav::-webkit-scrollbar-track       { background: transparent; }
.sidebar__nav::-webkit-scrollbar-thumb       { background: rgba(28, 27, 24, 0.2); border-radius: 3px; }
.sidebar__nav::-webkit-scrollbar-thumb:hover { background: rgba(28, 27, 24, 0.35); }

/* Section grouping. Two things give each sub-app its own visual
   identity: (a) a generous top margin so the cluster sits apart, and
   (b) a hairline divider at the top of each section *except* the
   first — divider + space together do what an unadorned gap can't,
   which is signal "new group here" at a glance. The Dashboard link
   above the first section sits flush — no top margin, no divider. */
.sidebar__nav > .sidebar__section {
  margin-top: var(--gap-5);
  padding-top: var(--gap-4);
  border-top: 1px solid var(--rule);
}
.sidebar__nav > .sidebar__section:first-of-type {
  border-top: 0;
  padding-top: 0;
}

/* Native <details>. The user-agent's `display: list-item` on summary
   gets killed via list-style: none so we can shape it ourselves.
   `display: flex; flex-direction: column` makes the section a flex
   container so its children (summary + links) are flex items with
   the SAME layout context as the top-level Dashboard link, which is
   a flex item of nav. Without this, in-section links were block-
   level children of a block <details>, and the size negotiation came
   out subtly different from Dashboard's. With both contexts being
   flex-column, both Dashboard and in-section links stretch to fill
   their cross-axis identically. `padding: 0; margin: 0` defensively
   kills user-agent inline padding. */
.sidebar__section {
  display: flex;
  flex-direction: column;
  padding: 0;
  margin: 0;
}
.sidebar__section > summary {
  list-style: none;
  padding-inline-start: 0;
}
.sidebar__section > summary::-webkit-details-marker { display: none; }
.sidebar__section > summary::marker { content: ""; }

/* Heading doubles as the toggle. Reads as a small-caps label that's
   clearly a heading (more contrast than before — ink-muted instead
   of ink-faint, slightly larger 0.72rem) so each sub-app's group
   announces itself rather than disappearing into the nav. A chevron
   on the right rotates with [open] state. */
.sidebar__heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-2);
  margin: 0 0 var(--gap-2);
  padding: 0 var(--gap-2);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.085em;
  color: var(--ink-muted);
  cursor: pointer;
  user-select: none;
  transition: color 120ms ease;
}
.sidebar__heading:hover { color: var(--ink); }
.sidebar__heading-chevron {
  display: inline-flex;
  align-items: center;
  width: 0.75rem;
  height: 0.75rem;
  color: currentColor;
  transition: transform 150ms ease;
}
.sidebar__heading-chevron svg { width: 100%; height: 100%; stroke-width: 2; }
/* Chevron-down default; rotate -90 (points right) when closed. */
.sidebar__section:not([open]) > .sidebar__heading .sidebar__heading-chevron {
  transform: rotate(-90deg);
}

/* Each rail item. The selector specificity (.sidebar prefix) beats
   any global `a` rules that would otherwise force their own padding /
   color (mirroring the .nav-menu specificity bump). Icon + label
   sit on one row; the label hides when collapsed. */
.sidebar .sidebar__link {
  display: flex;
  align-items: center;
  /* Stretch cross-axis in any flex parent (nav, section). The
     redundant width:100% + min-width:100% covers the equivalent
     block-parent case if the section ever rendered as a block. */
  align-self: stretch;
  width: 100%;
  min-width: 100%;
  gap: var(--gap-3);
  box-sizing: border-box;
  min-block-size: var(--sidebar-row-height);
  padding: 0 var(--gap-2);
  border-radius: var(--radius-sm);
  color: var(--ink-soft);
  text-decoration: none;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  transition:
    background-color 120ms ease,
    color 120ms ease;
}
.sidebar .sidebar__icon {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: var(--sidebar-icon-size);
  height: var(--sidebar-icon-size);
  color: inherit; /* SVG strokes use currentColor so active-state accent flows in */
}
.sidebar .sidebar__icon svg {
  width: 100%;
  height: 100%;
  display: block;
  stroke-width: 1.6;
}
.sidebar .sidebar__label { flex: 1 1 auto; min-width: 0; }
.sidebar .sidebar__badge { flex: 0 0 auto; }
.sidebar .sidebar__link + .sidebar__link { margin-top: 0.1rem; }
.sidebar .sidebar__link:hover {
  background: color-mix(in srgb, var(--ink) 5%, transparent);
  color: var(--ink);
}
/* Active state. Background tint + accent text are kept; the new
   `box-shadow: inset` draws a 3px left bar in the accent color
   without consuming layout width (avoiding a row-shift when toggling
   active). Together the bar + tint make the current page obvious
   even with a quick scan, while still feeling restrained. */
.sidebar .sidebar__link.is-active {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--accent);
  font-weight: 600;
  box-shadow: inset 3px 0 0 0 var(--accent);
}
.sidebar .sidebar__link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* Collapsed state — icon-only rail. Hide labels, headings, the
   brand text and the user-widget name; the icons + section
   dividers carry the structure. Pointer events still work so
   tooltips (title= on each link) surface the label on hover. */
.sidebar--collapsed .sidebar__brand,
.sidebar--collapsed .sidebar__label,
.sidebar--collapsed .sidebar__heading,
.sidebar--collapsed .sidebar__badge,
.sidebar--collapsed .user-menu__name,
.sidebar--collapsed .user-menu__caret {
  display: none;
}

/* When the whole sidebar is collapsed (icon-only), force ALL section
   items visible regardless of the section's own collapsed state —
   the headings are hidden, so per-section toggles would be invisible
   anyway. Icons stay accessible. */
.sidebar--collapsed details.sidebar__section:not([open]) > .sidebar__link {
  display: flex;
}

/* Tighter sidebar padding when collapsed so the 4rem rail isn't mostly
   eaten by the gap-4 horizontal pad (originally 16px each side, leaving
   only ~32px content — barely fit the 30px avatar, and made icons look
   left-aligned because the math couldn't center anything reliably).
   NOTE: do NOT set `align-items: center` on this flex column — the
   default `stretch` is what makes the nav + sections + links span the
   sidebar's full content width. With center, children shrink to
   content width and `justify-content: center` on a now-narrow link
   has no room to do its job. */
.sidebar--collapsed .sidebar {
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}

.sidebar--collapsed .sidebar__top {
  justify-content: center;
  width: 100%;
}

/* Force-center every nav row. Padding and `gap` are reset to 0 — with
   the label hidden the icon is the only content, `justify-content:
   center` puts it on the rail's centerline. */
.sidebar--collapsed .sidebar .sidebar__link {
  justify-content: center;
  padding: 0;
  gap: 0;
  width: 100%;
}
.sidebar--collapsed .sidebar__section {
  padding-top: var(--gap-3);
  border-top: 1px solid var(--rule);
  width: 100%;
}
.sidebar--collapsed .sidebar__section:first-of-type {
  border-top: 0;
  padding-top: 0;
}

/* User widget at the bottom — center the avatar in the same way the
   link icons center. Drop the trigger's own horizontal padding so
   the avatar can sit on the centerline without being squished
   against either edge. */
.sidebar--collapsed .user-menu--sidebar {
  width: 100%;
}
.sidebar--collapsed .user-menu--sidebar .user-menu__trigger {
  justify-content: center;
  padding: 0.3rem 0;
  gap: 0;
  width: 100%;
}

/* The user widget docks at the bottom. Bordered top edge so it reads
   as a distinct cluster from the nav above. Min-height matches the
   main column's footer (var(--bottom-strip-h) in root.css) so the
   two top borders sit at the same Y across the layout — both are
   bottom-pinned, both occupy the same vertical extent. */
.user-menu--sidebar {
  margin-top: auto;
  border-top: 1px solid var(--rule);
  min-height: var(--bottom-strip-h);
  display: flex;
  align-items: center;
}
.user-menu--sidebar > summary {
  list-style: none;
  cursor: pointer;
}
.user-menu--sidebar .user-menu__trigger {
  width: 100%;
  justify-content: flex-start;
}
.user-menu--sidebar .user-menu__name {
  flex: 1 1 auto;
  min-width: 0;
}
/* Flip the dropdown panel upward — the trigger sits at the viewport
   bottom, so opening down would clip. */
.user-menu--sidebar .user-menu__panel {
  top: auto;
  bottom: calc(100% + 0.5rem);
  left: 0;
  right: auto;
  min-width: 100%;
}

/* Main content fills the remaining grid column. Override .site-main's
   `margin: 0 auto` / max-width — the sidebar already constrains the
   page horizontally, so the content pane uses the full remaining
   width with its own padding. Flex column + min-height: 100vh +
   margin-top:auto on the footer pins the footer to the viewport
   bottom on short pages; on long pages it just sits at the natural
   end of content. Selector specificity (0,0,2,0) wins over
   `.site-main` (0,0,1,0) regardless of file load order. */
.site--sidebar .site-main {
  max-width: none;
  margin: 0;
  width: 100%;
  min-width: 0;
  padding: var(--gap-7) var(--gap-6) var(--gap-6);
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.site--sidebar .site-footer {
  background: transparent;
  border-top: 1px solid var(--rule);
  margin-top: auto;
}
.site--sidebar .site-footer__inner {
  max-width: none;
  /* Balanced top/bottom so the footer feels intentional, not jammed
     against the content above. Horizontal padding is zero (the
     main column already provides side padding via .site-main). */
  padding: var(--gap-4) 0 var(--gap-3);
}
