/* ============================================================================
 *  CAL'S HOMEPAGE — stylesheet
 *  black terminal · phosphor green · deep violet · a little HUD · no glass
 * ========================================================================== */

/* ------------------------------------------------------------------ tokens */
:root {
  --bg:          #000000;
  --bg-soft:     #0a0813;
  --ink:         #e8ecf4;
  --ink-dim:     #8e96ad;
  --ink-faint:   #5a6178;

  --green:       #39ff5a;
  --green-soft:  #7dffa0;
  --green-deep:  #12b840;

  --violet:      #a06cff;
  --violet-deep: #4b2a8f;
  --violet-glow: rgba(160, 108, 255, .30);

  --warn:        #ffcf6b;
  --err:         #ff6b8a;

  --line:        rgba(160, 108, 255, .20);
  --line-soft:   rgba(160, 108, 255, .10);

  --mono: ui-monospace, "JetBrains Mono", "Cascadia Mono", "SF Mono", Menlo,
          Consolas, "DejaVu Sans Mono", "Liberation Mono", monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
          "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", sans-serif;

  --gutter-w: 18px;
  --pad-x: clamp(14px, 3.4vw, 44px);
  --rule: 1px solid var(--line);
  --dur: .5s;
  --ease: cubic-bezier(.22, .61, .36, 1);
  --cell: 11px;
}

*, *::before, *::after { box-sizing: border-box; }

/* ==========================================================================
 *  CURSOR — the system pointer is hidden and drawn by hand (assets/terminal.js)
 * ======================================================================== */
html.has-custom-cursor,
html.has-custom-cursor body,
html.has-custom-cursor a,
html.has-custom-cursor button,
html.has-custom-cursor .act,
html.has-custom-cursor .chip { cursor: none; }
/* typing still needs a real caret, so text entry keeps the I-beam */
html.has-custom-cursor input,
html.has-custom-cursor textarea { cursor: text; }

.ms {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 90;
  pointer-events: none;
  will-change: transform;
  contain: layout style;
}
.ms__ring {
  position: absolute;
  left: 0; top: 0;
  width: 26px; height: 26px;
  margin: -13px 0 0 -13px;
  border: 1px solid rgba(57, 255, 90, .40);
  border-radius: 50%;
  transition: width .18s var(--ease), height .18s var(--ease),
              margin .18s var(--ease), border-color .18s var(--ease), opacity .18s linear;
}
.ms__block {
  position: absolute;
  left: 0; top: 0;
  width: .58em; height: 1.02em;
  margin: -.51em 0 0 -.29em;
  background: var(--green);
  box-shadow: 0 0 .55em rgba(57, 255, 90, .8);
  animation: blink 1.06s steps(1, end) infinite;
}
html.ms-down .ms__ring { width: 18px; height: 18px; margin: -9px 0 0 -9px; border-color: var(--green); }
html.ms-hot .ms__block { background: #d8ffe0; box-shadow: 0 0 .9em rgba(57, 255, 90, 1); }
html.ms-text .ms__block { animation: none; }
html.ms-text .ms__ring { opacity: 0; }
html.ms-hidden .ms { opacity: 0; }

html {
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
  scrollbar-color: var(--violet-deep) transparent;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--mono);
  font-size: var(--fs, clamp(13px, 1.05vw + 9px, 16.5px));
  line-height: 1.62;
  font-variant-ligatures: none;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--green); color: #04140a; }

/* pure black. no bloom, no vignette — the colour comes from the type itself */
body::before { content: none; }

a { color: var(--green); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }
button { font: inherit; color: inherit; }

:focus-visible { outline: 1px dashed var(--green); outline-offset: 3px; }

kbd {
  font-family: var(--mono);
  font-size: .82em;
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  padding: 0 .35em;
  color: var(--ink-dim);
  background: transparent;
}

.page { position: relative; z-index: 1; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* ==========================================================================
 *  HOME — boot log, avatar, welcome words
 * ======================================================================== */
.home {
  position: relative;
  padding: clamp(26px, 5vh, 64px) var(--pad-x) clamp(18px, 4vh, 42px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
/* `gone` normally means "out of the layout" — but during the hand-off the splash
   fades, and `display:none` would skip straight to the end of that fade. */
.home:not(.home__drop)[data-home-state="gone"] { display: none; }
.home__drop {
  opacity: 0;
  transform: translateY(-9px);
  pointer-events: none;
  transition: opacity .34s linear, transform .34s var(--ease);
}
.home.is-fast { --dur: .001s; }
.home.is-fast.home__drop { transition-duration: .16s; }

/* --- cold boot: the page is scroll-locked while the intro plays -------------
   The intro is taller than one screen, so anything that scrolls the window
   (the log growing, the avatar lighting up row by row) would carry the avatar
   and the greeting out of view — the splash would be a flash nobody sees.
   Anchoring is disabled too: the browser otherwise "helps" by keeping a growing
   element in view, which has exactly the same effect. */
html.boot-lock, html.boot-lock body { overflow: hidden; }
html.boot-lock { height: 100%; }
.boot-lock,
.boot-lock * { overflow-anchor: none; }

/* the terminal underneath is being prepared, not performed: its prompt and chrome
   stay out of the way until the splash hands over */
body.is-booting .term__prompt,
body.is-booting .term__hint,
body.is-booting .jump { visibility: hidden; }

.home__body { max-width: 1180px; margin: 0 auto; }

/* initialising line — on screen for the few ms before the log starts */
.home__idle {
  position: absolute;
  left: var(--pad-x);
  bottom: 8px;
  font-size: .8em;
  color: var(--ink-faint);
  letter-spacing: .12em;
  text-transform: uppercase;
  opacity: 1;
  transition: opacity .25s linear;
}
.home[data-home-state="boot"] .home__idle { opacity: 0; }
.home__idleGlyph { color: var(--green); margin-right: .6em; animation: pulse 1.1s steps(2, end) infinite; }

/* ---- boot log ---- */
.syslog { margin: 0 0 clamp(18px, 3.2vh, 34px); }
.sl {
  display: flex;
  gap: .6em;
  font-size: .84em;
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
  opacity: 0;
  animation: fadeIn .18s linear forwards;
}
.sl__px { color: var(--violet); }
.sl__t  { color: var(--ink-faint); }
.sl--ok   .sl__t { color: var(--ink-dim); }
.sl--warn .sl__t { color: var(--warn); }
.sl--warn .sl__px { color: var(--warn); }

/* ---- avatar + system readout ---- */
.masthead {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  align-items: start;
  gap: clamp(18px, 4vw, 54px);
  margin: 0 0 clamp(20px, 3.6vh, 40px);
}

@property --scan {
  syntax: '<number>';
  inherits: false;
  initial-value: 0;
}

.avatar { position: relative; }

/* ---- text dot-matrix portrait ----
   A grid of monospace glyphs. `--cell` is one character cell; the font size is
   derived from it, so the whole portrait scales as a single unit.            */
.avatar__art {
  display: block;
  margin: 0;
  font-family: var(--mono);
  font-size: var(--cell, 11px);
  line-height: 1;
  letter-spacing: 0;
  font-variant-ligatures: none;
  white-space: pre;
  color: var(--green);
  text-shadow: 0 0 .35em rgba(57, 255, 90, .45);
  overflow: visible;
  -webkit-user-select: none;
  user-select: none;
}
.avatar__art.is-fallback { color: var(--warn); text-shadow: none; }

.avatar.is-text { display: flex; justify-content: center; }
.avatar.is-text .avatar__art {
  /* one row of the matrix; the text itself keeps the aspect ratio.
     The glyph size is derived from the viewport rather than fixed per breakpoint:
     the portrait is 58 columns of monospace, so its width is ~35 x cell and its
     height 23 x cell. It has to clear both the text column (58ch inside the body
     margins) and, because the splash is scroll-locked while it plays, two thirds
     of the viewport height — otherwise the greeting ends up below the fold on a
     laptop or a phone held upright. */
  padding: .28em .5em .34em;
  border: 1px solid var(--line-soft);
  background: transparent;
  --cell: max(5.4px, min(11px, (100vw - 2 * var(--pad-x) - 2em) / 35, 62vh / 23));
  --scan: 0;
  clip-path: inset(0 0 calc((1 - var(--scan)) * 100%) 0);
  transition: clip-path .95s linear;
}
.avatar[data-scan="1"] .avatar__art { --scan: 1; }
.avatar[data-scan="2"] .avatar__art { clip-path: none; transition: none; }

.avatar__sig {
  position: absolute;
  right: 2%;
  bottom: -1.15em;
  font-size: .68em;
  letter-spacing: .34em;
  color: var(--violet);
  opacity: .75;
}

/* ---- system readout ---- */
.sysinfo {
  list-style: none;
  margin: 0;
  padding: 0 0 0 clamp(10px, 1.6vw, 20px);
  border-left: var(--rule);
  align-self: stretch;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: .18em;
  min-width: 0;
}
.si {
  display: grid;
  grid-template-columns: minmax(5.4em, 7.2em) minmax(0, 1fr);
  gap: .9em;
  font-size: .84em;
  line-height: 1.5;
  min-width: 0;
  opacity: 0;
  transform: translateX(-6px);
}
.si__k {
  color: var(--violet);
  text-transform: uppercase;
  letter-spacing: .1em;
  font-size: .88em;
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.si__k::after { content: ""; }
.si__v { color: var(--ink-dim); min-width: 0; overflow-wrap: anywhere; }
.si__v b { color: var(--green); font-weight: 500; }
.masthead[data-scan="1"] .si {
  animation: slideIn .42s var(--ease) forwards;
  animation-delay: calc(var(--i, 0) * 150ms);
}
.masthead[data-scan="2"] .si { opacity: 1; transform: none; animation: none; }

/* ---- welcome ---- */
.welcome { margin: clamp(14px, 3vh, 34px) 0 0; text-align: center; }
.welcome__top {
  font-size: .92em;
  letter-spacing: .62em;
  text-indent: .62em;
  color: var(--violet);
  text-shadow: 0 0 .5em var(--violet-glow);
  min-height: 1.6em;
}
.welcome__main {
  margin-top: .18em;
  font-size: clamp(19px, 4.6vw, 46px);
  line-height: 1.14;
  letter-spacing: .1em;
  font-weight: 700;
  color: var(--green);
  text-shadow: 0 0 .32em rgba(57, 255, 90, .5);
  word-break: break-word;
}
.welcome__main .car { vertical-align: middle; }

/* ---- the same greeting, living permanently in the terminal output ---- */
.line--banner {
  display: block;
  text-align: center;
  padding: clamp(10px, 2vh, 26px) 0 clamp(12px, 2.4vh, 30px);
  opacity: 0;
  animation: fadeIn .5s var(--ease) forwards;
}
.line--banner-first { padding-top: clamp(14px, 2.6vh, 34px); }
.line--banner .banner__top {
  font-size: .82em;
  letter-spacing: .58em;
  text-indent: .58em;
  color: var(--violet);
  text-shadow: 0 0 .5em var(--violet-glow);
}
.line--banner .banner__main {
  margin-top: .1em;
  font-size: clamp(17px, 3.2vw, 34px);
  line-height: 1.16;
  letter-spacing: .1em;
  font-weight: 700;
  color: var(--green);
  text-shadow: 0 0 .3em rgba(57, 255, 90, .45);
  word-break: break-word;
}
.line--banner .banner__main .car { vertical-align: middle; }

/* ---- the arrival hint: one bright violet line, blinking ---- */
.line--hint {
  display: block;
  padding: 0 0 .35em;
}
.line--hint-first { padding-top: .5em; }
.line--hint .line__body,
.line--hint .line__text {
  display: block;
}
.line--hint .line__text {
  color: var(--violet);
  font-weight: 700;
  letter-spacing: .1em;
  text-shadow: 0 0 .5em rgba(160, 108, 255, .55), 0 0 1.6em rgba(160, 108, 255, .25);
  animation: hintBlink 1.6s steps(1, end) infinite;
}
@keyframes hintBlink { 0%, 78% { opacity: 1; } 79%, 100% { opacity: .30; } }

/* ==========================================================================
 *  TERMINAL
 * ======================================================================== */
.term {
  position: relative;
  /* isolate: the output lines animate their own opacity, which would otherwise
     paint them above the sticky prompt bar */
  isolation: isolate;
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 var(--pad-x) 0;
  min-height: calc(100vh - 210px);
}

/* ---- HUD corners (kept deliberately sparse) ---- */
.term__hud { position: relative; height: 0; }
.hud__corner {
  position: absolute;
  width: 14px;
  height: 14px;
  border: 1px solid var(--line);
  opacity: 0;
  animation: fadeIn .8s var(--ease) .3s forwards;
}
.hud__corner--tl { left: -1px; top: 0; border-right: 0; border-bottom: 0; }
.hud__corner--tr { right: -1px; top: 0; border-left: 0; border-bottom: 0; }
.hud__corner--bl { left: -1px; bottom: 0; border-right: 0; border-top: 0; }
.hud__corner--br { right: -1px; bottom: 0; border-left: 0; border-top: 0; }
.hud__bar {
  position: absolute;
  right: 24px;
  top: -1.55em;
  font-size: .68em;
  letter-spacing: .22em;
  color: var(--ink-faint);
  opacity: 0;
  animation: fadeIn .8s var(--ease) .3s forwards;
}

/* ---- output stream ---- */
.term__stream {
  padding: 0 0 1.2em;
  scroll-margin-bottom: 220px;
  outline: none;
}

.line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 .6em;
  padding: .1em 0;
  opacity: 0;
  animation: fadeIn .3s var(--ease) forwards;
  animation-delay: calc(var(--i, 0) * 14ms);
  min-width: 0;
}
.line--nowrap { white-space: pre; overflow-x: auto; overflow-y: hidden; }
.line--nowrap::-webkit-scrollbar { height: 3px; }
.line--tight { padding: 0; }
.line--tiny { padding: 0; line-height: .6; }
.line--desc { padding-left: var(--gutter-w); }
.line--matrix { display: block; letter-spacing: .08em; margin: .4em 0; }

/* ---- full-screen matrix overlay ---- */
.mx-screen {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: #000;
  overflow: hidden;
  animation: fadeIn .25s linear;
  cursor: none;
}
.mx-screen__grid {
  display: grid;
  justify-content: center;
  align-content: start;
  width: 100%;
  height: 100%;
}
.mx-screen__cell {
  font-family: var(--mono);
  font-size: 15px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: transparent;
  white-space: pre;
  will-change: color;
}
.mx-screen__cell--t3 { color: rgba(57, 255, 90, .10); }
.mx-screen__cell--t2 { color: rgba(57, 255, 90, .30); }
.mx-screen__cell--t1 { color: rgba(57, 255, 90, .62); }
.mx-screen__cell--head { color: #dcffe4; text-shadow: 0 0 .55em rgba(57, 255, 90, .95); }
.mx-screen__caption {
  position: absolute;
  left: 0; right: 0; bottom: 14px;
  text-align: center;
  font-size: .72em;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: rgba(57, 255, 90, .45);
}

.line__gutter {
  flex: 0 0 auto;
  width: var(--gutter-w);
  color: var(--violet-deep);
  font-size: .9em;
  user-select: none;
}
.line--input { color: var(--ink); }
.line--input .line__gutter { color: var(--green-deep); }
.line--input .line__text { color: var(--green); }

.line__label {
  flex: 0 0 auto;
  color: var(--violet);
  min-width: 0;
}
.line__body {
  flex: 1 1 16ch;
  min-width: 0;
  overflow-wrap: anywhere;
}
.line__body--nowrap { flex: 0 0 auto; white-space: pre; }
.line__meta { flex: 0 0 auto; font-size: .9em; }
.line__actions { display: inline-flex; gap: .45em; flex-wrap: wrap; font-size: .88em; }

/* segment colours */
.sg { }
.sg--acc  { color: var(--violet); }
.sg--dim  { color: var(--ink-faint); }
.sg--good { color: var(--green); }
.sg--warn { color: var(--warn); }
.sg--b    { color: var(--ink); font-weight: 700; }
.sg--link { color: var(--green); }

/* line kinds */
.line--out .line__text { color: var(--ink); }
.line--sys { font-size: .9em; }
.line--sys .line__text { color: var(--ink-dim); }
.line--ok  { }
.line--ok .line__text { color: var(--green); text-shadow: 0 0 .35em rgba(57, 255, 90, .35); }
.line--warn .line__text { color: var(--warn); }
.line--err .line__text { color: var(--err); }
.line--link .line__text { color: var(--green-soft); }
.line--kv .line__label { min-width: 6.6em; }
.line--kv .line__text { color: var(--ink); }
.line--item .line__label { color: var(--green); }
.line--item .line__text { color: var(--ink); }
.line--cmd .line__label { min-width: 10ch; }
.line--cmd .line__text { color: var(--ink-dim); }
.line--art .line__text { color: var(--ink-dim); line-height: 1.35; }
.line--gap { line-height: .9; padding: 0; }

.line--sec {
  margin-top: .9em;
  padding-top: .35em;
  border-top: var(--rule);
}
.line--sec .line__text {
  color: var(--green);
  font-weight: 700;
  letter-spacing: .24em;
  text-transform: uppercase;
  text-shadow: 0 0 .45em rgba(57, 255, 90, .32);
}
.line--sec .line__meta { color: var(--violet); letter-spacing: .1em; }

.line--hr { padding: 0; margin: .55em 0 .1em; }
.line--hr .line__body { display: none; }
.line--hr::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(90deg, var(--line), var(--line-soft) 55%, transparent);
}

.line--matrix .mx { color: rgba(57, 255, 90, .28); }
.line--matrix .mx--trail { color: rgba(57, 255, 90, .55); }
.line--matrix .mx--head { color: #d8ffe0; text-shadow: 0 0 .5em rgba(57, 255, 90, .8); }

/* inline action chips inside output */
.act {
  font-family: var(--mono);
  font-size: .82em;
  letter-spacing: .06em;
  padding: .05em .55em;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--green);
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
  text-decoration: none;
  white-space: nowrap;
}
.act:hover { background: rgba(57, 255, 90, .12); border-color: var(--green-deep); text-decoration: none; }
.act--btn::before { content: "▸ "; color: var(--violet); }
.act.is-pending,
.act.is-pending:hover {
  color: var(--ink-faint);
  border-color: var(--line-soft);
  background: transparent;
  cursor: not-allowed;
  text-decoration: none;
}

/* ------------------------------------------------------------------ caret */
.car {
  display: inline-block;
  width: .58em;
  height: 1.02em;
  line-height: 0;
  margin-left: .14em;
  background: var(--green);
  vertical-align: middle;
  box-shadow: 0 0 .5em rgba(57, 255, 90, .75);
}
.car--ghost { background: var(--green); opacity: .9; }
.car.is-live { animation: blink 1.06s steps(1, end) infinite; }
.car.is-pulse { animation: caretPulse .34s var(--ease); }

/* ---------------------------------------------------------------- prompt */
.term__prompt {
  position: sticky;
  bottom: 0;
  z-index: 9;
  display: flex;
  /* centre, not baseline: the block caret is an inline-block whose baseline sits
     on its bottom edge, which pushed it below the typed text */
  align-items: center;
  gap: .6em;
  padding: .55em 0 .5em;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0), var(--bg) 34%, var(--bg));
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease);
  min-width: 0;
}
.term__prompt.is-live { border-bottom-color: var(--line); }
.ps1 { color: var(--green); flex: 0 0 auto; text-shadow: 0 0 .4em rgba(57, 255, 90, .3); }
.line__body--input {
  flex: 1 1 auto;
  min-width: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  color: var(--green);
}
.line__body--input .line__text { white-space: pre-wrap; overflow-wrap: anywhere; }

/* the real input: invisible but focusable, so phones raise their keyboard */
.term__input {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 2.2em;
  opacity: 0;
  border: 0;
  padding: 0;
  background: transparent;
  color: transparent;
  caret-color: transparent;
  font: inherit;
  z-index: 5;
}
.term__input::placeholder { color: transparent; }
.term__input:focus { outline: none; }

/* --------------------------------------------------------------- chip bar */
.chips {
  display: none;
  flex-wrap: wrap;
  gap: .35em .4em;
  padding: .1em 0 .6em;
}
.chips[data-on="1"] { display: flex; }
.chip {
  font-family: var(--mono);
  font-size: .8em;
  padding: .18em .7em;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--green-soft);
  cursor: pointer;
  transition: all var(--dur) var(--ease);
}
.chip:hover, .chip:active {
  background: rgba(57, 255, 90, .14);
  border-color: var(--green);
  color: var(--green);
}
.chip:nth-child(4n+2) { border-color: rgba(160, 108, 255, .26); color: var(--violet); }
.chip:nth-child(4n+2):hover { background: rgba(160, 108, 255, .14); border-color: var(--violet); }

.term__hint {
  font-size: .78em;
  color: var(--ink-faint);
  padding: 0 0 2.4em;
  letter-spacing: .04em;
}
.term__hint b { color: var(--green); font-weight: 500; }

/* ------------------------------------------------------------------ misc */
.foot {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 var(--pad-x) calc(28px + env(safe-area-inset-bottom, 0px));
  display: flex;
  align-items: center;
  gap: .6em;
  font-size: .74em;
  color: var(--ink-faint);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.foot__dot {
  width: .5em; height: .5em;
  background: var(--green);
  box-shadow: 0 0 .5em var(--green);
  animation: blink 2.4s steps(1, end) infinite;
}
.foot__sep { color: var(--violet-deep); }

.jump {
  position: fixed;
  right: 14px;
  bottom: 14px;
  z-index: 6;
  width: 2.1em;
  height: 2.1em;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  background: rgba(0, 0, 0, .86);
  color: var(--green);
  cursor: pointer;
  font-size: 1rem;
}
.jump:hover { border-color: var(--green); }

.skip {
  position: absolute;
  right: var(--pad-x);
  top: clamp(10px, 2.4vh, 26px);
  font-size: .74em;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-dim);
  background: transparent;
  border: 1px solid var(--line);
  padding: .3em .7em;
  cursor: pointer;
  opacity: 0;
  animation: fadeIn .5s var(--ease) .8s forwards;
}
.skip:hover { color: var(--green); border-color: var(--green); }

/* ==========================================================================
 *  ANIMATION
 * ======================================================================== */
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes slideIn { from { opacity: 0; transform: translateX(-7px); } to { opacity: 1; transform: none; } }
@keyframes blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes caretPulse {
  0%   { transform: scaleY(1);   box-shadow: 0 0 .5em rgba(57, 255, 90, .75); }
  35%  { transform: scaleY(1.5); box-shadow: 0 0 1.1em rgba(57, 255, 90, 1); }
  100% { transform: scaleY(1);   box-shadow: 0 0 .5em rgba(57, 255, 90, .75); }
}
@keyframes pulse { 0%, 49% { opacity: 1; } 50%, 100% { opacity: .25; } }
@keyframes msPing {
  from { transform: scale(.35); opacity: .95; }
  to   { transform: scale(6);   opacity: 0; }
}
.ms__ping {
  position: absolute;
  left: 0; top: 0;
  width: 30px; height: 30px;
  margin: -15px 0 0 -15px;
  border: 1px solid var(--green);
  border-radius: 50%;
  animation: msPing .5s var(--ease) forwards;
}

/* click burst: a green ripple from the caret */
.ripple {
  position: fixed;
  z-index: 7;
  width: 10px;
  height: 10px;
  margin: -5px 0 0 -5px;
  border: 1px solid var(--green);
  border-radius: 50%;
  pointer-events: none;
  animation: ripple .62s var(--ease) forwards;
}
@keyframes ripple {
  from { transform: scale(.4); opacity: .95; }
  to   { transform: scale(7.5); opacity: 0; }
}
.spark {
  position: fixed;
  z-index: 7;
  font-size: .8rem;
  color: var(--green);
  pointer-events: none;
  text-shadow: 0 0 .5em rgba(57, 255, 90, .8);
  animation: spark .8s var(--ease) forwards;
}
@keyframes spark {
  from { transform: translate(0, 0) scale(1); opacity: 1; }
  to   { transform: translate(var(--dx, 0), var(--dy, -18px)) scale(.5); opacity: 0; }
}

/* ==========================================================================
 *  RESPONSIVE
 * ======================================================================== */
@media (max-width: 900px) {
  .masthead { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .avatar__sig { bottom: -1.05em; }
  .sysinfo {
    border-left: 0;
    border-top: var(--rule);
    padding: 14px 0 0;
    gap: .1em;
  }
  .si { grid-template-columns: minmax(5em, 6.4em) minmax(0, 1fr); font-size: .8em; }
  .term { min-height: 60vh; }
  .welcome__top { letter-spacing: .4em; text-indent: .4em; }
}

@media (max-width: 560px) {
  :root { --gutter-w: 14px; }
  .home { padding-top: 34px; }
  .avatar.is-text .avatar__art { padding: .22em .38em .28em; }
  .si { grid-template-columns: minmax(4.4em, 5.4em) minmax(0, 1fr); gap: .6em; }
  .line--kv { display: block; }
  .line--kv .line__label { display: block; min-width: 0; }
  .line--desc { padding-left: 0; }
  .line--cmd { display: grid; grid-template-columns: minmax(8ch, auto) minmax(0, 1fr); }
  .term__hint { padding-bottom: 1.6em; }
  .foot { flex-wrap: wrap; }
}

@media (max-width: 380px) {
  .chip { font-size: .74em; padding: .16em .5em; }
}

/* Height queries: the splash has to fit one screen, because the page is
   scroll-locked while it plays. A laptop window is around 700–800px tall, where
   the default 11px cell plus the full log would push the greeting below the fold
   — the visitor would never see `WELCOME TO` at all. Trim the portrait and the
   log so the whole intro lands inside the viewport. */
@media (max-height: 900px) {
  .home { padding-top: clamp(18px, 3.4vh, 40px); }
  .welcome { margin-top: clamp(10px, 1.8vh, 22px); }
}
@media (max-height: 780px) {
  .syslog { margin-bottom: clamp(12px, 2.2vh, 22px); }
  .home { padding-bottom: clamp(14px, 2.6vh, 30px); }
}
@media (max-height: 700px) {
  .masthead { margin-bottom: clamp(14px, 2.2vh, 24px); }
  .sysinfo { gap: 0; }
  .si { font-size: .8em; }
}
@media (max-height: 620px) {
  .sl:nth-child(n+16) { display: none; }
  .welcome__main { font-size: clamp(17px, 4.6vw, 34px); }
}


/* Short viewports get the last word on the portrait size: a laptop window is
   around 700–800px tall, and a phone in portrait is 570–850px, so the `--cell`
   picked by the width queries above (sized for reading a phone in landscape) is
   far too tall here — it would push the greeting clean off the first screen. */
@media (max-height: 820px) {
}

/* ==========================================================================
 *  ACCESSIBILITY / MOTION
 * ======================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001s !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001s !important;
  }
  .car.is-live { animation: none; opacity: 1; }
  .line--hint .line__text { animation: none; opacity: 1; }
  .line { opacity: 1; }
  .si { opacity: 1; transform: none; }
  .skip { opacity: 1; }
  .hud__corner, .hud__bar { opacity: 1; }
}

@media print {
  body::before, .chips, .skip, .jump, .car { display: none !important; }
  body { color: #000; background: #fff; }
}
