/* ---- CASCADE LAYER ------------------------------------------------------
 *
 * Everything the kit ships sits in ONE layer named `overscan`, so a consumer's
 * own CSS beats it without a specificity fight and without !important. That is
 * close to mandatory for a distributed kit: an app should be able to restyle a
 * panel by writing a plain rule.
 *
 * ⚠️ ONE layer, deliberately, NOT a sub-layer per file. Sub-layers look tidier
 * and would silently reorder the kit against itself: layer order beats
 * specificity, so a high-specificity rule in an early file that currently wins
 * would start losing to a low-specificity rule in a later one. A single layer
 * preserves source order exactly, so nothing inside the kit changes.
 *
 * Unlayered author CSS wins over all of it. That is the point.
 */

@layer overscan {
/* Command line. */

ov-cli {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-block-size: 0;
  font-family: var(--ov-font-mono);
  font-size: var(--ov-size-2);
  color: var(--ov-ink);
  cursor: text;
}

/* ⚠️ THE OTHER AXIS, AND IT IS THE SAME CURSOR. Six themes hang the mark below
 * the text (`--ov-text-mark-drop`: industrial -0.12em, machina -0.1em,
 * aegis and vector -0.08em, holo -0.06em, esper -0.05em) because an underscore
 * or a read edge belongs under the line, not on it. On the LAST row that
 * overhang fell outside the box and the shell grew a vertical scrollbar for
 * one pixel of decoration. Terminal and antiseptic sit at 0 and never showed
 * it, which is why this looked like a rounding error and is not one.
 *
 * ⭐ RESERVED FROM THE TOKEN, so the box gives back exactly what the theme's
 * own cursor takes and nothing is a magic number: a theme with no drop gets no
 * padding, and because the drop is in `em` this holds at any font size. The
 * `max()` keeps a positive drop, should a theme ever want one, from computing
 * a negative padding and voiding the declaration. */
.ov-cli__out {
  flex: 1 1 auto;
  min-block-size: 0;
  overflow: auto;
  padding-block-end: max(0px, calc(-1 * var(--ov-text-mark-drop, 0px)));
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Scrolls rather than truncating, for the reason in log.css: an ellipsis takes
 * the end, and languages disagree about what lives there. */

/* 🔴 `max-content` IS WHAT KEEPS THE CURSOR OUT OF THE SCROLLBAR, and without
 * it the shell scrolled in seven of the ten themes for no content at all.
 * A row is a flex item, so it was stretched to the full width of
 * `.ov-cli__out`. `.ov-out::after` in motion.css is the theme's cursor and it
 * is positioned at `inset-inline-start: var(--ov-reveal)`, which finishes at
 * 100%: a percentage of the ROW. Stretched, that put the cursor hard on the
 * row's right edge and its own width past it, on EVERY row whatever the row
 * said, and an absolutely positioned descendant still counts toward the scroll
 * container's overflow. The bar that appeared was exactly the width of the
 * cursor, measured per theme: terminal 6px at 0.55em, industrial 9px at
 * 0.85em, esper 33px at 3em. Antiseptic was the only one spared, because it
 * declares no cursor at all.
 *
 * ⚠️ AND THE VERTICAL BAR CAME WITH IT. `.ov-cli__out` is sized to exactly its
 * content height, so the 11px the horizontal bar took forced a second bar for
 * content that had fitted a moment earlier. Both went when the cursor did.
 *
 * ⭐ `max-content`, not `fit-content`: fit-content clamps at the available
 * width, which puts a long line's cursor back on the edge and the bar back
 * with it. At max-content the row is exactly as wide as its text, so the
 * cursor lands after the last character, which is the one place motion.css
 * always claimed it was. The two readers of `--ov-reveal` had been resolving
 * their percentages against different boxes: `clip-path` against the inner
 * span, `inset-inline-start` against this row. Now they are the same box.
 */
.ov-cli__row { white-space: pre; inline-size: max-content; }
.ov-cli__row.is-echo { color: var(--ov-dim); }
.ov-cli__row.is-dim { color: var(--ov-faint); }
.ov-cli__row.is-bad { color: var(--ov-alarm); }

.ov-cli__line { display: flex; align-items: baseline; gap: 8px; }

.ov-cli__prompt { color: var(--ov-accent); flex: 0 0 auto; }

.ov-cli__input {
  flex: 1 1 auto;
  min-inline-size: 0;
  font: inherit;
  letter-spacing: inherit;
  color: var(--ov-ink);
  background: none;
  border: 0;
  padding: 0;
  caret-color: var(--ov-accent);
}

.ov-cli__input:focus { outline: none; }

/* The focus ring goes on the line, not the bare input, so the prompt is
 * visibly part of the focused control. */
ov-cli:focus-within .ov-cli__line {
  outline: 2px solid var(--ov-accent);
  outline-offset: 2px;
}
}
