/* Self-hosted so the page has no third-party dependency: the Google Fonts
   stylesheet cost a render-blocking round trip, logged 401s to the console,
   and its late swap was the whole 0.17 CLS. font-display:swap keeps text
   visible while these 60KB load. */
@font-face {
  font-family: "Space Grotesk";
  src: url("fonts/space-grotesk-var.woff2") format("woff2-variations");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}
@font-face { font-family:"IBM Plex Mono"; src:url("fonts/plex-mono-400.woff2") format("woff2"); font-weight:400; font-style:normal; font-display:swap; }
@font-face { font-family:"IBM Plex Mono"; src:url("fonts/plex-mono-500.woff2") format("woff2"); font-weight:500; font-style:normal; font-display:swap; }
@font-face { font-family:"IBM Plex Mono"; src:url("fonts/plex-mono-600.woff2") format("woff2"); font-weight:600; font-style:normal; font-display:swap; }

/* ============================================================
   krysnewman.com / knewman23.github.io
   Light-first Swiss index. Dark is an override, never a fork.
   Every colour is a token on :root so the SVG schematics,
   which use var(--…) and currentColor, invert with the page.
   ============================================================ */

:root {
  color-scheme: light;
  --bg:      #fbfbf9;
  --card:    #ffffff;
  --sunken:  #f5f5f2;
  --ink:     #0e0f11;
  --ink-2:   #2c2e33;
  --soft:    #5c5f67;
  --faint:   #71747c;
  --line:    #e2e2df;
  --line-2:  #cfcfcb;
  --accent:  #1f4ed8;
  --ok:      #0f7a4a;
  --ok-bg:   #f0faf4;
  --ok-line: #bfe3d0;
  --warn:    #85670f;
  --warn-bg: #fdf8ec;
  --warn-line:#ecdcb4;
  --dot-warn:#d9a020;
  --band-bg: #0e0f11;
  --band-ink:#ffffff;
  --band-dim:#8b8f98;
  /* A belt is a real object with a real colour, so these are literal
     rather than derived. The rank bar carries a stroke because black on
     near-black would otherwise vanish in dark. */
  --belt:    #5b2d8e;
  --belt-tip:#14161d;

  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --sans: "Space Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;

  --gut: 40px;
  --max: 1120px;
}

/* Dark is a token swap. Roles stay identical: --card is still
   "the surface above --bg", so no component needs a dark branch. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:      #0b0c0e;
  --card:    #13151a;
  --sunken:  #0f1116;
  --ink:     #edeef1;
  --ink-2:   #d2d4da;
  --soft:    #9a9da6;
  --faint:   #7b7e88;
  --line:    #22252c;
  --line-2:  #2e323b;
  --accent:  #8b9bff;
  --ok:      #55d4a0;
  --ok-bg:   rgba(85,212,160,.09);
  --ok-line: rgba(85,212,160,.24);
  --warn:    #e2b357;
  --warn-bg: rgba(226,179,87,.09);
  --warn-line:rgba(226,179,87,.24);
  --dot-warn:#e2b357;
  --band-bg: #06070a;
  --band-ink:#ffffff;
  --band-dim:#7e828d;
  --belt:    #9f7aea;
  --belt-tip:#05060a;
}

/* Respect the OS when the visitor has expressed no preference.
   Guarded on :not([data-theme="light"]) so an explicit light
   choice still wins over a dark OS. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg:#0b0c0e; --card:#13151a; --sunken:#0f1116;
    --ink:#edeef1; --ink-2:#d2d4da; --soft:#9a9da6; --faint:#7b7e88;
    --line:#22252c; --line-2:#2e323b;
    --accent:#8b9bff; --ok:#55d4a0; --ok-bg:rgba(85,212,160,.09); --ok-line:rgba(85,212,160,.24);
    --warn:#e2b357; --warn-bg:rgba(226,179,87,.09); --warn-line:rgba(226,179,87,.24); --dot-warn:#e2b357;
    --band-bg:#06070a; --band-ink:#fff; --band-dim:#7e828d;
    --belt:#9f7aea; --belt-tip:#05060a;
  }
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.wrap { max-width: var(--max); margin: 0 auto; padding: 0 var(--gut); }

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--card); color: var(--ink);
  padding: 10px 16px; z-index: 99;
  font-family: var(--mono); font-size: 12px;
  border: 1px solid var(--accent);
}
.skip:focus { left: 12px; top: 12px; }

/* shared micro-label */
.lbl {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--faint);
}

/* ---------- top band ---------- */
.band {
  background: var(--band-bg);
  color: var(--band-ink);
  position: sticky; top: 0; z-index: 10;
  border-bottom: 1px solid #23262d;
}
.band .wrap {
  display: flex; align-items: center; justify-content: space-between;
  min-height: 44px; gap: 16px;
}
.band .lbl { color: var(--band-dim); }
.band .lbl b { color: var(--band-ink); font-weight: 500; }
.band nav { display: flex; align-items: center; gap: 22px; }
.band nav a {
  font-family: var(--mono); font-size: 10px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--band-dim); text-decoration: none;
}
.band nav a:hover { color: var(--band-ink); }

/* theme toggle */
.theme {
  background: transparent;
  border: 1px solid #33373f;
  color: var(--band-dim);
  font-family: var(--mono); font-size: 10px; letter-spacing: .12em;
  text-transform: uppercase;
  padding: 5px 10px; border-radius: 2px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px;
  line-height: 1;
}
.theme:hover { color: var(--band-ink); border-color: #4b515c; }
.theme svg { width: 12px; height: 12px; }
/* Show the icon for the theme you'd switch TO. */
.theme .i-dark { display: inline; }
.theme .i-light { display: none; }
:root[data-theme="dark"] .theme .i-dark { display: none; }
:root[data-theme="dark"] .theme .i-light { display: inline; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme .i-dark { display: none; }
  :root:not([data-theme="light"]) .theme .i-light { display: inline; }
}

/* ---------- identity ---------- */
.id {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 0 24px;
  padding: 72px 0 0;
  align-items: end;
}
.id .name { grid-column: 1 / 8; }
.id h1 {
  font-size: clamp(44px, 6.6vw, 80px);
  font-weight: 700; letter-spacing: -.04em; line-height: .94;
  margin: 12px 0 0;
}
.id .role {
  grid-column: 9 / 13;
  font-family: var(--mono); font-size: 11px; line-height: 2.2;
  letter-spacing: .1em; text-transform: uppercase; color: var(--soft);
  border-left: 2px solid var(--accent); padding-left: 16px;
}
.id .role b { color: var(--ink); font-weight: 600; }
.bio {
  grid-column: 1 / 9;
  font-size: 17.5px; line-height: 1.66; color: var(--soft);
  margin: 26px 0 0;
}
.bio b { color: var(--ink); font-weight: 500; }
.hr { height: 1px; background: var(--line); margin: 52px 0 0; }

/* ---------- section head ---------- */
section { padding: 56px 0 0; }
.sh { display: flex; align-items: center; gap: 14px; margin-bottom: 22px; }
.sh h2 {
  font-family: var(--mono); font-size: 13px; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase; margin: 0;
  color: var(--ink);
}
.sh .ln { flex: 1 1 auto; height: 1px; background: var(--line); }
.sh .ct { font-family: var(--mono); font-size: 10px; letter-spacing: .12em; color: var(--faint); white-space: nowrap; }

/* ---------- project cards ---------- */
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 22px 22px 18px;
  text-decoration: none;
  display: flex; flex-direction: column;
  transition: border-color .14s ease, transform .14s ease;
}
.card:hover, .card:focus-visible { border-color: var(--ink); transform: translateY(-2px); }
.ctop { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 16px; gap: 12px; }
.cn { font-family: var(--mono); font-size: 10px; color: var(--faint); letter-spacing: .14em; }
.pill {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em;
  text-transform: uppercase; padding: 3px 7px; border-radius: 2px;
  border: 1px solid; white-space: nowrap;
}
.p-live { color: var(--ok);   border-color: var(--ok-line);   background: var(--ok-bg); }
.p-soon { color: var(--warn); border-color: var(--warn-line); background: var(--warn-bg); }
.card h3 { font-size: 22px; font-weight: 700; letter-spacing: -.025em; margin: 0 0 9px; }
.card p { font-size: 15.5px; line-height: 1.58; color: var(--soft); margin: 0 0 18px; }
.schema {
  background: var(--sunken);
  border: 1px solid var(--line);
  border-radius: 2px;
  margin-bottom: 16px;
  display: block; width: 100%; height: auto;
}
.cfoot {
  margin-top: auto; border-top: 1px solid var(--line);
  padding-top: 12px; display: flex; justify-content: space-between;
  align-items: center; gap: 12px;
}
.tags { font-family: var(--mono); font-size: 10px; letter-spacing: .08em; color: var(--soft); text-transform: uppercase; }
.go { font-family: var(--mono); font-size: 11px; color: var(--faint); white-space: nowrap; }
.card:hover .go, .card:focus-visible .go { color: var(--accent); }

/* ---------- stack (definition list, not skill bars) ---------- */
.skills { display: grid; grid-template-columns: 168px 1fr; margin: 0; }
.skills dt {
  font-family: var(--mono); font-size: 10px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--faint);
  padding: 15px 0; border-top: 1px solid var(--line);
}
.skills dd {
  margin: 0; padding: 15px 0; border-top: 1px solid var(--line);
  font-size: 15.5px; line-height: 1.62; color: var(--ink-2);
}

/* ---------- career (full width: role and org need the room) ---------- */
.career td.n { width: 27%; white-space: normal; padding-right: 26px; }

/* The line under a role or a degree: employer, or awarding institution.
   Shared by .career and the education table so both read the same way. */
td.n .org {
  display: block; margin-top: 5px;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--soft); font-weight: 500;
  white-space: normal;
}

/* ---------- tables ---------- */
table { width: 100%; border-collapse: collapse; }
caption { position: absolute; left: -9999px; }
td, th { text-align: left; }
td {
  padding: 13px 12px 13px 0;
  border-bottom: 1px solid var(--line);
  font-size: 15.5px; vertical-align: top;
}
td.y {
  font-family: var(--mono); font-size: 11px; letter-spacing: .08em;
  color: var(--faint); width: 84px; white-space: nowrap; padding-top: 16px;
}
td.n { font-weight: 500; width: 38%; color: var(--ink); }
td.n a { text-decoration: none; border-bottom: 1px solid var(--line-2); }
td.n a:hover { color: var(--accent); border-color: var(--accent); }
td.d { color: var(--soft); font-size: 15px; }
td.k {
  font-family: var(--mono); font-size: 10px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--faint); text-align: right;
  width: 116px; white-space: nowrap;
}
/* Experience carries four rows of prose, education two short ones, so an
   even split starves the description column and wraps it to three lines.
   align-self stops the shorter table being stretched to match the taller. */
.two { display: grid; grid-template-columns: 1.18fr 1fr; gap: 0 48px; }
.two table { align-self: start; }
.two td.n { width: auto; white-space: nowrap; padding-right: 24px; }
.two td.d { width: 52%; }
/* "Arizona State University" is 24 characters of letter-spaced uppercase
   mono, which does not fit the education column at its natural width --
   it has to be allowed to size the column or it wraps mid-name. The two
   descriptions there are short enough to give up the room. */
.two td.n .org { white-space: nowrap; }

/* ---------- footer ---------- */
footer {
  margin-top: 76px; border-top: 1px solid var(--line);
  padding: 40px 0 58px;
}
.foot-row {
  display: flex; justify-content: space-between; align-items: center;
  gap: 16px; flex-wrap: wrap;
}

/* The shared crest. eagle.png is a black line drawing on transparent, so
   dark inverts it; light leaves it alone and carries more opacity, because
   black at 42% on off-white is a ghost where white at 42% on near-black is
   not. Below about 110px the engraving's lines merge into a smudge, which
   is why this is not smaller. */
footer .crest {
  display: block; width: 132px; height: auto;
  margin: 0 auto 30px;
  opacity: .55;
}
:root[data-theme="dark"] footer .crest { filter: invert(1); opacity: .42; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) footer .crest { filter: invert(1); opacity: .42; }
}
footer a {
  font-family: var(--mono); font-size: 10px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--soft); text-decoration: none;
  margin-left: 22px;
}
footer a:first-child { margin-left: 0; }
footer a:hover { color: var(--accent); }
footer .links { display: flex; flex-wrap: wrap; }

/* ---------- responsive ---------- */
@media (max-width: 900px) {
  .id .name { grid-column: 1 / 9; }
  .id .role { grid-column: 9 / 13; }
  .bio { grid-column: 1 / 12; }
  .two { grid-template-columns: 1fr; gap: 0; }
  .two td.n { white-space: normal; }
  .skills { grid-template-columns: 1fr; }
  .skills dt { padding-bottom: 0; border-top: 1px solid var(--line); }
  .skills dd { padding-top: 7px; border-top: 0; }
  .career td.n { width: 34%; }
  .two table:last-child { margin-top: 34px; }
}

@media (max-width: 760px) {
  :root { --gut: 22px; }
  .band nav a { display: none; }
  .band nav a.keep { display: inline; }
  .id { padding-top: 46px; display: block; }
  .id .role {
    border-left: 0; border-top: 2px solid var(--accent);
    padding: 14px 0 0; margin-top: 22px; line-height: 1.95;
  }
  .bio { font-size: 16.5px; margin-top: 22px; }
  .hr { margin-top: 38px; }
  section { padding-top: 42px; }
  .grid { grid-template-columns: 1fr; }
  td.k { display: none; }
  td.n { width: 42%; }
  .sh .ct { display: none; }

  /* The education rows stack here rather than at 520px. They are the
     narrowest three-column rows on the page -- a degree, the university
     and a capstone -- and by this width the auto layout has squeezed the
     name column down to the width of "Arizona State University", so the
     degree wraps and the three run together as one block. The career
     table is full width and holds its columns until 520px. */
  .two table, .two tbody, .two tr, .two td { display: block; width: auto; }
  .two tr { border-bottom: 1px solid var(--line); padding: 14px 0; }
  .two td { border: 0; padding: 0; }
  .two td.y { padding: 0 0 4px; width: auto; }
  .two td.n, .two td.d { width: auto; padding-right: 0; }
  .two td.n { font-size: 16.5px; margin-bottom: 9px; }
}

@media (max-width: 520px) {
  table, tbody, tr, td { display: block; width: auto; }
  tr { border-bottom: 1px solid var(--line); padding: 14px 0; }
  td { border: 0; padding: 0; }
  td.y { padding: 0 0 4px; width: auto; }
  /* Stacked, td.n often ends on the .org line, so this gap is the only
     thing separating the employer or university from the prose beneath
     it. 3px read as one block of text on a phone. */
  td.n { width: auto; font-size: 16.5px; margin-bottom: 9px; }
  /* These three carry column widths for the real table layout, and each
     outranks the bare td rules above on specificity. Once the rows are
     stacked there is no column left to size, so the widths have to be
     unset by name -- otherwise "Senior Software Engineer" wraps to three
     lines inside a 34% box, and the education capstones wrap inside a 52%
     one, while everything around them runs the full width of the screen. */
  .career td.n, .two td.n, .two td.d { width: auto; padding-right: 0; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  html { scroll-behavior: auto; }
}

html { scroll-behavior: smooth; }
section[id] { scroll-margin-top: 60px; }

@media print {
  .band, .theme { display: none; }
  body { background: #fff; color: #000; }
}

/* Table headers exist for screen readers only. The visual design uses
   position, not labels, but a data table without headers gives assistive
   tech no way to announce which column a cell belongs to. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap; border: 0;
}
