/* ============================================================================
   OLISEMEKA.DEV — "PAPER & PIXELS" DESIGN SYSTEM
   ----------------------------------------------------------------------------
   Clean white stock, hairline rules, generous whitespace, and hand-made pixel
   art used as the only ornament. The layout borrows Apple's quiet generosity:
   one column of focus, a lot of air, and type that carries the hierarchy.
   No glows, no gradients-as-decoration, no floating shapes.

   SECTIONS
     01. Tokens
     02. Reset & base
     03. Typography primitives
     04. Layout primitives
     05. Pixel-art primitives
     06. Buttons & controls
     07. Site header
     08. Site footer
     09. Hero
     10. Skills index
     11. Cards
     12. Section furniture (embeds, empty states, pagers)
     13. Homepage sections
     14. Blog list controls
     15. Now timeline
     16. Tags
     17. Contact page
     18. Résumé page
     19. 404
     20. Overlays (image modal, reading progress)
     21. Motion & responsive
     22. Jobs page
   ============================================================================ */

/* ============================================================================
   01. TOKENS
   ============================================================================ */
:root {
  /* ---- Paper ------------------------------------------------------------ */
  --paper:          #ffffff;
  --paper-raised:   #ffffff;
  --paper-sunken:   #f5f5f7;

  /* ---- Ink -------------------------------------------------------------- */
  --ink:            #1d1d1f;
  --ink-2:          #424245;
  --ink-3:          #6e6e73;
  --ink-4:          #86868b;

  /* ---- Rules ------------------------------------------------------------ */
  --rule:           #e8e8ed;
  --rule-2:         #d2d2d7;
  --rule-3:         #b0b0b8;
  --grid:           rgba(29, 29, 31, 0.05);

  /* ---- Accent (deep teal ink) ------------------------------------------ */
  --accent:         #0f6b5e;
  --accent-deep:    #0a4f45;
  --accent-soft:    rgba(15, 107, 94, 0.07);
  --accent-line:    rgba(15, 107, 94, 0.26);

  /* ---- Type ------------------------------------------------------------- */
  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --font-pixel: "Silkscreen", "JetBrains Mono", ui-monospace, monospace;

  --step--2: 0.6875rem;   /* 11px */
  --step--1: 0.8125rem;   /* 13px */
  --step-0:  1rem;        /* 16px */
  --step-1:  1.125rem;    /* 18px */
  --step-2:  1.375rem;    /* 22px */
  --step-3:  1.75rem;     /* 28px */
  --step-4:  2.25rem;     /* 36px */
  --step-5:  clamp(2.5rem, 5.5vw, 3.5rem);

  /* ---- Space ------------------------------------------------------------ */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 2.75rem;
  --sp-8: 4rem;
  --sp-9: 6rem;
  --sp-10: 8rem;

  /* ---- Structure -------------------------------------------------------- */
  --measure:      44rem;   /* prose column */
  --wide:         70rem;   /* page container */
  --narrow:       52rem;
  --header-h:     4.5rem;
  --rule-w:       1px;

  /* ---- Pixel shadows (hard edges, never blurred) ------------------------ */
  --px-shadow:      3px 3px 0 var(--rule-2);
  --px-shadow-ink:  4px 4px 0 var(--ink);

  --radius-pill: 999px;    /* the only curve on the page: the nav dock */
}

/* ============================================================================
   02. RESET & BASE
   ============================================================================ */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  background: var(--paper);
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + var(--sp-5));
}

body {
  position: relative;
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font-family: var(--font-sans);
  font-size: var(--step-0);
  line-height: 1.65;
  color: var(--ink);
  background-color: var(--paper);
  /* Only paper grain: colour washes read as decoration and are reserved for
     the ASCII wordmark's front layer. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.035'/%3E%3C/svg%3E");
  background-repeat: repeat;
  background-size: 160px 160px;
  background-attachment: scroll;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img, svg, video, canvas, iframe { max-width: 100%; }
img { height: auto; display: block; }

a {
  color: var(--accent);
  text-decoration: none;
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
}
a:hover { text-decoration: underline; }

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

::selection {
  background: var(--accent-soft);
  color: var(--ink);
}

hr {
  border: 0;
  border-top: var(--rule-w) solid var(--rule);
  margin: var(--sp-7) 0;
}

/* ============================================================================
   03. TYPOGRAPHY PRIMITIVES
   ============================================================================ */
h1, h2, h3, h4, h5, h6 {
  margin: 0 0 var(--sp-4);
  font-weight: 700;
  line-height: 1.18;
  letter-spacing: -0.022em;
  color: var(--ink);
  text-wrap: balance;
  /* Long unbroken words must not widen the document on a phone. The webfont
     usually keeps titles inside the measure, but a slow/blocked font request
     falls back to a wider face and can push a word past the viewport. */
  overflow-wrap: break-word;
}

h1 { font-size: var(--step-5); font-weight: 800; letter-spacing: -0.035em; }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1); }

p { margin: 0 0 var(--sp-4); }
p:last-child { margin-bottom: 0; }

strong { font-weight: 650; color: var(--ink); }

/* Monospace label — used for eyebrows, meta, nav, tags. */
.mono,
.eyebrow,
.meta {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* Pixel-font label — the loudest pixel signal, used sparingly. */
.pixel {
  font-family: var(--font-pixel);
  font-weight: 400;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-4);
  color: var(--ink-3);
}
.eyebrow::before {
  content: "";
  width: 8px;
  height: 8px;
  background: var(--accent);
  flex: none;
}

.lede {
  font-size: var(--step-1);
  line-height: 1.6;
  color: var(--ink-2);
}

/* ============================================================================
   04. LAYOUT PRIMITIVES
   ============================================================================ */
.container {
  width: 100%;
  max-width: var(--wide);
  margin-inline: auto;
  padding-inline: var(--sp-5);
}
.container-narrow {
  width: 100%;
  max-width: var(--narrow);
  margin-inline: auto;
  padding-inline: var(--sp-5);
}
.container-prose {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--sp-5);
}

/* --- Page frame ----------------------------------------------------------
   One dashed rectangle traces the outer edge of the content column, turning
   the whole document into a single ruled sheet of paper. It sits just outside
   .container's padding — the text never touches it — and is absolute, so the
   frame runs the full height of the document and scrolls with the page. The
   border is painted above the paper grain but below the header dock;
   `pointer-events: none` keeps it from ever stealing a click. */
body::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  z-index: 0;
  width: min(100%, var(--wide));
  transform: translateX(-50%);
  border: 1px dashed var(--rule-2);
  pointer-events: none;
}

.section { padding-block: clamp(4.5rem, 9vw, 8rem); }
.section--ruled { position: relative; }
.section--ruled::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 0;
  border-top: var(--rule-w) dashed var(--rule-2);
}

/* Two-column label/content split used by every major section. */
.section-grid {
  display: grid;
  grid-template-columns: 12rem minmax(0, 1fr);
  gap: var(--sp-8) clamp(3rem, 6vw, 5rem);
  align-items: start;
}
.section-grid > .section-aside {
  position: sticky;
  top: calc(var(--header-h) + var(--sp-5));
}
.aside-title {
  margin: 0 0 var(--sp-3);
  font-size: var(--step-2);
  line-height: 1.2;
}
.aside-note {
  margin: 0;
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--ink-3);
}
.aside-note a { color: var(--ink-2); text-decoration: underline; text-decoration-color: var(--rule-3); }
.aside-note a:hover { color: var(--accent); text-decoration-color: var(--accent); }
@media (max-width: 60rem) {
  .section-grid { grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); }
  .section-grid > .section-aside { position: static; }
}

.section-head { margin-bottom: var(--sp-6); }
.section-head h2 { margin-bottom: var(--sp-2); }
.section-head p { color: var(--ink-2); max-width: 46rem; }

.stack > * + * { margin-top: var(--sp-4); }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: var(--sp-3) var(--sp-4);
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-mono);
  font-size: var(--step--1);
}
.skip-link:focus { left: var(--sp-4); top: var(--sp-4); }

.visually-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ============================================================================
   05. PIXEL-ART PRIMITIVES
   ============================================================================ */

/* Four L-shaped corner brackets drawn with background gradients — no assets,
   colour controlled by `--bc`, geometry by `--arm` / `--thick`. */
.px-brackets { position: relative; }
.px-brackets::after {
  content: "";
  position: absolute;
  inset: calc(-1 * var(--gap, 6px));
  --arm: 13px;
  --thick: 2px;
  --bc: var(--ink);
  pointer-events: none;
  background:
    linear-gradient(var(--bc), var(--bc)) left top / var(--arm) var(--thick) no-repeat,
    linear-gradient(var(--bc), var(--bc)) left top / var(--thick) var(--arm) no-repeat,
    linear-gradient(var(--bc), var(--bc)) right top / var(--arm) var(--thick) no-repeat,
    linear-gradient(var(--bc), var(--bc)) right top / var(--thick) var(--arm) no-repeat,
    linear-gradient(var(--bc), var(--bc)) left bottom / var(--arm) var(--thick) no-repeat,
    linear-gradient(var(--bc), var(--bc)) left bottom / var(--thick) var(--arm) no-repeat,
    linear-gradient(var(--bc), var(--bc)) right bottom / var(--arm) var(--thick) no-repeat,
    linear-gradient(var(--bc), var(--bc)) right bottom / var(--thick) var(--arm) no-repeat;
}

/* ============================================================================
   06. BUTTONS & CONTROLS
   ============================================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0.7rem 1.15rem;
  border: var(--rule-w) solid var(--ink);
  background: var(--paper-raised);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.02em;
  line-height: 1.2;
  cursor: pointer;
  transition: transform 0.08s steps(2), box-shadow 0.08s steps(2),
              background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translate(2px, 2px); box-shadow: none; }

.btn--primary {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
.btn--primary:hover {
  background: var(--accent-deep);
  border-color: var(--accent-deep);
  box-shadow: var(--px-shadow);
}

.btn--ghost { background: transparent; border-color: var(--rule-2); color: var(--ink-2); }
.btn--ghost:hover {
  border-color: var(--ink);
  color: var(--ink);
  box-shadow: var(--px-shadow);
}

.btn--small { padding: 0.45rem 0.8rem; font-size: var(--step--2); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  align-items: center;
}

/* Small square icon link (socials, footer actions). */
.icon-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 2.25rem;
  block-size: 2.25rem;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  color: var(--ink-2);
  font-size: 0.95rem;
  transition: color 0.12s ease, border-color 0.12s ease, background-color 0.12s ease;
}
.icon-link:hover {
  color: var(--ink);
  border-color: var(--ink);
  text-decoration: none;
}
.icon-link svg { inline-size: 1.05rem; block-size: 1.05rem; }

/* --- Header clearance --------------------------------------------------- */
/* The dock floats over the page, so main content is offset below it.
   `main` also grows to fill the viewport so the footer always sits on the
   bottom edge of short pages. */
#main-content {
  position: relative;
  padding-top: var(--header-h);
  flex: 1 0 auto;
}
/* A dashed rule closes the header band, matching the page frame and section
   dividers. It scrolls away with the sheet rather than pinning to the dock. */
#main-content::before {
  content: "";
  position: absolute;
  inset: var(--header-h) 0 auto;
  border-top: var(--rule-w) dashed var(--rule-2);
  pointer-events: none;
}

/* ============================================================================
   07. SITE HEADER — floating pill dock
   A compact, centred capsule that hovers over the paper. Fixed rather than
   sticky so the grid stays continuous behind it.
   ============================================================================ */
.site-header {
  position: fixed;
  top: var(--sp-3);
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  /* Hug the links rather than sitting at a fixed 34rem: the capsule should read
     as tightly packed, not as a wide pill with slack at both ends. */
  width: max-content;
  max-width: calc(100% - var(--sp-5));
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.15rem;
  padding: 0.3rem 0.4rem;
  background: rgba(255, 255, 255, 0.9);
  border: var(--rule-w) solid var(--rule-2);
  border-radius: var(--radius-pill);
  box-shadow:
    0 1px 0 rgba(22, 24, 28, 0.03),
    0 4px 14px rgba(22, 24, 28, 0.06);
  backdrop-filter: saturate(150%) blur(10px);
  -webkit-backdrop-filter: saturate(150%) blur(10px);
}

.site-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.15rem;
  flex-wrap: nowrap;
  min-width: 0;
}

.nav-link {
  display: block;
  padding: 0.4rem 0.7rem;
  border: var(--rule-w) solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  color: var(--ink-2);
  white-space: nowrap;
  transition: color 0.12s ease, background-color 0.12s ease, border-color 0.12s ease;
}
.nav-link:hover {
  color: var(--ink);
  background: var(--paper-sunken);
  text-decoration: none;
}
.nav-link[aria-current="page"] {
  color: var(--accent-deep);
  background: var(--accent-soft);
  border-color: var(--accent-line);
}

.nav-group {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  margin-left: 0.35rem;
  /* 0.85rem, not 0.4rem: the divider is a full 13.6px from the last nav
     label and from the Contact pill, so it sits centred between them rather
     than crowding the button. */
  padding-left: 0.85rem;
  border-left: var(--rule-w) solid var(--rule);
}
.nav-group .icon-link {
  inline-size: 2rem;
  block-size: 2rem;
  border-radius: var(--radius-pill);
  border-color: transparent;
  background: transparent;
  font-size: 0.95rem;
}
.nav-group .icon-link:hover {
  color: var(--accent-deep);
  background: var(--accent-soft);
  border-color: var(--accent-line);
}
.nav-group .icon-link svg { inline-size: 1rem; block-size: 1rem; }

/* The dock's one call to action: pure black on white, and it stays that way.
   Following the link must not repaint it, so :link, :visited and :hover are
   all pinned — the only change on hover is the inversion. */
.nav-cta,
.nav-cta:link,
.nav-cta:visited,
.nav-cta:active {
  display: inline-flex;
  align-items: center;
  padding: 0.42rem 0.9rem;
  border: var(--rule-w) solid var(--ink);
  border-radius: var(--radius-pill);
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.04em;
  line-height: 1.2;
  white-space: nowrap;
  transition: background-color 0.12s ease, color 0.12s ease;
}
.nav-cta:hover,
.nav-cta:focus-visible {
  background: var(--paper-raised);
  border-color: var(--ink);
  color: var(--ink);
  text-decoration: none;
}

@media (max-width: 30rem) {
  .nav-link { padding: 0.38rem 0.5rem; font-size: var(--step--2); }
  .nav-group { margin-left: 0.2rem; padding-left: 0.7rem; }
  .nav-group .icon-link { inline-size: 1.75rem; block-size: 1.75rem; }
  .nav-cta { padding: 0.36rem 0.6rem; letter-spacing: 0.02em; }
}

/* ============================================================================
   08. SITE FOOTER — a quiet close to the page
   Two things only: one row (links left, colophon over a back-to-top link on
   the right), sitting in generous air on the white stock.
   ============================================================================ */
.site-footer {
  position: relative;
  background: transparent;
}
.site-footer::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 0;
  border-top: var(--rule-w) dashed var(--rule-2);
}

.footer-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3) var(--sp-6);
  padding-block: clamp(2.5rem, 5vw, 4rem) clamp(2rem, 4vw, 3.5rem);
}

/* --- links -------------------------------------------------------------- */
.footer-links {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem 0.85rem;
}
.footer-link {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45rem;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.04em;
  color: var(--ink-2);
  transition: color 0.12s ease;
}
.footer-link:hover { color: var(--accent-deep); text-decoration: none; }

/* Pixel bullet — a square, not a round chip, so it reads as pixel art
   rather than as an icon font. */
.footer-dot {
  inline-size: 5px;
  block-size: 5px;
  background: var(--rule-3);
  flex: none;
  transform: translateY(-2px);
  transition: background-color 0.12s ease;
}
.footer-link:hover .footer-dot { background: var(--accent); }

/* --- colophon + back to top --------------------------------------------- */
.footer-aside {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
}
.footer-aside > * + * { margin-top: 0.5rem; }
.footer-note {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-4);
}
.footer-note a { color: var(--ink-3); }
.footer-note a:hover { color: var(--accent-deep); text-decoration: none; }

.footer-top {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.footer-top:hover { color: var(--accent-deep); text-decoration: none; }
.footer-top__arrow { font-size: 1.05em; line-height: 0; transform: translateY(-1px); }

@media (max-width: 48rem) {
  /* The row cannot hold links plus colophon: stack them, centred, so it reads
     as a deliberate signature instead of a squeeze. */
  .footer-row {
    flex-direction: column;
    align-items: center;
    padding-block: var(--sp-6) var(--sp-5);
    text-align: center;
  }
  /* margin, not gap: keeps the spacing if `gap` inside a column flex
     container is unsupported (older Safari). */
  .footer-row > * + * { margin-top: var(--sp-5); }
  .footer-links { justify-content: center; }
  .footer-aside { align-items: center; text-align: center; }
}

@media (max-width: 32rem) {
  .footer-links { gap: 0.3rem 0.6rem; }
  .footer-link,
  .footer-note,
  .footer-top { font-size: var(--step--2); }
  .footer-link { gap: 0.35rem; }
  .footer-note { letter-spacing: 0.04em; }
}

/* ============================================================================
   09. HERO
   ============================================================================ */
.hero { padding-block: clamp(4.5rem, 9vw, 8rem) clamp(4rem, 7vw, 6.5rem); }

.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 17rem;
  gap: var(--sp-8);
  align-items: start;
}
@media (max-width: 56rem) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); gap: var(--sp-6); }
}

/* --- ASCII wordmark ----------------------------------------------------- */
/* Three stacked copies of the same block art, offset by whole pixels, read as
   a letterpress extrusion. The front copy carries a teal-to-ink wash; the
   offsets stay paper-toned, with no glow or blur.

   The art is 71 monospace cells wide, so the font size is capped by the space
   actually available beside (or above) the portrait — the wordmark can never
   clip, at any viewport. Below 34rem it gives way to set type. */
.ascii-name {
  --ascii-cols: 42.6;               /* 71 cells x 0.6em advance */
  /* 17rem portrait + 2rem gap + 3rem container gutters. */
  --ascii-size: min(0.85rem, (min(70rem, 100vw) - 22rem) / var(--ascii-cols));
  margin: 0 0 var(--sp-5);
  line-height: 0;
}

.ascii-name__stack {
  position: relative;
  display: block;
  font-size: var(--ascii-size);
  line-height: 1;
}

.ascii-name__layer {
  margin: 0;
  font-family: var(--font-mono);
  font-size: inherit;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0;
  white-space: pre;
  background: none;
  border: 0;
  padding: 0;
  overflow: visible;
}

.ascii-name__layer--back,
.ascii-name__layer--mid {
  position: absolute;
  inset: 0;
  user-select: none;
  pointer-events: none;
}
.ascii-name__layer--back  { color: var(--rule-2); transform: translate(3px, 3px); }
.ascii-name__layer--mid   { color: var(--rule-3); transform: translate(1.5px, 1.5px); }
.ascii-name__layer--front {
  position: relative;
  z-index: 1;
  color: var(--ink);
  background: linear-gradient(180deg, var(--ink) 30%, var(--accent-deep) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

@media (max-width: 56rem) {
  /* Single-column hero: the wordmark owns the full measure. 4rem covers the
     container gutters plus the scrollbar. */
  .ascii-name { --ascii-size: min(0.78rem, (min(70rem, 100vw) - 4rem) / var(--ascii-cols)); }
  .ascii-name__layer--back { display: none; }
}
@media (max-width: 40rem) {
  /* Tighten the gutter so the 71-cell wordmark keeps as much size as possible. */
  .ascii-name { --ascii-size: min(0.62rem, (100vw - 4rem) / var(--ascii-cols)); }
}

.hero-role {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  margin: 0 0 var(--sp-5);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--ink-2);
}
.hero-role .at { color: var(--ink-4); }

/* Role badge — the original pill treatment, with a live status dot. */
.role-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.28rem 0.65rem;
  border: var(--rule-w) solid var(--accent-line);
  border-radius: 6px;
  background: var(--accent-soft);
  color: var(--accent-deep);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}
.role-badge::before {
  content: "";
  inline-size: 6px;
  block-size: 6px;
  flex: none;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 0 rgba(15, 107, 94, 0.35);
  animation: role-pulse 3s ease-out infinite;
}
@keyframes role-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(15, 107, 94, 0.35); }
  70%  { box-shadow: 0 0 0 8px rgba(15, 107, 94, 0); }
  100% { box-shadow: 0 0 0 0 rgba(15, 107, 94, 0); }
}
.company-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0.25rem 0.6rem 0.25rem 0.3rem;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  color: var(--ink);
  font-weight: 500;
}
.company-pill:hover { border-color: var(--ink); text-decoration: none; }
/* The Codegig mark is yellow-on-transparent, so it needs a dark chip to read
   against paper. */
.company-pill img {
  inline-size: 1.15rem;
  block-size: 1.15rem;
  padding: 2px;
  background: var(--ink);
  border-radius: 2px;
}

.hero-bio {
  max-width: 38rem;
  margin: 0 0 var(--sp-6);
  font-size: var(--step-1);
  line-height: 1.62;
  color: var(--ink-2);
}
.hero-bio strong { color: var(--ink); font-weight: 650; }
/* Frosted chip for the live location + weather, as on the old site — re-cut
   for paper: flat raised fill, a bright top highlight, a soft cast shadow. */
.weather-display {
  display: inline-flex;
  align-items: center;
  padding: 0.05em 0.5em;
  margin: 0 1px;
  border: var(--rule-w) solid var(--rule-2);
  border-radius: 6px;
  background: var(--paper-raised);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  backdrop-filter: blur(10px) saturate(160%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    inset 0 -1px 0 rgba(22, 24, 28, 0.04),
    0 1px 2px rgba(22, 24, 28, 0.06);
  font-weight: 500;
  color: var(--ink);
  white-space: nowrap;
  vertical-align: baseline;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.weather-display:hover {
  border-color: var(--accent-line);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    0 2px 10px rgba(15, 107, 94, 0.16);
}
.weather-display a {
  display: inline-flex;
  align-items: center;
  color: inherit;
  text-decoration: none;
}

/* ---- Pixel portrait ---------------------------------------------------- */
.hero-portrait { position: relative; justify-self: end; }
@media (max-width: 56rem) { .hero-portrait { justify-self: start; order: -1; } }

.avatar-frame {
  --gap: 7px;
  position: relative;
  z-index: 1;
  display: block;
  inline-size: clamp(12rem, 18vw, 17rem);
  padding: var(--sp-2);
  background: var(--paper-raised);
  border: var(--rule-w) solid var(--ink);
  box-shadow: var(--px-shadow-ink);
}
.avatar-frame img {
  inline-size: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  image-rendering: pixelated;
  -ms-interpolation-mode: nearest-neighbor;
}
.avatar-caption {
  position: absolute;
  left: 0;
  bottom: calc(-1 * var(--sp-6));
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-3);
  white-space: nowrap;
}
@media (max-width: 56rem) {
  .avatar-frame { inline-size: 9rem; }
  .avatar-caption { display: none; }
}

/* ============================================================================
   09b. EXPERIENCE
   ============================================================================ */
.exp-list {
  display: grid;
  gap: var(--sp-5);
}

.exp {
  padding: var(--sp-5) var(--sp-6);
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
}
.exp:hover {
  border-color: var(--accent-line);
  box-shadow: 0 14px 36px rgba(29, 29, 31, 0.06);
  transform: translateY(-2px);
}

.exp-head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  padding-bottom: var(--sp-4);
  border-bottom: var(--rule-w) solid var(--rule);
}

.exp-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 2.6rem;
  block-size: 2.6rem;
  flex: none;
  border: var(--rule-w) solid var(--rule);
  background: var(--paper-sunken);
}
.exp-mark img { inline-size: 1.6rem; block-size: 1.6rem; object-fit: contain; }
/* Marks that are light-on-transparent need a dark tile to read on paper. */
.exp-mark--dark { background: var(--ink); border-color: var(--ink); }
.exp-initial {
  font-family: var(--font-pixel);
  font-size: 1.05rem;
  line-height: 1;
  color: var(--ink-3);
}

.exp-id { flex: 1; min-width: 0; }
.exp-role {
  margin: 0 0 0.15rem;
  font-size: var(--step-2);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
}
.exp-role a { color: var(--ink); }
.exp-role a:hover { color: var(--accent); text-decoration: none; }

.exp-company {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.04em;
  color: var(--ink-3);
}
.exp-company a { color: var(--ink-2); }
.exp-company a:hover { color: var(--accent); }
.exp-company .sep { inline-size: 3px; block-size: 3px; background: var(--rule-3); }

.exp-period {
  flex: none;
  margin: 0;
  padding-top: 0.2rem;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.04em;
  color: var(--ink-3);
  text-align: right;
  white-space: nowrap;
}

.exp-summary {
  margin: var(--sp-4) 0 0;
  font-size: var(--step-0);
  line-height: 1.6;
  color: var(--ink-2);
}

.exp-points {
  margin: var(--sp-4) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--sp-3);
}
.exp-points li {
  position: relative;
  padding-left: 1.15rem;
  font-size: var(--step--1);
  line-height: 1.65;
  color: var(--ink-2);
}
.exp-points li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  inline-size: 5px;
  block-size: 5px;
  background: var(--accent);
}

.exp-stack {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: var(--sp-5) 0 0;
  padding: var(--sp-4) 0 0;
  border-top: var(--rule-w) solid var(--rule);
  list-style: none;
}
.stack-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.25rem 0.6rem;
  border: var(--rule-w) solid var(--rule);
  background: var(--paper-sunken);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-2);
}
.stack-tag img { inline-size: 0.9rem; block-size: 0.9rem; flex: none; }
.stack-tag i { font-size: 0.8rem; color: var(--ink-3); flex: none; }

@media (max-width: 40rem) {
  .exp { padding: var(--sp-5); }
  .exp-head { flex-wrap: wrap; }
  .exp-period { text-align: left; padding-top: 0; width: 100%; }
}

/* ============================================================================
   10. SKILLS INDEX
   Two columns at desktop width, so an opened entry gets a readable measure
   instead of a narrow ribbon of text.
   ============================================================================ */
.skill-groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: var(--sp-7) var(--sp-6);
  align-items: start;
}

.skill-group-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-2);
  padding-bottom: var(--sp-2);
  border-bottom: var(--rule-w) solid var(--ink);
  font-family: var(--font-pixel);
  font-size: 0.72rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.skill-group-title .count {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-4);
  letter-spacing: 0;
}
.skill-group-desc {
  margin: 0 0 var(--sp-4);
  font-size: var(--step--1);
  color: var(--ink-3);
  line-height: 1.55;
}

.skill-list { list-style: none; margin: 0; padding: 0; }

.skill {
  border-bottom: var(--rule-w) solid var(--rule);
}
.skill > summary {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 0.4rem 0;
  cursor: pointer;
  list-style: none;
  color: var(--ink-2);
  transition: color 0.12s ease;
}
.skill > summary::-webkit-details-marker { display: none; }
.skill > summary:hover { color: var(--ink); }
.skill > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.skill-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 1.4rem;
  block-size: 1.4rem;
  flex: none;
  border: var(--rule-w) solid var(--rule);
  background: var(--paper-raised);
}
.skill-mark img { inline-size: 0.9rem; block-size: 0.9rem; }

.skill-name { flex: 1; font-size: var(--step--1); font-weight: 500; }

.skill-toggle {
  flex: none;
  font-size: 0.75rem;
  color: var(--ink-4);
  transition: color 0.12s ease, transform 0.12s ease;
}
.skill[open] > summary .skill-toggle { color: var(--accent); transform: rotate(90deg); }
.skill[open] > summary { color: var(--ink); font-weight: 600; }

.skill-detail {
  padding: 0 0 var(--sp-4) 2.25rem;
  font-size: var(--step--1);
  line-height: 1.65;
  color: var(--ink-2);
}
.skill-detail p { margin: 0 0 var(--sp-3); }
.skill-projects {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-3);
}
.skill-projects a {
  padding: 0.15rem 0.45rem;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  color: var(--ink-2);
}
.skill-projects a:hover { border-color: var(--ink); color: var(--ink); text-decoration: none; }

/* ============================================================================
   11. CARDS
   ----------------------------------------------------------------------------
   One component for every project and every post: a gallery print. A clipped
   mount holds the figure, with the caption on a smaller plate hung below and
   to the right. The grid is salon-hung, so the second column sits lower.

   The wireframe window (`.three-container`) and the tilt live in depth.css.
   `.card-tags` and `.card-badge` are also used by the project detail header,
   so they stay here even though the card itself no longer renders them.
   ============================================================================ */
.card-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 3rem 2.5rem;                 /* mockup: 48 / 40 */
  list-style: none;
  margin: 0;
  padding: 0;
}

/* The wrapper is a grid child on the blog list; keep the 3D context flowing
   through it so the tilt still gets the grid's perspective. */
.card-grid > * { min-width: 0; transform-style: preserve-3d; }
.card-grid > *:nth-child(2n) { margin-top: 2.25rem; }

@media (max-width: 48rem) {
  .card-grid { grid-template-columns: minmax(0, 1fr); gap: var(--sp-8); }
  .card-grid > *:nth-child(2n) { margin-top: 0; }
}

/* ---- The print ---------------------------------------------------------- */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
}

/* Bulldog clip holding the print to the wall. */
.card-clip {
  position: absolute;
  top: -0.7rem;
  left: 50%;
  margin-left: -0.7rem;
  inline-size: 1.4rem;
  block-size: 1rem;
  color: var(--ink);
  pointer-events: none;
  transform: translateZ(34px);
}
.card-clip svg { display: block; inline-size: 100%; block-size: 100%; }
.card-clip::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 0.95rem;
  inline-size: 1px;
  block-size: 0.6rem;
  margin-left: -0.5px;
  background: var(--rule-3);
}

/* ---- Mount: the matted figure ------------------------------------------- */
.card-mount {
  position: relative;
  padding: var(--sp-4);
  background: var(--paper-raised);
  border: var(--rule-w) solid var(--ink);
  box-shadow: var(--px-shadow-ink);
  /* No preserve-3d here on purpose: it would project the wireframe window's
     translateZ and drag it off the corner it is meant to lap over. */
}

.card-art {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
}
.card-art img {
  inline-size: 100%;
  block-size: 100%;
  /* contain, never cover: a screenshot or a plot is evidence, don't crop it */
  object-fit: contain;
  filter: saturate(0.94);
  transition: transform 0.35s cubic-bezier(0.2, 0.7, 0.3, 1);
}
.card:hover .card-art img { transform: scale(1.015); }

/* No screenshot: ruled paper, and the wireframe takes the frame. */
.card-art--blank {
  background-color: var(--paper-sunken);
  background-image:
    linear-gradient(var(--grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: 14px 14px;
}
.card-blank-tag {
  position: absolute;
  left: var(--sp-3);
  bottom: var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-4);
}

/* ---- Caption plate: narrower than the print, hung off-centre ------------- */
.card-plate {
  align-self: flex-start;
  max-inline-size: min(100%, 22rem);
  margin: 1.1rem 0 0 1.9rem;
  padding: 0.7rem 0.9rem 0.75rem;
  background: var(--paper-raised);
  border: var(--rule-w) solid var(--ink);
  box-shadow: 2px 2px 0 var(--ink);
  transform: translateZ(14px);
}
@media (max-width: 30rem) {
  .card-plate { margin-left: var(--sp-4); max-inline-size: 100%; }
}

.card-kicker {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0 0 0.35rem;
  font-family: var(--font-pixel);
  font-size: 0.6rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.card-dot { inline-size: 0.5rem; block-size: 0.5rem; background: var(--rule-3); flex: none; }
.card--featured .card-dot { background: var(--accent); }

.card-title {
  margin: 0 0 0.3rem;
  font-size: 1.0625rem;
  font-weight: 650;
  letter-spacing: -0.015em;
  line-height: 1.3;
}
.card-title a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 0.18em;
  transition: color 0.12s ease, text-decoration-color 0.12s ease;
}
.card:hover .card-title a { color: var(--accent); text-decoration-color: var(--accent-line); }

/* Class name kept as `card-excerpt`: static/js/blog-list.js searches it. */
.card-excerpt {
  margin: 0 0 0.55rem;
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--ink-2);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 0.45rem;
  margin: 0;
  padding: 0.45rem 0 0;
  border-top: var(--rule-w) solid var(--rule);
  list-style: none;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.card-meta li + li::before { content: "·"; margin-right: 0.45rem; color: var(--rule-3); }
/* The trailing field sits hard right; suppress its separator. */
.card-meta-end { margin-left: auto; }
.card-meta-end::before { content: none !important; margin: 0 !important; }
.card-meta a { color: var(--ink-3); }
.card-meta a:hover { color: var(--accent); }

.card-status {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: var(--ink-2);
  white-space: nowrap;
}
.card-status::before { content: ""; inline-size: 6px; block-size: 6px; background: var(--accent); flex: none; }
.card-status--wip { color: var(--ink-4); }
.card-status--wip::before { background: var(--rule-2); }

/* ---- Also used by the project detail header ------------------------------ */
.card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.card-tag {
  padding: 0.1rem 0.45rem;
  border: var(--rule-w) solid var(--rule);
  background: var(--paper-sunken);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-3);
}
.card-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* ============================================================================
   12. SECTION FURNITURE
   ============================================================================ */
.section-actions {
  display: flex;
  justify-content: center;
  margin-top: var(--sp-6);
}

/* Framed live embed (the Paokinator game). */
.embed-panel {
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  padding: var(--sp-3);
}
.embed-panel-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: 0 var(--sp-1) var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.embed-panel-bar .lights { display: inline-flex; gap: 5px; }
.embed-panel-bar .lights i {
  inline-size: 8px;
  block-size: 8px;
  background: var(--rule-2);
}
.embed-panel-bar .lights i:first-child { background: var(--rule-3); }
.embed-panel-frame {
  position: relative;
  border: var(--rule-w) solid var(--rule);
  background: var(--paper-sunken);
}
.embed-panel-frame iframe {
  display: block;
  inline-size: 100%;
  block-size: 34rem;
  border: 0;
}
@media (max-width: 48rem) { .embed-panel-frame iframe { block-size: 26rem; } }

.empty-state {
  padding: var(--sp-8) var(--sp-5);
  border: var(--rule-w) dashed var(--rule-3);
  background: var(--paper-raised);
  text-align: center;
}
.empty-state .empty-glyph { font-size: 1.6rem; color: var(--ink-4); margin-bottom: var(--sp-4); display: block; }
.icon-lg { font-size: 1.5em; line-height: 1; }
.empty-title { margin: 0 0 var(--sp-2); font-size: var(--step-2); }
.empty-message { margin: 0 auto var(--sp-5); max-width: 34rem; color: var(--ink-2); }
.empty-cta { display: flex; justify-content: center; }

/* Prev / next navigation between sibling pages. */
.pager {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-4);
  margin-top: var(--sp-8);
  padding-top: var(--sp-6);
  border-top: var(--rule-w) solid var(--rule);
}
.pager--single { grid-template-columns: minmax(0, 1fr); }
.pager-link {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4);
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  color: var(--ink);
  transition: border-color 0.12s ease, box-shadow 0.12s steps(2),
              transform 0.08s steps(2);
}
.pager-link:hover {
  border-color: var(--ink);
  box-shadow: var(--px-shadow);
  text-decoration: none;
}
.pager-link:active { transform: translate(2px, 2px); box-shadow: none; }
.pager-arrow {
  display: grid;
  place-items: center;
  flex: none;
  inline-size: 2.75rem;
  block-size: 2.75rem;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-sunken);
  color: var(--ink-2);
  font-size: var(--step--1);
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.pager-link:hover .pager-arrow,
.pager-link:focus-visible .pager-arrow {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}
.pager-copy {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 0.2rem;
  min-inline-size: 0;
}
.pager-link--next { text-align: right; }
.pager-link--next .pager-arrow { order: 2; }
.pager-direction {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.pager-link--next .pager-direction { justify-content: flex-end; }
.pager-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  font-weight: 600;
  line-height: 1.35;
}
@media (max-width: 40rem) {
  .pager { grid-template-columns: minmax(0, 1fr); }
  .pager-link--next { text-align: left; }
  .pager-link--next .pager-direction { justify-content: flex-start; }
}

.back-link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-5);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.back-link:hover { color: var(--ink); text-decoration: none; }

/* ============================================================================
   13. HOMEPAGE SECTIONS
   ============================================================================ */
.page-head { padding-block: var(--sp-8) var(--sp-6); }
.page-head h1 { margin-bottom: var(--sp-3); }
.page-head .lede { max-width: 40rem; }
.page-head-extra { margin: var(--sp-5) 0 0; color: var(--ink-3); }
.page-head-extra .back-link { margin-bottom: 0; }

/* A plain-spoken note on who writes the blog. It belongs to the page head,
   not the prose, so it keeps the lede's measure and its own quiet icon. */
.writing-note {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  max-width: 40rem;
  margin: var(--sp-4) 0 0;
  font-size: var(--step-0);
  line-height: 1.6;
  color: var(--ink-2);
}
.writing-note i {
  flex: none;
  margin-top: 0.2em;
  color: var(--accent);
}

/* ============================================================================
   14. BLOG LIST CONTROLS
   ============================================================================ */
/* The page head already supplies the break above the search controls; adding
   the section's full top padding here opened a second, empty chapter. */
.blog-index { padding-block-start: 0; }

.list-controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-bottom: var(--sp-6);
  padding-bottom: var(--sp-5);
  border-bottom: var(--rule-w) solid var(--rule);
}

.search-field {
  position: relative;
  flex: 1 1 16rem;
  display: flex;
  align-items: center;
}
.search-field > i {
  position: absolute;
  left: 0.8rem;
  font-size: 0.85rem;
  color: var(--ink-4);
  pointer-events: none;
}
.search-field input {
  inline-size: 100%;
  padding: 0.6rem 0.8rem 0.6rem 2.2rem;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--ink);
}
.search-field input::placeholder { color: var(--ink-4); }
.search-field input:focus { outline: none; border-color: var(--ink); box-shadow: var(--px-shadow); }

.filter-wrap { position: relative; }
.filter-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0.6rem 0.9rem;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  color: var(--ink-2);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  cursor: pointer;
}
.filter-toggle:hover { border-color: var(--ink); color: var(--ink); }

.filter-dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 30;
  display: none;
  min-width: 13rem;
  max-height: 20rem;
  overflow-y: auto;
  padding: var(--sp-2);
  border: var(--rule-w) solid var(--ink);
  background: var(--paper-raised);
  box-shadow: var(--px-shadow);
}
.filter-dropdown.active { display: block; }
/* On a phone the toggle sits near the left edge, so a right-aligned 13rem
   menu hangs off the screen. Drop the menu as a full-width panel below the
   whole control row instead. */
@media (max-width: 30rem) {
  .list-controls { position: relative; }
  .filter-wrap { position: static; }
  .filter-dropdown {
    left: 0;
    right: 0;
    min-inline-size: 0;
    max-inline-size: none;
  }
}
.tag-filter {
  display: block;
  inline-size: 100%;
  padding: 0.4rem 0.6rem;
  border: 0;
  background: transparent;
  color: var(--ink-2);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  text-align: left;
  cursor: pointer;
}
.tag-filter:hover { background: var(--paper-sunken); color: var(--ink); }
.tag-filter.active { background: var(--accent-soft); color: var(--accent-deep); font-weight: 500; }

/* ============================================================================
   15. NOW TIMELINE
   ============================================================================ */
/* The spine is two stacked 2px rules: a static track and an accent fill that
   is scaled from the top as the reader scrolls (see js/timeline.js). */
.timeline {
  position: relative;
  margin: 0;
  padding: 0 0 0 var(--sp-6);
  list-style: none;
}
.timeline::before,
.timeline::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  inline-size: 2px;
}
.timeline::before { background: var(--rule-2); }
.timeline::after {
  background: var(--accent);
  transform: scaleY(var(--timeline-progress, 0));
  transform-origin: top center;
}

.entry { position: relative; padding-bottom: var(--sp-7); }
.entry:last-child { padding-bottom: 0; }
.entry::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--sp-6) - 2.5px);
  top: 0.45rem;
  inline-size: 7px;
  block-size: 7px;
  background: var(--accent);
}

/* Reveal-on-scroll is opt-in: js/timeline.js adds `.is-animated`, so the page
   is fully readable with JavaScript off. */
.timeline.is-animated .entry > * {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.45s ease, transform 0.45s cubic-bezier(0.22, 0.8, 0.3, 1);
}
.timeline.is-animated .entry::before {
  transform: scale(0);
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.timeline.is-animated .entry.is-visible > * { opacity: 1; transform: none; }
.timeline.is-animated .entry.is-visible::before { transform: scale(1); }
.timeline.is-animated .entry > *:nth-child(2) { transition-delay: 0.06s; }
.timeline.is-animated .entry > *:nth-child(3) { transition-delay: 0.12s; }
.timeline.is-animated .entry > *:nth-child(n+4) { transition-delay: 0.18s; }

@media (prefers-reduced-motion: reduce) {
  .timeline.is-animated .entry > *,
  .timeline.is-animated .entry::before { opacity: 1; transform: none; }
}

.entry-date {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.entry-mood {
  display: inline-block;
  margin-left: var(--sp-3);
  padding: 0.05rem 0.4rem;
  border: var(--rule-w) solid var(--rule);
  background: var(--paper-raised);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-3);
}
.entry-title { margin: 0 0 var(--sp-3); font-size: var(--step-2); }
.entry-body { color: var(--ink-2); }
.entry-image {
  margin-top: var(--sp-4);
  border: var(--rule-w) solid var(--rule);
  background: var(--paper-raised);
  padding: var(--sp-2);
}
.entry-tags { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-4); }
.entry-tag {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-3);
}
.timeline-footer {
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: var(--rule-w) solid var(--rule);
  color: var(--ink-3);
  font-size: var(--step--1);
}

/* ============================================================================
   16. TAGS
   ============================================================================ */
.tag-cloud {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: var(--sp-3);
}
.tag-item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  color: var(--ink);
  transition: border-color 0.12s ease, box-shadow 0.12s steps(2);
}
.tag-item:hover { border-color: var(--ink); box-shadow: var(--px-shadow); text-decoration: none; }
.tag-name { font-family: var(--font-mono); font-size: var(--step--1); font-weight: 500; }
.tag-count { font-family: var(--font-mono); font-size: var(--step--2); color: var(--ink-4); }

/* ============================================================================
   17. CONTACT PAGE
   ============================================================================ */
.contact-shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.contact-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  /* Matches .contact-card so the bar reads as the card's running head. */
  max-width: 40rem;
  width: 100%;
  margin-inline: auto;
  padding: var(--sp-5) var(--sp-5) var(--sp-3);
}
/* --- Back link ----------------------------------------------------------- */
/* One control, shared by the contact top bar and the project detail pages:
   step back through history when there is history, otherwise fall through to
   the href, which is always the sensible parent. */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.back-link:hover { color: var(--ink); text-decoration: none; }
.back-link i { font-size: 0.72rem; }

.contact-main {
  flex: 1;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--sp-6) var(--sp-5) var(--sp-9);
}
.contact-card {
  width: 100%;
  max-width: 40rem;
}
.contact-card h1 { margin-bottom: var(--sp-3); }
.contact-card .lede { margin-bottom: var(--sp-6); }

.cooldown-text {
  margin: var(--sp-3) 0 0;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-3);
}

/* Hugging Face brand mark inside the "elsewhere" list. */
.hf-mark { display: inline-flex; }
.hf-mark svg { inline-size: 0.95rem; block-size: 0.95rem; }

.contact-form {
  display: grid;
  gap: var(--sp-5);
  padding: var(--sp-6);
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
}

.field { display: grid; gap: var(--sp-2); }
.field label {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.field input,
.field textarea {
  inline-size: 100%;
  padding: 0.7rem 0.85rem;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper);
  font-family: var(--font-sans);
  font-size: var(--step-0);
  color: var(--ink);
  transition: border-color 0.12s ease, box-shadow 0.12s steps(2);
}
.field textarea { resize: vertical; min-height: 9rem; line-height: 1.6; }
.field input::placeholder,
.field textarea::placeholder { color: var(--ink-4); }
.field input:focus,
.field textarea:focus { outline: none; border-color: var(--ink); box-shadow: var(--px-shadow); }

.form-actions { display: flex; justify-content: flex-start; }
.form-submit {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0.7rem 1.25rem;
  border: var(--rule-w) solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  cursor: pointer;
  transition: transform 0.08s steps(2), box-shadow 0.08s steps(2), background-color 0.12s ease;
}
.form-submit:hover { background: var(--accent-deep); border-color: var(--accent-deep); box-shadow: var(--px-shadow); }
.form-submit:active { transform: translate(2px, 2px); box-shadow: none; }
.form-submit[disabled] { opacity: 0.55; cursor: not-allowed; box-shadow: none; }

.form-status {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--accent-deep);
}
.form-status--error { color: #b91c1c; }

.thank-you {
  padding: var(--sp-7) var(--sp-6);
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  text-align: center;
}
.thank-you .thank-you-glyph { font-size: 1.9rem; color: var(--accent); margin-bottom: var(--sp-4); display: block; }
.thank-you h2 { margin-bottom: var(--sp-3); }
.thank-you p { color: var(--ink-2); }
.thank-you.hidden { display: none; }

.contact-elsewhere {
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: var(--rule-w) solid var(--rule);
}
/* Leading position: the profiles come before the form, so the rule moves to
   the underside and the block introduces the page instead of closing it. */
.contact-elsewhere--lead {
  margin-top: 0;
  margin-bottom: var(--sp-6);
  padding-top: 0;
  padding-bottom: var(--sp-5);
  border-top: 0;
  border-bottom: var(--rule-w) solid var(--rule);
}
.contact-elsewhere--lead .contact-elsewhere-label { margin-bottom: var(--sp-4); }
.contact-elsewhere-label {
  margin: 0 0 var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.contact-elsewhere-links { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.contact-elsewhere-links a {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0.4rem 0.7rem;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  color: var(--ink-2);
  font-family: var(--font-mono);
  font-size: var(--step--2);
}
.contact-elsewhere-links a:hover { border-color: var(--ink); color: var(--ink); text-decoration: none; }
.contact-elsewhere-links svg { inline-size: 0.95rem; block-size: 0.95rem; }

/* ============================================================================
   18. RÉSUMÉ PAGE
   ============================================================================ */
/* The document viewer is the framed embed from section 12 with a portrait
   opening: a letter page needs for height what the game embed spends on width. */
.resume-viewer .embed-panel-frame iframe {
  block-size: min(78vh, 56rem);
  min-block-size: 30rem;
}
@media (max-width: 48rem) {
  .resume-viewer .embed-panel-frame iframe { block-size: 62vh; min-block-size: 24rem; }
}

/* Caption under the panel: what the file is, then the escape hatch for the
   browsers (mostly mobile Safari) that will not render a PDF inline. */
.resume-note {
  margin: var(--sp-4) 0 0;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  line-height: 1.7;
  color: var(--ink-3);
}

/* ============================================================================
   19. 404
   ============================================================================ */
.not-found {
  display: grid;
  place-items: center;
  min-height: 60vh;
  padding: var(--sp-9) var(--sp-5);
  text-align: center;
}
.not-found-code {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  margin-bottom: var(--sp-5);
  font-family: var(--font-pixel);
  font-size: clamp(3rem, 12vw, 6rem);
  line-height: 1;
  color: var(--ink);
}
.not-found-code i { font-size: clamp(1.75rem, 6vw, 3rem); color: var(--accent); }
.not-found h1 { font-size: var(--step-3); margin-bottom: var(--sp-3); }
.not-found p { color: var(--ink-2); max-width: 32rem; margin-inline: auto; }
.not-found .btn-row { justify-content: center; margin-top: var(--sp-6); }

/* ============================================================================
   20. OVERLAYS
   ============================================================================ */
.reading-progress-container {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  height: 2px;
  background: transparent;
  pointer-events: none;
}
.reading-progress-bar {
  height: 100%;
  width: 0;
  background: var(--accent);
  transition: width 0.1s linear;
}

.image-modal {
  position: fixed;
  inset: 0;
  /* Above the floating header dock: at phone widths the close button sits
     under the dock and would otherwise be unclickable. */
  z-index: 1100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-5);
  background: rgba(22, 24, 28, 0.82);
}
.image-modal__figure {
  max-width: min(92vw, 72rem);
  max-height: 90vh;
  margin: 0;
  border: var(--rule-w) solid rgba(255, 255, 255, 0.18);
  background: var(--paper-raised);
  padding: var(--sp-2);
}
.image-modal__figure img { max-height: 78vh; object-fit: contain; margin-inline: auto; }
.image-modal__caption {
  margin: var(--sp-3) 0 var(--sp-1);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-3);
  text-align: center;
}
.image-modal__close {
  position: absolute;
  top: var(--sp-5);
  right: var(--sp-5);
  inline-size: 2.5rem;
  block-size: 2.5rem;
  display: grid;
  place-items: center;
  border: var(--rule-w) solid rgba(255, 255, 255, 0.3);
  background: transparent;
  color: #fff;
  font-size: 1.1rem;
  cursor: pointer;
}
.image-modal__close:hover { background: rgba(255, 255, 255, 0.12); }

/* ============================================================================
   21. MOTION & RESPONSIVE
   ============================================================================ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

@media (max-width: 48rem) {
  :root { --sp-9: 4rem; --sp-10: 5rem; }
  .hero { padding-block: var(--sp-7) var(--sp-6); }
  .contact-form { padding: var(--sp-5); }
}

@media print {
  .site-header, .site-footer, .reading-progress-container, .image-modal { display: none; }
  body { background: #fff; }
  body::before { display: none; }
  a { color: var(--ink); }
}

/* ============================================================================
   22. JOBS PAGE — the public application ledger
   ============================================================================ */

/* --- Hero --------------------------------------------------------------- */
.jobs-hero { padding-block: var(--sp-8) 0; }
.jobs-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(18rem, 0.6fr);
  gap: var(--sp-5) var(--sp-7);
  align-items: start;
}
.jobs-hero__grid .jobs-score {
  width: 100%;
  max-width: 26rem;
  justify-self: end;
}
.jobs-hero__copy { max-width: 56rem; min-width: 0; }
.jobs-hero__copy h1 {
  max-width: 20ch;
  margin-bottom: var(--sp-3);
}
.jobs-hero__copy .lede { max-width: 48rem; }

.jobs-stamp {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  margin: var(--sp-5) 0 0;
  padding: 0.45rem 0.7rem;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.07em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--ink-2);
}
.jobs-stamp__pulse {
  width: 8px;
  height: 8px;
  background: var(--accent);
  flex: none;
  animation: jobs-pulse 2.4s steps(2) infinite;
}
.jobs-stamp__sep { color: var(--ink-4); }
@keyframes jobs-pulse {
  0%, 60% { opacity: 1; }
  61%, 100% { opacity: 0.35; }
}

/* --- Live ledger card ---------------------------------------------------- */
.jobs-score {
  position: relative;
  padding: var(--sp-5);
  border: var(--rule-w) solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  box-shadow: 6px 6px 0 var(--rule-2);
}
.jobs-score::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: 2.5rem;
  height: 4px;
  background: #67c9b9;
}
.jobs-score__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}
.jobs-score__label,
.jobs-score__live {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
  line-height: 1.4;
  text-transform: uppercase;
}
.jobs-score__label { color: rgba(251, 251, 249, 0.6); }
.jobs-score__live {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: #67c9b9;
}
.jobs-score__live i {
  width: 6px;
  height: 6px;
  background: currentColor;
}
.jobs-score__verdict {
  margin: var(--sp-4) 0 var(--sp-3);
  font-family: var(--font-pixel);
  font-size: clamp(1.65rem, 2.7vw, 2.15rem);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: 0.01em;
  color: var(--paper);
}
.jobs-score__verdict span { color: #e0895c; }
.jobs-score__meter {
  display: grid;
  grid-template-columns: repeat(10, minmax(0, 1fr));
  gap: 4px;
  margin-bottom: var(--sp-3);
}
.jobs-score__meter i {
  display: block;
  height: 13px;
  background: rgba(251, 251, 249, 0.14);
}
.jobs-score__meter i.is-on { background: #e0895c; }
.jobs-score__ends {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-3);
  margin: -0.45rem 0 var(--sp-3);
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.08em;
  line-height: 1.4;
  text-transform: uppercase;
  color: rgba(251, 251, 249, 0.5);
}
.jobs-score__rates {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-3);
  margin: 0 0 var(--sp-3);
  padding: var(--sp-3) 0;
  border-top: var(--rule-w) solid rgba(251, 251, 249, 0.14);
  border-bottom: var(--rule-w) solid rgba(251, 251, 249, 0.14);
}
.jobs-score__rate { min-width: 0; margin: 0; }
.jobs-score__rate dt {
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.08em;
  line-height: 1.4;
  text-transform: uppercase;
  color: rgba(251, 251, 249, 0.5);
  white-space: nowrap;
}
.jobs-score__rate dd {
  margin: 0.15rem 0 0;
  font-family: var(--font-pixel);
  font-size: 1.15rem;
  line-height: 1.2;
  color: var(--paper);
}
.jobs-score__rate dd span {
  display: block;
  margin-top: 0.15rem;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.02em;
  line-height: 1.4;
  color: rgba(251, 251, 249, 0.5);
}
.jobs-score__note {
  margin: 0;
  font-size: var(--step--1);
  line-height: 1.55;
  color: rgba(251, 251, 249, 0.64);
}

/* --- Snapshot ticker ---------------------------------------------------- */
.jobs-ticker {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  margin-top: var(--sp-6);
  border: var(--rule-w) solid var(--rule-2);
  border-right: 0;
  border-bottom: 0;
  background: var(--paper-raised);
}
.jobs-ticker__cell {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: var(--sp-4) var(--sp-4) var(--sp-3);
  border-right: var(--rule-w) solid var(--rule-2);
  border-bottom: var(--rule-w) solid var(--rule-2);
}
.jobs-ticker__cell:first-child { background: var(--accent-soft); }
.jobs-ticker__label {
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--ink-3);
}
.jobs-ticker__value {
  font-family: var(--font-pixel);
  font-size: 1.55rem;
  line-height: 1.15;
  color: var(--ink);
}
.jobs-ticker__cell:first-child .jobs-ticker__value { color: var(--accent-deep); }
.jobs-ticker__note {
  font-size: var(--step--1);
  line-height: 1.45;
  color: var(--ink-3);
}

/* --- Shared section furniture ------------------------------------------- */
.jobs-section { padding-block: var(--sp-8); }
.jobs-section-head { margin-bottom: var(--sp-5); }
.jobs-section-head h2 { max-width: 20ch; }
.jobs-section-head p { max-width: 54rem; }

/* --- How it works ------------------------------------------------------- */
.jobs-steps {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: var(--rule-w) solid var(--rule-2);
}
.jobs-steps li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0 var(--sp-4);
  padding: var(--sp-4) var(--sp-6) var(--sp-5) 0;
  border-bottom: var(--rule-w) solid var(--rule-2);
}
.jobs-steps li:nth-child(2n) {
  padding-right: 0;
  padding-left: var(--sp-6);
  border-left: var(--rule-w) solid var(--rule-2);
}
.jobs-steps__num {
  grid-row: 1 / span 2;
  font-family: var(--font-pixel);
  font-size: 0.72rem;
  line-height: 1.7;
  letter-spacing: 0.03em;
  color: var(--accent);
}
.jobs-steps h3 {
  margin: 0 0 var(--sp-2);
  font-size: var(--step-1);
  line-height: 1.25;
}
.jobs-steps p {
  margin: 0;
  font-size: var(--step--1);
  line-height: 1.65;
  color: var(--ink-2);
}
.jobs-portable {
  max-width: 60rem;
  margin: var(--sp-5) 0 0;
  padding-top: var(--sp-4);
  border-top: var(--rule-w) solid var(--rule-2);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  line-height: 1.7;
  color: var(--ink-3);
}

/* --- Guardrails --------------------------------------------------------- */
.jobs-guardrails__list {
  display: grid;
  gap: var(--sp-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.jobs-guardrails__list li {
  padding: var(--sp-3) var(--sp-4);
  border: var(--rule-w) solid var(--rule-2);
  border-left: 3px solid var(--accent);
  background: var(--paper-raised);
  font-size: var(--step--1);
  line-height: 1.65;
  color: var(--ink-2);
}

/* --- Collapsed process notes -------------------------------------------- */
.jobs-disclosure { border-top: var(--rule-w) solid var(--rule-2); }
.jobs-disclosure:last-child { border-bottom: var(--rule-w) solid var(--rule-2); }
.jobs-disclosure > summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem var(--sp-3);
  padding: var(--sp-4) 0;
  cursor: pointer;
  list-style: none;
}
.jobs-disclosure > summary::-webkit-details-marker { display: none; }
.jobs-disclosure > summary::after {
  content: "+";
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--step-1);
  line-height: 1;
  color: var(--accent);
}
.jobs-disclosure[open] > summary::after { content: "\2212"; }
.jobs-disclosure > summary:hover .jobs-disclosure__title { color: var(--accent); }
.jobs-disclosure > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.jobs-disclosure__title {
  font-family: var(--font-pixel);
  font-size: var(--step-1);
  line-height: 1.3;
  color: var(--ink);
}
.jobs-disclosure__body { padding-bottom: var(--sp-6); }

/* --- Sankey panel ------------------------------------------------------- */
.jobs-panel {
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  box-shadow: 5px 5px 0 var(--rule);
}
.jobs-flowbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: var(--rule-w) solid var(--rule);
  background: var(--paper-sunken);
}
.jobs-stages {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  margin: 0;
  padding: 0;
  list-style: none;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.09em;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--ink-2);
}
.jobs-stages li { display: inline-flex; align-items: center; gap: 0.4rem; }
.jobs-stages li + li::before {
  content: "\2192";
  margin-right: 0.15rem;
  color: var(--rule-3);
}
.jobs-stages span { color: var(--ink-4); }
.jobs-flowbar__hint {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}
.jobs-flowbar__hint b { color: var(--ink-4); font-weight: 400; }

.jobs-sankey {
  position: relative;
  background: var(--paper-raised);
}
.jobs-sankey svg {
  display: block;
  width: 100%;
  height: auto;
}
.jobs-sankey svg.is-compact .sankey-label { font-size: 9.5px; stroke-width: 3px; }
.jobs-sankey svg.is-compact .sankey-column { font-size: 8.5px; letter-spacing: 0.1em; }

.sankey-guide {
  stroke: var(--rule);
  stroke-width: 1;
  stroke-dasharray: 2 6;
  pointer-events: none;
}
.sankey-column {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  fill: var(--ink-4);
  pointer-events: none;
}
.sankey-label {
  font-family: var(--font-mono);
  font-size: 11px;
  paint-order: stroke;
  stroke: var(--paper-raised);
  stroke-width: 4px;
  stroke-linejoin: round;
  pointer-events: none;
}
.sankey-label-name { fill: var(--ink-2); font-weight: 500; }
.sankey-label-count { fill: var(--ink-3); }

.sankey-link {
  cursor: pointer;
  fill-opacity: 0.3;
  transition: fill-opacity 0.12s ease;
}
.sankey-link:hover { fill-opacity: 0.66; }
.jobs-sankey.is-hovering .sankey-link { fill-opacity: 0.06; }
.jobs-sankey.is-hovering .sankey-link.is-active { fill-opacity: 0.86; }

.sankey-node {
  cursor: default;
  shape-rendering: crispEdges;
  transition: opacity 0.12s ease;
}
.jobs-sankey.is-hovering .sankey-node { opacity: 0.22; }
.jobs-sankey.is-hovering .sankey-node.is-active { opacity: 1; }
.sankey-node:focus-visible {
  outline: none;
  stroke: var(--accent);
  stroke-width: 2px;
}

.jobs-tooltip {
  position: absolute;
  z-index: 5;
  max-width: 19rem;
  padding: 0.5rem 0.65rem;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  line-height: 1.55;
  white-space: pre-line;
  pointer-events: none;
  box-shadow: 4px 4px 0 rgba(22, 24, 28, 0.14);
}
.jobs-noscript {
  margin: 0;
  padding: var(--sp-5);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-3);
}

/* --- Inspector ---------------------------------------------------------- */
.jobs-inspector {
  padding: var(--sp-5);
  border-top: var(--rule-w) solid var(--rule);
  background: var(--paper-sunken);
}
.jobs-inspector__job {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1.55fr) auto;
  gap: var(--sp-4) var(--sp-6);
  align-items: center;
}
.jobs-inspector__head { min-width: 0; }
.jobs-inspector__eyebrow {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0 0 var(--sp-2);
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.09em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--ink-3);
}
.jobs-inspector__eyebrow::before {
  content: "";
  width: 6px;
  height: 6px;
  background: var(--accent);
  flex: none;
}
.jobs-inspector__role {
  margin: 0 0 var(--sp-1);
  font-size: var(--step-2);
  line-height: 1.25;
}
.jobs-inspector__company {
  margin: 0;
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--ink-2);
}
.jobs-inspector__sep { color: var(--ink-4); }

.jobs-inspector__meta {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-3);
  margin: 0;
}
.jobs-inspector__meta-item { min-width: 0; }
.jobs-inspector__meta-item dt {
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  letter-spacing: 0.09em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--ink-3);
}
.jobs-inspector__meta-item dd {
  margin: 0.2rem 0 0;
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--ink-2);
}
.jobs-inspector__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
}
.jobs-inspector__no-link {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  line-height: 1.5;
  color: var(--ink-3);
}

/* --- Source legend ------------------------------------------------------ */
.jobs-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-top: var(--rule-w) solid var(--rule);
  background: var(--paper-raised);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  line-height: 1.5;
  color: var(--ink-3);
}
.jobs-legend__title {
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-4);
}
.jobs-legend__item { display: inline-flex; align-items: center; gap: 0.42rem; }
.jobs-legend__item i { width: 9px; height: 9px; flex: none; }
.jobs-legend__item b { color: var(--ink-2); font-weight: 500; }

/* --- Ledger ------------------------------------------------------------- */
.jobs-ledger__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(19rem, 0.9fr);
  gap: var(--sp-5) var(--sp-7);
  align-items: end;
  margin-bottom: var(--sp-5);
}
.jobs-ledger__head .section-head { margin-bottom: 0; }
.jobs-ledger__head .section-head h2 { max-width: none; }
.jobs-ledger__head .section-head p { max-width: 40rem; }

.jobs-ledger__tools {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.jobs-search {
  position: relative;
  display: flex;
  align-items: center;
  height: 2.55rem;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
}
.jobs-search:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}
.jobs-search svg {
  width: 15px;
  height: 15px;
  margin-left: 0.7rem;
  fill: none;
  stroke: var(--ink-4);
  stroke-width: 1.5;
  flex: none;
}
.jobs-search input {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0 0.7rem;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  -webkit-appearance: none;
  appearance: none;
}
.jobs-search input:focus { outline: none; }
.jobs-search input::placeholder { color: var(--ink-3); opacity: 1; }

.jobs-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.jobs-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.34rem 0.55rem;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  color: var(--ink-2);
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  line-height: 1.35;
  cursor: pointer;
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.jobs-chip span { color: var(--ink-4); }
.jobs-chip:hover { border-color: var(--rule-3); color: var(--ink); }
.jobs-chip.is-active {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--paper);
}
.jobs-chip.is-active span { color: rgba(251, 251, 249, 0.6); }
.jobs-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.jobs-ledger__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-bottom: var(--sp-2);
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--ink-3);
}
.jobs-ledger__meta p { margin: 0; }
.jobs-ledger__meta strong { color: var(--ink); }

.jobs-table-wrap {
  max-height: 46rem;
  overflow: auto;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
}
.jobs-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--step--1);
}
.jobs-table th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 0.7rem 0.9rem;
  border-bottom: var(--rule-w) solid var(--rule-2);
  background: var(--paper-sunken);
  font-family: var(--font-mono);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-align: left;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}
.jobs-table td {
  padding: 0.62rem 0.9rem;
  border-bottom: var(--rule-w) solid var(--rule);
  vertical-align: top;
}
.jobs-table tbody tr:last-child td { border-bottom: 0; }
.jobs-table tbody tr:hover { background: var(--accent-soft); }
.jobs-table tbody tr[hidden] { display: none; }
.jobs-date {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-3);
  white-space: nowrap;
}
.jobs-company { font-weight: 600; white-space: nowrap; }
.jobs-role { min-width: 16rem; }
.jobs-role a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--rule-2);
  text-underline-offset: 0.15em;
}
.jobs-role a:hover { color: var(--accent); text-decoration-color: var(--accent); }
.jobs-location {
  display: block;
  margin-top: 0.1rem;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  line-height: 1.5;
  color: var(--ink-3);
}
.jobs-source,
.jobs-setup,
.jobs-date {
  font-family: var(--font-mono);
  font-size: var(--step--2);
}
.jobs-source,
.jobs-setup {
  color: var(--ink-2);
  white-space: nowrap;
}
.jobs-status-cell { white-space: nowrap; }

.jobs-status {
  display: inline-flex;
  align-items: center;
  gap: 0.32rem;
  padding: 0.14rem 0.42rem 0.1rem;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  font-family: var(--font-mono);
  font-size: 0.625rem;
  line-height: 1.5;
  letter-spacing: 0.02em;
  color: var(--ink-2);
  white-space: nowrap;
}
.jobs-status::before {
  content: "";
  width: 5px;
  height: 5px;
  background: var(--ink-4);
  flex: none;
}
.jobs-status--screening {
  border-color: var(--accent-line);
  background: var(--accent-soft);
  color: var(--accent-deep);
}
.jobs-status--screening::before { background: var(--accent); }
.jobs-status--interview {
  border-color: rgba(194, 112, 61, 0.4);
  background: #fbf1e9;
  color: #8a4d24;
}
.jobs-status--interview::before { background: #c2703d; }
.jobs-status--offer {
  border-color: rgba(47, 107, 60, 0.4);
  background: #edf5ee;
  color: #2f6b3c;
}
.jobs-status--offer::before { background: #2f6b3c; }
.jobs-status--rejected {
  border-color: rgba(163, 59, 59, 0.35);
  background: #fbf0f0;
  color: #8a3030;
}
.jobs-status--rejected::before { background: #a33b3b; }
.jobs-status--ghosted,
.jobs-status--withdrawn,
.jobs-status--pending {
  border-style: dashed;
  color: var(--ink-3);
}

.jobs-empty {
  margin: 0;
  padding: var(--sp-6) var(--sp-4);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.7;
  text-align: center;
  color: var(--ink-3);
}
.jobs-empty__reset {
  margin-left: 0.35rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}
.jobs-footnote {
  margin: var(--sp-4) 0 0;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  line-height: 1.7;
  color: var(--ink-3);
}
.jobs-footnote code {
  padding: 0.1em 0.3em;
  background: var(--paper-sunken);
  color: var(--ink-2);
}

/* --- Responsive --------------------------------------------------------- */
@media (max-width: 72rem) {
  .jobs-inspector__job {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  }
  .jobs-inspector__actions {
    grid-column: 1 / -1;
  }
}

@media (max-width: 60rem) {
  .jobs-hero { padding-top: var(--sp-7); }
  .jobs-hero__grid { grid-template-columns: minmax(0, 1fr); }
  .jobs-hero__grid .jobs-score { max-width: none; justify-self: stretch; }
  .jobs-hero__copy h1 { max-width: none; }
  .jobs-score { max-width: none; }
  .jobs-ticker { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .jobs-steps { grid-template-columns: minmax(0, 1fr); }
  .jobs-steps li,
  .jobs-steps li:nth-child(2n) {
    padding-right: 0;
    padding-left: 0;
    border-left: 0;
  }
  .jobs-ledger__head { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .jobs-ledger__tools { max-width: 42rem; }
}

@media (max-width: 60rem) {
  .jobs-section { padding-block: var(--sp-7); }
  .jobs-table-wrap {
    max-height: none;
    overflow: visible;
    border: 0;
    background: transparent;
  }
  .jobs-table,
  .jobs-table tbody { display: block; }
  .jobs-table thead { display: none; }
  .jobs-table tbody { display: grid; gap: 0.65rem; }
  .jobs-table tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.35rem 0.75rem;
    padding: 0.9rem 1rem;
    border: var(--rule-w) solid var(--rule-2);
    background: var(--paper-raised);
  }
  .jobs-table tbody tr:hover { background: var(--paper-raised); }
  .jobs-table td {
    display: block;
    padding: 0;
    border: 0;
  }
  .jobs-company {
    order: 1;
    flex: 1 1 auto;
    min-width: 0;
    font-size: var(--step-0);
    line-height: 1.3;
    white-space: normal;
  }
  .jobs-status-cell { order: 2; margin-left: auto; }
  .jobs-role { order: 3; flex: 1 1 100%; min-width: 0; line-height: 1.5; }
  .jobs-date { order: 4; color: var(--ink-3); }
  .jobs-source { order: 5; color: var(--ink-3); }
  .jobs-setup { order: 6; color: var(--ink-3); }
  .jobs-source::before { content: "\00b7  "; color: var(--ink-4); }
  .jobs-setup::before { content: "\00b7  "; color: var(--ink-4); }
  .jobs-location { margin-top: 0.2rem; }
  .jobs-empty { border: var(--rule-w) solid var(--rule-2); background: var(--paper-raised); }
}

@media (max-width: 48rem) {
  .jobs-hero { padding-top: var(--sp-6); }
  .jobs-hero__copy h1 br { display: none; }
  .jobs-stamp { gap: 0.2rem var(--sp-2); font-size: 0.625rem; }
  .jobs-stamp__sep { display: none; }
  .jobs-score { max-width: none; padding: var(--sp-4); box-shadow: 4px 4px 0 var(--rule-2); }
  .jobs-score__verdict { margin-top: var(--sp-4); }
  .jobs-ticker { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .jobs-ticker__cell { padding: var(--sp-3); }
  .jobs-flowbar { align-items: flex-start; }
  .jobs-flowbar__hint { display: none; }
  .jobs-stages {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.3rem 0.9rem;
  }
  .jobs-stages li + li::before { content: none; }
  .jobs-inspector { padding: var(--sp-4); }
  .jobs-inspector__job { grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); }
  .jobs-inspector__actions { grid-column: auto; }
  .jobs-inspector__meta { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3) var(--sp-4); }
  .jobs-inspector__role { font-size: var(--step-1); }
  .jobs-legend { gap: 0.4rem 0.85rem; padding: var(--sp-3); }
  .jobs-legend__title { flex-basis: 100%; }
  .jobs-ledger__tools { max-width: none; }
  .jobs-chips { gap: 0.3rem; }
  .jobs-chip { padding: 0.35rem 0.5rem; }
  .jobs-footnote { line-height: 1.6; }
}

@media (max-width: 24rem) {
  .jobs-ticker { grid-template-columns: minmax(0, 1fr); }
  .jobs-ticker__cell:last-child { grid-column: auto; }
  .jobs-inspector__meta { grid-template-columns: minmax(0, 1fr); }
}

/* ============================================================================
   23. THEME — "paper" by day, "ink" by night
   ----------------------------------------------------------------------------
   The palette never inverts mechanically: the dark theme is its own set of
   tokens, and the handful of surfaces that use fixed dark panels get their own
   overrides below so white-on-dark type stays white-on-dark.

   The transition itself is a View Transition circle grown from the toggle (see
   static/js/theme.js); the fallback is a short crossfade.
   ============================================================================ */
:root {
  /* GitHub's own contribution greens, so the graph reads as a contribution
     graph at a glance instead of blending into the site's teal accent. */
  --heat-0: #ebedf0;
  --heat-1: #9be9a8;
  --heat-2: #40c463;
  --heat-3: #30a14e;
  --heat-4: #216e39;
}

:root[data-theme="dark"] {
  --paper:          #111113;
  --paper-raised:   #18181b;
  --paper-sunken:   #0b0b0d;

  --ink:            #f5f5f7;
  --ink-2:          #c7c7cc;
  --ink-3:          #9a9aa0;
  --ink-4:          #7c7c82;

  --rule:           #26262a;
  --rule-2:         #38383d;
  --rule-3:         #55555c;
  --grid:           rgba(245, 245, 247, 0.06);

  --accent:         #67c9b9;
  --accent-deep:    #8ee8d7;
  --accent-soft:    rgba(103, 201, 185, 0.11);
  --accent-line:    rgba(103, 201, 185, 0.32);

  --px-shadow:      3px 3px 0 #000;
  --px-shadow-ink:  4px 4px 0 rgba(0, 0, 0, 0.72);

  --heat-0: #1b2028;
  --heat-1: #0e4429;
  --heat-2: #006d32;
  --heat-3: #26a641;
  --heat-4: #39d353;
}

:root[data-theme="dark"] .header-inner {
  background: rgba(24, 24, 27, 0.88);
  border-color: var(--rule-2);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.04),
    0 6px 22px rgba(0, 0, 0, 0.42);
}

:root[data-theme="dark"] .weather-display {
  background: #222226;
  border-color: var(--rule-2);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    inset 0 -1px 0 rgba(0, 0, 0, 0.2),
    0 1px 2px rgba(0, 0, 0, 0.35);
}

/* The Codegig mark is yellow on transparent; it always needs a dark tile,
   even when the page itself has turned dark. */
.company-pill img { background: #1d1d1f; }

:root[data-theme="dark"] .card-plate { box-shadow: 2px 2px 0 #000; }
:root[data-theme="dark"] .card--3d .three-container {
  box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.5);
}
:root[data-theme="dark"] .card--3d .three-container canvas {
  filter:
    drop-shadow(0 0 1.5px rgba(0, 0, 0, 0.95))
    drop-shadow(0 0 3px rgba(0, 0, 0, 0.8));
}

/* The live ledger card is white-on-dark by design, so it must stay dark in the
   dark theme; its internals use fixed light ink values. */
:root[data-theme="dark"] .jobs-score {
  background: #1d1d1f;
  color: #fbfbf9;
  border-color: var(--ink);
}
:root[data-theme="dark"] .jobs-score__verdict,
:root[data-theme="dark"] .jobs-score__rate dd { color: #fbfbf9; }

:root[data-theme="dark"] .form-status--error { color: #f2a3a3; }
:root[data-theme="dark"] .jobs-status--interview {
  border-color: rgba(194, 112, 61, 0.5);
  background: rgba(194, 112, 61, 0.14);
  color: #e8aa79;
}
:root[data-theme="dark"] .jobs-status--offer {
  border-color: rgba(91, 176, 108, 0.45);
  background: rgba(91, 176, 108, 0.14);
  color: #9cd6a6;
}
:root[data-theme="dark"] .jobs-status--rejected {
  border-color: rgba(193, 89, 89, 0.45);
  background: rgba(193, 89, 89, 0.14);
  color: #e4a3a3;
}

/* Code highlighting uses a few fixed inks that disappear on dark stock. */
:root[data-theme="dark"] .prose .chroma .nf,
:root[data-theme="dark"] .prose .chroma .fm,
:root[data-theme="dark"] .prose .chroma .nb,
:root[data-theme="dark"] .prose .chroma .bp,
:root[data-theme="dark"] .prose .chroma .nc,
:root[data-theme="dark"] .prose .chroma .nd,
:root[data-theme="dark"] .prose .chroma .nl { color: #7cc4f0; }
:root[data-theme="dark"] .prose .chroma .no,
:root[data-theme="dark"] .prose .chroma .ne { color: #c4a5ff; }
:root[data-theme="dark"] .prose .chroma .m,
:root[data-theme="dark"] .prose .chroma .mb,
:root[data-theme="dark"] .prose .chroma .mf,
:root[data-theme="dark"] .prose .chroma .mh,
:root[data-theme="dark"] .prose .chroma .mi,
:root[data-theme="dark"] .prose .chroma .mo { color: #e0b36d; }
:root[data-theme="dark"] .prose .chroma .s,
:root[data-theme="dark"] .prose .chroma .sa,
:root[data-theme="dark"] .prose .chroma .sb,
:root[data-theme="dark"] .prose .chroma .sc,
:root[data-theme="dark"] .prose .chroma .dl,
:root[data-theme="dark"] .prose .chroma .sd,
:root[data-theme="dark"] .prose .chroma .s2,
:root[data-theme="dark"] .prose .chroma .se,
:root[data-theme="dark"] .prose .chroma .sh,
:root[data-theme="dark"] .prose .chroma .si,
:root[data-theme="dark"] .prose .chroma .sx,
:root[data-theme="dark"] .prose .chroma .s1,
:root[data-theme="dark"] .prose .chroma .ss { color: #9ad8a8; }
:root[data-theme="dark"] .prose .chroma .gd { color: #f2a3a3; background: rgba(185, 28, 28, 0.16); }
:root[data-theme="dark"] .prose .chroma .gi { color: #9ad8a8; background: rgba(21, 128, 61, 0.16); }
:root[data-theme="dark"] .prose .chroma .gh,
:root[data-theme="dark"] .prose .chroma .gu { color: #7cc4f0; }
:root[data-theme="dark"] .prose mark { background: rgba(250, 204, 21, 0.24); color: var(--ink); }

/* ---- Toggle ------------------------------------------------------------- */
.theme-toggle {
  display: grid;
  place-items: center;
  inline-size: 2rem;
  block-size: 2rem;
  padding: 0;
  border: var(--rule-w) solid transparent;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--ink-2);
  cursor: pointer;
  transition: color 0.12s ease, background-color 0.12s ease, border-color 0.12s ease;
}
.theme-toggle:hover,
.theme-toggle:focus-visible {
  color: var(--accent-deep);
  background: var(--accent-soft);
  border-color: var(--accent-line);
}
.theme-toggle__icons {
  position: relative;
  display: block;
  inline-size: 1.05rem;
  block-size: 1.05rem;
}
.theme-toggle__icon {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  transition: opacity 0.2s ease, transform 0.42s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.theme-toggle__icon--moon { opacity: 0; transform: rotate(-90deg) scale(0.4); }
[data-theme="dark"] .theme-toggle__icon--sun { opacity: 0; transform: rotate(90deg) scale(0.4); }
[data-theme="dark"] .theme-toggle__icon--moon { opacity: 1; transform: none; }

/* ---- The circle reveal -------------------------------------------------- */
::view-transition-old(root) {
  animation: none;
  mix-blend-mode: normal;
}
::view-transition-new(root) {
  animation: theme-reveal 0.62s cubic-bezier(0.22, 0.8, 0.3, 1) both;
  mix-blend-mode: normal;
}
@keyframes theme-reveal {
  from { clip-path: circle(0 at var(--theme-x, 50%) var(--theme-y, 0)); }
  to   { clip-path: circle(var(--theme-r, 150vmax) at var(--theme-x, 50%) var(--theme-y, 0)); }
}

html.theme-is-switching,
html.theme-is-switching *,
html.theme-is-switching *::before,
html.theme-is-switching *::after {
  transition:
    background-color 0.34s ease,
    color 0.34s ease,
    border-color 0.34s ease,
    box-shadow 0.34s ease,
    fill 0.34s ease,
    stroke 0.34s ease !important;
}

/* ============================================================================
   24. HOMEPAGE — hero call to action and job band
   ----------------------------------------------------------------------------
   The résumé is the page's primary ask, so it gets the one oversized, filled
   control in the hero. Contact remains available as a quieter outline beside
   it, and the meta line answers the two questions a recruiter asks before
   clicking: how long is it, and how current is it.
   ============================================================================ */
.hero { padding-block-end: clamp(2.5rem, 5vw, 4rem); }

.hero-cta__actions {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: var(--sp-3);
}
.hero-cta__resume {
  display: grid;
  gap: var(--sp-2);
}
.hero-cta__primary,
.hero-cta__secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.65rem;
  min-height: 3.5rem;
  padding: 0.9rem 1.4rem;
  border: var(--rule-w) solid var(--ink);
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  transition: transform 0.08s steps(2), box-shadow 0.08s steps(2),
              background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.hero-cta__primary {
  background: var(--ink);
  color: var(--paper);
  box-shadow: var(--px-shadow);
}
.hero-cta__primary:hover {
  background: var(--accent-deep);
  border-color: var(--accent-deep);
  color: var(--paper);
  box-shadow: 4px 4px 0 var(--rule-2);
  text-decoration: none;
}
.hero-cta__primary:active,
.hero-cta__secondary:active {
  transform: translate(3px, 3px);
  box-shadow: none;
}
.hero-cta__secondary {
  background: var(--paper-raised);
  border-color: var(--rule-2);
  color: var(--ink-2);
}
.hero-cta__secondary:hover {
  border-color: var(--ink);
  color: var(--ink);
  box-shadow: var(--px-shadow);
  text-decoration: none;
}

.hero-cta__arrow {
  display: inline-block;
  font-size: 1.15em;
  line-height: 1;
  transition: transform 0.12s steps(2);
}
.hero-cta__primary:hover .hero-cta__arrow,
.hero-cta__secondary:hover .hero-cta__arrow {
  transform: translateX(3px);
}

.hero-cta__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: var(--sp-2) 0 0;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.hero-cta__meta::before {
  content: "";
  inline-size: 5px;
  block-size: 5px;
  background: var(--accent);
  flex: none;
}

/* Stack the pair on a phone: side by side, the labels would shrink back to
   the small, easy-to-miss controls this CTA replaced. */
@media (max-width: 30rem) {
  .hero-cta__actions {
    flex-direction: column;
    align-items: stretch;
  }
  .hero-cta__primary,
  .hero-cta__secondary { inline-size: 100%; }
}

/* ============================================================================
   25. TECH STACK — pills + native dialog
   ============================================================================ */
.tech { min-width: 0; }
.tech-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
}
.tech-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}
.tech-filter {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.4rem 0.7rem;
  border: var(--rule-w) solid transparent;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--ink-3);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.2;
  cursor: pointer;
  transition: color 0.12s ease, background-color 0.12s ease, border-color 0.12s ease;
}
.tech-filter:hover { color: var(--ink); background: var(--paper-sunken); }
.tech-filter.is-active {
  color: var(--accent-deep);
  background: var(--accent-soft);
  border-color: var(--accent-line);
}
.tech-filter__count {
  padding: 0.02rem 0.3rem;
  border: var(--rule-w) solid var(--rule);
  border-radius: var(--radius-pill);
  background: var(--paper-raised);
  font-size: 0.58rem;
  color: var(--ink-4);
}
.tech-filter.is-active .tech-filter__count {
  border-color: var(--accent-line);
  background: transparent;
  color: var(--accent-deep);
}

.tech-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.55rem;
}
.tech-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.36rem 0.85rem 0.36rem 0.38rem;
  border: var(--rule-w) solid var(--rule-2);
  border-radius: var(--radius-pill);
  background: var(--paper-raised);
  color: var(--ink-2);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.2;
  cursor: pointer;
  transition:
    color 0.12s ease,
    border-color 0.12s ease,
    box-shadow 0.08s steps(2),
    transform 0.08s steps(2);
}
.tech-pill:hover {
  color: var(--ink);
  border-color: var(--ink);
  box-shadow: var(--px-shadow);
  transform: translate(-1px, -1px);
}
.tech-pill:active { transform: translate(1px, 1px); box-shadow: none; }
.tech-pill[hidden] { display: none; }
.tech-pill__icon {
  display: grid;
  place-items: center;
  inline-size: 1.5rem;
  block-size: 1.5rem;
  flex: none;
  border: var(--rule-w) solid var(--rule);
  border-radius: 50%;
  background: #fff;
}
.tech-pill__icon img { inline-size: 0.9rem; block-size: 0.9rem; }
.tech-pill__label { white-space: nowrap; }
.tech-hint {
  margin: var(--sp-5) 0 0;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-4);
}
.tech-noscript {
  margin: var(--sp-4) 0 0;
  font-size: var(--step--1);
  color: var(--ink-2);
}
@media (max-width: 40rem) {
  .tech-toolbar { align-items: flex-start; }
  .tech-filter { padding: 0.35rem 0.55rem; font-size: var(--step--2); }
  .tech-pill { font-size: var(--step--2); }
  .tech-hint { line-height: 1.6; }
}

/* ---- Dialog ------------------------------------------------------------- */
html.skill-modal-open,
html.skill-modal-open body { overflow: hidden; }

.skill-modal {
  inline-size: min(92vw, 44rem);
  max-inline-size: 44rem;
  max-block-size: min(86vh, 48rem);
  margin: auto;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  overflow: visible;
}
.skill-modal::backdrop {
  background: rgba(10, 11, 13, 0.58);
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
  opacity: 0;
  transition: opacity 0.18s ease;
}
.skill-modal.is-open::backdrop { opacity: 1; }
.skill-modal__panel {
  display: flex;
  flex-direction: column;
  max-block-size: min(86vh, 48rem);
  padding: clamp(1.25rem, 3vw, 2rem);
  border: var(--rule-w) solid var(--ink);
  background: var(--paper-raised);
  box-shadow: 8px 8px 0 var(--rule-2);
  opacity: 0;
  transform: translateY(12px) scale(0.985);
  transition: opacity 0.2s ease, transform 0.28s cubic-bezier(0.22, 0.8, 0.3, 1);
}
.skill-modal.is-open .skill-modal__panel { opacity: 1; transform: none; }
.skill-modal.is-closing .skill-modal__panel {
  opacity: 0;
  transform: translateY(8px) scale(0.99);
}
.skill-modal__head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding-bottom: var(--sp-4);
  border-bottom: var(--rule-w) solid var(--rule);
}
.skill-modal__icon {
  display: grid;
  place-items: center;
  inline-size: 3rem;
  block-size: 3rem;
  flex: none;
  border: var(--rule-w) solid var(--ink);
  background: #fff;
  box-shadow: 2px 2px 0 var(--rule-2);
}
.skill-modal__icon img { inline-size: 1.75rem; block-size: 1.75rem; }
.skill-modal__id { flex: 1; min-width: 0; }
.skill-modal__kicker {
  margin: 0 0 0.15rem;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent-deep);
}
.skill-modal__title {
  margin: 0;
  font-size: var(--step-2);
  line-height: 1.18;
}
.skill-modal__close {
  display: grid;
  place-items: center;
  inline-size: 2.25rem;
  block-size: 2.25rem;
  flex: none;
  padding: 0;
  border: var(--rule-w) solid var(--rule-2);
  background: transparent;
  color: var(--ink-3);
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease;
}
.skill-modal__close:hover { color: var(--ink); border-color: var(--ink); }
.skill-modal__body {
  overflow-y: auto;
  padding-top: var(--sp-4);
  overscroll-behavior: contain;
}
.skill-modal__desc {
  margin: 0 0 var(--sp-4);
  font-size: var(--step-1);
  line-height: 1.5;
  color: var(--ink);
}
.skill-modal__details {
  margin: 0;
  font-size: var(--step-0);
  line-height: 1.7;
  color: var(--ink-2);
}
/* Provenance: a small accent-ruled note, distinct from the prose below it. */
.skill-modal__source {
  margin: 0 0 var(--sp-5);
  padding: var(--sp-3) var(--sp-4);
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
}
.skill-modal__source .skill-modal__label {
  margin-bottom: var(--sp-2);
  color: var(--accent-deep);
}
.skill-modal__source-text {
  margin: 0;
  font-size: var(--step-0);
  line-height: 1.65;
  color: var(--ink-2);
}
/* The used-in block owns the only divider inside the body; About flows as
   ordinary prose, with no second rule above or below it. */
.skill-modal__about { margin: 0 0 var(--sp-4); }
.skill-modal__about .skill-modal__label { margin-bottom: var(--sp-2); }
.skill-modal__used {
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: var(--rule-w) solid var(--rule);
}
.skill-modal__label {
  margin: 0 0 var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.skill-modal__projects {
  display: grid;
  gap: var(--sp-2);
  list-style: none;
  margin: 0;
  padding: 0;
}
.skill-modal__projects a {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.1rem 0.75rem;
  padding: 0.65rem 0.8rem;
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper);
  color: var(--ink);
  transition: border-color 0.12s ease, box-shadow 0.08s steps(2);
}
.skill-modal__projects a:hover {
  border-color: var(--ink);
  box-shadow: var(--px-shadow);
  text-decoration: none;
}
.skill-modal__project-title { font-weight: 600; font-size: var(--step--1); }
.skill-modal__project-summary {
  display: -webkit-box;
  grid-column: 1;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  color: var(--ink-3);
  font-size: var(--step--2);
  line-height: 1.5;
}
.skill-modal__project-arrow {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  color: var(--ink-4);
}
.skill-modal__project-empty {
  color: var(--ink-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
}
@media (max-width: 40rem) {
  .skill-modal { inline-size: calc(100vw - 2rem); }
  .skill-modal__panel { padding: var(--sp-4); box-shadow: 5px 5px 0 var(--rule-2); }
  .skill-modal__title { font-size: var(--step-1); }
}

/* ============================================================================
   26. GITHUB ACTIVITY
   ============================================================================ */
.activity { min-width: 0; }
.activity-graph {
  --heat-gap: clamp(1px, 0.35vw, 3px);
  display: block;
  padding: var(--sp-4);
  border: var(--rule-w) solid var(--rule-2);
  background: var(--paper-raised);
  color: var(--ink);
  cursor: pointer;
  transition: border-color 0.12s ease, box-shadow 0.08s steps(2);
}
.activity-graph:hover {
  border-color: var(--ink);
  box-shadow: var(--px-shadow);
  text-decoration: none;
}
.activity-head,
.activity-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.activity-head { margin-bottom: var(--sp-3); }
.activity-open { color: var(--accent-deep); }
.activity-graph:hover .activity-open { text-decoration: underline; }
/* Each week is one column of seven days. Flex lets the columns share the full
   width on desktop and wrap into two full-year rows on a phone. */
.heatmap {
  display: flex;
  align-items: stretch;
  gap: var(--heat-gap);
  padding-block-start: 1.15rem;
  min-block-size: 6rem;
}
.heat-week {
  position: relative;
  display: grid;
  flex: 1 1 0;
  grid-template-rows: repeat(7, auto);
  gap: var(--heat-gap);
  min-inline-size: 0;
}
.heat-week__month {
  position: absolute;
  inset-block-end: calc(100% + 0.35rem);
  inset-inline-start: 0;
  font-family: var(--font-mono);
  font-size: 0.56rem;
  line-height: 1;
  color: var(--ink-4);
  white-space: nowrap;
}
.heat-cell {
  display: block;
  inline-size: 100%;
  aspect-ratio: 1;
  border-radius: 2px;
  background: var(--heat-0);
  outline: 1px solid transparent;
  outline-offset: 1px;
  transition: outline-color 0.1s ease, background-color 0.1s ease;
}
.heat-cell[data-level="1"] { background: var(--heat-1); }
.heat-cell[data-level="2"] { background: var(--heat-2); }
.heat-cell[data-level="3"] { background: var(--heat-3); }
.heat-cell[data-level="4"] { background: var(--heat-4); }
.heat-cell--pad { background: transparent; }
.heat-cell:hover { outline-color: var(--ink); }
.heatmap-skeleton {
  display: block;
  flex: 1 1 100%;
  min-block-size: 6rem;
  background:
    linear-gradient(90deg, transparent, var(--paper-sunken) 45%, transparent 60%)
    0 0 / 200% 100% no-repeat,
    var(--heat-0);
  animation: heat-shimmer 1.3s linear infinite;
}
@keyframes heat-shimmer {
  to { background-position: -200% 0, 0 0; }
}
.heatmap-fallback {
  display: grid;
  flex: 1 1 100%;
  place-items: center;
  min-block-size: 6rem;
  padding: var(--sp-4);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  line-height: 1.6;
  color: var(--ink-3);
  text-align: center;
}
.activity-foot { margin-top: var(--sp-3); }
.activity-total strong { color: var(--ink); font-weight: 600; }
.activity-key { display: inline-flex; align-items: center; gap: 0.35rem; }
.activity-key__cells { display: inline-flex; gap: 3px; }
.activity-key__cells i {
  inline-size: 0.55rem;
  block-size: 0.55rem;
  border-radius: 2px;
  background: var(--heat-0);
}
.activity-key__cells i[data-level="1"] { background: var(--heat-1); }
.activity-key__cells i[data-level="2"] { background: var(--heat-2); }
.activity-key__cells i[data-level="3"] { background: var(--heat-3); }
.activity-key__cells i[data-level="4"] { background: var(--heat-4); }
.activity-note {
  min-block-size: 1.1em;
  margin: var(--sp-2) 0 0;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--ink-3);
}
/* Phones: 27 week columns per row, so the full year sits in two rows with no
   horizontal scrolling. Desktop keeps all 53 weeks on a single line. */
@media (max-width: 40rem) {
  .activity-graph { --heat-gap: 2px; padding: var(--sp-3); }
  .activity-head { align-items: flex-start; flex-direction: column; gap: 0.25rem; }
  .activity-foot { align-items: flex-start; flex-direction: column; gap: 0.5rem; }
  .heatmap {
    flex-wrap: wrap;
    row-gap: 1.7rem;
    padding-block-start: 1.2rem;
    min-block-size: 0;
  }
  .heat-week {
    /* 26 gaps of 2px plus 1px of rounding slack, divided across 27 columns. */
    flex: 0 0 calc((100% - 53px) / 27);
  }
  .heatmap-skeleton, .heatmap-fallback { flex: 1 1 100%; min-block-size: 4.5rem; }
}

/* ============================================================================
   27. FOOTER WORDMARK
   ----------------------------------------------------------------------------
   The name is set large, centred, and clipped by the bottom edge. Height is
   tied to the font size so the same proportion of the letters stays visible at
   every width; on a phone the top of every glyph is still legible.
   ============================================================================ */
.site-footer { overflow: hidden; }
.footer-brand {
  /* 42.6em is the art's measured width (71 monospace cells x 0.6em). The font
     size can grow with the viewport but stops at 1.2rem, so on a wide screen
     the wordmark stays a considered footer mark instead of a billboard. 4.8em
     of the six-line art stays visible; the rest is clipped by the page edge. */
  --ascii-size: min(1.2rem, calc((100vw - 2rem) / 42.6));
  display: flex;
  justify-content: center;
  align-items: flex-start;
  block-size: 4.8em;
  margin-top: clamp(2.5rem, 6vw, 4.5rem);
  overflow: hidden;
  font-size: var(--ascii-size);
  line-height: 1;
  user-select: none;
}
.footer-brand__stack { font-size: inherit; }
.footer-brand .ascii-name__layer { font-size: inherit; }

@media (max-width: 48rem) {
  .footer-brand { margin-top: var(--sp-6); }
}

/* ============================================================================
   28. EMBED BAR ACTION
   ============================================================================ */
.embed-panel-open {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  white-space: nowrap;
}
.embed-panel-open:hover { color: var(--ink); text-decoration: none; }
