﻿/* RAIL-01: the in-page tick rail. Three variables, three channels, as the owner approved 2026-10-28:
 *   brightness = distance from the reading position (JS writes --d, the step count);
 *   width      = how much the entry itself holds (build-time bucket w1…w4 from the card's character count);
 *   thickness  = structure (a head is 3px, a plain entry 2px), so the eye can find the chapter starts.
 *
 * Shared by the history page and the collegiate homepage and faculty page, which have different palettes and
 * different page margins, so everything page-specific arrives in variables the page sets on .rail itself:
 *   --rail-left   where the rail sits (each page computes it from its own margin token)
 *   --rail-mark   the 「当前位置」 colour (--mark on the inner pages, --accent on the collegiate ones)
 *   --rail-card-* the preview card's palette
 *   --rail-n      how many ticks are showing, so a long rail shortens its own step instead of overflowing
 *
 * Desktop pointer only: the preview card needs hover, and the ticks need a page margin to sit in. Each page sets its
 * own threshold, below which the rail is not rendered at all and the page's existing directory is the only one.
 */
.rail { display: none; }

@media (hover: hover) and (pointer: fine) {
  .rail {
    --rail-w: 74px;              /* the widest tick (w4) plus the 14px the current one grows by */
    --rail-gap: 18px;            /* clear space between the longest tick and the text column */
    --rail-n: 27;
    --rail-step: clamp(7px, calc(78vh / var(--rail-n)), 16px);
    position: fixed;
    left: var(--rail-left);
    top: 50%;
    transform: translateY(-50%);
    z-index: 30;
  }

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

  /* The link's accessible name, for screen readers only. The rail carries its own rule rather than relying on a
     page's .vh helper: the collegiate pages have no such class, and without this the titles render as visible text. */
  .rail .rail-name {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .rail li {
    --d: 9;
    display: block;
  }

  .rail a {
    display: flex;
    align-items: center;
    position: relative;
    height: var(--rail-step);    /* the step: the ticks read as one continuous scale, not as separate buttons */
    text-decoration: none;
    color: var(--rail-ink, var(--ink));
    opacity: max(.14, calc(1 - var(--d) * .11));
  }

  .rail-line {
    display: block;
    width: var(--w, 32px);
    height: 2px;
    border-radius: 1px;
    background: currentColor;
  }

  .rail .w1 { --w: 24px; }
  .rail .w2 { --w: 34px; }
  .rail .w3 { --w: 46px; }
  .rail .w4 { --w: 60px; }
  .rail .is-head .rail-line { height: 3px; }

  /* Current entry: full strength, in the page's own 「当前位置」 colour, and a touch longer so it reads as the centre. */
  .rail a[aria-current] {
    color: var(--rail-mark, var(--mark));
    opacity: 1;
  }
  .rail a[aria-current] .rail-line { width: calc(var(--w, 32px) + 14px); }

  /* Hover / keyboard focus: the whole rail steps back so the hovered tick and its card own the attention. */
  .rail:hover a { opacity: max(.1, calc(1 - var(--d) * .13)); }
  .rail a:hover, .rail a:focus-visible { opacity: 1; }
  .rail a:focus-visible { outline: 2px solid var(--rail-mark, var(--brand)); outline-offset: 3px; border-radius: 2px; }

  /* Preview card: title, then the entry's own words, clamped to three lines. Decoration for the pointer;
     the link's accessible name already carries the title, so the card is aria-hidden in the markup.
     Owner 2026-10-28: the card floats over the text column, as in the reference — do not narrow it or pull it
     back into the margin. Only the ticks must stay clear of the text; the card appears on hover and leaves with it. */
  .rail-card {
    position: absolute;
    left: calc(100% + 14px);
    top: 50%;
    transform: translateY(-50%) translateX(-4px);
    width: 280px;
    padding: 12px 14px;
    border-radius: 14px;
    background: var(--rail-card-bg, var(--ink));
    color: var(--rail-card-fg, var(--on-ink));
    box-shadow: 0 10px 28px rgba(23, 63, 54, .22);
    opacity: 0;
    visibility: hidden;
    transition: opacity .14s ease, transform .14s ease;
    pointer-events: none;
  }
  .rail a:hover .rail-card, .rail a:focus-visible .rail-card {
    opacity: 1;
    visibility: visible;
    transform: translateY(-50%) translateX(0);
  }

  .rail-t {
    display: block;
    font-family: var(--sans);
    font-size: 14px;
    font-weight: 700;
    line-height: 1.4;
  }
  .rail-m {
    display: block;
    font-family: var(--latin);
    font-size: 12px;
    color: var(--rail-card-meta, var(--on-ink-2));
  }
  .rail-b {
    margin-top: 6px;
    font-family: var(--sans);
    font-size: 13px;
    line-height: 1.55;
    color: var(--rail-card-meta, var(--on-ink-2));
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
  }

  /* Reduced motion: the card appears without sliding or fading. The collegiate pages' ?motion=off switch writes
     html[data-motion] from their own head script; the generated inner pages do not carry it, so there the OS
     preference is the only signal. Both are honoured wherever they exist. */
  @media (prefers-reduced-motion: reduce) {
    .rail-card { transition: none; transform: translateY(-50%); }
    .rail a:hover .rail-card, .rail a:focus-visible .rail-card { transform: translateY(-50%); }
  }
  html[data-motion="reduced"] .rail-card { transition: none; transform: translateY(-50%); }
  html[data-motion="reduced"] .rail a:hover .rail-card,
  html[data-motion="reduced"] .rail a:focus-visible .rail-card { transform: translateY(-50%); }
}

/* The history page (and any other page generated by sync_shell.py): the shell's --pad is the text column's margin.
   Below 1440px that margin cannot hold the ticks. */
@media (min-width: 1440px) and (hover: hover) and (pointer: fine) {
  .rail-inner {
    --rail-left: calc(var(--pad) - var(--rail-w) - var(--rail-gap));
    display: block;
  }
}

/* The collegiate homepage and faculty page: .wrap is a max-1600px column centred in the viewport, and its own
   --gutter padding sits inside it, so the text starts at (viewport - column) / 2 + gutter. That whole distance is
   the margin the ticks may use. Palette comes from those pages' own tokens (--accent is the 「当前位置」 colour
   there, as everywhere else on them).
   The faculty rail carries 76 ticks, so --rail-step (set from --rail-n in the base block) shortens accordingly. */
@media (min-width: 1440px) and (hover: hover) and (pointer: fine) {
  .rail-home, .rail-roster {
    /* Narrower buckets than the inner pages: at 1440px this margin is only the 72px gutter, and ticks sized for
       the inner pages' --pad would hang off the left edge. The ratios between the four buckets are kept. */
    --rail-w: 50px;
    --rail-gap: 14px;
    --rail-text: calc(max(0px, (100vw - 1600px) / 2) + var(--gutter));
    --rail-left: max(8px, calc(var(--rail-text) - var(--rail-w) - var(--rail-gap)));
    --rail-mark: var(--accent);
    --rail-card-bg: var(--ink);
    --rail-card-fg: var(--paper);
    --rail-card-meta: #cfc9c2;
    display: block;
  }
  .rail-home .w1, .rail-roster .w1 { --w: 16px; }
  .rail-home .w2, .rail-roster .w2 { --w: 23px; }
  .rail-home .w3, .rail-roster .w3 { --w: 31px; }
  .rail-home .w4, .rail-roster .w4 { --w: 40px; }
  .rail-home a[aria-current] .rail-line,
  .rail-roster a[aria-current] .rail-line { width: calc(var(--w, 24px) + 10px); }
}
