/* glass-rail.css — the contents rail as an instrument.
 *
 * Dan, 2026-09-06, in substance: the side menu did not look like ours — not
 * ikonic, not the console grammar — and at the very least it should default
 * to collapsed. The default landed in the reading round; this is the rest of
 * the sentence.
 *
 * The grammar is the house's (docs/design/nested-rails.md, the magazine-rails
 * note beside it, and the desk's own `.rail` in styles.css):
 *
 *   ELBOW      the rail begins with a corner, not an edge. One block, rounded
 *              into the header, that says "the instrument starts here".
 *   RAILS      a vertical bar carries structure; a BOX around a row does not.
 *              Nothing here is a bordered card.
 *   ORDINALS   the number IS the address you say out loud, so it is set in
 *              display type at the left edge where the eye lands first.
 *   PILLS      a group head is a filled block with its count as an ordinal on
 *              the block — the house shape, which is a block with a number
 *              on it, not a word with a number beside it.
 *   ONE STRIP  Topics · Time · Gloss · Plain are four pills on one strip, not
 *              two rows of underlined words. They are the same kind of
 *              choice, so they are the same kind of control.
 *
 * WHAT IS NOT NEGOTIABLE, and why every rule below is a rule about painting:
 * `.toc-row`, `.toc-group`, `.toc-head`, `.toc-n`, `.ord`, `data-ch`,
 * `data-key`, `data-alt`, `--d` and `.toc-mode[data-mode|data-read]` are the
 * contract `glass.js` and every voice consumer read. `#toc .toc-row` in DOM
 * order is *what a visitor can see*. So this file changes how the rail LOOKS
 * and never what it IS — the markup glass-rail.js emits is untouched, and the
 * flat manual's rail is byte-identical below the header.
 */

/* ── the header, and the elbow ────────────────────────────────────────
 * A console panel opens with a corner. `#toc-side h3` is that corner: a
 * filled block whose outer edge is rounded into the frame, with the ◂ that
 * shuts the rail riding on it. It is not a caption above a list; it is the
 * top of the instrument, and the rail hangs from it. */
/* ── THE ELBOW IS ONE STROKE THAT TURNS ──────────────────────────────
 * Dan, 2026-09-07, on /getting-around: "better, but this design is missing
 * some important details on how the curves line up." The arm was a pill
 * BESIDE a bar. In the house grammar (docs/design/nested-rails.md) the
 * horizontal arm across the top runs into the CONTENTS block and turns down
 * into the rail's right-edge bar, and the three are ONE amber shape:
 *
 *   ONE THICKNESS   `--elbow-w` — the arm's own height. The block's arm side
 *                   and the leg it turns into are the same, so the stroke
 *                   never reads thinner in one place than another.
 *   OUTER RADIUS    `--elbow-R` (2x the stroke) on the corner the stroke
 *                   turns AROUND, and on the cap at its far end. Never a
 *                   square cut.
 *   INNER FILLET    `--elbow-r` (= the stroke) CUT OUT of the paper side
 *                   where the arm bends down — a concave curve, drawn as a
 *                   block of the ground colour with one rounded corner, so
 *                   the stroke bends rather than butts.
 *   BRANCHES        a nested group turns its own small elbow into the parent
 *                   bar, with the same fillet at reduced scale.
 */
/* the three tokens live on :root because the stroke does not belong to the
   rail alone — the arm across the top and the cap at the lamp end are the
   same stroke, drawn by glass-term.css */
:root {
  --elbow-w: 24px;
  --elbow-R: calc(var(--elbow-w) * 2);
  --elbow-r: var(--elbow-w);
}
#toc-side { padding-right: 0; }
#toc-side h3 {
  display: flex; align-items: center; justify-content: space-between;
  min-height: var(--elbow-w);
  margin: 0 0 0.55rem; padding: 0.42rem 0.5rem 0.42rem 0.7rem;
  font-family: var(--font-display); font-size: var(--fs-1); font-weight: 600;
  letter-spacing: var(--track-wide); text-transform: uppercase;
  color: var(--on-amber); background: var(--amber);
  /* the corner the stroke turns around, and the cap at its other end */
  border-radius: var(--elbow-R) 0 0 var(--elbow-R);
  position: relative;
}
/* the elbow's leg — the amber upright the whole rail hangs from, turning
   down the RIGHT end of the header band (Dan, 2026-09-07: "The colored bar
   should be on the right not the left so there is more continuity").
   Continuity with WHAT is the whole of it: with the paper. A bar down the
   left edge has the entire rail between it and the page it addresses; a bar
   down the right edge is flush against the paper and meets the header's
   amber band at the corner, so the two are ONE elbow around the contents
   rather than two ornaments. The rail's own right padding goes with it: the
   column's right edge IS the bar's edge, and nesting steps inward from there. */
#toc-side h3::after {
  content: ""; position: absolute; right: 0; top: 100%;
  width: var(--elbow-w); height: calc(var(--elbow-w) * 1.6);
  background: var(--amber);
  /* the outside of the turn keeps going; the inside is cut by the fillet */
  border-radius: 0 0 0 0;
}
/* THE CONCAVE FILLET — the inside of the turn, curved so the arm BENDS into
   the leg instead of butting against it. One block in the inner corner with
   its outer corner rounded away, and what shows through that corner is the
   ground: the same curve §13 describes as "a pseudo-element with a rounded
   corner in the ground colour", drawn from the stroke's side instead of the
   paper's. Drawn the other way it needs the corner over-filled with amber
   first and then covered — two elements, and a colour that has to match the
   ground exactly or the seam shows at every scheme change. One element, no
   seam, and the arc is the same arc. No image, no clip-path. */
#toc-side h3::before {
  content: ""; position: absolute; right: var(--elbow-w); top: 100%;
  width: var(--elbow-r); height: var(--elbow-r);
  background: var(--amber);
  border-bottom-left-radius: var(--elbow-r);
  pointer-events: none;
}
/* The ◂ rides ON the elbow, so it takes the elbow's ink. Two ids on purpose:
   glass-reading.css ships `.side h3 #toc-shut { color: var(--amber) }` and
   loads after this sheet — amber on amber is an invisible control. */
/* D-29 — 12x9px at 9.42px type is not a control. It is a 24px square on a
   desk (44 on a phone, in glass-phone.css) and the glyph inside it keeps its
   size: what grew is the thing a pointer has to hit, not the drawing. */
#toc-side h3 #toc-shut { color: var(--on-amber); cursor: pointer; float: none;
  font-size: 0.95em; line-height: 1; opacity: 0.8;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 24px; min-height: 24px; padding: 0; }
#toc-side h3 #toc-shut:hover { color: var(--on-amber); opacity: 1; }
#toc-side h3 #toc-shut:focus-visible { outline: 2px solid var(--void); outline-offset: 1px; }
/* the rail hangs from the elbow: one upright, on the paper's side of
   everything, continuing the leg the header dropped */
/* the rail hangs from the leg the block dropped: the stroke thins into the
   upright the rows branch off, and the two meet at the same right edge */
#toc { position: relative; padding-right: 0.55rem; }
#toc::before {
  content: ""; position: absolute; right: 0; top: 0; bottom: 0.4rem; width: 3px;
  background: var(--amber-deep); border-radius: 0 0 2px 2px;
}

/* ── one chip strip ───────────────────────────────────────────────────
 * Topics · Time · Gloss · Plain. Four pills, one strip, wrapping when the
 * rail is narrow — an instrument's mode row, not two lines of underlined
 * words. `.toc-modes-dot` was the separator between two pairs; pills do not
 * need one, so it becomes a thin rule that keeps the pairs legible. */
.toc-modes { display: inline-flex; align-items: center; gap: 0.2rem; margin: 0 0.2rem 0.45rem 0; }
.toc-modes + .toc-modes { margin-left: 0; }
/* a chip is 39-53px wide and was 16px tall — a word, not a control (D-21,
   D-23). The pill grows to 24px on a desk and 44 on a phone; the type does
   not, because the type is the rail's own scale. */
.toc-mode {
  font-family: var(--font-display); font-size: var(--fs-1); font-weight: 600;
  letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--muted); background: var(--raised); border: 0;
  display: inline-flex; align-items: center; min-height: 24px;
  padding: 0.16rem 0.55rem; border-radius: 999px; cursor: pointer; white-space: nowrap;
  transition: background var(--t-sweep) ease, color var(--t-sweep) ease;
}
.toc-mode:hover { color: var(--amber); }
.toc-mode.on { color: var(--on-cyan); background: var(--lavender); }
.toc-mode:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.toc-modes-dot { display: none; }

/* ── a group is a rail pill, its count an ordinal on the block ────────
 * The house shape is a BLOCK WITH A NUMBER ON IT. So the head is a filled
 * pill and `.toc-n` sits on it as the ordinal, rather than a tracked word
 * with a grey number floating to its right. The pill lights amber on the
 * path you are standing in — the same signal the rows use. */
.toc-group {
  display: flex; align-items: center; gap: 0.4rem; cursor: pointer;
  position: relative;              /* a pick badge rides the header it addresses */
  margin: 0.45rem 0 0.2rem; padding: 0.24rem 0.5rem 0.24rem 0.5rem;
  background: var(--raised);
  border-radius: var(--r-rail) 0 0 var(--r-rail);
  border-right: 3px solid var(--lavender-idle);
  font-family: var(--font-display); font-size: var(--fs-2); font-weight: 600;
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--lavender);
}
/* A BRANCH TURNS INTO THE PARENT BAR. §13: a nested group is a short
   horizontal that runs into the bar above it with the same concave fillet at
   reduced scale, so the hierarchy reads as branches of one stroke rather than
   as a stack of separate strips. `--d` is the depth the renderer emitted, so
   the stub reaches exactly one step out to its parent's bar, and the fillet
   is the elbow's own, a third of the size. */
.toc-group[style*="--d"]::after {
  content: ""; position: absolute; right: calc(-1 * 0.7rem); top: 0;
  width: 0.7rem; height: 3px; background: var(--lavender-idle);
}
.toc-group[style*="--d:0"]::after { display: none; }   /* the trunk turns into nothing */
.toc-group.here[style*="--d"]::after { background: var(--amber); }
.toc-group.open[style*="--d"]::after { background: var(--cyan); }
.toc-group.open.here[style*="--d"]::after { background: var(--amber); }
/* …and the curve where the branch meets the bar, at the branch's scale */
.toc-group[style*="--d"]::before {
  content: ""; position: absolute; right: calc(-1 * 0.7rem); top: 3px;
  width: calc(var(--elbow-r, 24px) / 3); height: calc(var(--elbow-r, 24px) / 3);
  background: inherit; border-bottom-right-radius: calc(var(--elbow-r, 24px) / 3);
  pointer-events: none;
}
.toc-group:hover { background: color-mix(in srgb, var(--lavender) 16%, var(--raised)); }
.toc-group.here { color: var(--amber); border-right-color: var(--amber);
  background: color-mix(in srgb, var(--amber) 14%, var(--raised)); }
.toc-group.open { border-right-color: var(--cyan); }
.toc-group.open.here { border-right-color: var(--amber); }
/* the glyph is the control: it takes focus and a screen reader says what it does */
.toc-tog { display: inline-block; color: inherit; cursor: pointer;
  font-size: 0.72em; line-height: 1; transition: transform var(--t-sweep) ease; }
.toc-tog:focus-visible, .toc-head:focus-visible { outline: 2px solid var(--amber);
  outline-offset: 1px; border-radius: 2px; }
.toc-group.open .toc-tog { transform: rotate(90deg); }
.toc-head { flex: 1; min-width: 0; }
.toc-head[data-ch]:hover { text-decoration: underline; }
/* the count, as an ordinal ON the block */
.toc-n {
  flex: none; font-family: var(--font-display); font-size: var(--fs-1); font-weight: 700;
  letter-spacing: var(--track-label);
  color: var(--on-cyan); background: var(--lavender-idle);
  padding: 0.06rem 0.42rem; border-radius: 999px; min-width: 1.6rem; text-align: center;
}
.toc-group.here .toc-n { background: var(--amber); color: var(--on-amber); }

/* ── a page row is a speakable address ────────────────────────────────
 * The ordinal is what you SAY ("open 34"), so it is display type at the left
 * edge, on the rail, where the eye lands. The row itself is a rail — an
 * upright and a title — never a box. Amber is the group you are in; cyan is
 * the page you are ON, and that row fuses into the paper: its right corners
 * square off and it crosses the gutter, so the menu opens into the page
 * rather than pointing at it. */
.toc-row {
  display: flex; align-items: baseline; gap: 0.55rem; cursor: pointer;
  color: inherit; text-decoration: none;
  padding: 0.26rem 0.55rem 0.26rem 0.5rem; font-size: var(--fs-3); line-height: 1.35;
  position: relative; border-right: 3px solid var(--amber-deep);
  border-radius: var(--r-rail) 0 0 var(--r-rail);
  transition: transform var(--t-sweep) ease, background var(--t-sweep) ease;
}
.toc-row:link, .toc-row:visited { color: inherit; text-decoration: none; }
/* the zebra cannot be counted in CSS once group headers sit between the rows
   — nth-of-type would stripe the headers too. The renderer, which knows what
   it drew, says which side of the stripe each row is on. */
.toc-row:nth-of-type(odd) { border-right-color: var(--amber); }
.toc-row[data-alt="0"] { border-right-color: var(--amber); }
.toc-row[data-alt="1"] { border-right-color: var(--amber-deep); }
.toc-row:hover { background: var(--raised); transform: translateX(-2px); }
/* the page you are ON needs no trick to reach the paper: with the bar on the
   right it is already against it. What was a negative margin and 1.4rem of
   padding — a row shoved across the gutter to point at the page — is the
   rail's own geometry now, so the cyan is the only thing that changes. */
.toc-row.now {
  background: var(--raised); border-right-color: var(--cyan);
  transform: none; z-index: 2;
}
/* the address must never wrap — "10 ·" breaking across two lines was what
   tightening the padding cost, and the ordinal IS the thing you say */
.toc-row .ord {
  flex: none; font-family: var(--font-display); font-weight: 700;
  font-size: var(--fs-2); letter-spacing: var(--track-label);
  color: var(--amber); min-width: 2.1rem; text-align: right; white-space: nowrap;
}
.toc-row.now .ord { color: var(--cyan); }
.toc-row.now > span:nth-child(2) { color: var(--fg); }
/* family tint on structure only — the signal colour always wins on now/hover */
.toc-row[data-family="library"] { border-right-color: var(--family-library); }
.toc-row[data-family="try"] { border-right-color: var(--family-time); }
.toc-row[data-family="system"] { border-right-color: var(--family-system); }
.toc-row[data-family].now { border-right-color: var(--cyan); }
.toc-row.pickable { outline: 1px solid var(--amber); }
/* NESTING STEPS THE BAR IN FROM THE RIGHT, and moves nothing else. A
   sub-menu used to be an indent — 0.7rem of left padding per level — which
   pushed the ordinal, the thing a reader says out loud, off its own edge one
   step at a time. With the bar on the paper's side the depth belongs there:
   each level's bar stands one step further from the paper, the nesting reads
   as the elbow's own grammar, and the titles and ordinals stay in one
   column. Only the taxonomy rail carries --d; a flat pack has none. */
.toc-group, .toc-row[style*="--d"] { margin-right: calc(var(--d, 0) * 0.7rem); }
/* the LIBRARY divider on the flat manual: a rail label, not a heading */
.toc-div { margin: 0.9rem 0 0.3rem; padding-right: 0.2rem; text-align: right;
  font-family: var(--font-display); font-size: var(--fs-1); font-weight: 600;
  letter-spacing: var(--track-wide); color: var(--lavender); text-transform: uppercase;
  border-right: 3px solid var(--lavender-idle); }
/* the day, at the row's end — the rail's own answer to "when was this" */
.toc-date { margin-left: auto; padding-left: 0.5rem; white-space: nowrap;
  font-family: var(--font-data); font-size: var(--fs-1); color: var(--muted); }

/* THE TAB IS THE STROKE'S OWN END, not a sliver on the far side of the page.
 * It was a 44x150 vertical strip fixed at the left edge at 34% height —
 * reading bottom-to-top, in a surface whose stroke now runs along the top and
 * down the RIGHT edge of the contents (round 7, §10). A second bar on the
 * opposite edge is what Dan's §13 screenshot calls a stray sliver.
 *
 * Shut, the contents live exactly where they live when open: the block at the
 * arm's left end. Same height as the stroke, same outer corner, same words —
 * so opening and shutting the rail moves nothing but the rail. */
#toc-tab { position: fixed; left: 0; top: 0; z-index: 95; writing-mode: horizontal-tb;
  display: inline-flex; align-items: center; gap: 0.15rem;
  font-family: var(--font-display); font-size: 0.72rem; font-weight: 600;
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--on-amber); background: var(--amber); border: none;
  border-radius: var(--elbow-R) 0 0 0; padding: 0 0.9rem; cursor: pointer;
  min-width: 44px; height: var(--elbow-w); text-align: left; }
/* …and the arm starts after it, the way it starts after the block when the
   rail is open (glass-term.css pushes it to 260px there) */
@media (min-width: 901px) {
  body.toc-shut:has(.omni-term[data-state="narrow"]) .omni-term[data-state="narrow"] { left: 172px; }
}
#toc-tab .tt-n { margin-inline-start: 0.5em; font-family: var(--font-data); font-size: 0.9em;
  letter-spacing: 0.04em; color: var(--on-amber); opacity: 0.8; }
/* the chevron points at the contents, which are one press away under it */
#toc-tab .tt-c { margin-inline-start: 0.5em; display: inline-block; font-size: 1.1em; line-height: 1; }
#toc-tab:hover { filter: brightness(1.08); }
#toc-tab:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
/* ONE pulse, on a first visit, and never again — glass-nearby.js writes the
 * key that says so. A reader who has already opened or shut the contents is
 * not told where they are. Motion that repeats is decoration, and this
 * surface does not carry decoration; this one says "the contents went here". */
@keyframes toc-tab-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(255, 176, 46, 0.55); }
  70%  { box-shadow: 0 0 0 14px rgba(255, 176, 46, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 176, 46, 0); }
}
#toc-tab.pulse { animation: toc-tab-pulse 1.6s ease-out 1; }
@media (prefers-reduced-motion: reduce) { #toc-tab.pulse { animation: none; } }
body:not(.toc-shut) #toc-tab { display: none; }   /* the rail is its own handle when open */

/* ── the phone: the chip shelf IS the rail ────────────────────────────
 * One horizontal strip that scrolls, so there is nothing to collapse and no
 * edge tab. The elbow would be a corner with nothing under it, so it stands
 * down and the head becomes a plain label. */
@media (max-width: 900px) {
  /* the phone's own stroke is drawn in glass-phone.css, which loads last and
     is where the shelf's furniture already lives */
  #toc-side h3::after { display: none; }
  .toc-group[style*="--d"]::after, .toc-group[style*="--d"]::before { display: none; }
  #toc { display: flex; gap: 0.45rem; overflow-x: auto; padding: 0 0 0.4rem;
    -webkit-overflow-scrolling: touch; }
  #toc::before { display: none; }
  .toc-row { flex: 0 0 auto; max-width: 15rem; background: var(--raised);
    border-radius: var(--r-rail) 0 0 var(--r-rail); padding: 0.35rem 0.5rem 0.35rem 0.6rem; }
  .toc-row span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .toc-row.now { border-right-color: var(--cyan); }
  /* D-21 — 59 of 60 phone targets were under 44x44: twelve group arrows at
     6x8px, "Art" at 27x12, the mode chips at 39x16. Every row, header and
     chip on the shelf is a 44px target now; the type is unchanged, so what
     grew is the reach and not the look. */
  .toc-row, .toc-group { min-height: 44px; align-items: center; }
  .toc-mode { min-height: 44px; padding: 0 0.8rem; }
  .toc-group { flex: 0 0 auto; margin: 0; align-self: center; }
  /* a shelf is one line: there is no column for a depth step to read against,
     so the chips sit level and each keeps its bar on its own paper side */
  .toc-group, .toc-row[style*="--d"] { margin-right: 0; }
  .toc-div { flex: 0 0 auto; align-self: center; margin: 0 0.3rem; white-space: nowrap;
    border-right: 0; padding-right: 0; text-align: left; }
  .toc-modes { margin-bottom: 0.35rem; }
}

/* ── the reading dot ──────────────────────────────────────────────────
 * A page you spent two minutes or more in carries one small mark after its
 * ordinal — its title says how long ("read 12 min"). It is INSIDE the .ord
 * span, not a sibling, because `#toc .toc-row > span:nth-child(2)` is how
 * every voice consumer finds the title on screen.
 *
 * It is drawn from the reader's own record (glass-memory.js) and only when
 * they asked for one. Cyan is where-you-are on this rail, so the dot is
 * lavender: it is a fact about the past, not a claim about the present. */
.mem-dot {
  display: inline-block; width: 5px; height: 5px; margin-left: 0.3rem;
  border-radius: 50%; background: var(--lavender); vertical-align: 0.15em;
}
.toc-row.now .mem-dot { display: none; }

/* ── a draft, on its rail row ─────────────────────────────────────────
 * Only the owner's own preview bake has these rows at all, so the mark is
 * not a warning — it is the answer to "which of these is not live yet".
 * Amber, the house's colour for a state you are IN, and after the title so
 * the recogniser still reads the page's own name at nth-child(2). */
.toc-row .toc-draft {
  margin-left: auto; padding-left: 0.5rem; white-space: nowrap;
  font-family: var(--font-display); font-size: var(--fs-1);
  letter-spacing: var(--track-label); color: var(--amber); }
.toc-row[data-draft] .ord { color: var(--amber); }
