:root {
  --bg: #0d1117;
  --panel: #161b22;
  --border: #30363d;
  --text: #c9d1d9;
  --muted: #8b949e;
  --green: #27c93f;
  --blue: #58a6ff;
  --amber: #e3b341;
  --red: #ff5f56;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  /* Shared motion tokens: one duration + easing for every "transition" effect
     (style change, background change) so they read as the same gesture. */
  --fx-fade: 0.34s;
  --fx-ease: ease;
  --fx-poweron: 0.42s; /* CRT "power-on" when the terminal is reopened */
  --pbar-empty: #30363d; /* unfilled groove of a progress bar */
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
[hidden] { display: none !important; } /* otherwise .term-line { display:flex } overrides the hidden attribute */
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--mono);
  line-height: 1.6;
}
#net-canvas { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 0; }
/* Lift the page content above the canvas — but not the preloader, which must
   stay fixed on top (its #preloader rule would otherwise be overridden here,
   because :not(#net-canvas) carries an id's specificity). */
body > *:not(#net-canvas):not(#preloader) { position: relative; z-index: 1; }
/* Crossfade on `background` change (see fadeBackground in main.js): the canvas
   dips to near-invisible, the mode switches at the dim point, then it fades back
   — the same fade gesture as a `style` change. */
#net-canvas.refading { animation: bg-fade var(--fx-fade) var(--fx-ease) both; }
@keyframes bg-fade { 0% { opacity: 1; } 45% { opacity: 0.1; } 100% { opacity: 1; } }

.terminal { max-width: 988px; margin: 4vh auto 6vh; padding: 0 16px; }
.term-window { background: var(--bg); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.term-titlebar { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 8px;
  padding: 9px 12px; background: var(--panel); border-bottom: 1px solid var(--border); }
.tb-traffic { grid-column: 1; display: inline-flex; align-items: center; gap: 7px; justify-self: start; }
.term-title { grid-column: 2; justify-self: center; text-align: center; color: var(--muted);
  font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.tb-controls { grid-column: 3; display: inline-flex; align-items: center; gap: 12px; justify-self: end; }
.dot { width: 11px; height: 11px; border-radius: 50%; display: inline-block; }
.dot-r { background: var(--red); } .dot-y { background: var(--amber); } .dot-g { background: var(--green); }
.ctl { color: var(--muted); font-size: 11px; line-height: 1; user-select: none; }
/* The close control and the mac red dot are clickable (they minimize the terminal). */
.ctl-close, .dot-r { cursor: pointer; }

/* Fade re-render played on `style` change (see fadeStyle in main.js): the window
   dips in opacity and scale, the style swaps at the dim point, then it fades back
   in — a clean "re-render", ~0.34s. */
.term-window.restyling { animation: style-fade var(--fx-fade) var(--fx-ease) both; }
@keyframes style-fade {
  0%   { opacity: 1; transform: scale(1); }
  45%  { opacity: 0.25; transform: scale(0.97); }
  100% { opacity: 1; transform: scale(1); }
}

/* Power-on (CRT) when the terminal is reopened via the toggle button (see
   powerOn() in main.js): the window "switches on" — a thin bright line expands
   vertically, then the screen text fades in. */
.term-window.powering-on { animation: term-poweron var(--fx-poweron) var(--fx-ease) both; transform-origin: center; }
@keyframes term-poweron {
  0%   { opacity: 0.4; transform: scaleY(0.012); filter: brightness(2.2); }
  55%  { opacity: 1;   transform: scaleY(0.012); filter: brightness(2.2); }
  75%  { opacity: 1;   transform: scaleY(1);     filter: brightness(1.5); }
  100% { opacity: 1;   transform: scaleY(1);     filter: brightness(1); }
}
.term-window.powering-on .term-body,
.term-window.powering-on .term-title { animation: term-poweron-text var(--fx-poweron) var(--fx-ease) both; }
@keyframes term-poweron-text { 0%, 70% { opacity: 0; } 100% { opacity: 1; } }

/* Power-off (CRT) — the reverse, played when the terminal is closed (see
   powerOff() in main.js): the text fades, the screen collapses to a bright line,
   then it goes dark, after which the window is hidden and the summary appears. */
.term-window.powering-off { animation: term-poweroff var(--fx-poweron) var(--fx-ease) both; transform-origin: center; }
@keyframes term-poweroff {
  0%   { opacity: 1;   transform: scaleY(1);     filter: brightness(1); }
  25%  { opacity: 1;   transform: scaleY(1);     filter: brightness(1.5); }
  45%  { opacity: 1;   transform: scaleY(0.012); filter: brightness(2.2); }
  100% { opacity: 0.4; transform: scaleY(0.012); filter: brightness(2.2); }
}
.term-window.powering-off .term-body,
.term-window.powering-off .term-title { animation: term-poweroff-text var(--fx-poweron) var(--fx-ease) both; }
@keyframes term-poweroff-text { 0% { opacity: 1; } 30%, 100% { opacity: 0; } }

/* mac: traffic lights at left, title centered, no right-hand controls */
.style-mac .tb-controls { display: none; }
/* windows: title left, square line controls at right */
.style-windows { border-radius: 6px; }
.style-windows .term-titlebar { grid-template-columns: auto 1fr auto; }
.style-windows .tb-traffic { display: none; }
.style-windows .term-title { justify-self: start; text-align: left; }
.style-windows .ctl-close:hover { color: var(--red); }
/* linux (GNOME-like): title centered, round controls at right */
.style-linux { border-radius: 8px; }
.style-linux .tb-traffic { display: none; }
.style-linux .ctl { display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%; background: rgba(255, 255, 255, 0.07); }
.term-avatar { display: block; width: 96px; height: 96px; border-radius: 50%; object-fit: cover;
  margin: 0 auto 18px; border: 2px solid var(--green); background: var(--panel); }
.term-body { padding: 14px 16px; height: clamp(340px, 56vh, 560px); overflow-y: auto; cursor: text; font-size: 14px;
  scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
.term-body::-webkit-scrollbar { width: 10px; }
.term-body::-webkit-scrollbar-track { background: var(--bg); }
.term-body::-webkit-scrollbar-thumb { background: var(--border); border-radius: 6px; border: 2px solid var(--bg); }
.term-body::-webkit-scrollbar-thumb:hover { background: #3f4651; }
.term-line { display: flex; align-items: baseline; gap: 6px; }
.term-prompt { white-space: nowrap; color: var(--green); }
.c-sep { color: var(--muted); } .c-path { color: var(--blue); }
.term-input { flex: 1; min-width: 0; background: transparent; border: none; outline: none;
  color: var(--text); caret-color: var(--text); font-family: var(--mono); font-size: 14px; padding: 0; }
.line-title { color: #fff; }
.line-muted, .line-help { color: var(--muted); }
.line-error { color: var(--red); }
.line-accent { color: var(--amber); }
.line-solved { color: var(--green); } /* a `solve` bar that reached 100% */
/* the final "all solved" line blinks three times when it appears, then stays */
.line-solved.blink3 { animation: solve-blink 0.3s steps(1) 3 both; }
@keyframes solve-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
/* Progress bar (skills / solve): the filled part is a solid CSS gradient rather
   than '█' glyphs, so there are no sub-pixel seams between cells. The track is a
   run of monospace spaces (width) and the row is white-space:pre so the padded
   label lines up. currentColor = the row's colour (muted / green / red). */
.pbar-row { white-space: pre; }
.pbar { position: relative; display: inline-block; }
.pbar::before {
  content: ""; position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%);
  height: 1.05em; border-radius: 1px;
  background: linear-gradient(to right,
    currentColor 0, currentColor var(--pct, 0%),
    var(--pbar-empty) var(--pct, 0%), var(--pbar-empty) 100%);
}
.line-skill::before { content: "▸ "; color: var(--green); }
.line-link a { color: var(--blue); text-decoration: none; }
.line-link a:hover { text-decoration: underline; }
/* Typewriter caret: a thin blinking bar ("|"), matching the input's text caret
   instead of a solid block, so the cursor looks the same while the terminal
   "types" and while you type. */
.type-caret { display: inline-block; width: 2px; height: 1.1em; margin-left: 1px;
  background: var(--text); vertical-align: text-bottom; animation: caret-blink 1s steps(1) infinite; }
@keyframes caret-blink { 50% { opacity: 0; } }

/* Preloader: a full-screen black overlay present in the markup from first paint,
   so the summary never flashes before the terminal is ready. JS fills it (boot
   log or logo) and removes it (.done); a CSS safety fade clears it even if
   scripting stalls. */
#preloader { position: fixed; inset: 0; z-index: 9999; background: #000; color: var(--green);
  font-family: var(--mono); display: flex; overflow: hidden;
  animation: preloader-safety 0.4s ease 6s forwards; }
@keyframes preloader-safety { to { opacity: 0; visibility: hidden; } }
#preloader.done { opacity: 0; visibility: hidden; transition: opacity 0.25s ease; }
/* boot-log variant */
#preloader.pl-boot { align-items: flex-start; justify-content: flex-start; padding: 18px 20px;
  font-size: 13px; line-height: 1.6; }
#preloader .pl-log { white-space: pre-wrap; }
#preloader .pl-cursor { display: inline-block; width: 8px; height: 14px; background: var(--green);
  vertical-align: middle; animation: caret-blink 1s steps(1) infinite; }
/* cursor + logo variant */
#preloader.pl-logo { flex-direction: column; align-items: center; justify-content: center; gap: 16px; }
#preloader .pl-brand { color: var(--muted); font-size: 13px; }
#preloader .pl-mark { color: var(--green); font-size: 34px; font-weight: bold; }
#preloader .pl-mark .pl-bar { animation: caret-blink 1s steps(1) infinite; }
#preloader .pl-loader { width: 180px; height: 3px; background: var(--border); border-radius: 2px; overflow: hidden; }
#preloader .pl-loader i { display: block; height: 100%; width: 0; background: var(--green);
  animation: pl-fill 0.7s ease forwards; }
@keyframes pl-fill { to { width: 100%; } }

.tok-bold { font-weight: 700; color: #fff; }
.tok-link { color: var(--blue); text-decoration: none; }
.tok-link:hover { text-decoration: underline; }

/* The toggle button lives below the window and is shown (see setMinimized in
   main.js) only while the terminal is closed — its job is to reopen it. */
.term-controls { text-align: center; margin-top: 16px; }
.less-btn { background: transparent; color: var(--green); border: 1px solid var(--green);
  border-radius: 6px; padding: 6px 16px; font-family: var(--mono); font-size: 13px; cursor: pointer; }
.less-btn:hover { background: rgba(39, 201, 63, 0.1); }

.scroll { max-width: 760px; margin: 0 auto; padding: 8px 16px 8vh; font-size: 14px; }
.block { padding: 14px 0; }
.block + .block { border-top: 1px solid var(--border); }
.block h1 { color: #fff; font-size: 16px; font-weight: bold; margin: 0 0 2px; }
.block .role { color: var(--green); margin: 0 0 10px; }
.block h2 { color: var(--blue); font-size: 14px; font-weight: bold; margin: 0 0 6px; }
.skills-list, .social-list { list-style: none; padding: 0; margin: 0; }
.skills-list li::before { content: "▸ "; color: var(--green); }
.social-list a { color: var(--blue); text-decoration: none; }
.social-note { color: var(--muted); margin-top: 10px; font-style: italic; }
/* skills, when the terminal is minimized: the same "always evolving" gag as the
   `skills` command, instead of a list. */
.skills-evolving { color: var(--muted); font-style: italic; margin: 0; }
.social-list a:hover { text-decoration: underline; }
.site-footer { text-align: center; color: var(--muted); padding: 4vh 16px; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
