/* Side-panel rail — the narrow icon strip down the far RIGHT.
 *
 * Paired with `js/sidebar/panel_rail.js`, which builds every row. The strip is
 * on screen (`html[data-panel-rail='on']`) or the device is a phone and it does
 * not exist at all (the attribute is absent). It has ONE width: there is no
 * icons-plus-labels state like `styles/nav-rail.css`, because pressing an icon
 * here opens a panel that covers 420px of the screen, and spending 218px on the
 * name of the thing you are about to cover buys nothing.
 *
 * Two states DO live on the strip itself, and neither changes its width:
 *   `.is-selected` — the row the chevron acts on. Always exactly one.
 *   `.is-active`   — that row's panel is on screen. Read off the panel's own
 *                    button, so a panel closed from its own header un-lights it.
 * `data-panel-open` on the rail is the second of those for the SELECTED row,
 * and all it does down here is turn the chevron around.
 *
 * Nothing here is inside a media query, deliberately: the rail is shown on a
 * DEVICE, not at a width. `html[data-panel-rail]` is written by the module from
 * the same `data-device` classification `js/mobile/mobile.js` publishes, so a
 * breakpoint here could not disagree with `styles/mobile.css` — which hides
 * `.topbar-actions` on a phone and hands the panels to the nav drawer.
 *
 * ── Panels dock BESIDE the rail, and travel UNDER it ────────────────────
 * Every side panel is `.chat-panel`, `position: fixed; right: 0`, at z-index 50
 * against this rail's 45 — so left alone, an open panel sits on top of the rail
 * and the only control that closes it, and a panel OPENING slides its whole
 * card across the icons on the way to its dock. Four things move together and
 * must keep moving together, and all four are scoped to `[data-panel-rail='on']`
 * — the state where a strip is actually taking up room. On a phone there is
 * none, and the panels' own rules are already right:
 *   1. the panel's `right`, so it stops at the rail's inner edge;
 *   2. the panel's `z-index`, dropped BELOW the rail so it emerges from behind
 *      the strip instead of passing over it;
 *   3. the shell's `padding-right`, which is rail + panel while one is open;
 *   4. the CLOSED panel's transform — `translateX(100%)` slides it out by its
 *      own width, which would park it exactly over the rail. Behind it now,
 *      but "behind an opaque strip" is a weaker claim than "off screen", so it
 *      still clears the rail's width as well.
 * Load after `chat.css` and `today-calendar-sidebar.css`. Order is belt to the
 * braces of specificity — every rule below carries `html[data-panel-rail…]`, so
 * it outranks the single-class rules it overrides whatever the load order.
 */

:root {
  --panel-rail-width: 56px;
  /* Width of anything docked OUTBOARD of the shared slot — between the strip
     and the panels below. Zero for every panel here; the walkthrough sidebar
     sets it to its own width while it is open (js/tutorials/tutorials.css),
     which slides this dock inboard and indents the view for both at once.
     Every offset below folds it in, so a second outboard companion needs one
     declaration and no arithmetic of its own. */
  --panel-rail-outboard: 0px;
}

.panel-rail {
  display: none;
  position: fixed;
  inset: 0 0 0 auto;
  box-sizing: border-box;
  width: var(--panel-rail-width);
  /* Above the sticky topbar (30) and below the side panels (50) — the same
     sandwich the left rail sits in. */
  z-index: 45;
  flex-direction: column;
  align-items: center;
  overflow-x: hidden;
  overflow-y: auto;
  scrollbar-width: none;
  padding: 6px 0 10px;
  background: var(--daily-goals-bg, var(--card));
  border-left: 1px solid var(--border-strong);
}

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

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

html[data-panel-rail='on'] .app-shell {
  padding-right: calc(var(--panel-rail-width) + var(--panel-rail-outboard));
}

/* ── Room for an open panel ────────────────────────────────────────────── */

html[data-panel-rail='on'] .chat-panel {
  right: calc(var(--panel-rail-width) + var(--panel-rail-outboard));
  /* UNDER the strip, not over it. A panel is z-index 50 by default, above this
     rail's 45, so it opened by sliding across the icons and then stopping just
     past them — 56px of a card travelling over the control that closes it,
     every time. Below the rail it comes out from BEHIND the strip instead,
     which is what the geometry has been saying all along: the strip is the edge
     of the app and the panel lives inside it.
     40 keeps it above the sticky topbar (30); nothing else sits in 40-44. */
  z-index: 40;
  /* Decelerating curve — fast off the mark, settling into the dock rather than
     stopping dead. Paired with the shell's padding below so the view's edge and
     the panel's edge travel together; two different curves on one movement is
     what makes a drawer look like it is dragging the layout behind it. */
  transition: transform 220ms cubic-bezier(0.32, 0.72, 0, 1);
}

html[data-panel-rail='on'] .app-shell,
html[data-panel-rail='on'] .app-shell.app-shell-chat-open {
  /* padding-LEFT is the left rail's, at its own timing (styles/nav-rail.css and
     today-calendar-sidebar.css); it is restated because `transition` is a
     shorthand and would otherwise drop it. */
  transition:
    padding-left 180ms ease,
    padding-right 220ms cubic-bezier(0.32, 0.72, 0, 1);
}

/* Slide fully clear of the rail, not just of its own box — the panel is behind
   the strip now, but "behind an opaque strip" and "off screen" are different
   claims, and only one of them survives a translucent theme. See the header. */
html[data-panel-rail='on'] .chat-panel-hidden {
  transform: translateX(calc(100% + var(--panel-rail-width) + var(--panel-rail-outboard)));
}

html[data-panel-rail='on'] .app-shell.app-shell-chat-open {
  padding-right: calc(
    var(--chat-panel-width) + var(--panel-rail-width) + var(--panel-rail-outboard)
  );
}

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

.panel-rail-row {
  flex: 0 0 auto;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 42px;
  padding: 0;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  cursor: pointer;
  transition: color 120ms ease, background 120ms ease;
}

/* A gated-off panel hides its own toggle button and the rail hides the row with
   it. Must be restated: `display: flex` above outranks the UA `[hidden]` rule,
   so without this the row would stay on screen opening nothing. */
.panel-rail-row[hidden] {
  display: none;
}

.panel-rail-items {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  width: 100%;
}

.panel-rail-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  color: inherit;
}

/* Source-button icons are 16px; the rail draws them at the left rail's 20. */
.panel-rail-icon svg {
  width: 20px;
  height: 20px;
}

/* The row's name is its accessible name and its tooltip, never ink: the strip
   is icons only. Off screen rather than `display: none`, which would take it
   out of the accessibility tree along with the blocker's live count. */
.panel-rail-label {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

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

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

/* SELECTION is what the highlight means — not "a panel is on screen". The row
   the chevron acts on stays lit whether its panel is out or put away, including
   when you put it away by pressing this very row: minimising a panel is not
   picking a different one, and a highlight that dropped on the press would say
   the strip had forgotten which row you were working with.

   That leaves nothing for `.is-active` to add, and nothing is what it adds. The
   panel being on screen is already on screen, and the chevron above says which
   way it is about to travel; a second, louder highlight on the row would be a
   third statement of the same fact. It is kept as a hook — `aria-expanded` and
   `checks/panel_rail_check.mjs` both read it — with the two selectors written
   out separately so a future style for it has an obvious home. */
.panel-rail-item.is-selected {
  color: var(--accent);
  background: var(--utility-surface-strong);
  box-shadow: inset -3px 0 0 var(--accent);
}

.panel-rail-item.is-active {
  color: var(--accent);
}

/* Divides the chevron from the rows it acts on. A margin alone read as a gap in
   a strip that is already mostly gaps. */
.panel-rail-toggle {
  margin-bottom: 6px;
  padding-bottom: 0;
  border-bottom: 1px solid var(--border-strong);
  border-radius: 10px 10px 0 0;
}

/* The chevron is drawn pointing INWARD — at the middle of the screen, which is
   where the selected panel comes from. Once that panel is out, it turns around
   and points at the edge it is going back to. The rotation is on the icon, not
   the button, so the hit area and the divider above stay put. */
.panel-rail-toggle .panel-rail-icon {
  transition: transform 160ms ease;
}

.panel-rail[data-panel-open='true'] .panel-rail-toggle .panel-rail-icon {
  transform: rotate(180deg);
}

/* ── The buttons the rows press ────────────────────────────────────────── */

/* Every panel toggle stays in the DOM — its panel module looks it up by id and
   bails out if it is gone — but the rail is the only place you press one now,
   so the topbar copies are hidden while the rail is on screen. On a phone the
   attribute is absent, the rail is off, and these buttons are what
   `js/app-shell/nav_drawer.js` clicks. */
html[data-panel-rail] .panel-rail-source {
  display: none;
}
