@import url("/static/fonts/fonts.css");

/* ============================================================ tokens ==== */
:root {
  color-scheme: dark;

  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --sans: "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  --bg:      #0a0e0c;
  --panel:   #101512;
  --panel-2: #141a17;
  --rule:    #1f2823;
  --rule-2:  #2c3831;

  --text:    #ccd6d0;
  --bright:  #e8f0ec;
  --dim:     #77857d;
  --faint:   #4d5952;

  --green:   #52d99a;
  --green-d: #2f8f63;
  --amber:   #d8a54a;
  --blue:    #7aa9e6;
  --wash:    #13201a;

  --measure: 47rem;
  --wide:    60rem;
  --pad-x: clamp(1.1rem, 5vw, 2.75rem);
}

/* ============================================================== base ==== */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 15px/1.7 var(--mono);
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--green-d); color: #04120b; }

a { color: var(--green); text-decoration: none; }
a:hover { color: var(--bright); text-decoration: underline; text-underline-offset: 3px; }
:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

h1, h2, h3, h4 { color: var(--bright); font-family: var(--mono); line-height: 1.25; margin: 0; font-weight: 600; }
h1 { font-size: clamp(1.6rem, 4.4vw, 2.15rem); letter-spacing: -0.015em; }
h2 { font-size: 1.12rem; }
h3 { font-size: 1rem; }
p { margin: 0 0 1em; }
img, video { max-width: 100%; height: auto; }

.wrap  { max-width: var(--measure); margin: 0 auto; padding: 0 var(--pad-x); }
.wrap-wide { max-width: var(--wide); margin: 0 auto; padding: 0 var(--pad-x); }

/* the mono section label used throughout */
.label {
  font: 500 11px/1 var(--mono); letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--dim);
}

/* shell prompt, the recurring motif */
.prompt { color: var(--faint); white-space: nowrap; }
.prompt .u { color: var(--green); }
.prompt .p { color: var(--blue); }
.prompt .s { color: var(--dim); }

.cursor {
  display: inline-block; width: 0.58em; height: 1.05em; margin-left: 0.28em;
  background: var(--green); vertical-align: -0.16em;
  animation: blink 1.15s steps(1) infinite;
}
@keyframes blink { 0%, 55% { opacity: 1; } 56%, 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .cursor { animation: none; } }

/* ============================================================ chrome ==== */
.topbar {
  border-bottom: 1px solid var(--rule);
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(8px);
  position: sticky; top: 0; z-index: 20;
}
.topbar-in {
  display: flex; align-items: center; gap: 1rem;
  min-height: 48px; max-width: var(--wide); margin: 0 auto; padding: 0 var(--pad-x);
}
.brand { font-size: 12.5px; letter-spacing: 0.02em; }
.brand:hover { text-decoration: none; }
.brand:hover .p { color: var(--bright); }

.topnav { margin-left: auto; display: flex; gap: 1.15rem; }
.topnav a {
  font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--dim); padding: 3px 0; border-bottom: 1.5px solid transparent;
}
.topnav a:hover { color: var(--bright); text-decoration: none; }
.topnav a[aria-current] { color: var(--green); border-bottom-color: var(--green); }
.topnav a.edit { color: var(--amber); }

footer.foot { margin-top: 5rem; border-top: 1px solid var(--rule); padding: 1.25rem 0 3rem; }
.foot-in {
  max-width: var(--wide); margin: 0 auto; padding: 0 var(--pad-x);
  display: flex; flex-wrap: wrap; gap: 0.4rem 1.4rem; align-items: baseline;
  font-size: 11.5px; color: var(--faint); letter-spacing: 0.04em;
}
.foot-in a { color: var(--dim); }
.foot-in .spacer { margin-left: auto; }

/* flash messages */
.flash {
  border: 1px solid var(--rule-2); border-left: 2px solid var(--amber);
  background: var(--panel); color: var(--text);
  padding: 0.6rem 0.9rem; margin: 0 0 1rem; font-size: 13px;
}

/* =============================================================== home === */
.term { padding: clamp(2.5rem, 9vh, 5rem) 0 1rem; }
.term-line { margin-bottom: 1.5rem; font-size: 13.5px; }
.term-out { margin: 0 0 2.6rem 0; }

.term h1 { margin: 0 0 0.5rem; }
.term .role { color: var(--green); font-size: 13px; letter-spacing: 0.02em; margin-bottom: 1.5rem; }
.term .blurb {
  font-family: var(--sans); font-size: 1rem; line-height: 1.68;
  color: var(--text); max-width: 36rem; margin: 0;
}

/* ls output: the three destinations */
.ls { display: grid; gap: 1px; background: var(--rule); border: 1px solid var(--rule); }
.ls-row {
  display: grid; grid-template-columns: 2.3rem minmax(7.5rem, auto) 1fr auto;
  align-items: baseline; gap: 0 1.1rem;
  padding: 0.95rem 1rem; background: var(--panel); color: var(--text);
  transition: background-color .14s ease;
}
.ls-row:hover { background: var(--panel-2); text-decoration: none; }
.ls-n { color: var(--faint); font-size: 12px; }
.ls-name { color: var(--green); font-size: 1rem; font-weight: 500; }
.ls-row:hover .ls-name { color: var(--bright); }
.ls-desc { color: var(--dim); font-size: 12.5px; }
.ls-go { color: var(--faint); font-size: 12px; transition: transform .14s ease, color .14s ease; }
.ls-row:hover .ls-go { color: var(--green); transform: translateX(3px); }

.home-note { margin-top: 2.2rem; font-size: 12px; color: var(--faint); letter-spacing: 0.03em; }
.home-note a { color: var(--dim); }
.home-note a:hover { color: var(--green); }

/* ============================================================== page ==== */
.page-head { padding: 2.6rem 0 1.5rem; border-bottom: 1px solid var(--rule); margin-bottom: 2.2rem; }
.page-head.tight { border-bottom: 0; padding-bottom: 0.6rem; margin-bottom: 1.4rem; }
.page-head .label { display: block; margin-bottom: 0.65rem; }
.page-head .lede {
  margin: 0.75rem 0 0; color: var(--dim); max-width: 38rem;
  font-family: var(--sans); font-size: 0.97rem; line-height: 1.65;
}
.crumb { font-size: 11.5px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--faint); display: inline-block; margin-bottom: 1rem; }
.crumb:hover { color: var(--green); text-decoration: none; }

/* =========================================================== projects === */
.cards { display: grid; gap: 1px; background: var(--rule); border: 1px solid var(--rule); }
.card {
  background: var(--panel); padding: 1.4rem 1.35rem; color: inherit;
  display: grid; gap: 0.5rem; transition: background-color .14s ease;
}
.card:hover { background: var(--panel-2); text-decoration: none; }
.card-top { display: flex; align-items: center; gap: 0.8rem; flex-wrap: wrap; }
.card h2 { color: var(--bright); font-size: 1.05rem; }
.card:hover h2 { color: var(--green); }
.card p {
  margin: 0; color: var(--dim); font-family: var(--sans); font-size: 0.94rem; line-height: 1.6;
}
.card-cover {
  order: -1; margin: -1.4rem -1.35rem 0.35rem; width: calc(100% + 2.7rem);
  aspect-ratio: 21/9; object-fit: cover; border-bottom: 1px solid var(--rule);
}

.status {
  font: 500 10.5px/1 var(--mono); letter-spacing: 0.09em; text-transform: uppercase;
  padding: 4px 7px; border: 1px solid currentColor; white-space: nowrap;
}
.st-active   { color: var(--green); }
.st-shipped  { color: var(--blue); }
.st-research { color: var(--amber); }
.st-paused   { color: var(--dim); }
.st-archived { color: var(--faint); }

/* ============================================================ project === */
.meta-table {
  display: grid; grid-template-columns: 7.5rem 1fr; gap: 0.5rem 1.2rem;
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  padding: 1rem 0; margin: 0 0 2.2rem; font-size: 13.5px;
}
.meta-table dt { font-size: 11px; letter-spacing: 0.11em; text-transform: uppercase; color: var(--faint); line-height: 1.6; }
.meta-table dd { margin: 0; color: var(--text); }

.repo-link { display: inline-flex; align-items: center; gap: 0.45rem; font-size: 13px; }
.repo-link svg { width: 14px; height: 14px; fill: currentColor; flex: none; }

.section { margin: 3rem 0 0; }
.section > .label { display: flex; align-items: center; gap: 0.8rem; margin-bottom: 1.3rem; }
.section > .label::after { content: ""; flex: 1; height: 1px; background: var(--rule); }

/* --- timeline: a trace with vias ------------------------------------- */
.timeline { position: relative; margin: 0; padding: 0 0 0 1.7rem; list-style: none; }
.timeline::before {
  content: ""; position: absolute; left: 5px; top: 6px; bottom: 6px;
  width: 1.5px; background: var(--rule-2);
}
.entry { position: relative; padding-bottom: 2.1rem; }
.entry:last-child { padding-bottom: 0; }
.entry::before {
  content: ""; position: absolute; left: -1.7rem; top: 5px;
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--bg); border: 2.5px solid var(--green); box-sizing: border-box;
}
.entry.minor::before { border-color: var(--rule-2); }
.entry-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 0.8rem; margin-bottom: 0.45rem; }
.entry-date { font-size: 11.5px; color: var(--faint); letter-spacing: 0.05em; white-space: nowrap; }
.entry h3 { color: var(--bright); }
.entry-kind {
  font: 500 10.5px/1 var(--mono); letter-spacing: 0.07em;
  color: var(--green); background: var(--wash); border: 1px solid var(--rule-2); padding: 3.5px 6px;
}
.entry-body { font-size: 0.95rem; }
.entry-body > :last-child { margin-bottom: 0; }
.entry-src { font-size: 11px; color: var(--faint); letter-spacing: 0.05em; }

/* --- attachments ------------------------------------------------------ */
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 0.7rem; }
.gallery a { display: block; border: 1px solid var(--rule); background: var(--panel); }
.gallery a:hover { border-color: var(--green); text-decoration: none; }
.gallery img { display: block; width: 100%; aspect-ratio: 4/3; object-fit: cover; }
.gallery figcaption { font-size: 10.5px; color: var(--faint); padding: 6px 8px; border-top: 1px solid var(--rule); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.filelist { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.filelist li { border-bottom: 1px solid var(--rule); }
.filelist a, .filelist .row {
  display: grid; grid-template-columns: 3.5rem 1fr auto; gap: 1rem; align-items: center;
  padding: 0.62rem 0.4rem; font-size: 12.5px; color: var(--text);
}
.filelist a:hover { background: var(--panel); color: var(--green); text-decoration: none; }
.filelist .ext { color: var(--faint); font-size: 10.5px; letter-spacing: 0.08em; }
.filelist .size { color: var(--faint); font-size: 11px; }
.filelist .tools { display: flex; align-items: center; gap: 0.45rem; flex-wrap: nowrap; white-space: nowrap; }
.filelist .tools form { display: inline-flex; }

/* ============================================================= prose ==== */
.prose { font-family: var(--sans); font-size: 1rem; line-height: 1.68; color: var(--text); }
.prose h2 { margin: 2.2rem 0 0.7rem; font-size: 1.1rem; }
.prose h3 { margin: 1.7rem 0 0.5rem; }
.prose ul, .prose ol { padding-left: 1.15rem; margin: 0 0 1em; }
.prose li { margin-bottom: 0.3em; }
.prose li::marker { color: var(--green-d); }
.prose blockquote { margin: 1.3rem 0; padding: 0.15rem 0 0.15rem 1rem; border-left: 2px solid var(--green-d); color: var(--dim); }
.prose img { border: 1px solid var(--rule); }
.prose code {
  font: 400 0.86em/1.5 var(--mono); background: var(--wash);
  border: 1px solid var(--rule); padding: 1px 5px; color: var(--green);
}
.prose pre {
  background: var(--panel); border: 1px solid var(--rule);
  padding: 0.9rem 1rem; overflow-x: auto; font-size: 12.5px; line-height: 1.55;
}
.prose pre code { background: none; border: 0; padding: 0; color: var(--text); font-size: inherit; }
.prose table { width: 100%; border-collapse: collapse; margin: 1.3rem 0; font-size: 0.92rem; }
.prose th, .prose td { text-align: left; padding: 0.5rem 0.7rem 0.5rem 0; border-bottom: 1px solid var(--rule); }
.prose th {
  font: 500 11px/1.5 var(--mono); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--faint); border-bottom-color: var(--rule-2);
}

/* ============================================================ resume ==== */
.resume .prose h2 {
  font: 500 11px/1 var(--mono); letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--green); margin: 2.4rem 0 0; padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--rule);
}
.resume .prose h2 + * { margin-top: 1.2rem; }
.resume .prose h3 {
  font-family: var(--mono); font-size: 0.97rem; margin: 1.6rem 0 0.1rem;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem;
}
.resume .prose h3 .when { margin-left: auto; font-size: 11.5px; color: var(--faint); letter-spacing: 0.05em; font-weight: 400; }
.resume .prose .org { color: var(--green-d); font-size: 0.92rem; margin: 0.15rem 0 0.5rem; }
.resume .prose dl { display: grid; grid-template-columns: 9rem 1fr; gap: 0.5rem 1.2rem; margin: 0; align-items: baseline; }
.resume .prose dt { font: 400 11px/1.6 var(--mono); letter-spacing: 0.11em; text-transform: uppercase; color: var(--faint); }
.resume .prose dd { margin: 0; }
.resume-contact {
  list-style: none; margin: 0.9rem 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 0.3rem 1.15rem;
  font-size: 12.5px; color: var(--dim); letter-spacing: 0.01em;
}
.resume-contact a { color: var(--dim); }
.resume-contact a:hover { color: var(--green); }
.resume-actions { display: flex; flex-wrap: wrap; gap: 0.55rem; margin-top: 1.3rem; }

/* ============================================================ buttons ==== */
.btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font: 500 11.5px/1 var(--mono); letter-spacing: 0.09em; text-transform: uppercase;
  padding: 0.62rem 0.9rem; border: 1px solid var(--rule-2); background: var(--panel);
  color: var(--text); cursor: pointer;
}
.btn:hover { border-color: var(--green); color: var(--green); text-decoration: none; }
.btn-primary { background: var(--green); border-color: var(--green); color: #04120b; }
.btn-primary:hover { background: var(--bright); border-color: var(--bright); color: #04120b; }
.btn-danger { color: #e08585; border-color: #4a2b2b; }
.btn-danger:hover { border-color: #e08585; color: #e08585; }
.btn-sm { padding: 0.42rem 0.6rem; font-size: 10.5px; }

/* =========================================================== contact ==== */
.contact-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.contact-list li { border-bottom: 1px solid var(--rule); }
.contact-list .row {
  display: grid; grid-template-columns: 7rem 1fr auto; gap: 0.35rem 1.2rem;
  align-items: center; padding: 0.95rem 0.4rem; color: var(--text);
}
a.row:hover { background: var(--panel); text-decoration: none; }
.contact-list .k { font-size: 11px; letter-spacing: 0.11em; text-transform: uppercase; color: var(--faint); }
.contact-list .v { font-size: 13.5px; word-break: break-word; }
a.row:hover .v { color: var(--green); }
.contact-list .go { color: var(--faint); font-size: 12px; }
a.row:hover .go { color: var(--green); }

/* ============================================================== misc ==== */
.empty { border: 1px dashed var(--rule-2); padding: 2.2rem 1.4rem; text-align: center; color: var(--dim); font-size: 12.5px; }
.stream-project { font-size: 11px; letter-spacing: 0.09em; text-transform: uppercase; color: var(--green); }

/* ============================================================= admin ==== */
.adminbar {
  background: var(--wash); border-bottom: 1px solid var(--rule-2);
  font-size: 11.5px; letter-spacing: 0.06em;
}
.adminbar-in {
  max-width: var(--wide); margin: 0 auto; padding: 0.55rem var(--pad-x);
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1.1rem;
}
.adminbar a { color: var(--amber); }
.adminbar .spacer { margin-left: auto; }
.adminbar form { display: inline; }
.adminbar button {
  background: none; border: 0; color: var(--dim); font: inherit; cursor: pointer; padding: 0;
}
.adminbar button:hover { color: var(--bright); }

.form-grid { display: grid; gap: 1.1rem; }
.field { display: grid; gap: 0.35rem; }
.field > label { font-size: 11px; letter-spacing: 0.11em; text-transform: uppercase; color: var(--dim); }
.hint { font-size: 11px; color: var(--faint); letter-spacing: 0.02em; line-height: 1.6; }
::placeholder { color: var(--faint); opacity: 1; }

input[type="text"], input[type="password"], input[type="date"], input[type="url"],
input[type="number"], select, textarea {
  width: 100%; background: var(--panel); color: var(--text);
  border: 1px solid var(--rule-2); padding: 0.55rem 0.65rem;
  font: 400 13.5px/1.55 var(--mono);
}
textarea { resize: vertical; min-height: 8rem; line-height: 1.65; }
textarea.tall { min-height: 26rem; }
input:focus, select:focus, textarea:focus { border-color: var(--green); outline: none; }
input[type="file"] { font: 400 12px var(--mono); color: var(--dim); }

.row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
.row-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.1rem; }
.checks { display: flex; flex-wrap: wrap; gap: 1.3rem; align-items: center; }
.check { display: inline-flex; align-items: center; gap: 0.45rem; font-size: 12.5px; color: var(--text); cursor: pointer; }
.check input { accent-color: var(--green); width: 15px; height: 15px; }

.actions { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; margin-top: 0.4rem; }
.actions .spacer { margin-left: auto; }

.admin-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.admin-list li {
  border-bottom: 1px solid var(--rule); display: flex; flex-wrap: wrap;
  align-items: center; gap: 0.5rem 0.9rem; padding: 0.7rem 0.4rem; font-size: 13px;
}
.admin-list .name { color: var(--bright); }
.admin-list .meta { color: var(--faint); font-size: 11.5px; }
.admin-list .spacer { margin-left: auto; }
.badge { font-size: 10px; letter-spacing: 0.09em; text-transform: uppercase; padding: 3px 6px; border: 1px solid currentColor; }
.badge-draft { color: var(--amber); }
.badge-live  { color: var(--green); }

.uploads { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.6rem; }
.upload-item { border: 1px solid var(--rule); background: var(--panel); padding: 0.5rem; display: grid; gap: 0.4rem; }
.upload-item img { width: 100%; aspect-ratio: 4/3; object-fit: cover; border: 1px solid var(--rule); }
.upload-item .fname { font-size: 10.5px; color: var(--dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.upload-item .fsize { font-size: 10px; color: var(--faint); }
.upload-item .tools { display: flex; gap: 0.35rem; align-items: center; }
.copy {
  background: none; border: 1px solid var(--rule-2); color: var(--dim);
  font: 400 10px/1 var(--mono); letter-spacing: 0.06em; padding: 4px 6px; cursor: pointer;
}
.copy:hover { border-color: var(--green); color: var(--green); }
.danger-zone { border: 1px solid #3a2626; padding: 1.1rem; margin-top: 2.5rem; }

.login-card { max-width: 22rem; margin: 12vh auto; }

@media (max-width: 620px) {
  .ls-row { grid-template-columns: 1.9rem 1fr auto; }
  .ls-desc { grid-column: 2 / -1; }
  .meta-table { grid-template-columns: 1fr; gap: 0.1rem 0; }
  .meta-table dd { margin-bottom: 0.65rem; }
  .contact-list .row { grid-template-columns: 1fr auto; }
  .contact-list .k { grid-column: 1 / -1; }
  .row-2, .row-3 { grid-template-columns: 1fr; }
  .topnav { gap: 0.75rem; }
}

/* ============================================================= print ==== */
@page { size: A4; margin: 14mm 15mm 13mm; }

@media print {
  :root {
    --bg: #fff; --panel: #fff; --panel-2: #fff; --text: #111; --bright: #000;
    --dim: #444; --faint: #666; --rule: #ccc; --rule-2: #bbb;
    --green: #1d5344; --green-d: #1d5344;
  }
  /* :root beats a bare html selector, so the canvas has to be reset here or
     the page margins print with the dark screen background */
  :root { color-scheme: light; background: #fff; }
  html, body { background: #fff; }
  body { color: #111; font-size: 10.5pt; }
  .topbar, .adminbar, footer.foot, .resume-actions, .crumb, .cursor { display: none !important; }
  .wrap, .wrap-wide { max-width: none; padding: 0; }
  .page-head { padding-top: 0; padding-bottom: 0.8rem; }
  a { color: #000; text-decoration: none; }
  .resume-contact { color: #222; font-size: 8.6pt; gap: 0.1rem 0.85rem; margin-top: 0.5rem; }
  .resume-contact a { color: #222; }

  /* the resume is meant to land on a single sheet, so the vertical rhythm is
     tightened well past the on-screen spacing */
  .resume .page-head { padding-bottom: 0.45rem; margin-bottom: 0.9rem; }
  .resume .page-head .label { margin-bottom: 0.3rem; }
  .resume .page-head h1 { font-size: 19pt; }
  .resume .page-head .lede { margin-top: 0.25rem; font-size: 9.5pt; }
  .resume .prose { font-size: 9.4pt; line-height: 1.42; }
  .resume .prose p { margin-bottom: 0.45em; }
  .resume .prose h2 {
    color: #1d5344; font-size: 8.4pt; margin-top: 0.95rem; padding-bottom: 0.25rem;
  }
  .resume .prose h2 + * { margin-top: 0.55rem; }
  .resume .prose h3 { font-size: 10pt; margin: 0.7rem 0 0.05rem; }
  .resume .prose h3 .when { font-size: 8.4pt; }
  .resume .prose .org { color: #1d5344; font-size: 9pt; margin: 0.05rem 0 0.2rem; }
  .resume .prose ul { margin-bottom: 0.3em; padding-left: 1rem; }
  .resume .prose li { margin-bottom: 0.05em; }
  .resume .prose dl { gap: 0.28rem 1.1rem; grid-template-columns: 8rem 1fr; }
  .resume .prose dt { font-size: 8.2pt; }
  .entry, .resume .prose h3 { break-inside: avoid; }
}

/* ======================================================= pygments ==== */
pre { line-height: 125%; }
td.linenos .normal { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.hl .hll { background-color: #404040 }
.hl { background: #202020; color: #D0D0D0 }
.hl .c { color: #ABABAB; font-style: italic } /* Comment */
.hl .err { color: #A61717; background-color: #E3D2D2 } /* Error */
.hl .esc { color: #D0D0D0 } /* Escape */
.hl .g { color: #D0D0D0 } /* Generic */
.hl .k { color: #6EBF26; font-weight: bold } /* Keyword */
.hl .l { color: #D0D0D0 } /* Literal */
.hl .n { color: #D0D0D0 } /* Name */
.hl .o { color: #D0D0D0 } /* Operator */
.hl .x { color: #D0D0D0 } /* Other */
.hl .p { color: #D0D0D0 } /* Punctuation */
.hl .ch { color: #ABABAB; font-style: italic } /* Comment.Hashbang */
.hl .cm { color: #ABABAB; font-style: italic } /* Comment.Multiline */
.hl .cp { color: #FF3A3A; font-weight: bold } /* Comment.Preproc */
.hl .cpf { color: #ABABAB; font-style: italic } /* Comment.PreprocFile */
.hl .c1 { color: #ABABAB; font-style: italic } /* Comment.Single */
.hl .cs { color: #E50808; font-weight: bold; background-color: #520000 } /* Comment.Special */
.hl .gd { color: #FF3A3A } /* Generic.Deleted */
.hl .ge { color: #D0D0D0; font-style: italic } /* Generic.Emph */
.hl .ges { color: #D0D0D0; font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.hl .gr { color: #FF3A3A } /* Generic.Error */
.hl .gh { color: #FFF; font-weight: bold } /* Generic.Heading */
.hl .gi { color: #589819 } /* Generic.Inserted */
.hl .go { color: #CCC } /* Generic.Output */
.hl .gp { color: #AAA } /* Generic.Prompt */
.hl .gs { color: #D0D0D0; font-weight: bold } /* Generic.Strong */
.hl .gu { color: #FFF; text-decoration: underline } /* Generic.Subheading */
.hl .gt { color: #FF3A3A } /* Generic.Traceback */
.hl .kc { color: #6EBF26; font-weight: bold } /* Keyword.Constant */
.hl .kd { color: #6EBF26; font-weight: bold } /* Keyword.Declaration */
.hl .kn { color: #6EBF26; font-weight: bold } /* Keyword.Namespace */
.hl .kp { color: #6EBF26 } /* Keyword.Pseudo */
.hl .kr { color: #6EBF26; font-weight: bold } /* Keyword.Reserved */
.hl .kt { color: #6EBF26; font-weight: bold } /* Keyword.Type */
.hl .ld { color: #D0D0D0 } /* Literal.Date */
.hl .m { color: #51B2FD } /* Literal.Number */
.hl .s { color: #ED9D13 } /* Literal.String */
.hl .na { color: #BBB } /* Name.Attribute */
.hl .nb { color: #2FBCCD } /* Name.Builtin */
.hl .nc { color: #71ADFF; text-decoration: underline } /* Name.Class */
.hl .no { color: #40FFFF } /* Name.Constant */
.hl .nd { color: #FFA500 } /* Name.Decorator */
.hl .ni { color: #D0D0D0 } /* Name.Entity */
.hl .ne { color: #BBB } /* Name.Exception */
.hl .nf { color: #71ADFF } /* Name.Function */
.hl .nl { color: #D0D0D0 } /* Name.Label */
.hl .nn { color: #71ADFF; text-decoration: underline } /* Name.Namespace */
.hl .nx { color: #D0D0D0 } /* Name.Other */
.hl .py { color: #D0D0D0 } /* Name.Property */
.hl .nt { color: #6EBF26; font-weight: bold } /* Name.Tag */
.hl .nv { color: #40FFFF } /* Name.Variable */
.hl .ow { color: #6EBF26; font-weight: bold } /* Operator.Word */
.hl .pm { color: #D0D0D0 } /* Punctuation.Marker */
.hl .w { color: #666 } /* Text.Whitespace */
.hl .mb { color: #51B2FD } /* Literal.Number.Bin */
.hl .mf { color: #51B2FD } /* Literal.Number.Float */
.hl .mh { color: #51B2FD } /* Literal.Number.Hex */
.hl .mi { color: #51B2FD } /* Literal.Number.Integer */
.hl .mo { color: #51B2FD } /* Literal.Number.Oct */
.hl .sa { color: #ED9D13 } /* Literal.String.Affix */
.hl .sb { color: #ED9D13 } /* Literal.String.Backtick */
.hl .sc { color: #ED9D13 } /* Literal.String.Char */
.hl .dl { color: #ED9D13 } /* Literal.String.Delimiter */
.hl .sd { color: #ED9D13 } /* Literal.String.Doc */
.hl .s2 { color: #ED9D13 } /* Literal.String.Double */
.hl .se { color: #ED9D13 } /* Literal.String.Escape */
.hl .sh { color: #ED9D13 } /* Literal.String.Heredoc */
.hl .si { color: #ED9D13 } /* Literal.String.Interpol */
.hl .sx { color: #FFA500 } /* Literal.String.Other */
.hl .sr { color: #ED9D13 } /* Literal.String.Regex */
.hl .s1 { color: #ED9D13 } /* Literal.String.Single */
.hl .ss { color: #ED9D13 } /* Literal.String.Symbol */
.hl .bp { color: #2FBCCD } /* Name.Builtin.Pseudo */
.hl .fm { color: #71ADFF } /* Name.Function.Magic */
.hl .vc { color: #40FFFF } /* Name.Variable.Class */
.hl .vg { color: #40FFFF } /* Name.Variable.Global */
.hl .vi { color: #40FFFF } /* Name.Variable.Instance */
.hl .vm { color: #40FFFF } /* Name.Variable.Magic */
.hl .il { color: #51B2FD } /* Literal.Number.Integer.Long */

/* let code blocks sit on the panel colour, not pygments' own background */
.hl { background: transparent !important; }
.hl pre { margin: 0; }

/* ============================================================ motion ==== */
/* All of this is gated behind .js, set by an inline script in the head, so a
   browser with JavaScript off gets the finished page with nothing hidden. */

.caret {
  display: inline-block; width: 0.55em; height: 1.02em; background: var(--green);
  vertical-align: -0.15em; margin-left: 0.12em; opacity: 0;
}
.caret.on { opacity: 1; animation: blink 1.15s steps(1) infinite; }

.js .cursor { animation: none; opacity: 0; }
.js .cursor.on { animation: blink 1.15s steps(1) infinite; opacity: 1; }

.js [data-reveal],
.js [data-stagger] > * { opacity: 0; transform: translateY(6px); }

/* the home terminal writes line by line, so each step takes up no space at
   all until it is printed */
.js .term .seq { display: none; opacity: 0; transform: translateY(6px); }
.js .term .seq.shown { display: block; }
.js .term .seq.shown.is-in {
  opacity: 1; transform: none;
  transition: opacity .38s ease, transform .38s cubic-bezier(.2, .7, .3, 1);
}
.js [data-reveal].is-in {
  opacity: 1; transform: none;
  transition: opacity .42s ease, transform .42s cubic-bezier(.2, .7, .3, 1);
}

/* the via pops onto the trace as its entry arrives */
.js .entry[data-reveal]::before { transform: scale(0.4); opacity: 0; }
.js .entry[data-reveal].is-in::before {
  transform: none; opacity: 1;
  transition: transform .34s cubic-bezier(.2, .9, .3, 1) .06s, opacity .3s ease .06s;
}

/* the hairline beside a section label wipes in from the left */
.js .section[data-reveal] > .label::after { transform: scaleX(0); transform-origin: left; }
.js .section[data-reveal].is-in > .label::after {
  transform: none; transition: transform .55s cubic-bezier(.2, .7, .3, 1) .1s;
}

@media (prefers-reduced-motion: reduce) {
  .js [data-reveal], .js [data-stagger] > * { opacity: 1 !important; transform: none !important; }
  .js .term .seq { display: block !important; opacity: 1 !important; transform: none !important; }
  .js .entry[data-reveal]::before { opacity: 1 !important; transform: none !important; }
  .js .section[data-reveal] > .label::after { transform: none !important; }
  .caret.on, .js .cursor.on { animation: none; }
}

@media print {
  [data-reveal], [data-stagger] > *, .term .seq {
    display: block !important; opacity: 1 !important; transform: none !important;
  }
  .caret { display: none !important; }
}

/* ============================================================== boot ==== */
.boot { margin-bottom: 1.9rem; }
.boot-line {
  font-size: 12px; line-height: 1.95; color: var(--dim); letter-spacing: 0.02em;
}
.boot-line .t { color: var(--faint); }
.boot-line .ok { color: var(--green); }

/* the loading bar: two identical monospace glyph runs stacked exactly on top
   of each other, the top one clipped to 0 width and revealed left-to-right.
   clip-path is compositor-only, so this stays smooth regardless of how busy
   the main thread is, unlike a per-character typing timer. */
.bar {
  position: relative; display: inline-block; letter-spacing: -0.06em;
  vertical-align: -0.05em;
}
.bar-track { color: var(--rule-2); }
.bar-fill { position: absolute; inset: 0; color: var(--green-d); }
/* only a JS-driven page starts the bar empty; without JS it must read as
   already loaded, same as every other [data-reveal] element on the site */
.js .bar-fill { clip-path: inset(0 100% 0 0); }
.js .bar.fill .bar-fill {
  clip-path: inset(0 0 0 0);
  transition: clip-path 0.62s cubic-bezier(.22, .7, .27, 1);
}
.bar-pct {
  display: inline-block; min-width: 2.4em; color: var(--faint);
  font-variant-numeric: tabular-nums;
}

/* ============================================================ static ==== */
/* A CRT-ish grain and scanline wash over the home terminal. Both layers are
   moved with transforms only, so they composite without repainting, and both
   stop dead under prefers-reduced-motion. */
.term { position: relative; isolation: isolate; }
.term > .wrap-wide { position: relative; z-index: 1; }

.term-fx {
  position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
}

/* grain: a pre-baked 64px noise tile. An feTurbulence filter here looked the
   same but had to be re-rasterised constantly, which was heavy enough to
   starve the boot sequence on a slow machine. Stepping background-position on
   a tiled bitmap repaints roughly four times a second and costs almost nothing. */
.term-fx::before {
  content: ""; position: absolute; inset: 0;
  background-image: url("data:image/png;base64,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");
  background-repeat: repeat;
  opacity: 0.05;
  animation: grain 1.2s steps(1, end) infinite;
}

/* scanlines, drifting slowly downward */
.term-fx::after {
  content: ""; position: absolute; left: 0; right: 0; top: -10%; height: 130%;
  background: repeating-linear-gradient(
    to bottom,
    rgba(210, 255, 235, 0.022) 0 1px,
    transparent 1px 3px
  );
  animation: scan 9s linear infinite, glow 6.5s ease-in-out infinite;
  will-change: transform;
}

@keyframes grain {
  0%   { background-position:   0px   0px; }
  20%  { background-position: -11px   5px; }
  40%  { background-position:   7px -13px; }
  60%  { background-position: -17px  -7px; }
  80%  { background-position:  13px  11px; }
  100% { background-position:   0px   0px; }
}
@keyframes scan {
  from { transform: translateY(0); }
  to   { transform: translateY(3px); }
}
/* the faint brightness drift of a tube warming up */
@keyframes glow {
  0%, 100% { opacity: 1; }
  45%      { opacity: 0.55; }
  70%      { opacity: 0.85; }
}

@media (prefers-reduced-motion: reduce) {
  .term-fx::before, .term-fx::after { animation: none; }
}
@media print { .term-fx { display: none !important; } }
