/* === Argument Lens ======================================================
   A lens over the calibrator's stored argument. The steps travel left and
   right through a fixed central frame, and the step in the frame is the
   readable one; the movement is ported from chadlewine's HeroLens.

   Every token reads the site's --rc-* value when main.css is on the page
   (the song page) and falls back to the same literal when it is not (the
   harness), so the lens is on-palette in the site and self-contained
   outside it. Nothing here styles an element the lens does not own.
   ======================================================================== */

:root {
  --al-orange: var(--rc-orange, #ffbb33);

  --al-bg-dark: var(--rc-bg-dark, #0a0a14);
  --al-bg-panel: var(--rc-bg-panel, #12121e);
  --al-bg-card: var(--rc-bg-card, #181828);
  --al-border: var(--rc-border, #2a2a3e);
  --al-border-ui: var(--rc-border-ui, #646490);

  --al-text: var(--rc-text, #c8c8d8);
  --al-text-dim: var(--rc-text-dim, #c0c0ca);
  --al-text-bright: var(--rc-text-bright, #eeeef4);
  --al-accent: var(--rc-accent, #00d4aa);
  --al-accent-light: var(--rc-accent-bright, #4fe6c6);

  --al-font: var(--rc-font, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
  --al-font-mono: var(--rc-font-mono, 'JetBrains Mono', 'Fira Code', 'Consolas', monospace);

  /* Geometry, ported from chadlewine's HeroLens: FLAT translateX, no 3D.
     The neighbours park just off the frame at calc(100% - peek), so a strip
     of each rides over the current step's edge and the move reads as passing
     THROUGH the frame rather than orbiting it. */
  --al-frame-h: 400px;
  --al-peek: 79px;   /* visible strip of the flanking step (paddle = peek - gap, trimmed 15% 2026-09-08) */
  --al-gap: 16px;    /* pushes neighbours further out so a seam shows */
  --al-step-pad: 0.6rem;  /* text column inset past the peek strip */
  /* From the text column's edge out to the card's VISIBLE edge (the aperture
     line sits `peek - gap` in; the column starts `peek + step-pad` in). The
     head reaches out by this on both sides so its rule runs edge to edge. */
  --al-edge: calc(var(--al-step-pad) + var(--al-gap));
  --al-ease: 1100ms cubic-bezier(0.22, 1, 0.36, 1);
  --al-dot: 22px;    /* the dot button's hit area; its centre is half this */
}

.arglens,
.arglens *,
.arglens-page,
.arglens-page *,
.arglens-gate { box-sizing: border-box; }

.arglens { font-family: var(--al-font); }

.arglens-gate {
  max-width: 40rem;
  margin: 6rem auto;
  padding: 2rem;
  border: 1px solid var(--al-border);
  border-radius: 8px;
  text-align: center;
  color: var(--al-text-dim);
}

/* The harness page only. The song page's body is main.css's. */
.arglens-page {
  max-width: 1100px;
  margin: 0 auto;
  padding: 2rem 1.5rem 0;
  color: var(--al-text);
  font-family: var(--al-font);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* Paddles, dots and the tip button all get tapped in quick succession on a
     phone; `manipulation` keeps pan and pinch and drops double-tap zoom, so a
     second tap on a paddle is a second step and never a zoom. */
  touch-action: manipulation;
}

.arglens-status {
  margin: 0;
  font-size: 0.8rem;
  color: var(--al-text-dim);
}

.arglens-status[hidden] { display: none; }

/* --- The rail ----------------------------------------------------------- */

/* One dot per step, evenly spaced, with a track behind them and a fill that
   runs to the current dot. The dots carry no visible label: the step in the
   frame names itself, and sixteen labels would be a second reading surface
   above the one that matters. The name arrives on hover and focus, and is
   always on the accessible name.

   Padding-top leaves room for the tooltip so it never pushes the frame. */
.arglens__rail {
  position: relative;
  display: flex;
  align-items: center;
  padding: 1.9rem 0 1.15rem;
}

/* One segment per step: the track from the previous dot to this one, with
   the dot at its right end. The first segment is only its dot, so the dots
   land at the same even spacing space-between gave. A segment colours when
   its step is passed or current, which is what draws the fill: state is a
   class, and no script sets a length. */
.arglens__seg {
  position: relative;
  flex: 1 1 0;
  display: flex;
  justify-content: flex-end;
}

.arglens__seg:first-child { flex: 0 0 auto; }

.arglens__seg:not(:first-child)::before {
  content: "";
  position: absolute;
  top: calc(50% - 1px);
  left: 0;
  right: calc(var(--al-dot) / 2);
  height: 1px;
  background: var(--al-border);
  transition: background 0.4s ease;
}

.arglens__seg.is-passed::before,
.arglens__seg.is-current::before { background: #04836e; }

.arglens__dot {
  position: relative;
  z-index: 1;
  width: var(--al-dot);
  height: var(--al-dot);
  display: grid;
  place-items: center;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  font: inherit;
}

.arglens__dot:focus-visible { outline: none; }

.arglens__dot-mark {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 1px solid var(--al-border-ui);
  /* Opaque, plus a solid ring of page ground so the track line is cut off
     at the dot instead of running visibly behind it. */
  background: var(--al-bg-dark);
  box-shadow: 0 0 0 4px var(--al-bg-dark);
  transition: width 0.25s ease, height 0.25s ease,
              background 0.25s ease, border-color 0.25s ease,
              box-shadow 0.25s ease;
}

.arglens__dot:hover .arglens__dot-mark { border-color: var(--al-accent); }

.arglens__dot:focus-visible .arglens__dot-mark {
  box-shadow: 0 0 0 4px var(--al-bg-dark), 0 0 0 6px #066558;
}

/* Read already: filled, but stepped back. */
.arglens__dot.is-passed .arglens__dot-mark {
  background: #04836e;
  border-color: #04836e;
}

/* In the frame. */
.arglens__dot.is-current .arglens__dot-mark {
  width: 13px;
  height: 13px;
  background: var(--al-accent);
  border-color: var(--al-accent);
  box-shadow: 0 0 0 4px var(--al-bg-dark), 0 0 0 7px #082a2c;
}

/* The name, on hover and on focus. */
.arglens__dot-name {
  position: absolute;
  bottom: calc(100% + 2px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  white-space: nowrap;
  padding: 0.16rem 0.45rem;
  background: var(--al-bg-panel);
  border: 1px solid var(--al-border);
  border-radius: 4px;
  font-size: 0.6rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--al-text-bright);
  visibility: hidden;
  pointer-events: none;
}

.arglens__dot:hover .arglens__dot-name,
.arglens__dot:focus-visible .arglens__dot-name { visibility: visible; }

/* The ends would push their tooltip off the page, so they anchor instead. */
.arglens__seg:first-child .arglens__dot-name { left: 0; transform: none; }
.arglens__seg:last-child .arglens__dot-name { left: auto; right: 0; transform: none; }

/* --- The frame ---------------------------------------------------------- */

/* It CLIPS: the neighbours live outside it and only their peek strips show,
   which is what makes the travel read as passing through. */
/* The frame is a SWIVEL. Two faces share its footprint: the front carries
   the steps (tab, aperture, stage, paddles), the back carries the whole
   argument as text, scrolling inside. "Read as text" turns the card a half
   turn on its vertical axis, so the section never changes height: the text
   occupies exactly the space the steps did.

   The frame itself holds the perspective and NOTHING that flattens 3D: an
   overflow other than visible forces `transform-style: flat` on the card and
   the back face would paint through the front. The clip, the edge and the
   ground all sit on the faces. */
.arglens__frame {
  position: relative;
  /* A floor, not a fixed height: the row stretches the frame to the readout
     beside it, so the two share one bottom edge. Alone in its column (tablet,
     phone) the floor is the height. */
  height: auto;
  min-height: var(--al-frame-h);
  perspective: 2400px;
}

.arglens__card {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform var(--al-ease);
}

.arglens__card.is-flipped { transform: rotateY(180deg); }

/* The edge is drawn on the face, not inherited from contrast: the frame's
   ground is the same panel colour as the song section it sits in, so
   without a line the paddle strips read as open page. */
.arglens__face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border: 1px solid var(--al-border);
  border-radius: 12px;
  background: var(--al-bg-panel);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.arglens__face--back { transform: rotateY(180deg); }

/* The aperture frames the centre band only, so it lands inside the visible
   step rather than under the peeks. */
.arglens__aperture {
  position: absolute;
  top: 0;
  bottom: 0;
  left: max(0px, calc(var(--al-peek) - var(--al-gap)));
  right: max(0px, calc(var(--al-peek) - var(--al-gap)));
  /* Two vertical lines and nothing else. The face already draws the top,
     the bottom and the rounded corners; a second outline here doubled the
     horizontals and its own radius clipped against the card's square edge. */
  border: 0;
  border-left: 1px solid #0d4845;
  border-right: 1px solid #0d4845;
  pointer-events: none;
  z-index: 6;
}

.arglens__stage {
  position: absolute;
  inset: 0;
}

/* --- The tab ------------------------------------------------------------ */

/* Hangs from the frame's top edge and does not move. Every step slides
   underneath it, which is why it carries the count (a fact about the deck)
   and not the step name (a fact about the step in the frame). Opaque, and
   above the steps, so nothing shows through it as one passes.

   It runs out to the left edge of the CURRENT CARD -- the aperture's inset,
   `peek - gap` -- and uses that edge as its left border, so it reads as part
   of the card it hangs over rather than as a box floating inside it. The
   count still lines up with where a step's text starts, via padding rather
   than an offset. `pointer-events: none` keeps it from taking a hover or a
   click away from the paddle beside it. */
.arglens__tab {
  position: absolute;
  top: 0;
  left: max(0px, calc(var(--al-peek) - var(--al-gap)));
  z-index: 6;
  /* The count is centered in the tab on both axes, so the tab needs a real
     height to centre within rather than one derived from its own padding. */
  height: 3rem;
  display: grid;
  place-items: center;
  padding: 0 0.9rem;
  background: var(--al-bg-card);
  border: 1px solid var(--al-border);
  border-top: 0;
  border-left: 0;
  border-radius: 0 0 6px 0;
  font-family: var(--al-font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  color: #05af90;
  pointer-events: none;
}

/* --- A step ------------------------------------------------------------- */

/* Full-bleed inside the frame; only transform moves it. The horizontal
   padding clears the peek strips so no prose sits under a veiled edge. */
.arglens__step {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 100%;
  margin: 0;
  display: flex;
  flex-direction: column;
  /* No top padding: the head is a fixed 3rem band matching the tab, so the
     count, the name and the chip all centre on the same line. */
  padding: 0 calc(var(--al-peek) + var(--al-step-pad)) 0;
  background: var(--al-bg-card);
  /* No edge of its own: the face draws the frame's top and bottom, and a
     card rule under them was a second line. */
  border: 0;
  text-align: left;
  color: inherit;
  font: inherit;
  cursor: pointer;
  transform: translateX(100%);
  will-change: transform;
  transition: transform var(--al-ease);
}

.arglens__step[hidden] { display: none; }

.arglens__step:focus-visible { outline: 2px solid var(--al-accent); outline-offset: -3px; }

/* The mask over a step that is not in the frame. FULLY OPAQUE, and it does
   not transition: a fading mask is translucent for the whole 1100ms of the
   travel, which is what let a neighbour's prose bleed across the frame
   mid-slide. It is either entirely there or entirely gone, so a peek is
   always a clean solid strip. */
.arglens__step::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  opacity: 1;
  background: var(--al-bg-panel);
}

/* The three mounted states. The current step is full-bleed at 0 and
   unveiled; the neighbours park just off the frame, a peek strip riding over
   the current step's edge, above it. */
.arglens__step.is-current {
  cursor: default;
  z-index: 1;
  transform: translateX(0%);
}

.arglens__step.is-current::after { opacity: 0; }

.arglens__step.is-prev {
  z-index: 2;
  transform: translateX(calc(-100% + var(--al-peek) - var(--al-gap)));
}

.arglens__step.is-next {
  z-index: 2;
  transform: translateX(calc(100% - var(--al-peek) + var(--al-gap)));
}

.arglens__step-head {
  display: flex;
  align-items: center;
  /* The same 3rem as the tab, so the three elements share its middle. */
  height: 3rem;
  flex-shrink: 0;
  gap: 0.7rem;
  /* A proper bottom border, edge to edge: the head reaches out of the text
     column to the card's visible edge on both sides and pads the same
     amount back, so the name and the chip keep their column. On the left
     it also clears the fixed tab, which overhangs this row. */
  margin: 0 calc(-1 * var(--al-edge));
  padding: 0 var(--al-edge) 0 calc(3.6rem + var(--al-edge));
  flex-wrap: wrap;
  border-bottom: 1px solid var(--al-border);
}

.arglens__step-name {
  /* Nudged clear of the tab's right edge (Chad, by eye). */
  margin-left: 15px;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--al-text-bright);
}

/* The finding: the step's own verdict token, where it writes one. */
.arglens__finding {
  margin-left: auto;
  padding: 0.14rem 0.55rem;
  border: 1px solid var(--al-border-ui);
  border-radius: 999px;
  font-family: var(--al-font-mono);
  font-size: 0.68rem;
  color: var(--al-text-bright);
  white-space: nowrap;
  max-width: 22rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

.arglens__finding--pos { border-color: #26723f; color: #7fe39a; }
.arglens__finding--neg { border-color: #8c6a2e; color: var(--al-orange); }

/* Fixed footprint, prose scrolls inside. A three-word step and a 328-word
   step occupy exactly the same space in the frame. */
.arglens__step-body {
  flex: 1;
  overflow-y: auto;
  /* The scrollbar rides the card's visible right edge (the aperture line,
     `peek - gap` in from the frame) instead of the text column's edge. The
     body reaches out through the step's right padding by that difference and
     pads the same amount back, so the text keeps its column and its wraps. */
  --al-scroll-out: calc(var(--al-edge) - 4px);
  padding: 0.85rem var(--al-scroll-out) 1.35rem 0;
  margin: 0 calc(-1 * var(--al-scroll-out)) 0 0;
  font-size: 0.88rem;
  line-height: 1.72;
  color: var(--al-text);
  overflow-wrap: anywhere;
  -webkit-mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - 34px), transparent 100%);
          mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - 34px), transparent 100%);
  scrollbar-width: thin;
  scrollbar-color: var(--al-border-ui) transparent;
}

/* Prose keeps its own line breaks; the itemized rows do not want them. */
.arglens__para {
  margin: 0 0 0.75rem;
  white-space: pre-wrap;
}

.arglens__para:last-child { margin-bottom: 0; }

/* A shouted line ending in a colon inside a step is a heading over the rows
   that follow it, not a finding of its own. */
.arglens__subhead {
  margin: 1.1rem 0 0.5rem;
  font-family: var(--al-font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: #05af90;
}

.arglens__subhead:first-child { margin-top: 0; }

/* --- Line items --------------------------------------------------------- */

/* An enumeration written as running text, read back as an enumeration. The
   key column is fixed so the names stack into a scannable column rather than
   ragging with the prose. */
.arglens__items {
  list-style: none;
  margin: 0 0 0.75rem;
  padding: 0;
  /* The LIST is the grid: one key column for every row, sized to the widest
     key, so every body starts on the same line. Each row subgrids it. */
  display: grid;
  grid-template-columns: max-content 1fr;
}

.arglens__items:last-child { margin-bottom: 0; }

.arglens__item {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: 1 / -1;
  gap: 0.85rem;
  /* The key is mono and the body is sans, at different sizes, so without this
     each sits to the top of its own box and the two lines never meet. Grid
     baseline alignment lines up their FIRST baselines, which is what a
     multi-line body needs: the key stays with the line it labels. */
  align-items: baseline;
  padding: 0.4rem 0;
  border-top: 1px solid #1e1e2e;
}

.arglens__item:first-child { border-top: 0; padding-top: 0; }

.arglens__item-key {
  font-family: var(--al-font-mono);
  font-size: 0.7rem;
  /* Matches the body's line box so the shared baseline is stable. */
  line-height: 1.7;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--al-accent-light);
}

/* Checked and clear. Present for completeness, not a finding. It reads at
   full brightness in a second hue (slate blue against the accent green), and
   carries a mark: a filled check for a finding, an open ring for a check that
   passed clean. No dimming: everything is 100% opacity, solid colour. */
.arglens__item-key::before {
  content: "✓";
  display: inline-block;
  width: 1.1em;
  margin-right: 0.15em;
  color: var(--al-accent);
}

.arglens__item.is-quiet .arglens__item-key { color: #8fa3e6; }
.arglens__item.is-quiet .arglens__item-key::before { display: none; }
.arglens__item.is-quiet .arglens__item-body { color: #a9a9bb; }

.arglens__item-body { min-width: 0; }

/* Only the step in the frame scrolls. */
.arglens__step:not(.is-current) .arglens__step-body { overflow: hidden; }

.arglens__step-body::-webkit-scrollbar { width: 6px; }
.arglens__step-body::-webkit-scrollbar-thumb { background: var(--al-border-ui); border-radius: 3px; }

/* --- The paddles -------------------------------------------------------- */

/* THE PADDLE IS THE WHOLE PEEK STRIP, and it is the only interactive thing
   here. It used to be a small button sitting on top of the peeking step,
   which meant moving the cursor onto the arrow took it OFF the step and the
   hover state dropped out from under it. One element now owns the whole
   strip, so there is exactly one hover region and one press target.

   The arrow inside is decoration: `pointer-events: none`, no states of its
   own, nothing to hover. It only reacts to what the paddle is doing. */
.arglens__nav {
  position: absolute;
  top: 0;
  bottom: 0;
  /* EXACTLY THE VISIBLE PEEK, which is `peek - gap`, not `peek`: the
     neighbour parks at calc(100% - peek + gap), so the gap is the part of
     the strip it never reaches. Sized to the full peek, the paddle's last
     16px lay over the CURRENT step and its hover ground blotted the edge of
     the card. This is also the aperture's own inset, so the lit strip now
     stops exactly where the frame says the reading area begins. */
  width: calc(var(--al-peek) - var(--al-gap));
  z-index: 7;
  display: grid;
  place-items: center;
  padding: 0;
  /* Always filled. The strip is a paddle with its own ground at rest, hover
     and press; it never lets the parked neighbour show through. */
  background-color: var(--al-bg-panel);
  /* The grip: a fine dot grid a shade above the ground, solid colour on
     solid colour, so the strip reads as a thing with a surface. The dot
     colour lifts with the ground on hover and sinks with it on press. */
  --al-grip: #08080f;
  background-image: radial-gradient(circle, var(--al-grip) 0.8px, transparent 1.2px);
  background-size: 4px 4px;
  background-position: center;
  border: 0;
  cursor: pointer;
  transition: background-color 0.2s ease, box-shadow 0.12s ease;
}

.arglens__nav--prev { left: 0; }
.arglens__nav--next { right: 0; }

/* Just the shape. No plate, no border, no radius, no focus outline: the only
   things that paint are the chevron stroke and the edge under it. Nudged
   3px out and 2px up off the paddle's centre (Chad, by eye). */
.arglens__nav svg {
  width: 28px;
  height: 28px;
  display: block;
  pointer-events: none;
  color: var(--al-accent-light);
  filter: drop-shadow(0 1px 0 #02241f);
  transition: color 0.2s ease, filter 0.2s ease, transform 0.08s ease;
}

.arglens__nav--prev svg { transform: translate(-3px, -2px); }
.arglens__nav--next svg { transform: translate(3px, -2px); }

/* Hover: the paddle lights, the arrow lifts further out of it. */
.arglens__nav:hover:not(:disabled),
.arglens__nav:focus-visible:not(:disabled) {
  background-color: #1a1a2c;
  --al-grip: #0a0a14;
}

.arglens__nav:hover:not(:disabled) svg,
.arglens__nav:focus-visible:not(:disabled) svg {
  color: #7ff2da;
  filter: drop-shadow(0 2px 0 #02241f);
}

/* DEPRESSED, on the whole paddle. The strip sinks to a darker ground with a
   hard inset edge along its top, and the arrow's emboss inverts with it: the
   highlight moves from under the stroke to over it, which reads as light
   from below, and the glyph travels 1px down into the hole. */
.arglens__nav:active:not(:disabled) {
  background-color: #0c0c16;
  --al-grip: #030308;
  box-shadow: inset 0 2px 0 #05050c;
}

.arglens__nav:active:not(:disabled) svg {
  color: #23a288;
  filter: drop-shadow(0 -1px 0 #02241f);
}

.arglens__nav--prev:active:not(:disabled) svg { transform: translate(-3px, -1px); }
.arglens__nav--next:active:not(:disabled) svg { transform: translate(3px, -1px); }

/* NO FOCUS BOX. An outline would draw a rect around the strip, which is the
   one thing these controls are not allowed to have; focus states itself the
   same way hover does. */
.arglens__nav:focus-visible { outline: none; }

/* Pressed flat, not faded: the emboss goes shallow and the green goes back
   toward the ground, since there is no plate to grey out and no opacity to
   reach for. */
.arglens__nav:disabled { cursor: default; }

.arglens__nav:disabled svg {
  color: #14574c;
  filter: drop-shadow(0 1px 0 #0a1a1a);
}

/* --- Placement readout -------------------------------------------------- */

/* The frame and the readout share a row: three quarters to the steps, one
   quarter to the numbers they produce, stacked. */
.arglens__row {
  display: grid;
  grid-template-columns: 3fr 1fr;
  gap: 1rem;
  align-items: stretch;
  margin: 0 0 1.15rem;
}

.arglens__placement {
  display: flex;
  flex-direction: column;
  /* The seven slots spread over the column's full height, so the readout
     is exactly as tall as the frame and never a stack with slack under it. */
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0;
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--al-border);
  border-radius: 6px;
  background: var(--al-bg-panel);
}

.arglens__slot {
  flex: 0 0 auto;
  min-width: 0;
  padding: 0.3rem 0.5rem;
  border-left: 2px solid #23233a;
  transition: border-color 0.4s ease, color 0.4s ease;
}

.arglens__slot.is-landed { border-left-color: var(--al-accent); }

/* Three of the seven carry a bare number and need half the room. Halving the
   basis, the minimum AND the grow share hands the slack to the four that
   carry words: `negative_payload` was being clipped and the vernier's four
   deltas had nowhere to sit. */
/* Stacked in a column, every slot takes the full width; the old half-width
   rule for the three bare-number slots is moot here. */

.arglens__slot-label {
  display: block;
  font-size: 0.6rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: #55556a;
}

.arglens__slot.is-landed .arglens__slot-label { color: var(--al-text-dim); }

.arglens__slot-value {
  display: block;
  margin-top: 0.15rem;
  font-family: var(--al-font-mono);
  font-size: 0.92rem;
  /* A fixed line box, so a slot is the same height whatever it holds: the
     vernier's four dials at a smaller size sit in the same line as a dash. */
  line-height: 1.2rem;
  color: var(--al-text-bright);
}

.arglens__slot:not(.is-landed) .arglens__slot-value { color: #55556a; }

/* The vernier is four dials, not one number: the value carries a newline
   between them and reads one per line at every width. */
/* Stacked in the desktop column, the four dials condense onto the ONE line
   every other slot has: smaller mono, no wrap, the newlines in the value
   collapsing to spaces. The strip and the phone grid restore a line each. */
.arglens__placement [data-slot="vernier"] .arglens__slot-value {
  white-space: nowrap;
  font-size: 0.7rem;
  letter-spacing: -0.01em;
}

/* A pipe between points on the one-line form. */
.arglens__point + .arglens__point::before {
  content: "|";
  margin: 0 0.4em;
  color: var(--al-text-dim);
}

/* A point with a description is a button in the text's own clothes: no
   plate, no border, the value's font and colour, a dotted underline so it
   reads as something to ask. The tip is the step names' popover. */
.arglens__dial {
  padding: 0;
  background: none;
  border: 0;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
}

button.arglens__dial {
  cursor: help;
  text-decoration: underline dotted #55556a;
  text-underline-offset: 3px;
}

button.arglens__dial:hover,
button.arglens__dial:focus-visible {
  text-decoration-color: var(--al-accent);
  outline: none;
}

/* A point's tip is narrower than a step's, and grows toward the frame:
   the readout sits at the row's right edge, so a tip spanning to the
   inline end would run off the page. */
.arglens__point .arglens__info-tip {
  width: 15rem;
  position-area: block-end span-inline-start;
}

/* --- Foot --------------------------------------------------------------- */

.arglens__foot {
  display: flex;
  justify-content: center;
  padding-top: 0.25rem;
}
/* The open/close control. Centered, and a step up in size from the chrome
   around it, because it is the one thing on the page asking to be pressed. */
.arglens__text-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.6rem 1.2rem;
  background: transparent;
  border: 1px solid var(--al-border);
  border-radius: 999px;
  color: var(--al-text-dim);
  font-family: var(--al-font);
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.arglens__text-toggle:hover { color: var(--al-text-bright); border-color: var(--al-border-ui); }
.arglens__text-toggle:focus-visible { outline: 2px solid var(--al-accent); outline-offset: 2px; }

/* STROKE CHEVRON WITH A SPRING FLIP, lifted from chadworks' nav caret: a
   rotated square wearing two borders, currentColor so it tracks its label,
   and an open flip that overshoots the half turn and settles. One either
   side of the label, both spinning together. */
.arglens__caret {
  width: 7px;
  height: 7px;
  flex: 0 0 auto;
  border-right: 1.8px solid currentColor;
  border-bottom: 1.8px solid currentColor;
  /* Points right at rest (toward the back of the swivel), left once turned. */
  transform: rotate(-45deg) translate(-1px, 1px);
  transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.arglens__text-toggle[aria-pressed="true"] .arglens__caret {
  transform: rotate(135deg) translate(-1px, 1px);
}

/* --- The text face ------------------------------------------------------ */

/* Every step at once, for comparison. The lens is sequential by design, and
   comparison is the one thing a sequence is bad at. It is the BACK of the
   frame (see the swivel above): the same height as the steps, scrolling
   inside, never a fold that grows the section. */
.ag-astext__inner {
  height: 100%;
  overflow-y: auto;
  padding: 1.25rem 1.4rem;
  scrollbar-width: thin;
  scrollbar-color: var(--al-border-ui) transparent;
}

.ag-astext__inner::-webkit-scrollbar { width: 6px; }
.ag-astext__inner::-webkit-scrollbar-thumb { background: var(--al-border-ui); border-radius: 3px; }

.ag-astext__step { margin: 0 0 1.75rem; }
.ag-astext__step:last-child { margin-bottom: 0; }

.ag-astext__title {
  margin: 0 0 0.55rem;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--al-accent);
}


.ag-astext__inner .arglens__para {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.7;
  overflow-wrap: anywhere;
}

/* --- Narrow viewports --------------------------------------------------- */

/* --- Tablet portrait, single stack ------------------------------------- */

/* The row gives up its second column: the frame takes the full width and
   the readout returns to a wrapping strip beneath it. The frame grows so a
   long step still reads without the body scrolling on the first line. */
@media (max-width: 1024px) {
  :root { --al-frame-h: 520px; --al-peek: 69px; --al-gap: 12px; }
  .arglens-page { padding: 1.5rem 1.25rem 0; }
  .arglens__row { grid-template-columns: 1fr; gap: 0.85rem; }
  .arglens__placement { flex-direction: row; flex-wrap: wrap; justify-content: flex-start; gap: 0.4rem; }
  /* Every slot is sized to what it holds and no wider: a rem basis with a
     min-width summed past the strip on a 768 screen and pushed Charge onto
     a line of its own. Only the vernier grows, and only the route wraps. */
  .arglens__slot { flex: 0 1 auto; min-width: 0; padding: 0.3rem 0.4rem; }
  /* The route name is the widest value; sized to the longest name and the
     value wraps inside it. */
  .arglens__placement [data-slot="route"] { flex: 0 1 6.5rem; }
  /* The vernier is four short lines and lands last on the strip; it takes
     whatever the line has left rather than leaving a blank beside it. */
  .arglens__placement [data-slot="vernier"] { flex: 1 1 auto; }
  .arglens__placement [data-slot="vernier"] .arglens__slot-value {
    white-space: normal;
    font-size: 0.92rem;
    letter-spacing: 0;
  }
  /* One point per line, no delimiter. */
  .arglens__point { display: block; }
  .arglens__point + .arglens__point::before { content: none; }
  .arglens__placement [data-slot="route"] .arglens__slot-value { overflow-wrap: anywhere; }
  .arglens__finding { max-width: 16rem; }
}

/* --- Phone -------------------------------------------------------------- */

/* Narrow peeks so the reading column keeps its width; the head wraps the
   chip under the name; every row stacks its key above its body, since a
   key column beside a 14rem body leaves neither room; the readout is a
   two-column grid. The frame height follows the small viewport so the card
   is the screen and stays put while the URL bar comes and goes. */
@media (max-width: 640px) {
  :root {
    /* svh, not dvh: the small viewport is the height with the browser's
       URL bar shown, and it does not change as the bar collapses on scroll.
       A dvh height resized the card mid-scroll and flipped the body between
       overflowing and not. */
    --al-frame-h: min(600px, 72svh);
    --al-peek: 46px;
    --al-gap: 8px;
    --al-step-pad: 0.45rem;
    --al-dot: 18px;
  }
  body { font-size: 14px; }
  .arglens-page { padding: 1rem 0.75rem 0; }
  .arglens__rail { padding: 1.7rem 0 0.9rem; }
  .arglens__dot-name { font-size: 0.55rem; }

  .arglens__step-head {
    position: relative;
    height: auto;
    min-height: 3rem;
    padding: 0.55rem var(--al-edge) 0.55rem calc(3.4rem + var(--al-edge));
    /* One line: the chip shrinks to fit rather than dropping under the name. */
    flex-wrap: nowrap;
  }
  .arglens__tab { padding: 0 0.6rem; font-size: 0.62rem; }
  .arglens__step-name { margin-left: 8px; font-size: 0.74rem; }
  /* No chip on a phone: the head has room for the name and the tip only,
     and the step's own value lands in the readout beneath the frame. */
  .arglens__finding { display: none; }
  .arglens__step-body { font-size: 0.84rem; line-height: 1.6; padding-top: 0.65rem; }

  .arglens__items { grid-template-columns: 1fr; }
  .arglens__item { gap: 0.1rem; padding: 0.45rem 0; }
  .arglens__item-key { font-size: 0.64rem; }
  .arglens__sublist .arglens__item { padding: 0.3rem 0; }

  .arglens__nav svg { width: 20px; height: 20px; }
  .arglens__nav--prev svg { transform: translate(-1px, -2px); }
  .arglens__nav--next svg { transform: translate(1px, -2px); }
  .arglens__nav--prev:active:not(:disabled) svg { transform: translate(-1px, -1px); }
  .arglens__nav--next:active:not(:disabled) svg { transform: translate(1px, -1px); }

  .arglens__placement {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.4rem;
    padding: 0.65rem 0.7rem;
  }
  .arglens__slot,
  .arglens__placement [data-slot="visceral"],
  .arglens__placement [data-slot="center"],
  .arglens__placement [data-slot="charge"] { flex: none; min-width: 0; }
  /* The vernier is four lines tall, so it takes the right column across two
     rows and Center and Charge stack beside it; dense flow fills the cell
     the vernier skipped. No slot leaves a blank beside it. */
  .arglens__placement { grid-auto-flow: row dense; }
  .arglens__placement [data-slot="vernier"] { grid-column: 2; grid-row: span 2; }

  .arglens__info-tip { font-size: 0.67rem; }

  .ag-astext__inner { padding: 0.9rem; }
  .ag-astext__title { font-size: 0.88rem; }
}

/* --- Reduced motion ----------------------------------------------------- */

/* Positions are meaning here (the step you came from is on the left), so
   they stay. Only the travel goes: the steps cut rather than slide. */
@media (prefers-reduced-motion: reduce) {
  .arglens__step,
  .arglens__seg::before,
  .arglens__card,
  .arglens__caret {
    transition: none;
    will-change: auto;
  }
}

/* DOMINANT ARC: the posture rows close the beat list under a stronger rule. */
.arglens__item[data-kind="posture"] { border-top-color: #2a2a3e; }

/* CITATION RULES: keys are the placeholders standing in for redacted names
   ("a whiskey brand"), which read as phrases, not labels. */
.arglens__item[data-kind="citation"] .arglens__item-key { text-transform: none; letter-spacing: 0.01em; }

/* A row whose body is a list of its own: the anchors set aside in PRECEDENT
   PLACEMENT. The sublist is its own two-column grid inside the body column,
   its rows ruled with a dashed line so they read as one row's contents
   rather than as peers of the rows around them. */
.arglens__sublist {
  margin: 0;
  padding: 0;
}

.arglens__sublist .arglens__item {
  padding: 0.25rem 0;
  border-top: 1px dashed #1e1e2e;
}

.arglens__sublist .arglens__item:first-child { border-top: 0; padding-top: 0; }
.arglens__sublist .arglens__item:last-child { padding-bottom: 0; }

/* --- What this step is -------------------------------------------------- */

/* A small "i" beside the step name. The description is a POPOVER anchored
   to the button: it paints in the top layer, above the frame's clipping and
   outside the card's transform, and the browser places it below the icon,
   flipping above (and inward) when that side would run off the screen. So
   it is always fully on screen, on every width, with no measuring script. */
.arglens__info {
  display: inline-flex;
  align-items: center;
}

.arglens__info-btn {
  width: 1.05rem;
  height: 1.05rem;
  padding: 0;
  display: grid;
  place-items: center;
  border: 1px solid var(--al-border-ui);
  border-radius: 50%;
  background: none;
  color: var(--al-text-dim);
  font-family: var(--al-font-mono);
  font-size: 0.62rem;
  font-weight: 600;
  line-height: 1;
  cursor: help;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.arglens__info-btn:hover,
.arglens__info-btn:focus-visible {
  color: var(--al-accent-light);
  border-color: var(--al-accent);
  outline: none;
}

/* The popover's UA sheet centres it in the viewport with a black border;
   every one of those is reset. The implicit anchor is the invoking button. */
.arglens__info-tip {
  position: fixed;
  inset: auto;
  margin: 0.45rem 0;
  position-area: block-end span-inline-end;
  position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
  position-try-order: most-height;
  width: 22rem;
  max-width: calc(100vw - 1.5rem);
  padding: 0.55rem 0.7rem;
  /* Inverted: the page's bright text as the ground, its dark panel as the
     ink, so a tip reads as a label laid on the page rather than a panel
     cut into it. */
  background: var(--al-text-bright);
  border: 1px solid var(--al-text-bright);
  border-radius: 6px;
  /* A dark outer glow lifts the light tip off whatever it lands over. */
  box-shadow: 0 0 16px 3px #05050c;
  color: var(--al-bg-panel);
  font-family: var(--al-font);
  font-size: 0.7rem;
  line-height: 1.5;
  /* Its own text flow. The tip inherits from wherever its button sits, and
     the vernier's value is nowrap with tight tracking, which turned that
     tip into one unbroken line. */
  white-space: normal;
  letter-spacing: normal;
  font-weight: 400;
  text-align: left;
  text-transform: none;
  text-decoration: none;
  overflow: visible;
}

.arglens__info-tip:not(:popover-open) { display: none; }

/* Without anchor positioning the popover still opens in the top layer,
   centred in the viewport, which is readable if not adjacent. */
@supports not (position-area: block-end) {
  .arglens__info-tip { inset: 0; margin: auto; height: fit-content; }
}
