/* THE GOD TERMINAL — typer: editor tab strip, code view, cursor and reveal effects.
 * Everything lives inside #main (.panel). Colours come from palette tokens only. */

.ty { display: flex; flex-direction: column; }

/* ───────── tab strip ───────── */
.ty-head {
  position: relative;
  display: flex;
  flex: none;
  height: 2.5rem;
  border-bottom: 1px solid var(--line);
  border-radius: var(--radius) var(--radius) 0 0;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--panel-strong) 82%, transparent),
    color-mix(in srgb, var(--panel-strong) 38%, transparent));
  overflow: hidden;
}
.ty-tabs {
  position: relative;
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}
.ty-tabs::-webkit-scrollbar { display: none; }
.ty-head.is-overflow .ty-tabs {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 1.75rem, #000 calc(100% - 1.75rem), transparent);
  mask-image: linear-gradient(90deg, transparent, #000 1.75rem, #000 calc(100% - 1.75rem), transparent);
}

.ty-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  flex: none;
  height: 100%;
  padding: 0 1.05em;
  border: 0;
  border-right: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
  background: transparent;
  color: var(--dim);
  font: 500 0.875rem/1 var(--font-mono);
  letter-spacing: 0.01em;
  white-space: nowrap;
  cursor: pointer;
  transition: color 160ms, background-color 220ms, transform 120ms cubic-bezier(.2, 1.6, .4, 1);
}
.ty-tab:hover { color: var(--text); background-color: color-mix(in srgb, var(--text) 6%, transparent); }
.ty-tab:focus-visible { outline: 2px solid var(--line-bright); outline-offset: -3px; }
.ty-tab.is-active {
  color: var(--text-bright);
  text-shadow: var(--text-glow);
  background: linear-gradient(0deg, color-mix(in srgb, var(--accent) 18%, transparent), transparent 92%);
}
.ty-tab-dot {
  flex: none;
  width: 0.5em;
  height: 0.5em;
  border-radius: 1px;
  background: var(--dot);
  box-shadow: 0 0 6px var(--dot);
  opacity: 0.5;
  transform: rotate(45deg);
  transition: opacity 200ms, transform 320ms cubic-bezier(.3, 1.6, .4, 1);
}
.ty-tab.is-active .ty-tab-dot { opacity: 1; transform: rotate(45deg) scale(1.3); }
.ty-tab-ext { color: var(--faint); transition: color 200ms; }
.ty-tab.is-active .ty-tab-ext { color: var(--dim); }

/* Condensing (set by JS until the strip fits): inactive tabs lose their extension, then the
 * longest names their tail. */
.ty-head[data-fit="1"] .ty-tab { padding: 0 0.85em; gap: 0.5em; }
.ty-head[data-fit="1"] .ty-tab:not(.is-active) .ty-tab-ext,
.ty-tab.is-short:not(.is-active) .ty-tab-rest { display: none; }

/* Sliding underline under the active tab; its fill is the file's progress (white backfill leads). */
.ty-ink {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100px;
  height: 2px;
  transform-origin: 0 50%;
  background: color-mix(in srgb, var(--accent) 55%, transparent);
  box-shadow: 0 0 calc(10px * var(--glow-k) + 2px) var(--accent);
  pointer-events: none;
  transition: transform 460ms cubic-bezier(.3, 1.35, .4, 1);
}
/* The active tab looks lit from below. */
.ty-ink::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1.1rem;
  background: linear-gradient(0deg, color-mix(in srgb, var(--accent) 24%, transparent), transparent);
}
.ty-ink-back, .ty-ink-fill {
  position: absolute;
  inset: 0;
  transform-origin: 0 50%;
  transform: scaleX(0);
}
.ty-ink-back {
  background: #fff;
  box-shadow: 0 0 6px var(--text-bright);
  transition: transform 70ms ease-out;
}
.ty-ink-fill {
  background: linear-gradient(90deg, var(--accent), var(--text-bright));
  box-shadow: 0 0 8px var(--accent), 0 0 2px var(--text-bright);
  transition: transform 520ms cubic-bezier(.3, .7, .3, 1);
}

/* AUTO indicator */
.ty-auto {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  flex: none;
  height: 100%;
  padding: 0 1rem;
  border: 0;
  border-left: 1px solid var(--line);
  background: transparent;
  color: var(--dim);
  font: 800 0.8125rem/1 var(--font-mono);
  letter-spacing: 0.14em;
  overflow: hidden;
  cursor: pointer;
  transition: color 160ms, background-color 220ms, transform 120ms cubic-bezier(.2, 1.6, .4, 1);
}
.ty-auto:hover { color: var(--text-bright); }
.ty-auto:focus-visible { outline: 2px solid var(--line-bright); outline-offset: -3px; }
.ty-led {
  flex: none;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--faint) 70%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--line-bright) 45%, transparent);
}
.ty-auto-ms {
  min-width: 4.4ch;
  color: var(--faint);
  font-weight: 500;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.ty-auto.is-on {
  color: var(--text-bright);
  text-shadow: var(--text-glow);
  background: linear-gradient(0deg, color-mix(in srgb, var(--accent) 30%, transparent), color-mix(in srgb, var(--accent) 6%, transparent));
  box-shadow: inset 0 -2px 0 var(--accent);
}
/* A light sweep runs across the indicator while autotyping. */
.ty-auto::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 35%, color-mix(in srgb, var(--text-bright) 22%, transparent) 50%, transparent 65%);
  transform: translateX(-100%);
  opacity: 0;
  pointer-events: none;
}
.ty-auto.is-on::after { opacity: 1; animation: ty-auto-sweep 1.6s cubic-bezier(.5, 0, .5, 1) infinite; }
@keyframes ty-auto-sweep { to { transform: translateX(100%); } }
.ty-auto.is-on .ty-led {
  background: var(--accent);
  box-shadow: 0 0 9px var(--accent), 0 0 2px var(--text-bright);
  animation: ty-led 0.8s ease-in-out infinite;
}
.ty-auto.is-on .ty-auto-ms { color: var(--accent); }
@keyframes ty-led { 50% { opacity: 0.35; transform: scale(0.7); } }

/* ───────── code view ───────── */
.ty-body {
  --ty-gutter: 5ch;                               /* line-number column */
  --ty-code: calc(var(--ty-gutter) + 1.4ch);      /* where code starts */
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  border-radius: 0 0 var(--radius) var(--radius);
  font-family: var(--font-mono);
  font-size: 1.0625rem;
  line-height: 1.5;
  font-variant-ligatures: none;
  cursor: text;
  /* Taps only: with pan/zoom allowed, two thumbs rolling while both are down become a pinch,
     and the browser cancels them and swallows every tap until all fingers lift. */
  touch-action: none;
  -webkit-touch-callout: none;
}
.ty-body::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: var(--ty-gutter);
  background: color-mix(in srgb, var(--panel-strong) 40%, transparent);
  border-right: 1px solid color-mix(in srgb, var(--line) 65%, transparent);
  pointer-events: none;
}
.ty-view {
  position: absolute;
  inset: 0;
  overflow: hidden;
  container-type: inline-size;
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 1.4rem);
  mask-image: linear-gradient(180deg, transparent 0, #000 1.4rem);
}
.ty-doc {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  padding: 0.8rem 1.25rem 0 0;
  will-change: transform;
}
.ty-doc.is-ghost { pointer-events: none; }
.ty-doc.is-ghost .ty-band { opacity: 0; transition: opacity 160ms; }

.ty-band {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1.5em;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--accent) 15%, transparent),
    color-mix(in srgb, var(--accent) 6%, transparent) 45%,
    transparent 92%);
  box-shadow: inset 2px 0 0 var(--accent);
  pointer-events: none;
  transition: transform 130ms cubic-bezier(.2, .8, .3, 1);
}

.ty-line {
  position: relative;
  min-height: 1.5em;
  padding-left: calc(var(--ty-code) + 2ch);
  text-indent: -2ch;                              /* wrapped rows hang 2ch in */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  color: var(--syn-var);
  text-shadow: 0 0 calc(7px * var(--glow-k)) color-mix(in srgb, currentColor 55%, transparent);
}
.ty-line > span { text-shadow: 0 0 calc(7px * var(--glow-k)) color-mix(in srgb, currentColor 55%, transparent); }
.ty-line[data-n]::before {
  content: attr(data-n);
  position: absolute;
  top: 0;
  left: 0;
  width: calc(var(--ty-gutter) - 1.1ch);
  text-align: right;
  text-indent: 0;
  white-space: nowrap;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
  text-shadow: none;
  transition: color 200ms;
}
.ty-line.is-cur::before { color: var(--text-bright); text-shadow: var(--text-glow); }

/* Hex dump data rows (.ty-hex) are 78 columns. A view too narrow for that folds each at
 * its column boundaries under a 10ch hanging indent: address + bytes, then the ASCII
 * gutter; on phones address + 8 bytes, the other 8 bytes, then the gutter. The
 * half-column of slack leaves room for the caret at the end of a row. */
@container (max-width: 87ch) {
  .ty-hex {
    max-width: calc(var(--ty-code) + 10ch + 50.5ch);
    padding-left: calc(var(--ty-code) + 10ch);
    text-indent: -10ch;
  }
}
@container (max-width: 69ch) {
  .ty-hex { max-width: calc(var(--ty-code) + 10ch + 24.5ch); }
}

/* syntax */
.s-kw { color: var(--syn-kw); font-weight: 700; }
.s-str { color: var(--syn-str); }
.s-num { color: var(--syn-num); }
.s-com { color: var(--syn-com); font-style: italic; }
.s-fn { color: var(--syn-fn); }
.s-type { color: var(--syn-type); }
.s-punct { color: var(--syn-punct); }
.s-op { color: var(--syn-op); }
.s-var { color: var(--syn-var); }
.s-key { color: var(--syn-key); }
.s-const { color: var(--syn-const); }
.s-tag { color: var(--syn-tag); }
.s-ok, .s-warn, .s-err {
  font-weight: 800;
  border-radius: 3px;
  background: color-mix(in srgb, currentColor 14%, transparent);
}
.s-ok { color: var(--good); }
.s-warn { color: var(--warn); }
.s-err { color: var(--bad); }
html[data-palette="midnight"] .s-com { color: color-mix(in srgb, var(--syn-com) 75%, var(--dim)); }

/* Phosphor-hot reveal: each new chunk lands white-hot and cools to its colour. */
.ty-line .h { animation: ty-hot 380ms cubic-bezier(.3, .6, .35, 1); }
@keyframes ty-hot {
  from {
    color: color-mix(in srgb, var(--text-bright) 45%, #fff);
    text-shadow: 0 0 1px #fff, 0 0 calc(9px * var(--glow-k) + 3px) var(--text-bright), 0 0 calc(20px * var(--glow-k) + 4px) var(--glow);
  }
}
/* A flood of hot text (high typing power on autotype): the same white-hot landing, carried by the
 * line's own currentColor glow instead of an animated bloom. */
.ty-line .h.is-lite { animation-name: ty-hot-lite; }
@keyframes ty-hot-lite { from { color: #fff; } }

/* Block cursor: solid while typing (punched per advance from JS), blinks when idle. */
.ty-caret {
  position: relative;
  display: inline-block;
  width: 1ch;
  height: 1.12em;
  margin-left: 1px;
  vertical-align: -0.2em;
  border-radius: 2px;
  background: var(--cursor);
  box-shadow: 0 0 calc(12px * var(--glow-k) + 2px) var(--cursor);
  transform-origin: 50% 100%;
  text-indent: 0;
}
.ty-caret::after {
  content: '';
  position: absolute;
  inset: -0.9em -1.8em;
  border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--cursor) 20%, transparent), transparent);
  pointer-events: none;
}
.ty.is-idle .ty-caret { animation: ty-blink 1.1s ease-in-out infinite; }
@keyframes ty-blink {
  0%, 46% { opacity: 1; }
  54%, 94% { opacity: 0.08; }
}

/* ───────── channel banner ───────── */
.ty-banner {
  display: flex;
  align-items: center;
  gap: 0.9ch;
  min-height: 2em;
  margin: 0.55em 0 0.45em;
  padding: 0 0.5ch 0 1.25ch;
  text-indent: 0;
  white-space: pre;
  overflow: hidden;
}
.ty-rule {
  flex: 1 1 0;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, var(--accent));
  box-shadow: 0 0 8px var(--glow);
  transform-origin: 100% 50%;
}
.ty-rule:last-child { background: linear-gradient(270deg, transparent, var(--accent)); transform-origin: 0 50%; }
.ty-banner-label {
  padding: 0.12em 1.2ch;
  border: 1px solid color-mix(in srgb, var(--accent) 65%, transparent);
  border-radius: 4px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 18%, transparent), color-mix(in srgb, var(--accent) 5%, transparent));
  box-shadow: 0 0 calc(18px * var(--glow-k) + 2px) -6px var(--accent), inset 0 0 12px -6px var(--accent);
  font-weight: 800;
  letter-spacing: 0.08em;
  color: var(--text-bright);
  text-shadow: 0 0 calc(12px * var(--glow-k)) var(--glow);
}
.ty-banner-label b { color: var(--accent); font-weight: 800; text-shadow: 0 0 10px var(--accent); }
.ty-banner::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 30%;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--text-bright) 32%, transparent), transparent);
  transform: translateX(-110%);
  pointer-events: none;
}
.ty-banner.is-new .ty-rule { animation: ty-rule-in 560ms cubic-bezier(.2, .9, .2, 1) both; }
.ty-banner.is-new .ty-banner-label { animation: ty-label-in 520ms cubic-bezier(.2, 1.4, .3, 1) both; }
.ty-banner.is-new::after { animation: ty-sweep 900ms cubic-bezier(.4, 0, .2, 1) 160ms both; }
@keyframes ty-rule-in { from { transform: scaleX(0); opacity: 0; } }
@keyframes ty-label-in {
  0% { opacity: 0; transform: scale(0.7); color: #fff; }
  50% { opacity: 1; }
}
@keyframes ty-sweep { to { transform: translateX(380%); } }

/* ───────── printed messages ───────── */
.ty-msg {
  padding-left: var(--ty-code);
  text-indent: 0;
  font-weight: 700;
  color: var(--text-bright);
  text-shadow: var(--text-glow);
}
.ty-msg.is-new { animation: ty-msg-in 520ms cubic-bezier(.2, .9, .3, 1) both; }
@keyframes ty-msg-in {
  0% { opacity: 0; transform: translateX(-0.8em); color: #fff; text-shadow: 0 0 14px var(--text-bright); }
  50% { opacity: 1; }
}
.ty-msg::before {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(var(--ty-gutter) - 1.1ch);
  text-align: right;
}
.msg-ok, .msg-warn, .msg-err {
  background: linear-gradient(90deg, color-mix(in srgb, currentColor 16%, transparent), transparent 70%);
  box-shadow: inset 2px 0 0 currentColor;
}
.msg-ok { color: var(--good); }
.msg-warn { color: var(--warn); }
.msg-err { color: var(--bad); }
.msg-ok::before { content: '✓'; }
.msg-warn::before { content: '!'; }
.msg-err::before { content: '✕'; }

.msg-big {
  padding: 0.2em 1ch 0.3em;
  font-family: var(--font-display);
  font-size: 3rem;
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: 0.06em;
  text-align: center;
  white-space: normal;
  color: var(--text-bright);
  text-shadow: 0 0 calc(18px * var(--glow-k) + 4px) var(--accent), 0 0 3px var(--text-bright);
  background: radial-gradient(50% 60% at 50% 55%, color-mix(in srgb, var(--accent) 16%, transparent), transparent);
}
.msg-big.is-new { animation: ty-big-in 760ms cubic-bezier(.2, 1.5, .3, 1) both; }
@keyframes ty-big-in {
  0% { opacity: 0; transform: scale(0.55); color: #fff; }
  35% { opacity: 1; }
}
.msg-big.msg-ok, .msg-big.msg-warn, .msg-big.msg-err { background: none; box-shadow: none; text-shadow: 0 0 calc(18px * var(--glow-k) + 4px) currentColor; }
.msg-big::before { content: none; }

/* ───────── appended ASCII art (e.g. the pizza) ───────── */
.ty-art {
  position: relative;
  display: grid;
  justify-content: center;                        /* the art centres as one block… */
  justify-items: start;                           /* …while its rows stay left-aligned */
  margin: 0.4em 0;
  padding: 0.5em 0 0.6em var(--ty-gutter);
  font-size: min(1em, calc((100cqw - var(--ty-gutter) - 2.5rem) / (var(--cols, 40) * 0.6)));
  font-weight: 700;
  line-height: 1.12;
  text-indent: 0;
  white-space: pre;
}
.ty-art::before {
  content: '';
  position: absolute;
  inset: 0 0 0 var(--ty-gutter);
  background: radial-gradient(closest-side, color-mix(in srgb, var(--accent) 14%, transparent), transparent);
  pointer-events: none;
}
.ty-art-row { position: relative; text-shadow: 0 0 calc(10px * var(--glow-k) + 2px) currentColor; }
.ty-art-row > span { text-shadow: 0 0 calc(10px * var(--glow-k) + 2px) currentColor; }

/* ───────── clear wipe + typing heat ───────── */
.ty-wipe {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--accent) 15%, var(--text-bright) 50%, var(--accent) 85%, transparent);
  box-shadow: 0 0 18px 3px var(--glow);
  opacity: 0;
  pointer-events: none;
}
/* The beam's afterglow trails below it as it climbs. */
.ty-wipe::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 0;
  right: 0;
  height: 3.5rem;
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 22%, transparent), transparent);
}
.ty-heat {
  position: absolute;
  inset: -1px;
  border: 1px solid var(--line-bright);
  border-radius: var(--radius);
  box-shadow: 0 0 calc(28px * var(--glow-k) + 6px) -2px var(--glow),
    inset 0 0 calc(44px * var(--glow-k) + 8px) -16px var(--glow);
  opacity: 0;
  pointer-events: none;
  will-change: opacity;
}

/* ───────── small screens ───────── */
@media (max-width: 599px) {
  .ty-head { height: 2.75rem; }
  .ty-tab { padding: 0 0.85em; }
  .ty-auto { padding: 0 0.85rem; }
  .ty-auto-ms { display: none; }
  /* 4.4ch leaves a 3-digit line number room (3× typing power reaches line 100 quickly). */
  .ty-body { --ty-gutter: 4.4ch; --ty-code: calc(var(--ty-gutter) + 1ch); font-size: 0.9375rem; }
  .ty-doc { padding-right: 0.75rem; }
  .msg-big { font-size: 3rem; }
}

/* ───────── reduced motion: no bloom, no squash, gentle fades ───────── */
html[data-reduced-motion="on"] .ty-line .h { animation: ty-hot-rm 160ms ease-out; }
@keyframes ty-hot-rm { from { color: var(--text-bright); } }
html[data-reduced-motion="on"] .ty.is-idle .ty-caret { animation: ty-blink-rm 2.4s ease-in-out infinite; }
@keyframes ty-blink-rm { 50% { opacity: 0.45; } }
html[data-reduced-motion="on"] .ty-auto.is-on .ty-led,
html[data-reduced-motion="on"] .ty-auto.is-on::after { animation: none; }
html[data-reduced-motion="on"] .ty-auto::after { opacity: 0; }
html[data-reduced-motion="on"] .ty-banner.is-new .ty-rule,
html[data-reduced-motion="on"] .ty-banner.is-new .ty-banner-label,
html[data-reduced-motion="on"] .ty-msg.is-new { animation: ty-fade-in 240ms ease-out both; }
html[data-reduced-motion="on"] .ty-banner.is-new::after { animation: none; }
html[data-reduced-motion="on"] .ty-ink { transition-duration: 160ms; transition-timing-function: ease-out; }
@keyframes ty-fade-in { from { opacity: 0; } }
