/* Sidebar styles, named BEM-style: `sidebar` is the block, `sidebar__*` its
   elements, `sidebar--*` its modifiers. Two names here deliberately sit outside
   the block:

   - `sidebar-resizer` is its own block, not `sidebar__resizer`. The grabber is a
     SIBLING of .sidebar inside the <aside>, so it isn't part of the sidebar's
     subtree (see the `aside:has()` rule below, which exists for exactly that
     reason).
   - `sidebar-resizing` is a document-level state class sidebar_controller puts
     on <html> during a drag, not a class on any sidebar element.

   Bootstrap/Tabler-owned classes (`show`, `dropdown-menu`, `collapse`, the
   `d-*` utilities) keep their own names — Bootstrap's own JS and CSS write and
   read them, so they aren't ours to rename. */

:root {
  --sidebar-resizer-width: 15px;

  /* ---- Rail geometry -----------------------------------------------------
     The rail is chrome, not the content column, so it does NOT follow Ledger's
     "padding is vertical only" rule: the active fill is a chip sitting IN the
     rail, inset from both edges, rather than a band bleeding across it. That
     inset is the whole reason the current row reads as a marker instead of a
     stripe.

     Row height and icon size are tokens because they are set in two places --
     here for the labelled rail, and again in the `width <= 125px` container
     query for the icon rail, which is taller and squarer. Keep the icon in rem,
     not em: the container query changes the rail's font-size, so an em glyph
     comes out 17px beside a label and 20px in the icon rail.

     Theme-supplied, because the rail is chrome and its geometry is part of the
     look: Ledger runs 36px rows with a 20px glyph, Air 32px with 19px. */
  --lens-rail-inset: var(--lens-nav-inset);
  --lens-rail-row-min: var(--lens-nav-row-min);
  --lens-rail-icon: var(--lens-nav-icon);
}

/* ==== Base Selectors ==== */
/* Sidebar Body */
.sidebar {
  position: relative;
	font-size: 10pt;
	container-type: inline-size;
  container-name: sidebar; 
	transition: width 0.5s ease;
  /* Ledger tints the rail one step down from the sheet and separates it with a
     rule rather than a shadow, so the nav reads as the margin of the page
     rather than a floating panel. Both values are already in the ramp.

     The rule itself is on the data-side selectors below, because which edge it
     belongs on depends on which side the rail is mounted. Don't put it back
     here alongside a Bootstrap `.border-{side}` utility: the utility carries
     `!important` and wins, dragging in --tblr-border-color-translucent, a
     20%-alpha hairline that reads as no rule at all. */
  background-color: var(--lens-nav-bg);
  backdrop-filter: var(--lens-nav-filter);
  /* Same reasoning as .navbar in app.css: a blurred rail is a stacking context, and
     the rail holds the organization selector's dropdown. One step below the top bar
     so an open user menu still overlaps the rail rather than the other way round. */
  z-index: 1020;
}

/* Set the default size to the localStorage value */
/* Width is driven by these custom properties, never by an inline style on the
   sidebar itself. Two reasons: they live on <html>, outside every LiveComponent's
   DOM, so a live re-render can't strip the width; and the inline script in
   app.html.twig seeds them from localStorage before first paint, so the restored
   width is right on the first frame rather than applied after connect().
   sidebar_controller writes these on expand/shrink/drag.

   Matched on data-side (not `side`): `side` is a component prop, consumed rather
   than rendered, so an aside[side='...'] selector can never match. */
aside[data-side='start'] > .sidebar {
  width: var(--start-sidebar-size, 250px);
  border-right: var(--lens-nav-border);
}
aside[data-side='end'] > .sidebar {
  width: var(--end-sidebar-size, 250px);
  border-left: var(--lens-nav-border);
}

/* Suppress the width transition while dragging. A class on <html> rather than an
   inline style on the sidebar, for the same reason as above — nothing this
   controller writes should land inside a morphed subtree. */
html.sidebar-resizing .sidebar {
  transition: none !important;
}

/* Sidebar Items */
.sidebar__items {
	overflow: hidden;
	width: 100%;
}

/* Sidebar Spacer */
.sidebar__spacer {
	border-radius: var(--lens-radius-nav);
	align-items: center;
	justify-content: start;
  color: var(--tblr-secondary);
  text-decoration: none;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  gap: 0.5rem;
  min-height: var(--lens-rail-row-min);
  /* Inset rather than full-bleed -- see --lens-rail-inset. Width is computed
     instead of using margin alone because .sidebar__items is a centred flex
     column with `overflow: hidden`: a 100%-wide row plus side margins would
     overflow and get clipped rather than shrink. */
  width: calc(100% - 2 * var(--lens-rail-inset));
  margin-inline: var(--lens-rail-inset);
  padding: 0.125rem 0.375rem;
  flex-wrap: nowrap;
}

/* Sidebar Item */
.sidebar__item {
	border-radius: var(--lens-radius-nav);
	align-items: center;
	justify-content: start;
  color: var(--tblr-secondary);
  text-decoration: none;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  gap: 0.5rem;
  min-height: var(--lens-rail-row-min);
  /* Same inset and reasoning as .sidebar__spacer above. */
  width: calc(100% - 2 * var(--lens-rail-inset));
  margin-inline: var(--lens-rail-inset);
  /* Margin, not a gap on the parent: the rows sit in a plain overflow wrapper
     inside .sidebar__items, so a gap there never reaches them. */
  margin-block: 0.0625rem;
  padding: 0.125rem 0.375rem;
  flex-wrap: nowrap;
}

/* Ledger fills the active row with a pale blue and keeps the label in ink --
   a blue label would read as a link. Air disagrees and colours both, which is
   why the fill and the foreground are two tokens rather than one. */
/* Both halves are theme-supplied and must move together. A hardcoded fill beside
   a themed label is how the active row once came out 1.04:1 in dark -- the one
   row in the nav you could not read. */
.sidebar__item--active {
  background-color: var(--lens-nav-active-bg);
  color: var(--lens-nav-active-fg);
}

/* One size in both rails -- see --lens-rail-icon. */
.sidebar__item>svg {
	width: var(--lens-rail-icon);
	height: var(--lens-rail-icon);
	flex-shrink:0;
}

/* label.html.twig wraps the row's label in <b>, which the UA renders at 700 --
   heavier than anything else in the product, since the type scale caps at 600.
   Weight is not what marks the current page here; the filled row is. So the
   labels sit at the body weight and only the active row steps up. */
.sidebar__item-label b {
	font-weight: var(--tblr-font-weight-normal);
}

.sidebar__item--active .sidebar__item-label b {
	font-weight: var(--tblr-font-weight-medium);
}

.sidebar__item-description {
	color: var(--tblr-secondary);
	font-size: 0.75rem; /* 12px, per Ledger's rail */
}

/* Its own block (the page's main content area), not a sidebar element — it lives
   here only because it's related to the display of the sidebar */
.app-container {
  right: calc(var(--sidebar-resizer-width) / 2);
}

.sidebar__dropdown-indicator {
  transition: transform 0.3s ease;
  will-change: transform;
}

.show .sidebar__dropdown-indicator {
  transform: rotateZ(-180deg);
}

.sidebar__item .sidebar__item-label span {
	width: 100%;
	hyphens: auto;
	hyphenate-character: '-';
  text-decoration: none;
}

.sidebar__item>.sidebar__item-action {
	user-select: none;
}

.sidebar__item:hover {
  color: var(--tblr-body-color);
  /* One step up from the rail, one step below the active row. */
  background: var(--tblr-gray-200);
  border-color: transparent;
  text-decoration: none;
  /* background: color-mix(in srgb, var(--tblr-primary) 50%, #fff 30%); */
}

.sidebar__item:active {
  color: var(--tblr-primary);
  background-color: rgba(var(--tblr-primary-rgb), 0.04);
  border-color: var(--tblr-primary);
}

/* ==== Resize Grabber ==== */
.sidebar-resizer {
  position: relative;
	right: calc(var(--sidebar-resizer-width) / 2);
  width: var(--sidebar-resizer-width);
  height: 100%;
  background: transparent;
  cursor: ew-resize;
  flex-shrink: 0;
}

.sidebar-resizer--end {
  right: 0;
  z-index: 999;
  left: calc((var(--sidebar-resizer-width) / 2));
}

/* Primary Colored Indicator */
.sidebar-resizer::before,
.sidebar-resizer::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 10px;
  height: 40px;
  transform: translate(-50%, -50%);
  pointer-events: none;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(var(--tblr-primary-rgb), 30%) 0%,
    rgba(var(--tblr-primary-rgb), 40%) 20%,
    transparent 20%
  );
	border-radius: 50px;
}

.sidebar-resizer::after {
  transform: translate(-50%, -50%) rotate(180deg);
}

.sidebar-resizer:hover {
  background: rgba(var(--tblr-primary-rgb), 30%);
}

.sidebar-resizer:active {
  background: rgba(var(--tblr-primary-rgb), 50%);
}

/* Bootstrap uses multiple classes to integrate inline dropdowns, this just makes it available for our sidebar.
   The open subtree hangs off a vertical rule in the brand blue, and it is drawn
   entirely by utilities on the markup -- `border-start border-primary border-2`,
   see sidebar/group.html.twig. Nothing about that line is set here: all three
   utilities are `!important`, so a colour or a width in this rule would be dead
   code (which is exactly what a --tblr-border-color-translucent override here
   turned out to be). `border: none` below is the one thing that does land, and
   only on the three edges no utility claims. */
.sidebar__dropdown>.dropdown-menu {
  padding: 0;
  background: 0 0;
  position: static;
  color: inherit;
  box-shadow: none;
  border: none;
  min-width: 0;
  margin: 0;
}

.sidebar__dropdown .dropdown-menu a.sidebar__item {
  width: calc(100% - 8px);
}

/* ==== Fully Hidden State ==== */
/* Applied by sidebar_controller to the inner .sidebar, not the <aside> (see the
   HIDDEN_CLASS comment there). `!important` is required to beat the var-driven
   width rule above — which is the point: the --{side}-sidebar-size property is
   left intact, so removing this class animates straight back to the stored width
   via the .sidebar width transition, with nothing to restore. */
.sidebar.sidebar--hidden {
  width: 0 !important;
  min-width: 0 !important;
  padding: 0 !important;
  border-width: 0 !important;
  overflow: hidden;
}

/* The resize grabber sits outside .sidebar as a sibling, and precedes it when
   side="end" — so it can't be reached with a sibling combinator from the hidden
   element. :has() scopes it to the collapsed sidebar's own <aside>. */
aside:has(> .sidebar.sidebar--hidden) .sidebar-resizer {
  display: none;
}

/* ==== Container Queries ==== (These collapse the text when the sidebar is small) */
@container sidebar (width <= 300px) {
	.sidebar__items {
		gap: 0.25rem !important;
	}
	.sidebar__item-description {
		display: none;
	}
  .sidebar__hide-shrunk {
    display: none;
  }
}

@container sidebar (width <= 125px) {
  * {
		font-size: 12pt;
	}

  .sidebar__hide-collapsed {
    display: none;
  }

	.sidebar h1 {
		display: none;
	}

  .sidebar__dropdown-indicator {
    display: none;
  }

  /* The icon rail is squarer and looser than the labelled one: with nothing but
     a glyph to read, a 28px row reads as a cramped list of dots. Taller rows on
     a wider gap give each icon its own square target, which is what makes the
     filled current row read as a chip. */
	.sidebar__item {
    gap: 0px;
		justify-content: center !important;
    min-height: 3rem;                 /* 48px */
		padding: 0.25em 0 !important;
	}

  .sidebar__items {
    gap: 0.5rem !important;           /* 8px, overriding the <=300px rule */
  }

  /* The org tile is the rail's masthead once the name beside it is gone, so it
     steps up from avatar-sm (32px) to fill the rail's square. */
  .sidebar .avatar {
    --tblr-avatar-size: 2.75rem;      /* 44px */
    --tblr-avatar-font-size: 0.875rem;
  }

  .sidebar__item > a,
  .sidebar__item > * > a {
    justify-content: center !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
  }

  .sidebar__item .sidebar__item-label {
		display: none !important;
	}

  .sidebar__toggle--shrink {
		display: none !important;
	}

  .sidebar__toggle--expand {
		display: flex !important;
	}

  .sidebar__header {
    display: none !important;
  }

  .sidebar__item + .sidebar__header {
    display: flex !important;
  }

  .sidebar__header::after {
    margin: 0 !important;
  }

  .sidebar__header {
    margin: 0.25em 0 !important;
    width: 100%;
  }

  .sidebar__header>span {
    display: none !important;
  }
}


/* ==== Media Queries ==== */
@media (max-width: 991px) { 
  .sidebar {
    width: 100vw !important;
    padding: 1em;
    border-bottom: 1px solid var(--tblr-border-color);
    transition: none !important;
  }
  .sidebar__toggle {
    display: none;
  }
  .sidebar-resizer {
    display: none;
  }
}
@media (min-width: 992px) {
  /* 4.5rem is the icon rail proper: the 20px glyph centred in a 48px row, plus
     the 8px inset either side, with the 44px org tile still clearing it.

     THREE numbers decide how narrow the rail can get, and they all have to
     agree or the rail lands somewhere none of them intended:
       1. this min-width          -- the CSS floor
       2. `minSize`               -- what shrink() sets, and the drag's clamp
       3. the first `snap-sizes`  -- what a drag within 15px is pulled to
     Both 2 and 3 live in components/sidebar/index.html.twig. Miss 3 and the
     collapse button gives you one width while dragging gives you another. */
  .sidebar--app {
    min-width: 4.5rem;
    max-width: min(50vw, 350px);
  }
  .sidebar__items {
    height: 100%;
  }
}

/* Hover on a rail row. Its own token because the two themes disagree on what a
   hover IS: Ledger steps the grey, Air washes the brand blue at 4.5%. */
.sidebar__item:hover:not(.sidebar__item--active) {
  background-color: var(--lens-nav-hover-bg);
}
