/* Self-hosted so the page never contacts a third party for type.
   Google Fonts otherwise sees the IP of every visitor, and it is two more
   origins that have to be allowed in the CSP. Latin subset only: the only
   non-ASCII characters on the site are the en and em dash. Fetched from
   Google Fonts; JetBrains Mono and Inter are both SIL Open Font License. */

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/inter-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/inter-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/inter-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/inter-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/jetbrains-mono-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/jetbrains-mono-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/jetbrains-mono-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* kudzayimwashita.com
   ---------------------------------------------------------------------------
   Two independent token layers:

   1. PAGE tokens (--bg, --ink, --brand …) flip between light and dark. Light is
      the default and dark follows the visitor's OS setting, because most people
      reading a portfolio are on a bright screen in an office.

   2. TERMINAL tokens (--t-*) are always dark, in both appearances. A console
      embedded in a light page is how it is supposed to look, and it stops the
      console fighting the page for attention.

   Every text colour is checked against its own background: page text is AA or
   better (worst 5.90:1), terminal text is AAA throughout (worst 7.76:1).
   --------------------------------------------------------------------------- */

:root {
  /* ---- type scale ----
     Every page-chrome size resolves to one of these five steps. The terminal
     and lab panes keep their own mono sizes; a console legitimately sets type
     tighter than a document does. */
  --fs-label: 12px;    /* uppercase section labels and eyebrows */
  --fs-micro: 13px;    /* meta labels, links, captions */
  --fs-small: 14px;    /* meta values, fact captions, chips */
  --fs-body:  15.5px;  /* body copy, buttons, list items */
  --fs-lead:  18px;    /* card names and entry titles */
  --fs-intro: 17px;    /* section intro paragraphs (also the body base) */

  /* ---- page: light ---- */
  --bg:        #f7f9fc;
  --surface:   #ffffff;
  --surface-2: #edf2f8;
  --line:      #cbd8e6;
  --line-soft: #e2eaf3;
  --ink:       #0f1c2b;   /* 16.3:1 */
  --ink-2:     #3a4f64;   /*  8.0:1 */
  --ink-3:     #4a5f73;   /*  6.3:1 */
  --brand:     #0a5fa8;   /* fills; white on it 6.5:1 */
  --brand-txt: #095694;   /* brand-coloured text, 7.2:1 */
  --brand-deep:#084d8a;
  --brand-tint: rgba(10, 95, 168, 0.08);
  --on-brand:  #ffffff;
  --shadow:    0 1px 2px rgba(15,28,43,.05), 0 12px 32px rgba(15,28,43,.09);
  --shadow-lg: 0 2px 6px rgba(15,28,43,.06), 0 30px 70px rgba(15,28,43,.16);

  /* ---- terminal: always dark ---- */
  --t-bg:      #0b121a;
  --t-panel:   #0f1822;
  --t-raise:   #16212c;
  --t-line:    #22323f;
  --t-fg:      #dbe7f3;   /* 15.0:1 */
  --t-dim:     #93a9be;   /*  7.8:1 */
  --t-accent:  #5ec8ff;   /* 10.0:1 — cyan, to sit with the blue brand */
  --t-accent-dk: #14587f;
  --t-tint:    rgba(94, 200, 255, 0.13);
  --t-warn:    #f5c451;
  --t-err:     #ff9090;
  --t-link:    #7fd9ff;

  --mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  --ui:   "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, sans-serif;
  --r: 12px;
  --pad: 24px;
}

/* dark page: OS preference, unless the visitor has explicitly asked for light */
@media (prefers-color-scheme: dark) {
  :root:not([data-appearance="light"]) {
    --bg:        #0d141d;
    --surface:   #121b26;
    --surface-2: #1a2531;
    --line:      #27374a;
    --line-soft: #1b2733;
    --ink:       #e7eef6;   /* 15.8:1 */
    --ink-2:     #b4c4d4;   /* 10.4:1 */
    --ink-3:     #90a5b9;   /*  7.3:1 */
    --brand:     #5cb0f2;
    --brand-txt: #7cc2f7;
    --brand-deep:#3f98dd;
    --brand-tint: rgba(92, 176, 242, 0.13);
    --on-brand:  #08151f;
    --shadow:    0 1px 2px rgba(0,0,0,.4), 0 12px 32px rgba(0,0,0,.42);
    --shadow-lg: 0 2px 6px rgba(0,0,0,.45), 0 30px 70px rgba(0,0,0,.55);
  }
}
/* and the explicit override, which wins in both directions */
:root[data-appearance="dark"] {
  --bg:        #0d141d;
  --surface:   #121b26;
  --surface-2: #1a2531;
  --line:      #27374a;
  --line-soft: #1b2733;
  --ink:       #e7eef6;
  --ink-2:     #b4c4d4;
  --ink-3:     #90a5b9;
  --brand:     #5cb0f2;
  --brand-txt: #7cc2f7;
  --brand-deep:#3f98dd;
  --brand-tint: rgba(92, 176, 242, 0.13);
  --on-brand:  #08151f;
  --shadow:    0 1px 2px rgba(0,0,0,.4), 0 12px 32px rgba(0,0,0,.42);
  --shadow-lg: 0 2px 6px rgba(0,0,0,.45), 0 30px 70px rgba(0,0,0,.55);
}

/* terminal phosphor — an in-console preference, independent of page appearance */
:root[data-theme="green"] { --t-accent: #4ade80; --t-accent-dk: #17663c; --t-tint: rgba(74,222,128,.13); --t-link: #7fd9ff; }
:root[data-theme="amber"] { --t-accent: #f5b74f; --t-accent-dk: #7a5312; --t-tint: rgba(245,183,79,.13); --t-link: #ffd98a; }

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--ui);
  font-size: var(--fs-intro);
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
a { color: var(--brand-txt); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }
h1, h2, h3 { line-height: 1.22; margin: 0; letter-spacing: -0.02em; }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: 5px; }

.skip { position: absolute; left: -9999px; top: 8px; z-index: 2000; background: var(--surface); color: var(--brand-txt); padding: 10px 16px; border: 1px solid var(--line); border-radius: var(--r); }
.skip:focus { left: 12px; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.band, .hero, .foot { max-width: 1140px; margin: 0 auto; padding: 0 var(--pad); }
.hero.centred { text-align: center; }
.hero.centred .cta { justify-content: center; }

/* ---------------- header ---------------- */

header.bar {
  position: sticky; top: 0; z-index: 500;
  display: flex; align-items: center; gap: 18px;
  padding: 13px max(var(--pad), calc((100vw - 1140px) / 2));
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
}
.brand {
  font-family: var(--mono); font-weight: 700; letter-spacing: 0.06em;
  color: var(--ink); font-size: var(--fs-body); white-space: nowrap;
}
.brand:hover { text-decoration: none; }
.brand span { color: var(--ink-3); font-weight: 400; }
.led { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 9px; background: #21b26b; box-shadow: 0 0 0 3px rgba(33,178,107,.18); }

.bar nav { margin-left: auto; display: flex; align-items: center; gap: 2px; flex-wrap: wrap; }
.bar nav a {
  color: var(--ink-2); font-size: var(--fs-small); padding: 7px 13px; border-radius: 8px;
  transition: color .14s, background .14s;
}
.bar nav a:hover { color: var(--brand-txt); background: var(--brand-tint); text-decoration: none; }
.themebtn {
  background: var(--surface); border: 1px solid var(--line); color: var(--ink-2);
  width: 36px; height: 36px; border-radius: 9px; cursor: pointer; margin-left: 8px;
  font-size: var(--fs-body); line-height: 1; display: grid; place-items: center;
}
.themebtn:hover { color: var(--brand-txt); border-color: var(--brand); }

/* ---------------- hero ---------------- */

.hero { padding-top: 76px; padding-bottom: 60px; display: grid; grid-template-columns: minmax(0,1.45fr) minmax(300px,.85fr); gap: 56px; align-items: start; }
.pill {
  display: inline-flex; align-items: center; gap: 9px; font-size: var(--fs-micro); font-weight: 500;
  color: #0d7a4c; background: rgba(33,178,107,.11); border: 1px solid rgba(33,178,107,.32);
  padding: 5px 13px; border-radius: 999px; margin-bottom: 22px;
}
@media (prefers-color-scheme: dark) { :root:not([data-appearance="light"]) .pill { color: #4ad493; } }
:root[data-appearance="dark"] .pill { color: #4ad493; }
.pill i { width: 7px; height: 7px; border-radius: 50%; background: #21b26b; }

.eyebrow { font-family: var(--mono); font-size: var(--fs-micro); letter-spacing: 0.13em; text-transform: uppercase; color: var(--brand-txt); margin: 0 0 14px; font-weight: 500; }
.hero h1 { font-size: clamp(42px, 6.4vw, 68px); font-weight: 700; letter-spacing: -0.035em; margin: 0 0 18px; }
.lede { font-size: clamp(17px, 1.9vw, 20px); color: var(--ink-2); max-width: 62ch; margin: 0; }

.cta { display: flex; gap: 12px; flex-wrap: wrap; margin: 32px 0 0; }
.btn {
  display: inline-block; padding: 13px 24px; border-radius: 10px; font-size: var(--fs-body);
  font-weight: 600; border: 1px solid var(--line); color: var(--ink);
  background: var(--surface); box-shadow: var(--shadow);
  transition: border-color .15s, background .15s, transform .1s, color .15s, box-shadow .15s;
}
.btn:hover { border-color: var(--brand); color: var(--brand-txt); text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn.primary { background: var(--brand); color: var(--on-brand); border-color: var(--brand); }
.btn.primary:hover { background: var(--brand-deep); border-color: var(--brand-deep); color: var(--on-brand); }

/* profile card */
.pcard {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  padding: 26px; box-shadow: var(--shadow); position: sticky; top: 84px;
}
.avatar {
  width: 76px; height: 76px; border-radius: 50%; object-fit: cover; display: grid;
  place-items: center; font-family: var(--mono); font-weight: 700; font-size: 26px;
  letter-spacing: .02em; color: #fff; margin-bottom: 16px;
  background: linear-gradient(140deg, #0a5fa8, #10a2b8);
  box-shadow: 0 6px 18px rgba(10,95,168,.32);
}
.pcard h2 { font-size: var(--fs-lead); margin-bottom: 2px; }
.pcard .prole { color: var(--brand-txt); font-size: var(--fs-small); font-weight: 500; margin: 0 0 16px; }
.pmeta { list-style: none; margin: 0; padding: 16px 0 0; border-top: 1px solid var(--line-soft); font-size: var(--fs-small); }
.pmeta li { display: flex; gap: 10px; padding: 5px 0; color: var(--ink-2); }
.pmeta b { color: var(--ink-3); font-weight: 500; min-width: 74px; flex: none; font-size: var(--fs-micro); }

/* trust row */
.trust { grid-column: 1 / -1; margin-top: 14px; border-top: 1px solid var(--line); padding-top: 26px; }
.trust p { margin: 0 0 12px; font-size: var(--fs-label); letter-spacing: .15em; text-transform: uppercase; color: var(--ink-3); }
.trust ul { list-style: none; display: flex; flex-wrap: wrap; gap: 10px 28px; margin: 0; padding: 0; }
.trust li { font-size: var(--fs-body); font-weight: 600; color: var(--ink-2); }

.facts {
  grid-column: 1 / -1; list-style: none; margin: 40px 0 0; padding: 30px 0 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(185px, 1fr)); gap: 24px;
  border-top: 1px solid var(--line);
}
.facts b { display: block; font-family: var(--mono); font-size: 32px; font-weight: 700; color: var(--brand-txt); letter-spacing: -0.03em; line-height: 1.1; }
.facts span { display: block; color: var(--ink-3); font-size: var(--fs-small); margin-top: 8px; }

/* ---------------- bands ---------------- */

.band { padding-top: 74px; padding-bottom: 6px; scroll-margin-top: 70px; }
/* the console is jumped to directly, so it carries less lead-in */
#console { padding-top: 48px; }
.band-head { margin-bottom: 22px; max-width: 72ch; }
.band-head h2 { font-size: clamp(26px, 3.2vw, 35px); margin-bottom: 12px; }
.band-head p { color: var(--ink-2); margin: 0; font-size: var(--fs-intro); }

/* ---------------- console window ---------------- */

.shell {
  border-radius: 14px; overflow: hidden; position: relative;
  /* A bezel with real thickness rather than a 1px outline. The light edge along
     the top and the dark one along the bottom are what make it read as a raised
     object instead of a rectangle. */
  padding: 3px;
  background: linear-gradient(180deg, #33414f, #171f28 38%, #0d141b);
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, .55),
    inset 0 1px 0 rgba(255, 255, 255, .16),
    inset 0 -1px 0 rgba(0, 0, 0, .5),
    var(--shadow-lg);
}
.shell > * { position: relative; z-index: 1; }
/* Glass: one soft highlight across the top and a gentle inner vignette. Kept
   deliberately weak — anything stronger sits over the text and costs contrast,
   which is the opposite of what this site was tuned for. */
.shell::after {
  content: ""; position: absolute; inset: 3px; border-radius: 11px;
  pointer-events: none; z-index: 2;
  /* .04 not .05: at .05 the highlight lifts the background enough to drop
     dim terminal text to 6.93:1, just under the 7:1 the rest of the site
     holds to. Measured, not guessed. */
  background: linear-gradient(177deg, rgba(255,255,255,.04), rgba(255,255,255,0) 42%);
  box-shadow: inset 0 0 70px rgba(0, 0, 0, .34);
}
.shellbar {
  display: flex; align-items: center; gap: 8px; padding: 11px 16px;
  border-bottom: 1px solid var(--t-line);
  background: linear-gradient(180deg, #1d2835, var(--t-raise));
  border-radius: 11px 11px 0 0;
}
.shellbar span { font-family: var(--mono); font-size: 12.5px; color: var(--t-dim); margin-left: 8px; }
.dot { width: 11px; height: 11px; border-radius: 50%; display: inline-block;
  box-shadow: inset 0 1px 1px rgba(255,255,255,.4), inset 0 -1px 1px rgba(0,0,0,.32); }
.dot.r { background: #ff5f57; } .dot.y { background: #febc2e; } .dot.g { background: #28c840; }

.shellbody {
  display: flex; background: var(--t-bg); border-radius: 0 0 11px 11px;
  /* 330px is the chrome above it: sticky header + scroll offset + band
     heading + title bar. Fixed heights hid the input row on any viewport
     shorter than ~1000px. The extra ~16px keeps the window from kissing
     the bottom edge, which reads as clipped even when it is not. */
  height: min(620px, calc(100dvh - 350px));
  min-height: 320px;
}

.term { flex: 1; min-width: 0; display: flex; flex-direction: column; padding: 15px 18px 0; overflow: hidden; }
body.lab-open .term { display: none; }

#boot {
  display: flex; align-items: center; gap: 12px; flex: none; margin-bottom: 12px;
  padding: 9px 13px; border: 1px solid var(--t-line); border-radius: 8px;
  background: var(--t-raise); color: var(--t-dim);
  font-family: var(--mono); font-size: 12.5px; line-height: 1.5;
}
#boot.gone { display: none; }
#boot .b-meter { flex: none; width: 74px; height: 3px; background: var(--t-line); overflow: hidden; border-radius: 2px; }
#boot .b-meter > i { display: block; height: 100%; width: 40%; background: var(--t-accent); animation: slide 1.15s ease-in-out infinite; }
@keyframes slide { 0% { transform: translateX(-110%); } 100% { transform: translateX(300%); } }
@media (prefers-reduced-motion: reduce) { #boot .b-meter > i { animation: none; width: 100%; } }

#screen {
  flex: 1; overflow: auto; white-space: pre-wrap; word-break: break-word;
  font-family: var(--mono); font-size: 13.5px; line-height: 1.64; color: var(--t-fg);
  padding-bottom: 10px; scrollbar-width: thin; scrollbar-color: var(--t-line) transparent;
  scrollbar-gutter: stable;
}
#screen::-webkit-scrollbar { width: 9px; height: 9px; }
#screen::-webkit-scrollbar-thumb { background: var(--t-line); border-radius: 5px; }

.out  { color: var(--t-fg); }
.dim  { color: var(--t-dim); }
.ok   { color: var(--t-accent); }
.warn { color: var(--t-warn); }
.err  { color: var(--t-err); }
.head { color: var(--t-accent); font-weight: 700; letter-spacing: 0.08em; margin-top: 3px; }
.art  { white-space: pre; }   /* column-aligned output scrolls rather than wraps */
.echo { color: var(--t-dim); margin-top: 8px; }
.echo b { color: var(--t-fg); font-weight: 500; }

.inputrow { display: flex; align-items: center; gap: 9px; flex: none; border-top: 1px solid var(--t-line); padding: 11px 0 13px; font-family: var(--mono); font-size: 13.5px; }
#prompt { color: var(--t-accent); white-space: nowrap; font-weight: 500; }
#cmdline { flex: 1; min-width: 0; background: transparent; border: none; outline: none; color: var(--t-fg); font: inherit; caret-color: var(--t-accent); }
#cmdline::placeholder { color: var(--t-dim); opacity: .85; }

.chips { display: flex; gap: 6px; flex-wrap: wrap; padding: 0 0 11px; flex: none; }
.chip { background: var(--t-raise); border: 1px solid var(--t-line); color: var(--t-dim); border-radius: 999px; padding: 5px 13px; font-family: var(--mono); font-size: 12px; cursor: pointer; transition: color .14s, border-color .14s, background .14s; }
.chip:hover { color: var(--t-accent); border-color: var(--t-accent-dk); background: var(--t-tint); }

/* ---------------- console sidebar ---------------- */

aside { width: 288px; flex: none; border-left: 1px solid var(--t-line); background: var(--t-panel); overflow-y: auto; padding: 16px; font-family: var(--mono); }
.panel { margin-bottom: 22px; }
.panel h2 { margin: 0 0 10px; font-size: 10.5px; letter-spacing: 0.16em; font-weight: 600; color: var(--t-dim); text-transform: uppercase; font-family: var(--ui); }
#radar { width: 100%; height: auto; display: block; }
#radar { cursor: grab; }
#radar:active { cursor: grabbing; }
#radar .ring { fill: none; stroke: var(--t-line); stroke-width: 1; }
#radar .link { stroke: var(--t-line); stroke-width: 1; }
#radar .link.on { stroke: var(--t-accent); opacity: .4; }
#radar .link.off { stroke-dasharray: 2 4; opacity: .6; }
#radar .node circle { fill: var(--t-bg); stroke: var(--t-accent); stroke-width: 1.7; cursor: pointer; transition: r .18s; }
#radar .node.full circle { fill: var(--t-accent); }
#radar .node.gw circle { fill: var(--t-accent); }
#radar .node.ghost circle { fill: none; stroke: var(--t-dim); stroke-width: 1.2; opacity: .45; cursor: default; }
#radar .node:not(.ghost):hover circle { r: 8; }
#radar .sweep path { fill: var(--t-accent); opacity: .07; }
#radar .sweep { transform-box: view-box; transform-origin: 130px 92px; animation: sweep 5s linear infinite; }
@keyframes sweep { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { #radar .sweep { animation: none; opacity: 0; } }

.meter { height: 5px; background: var(--t-bg); border: 1px solid var(--t-line); border-radius: 3px; overflow: hidden; margin: 7px 0 9px; }
.meter > i { display: block; height: 100%; width: 0; background: var(--t-accent); transition: width .5s cubic-bezier(.2,.7,.3,1); }
.stat { display: flex; justify-content: space-between; font-size: 12.5px; color: var(--t-dim); padding: 1px 0; }
.stat b { color: var(--t-fg); font-weight: 500; }
.hostlist, .achlist { list-style: none; margin: 0; padding: 0; font-size: 12.5px; }
.hostlist li, .achlist li { padding: 3px 0; color: var(--t-dim); display: flex; gap: 8px; align-items: baseline; }
.hostlist li.on { color: var(--t-fg); cursor: pointer; border-radius: 4px; }
.hostlist li.on:hover { color: var(--t-accent); background: var(--t-tint); }
.hostlist li.done { color: var(--t-accent); }
.hostlist .ip { color: var(--t-dim); font-size: 11.5px; }
.achlist li.got { color: var(--t-accent); }
.achlist .mark { width: 1em; flex: none; }

/* ---------------- lab panel ---------------- */

#lab { flex: 1; min-width: 0; display: flex; flex-direction: column; padding: 15px 18px 13px; overflow: hidden; gap: 11px; font-family: var(--mono); color: var(--t-fg); }
#lab[hidden] { display: none; }
.lab-bar { display: flex; align-items: flex-start; gap: 14px; flex: none; }
#lab-title { color: var(--t-accent); font-weight: 700; letter-spacing: 0.04em; }
#lab-sub { display: none; }
.lbtn.close { margin-left: auto; }
.lab-ctl { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; flex: none; padding: 9px 12px; border: 1px solid var(--t-line); border-radius: 8px; background: var(--t-panel); }
/* min-width:0 so a control can shrink below its content: a flex item
   defaults to min-width:auto, so one long <option> stretched the whole
   control past the panel edge on a phone. */
.ctl { display: flex; align-items: center; gap: 7px; font-size: 11px; color: var(--t-dim); min-width: 0; }
.ctl > span { letter-spacing: 0.1em; text-transform: uppercase; font-family: var(--ui); }
.ctl select { background: var(--t-raise); color: var(--t-fg); border: 1px solid var(--t-line); border-radius: 6px; padding: 4px 7px; font: inherit; font-size: 12px; cursor: pointer; min-width: 0; max-width: 100%; text-overflow: ellipsis; }
.ctl input[type="range"] { width: 88px; accent-color: var(--t-accent); cursor: pointer; }
.lbtn { background: var(--t-raise); border: 1px solid var(--t-line); color: var(--t-dim); border-radius: 999px; padding: 5px 14px; font: inherit; font-size: 11.5px; cursor: pointer; transition: color .14s, border-color .14s, background .14s; }
.lbtn:hover { color: var(--t-accent); border-color: var(--t-accent-dk); background: var(--t-tint); }
.lbtn.primary { color: var(--t-accent); border-color: var(--t-accent-dk); background: var(--t-tint); font-weight: 500; }
.lab-stage {
  flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column;
  align-items: center; gap: 10px; border: 1px solid var(--t-line); border-radius: 8px;
  background: var(--t-bg); padding: 14px;
  /* Reserve the scrollbar track always. Without it the stage oscillates when
     content lands exactly on the overflow threshold: the bar appears, narrows
     the content, the content fits, the bar goes away, and it loops visibly. */
  scrollbar-gutter: stable;
}
.lab-stage canvas { max-width: 100%; height: auto; border: 1px solid var(--t-line); border-radius: 5px; image-rendering: pixelated; background: var(--t-bg); }
.lnote { margin: 0; color: var(--t-dim); font-size: 12.5px; text-align: center; max-width: 90ch; }
.lnote.ok { color: var(--t-accent); }
.lnote.err { color: var(--t-err); }
.lab-stats { display: flex; gap: 8px; flex-wrap: wrap; flex: none; min-height: 26px; }
.lstat { display: flex; gap: 8px; align-items: baseline; font-size: 11.5px; border: 1px solid var(--t-line); border-radius: 999px; padding: 3px 12px; background: var(--t-panel); }
.lstat span { color: var(--t-dim); letter-spacing: 0.05em; }
.lstat b { color: var(--t-accent); font-weight: 500; }
.bars { display: flex; align-items: flex-end; gap: 2px; width: 100%; flex: 1; min-height: 180px; }
.bars > i {
  flex: 1; min-width: 2px; border-radius: 2px 2px 0 0;
  background-color: var(--t-accent-dk);
  /* a lit left edge and a shaded right one turn a flat rectangle into a
     column; layered over background-color so .hit and .done keep their colour */
  background-image: linear-gradient(90deg, rgba(255,255,255,.26),
                                    rgba(255,255,255,.04) 42%, rgba(0,0,0,.30));
  box-shadow: inset 0 2px 0 rgba(255,255,255,.28);
  transition: height .05s linear;
}
.bars > i.hit { background-color: var(--t-warn); }
.bars > i.done { background-color: var(--t-accent); }
.split { display: flex; gap: 12px; width: 100%; flex: 1 1 auto; min-height: 0; }
.pane { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.pane-h { font-family: var(--ui); font-size: 10.5px; letter-spacing: 0.15em; text-transform: uppercase; color: var(--t-dim); }
.pane textarea { flex: 1; min-height: 90px; resize: vertical; background: var(--t-panel); color: var(--t-fg); border: 1px solid var(--t-line); border-radius: 6px; padding: 10px 12px; font: inherit; font-size: 12.5px; line-height: 1.65; outline: none; tab-size: 2; }
.pane textarea:focus { border-color: var(--t-accent-dk); box-shadow: 0 0 0 3px var(--t-tint); }
.pane-b { flex: 1; margin: 0; overflow: auto; background: var(--t-panel); border: 1px solid var(--t-line); border-radius: 6px; padding: 10px 12px; font-size: 12px; color: var(--t-fg); white-space: pre; min-height: 90px; }
.hrow { display: flex; align-items: center; gap: 9px; font-size: 12px; padding: 1px 0; }
.hrow.dim { color: var(--t-dim); }
.hsym { width: 5ch; color: var(--t-warn); flex: none; }
.hbar { flex: 1; height: 6px; background: var(--t-raise); border-radius: 3px; overflow: hidden; }
.hbar > i { display: block; height: 100%; background: var(--t-accent); opacity: .85; }
.hn { width: 4ch; text-align: right; color: var(--t-dim); flex: none; }
.hrow code { width: 12ch; text-align: right; color: var(--t-link); flex: none; font-size: 11.5px; }

/* ---------------- lab cards ---------------- */

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(285px, 1fr)); gap: 18px; }
.card {
  text-align: left; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); padding: 24px; cursor: pointer; color: inherit;
  font: inherit; display: flex; flex-direction: column; gap: 10px;
  box-shadow: var(--shadow);
  transition: border-color .16s, transform .14s, box-shadow .16s;
}
.card:hover { border-color: var(--brand); transform: translateY(-3px); box-shadow: var(--shadow-lg); }
.card h3 { font-size: var(--fs-lead); color: var(--ink); }
.card p { margin: 0; color: var(--ink-2); font-size: var(--fs-body); line-height: 1.6; }
.card .tags { color: var(--ink-3); font-family: var(--mono); font-size: 11.5px; }
.card .run { margin-top: auto; padding-top: 8px; color: var(--brand-txt); font-family: var(--mono); font-size: 12.5px; font-weight: 500; }

/* ---------------- background section ---------------- */

/* One scale for this whole column. It previously ran 12 / 13 / 15 / 15.5 / 16 /
   16.5 / 17.5px with a company set smaller than a project name, which is what
   made the section read as unstructured. Four steps, and an entry title is one
   rank whether it is an employer or a project. */
.cv {
  display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); gap: 52px;
  --cv-label: var(--fs-label);
  --cv-title: var(--fs-lead);   /* a company and a project are one rank */
  --cv-meta:  var(--fs-small);
  --cv-body:  var(--fs-body);
  --cv-micro: var(--fs-micro);
}
.cv-h {
  font-size: var(--cv-label); letter-spacing: 0.15em; text-transform: uppercase;
  color: var(--ink-3); border-bottom: 1px solid var(--line);
  padding-bottom: 9px; margin: 40px 0 20px; font-weight: 600;
}
.cv-main > .cv-h:first-child, .cv-side > .cv-h:first-child { margin-top: 0; }
.cv-role {
  font-size: var(--cv-title); font-weight: 700; color: var(--ink);
  margin: 26px 0 2px; letter-spacing: -0.01em; line-height: 1.3;
}
.cv-main > .cv-h + .cv-role { margin-top: 0; }
.cv-sub { color: var(--brand-txt); margin: 0 0 8px; font-size: var(--cv-meta); font-weight: 500; }
/* framing, not a headline: it must not outrank the company above it */
.cv-lede { margin: 0 0 10px; color: var(--ink-2); font-size: var(--cv-body); font-style: italic; }
.cv ul { margin: 0 0 14px; padding-left: 20px; color: var(--ink-2); font-size: var(--cv-body); }
.cv li { margin-bottom: 9px; }
.cv .more { font-size: var(--cv-micro); margin: 0; }
.projects article { margin-bottom: 22px; }
.projects h3 { font-size: var(--cv-title); font-weight: 700; color: var(--ink); margin-bottom: 5px; line-height: 1.3; }
.projects p { margin: 0; color: var(--ink-2); font-size: var(--cv-body); }
.plink, .plink.private { font-size: var(--cv-micro); }
.skill { margin-bottom: 14px; font-size: var(--cv-body); }
.skill b { display: block; color: var(--ink); font-weight: 600; }
.skill span { color: var(--ink-3); }
ul.plain { list-style: none; margin: 0 0 6px; padding: 0; font-size: var(--cv-body); }
ul.plain li { margin-bottom: 12px; color: var(--ink-2); }
ul.plain b { display: block; color: var(--ink); font-weight: 600; }
ul.plain span { color: var(--ink-3); font-size: var(--cv-micro); }
ul.tick li { padding-left: 22px; position: relative; }
ul.tick li::before { content: "\2713"; position: absolute; left: 0; color: var(--brand-txt); font-weight: 700; }

/* ---------------- footer ---------------- */

.foot { margin-top: 86px; border-top: 1px solid var(--line); padding-top: 46px; padding-bottom: 62px; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 30px; align-items: center; }
.foot h2 { font-size: clamp(21px, 2.5vw, 27px); margin-bottom: 9px; }
.foot p { margin: 0; color: var(--ink-2); font-size: var(--fs-intro); }
.foot-links { display: flex; gap: 10px; flex-wrap: wrap; }
.colophon { grid-column: 1 / -1; color: var(--ink-3); font-size: var(--fs-small); border-top: 1px solid var(--line-soft); padding-top: 22px; margin-top: 12px; }

/* ---------------- toasts ---------------- */

#toasts { position: fixed; right: 20px; bottom: 20px; z-index: 1001; display: flex; flex-direction: column; gap: 8px; align-items: flex-end; }
.toast { background: var(--t-raise); border: 1px solid var(--t-accent-dk); border-left: 3px solid var(--t-accent); border-radius: 10px; padding: 11px 16px; max-width: 320px; font-family: var(--mono); box-shadow: 0 12px 38px rgba(0,0,0,.4); animation: rise .32s cubic-bezier(.2,.8,.3,1) both; }
.toast .t-k { color: var(--t-dim); font-size: 10px; letter-spacing: 0.15em; text-transform: uppercase; font-family: var(--ui); }
.toast .t-t { color: var(--t-accent); font-weight: 700; }
.toast .t-d { color: var(--t-fg); font-size: 12px; }
@keyframes rise { from { opacity: 0; transform: translateY(12px) scale(.97); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .toast { animation: none; } }

/* ---------------- responsive ---------------- */

@media (max-width: 1000px) {
  .hero { grid-template-columns: 1fr; gap: 34px; padding-top: 54px; }
  .pcard { position: static; }
  .cv { grid-template-columns: 1fr; gap: 10px; }
  .shellbody { flex-direction: column; height: auto; }
  .term { padding: 13px 14px 0; }
  /* same reasoning as the desktop shell: derive it from what is left,
     so the prompt cannot end up below the fold */
  #screen { height: min(44vh, calc(100dvh - 455px)); min-height: 190px; flex: none; }
  #lab { padding: 12px 14px; }
  .split { flex-direction: column; min-height: 0; }
  aside { width: auto; border-left: none; border-top: 1px solid var(--t-line); }
  #radar { max-width: 320px; margin: 0 auto; }
  .foot { grid-template-columns: 1fr; }
  #toasts { left: 12px; right: 12px; align-items: stretch; }
  .toast { max-width: none; }
}
@media (max-width: 640px) {
  :root { --pad: 18px; }
  body { font-size: 16.5px; }
  .band { padding-top: 56px; }
  .brand span { display: none; }
  header.bar { padding-top: 10px; padding-bottom: 10px; }
  .bar nav { flex-wrap: nowrap; }
  .bar nav a[href="#cv"], .bar nav a[href="#lab-strip"],
  .bar nav a[href$=".pdf"], .bar nav a[rel~="me"] { display: none; }
  /* On a phone this paragraph runs to four lines and pushes the prompt off
     screen. The terminal's own boot banner says the same thing, and someone
     who tapped "console" wants the console. */
  #console .band-head p { display: none; }
  #console .band-head { margin-bottom: 16px; }

  .cta .btn { flex: 1 1 auto; text-align: center; }
}

/* ---------- lab: the visualisation alongside its own source ---------- */

/* the sidebar is not useful while a demo is running, and the room is */
body.lab-open aside { display: none; }

/* Nor is the section heading above it. With a demo open the shell is scrolled
   to sit under the sticky header, so it can take most of the viewport — on a
   720px-tall laptop the old height left the maze at 5px per cell. */
body.lab-open .shellbody { height: min(700px, calc(100dvh - 140px)); }
.shell { scroll-margin-top: 70px; }

.stagegrid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(320px, 460px);
  gap: 12px; width: 100%; flex: 1; min-height: 0;
}
/* the text-driven demos need more of the width for themselves */
.stagegrid.text { grid-template-columns: minmax(0, 1fr) minmax(290px, 380px); }
.viz {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  min-width: 0; min-height: 0; overflow: auto;
}
/* Only the canvas may shrink. `.bars` children are sized in percent, so
   its height has to stay definite or every bar collapses to zero. */
.viz canvas { flex: 0 1 auto; min-height: 0; }
.viz .bars { flex: 1 1 auto; min-height: 170px; }
.viz .lnote { flex: none; }
.codepane { display: flex; flex-direction: column; gap: 6px; min-width: 0; min-height: 0; }
.codebox {
  flex: 1; min-height: 0; overflow: auto;
  background: var(--t-panel); border: 1px solid var(--t-line); border-radius: 7px;
  padding: 9px 0; font-size: 11px; line-height: 1.65; scrollbar-gutter: stable;
}
.cl { display: flex; gap: 9px; padding: 0 10px; white-space: pre; }
.cl .n { color: var(--t-dim); opacity: .42; width: 3ch; text-align: right; flex: none; user-select: none; }
.cl .c { min-width: 0; }
.cl.on { background: var(--t-tint); box-shadow: inset 2px 0 0 var(--t-accent); }
.cl.on .n { color: var(--t-accent); opacity: 1; }
.codenote { margin: 0; color: var(--t-dim); font-size: 11.5px; }

.tk-kw  { color: var(--t-link); }
.tk-str { color: var(--t-warn); }
.tk-com { color: var(--t-dim); font-style: italic; }
.tk-num { color: var(--t-accent); }
.tk-def { color: var(--t-accent); font-weight: 600; }

@media (max-width: 1000px) {
  /* stacked: let the demo be as tall as it needs and scroll the page, rather
     than trapping it in a fixed box with its own scrollbar */
  body.lab-open .shellbody { height: auto; }
  #lab, .lab-stage, .viz { overflow: visible; }
  .lab-stage { min-height: 0; }
  .stagegrid, .stagegrid.text { grid-template-columns: 1fr; grid-template-rows: auto auto; }
  .codebox { max-height: 240px; flex: none; }
  .viz { overflow: visible; }
}

/* project repository links */
.projects .plink { margin: 6px 0 0; font-family: var(--mono); font-size: var(--fs-micro); }
.projects .plink a { color: var(--brand-txt); }
.projects .plink.private { color: var(--ink-3); font-style: normal; }

/* ---------- the objective bar ---------- */
/* Placed directly above the input, because "what do I do now" was the thing
   the console never answered. The command is a button: you can click it
   instead of typing it. */

.objective {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; flex: none;
  margin: 0 0 10px; padding: 9px 12px;
  border: 1px solid var(--t-accent-dk); border-left: 3px solid var(--t-accent);
  border-radius: 8px; background: var(--t-tint);
  font-family: var(--mono); font-size: 12.5px;
}
.objective .o-tag {
  flex: none; color: var(--t-accent); font-weight: 700; letter-spacing: .06em;
}
.objective .o-title { color: var(--t-fg); font-weight: 500; }
.objective .o-why { color: var(--t-dim); flex: 1 1 220px; min-width: 0; }
.objective .o-cmd {
  flex: none; font: inherit; cursor: pointer;
  background: var(--t-accent); color: #06121b; border: none;
  border-radius: 999px; padding: 3px 13px; font-weight: 600;
}
.objective .o-cmd:hover { filter: brightness(1.12); }
.objective.done { border-color: var(--t-accent); }
.objective.done .o-title { color: var(--t-accent); }

.misslist { list-style: none; margin: 0; padding: 0; font-size: 12.5px; counter-reset: none; }
.misslist li { display: flex; gap: 8px; padding: 3px 0; color: var(--t-dim); align-items: baseline; }
.misslist li.got { color: var(--t-accent); }
.misslist li.now { color: var(--t-fg); }
.misslist .mark { width: 1em; flex: none; }

@media (max-width: 640px) {
  .objective .o-why { display: none; }
}
