/* ─────────────────────────────────────────────────────────────────────────────
   THE LIBRARY DOCK — two vertical indexes of one page.

   Its own sheet, linked only by a library page, for the reason the rest of
   public/styles gives: area.css and brand-io.css are not supersets of one
   another, and adding rules to a shared sheet puts them on 72 pages whose
   cascade nobody re-measured.

   It borrows the floating control's tokens rather than restating them —
   --hc-bg, --hc-line, --hc-fg, --hc-acc — because the dock and the icon it
   opens from are one control in two shapes, and two sets of colours would make
   that a coincidence rather than a fact. hero-control.css declares them on
   `.hc`; they are declared again here because a custom property inherits from
   an ANCESTOR, and these two elements are siblings on <body>.
   ──────────────────────────────────────────────────────────────────────────── */

.vdock {
  --vd-bg: #0A0A0A;
  --vd-line: #272727;
  --vd-surf: #1C1C1C;
  --vd-fg: #FFFFFF;
  --vd-mut: #B4B4B4;
  --vd-sub: #7A7A7A;
  --vd-acc: #FF9013;
  --vd-w: 420px;
  --vd-gap: 22px;
  --vd-h: min(58vh, 520px);

  position: fixed;
  right: var(--vd-gap);
  bottom: var(--vd-gap);
  z-index: 121;
  width: min(var(--vd-w), calc(100vw - 32px));
  height: var(--vd-h);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--vd-line);
  border-radius: 16px;
  background: color-mix(in srgb, var(--vd-bg) 92%, transparent);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  box-shadow: 0 22px 50px -18px rgba(0, 0, 0, .78), 0 2px 10px rgba(0, 0, 0, .34);
  color: var(--vd-fg);
  font-family: var(--ui, system-ui, sans-serif);

  /* CLOSED IS THE DEFAULT, and it is the state the page loads in — see the
     script: the dock arrives on the first scroll, not on the hero.

     It travels by `transform` and fades by `opacity`, and it is
     `visibility:hidden` rather than `display:none` because display does not
     interpolate at all: dropped from the box tree there is nothing to animate
     from, and the panel would appear fully formed at the end of a transition
     that never ran. `visibility` is discrete but it is delayed, so it holds
     until the movement has finished. */
  visibility: hidden;
  opacity: 0;
  transform: translateY(14px) scale(.985);
  transform-origin: 100% 100%;
  transition:
    transform .42s cubic-bezier(.4, 0, .2, 1),
    opacity .3s cubic-bezier(.4, 0, .2, 1),
    visibility 0s linear .42s;
}

.vdock.is-open {
  visibility: visible;
  opacity: 1;
  transform: none;
  transition:
    transform .42s cubic-bezier(.4, 0, .2, 1),
    opacity .26s cubic-bezier(.4, 0, .2, 1),
    visibility 0s;
}

/* The folded control steps aside while the dock is open. Both park in the same
   corner, and two things there is one too many — so the icon is what you get
   when the index is closed, and the index is what you get when it is open. */
.hc.is-docked {
  opacity: 0;
  pointer-events: none;
  transition: opacity .24s cubic-bezier(.4, 0, .2, 1);
}

.vd-fold {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 2;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--vd-line);
  border-radius: 9px;
  background: var(--vd-surf);
  color: var(--vd-mut);
  cursor: pointer;
}
.vd-fold svg { width: 15px; height: 15px }
.vd-fold:hover { color: var(--vd-fg); border-color: #3A3A3A }

/* TWO COLUMNS, EQUAL. Neither index is the senior one: the sections say what
   the page is made of, the rows say what is inside them, and a reader arrives
   wanting either. `min-width:0` because a grid track's default `auto` minimum
   is its content, and one long prompt name would otherwise push its column
   wider than its share and squeeze the other. */
.vd-cols {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  /* minmax(0, 1fr) AND NOT 1fr. An implicit grid row is `auto`, which means
     "as tall as the content" — and the content here is three copies of a list
     that is deliberately longer than the panel. The row grew to 3,063px inside
     a 520px dock, `.vd-track` inherited a 3,063px height from it, and
     scrollHeight came out exactly equal to clientHeight: the columns did not
     scroll at all, because there was nothing to scroll. Nothing overflowed
     visibly either, so the only symptom was two dead lists. */
  grid-template-rows: minmax(0, 1fr);
  gap: 1px;
  background: var(--vd-line);
}
.vd-col {
  /* Both minimums, for the same reason and in both axes: a grid item's
     automatic minimum size is its content, so `min-width` keeps one long
     prompt name from widening its column past its share, and `min-height`
     lets the column be shorter than the list inside it. Without the second
     one the rule above cannot take effect. */
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--vd-bg);
}

.vd-hd {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 11px 12px 9px;
  border-bottom: 1px solid var(--vd-line);
  font-family: var(--io-mono, ui-monospace, monospace);
  font-size: 9.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--vd-sub);
}
.vd-hd b {
  font-weight: 500;
  padding: 1px 5px;
  border-radius: 5px;
  background: var(--vd-surf);
  color: var(--vd-mut);
}

/* THE VIEWPORT SCROLLS, and its scrollbar is hidden rather than styled: the
   column is driven by the page as often as by the pointer, and a bar that
   jumps about on its own is noise. It stays a real scroller — the wheel, a
   trackpad and a keyboard all still work on it. */
.vd-vp {
  flex: 1;
  min-height: 0;
  position: relative;
  /* The fade top and bottom is what says "this does not end" without drawing
     an arrow that would have to be kept in step with a strip that never runs
     out. It is a mask on the viewport, so it moves with neither. */
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 22px, #000 calc(100% - 22px), transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 22px, #000 calc(100% - 22px), transparent);
}
.vd-track {
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;   /* do not hand the page the wheel at the ends */
  scrollbar-width: none;
}
.vd-track::-webkit-scrollbar { width: 0; height: 0 }

.vd-i {
  display: flex;
  align-items: baseline;
  gap: 7px;
  padding: 7px 12px;
  text-decoration: none;
  color: var(--vd-mut);
  border-left: 2px solid transparent;
}
.vd-i:hover { color: var(--vd-fg); background: var(--vd-surf) }

.vd-n {
  flex: none;
  font-family: var(--io-mono, ui-monospace, monospace);
  font-size: 9px;
  letter-spacing: .06em;
  color: var(--vd-sub);
}
.vd-k {
  font-size: 11.5px;
  line-height: 1.32;
  /* Two lines, then an ellipsis. A prompt name that wraps to four turns the
     column into a paragraph and the index stops being scannable. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* WHERE THE PAGE IS. Set on every copy of the entry, not just the middle one,
   because all three are on screen at different moments and an index that
   highlights only one of them flickers as it wraps. */
.vd-i.on {
  color: var(--vd-fg);
  border-left-color: var(--vd-acc);
  background: color-mix(in srgb, var(--vd-acc) 9%, transparent);
}
.vd-i.on .vd-n { color: var(--vd-acc) }

/* At phone width there is no room for two columns beside a page. The dock
   spans the screen and the columns keep their pairing — halved, not stacked,
   because stacked they are two lists and the whole point is that they move
   against each other. */
@media (max-width: 560px) {
  .vdock {
    --vd-h: min(46vh, 340px);
    left: 16px;
    right: 16px;
    width: auto;
  }
  .vd-k { font-size: 11px }
}

/* A reader who has asked for less motion gets the index without the glide: it
   still arrives, still tracks the page, and does so by cutting rather than
   travelling. The script's own 260ms glide is short enough to read as a cut
   at this setting; what matters here is that nothing slides in from the
   corner. */
@media (prefers-reduced-motion: reduce) {
  .vdock,
  .vdock.is-open,
  .hc.is-docked { transition: none }
}
