/* glass-term.css — the desk's omni-terminal, dressed for a published glass.
 *
 * These rules are the desk's `styles.css` §omni-term and `omni.css` §dock,
 * SHIPPED AS ONE SHEET rather than copied into glass.html: the class names,
 * the token names and the state grammar are the desk's to the letter, so
 * "the same terminal" is a fact about the CSS and not a resemblance. What
 * is not here is what a glass has no elements for — `.term-tabs`, the
 * session cards, `ol.correction-alts` — because a glass has ONE session and
 * a strip of one tab would be a lie about the surface.
 *
 * Three sizes, one line:
 *   narrow  the present omni line, the reply, and nothing else
 *   half    46vh of log above the line (the desk's number)
 *   full    the terminal takes the page; body.term-full stands the stage down
 *
 * Layout note: the glass's <body> is the flex column (the desk has a
 * .frame), so `.omni-term` is a flex ITEM of the body and `.stage` is its
 * sibling. `body.term-full` is what hides the stage — a class the JS sets in
 * one place — rather than a sibling selector that would have to reach past
 * whatever the page grows next.
 */

/* ── the terminal ─────────────────────────────────────────────────────── */
.omni-term {
  display: flex; flex-direction: column;
  background: var(--void);
  border-bottom: 2px solid var(--amber);
  flex: 0 0 auto;
  min-height: 0;
  padding: 0.5rem 0 0.1rem;
}
.omni-term[data-state="half"] { flex: 0 0 46vh; padding-top: 0; }
.omni-term[data-state="full"] { flex: 1 1 auto; flex-basis: 0; padding-top: 0; }
body.term-full .stage,
body.term-full #toc-tab,
body.term-full #rail-tab { display: none; }
/* full is the terminal's page: a floating graph would be furniture on it */
body.term-full .viz.g3d-float { display: none; }

/* ── the log ──────────────────────────────────────────────────────────
 * Monospace, because it is a transcript of an exchange, not prose. `u` is
 * what you said, in the pack's own prompt; every other line is what the
 * glass answered, in the colour its kind has always had on the desk. */
.term-log {
  flex: 1; overflow: auto; padding: 0.5rem 1.1rem 0.3rem;
  font-family: var(--font-data); font-size: var(--fs-3); line-height: 1.55;
  color: var(--fg); white-space: pre-wrap; overflow-wrap: anywhere;
}
.term-log > div { margin: 0 0 0.1rem; }
.term-log .u { color: var(--cyan); margin-top: 0.5rem; }
.term-log .u:first-child { margin-top: 0; }
.term-log .err { color: var(--alert, #ff5d5d); }
.term-log .st { color: var(--muted); }
.term-log .hint { color: var(--amber); font-size: var(--fs-2); letter-spacing: var(--track-label); margin: 0.15rem 0 0.4rem; }
/* a search hit: indented under the answer it belongs to, with the same
   locator the hits box prints — the terminal quotes, it does not summarise */
.term-log .q { color: var(--fg); padding-left: 1.6rem; border-left: 2px solid var(--amber-deep);
  margin-left: 0.2rem; font-size: var(--fs-2); }
.term-log .qloc { display: block; font-family: var(--font-display); font-size: var(--fs-1);
  letter-spacing: var(--track-label); text-transform: uppercase; color: var(--lavender); }
/* one session, and the surface says so rather than drawing a strip of one tab */
#term-hint { padding: 0.35rem 1.1rem 0; font-family: var(--font-display); font-size: var(--fs-1);
  letter-spacing: var(--track-label); text-transform: uppercase; color: var(--muted); }
#term-hint[hidden] { display: none; }

/* ── the line ─────────────────────────────────────────────────────────
 * The desk's `#term-form`: a raised pill while the terminal is narrow, and
 * a flat bar with a rule above it once the log is on screen — so the line
 * reads as the bottom of the terminal rather than a box inside it. */
#omni-form {
  display: flex; gap: 0.5rem; align-items: center;
  margin: 0 1.1rem 0.15rem;
  padding: 0.4rem 0.7rem;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: 4px;
}
.omni-term[data-state="half"] #omni-form,
.omni-term[data-state="full"] #omni-form {
  margin: 0; border: 0; border-top: 1px solid var(--line); border-radius: 0;
  padding: 0.35rem 1.1rem 0.5rem; background: var(--void);
}
#omni-form .ps1 { font-family: var(--font-data); color: var(--amber); font-size: var(--fs-4);
  white-space: nowrap; user-select: none; }
#omni {
  flex: 1; min-width: 0;
  background: transparent; border: 0; outline: 0;
  color: var(--fg); font-family: var(--font-data); font-size: var(--fs-4);
  caret-color: var(--amber);
}
#omni::placeholder { color: var(--muted); }
#omni-form .chip {
  font-family: var(--font-display);
  background: var(--lavender);
  color: var(--on-cyan);
  border: 0;
  padding: 0.25rem 0.6rem;
  font-size: var(--fs-2);
  letter-spacing: 0.08em;
  cursor: pointer;
  text-transform: uppercase;
  border-radius: 2px;
}
#omni-form .chip:hover { filter: brightness(1.15); }
#omni-form .chip:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }

/* ── the dock ─────────────────────────────────────────────────────────
 * omni.css §dock: what the room said back, what it heard, and — on a glass
 * — the intro mark and the boundary meter riding at the far end. */
#omni-dock {
  display: flex;
  gap: 0.35rem 0.75rem;
  margin: -0.15rem 1.1rem 0.4rem;
  padding: 0.25rem 0.7rem 0.3rem;
  background: var(--raised);
  border: 1px solid var(--line);
  border-top: 0;
  border-radius: 0 0 4px 4px;
  align-items: center;
}
.omni-term[data-state="half"] #omni-dock,
.omni-term[data-state="full"] #omni-dock {
  margin: 0; border: 0; border-radius: 0; padding: 0.2rem 1.1rem 0.4rem; background: var(--void);
}
#omni-dock .ack { font-family: var(--font-display); font-size: var(--fs-3); color: var(--fg);
  text-align: left; flex: none; max-width: 62%; }
/* §12: the reply seat exists only while there is a reply. An empty row
   holding a stale sentence was the audit's D-16 — a status line that
   never cleared — and in narrow it also stole a row from the paper. */
#omni-dock .ack[hidden] { display: none; }
#omni-dock .live { font-size: var(--fs-2); color: var(--cyan); }
#omni-dock #voice-out { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#omni-dock #voice-out[hidden] { display: none; }
#omni-dock #glass-mark { margin-left: auto; }
#omni-dock #boundary-meter { flex: none; }

/* ── narrow: the thin arm of the same elbow (§12) ─────────────────────
 *
 * Dan, 2026-09-07, on two screenshots: "It shouldn't say 'terminal locked'
 * or 'terminal' etc. The omni should fit into the same curve as 'contents'
 * on the top bar, if collapsed, perhaps it's just a thin small thing at the
 * top. It doesn't necessarily have to be always present." And then: "It
 * shouldn't get in the way of the page, but it should make itself known as
 * an option", and "the collapsed form of the terminal should get out of the
 * way a bit more."
 *
 * So, collapsed: ONE row, ≤24px, overlaid at the top edge so the paper
 * keeps its full height; the same amber, radius and tracked face as
 * #toc-tab's elbow, so the two read as one instrument. The prompt is at the
 * left where the elbow turns and the lamp is at the far right — the mic is
 * the first-class control and typing is the quiet alternative, so the lamp
 * gets the corner your thumb reaches. Nothing else: no TERM chip, no
 * GLASS/OUT readouts, no example verbs. Those belong to half and full.
 */
.omni-term[data-state="narrow"] {
  position: fixed; top: 0; left: 0; right: 0; z-index: 94;
  padding: 0; background: color-mix(in srgb, #0b0f16 86%, transparent);
  backdrop-filter: blur(4px);
  border-bottom: 1px solid var(--amber-deep);
  /* THE ARM'S FAR END IS A CAP, not a cut (§13): the same outer radius the
     elbow turns around, at the end where the lamp sits. */
  border-radius: 0 0 var(--elbow-R, 24px) 0;
  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1);
}
.omni-term[data-state="narrow"] #omni-form {
  margin: 0; padding: 0 0.6rem 0 0.9rem; border: 0; border-radius: 0; background: none;
  /* 23 + the section's 1px amber rule = 24, which is the §9c addendum's
     ceiling for the whole bar. It measured 25 because the border was not
     counted (review M-3). */
  min-height: 23px; height: 23px; gap: 0.55rem;
}
/* prompt, then the line, then the lamp at the far right */
.omni-term[data-state="narrow"] #omni-form .ps1 { order: 1; font-size: var(--fs-2); opacity: 0.55; }
.omni-term[data-state="narrow"] #omni { order: 2; font-size: var(--fs-2); opacity: 0.72; }
.omni-term[data-state="narrow"] #voice-state { order: 3; margin-left: auto; opacity: 0.6;
  min-width: 2.2rem; text-align: center; }
/* …and the whole arm comes up to full strength the moment it is pointed at */
.omni-term[data-state="narrow"]:hover #omni-form > *,
.omni-term[data-state="narrow"]:focus-within #omni-form > * { opacity: 1; }
.omni-term[data-state="narrow"] #omni:focus { opacity: 1; }
/* 2px, like every other control on this surface — D-30 was met at 1 (M-2) */
.omni-term[data-state="narrow"] #omni:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
/* the chrome that belongs to half and full only */
.omni-term[data-state="narrow"] #term-btn,
.omni-term[data-state="narrow"] #term-close,
.omni-term[data-state="narrow"] #omni-dock,
.omni-term[data-state="narrow"] #term-hint { display: none; }
/* ── one continuous line: the elbow's arm IS the omni (§12 addendum) ───
 * Dan, 2026-09-07, annotating a screenshot: the collapsed omni was a strip
 * of its OWN across the top and the rail's amber CONTENTS block a second
 * horizontal line 30px under it — two bars where the brief asks for one
 * instrument. So the CONTENTS block turns the corner at y=0 and the omni
 * runs on from its right edge: one 24px band, contiguous in x, nothing above
 * it, and the site title below it.
 *
 * Desktop only. On a phone the rail is a chip shelf and its head is already
 * a plain label (glass-rail.css), so the omni's own full-width bar at the
 * top of the shelf is the one line, and there is no second strip to merge.
 *
 * `.stage` is `260px 1fr`, so 260px is where the paper starts and where the
 * omni must start with it. Scoped to :has(narrow) because half and full are
 * a sheet over the top edge, and an amber block fixed above one would be a
 * bar floating over the terminal. */
@media (min-width: 901px) {
  body:has(.omni-term[data-state="narrow"]):not(.toc-shut) #toc-side h3 {
    position: fixed; top: 0; left: 0; width: 260px; height: var(--elbow-w); z-index: 94;
    margin: 0; padding: 0 0 0 0.9rem; box-sizing: border-box;
    /* the outer corner of the whole stroke: the arm comes in from the right,
       runs into this block and turns down at its far end (§13) */
    border-radius: var(--elbow-R) 0 0 0;
    transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1);
  }
  /* THE LEG DROPS AT THE BLOCK'S RIGHT END. It was pinned to `left: 0.9rem`
     when the rail's colour bar was on the left; round 7 moved that bar to the
     right edge and this override stayed behind, so the arm dropped a stray
     amber sliver at the far left of the screen with nothing under it — the
     "second bar at x = 0" in Dan's §13 screenshot. The leg belongs where the
     rail's own upright is, which is the block's right end. */
  body:has(.omni-term[data-state="narrow"]):not(.toc-shut) #toc-side h3::after { left: auto; right: 0; }
  body:not(.toc-shut) .omni-term[data-state="narrow"] { left: 260px; }
  /* …and the two tuck together, or the amber block would sit on alone */
  body:has(.omni-term[data-state="narrow"][data-lip="1"]):not(.toc-shut) #toc-side h3 {
    transform: translateY(calc(-100% + 6px)); }
  body:has(.omni-term[data-state="narrow"][data-lip="1"]:hover):not(.toc-shut) #toc-side h3 {
    transform: none; }
}

/* the lip: 6px of amber at the top edge, which is also the pull handle */
.omni-term[data-state="narrow"][data-lip="1"] { transform: translateY(calc(-100% + 6px)); }
.omni-term[data-state="narrow"][data-lip="1"]:hover { transform: none; }
@media (prefers-reduced-motion: reduce) { .omni-term[data-state="narrow"] { transition: none; } }
/* The arm overlays the top edge, so the rails start below it — the
   CONTENTS head was being drawn behind the prompt. The paper needs no
   such offset: its first line is a masthead the reader scrolls past, and
   the bar tucks to its lip the moment they do. */
.omni-term[data-state="narrow"] ~ .stage .side { padding-top: 30px; }
/* one breath, on a first visit, and never again — the same law as #toc-tab's
   single pulse: motion that repeats is decoration, and this surface carries
   none. This one says "the mic is here". */
@keyframes omniBreathe {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 176, 46, 0); }
  45%      { box-shadow: 0 0 0 7px rgba(255, 176, 46, 0.35); }
}
#voice-state.breathe { animation: omniBreathe 2.2s ease-in-out 1; }
@media (prefers-reduced-motion: reduce) { #voice-state.breathe { animation: none; } }

/* ── × close  esc (§9c/§15) ───────────────────────────────────────────
 * "plus an easy to close terminal", and "it should be clear from the
 * terminal that hitting escape closes it". Always visible in half and full,
 * ≥44px, at the top-right corner, with the key beside it in the data face.
 */
.term-close {
  position: absolute; top: 0; right: 0; z-index: 3;
  min-width: 44px; min-height: 44px; padding: 0.3rem 0.8rem;
  display: inline-flex; align-items: center; gap: 0.45rem;
  font-family: var(--font-display); font-size: var(--fs-2); letter-spacing: var(--track-label);
  text-transform: lowercase; color: var(--amber);
  background: var(--raised); border: 1px solid var(--amber); border-top: 0; border-right: 0;
  border-radius: 0 0 0 6px; cursor: pointer;
}
.term-close kbd { font-family: var(--font-data); font-size: 0.85em; color: var(--fg);
  background: #0b0f16; border: 1px solid var(--line); border-radius: 3px; padding: 0.05rem 0.35rem; }
.term-close:hover { background: var(--amber); color: #0b0f16; }
.term-close:hover kbd { color: var(--fg); }
.term-close:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.omni-term { position: relative; }

/* ── the phone ────────────────────────────────────────────────────────
 * Narrow only, and the log opens as full (glass-term.js `phone`): 46vh of
 * transcript over a 390px page is neither the page nor the terminal. */
@media (max-width: 900px) {
  .omni-term { padding-top: 0.35rem; }
  /* On a phone the BODY scrolls (glass.html sets height:auto there), so a
   * flex-grown terminal grows to nothing — measured at 4px. Full is a fixed
   * sheet over the page instead, which is what "takes the page" means when
   * the page is taller than the viewport. */
  .omni-term[data-state="full"] {
    position: fixed; inset: 0; z-index: 95;
    flex: none; height: 100%; padding-top: 0;
    background: var(--void); border-bottom: 0;
  }
  /* A phone HAS a half (audit D-02: the old build heard "half" and gave
     `full`, and the article was gone for the rest of the session). Same
     sheet, half the height, the paper still visible under it — which is the
     whole point of asking for a half. */
  .omni-term[data-state="half"] {
    position: fixed; top: 0; left: 0; right: 0; bottom: auto; z-index: 95;
    flex: none; height: 52vh; padding-top: 0;
    background: var(--void); border-bottom: 2px solid var(--amber);
  }
  #omni-form { margin: 0 0.5rem 0.15rem; padding: 0.35rem 0.5rem; gap: 0.35rem; }
  /* 16px LITERALLY, not a step on the scale. iOS Safari auto-zooms any input
     whose computed size is under 16px on focus; the threshold is an absolute
     px in the platform, so a token that later moved would take the bug back.
     The alternative — `maximum-scale=1` in the viewport — stops the zoom by
     stopping every visitor from zooming anything, which is not a trade we
     make. The prompt matches so the line reads as one thing. */
  #omni-form .ps1 { font-size: 16px; }
  #omni { font-size: 16px; }
  /* …including the collapsed arm, whose narrow rules are more specific */
  .omni-term[data-state="narrow"] #omni-form .ps1,
  .omni-term[data-state="narrow"] #omni { font-size: 16px; }
  /* 23 + the rule = 24 here too: a phone's arm is not allowed to be taller
     than a desktop's (review M-3). 16px type still fits a 23px row. */
  .omni-term[data-state="narrow"] #omni-form { min-height: 23px; height: 23px; }
  /* I-9: a phone has no Escape key, so it is never shown one. The × and a
     swipe up are what close it there, and the hint row says the same. */
  .term-close kbd { display: none; }
  /* I-8: a flash is a tap target (a tap dismisses it), so it gets 44 here —
     with padding, not `display:flex`, which would drop the two-line clamp. */
  .flash { min-height: 44px; box-sizing: border-box; padding-top: 0.7rem; padding-bottom: 0.7rem; }
  #omni-dock { margin: -0.15rem 0.5rem 0.35rem; flex-wrap: wrap; row-gap: 0.2rem; }
  #omni-dock .ack { flex: 1 1 100%; max-width: none; font-size: var(--fs-2); }   /* the reply takes its own row and wraps */
  .term-log { padding: 0.4rem 0.6rem 0.2rem; }
  #term-hint { padding: 0.3rem 0.6rem 0; }
}

/* §10: Home's way-in line, in the resume line's own family — same weight,
   same amber, and it sits above it because the author's guide comes before
   where you happened to stop. */
.start-here { margin: 0.6rem 0 0.2rem; font-family: var(--font-display); font-size: var(--fs-2); }
.start-here a { color: var(--amber); text-decoration: none; border-bottom: 1px solid transparent; }
.start-here a:hover, .start-here a:focus-visible { border-bottom-color: var(--amber); }

/* ── the grammar, as a list you can click (§13) ───────────────────────
 * Dan, 2026-09-07: "Here, clicking around is going to be one of the primary
 * ways to get around." The prompt is the control and this is what it drops:
 * sentences, not features, so using it teaches the grammar. Anchored under
 * the omni's left edge, in the elbow's family, with 44px rows.
 */
.omni-menu {
  position: fixed; top: calc(var(--omni-h, 28px) + 2px); left: 0.6rem; z-index: 97;
  min-width: 15rem; max-width: min(22rem, calc(100vw - 1.2rem));
  padding: 0.25rem;
  background: #0b0f16; border: 1px solid var(--amber); border-top: 0;
  border-radius: 0 0 6px 6px; box-shadow: 0 10px 28px rgba(0, 0, 0, 0.6);
  display: flex; flex-direction: column;
}
.omni-menu[hidden] { display: none; }
.menu-item {
  display: flex; flex-direction: column; gap: 0.05rem; align-items: flex-start;
  min-height: 44px; padding: 0.35rem 0.7rem;
  background: none; border: 0; border-radius: 3px; cursor: pointer; text-align: left;
  font: inherit; color: var(--fg);
}
.menu-item .mi-say { font-family: var(--font-display); font-size: var(--fs-2);
  letter-spacing: var(--track-label); color: var(--cyan); }
.menu-item .mi-hint { font-size: var(--fs-1); color: var(--muted); }
.menu-item:hover, .menu-item.on { background: var(--raised); }
.menu-item:hover .mi-say, .menu-item.on .mi-say { color: var(--amber); }
.menu-item:focus-visible { outline: 2px solid var(--amber); outline-offset: -2px; }
/* the prompt is a control, and it says so on hover */
#term-ps1 { cursor: pointer; border-radius: 3px; }
#term-ps1:hover { color: var(--fg); background: var(--raised); }
#term-ps1:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
@media (max-width: 900px) { .omni-menu { left: 0.3rem; right: 0.3rem; max-width: none; } }

/* ── 44px, even where the chrome is 20 (audit D-21) ───────────────────
 * A control's TARGET and its picture are not the same thing. The collapsed
 * arm is 24px on purpose (§9c) and the chips are small because they are
 * quiet, but a finger needs 44px either way — so the target is grown with a
 * transparent box around the control rather than by making the control
 * bigger. Nothing here changes what anything looks like.
 */
#voice-state, #term-btn, #glass-mark, #term-ps1, .colo-copy, .hit-more { position: relative; }
#voice-state::before, #term-btn::before, #glass-mark::before, #term-ps1::before, .colo-copy::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: max(100%, 44px); height: max(100%, 44px);
  transform: translate(-50%, -50%);
}
/* the notes tab is a page-level control and has the room to just be 44 */
body #rail-tab { min-width: 44px; text-align: center; }

/* ── the live filter (§14) ────────────────────────────────────────────
 * Dan, 2026-09-07: "omni should feel a little bit more like another way to
 * search the toc on the left." The rail and the omni are one set of pages,
 * so typing in one moves the other: rows that do not match go, groups with
 * nothing left go, and the counts say what is actually there. The match
 * itself is marked in the same amber the ordinals use, because the omni's
 * input and the rail's chips are one family.
 */
#toc .toc-row.f-off, #toc .toc-group.f-off { display: none; }
#toc .toc-row.f-hit.kb-on { outline: 1px solid var(--amber); outline-offset: -1px; }
.f-mark { background: color-mix(in srgb, var(--amber) 30%, transparent); color: inherit;
  border-radius: 2px; padding: 0 0.1em; }
/* the nearby strip dims rather than disappears: it is a map of where you
   are, and holes in a map are worse than dim marks on one */
.nearby [data-ch].f-off { opacity: 0.28; }
.nearby [data-ch].f-hit { outline: 1px solid var(--amber); outline-offset: 1px; }
body.filtering .omni-term[data-state="narrow"] #omni-form > * { opacity: 1; }

/* ── the results, inside the terminal (§9a) ──────────────────────────
 * The same rows the page's panel draws, in the terminal's own scrolling
 * body. It takes the room and the log keeps a share of it: the transcript
 * is what tells you WHICH question these ten answer.
 */
.term-hits { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 0.5rem 1.1rem 0.3rem; }
.term-hits[hidden] { display: none; }
/* The results take the terminal's body while they are up. 46vh shared
   between ten rows and a transcript gave neither enough room to be read —
   the log's lines were landing on top of row 2. The transcript is one Esc
   away, and it comes back the moment the results are closed. */
.omni-term:has(> .term-hits:not([hidden])) > .term-log { display: none; }
.term-hits .hit-q pre.code { max-width: 100%; }
.term-hits h3 { margin: 0 0 0.5rem; font-family: var(--font-display); font-size: var(--fs-1);
  letter-spacing: var(--track-wide); text-transform: uppercase; color: var(--amber); font-weight: 600; }
/* ordinal · locator · title on ONE line: glass.html's `.hit .src` is a block
   (it is a card's kicker there), which broke the head in two here. */
/* the count line, in the panel's own head — where the flash used to be, over
   the rows it counts (re-review New-2). It scrolls with the answer, it is
   selectable and copyable (D-32), and it takes the panel's room, not the
   paper's. */
.hits .hit-cap { font-family: var(--font-display); font-size: var(--fs-1); color: var(--fg);
  line-height: 1.45; margin: 0.1rem 0 0.5rem; max-width: 62ch; }
.hits .hit-head .src { display: inline; }
.hits .hit-head { line-height: 1.5; margin-bottom: 0.25rem; }
.hits .hit-a { font-family: var(--font-display); color: var(--cyan); text-decoration: none;
  border-bottom: 1px solid transparent; }
.hits .hit-a:hover, .hits .hit-a:focus-visible { border-bottom-color: var(--cyan); }
.hits .hit-n { font-family: var(--font-display); color: var(--amber); font-weight: 600; }
.hits .hit-also { font-family: var(--font-display); font-size: var(--fs-1);
  letter-spacing: var(--track-label); text-transform: uppercase; color: var(--muted); margin-top: 0.3rem; }
/* every row is a tap target, not a line of text (audit D-21) */
/* ── the found sky (§18) ──────────────────────────────────────────────
 * Under the list, in the same panel, so it is the same answer at two scales.
 * Its height is a CONSTANT: a layout change must never reflow the paper
 * under it (graph fix §5), and "bigger"/"smaller" is the reader asking, not
 * the picture deciding.
 */
.found-sky {
  margin: 0.6rem 0 0.2rem; padding-top: 0.5rem;
  border-top: 1px solid color-mix(in srgb, var(--amber) 30%, transparent);
  /* §18: "it appears after the list … the list stays scrollable above it".
     Under ten rows of quoted paragraphs that is three thousand pixels down,
     which is a picture nobody sees. Sticky is that sentence made literal: the
     sky holds the bottom edge while the rows run past it, and it takes its own
     box in the flow, so nothing reflows when it arrives or goes. */
  position: sticky; bottom: 0; z-index: 2;
  background: color-mix(in srgb, var(--amber) 7%, #0b0f16);
}
.found-sky[hidden] { display: none; }
.found-sky .fs-svg { display: block; width: 100%; max-width: 760px; margin: 0 auto; height: 220px; touch-action: none; cursor: grab; }
.found-sky[data-size="big"] .fs-svg { height: 360px; }
.found-sky .fs-svg:active { cursor: grabbing; }
.found-sky .fs-e { stroke: color-mix(in srgb, var(--amber) 34%, transparent); stroke-width: 0.4; }
.found-sky .fs-n { cursor: pointer; }
.found-sky .fs-n circle { stroke: #0b0f16; stroke-width: 0.5; }
.found-sky .fs-near circle { opacity: 0.55; }
/* the page you are ON is the brightest thing here (graph §1, M-2) */
.found-sky .fs-here circle { stroke: var(--amber); stroke-width: 1.4; opacity: 1; }
.found-sky .fs-here .fs-l { font-weight: 700; fill: var(--amber); }
.found-sky .fs-focus circle { stroke: var(--fg); stroke-width: 1.4; }
/* …and what the focused row is joined to is lit, not merely present (I-3) */
.found-sky .fs-lit circle { stroke: color-mix(in srgb, var(--fg) 70%, transparent); stroke-width: 0.9; }
.found-sky .fs-lit .fs-l, .found-sky .fs-focus .fs-l { fill: var(--fg); }
.found-sky .fs-n:focus-visible { outline: none; }
.found-sky .fs-n:focus-visible circle { stroke: var(--amber); stroke-width: 1.4; }
.found-sky .fs-o { font-family: var(--font-display); font-size: 4.4px; font-weight: 700;
  fill: var(--amber); text-anchor: middle; }
.found-sky .fs-l { font-family: var(--font-display); font-size: 4px; fill: var(--fg);
  text-anchor: middle; }
/* the timeline says it is one (I-7) */
.found-sky .fs-axis { stroke: color-mix(in srgb, var(--amber) 55%, transparent); stroke-width: 0.4; }
.found-sky .fs-ax { font-family: var(--font-data); font-size: 3.6px; fill: var(--muted); }
.found-sky .fs-ax-r { text-anchor: end; }
/* graph §7 / I-4: the colour never carries the topic alone */
.found-sky .fs-keys { display: flex; flex-wrap: wrap; gap: 0.15rem 0.7rem; margin: 0.3rem 0 0; }
.found-sky .fs-key { display: inline-flex; align-items: center; gap: 0.3rem;
  font-family: var(--font-display); font-size: var(--fs-1); letter-spacing: var(--track-label);
  text-transform: uppercase; color: var(--muted); }
.found-sky .fs-key i { width: 0.55rem; height: 0.55rem; border-radius: 50%; display: inline-block; }
/* the chips print the phrases the grammar answers — one table, two doors */
.found-sky .fs-chips { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-bottom: 0.4rem; }
.found-sky .fs-chip { min-height: 44px; padding: 0.2rem 0.6rem; cursor: pointer;
  font-family: var(--font-display); font-size: var(--fs-1); letter-spacing: var(--track-label);
  text-transform: uppercase; color: var(--amber); background: transparent;
  border: 1px solid color-mix(in srgb, var(--amber) 45%, transparent); border-radius: 3px; }
.found-sky .fs-chip.on { background: var(--amber); color: #0b0f16; }
.found-sky .fs-chip:hover { border-color: var(--amber); }
.found-sky .fs-chip:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.found-sky .fs-rule { margin: 0.15rem 0 0; font-family: var(--font-display);
  font-size: var(--fs-1); letter-spacing: var(--track-label); color: var(--muted); }
@media (max-width: 900px) {
  .found-sky .fs-svg { height: 200px; max-width: none; }
  /* the label's own size is computed from the measured box and set on the
     element (glass-found-sky.js labelSize) so it lands on the app's 11 CSS px
     floor whatever the scale; this is only the fallback. The ordinal is a
     numeral and gets the same treatment by hand. */
  .found-sky .fs-o { font-size: 7.5px; }
  .found-sky .fs-ax { font-size: 6px; }
  /* M-9: twelve chips took five rows and 200px — more of the phone than the
     picture they label. One row that scrolls, like the contents shelf. */
  .found-sky .fs-chips { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
    padding-bottom: 0.2rem; }
  .found-sky .fs-chip { flex: 0 0 auto; }
}

/* the fold (§16): one row per page, and the rest of that page's sections
   named under it. The line is a control — it prints the phrase that opens
   it, so the words a reader says and the words they tap are the same. */
.hits .hit-fold { min-height: 44px; display: flex; align-items: center; cursor: pointer;
  margin-top: 0.35rem; padding: 0.2rem 0.1rem;
  font-family: var(--font-display); font-size: var(--fs-1); letter-spacing: var(--track-label);
  color: var(--amber); border-top: 1px solid color-mix(in srgb, var(--amber) 30%, transparent); }
.hits .hit-fold:hover { color: var(--fg); }
.hits .hit-fold:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.hits .hit-sub { min-height: 44px; cursor: pointer; margin: 0.35rem 0 0 0.9rem;
  padding: 0.3rem 0.6rem; border-left: 2px solid color-mix(in srgb, var(--amber) 45%, transparent);
  background: color-mix(in srgb, var(--raised) 70%, transparent); border-radius: 2px; }
.hits .hit-sub:hover { border-left-color: var(--amber); }
.hits .hit { min-height: 44px; cursor: pointer; }
.hits .hit-more { min-height: 44px; display: flex; align-items: center; cursor: pointer; }
/* The contents elbow is fixed at 34% of the viewport, which is INSIDE a
   half-open terminal — the two elbows were drawn on top of each other. It
   starts below whatever the omni currently is. */
body #toc-tab { top: max(34%, calc(var(--omni-h, 0px) + 1.2rem)); }

/* ── the flash ────────────────────────────────────────────────────────
 * §9c. One line of news over the top edge, in the elbow's own family. It
 * is `position: fixed` for one reason that matters more than the look: a
 * flash must take NO layout room. The paper does not reflow for news, so
 * the line the reader was on stays where it was — which is the whole point
 * of not growing the terminal for a hit count.
 *
 * Two lines is the ceiling, enforced here rather than by trusting callers:
 * "a flash never carries a passage". Anything longer belongs in the hits
 * panel, which has room and a scrollbar.
 */
.flash {
  position: fixed; left: 0; right: 0; z-index: 96;
  top: calc(var(--omni-h, 28px) + 2px);
  margin: 0 auto; width: fit-content; max-width: min(46rem, calc(100vw - 2rem));
  padding: 0.4rem 0.9rem;
  background: color-mix(in srgb, var(--amber) 14%, #0b0f16);
  border: 1px solid var(--amber); border-top: 0; border-radius: 0 0 5px 5px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.55);
  font-family: var(--font-display); font-size: var(--fs-2); line-height: 1.4;
  letter-spacing: 0.01em; color: var(--fg);
  cursor: pointer;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  animation: flashIn 0.18s ease-out;
}
.flash[hidden] { display: none; }
.flash.flash-miss { border-color: var(--alert, #ff5d5d);
  background: color-mix(in srgb, var(--alert, #ff5d5d) 12%, #0b0f16); }
@keyframes flashIn { from { transform: translateY(-6px); opacity: 0; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .flash { animation: none; } }
@media (max-width: 900px) { .flash { max-width: calc(100vw - 1rem); font-size: var(--fs-1); } }

/* ── the colophon ─────────────────────────────────────────────────────
 * The page's own footer, at the end of the paper (glass-foot.js says why it
 * is there and not after .stage). Magazine furniture: one rule above, small
 * tracked display heads, three columns where there is room and a stack
 * where there is not. Nothing in it competes with the page — it is the last
 * thing you read, not the first.
 *
 * It lives in this sheet because it is the same furniture layer as the
 * terminal: both are the glass's chrome, both are the desk's grammar, and
 * both ship as one file the kit copies.
 */
.colophon {
  margin: 3.5rem 0 0;
  padding: 1.4rem 0 2.2rem;
  border-top: 2px solid var(--amber-deep);
  /* Flex, not auto-fit grid: auto-fit makes as many tracks as FIT, so four
     columns on a 1355px paper became five with one empty and four squeezed.
     Flex makes exactly as many columns as there are things to say. */
  display: flex; flex-wrap: wrap; gap: 1.2rem 2.2rem; align-items: flex-start;
}
.colophon[hidden] { display: none; }
.colo-col { flex: 1 1 15rem; min-width: 0; max-width: 26rem; }
.colo-col h4 {
  margin: 0 0 0.5rem;
  font-family: var(--font-display); font-size: var(--fs-1); font-weight: 600;
  letter-spacing: var(--track-wide); text-transform: uppercase; color: var(--amber);
}
.colo-col p { margin: 0 0 0.4rem; font-size: var(--fs-2); line-height: 1.5; color: var(--fg); }
.colo-col .colo-law { color: var(--muted); font-size: var(--fs-1); line-height: 1.45; }
/* D-29 — the colophon's links measured 15-18px tall: "Published with
   Ikonic" 109x15, the law line 332x15, "Atom feed" 53x15. They work, and a
   thumb still misses them. The padding is on the INLINE box, so the words
   stay where they are in the sentence and the box a pointer hits is 24px on
   a desk and 44 on a phone. */
.colo-a { display: inline-block; padding-block: 0.32rem; }
.colo-a { color: var(--cyan); text-decoration: none; border-bottom: 1px solid transparent; }
.colo-a:hover { border-bottom-color: var(--cyan); }
.colo-a.colo-quiet { color: var(--muted); }
.colo-a.colo-quiet:hover { color: var(--cyan); border-bottom-color: var(--cyan); }
/* the feed address: it exists to be copied, so it is monospace and it wraps
   rather than truncating — a half-shown address is not an address */
.colo-feed { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.colo-feed code { font-family: var(--font-data); font-size: var(--fs-1); color: var(--cyan);
  background: var(--raised); padding: 0.15rem 0.4rem; border-radius: 3px; overflow-wrap: anywhere; }
.colo-copy { font-family: var(--font-display); font-size: var(--fs-1); letter-spacing: var(--track-label);
  text-transform: uppercase; color: var(--on-cyan); background: var(--lavender);
  border: 0; border-radius: 2px; padding: 0.15rem 0.5rem; cursor: pointer; }
.colo-copy:hover { filter: brightness(1.15); }
.colo-copy:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.colo-col p.colo-quiet { color: var(--muted); font-size: var(--fs-1); }
.colo-col p.colo-quiet em { font-style: normal; color: var(--amber); }
/* Tools & offers: cards, because each is a separate thing you might want —
   the title is the link, the price rides it, the author's sentence follows.
   No button, no cart: the link goes where they sell and this page stops. */
.colo-offer { padding: 0.4rem 0 0.4rem 0.6rem; margin-bottom: 0.4rem;
  border-left: 2px solid var(--lavender-idle); }
.colo-offer[data-kind="service"] { border-left-color: var(--cyan); }
.colo-offer[data-kind="package"] { border-left-color: var(--amber); }
.colo-otitle { margin: 0 0 0.15rem !important; }
.colo-otitle .colo-a { color: var(--fg); border-bottom-color: var(--line); }
.colo-otitle .colo-a:hover { color: var(--cyan); border-bottom-color: var(--cyan); }
.colo-price { font-family: var(--font-data); font-size: var(--fs-1); color: var(--amber);
  margin-left: 0.4rem; white-space: nowrap; }
.colo-col p.colo-sum { color: var(--muted); font-size: var(--fs-1); line-height: 1.45; margin: 0; }
/* the last line: the law's own indicator, at the far edge, quiet */
.colo-rule {
  flex: 1 1 100%;
  display: flex; justify-content: flex-end; align-items: baseline;
  padding-top: 0.9rem; border-top: 1px solid var(--line);
}
#colo-meter {
  font-family: var(--font-data); font-size: var(--fs-1); letter-spacing: 0.12em;
  color: var(--muted); background: var(--raised); padding: 0.15rem 0.5rem; border-radius: 3px;
}
/* the other half of the boundary band: what STAYED in this browser. Same
   band, same weight, opposite end — the meter says what left, this says what
   was kept, and a reader meets the pair together. `margin-right: auto` is
   what puts it at the left of a row that justifies to the right. */
#colo-memory {
  margin-right: auto; display: flex; align-items: baseline; gap: 0.5rem;
  font-family: var(--font-data); font-size: var(--fs-1); letter-spacing: 0.08em;
  color: var(--muted);
}
#colo-memory:empty { display: none; }
/* D-29's own enumerated control ("remember my reading", 112x18 at both
   sizes). It is an `.ob-chip` inside `#colo-memory`, so neither the `.colo-a`
   rule above nor `.colo-copy`'s grown `::before` reached it — the round said
   "the colophon's links are out of it", which was true of the four links and
   of `copy` and not of this one (review I-4). It takes the same treatment as
   every other control in the colophon: the type is unchanged, the box a
   thumb has to hit is not. */
#colo-memory .mem-chip {
  font-size: var(--fs-1); padding: 0.1rem 0.5rem;
  position: relative; display: inline-flex; align-items: center; min-height: 24px;
}
#colo-memory .mem-chip::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: max(100%, 44px); height: max(100%, 44px); transform: translate(-50%, -50%);
}
@media (max-width: 900px) { #colo-memory .mem-chip { min-height: 44px; } }

/* ── the ask ──────────────────────────────────────────────────────────
 * One line under the reply, and the two things you would say back. It is
 * the omni's own row, not a banner over the page: a stranger who ignores it
 * reads the page they came for, and nothing is recorded either way. */
.consent-ask {
  /* An OVERLAY, not a row (review C-1). As a child of #omni-term this made
     the collapsed arm 129px on the second page of every session, and
     `--omni-h` — published from a ResizeObserver on .omnibar — pushed the
     paper down by the same 129px. §12 gives the arm one row and no second
     one, ever. Fixed under the bar, in the flash's family, so a question can
     be asked without the page moving under the reader. */
  position: fixed; left: 50%; transform: translateX(-50%);
  top: calc(var(--omni-h, 28px) + 2px);
  z-index: 96; width: min(34rem, calc(100vw - 1.2rem));
  padding: 0.55rem 0.8rem;
  border: 1px solid var(--amber); border-top: 0; border-left-width: 2px;
  border-radius: 0 0 5px 5px;
  background: color-mix(in srgb, var(--amber) 10%, #0b0f16);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.55);
}
.consent-ask[hidden] { display: none; }
.consent-ask .ask-line {
  margin: 0 0 0.45rem; font-size: var(--fs-2); line-height: 1.45; color: var(--fg); max-width: 62ch;
}
.consent-ask .ask-chips { display: flex; flex-wrap: wrap; gap: 0.45rem; }
@media (max-width: 900px) {
  /* no grid-template-columns here: .colophon is flex, and the stack comes
     from flex-wrap + a flex-basis wider than the phone. The grid property was
     left behind when the layout changed and did nothing. */
  .colophon { gap: 1.1rem; margin-top: 2.4rem; padding-bottom: 1.4rem; }
  .colo-a { padding-block: 0.95rem; }
}

/* ── the author's own way in (glass-owner.js) ─────────────────────────
 * On the colophon's last line, beside the boundary meter, because both are
 * the same kind of statement: what this page is doing about YOU. Before the
 * author proves anything it is one quiet word — a stranger who clicks it
 * gets a random number and a public key, which is all it has to give away.
 */
.colo-owner { display: flex; align-items: baseline; gap: 0.5rem; margin-right: 0.9rem; }
.colo-owner-btn {
  font-family: var(--font-display); font-size: var(--fs-1); letter-spacing: var(--track-label);
  text-transform: uppercase; color: var(--muted); background: none;
  border: 1px solid var(--line); border-radius: 2px;
  padding: 0.15rem 0.5rem; cursor: pointer; }
.colo-owner-btn:hover { color: var(--amber); border-color: var(--amber-idle); }
.colo-owner-btn:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.colo-owner-on { font-family: var(--font-data); font-size: var(--fs-1); color: var(--amber); }

/* The panel: the challenge, then the author's own view of the bake. Amber
   rules on the left, the house's mark for "you are in a state" — never a
   modal, because nothing here interrupts reading. */
#owner-seat[hidden] { display: none; }
.owner-panel {
  margin: 1.6rem 0 2.4rem; padding: 0.9rem 0 0.9rem 0.9rem;
  border-left: 3px solid var(--amber); background: var(--raised); border-radius: 0 3px 3px 0; }
.owner-panel h4 {
  margin: 0 0 0.5rem;
  font-family: var(--font-display); font-size: var(--fs-1); font-weight: 600;
  letter-spacing: var(--track-wide); text-transform: uppercase; color: var(--amber); }
.owner-panel p { margin: 0 0 0.5rem; font-size: var(--fs-2); line-height: 1.5; color: var(--fg); }
.owner-panel p.owner-quiet { color: var(--muted); font-size: var(--fs-1); line-height: 1.45; }
.owner-panel p.owner-quiet em { font-style: normal; color: var(--amber); }
.owner-row b { color: var(--muted); font-weight: 600; margin-right: 0.5rem; }
/* the challenge exists to be copied or read aloud, so it wraps rather than
   truncating — half a nonce is not a nonce */
.owner-chal { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.owner-chal code {
  font-family: var(--font-data); font-size: var(--fs-1); color: var(--cyan);
  background: var(--panel); padding: 0.2rem 0.45rem; border-radius: 3px; overflow-wrap: anywhere; }
.owner-token {
  font-family: var(--font-data); font-size: var(--fs-1); color: var(--fg);
  background: var(--panel); border: 1px solid var(--line); border-radius: 3px;
  padding: 0.3rem 0.45rem; min-width: 18rem; max-width: 100%; margin-right: 0.5rem; }
.owner-token:focus-visible { outline: 2px solid var(--amber); outline-offset: 1px; }
@media (max-width: 900px) {
  .colo-owner-btn { padding: 0.5rem 0.7rem; }   /* 44px of reach on a thumb */
  .owner-token { min-width: 0; width: 100%; margin: 0 0 0.5rem; }
}

/* ── a gated instrument, and the guest holding the key ────────────────
 * The box sits exactly where the instrument would have been, at its size,
 * so the page does not reflow when a grant arrives. Lavender, not amber:
 * amber is a state you are IN, and this is a state you are OUT of.
 */
.viz-locked {
  padding: 1.1rem 1rem; border: 1px dashed var(--lavender-idle); border-radius: 3px;
  background: var(--raised); text-align: center; }
.viz-locked .vl-what {
  margin: 0 0 0.35rem;
  font-family: var(--font-display); font-size: var(--fs-3); font-weight: 600;
  letter-spacing: var(--track-label); text-transform: uppercase; color: var(--lavender); }
.viz-locked .vl-why { margin: 0 0 0.3rem; font-size: var(--fs-2); color: var(--fg); }
.viz-locked .vl-why em { font-style: normal; color: var(--amber); }
.viz-locked .vl-note { margin: 0.2rem 0 0; font-size: var(--fs-1); color: var(--muted); }
.viz-locked .vl-a { color: var(--cyan); text-decoration: none; border-bottom: 1px solid var(--cyan); }
/* the guest's own line, beside the owner's, on the colophon's last rule */
.colo-guest-seat { display: flex; align-items: baseline; gap: 0.5rem; margin-right: 0.9rem; }
.colo-guest { font-family: var(--font-data); font-size: var(--fs-1); color: var(--lavender); }
