@layer components {
  /* Width of the categories sidebar when it is visible. */
  :root {
    --app-sidebar-width: 19rem;
    /* Minimum viewport width at which the sidebar is allowed to render.
       Below this, we fall back to the original header dropdown layout
       even when the user has enabled the sidebar. */
    --app-sidebar-breakpoint: 900px;
  }

  .app-sidebar {
    display: none;
    position: fixed;
    top: calc(var(--app-header-height, 2.75rem) + var(--blitz-staging-banner-height, 0rem));
    /* Sits at the app column's left edge — flush left on normal screens, offset
       inward when the column is centred on very wide screens. */
    left: var(--app-gutter);
    bottom: 0;
    width: var(--app-sidebar-width);
    background-color: var(--surface);
    border-right: 1px solid var(--sidebar-border);
    flex-direction: column;
    min-height: 0;
    z-index: 50;
    /* Mirror .app-main's padding-top so the sidebar's header row starts at
       the same y as the resource-header row. */
    padding-top: 1rem;
  }

  .app-sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0 1rem;
    /* Matches the .view-toggle-btn height in the resource-header so the
       "Kategorien" row aligns with the "Alle Notizen" row. */
    min-height: 2.5rem;
    border-bottom: 1px solid var(--hairline);
  }

  .app-sidebar-title {
    font-weight: 700;
    font-size: 1.15rem;
    line-height: 1.2;
    letter-spacing: 0.01em;
    color: var(--wine-deep);
    overflow: hidden;
    /* Wrap long category names onto a second line instead of truncating with
       an ellipsis on the first; only clamp once we exceed two lines. */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
  }

  .app-sidebar-header-actions {
    display: flex;
    align-items: center;
    gap: 0.1rem;
  }

  /* Header on the note detail page doubles as a "back to the list" link. */
  .app-sidebar-back {
    display: flex;
    align-items: center;
    gap: 0.2rem;
    min-width: 0;
    margin-left: -0.25rem;
    padding: 0.15rem 0.35rem;
    border-radius: 6px;
    color: inherit;
    text-decoration: none;
  }

  .app-sidebar-back:hover {
    background-color: #faf3f1;
    color: var(--wine);
    text-decoration: none;
  }

  .app-sidebar-back-icon {
    --icon-size: 1.1rem;
    color: var(--muted-2);
    flex-shrink: 0;
  }

  .app-sidebar-header-main {
    flex: 1;
    min-width: 0;
  }

  .app-sidebar-icon-btn,
  .sidebar-toggle-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border-radius: 8px;
    background: transparent;
    border: none;
    color: var(--muted);
    cursor: pointer;
    --icon-size: 1.4rem;
    transition: background-color 0.15s ease, color 0.15s ease;
  }

  .app-sidebar-icon-btn:hover,
  .sidebar-toggle-btn:hover {
    background-color: #faf3f1;
    color: var(--wine);
    text-decoration: none;
  }

  .app-sidebar-filter {
    position: relative;
    /* margin-top matches .resource-header's margin-bottom so the filter's
       top edge lines up with the first row of cards in the main content. */
    margin: 1rem 0.75rem 0.25rem;
  }

  .app-sidebar-filter-icon {
    --icon-size: 1rem;
    position: absolute;
    left: 0.55rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--muted-2);
    pointer-events: none;
  }

  .app-sidebar-filter-input {
    width: 100%;
    height: 2rem;
    padding: 0 0.6rem 0 1.8rem;
    border: 1px solid transparent;
    border-radius: 10px;
    background-color: #f5e9e3;
    font: inherit;
    font-size: 0.85rem;
    color: var(--ink);
    outline: none;
  }

  .app-sidebar-filter-input::placeholder {
    color: var(--muted-2);
  }

  .app-sidebar-filter-input:focus {
    border-color: var(--wine);
    background-color: white;
  }

  .app-sidebar-item.is-filtered-out {
    display: none;
  }

  .app-sidebar-nav {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 0.5rem 0.4rem 0.5rem 0.6rem;
    display: flex;
    flex-direction: column;
    gap: 3px;
  }

  .app-sidebar-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.25rem;
    border-radius: 10px;
    color: var(--wine);
    text-decoration: none;
    font-size: 0.98rem;
    font-weight: 500;
    letter-spacing: 0.01em;
    min-height: 2.4rem;
  }

  .app-sidebar-item:hover {
    background-color: #faf3f1;
    color: var(--wine);
    text-decoration: none;
  }

  /* Keyboard focus ring for ↑/↓ navigation — distinct from the amber
     "selected" (currently open) note. */
  .app-sidebar-item:focus-visible {
    outline: 2px solid #93c5fd;
    outline-offset: -2px;
  }

  .app-sidebar-item.selected {
    background-color: var(--gold);
    color: var(--wine-deep);
    font-weight: 600;
  }

  .app-sidebar-item.selected:hover {
    background-color: var(--gold-hover);
    color: var(--wine-deep);
  }

  /* Category row currently hovered while dragging an item from the list
     (move_to_category_controller). */
  .app-sidebar-item.is-drop-target {
    background-color: #dbeafe;
    box-shadow: inset 0 0 0 2px #60a5fa;
  }

  /* The card/row being dragged onto a sidebar category. */
  .is-dragged {
    opacity: 0.4;
  }

  a.app-sidebar-item,
  .app-sidebar-item-link {
    display: flex;
    align-items: center;
    min-width: 0;
    padding: 0.5rem 0.7rem;
    color: inherit;
    text-decoration: none;
  }

  /* Only the inner link (inside a wrapping .app-sidebar-item <div>) needs to
     grow horizontally to fill the click area next to the action menu. On the
     bare <a class="app-sidebar-item"> ("Alle Notizen"), flex: 1 would make it
     stretch vertically inside the column-flex nav when few categories exist. */
  .app-sidebar-item-link {
    flex: 1;
    /* Extra right-padding is added on hover to make room for the (then visible)
       3-dots menu; transition keeps the label from jumping as it truncates. */
    transition: padding-right 0.12s ease;
  }

  .app-sidebar-item-link:hover {
    text-decoration: none;
  }

  /* Reserve space for the action menu only while it is actually shown, so the
     full category name has the whole row width at rest and only shortens on
     hover / focus / open. Matches the menu button's exact footprint (its
     right: 0.35rem offset + 1.75rem width) so nothing is truncated beyond what
     the button genuinely covers — a wider reservation clipped ~2 extra chars. */
  .app-sidebar-item:hover .app-sidebar-item-link,
  .app-sidebar-item:focus-within .app-sidebar-item-link,
  .app-sidebar-item:has(.dropdown-menu.show) .app-sidebar-item-link {
    padding-right: 2.1rem;
  }

  .app-sidebar-item-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
  }

  /* Separator between the pinned "Express-…" bucket and the real categories. */
  .app-sidebar-divider {
    border: none;
    border-top: 1px solid var(--hairline);
    margin: 5px 0.7rem;
  }

  /* Icon sitting right after the "Express-…" label. */
  .app-sidebar-item-icon {
    flex-shrink: 0;
    margin-left: 0.35rem;
    --icon-size: 1rem;
    color: var(--wine);
  }

  /* Category names are shown in upper-case regardless of how they were entered
     (the "Alle Notizen" / uncategorised nav rows use a bare .app-sidebar-item,
     so they are intentionally left as-is). */
  .app-sidebar-item-link .app-sidebar-item-label {
    text-transform: uppercase;
    letter-spacing: 0.02em;
  }

  .app-sidebar-item-menu {
    --icon-size: 1.1rem;
    --dropdown-menu-left: auto;
    --dropdown-menu-right: 0;
    /* Absolutely positioned so it overlays the row's right edge instead of
       reserving flow space — that lets the label use the full width at rest. */
    position: absolute;
    right: 0.35rem;
    top: 50%;
    transform: translateY(-50%);
    flex-shrink: 0;
    visibility: hidden;
  }

  .app-sidebar-item:hover .app-sidebar-item-menu,
  .app-sidebar-item-menu:focus-within,
  .app-sidebar-item-menu:has(.dropdown-menu.show) {
    visibility: visible;
  }

  .app-sidebar-item-menu .dropdown-toggle-button {
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 4px;
    color: var(--muted-2);
    background: transparent;
    border: none;
    cursor: pointer;
  }

  .app-sidebar-item-menu .dropdown-toggle-button:hover {
    background-color: rgba(138, 39, 64, 0.08);
    color: var(--wine);
  }

  /* The sidebar toggle lives next to the resource title (never inside the
     sidebar) and is a single button that opens or closes the sidebar in either
     state. Hidden below the sidebar breakpoint, where the sidebar is
     force-collapsed and toggling is meaningless; shown on wide screens by the
     media query below. */
  .sidebar-toggle-btn {
    display: none;
  }

  /* Wide viewports: respect the user's saved preference. */
  @media (min-width: 900px) {
    /* On wide screens the sidebar always participates in layout; collapsed vs
       expanded is a slide+fade rather than a display toggle, so it animates
       instead of snapping. Collapsed = translated fully off the left edge and
       faded out; `visibility` flips only after the outro so hidden rows drop
       out of the tab order without cutting the animation short. */
    .app-sidebar {
      display: flex;
      transform: translateX(calc(-100% - var(--app-gutter) - 1px));
      opacity: 0;
      visibility: hidden;
      transition: transform 0.28s ease, opacity 0.28s ease, visibility 0s 0.28s;
    }

    .app-main[data-sidebar="visible"] .app-sidebar {
      transform: translateX(0);
      opacity: 1;
      visibility: visible;
      transition: transform 0.28s ease, opacity 0.28s ease, visibility 0s 0s;
    }

    /* Always visible on wide screens — the same button toggles both ways. */
    .sidebar-toggle-btn {
      display: inline-flex;
    }
  }

  /* Narrow viewports: collapse automatically, no matter what was saved. */
  @media (max-width: 899px) {
    .app-sidebar {
      display: none !important;
    }
  }
}

/* Layout overrides live in the utilities layer so they beat
   .max-width-container's margin-left: auto, which is also in utilities.

   Everything is anchored to the viewport's left edge (never centred) and the
   header is made independent of the sidebar state, so toggling the sidebar
   never shifts the header or the centring of the page — only the main content
   reflows to make room for the sidebar. */
@layer utilities {
  @media (min-width: 900px) {
    /* Content: offset by the gutter (0 — the column is anchored left); only the
       left margin gains the sidebar width when the sidebar is open. The margin
       animates with the same duration/easing as the sidebar's slide (see
       .app-sidebar's `transition: transform 0.28s ease`) so the content's left
       edge and the sidebar's right edge move in lockstep. */
    .app-main {
      transition: margin-left 0.28s ease;
    }

    .app-main[data-sidebar="hidden"] {
      margin-left: var(--app-gutter);
    }

    .app-main[data-sidebar="visible"] {
      margin-left: calc(var(--app-gutter) + var(--app-sidebar-width));
      max-width: calc(var(--content-max-width, 100%) - var(--app-sidebar-width));
    }

    /* Header content: same gutter offset, right edge capped at
       --content-max-width. Independent of sidebar state, so it never moves on
       toggle; centres together with the sidebar and content on wide screens. */
    .app-header > .max-width-container {
      max-width: var(--content-max-width);
      margin-left: var(--app-gutter);
      margin-right: auto;
    }

    /* Width-lock the brand group (TROVARO) so the archive card that follows
       always STARTS on the content column's left edge — aligned with the cards
       and title below (sidebar-width + .app-main's 1rem padding), not on the
       bare sidebar border. Applied in both sidebar states so the card never
       shifts on toggle. Geometry: the archive card's left edge = brand-group
       left (1.25rem header padding) + this width + the 1rem header flex-gap, set
       equal to the content column left (sidebar-width + 1rem), so:
         width = (sidebar-width + 1rem) − 1.25rem − 1rem = sidebar-width − 1.25rem. */
    .header-brand-group {
      width: calc(var(--app-sidebar-width) - 1.25rem);
      flex: 0 0 auto;
    }
  }
}

/* Users who prefer reduced motion get the instant toggle back. */
@media (prefers-reduced-motion: reduce) {
  .app-sidebar,
  .app-main {
    transition: none;
  }
}
