/* ============================================================================
   Menu — the left navigation        COMPONENTS.md §7.1, §7.2, §7.3

   Built from the FE Client home screenshot, against the CURRENT-generation
   recipe (`Menu` + `Menu / Item` + `Menu / Group` + `Menu / Divider`).
   Explicitly NOT `Menu / Default` (§7.4, legacy, 84 variants) and not the five
   `BACKUP /` sets (§7.5), which freeze `#4211a0` as a literal.

   ⚠️ ROW HEIGHT DIVERGES FROM §7.2. The recipe documents Large 78 / Small 62.
   The screenshot's rows are on a 40px pitch with no subtitle line. The
   screenshot is the spec the design gave, so 40 is used — but this means the
   FE.C sidebar is not using the documented `Menu / Item` geometry. Flagged in
   the README; worth reconciling with the DS rather than assuming either side.

   §7 F3 — the DS signals `Selected` by label colour ALONE. This does not:
   Selected carries four channels (see .menu__item.is-selected).
   §7 F2 — the DS `Hover` produces no token change from `Default`. This does.
   §7.2 — `Menu / Item` is one of only two sets modelling Focus. Honoured.
   §7.3 F8 — `Menu / Divider` Title uses `RAW #8c8c8c`. Bound here.

   TODO(tokens): every bare px length in this file is a SIZE.
   DESIGN.md §12.4 records size as not built.
   ========================================================================== */

.menu {
  /* §7.1 token contract: fill surface/raised. */
  background: var(--color-surface-raised);
  border-radius: var(--shape-radius-card);
  padding: var(--space-xs) var(--space-2xs);
  /* Takes the slack in the full-height sidebar, and scrolls inside itself when
     the nav outgrows the viewport. `min-block-size: 0` is what lets a flex item
     actually shrink below its content size. */
  flex: 1 1 auto;
  min-block-size: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  /* No stroke and no shadow. Neither is needed once the page is the sunken
     layer: Light puts raised #ffffff on sunken #f5f5f5, Dark puts raised
     #2f2f2f on sunken #1f1f1f, so the surface pair carries the edge on its own
     — which is what DESIGN.md §8 says to rely on in Dark anyway.

     Elevation/Raised was here (§8 describes it for "cards and resting
     surfaces") but its key layer is `0 1px 2px rgba(0,0,0,.16)`, and a 2px blur
     at that opacity renders as a hairline right round the card rather than as
     lift. On a sunken page that reads as an unwanted stroke. Removed.
     `--elevation-overlay` and `--elevation-sticky` are still consumed, on the
     dropdown panels and the navbar, where a surface pair is not available. */
}

.menu__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* --- Menu / Item ---------------------------------------------------------- */
.menu__item {
  position: relative;
  display: flex;
  inline-size: 100%;
  align-items: center;
  gap: var(--space-sm);
  /* See the row-height note in the file header. */
  min-block-size: 40px;
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--radius-xs);
  text-align: start;
  text-decoration: none;
  color: var(--color-content-primary);
  font-family: var(--font-family-text);
  /* §7.2: label is Label/MD Regular — the UI type track, per DESIGN.md §5.2. */
  font-size: var(--font-label-md-size);
  line-height: var(--font-label-md-line-height);
  font-weight: var(--font-weight-regular);
  letter-spacing: var(--font-letter-spacing-default);
  transition: background-color 100ms ease, color 100ms ease; /* TODO(tokens): motion not built */
}

/* §7 F2: the DS Hover is a no-op. A navigation row must react to the pointer. */
.menu__item:hover {
  background: var(--color-soft-neutral-hover);
  color: var(--color-content-headline);
}

/* CLAUDE.md known gaps: no pressed state anywhere, though the soft-neutral
   pressed step exists and is correct. Consumed. */
.menu__item:active {
  background: var(--color-soft-neutral-pressed);
}

/* --- Selected -------------------------------------------------------------
   §7 F3 calls out colour-as-sole-channel here, and `indicator/brand`'s own
   description says to "always pair with a weight or icon change". Four
   channels, so the state survives without colour entirely:
     1. the indicator bar   (::before, --color-indicator-brand)
     2. brand ink           (--color-content-brand)
     3. a weight step       (regular → medium)
     4. a _line → _fill glyph swap  (ASSETS.md §3)
   No fill, per the §7.2 contract (Selected keeps surface/raised). */
.menu__item.is-selected {
  color: var(--color-content-brand);
  font-weight: var(--font-weight-medium);
}

.menu__item.is-selected::before {
  content: "";
  position: absolute;
  inset-block: var(--space-2xs);
  inset-inline-start: calc(-1 * var(--space-2xs));
  /* CLAUDE.md known gaps: `indicator/brand` has zero consumers. It is the
     documented "non-colour redundancy channel" — this is what it is for. */
  inline-size: var(--border-width-heavy);
  border-radius: var(--radius-full);
  background: var(--color-indicator-brand);
}

.menu__item.is-selected .icon {
  --icon-src: var(--icon-src-fill);
}

.menu__item[aria-disabled="true"] {
  color: var(--color-content-disabled);
  pointer-events: none;
}

.menu__icon {
  flex: none;
  /* Inherits colour from the row — ASSETS.md §4: icons follow content/*. */
  color: inherit;
}

.menu__label {
  min-inline-size: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Menu / Item / Tag — notification count. Kept for parity with §7.3 even
   though no row in the screenshot carries one. */
.menu__item .badge {
  flex: none;
}

/* --- Menu / Divider — Line ----------------------------------------------- */
.menu__divider {
  block-size: var(--border-width-thin);
  margin: var(--space-xs) var(--space-sm);
  background: var(--color-border-default);
  border: 0;
}

/* --- Menu / Group heading -----------------------------------------------
   §7.1 / §7.3: content/secondary, Label/SM Medium.
   The uppercase treatment is what `letter-spacing/wide` was minted for —
   DESIGN.md §5.1 describes it as "intended for uppercase micro-labels" and
   "not currently used". Consumed here for exactly its stated purpose. */
.menu__group-heading {
  margin: 0;
  padding: var(--space-xs) var(--space-sm) var(--space-2xs);
  color: var(--color-content-secondary);
  font-family: var(--font-family-text);
  font-size: var(--font-label-sm-size);
  line-height: var(--font-label-sm-line-height);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--font-letter-spacing-wide);
  text-transform: uppercase;
}

/* ============================================================================
   THE DISCLOSURE — below 1024 the menu is a dropdown

   ⚠️ NO COMP. The reasoning, and what it replaces, is in src/components/menu.js.
   Nothing above this line changes: the same `.menu` card is the panel, so a row
   looks and behaves identically in both bands.
   ========================================================================== */

/* Above 1024 the wrapper is not there at all — the nav stays a direct flex
   child of `.sidebar`, so the desktop column is exactly what it was. */
.menu-shell {
  display: contents;
}

.menu-toggle {
  display: none;
}

@media (max-width: 1023px) {
  .menu-shell {
    display: block;
    position: relative;
    /* Full width, like the greeting card above it — see the note in
       sidebar.css. The trigger and the panel are one control and take one
       width, so the panel spans the gutters too and its rows get more columns
       to wrap into. */
  }

  /* --- The trigger -------------------------------------------------------
     A `Menu / Item` at heart — same surface, same radius, same label type —
     with a caret and a second line of context. It is not a hamburger: it names
     the row you are on, because collapsing the rail otherwise trades a visible
     position for a glyph. */
  .menu-toggle {
    display: flex;
    inline-size: 100%;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-xs) var(--space-md);
    /* TODO(tokens): size not built. 56 is the 40px row plus the eyebrow line. */
    min-block-size: 56px;
    border: 0;
    border-radius: var(--shape-radius-card);
    background: var(--color-surface-raised);
    color: var(--color-content-primary);
    font-family: var(--font-family-text);
    text-align: start;
    cursor: pointer;
    transition: background-color 100ms ease; /* TODO(tokens): motion not built */
  }

  /* The same two states the rows carry, for the same reason — §7 F2's no-op
     Hover is not reproduced, and the unconsumed pressed step is. */
  .menu-toggle:hover {
    background: var(--color-soft-neutral-hover);
  }

  .menu-toggle:active {
    background: var(--color-soft-neutral-pressed);
  }

  /* §7.2 models Focus and this honours it — one of the five components in
     ~300 that has the state. `:focus-visible` only. */
  .menu-toggle:focus-visible {
    outline: var(--shape-focus-width) solid var(--color-border-focus);
    outline-offset: var(--shape-focus-offset);
  }

  .menu-toggle__icon {
    flex: none;
    /* The trigger names the current row, so it takes that row's ink — the same
       brand colour and the same `_fill` weight the selected row uses. Two
       channels, not colour alone. */
    color: var(--color-content-brand);
    --icon-src: var(--icon-src-fill);
  }

  .menu-toggle__label {
    display: flex;
    flex: 1 1 auto;
    min-inline-size: 0;
    flex-direction: column;
  }

  /* "Menu" above the row name. It is what tells the reader the control is the
     navigation rather than a heading for the page they are on — the word the
     glyph alone would have had to carry. */
  .menu-toggle__eyebrow {
    color: var(--color-content-secondary);
    font-size: var(--font-label-sm-size);
    line-height: var(--font-label-sm-line-height);
    font-weight: var(--font-weight-medium);
    letter-spacing: var(--font-letter-spacing-wide);
    text-transform: uppercase;
  }

  .menu-toggle__current {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--color-content-brand);
    font-size: var(--font-label-md-size);
    line-height: var(--font-label-md-line-height);
    font-weight: var(--font-weight-medium);
  }

  .menu-toggle__caret {
    flex: none;
    color: var(--color-content-secondary);
    transition: transform 150ms ease; /* TODO(tokens): motion not built */
  }

  [data-menu-shell][data-open="true"] .menu-toggle__caret {
    transform: rotate(180deg);
  }

  /* --- The panel ---------------------------------------------------------
     The same `.menu` card, lifted out of the flow so opening the navigation
     does not push the page down — the behaviour that made the inline rail
     costly on exactly these viewports.

     `--elevation-overlay` rather than the surface pair the card relies on at
     desktop: over the page it is raised-on-sunken and the pair carries the
     edge, but this panel lands on top of other raised cards, where it would be
     white on white. Same argument dropdown.css makes for its own panels. */
  .menu-shell .menu {
    position: absolute;
    z-index: 20; /* TODO(tokens): z-index not built — DESIGN.md §12.4. */
    inset-inline: 0;
    inset-block-start: calc(100% + var(--space-2xs));
    flex: none;
    padding: var(--space-xs);
    box-shadow: var(--elevation-overlay);
    /* Never taller than the room under the trigger. 
       TODO(tokens): size not built. 56 is the trigger, 24 the gutter. */
    max-block-size: calc(100dvh - 64px - 56px - var(--space-lg) * 3);
    overflow-y: auto;
    scrollbar-width: thin;
  }

  /* Two or three columns while there is room for them, one when there is not.
     The rows are the same rows; only how many fit on a line changes. */
  .menu-shell .menu__list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  }
}
