/* Desktop navigation rail — the narrow icon strip down the far left.
 *
 * Paired with `js/app-shell/nav_rail.js`, which builds every row and owns the
 * two states. Nothing here is inside a media query, and that is deliberate:
 * the rail is not "shown at a width", it is shown on a device — the rail and
 * the shell's padding both hang off `html[data-nav-rail='on']`, which the
 * module sets from the SAME `data-device` classification `js/mobile/mobile.js`
 * publishes. A second breakpoint here could disagree with `styles/mobile.css`
 * and leave a shell padded for a rail that is not on screen.
 *
 * ── Two ways to widen, and they are deliberately different ──────────────
 * PRESSING the hamburger COMMITS: the shell gives up the width and the rail
 * sits beside the view. HOVERING only PEEKS: the rail widens over the view and
 * the shell never moves. The difference is the point — a pointer crossing the
 * strip on its way somewhere else must not reflow the Calendar grid under it,
 * while a deliberate press is allowed to change the layout for as long as it is
 * left open. Hover therefore touches `width` and nothing else; the shell's
 * padding is driven only by `data-nav-rail`, which only `setExpanded` writes.
 *
 * ── Expanding widens the layout; the icons still do not move ────────────
 * 1. The shell is padded by the rail's CURRENT width: `data-nav-rail` is 'on'
 *    while collapsed and 'expanded' while open, and `.app-shell` follows. The
 *    expanded rail therefore sits beside the view rather than over it — nothing
 *    is ever hidden behind it. There is no width transition on purpose: the
 *    rail and the shell's padding have to change in the same frame, and
 *    animating a padding that reflows the Calendar grid is 160ms of jank. (The
 *    hover peek moves no padding, so it may animate — see the hover block.)
 * 2. Rows are laid out at the EXPANDED width in BOTH states and clipped by the
 *    rail's `overflow-x: hidden`. The icon is its own fixed-width column, so
 *    widening the rail reveals a label that was always there instead of
 *    re-flowing the row. Never give a row `width: 100%` — that is the one edit
 *    that puts the icons back on a moving centre line.
 * Section headings hold their height for the same reason: the divider is
 * always drawn and only its text fades in.
 *
 * Load order: after `layout.css`, whose `.app-shell` this re-pads. It used to
 * also have to follow `reflection-blocker.css` and outrank that file's left
 * drawer; no side panel opens on this edge any more (see the note below the
 * padding rules).
 */

:root {
  --nav-rail-width: 56px;
  --nav-rail-expanded-width: 218px;
}

.nav-rail {
  display: none;
  position: fixed;
  inset: 0 auto 0 0;
  box-sizing: border-box;
  width: var(--nav-rail-width);
  /* Above the sticky topbar (30) and below the side panels (50): the
     my-calendars panel opens over this corner by design, and it is wider. */
  z-index: 45;
  flex-direction: column;
  overflow-x: hidden;
  overflow-y: auto;
  scrollbar-width: none;
  padding: 6px 0 10px;
  background: var(--daily-goals-bg, var(--card));
  border-right: 1px solid var(--border-strong);
}

.nav-rail::-webkit-scrollbar {
  display: none;
}

html[data-nav-rail] .nav-rail {
  display: flex;
}

html[data-nav-rail] .app-shell {
  padding-left: var(--nav-rail-width);
}

/* Expanded, the shell gives up the extra width instead of being covered. */
html[data-nav-rail='expanded'] .app-shell {
  padding-left: var(--nav-rail-expanded-width);
}

/* Nothing on this edge indents for a side panel any more. My calendars gave up
   the left dock on 2026-08-09 and the reflection blocker on 2026-08-14; both
   needed a restatement here while they were left drawers, because the 56px rule
   above outranks a single-class `padding-left` and would have left the shell
   indented by the rail's width with a 340px panel sitting on top of the view.
   Every panel docks against the RIGHT rail now (styles/panel-rail.css), which
   is a different property on a different edge. */

.nav-rail[data-expanded='true'] {
  width: var(--nav-rail-expanded-width);
}

/* ── Hover peek — widens OVER the view, never beside it ─────────────────── */

/* Only for a real pointer. A touch device fires a sticky `:hover` on the first
   tap, which would leave the rail stuck open over the view with no way to
   dismiss it; there the hamburger is the only way in. */
@media (hover: hover) and (pointer: fine) {
  /* Scoped to the COLLAPSED rail: once the hamburger has committed, the width
     is already the expanded one and the shell is padded for it, so a hover rule
     here could only re-assert what is true and would fight the commit on exit.
     Nothing in this block writes `.app-shell` padding — that is what makes the
     peek an overlay rather than a second copy of the press. */
  .nav-rail:not([data-expanded='true']):hover {
    width: var(--nav-rail-expanded-width);
    /* It is over content now, so it has to read as a layer. The rail's own
       background is already opaque; this is the edge that says so. */
    box-shadow: 6px 0 20px rgba(0, 0, 0, 0.22);
    /* Safe to animate precisely because no padding follows it: nothing reflows,
       so this is 120ms of the rail alone. Declared on the hovered state only,
       so leaving snaps back — a widening that lingers after the pointer has
       gone reads as the rail being stuck. */
    transition: width 120ms ease;
  }

  .nav-rail:not([data-expanded='true']):hover .nav-rail-label,
  .nav-rail:not([data-expanded='true']):hover .nav-rail-section span {
    opacity: 1;
  }
}

/* ── Rows ──────────────────────────────────────────────────────────────── */

.nav-rail-row {
  /* Laid out expanded in BOTH states and clipped by the rail. See the header. */
  flex: 0 0 auto;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  width: var(--nav-rail-expanded-width);
  min-width: var(--nav-rail-expanded-width);
  height: 42px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
  transition: color 120ms ease, background 120ms ease;
}

.nav-rail-icon {
  flex: 0 0 var(--nav-rail-width);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The period letter sits in the icon column, at the size an icon occupies, so a
   letter row and an icon row are the same shape and share one left edge. */
.nav-rail-glyph {
  display: block;
  width: 20px;
  font-size: 14px;
  font-weight: 700;
  line-height: 20px;
  letter-spacing: 0.02em;
  text-align: center;
}

/* 3Y — the one span with two characters in it. It gives up the tracking and two
   points rather than widening the column: every other row's icon shares that
   column's centre line, and moving it would move all of them. */
.nav-rail-glyph-wide {
  font-size: 12px;
  letter-spacing: 0;
}

.nav-rail-label {
  white-space: nowrap;
  overflow: hidden;
  opacity: 0;
  transition: opacity 120ms ease;
}

.nav-rail[data-expanded='true'] .nav-rail-label {
  opacity: 1;
}

.nav-rail-row:hover {
  color: var(--text-primary);
  background: var(--utility-surface-strong);
}

/* A period the current surface cannot render — the Calendar has no month,
   quarter or year view. Flat and unclickable rather than hidden: a letter that
   vanished and came back would move every row below it each time the surface
   changed, and the gap is information (this view does not go that wide). */
.nav-rail-period.is-unavailable,
.nav-rail-period.is-unavailable:hover {
  color: var(--text-secondary);
  background: transparent;
  opacity: 0.35;
  cursor: default;
}

.nav-rail-row:focus-visible {
  outline: 2px solid var(--tab-active-border);
  outline-offset: -2px;
}

.nav-rail-item.is-active {
  color: var(--accent);
  background: var(--utility-surface-strong);
  /* An inset bar rather than a border: a border would change the row's box and
     shift the icon by its width when a row becomes active. */
  box-shadow: inset 3px 0 0 var(--accent);
}

.nav-rail-toggle {
  margin-bottom: 4px;
}

/* ── Section headings ──────────────────────────────────────────────────── */

.nav-rail-section {
  flex: 0 0 auto;
  box-sizing: border-box;
  display: flex;
  align-items: flex-end;
  width: var(--nav-rail-expanded-width);
  min-width: var(--nav-rail-expanded-width);
  height: 30px;
  margin: 6px 0 2px;
  padding: 0 0 4px 16px;
  border-top: 1px solid var(--border-strong);
  color: var(--text-secondary);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  opacity: 0.75;
}

/* The rule belongs BETWEEN sections; above the first one it reads as a stray
   line across the top of the rail. */
.nav-rail-section-first {
  border-top: 0;
}

.nav-rail-section span {
  white-space: nowrap;
  overflow: hidden;
  opacity: 0;
  transition: opacity 120ms ease;
}

.nav-rail[data-expanded='true'] .nav-rail-section span {
  opacity: 1;
}
