/* ============================================================
   Kia Hughes Portfolio
   Monotone, structured after nickchubbdesign.com: home = work
   grid, About/Contact are separate pages, no color accent.
   ============================================================ */
@import url('https://fonts.googleapis.com/css2?family=Anton&family=Archivo:wght@500;600;700;800&family=Space+Grotesk:wght@400;500;600;700&display=swap');

:root {
  --color-bg: #FAFAF9;
  --color-surface: #FFFFFF;
  --color-ink: #16171A;
  --color-ink-soft: #55585F;
  --color-border: #E4E3DF;
  --color-border-strong: #C9C8C2;
  --font-display: 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  --font-body: 'Space Grotesk', 'Helvetica Neue', Arial, sans-serif;
  --font-logo: 'Anton', 'Archivo', sans-serif;
  --space-3xs: 0.25rem;
  --space-2xs: 0.5rem;
  --space-xs: 0.75rem;
  --space-sm: 1rem;
  --space-md: 1.5rem;
  --space-lg: 2.5rem;
  --space-xl: 4rem;
  --space-2xl: 6rem;
  --space-3xl: 8rem;
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --shadow-sm: 0 1px 2px rgba(20, 20, 18, 0.06);
  --shadow-md: 0 8px 24px rgba(20, 20, 18, 0.08);
  --shadow-lg: 0 20px 48px rgba(20, 20, 18, 0.14);
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --container: 1360px;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  /* Clip stray sub-pixel horizontal overflow without creating a scroll
     container (so position: sticky keeps working). */
  overflow-x: clip;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* Page transition veil: a paper-colored overlay that fades off on load and
   back on before an internal navigation (leave class set in script.js), for
   a seamless crossfade between pages. Invisible (and inert) under reduced
   motion, and with no JS the CSS intro still clears it. */
.page-fade {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--color-bg);
  pointer-events: none;
  opacity: 0;
}

@media (prefers-reduced-motion: no-preference) {
  .page-fade {
    animation: nk-page-intro 500ms var(--ease) both;
  }

  .page-fade.is-leaving {
    opacity: 1;
    transition: opacity 260ms var(--ease);
    animation: none;
  }
}

@keyframes nk-page-intro {
  from { opacity: 1; }
  to { opacity: 0; }
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

a {
  color: inherit;
  text-decoration: none;
}

.link-underline {
  text-underline-offset: 3px;
  text-decoration: underline;
  text-decoration-color: transparent;
  transition: text-decoration-color 200ms var(--ease);
}

.link-underline:hover,
.link-underline:focus-visible {
  text-decoration-color: currentColor;
}

:focus-visible {
  outline: 2px solid var(--color-ink);
  outline-offset: 3px;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin: 0;
}

p {
  margin: 0;
}

.eyebrow {
  /* inline-block (not inline-flex): on iOS Safari, letter-spacing on an
     inline-flex box clips the leading characters (showed "ERVIEW" for
     "OVERVIEW"). inline-block renders the letter-spacing correctly. */
  display: inline-block;
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
}

.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  list-style: none;
  margin: 0;
  padding: 0;
}

.tag {
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  padding: 0.35rem 0.7rem;
  border: 1px solid var(--color-border-strong);
  border-radius: 999px;
  color: var(--color-ink-soft);
  white-space: nowrap;
}

.container {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 clamp(1.25rem, 3vw, 2.5rem);
}

/* Small circled arrow link, used for "Let's talk" style affordances */
.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: 0.95rem;
  font-weight: 500;
}

.arrow-link__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid var(--color-border-strong);
  transition: background 200ms var(--ease), border-color 200ms var(--ease), color 200ms var(--ease), transform 200ms var(--ease);
  flex-shrink: 0;
}

.arrow-link__icon svg {
  width: 12px;
  height: 12px;
}

.arrow-link:hover .arrow-link__icon {
  background: var(--color-ink);
  border-color: var(--color-ink);
  color: var(--color-bg);
  transform: translateX(2px);
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  padding: 0.85rem 1.5rem;
  border-radius: 999px;
  cursor: pointer;
  border: 1px solid transparent;
  transition: transform 200ms var(--ease), background 200ms var(--ease), color 200ms var(--ease), border-color 200ms var(--ease);
}

.btn svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.btn:hover {
  transform: translateY(-2px);
}

.btn--primary {
  background: var(--color-ink);
  color: var(--color-bg);
  border-color: var(--color-ink);
}

.btn--primary:hover {
  background: var(--color-ink-soft);
  border-color: var(--color-ink-soft);
}

.btn--outline {
  background: transparent;
  border-color: var(--color-border-strong);
  color: var(--color-ink);
}

.btn--outline:hover {
  border-color: var(--color-ink);
}

.btn--on-dark {
  background: #F4F3F0;
  color: #111214;
  border-color: #F4F3F0;
}

.btn--on-dark:hover {
  background: #fff;
  border-color: #fff;
}

.btn--ghost-dark {
  background: transparent;
  border-color: rgba(244, 243, 240, 0.35);
  color: #F4F3F0;
}

.btn--ghost-dark:hover {
  border-color: #F4F3F0;
}

/* ---------- Reveal on scroll ---------- */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 600ms var(--ease), transform 600ms var(--ease);
}

.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
  }
}

/* ============================================================
   Header / Nav
   ============================================================ */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  background: var(--color-bg);
  border-bottom: 1px solid transparent;
  transition: background 400ms var(--ease), border-color 400ms var(--ease), box-shadow 400ms var(--ease);
}

/* Once scrolled, the bar becomes frosted glass: translucent paper + blur,
   so the page content shows through softly behind it. */
.site-header.is-scrolled {
  background: rgba(250, 250, 249, 0.72);
  -webkit-backdrop-filter: blur(16px) saturate(1.5);
  backdrop-filter: blur(16px) saturate(1.5);
  border-color: var(--color-border);
  box-shadow: var(--shadow-sm);
}

/* Browsers without backdrop-filter get a near-opaque fallback so text stays legible. */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .site-header.is-scrolled {
    background: rgba(250, 250, 249, 0.96);
  }
}

.site-header__inner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding-top: clamp(2.6rem, 6vw, 3.75rem);
  padding-bottom: 1.75rem;
  transition: padding 400ms var(--ease);
}

.site-header.is-shrunk .site-header__inner {
  padding-top: 0.65rem;
  padding-bottom: 0.65rem;
}

.brand {
  display: flex;
  flex-direction: column;
  gap: 0.2em;
  line-height: 1;
  font-size: 1.6rem;
  transition: font-size 400ms var(--ease);
}

.site-header.is-shrunk .brand {
  font-size: 0.82rem;
}

.brand__name {
  font-family: var(--font-logo);
  font-size: 2.56em;
  font-weight: 400;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--color-ink);
}

.brand__title {
  font-family: var(--font-body);
  font-size: 0.62em;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
}

/* On mobile, always use the compact ("shrunk") header: skip the tall landing
   version entirely so it opens already pulled-up. */
@media (max-width: 860px) {
  .site-header__inner {
    padding-top: 0.65rem;
    padding-bottom: 0.65rem;
  }

  .brand {
    font-size: 0.82rem;
  }
}

.nav {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  margin-left: auto;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 1rem;
  font-weight: 500;
}

.nav__links a {
  position: relative;
  padding: 0.25rem 0;
}

.nav__links a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 100%;
  bottom: -2px;
  height: 1px;
  background: var(--color-ink);
  transition: right 250ms var(--ease);
}

.nav__links a:hover::after,
.nav__links a:focus-visible::after,
.nav__links a[aria-current="page"]::after {
  right: 0;
}

/* The current page's underline rests at half strength so hover still reads. */
.nav__links a[aria-current="page"]::after {
  background: var(--color-ink-soft);
}

.nav__links a[aria-current="page"]:hover::after {
  background: var(--color-ink);
}

.nav__social {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--color-border-strong);
  transition: background 200ms var(--ease), border-color 200ms var(--ease), color 200ms var(--ease);
}

.nav__social:hover {
  background: var(--color-ink);
  border-color: var(--color-ink);
  color: var(--color-bg);
}

.nav__social-icons {
  width: 16px;
  height: 16px;
  overflow: hidden;
  position: relative;
}

.nav__social-icons svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  transition: transform 260ms var(--ease);
}

.nav__social-icons svg:last-child {
  top: 16px;
}

.nav__social:hover .nav__social-icons svg {
  transform: translateY(-16px);
}

.nav-toggle {
  display: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--color-border-strong);
  background: transparent;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  /* Black icon everywhere (the SVG strokes use currentColor); without this it
     inherited the teal accent on the project page. */
  color: var(--color-ink);
}

.nav-toggle svg {
  width: 18px;
  height: 18px;
}

/* ============================================================
   Header spacer: reserves room under the fixed, shrinking header.
   Its height is synced to the real header height in script.js.
   ============================================================ */
.header-spacer {
  height: clamp(9.5rem, 20vw, 12.5rem);
}

/* ============================================================
   Section scaffolding
   ============================================================ */
section {
  padding: var(--space-2xl) 0;
}

/* Work grid leads the home page now, so it sits close under the header. */
.work {
  padding-top: var(--space-md);
}

.section-head {
  margin-bottom: var(--space-lg);
}

.section-head h2 {
  font-size: clamp(1.6rem, 2.6vw, 2.1rem);
}

/* ============================================================
   Work grid
   ============================================================ */
/* Two-column showcase grid tuned for 4 projects: a staggered 2x2 brick
   where each column holds one short + one tall tile (offset between the
   columns) so the tops and bottoms align while the middle staggers.
   Explicit row lines keep it gap-free at exactly this count. */
.work-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: 190px;
  gap: var(--space-sm);
}

.project-card {
  position: relative;
  display: block;
  border-radius: 6px;
  overflow: hidden;
  background: #EFEEEA;
  border: 1px solid var(--color-border);
  cursor: pointer;
  transition: box-shadow 280ms var(--ease), border-color 280ms var(--ease);
}

.project-card:nth-child(1) {
  grid-column: 1;
  grid-row: 1 / 3;
}

.project-card:nth-child(2) {
  grid-column: 2;
  grid-row: 1 / 4;
}

.project-card:nth-child(3) {
  grid-column: 1;
  grid-row: 3 / 6;
}

.project-card:nth-child(4) {
  grid-column: 2;
  grid-row: 4 / 6;
}

.project-card:hover {
  box-shadow: var(--shadow-lg);
  border-color: var(--color-border-strong);
}

.project-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1) translateZ(0);
  backface-visibility: hidden;
  will-change: transform;
  transition: transform 1250ms cubic-bezier(0.16, 1, 0.3, 1);
}

.project-card:hover img {
  transform: scale(1.08) translateZ(0);
}

/* Rest-state dark gradient, for title legibility on the raw photo. Fades
   out on hover instead of changing shape/color, so it's a cheap opacity
   transition rather than an animated gradient. */
.project-card__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, rgba(0, 0, 0, 0.65) 0%, rgba(0, 0, 0, 0.15) 45%, transparent 70%);
  opacity: 1;
  will-change: opacity;
  transform: translateZ(0);
  transition: opacity 1300ms var(--ease);
  pointer-events: none;
}

.project-card:hover .project-card__scrim {
  opacity: 0;
}

/* Frosted-glass layer: the backdrop-filter VALUE never changes (that's what
   caused the jank/jitter, since the browser has to recompute the blur
   every frame while it's animating). Instead it's always at full strength
   and we only crossfade its opacity in, which is nearly free for the GPU.
   Real element (not a pseudo-element) so it's guaranteed to paint above
   the \<img>, rather than relying on pseudo-element paint-order rules. */
.project-card__frost {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(165deg, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0.34) 40%, rgba(255, 255, 255, 0.24) 100%);
  backdrop-filter: blur(22px) saturate(1.5);
  -webkit-backdrop-filter: blur(22px) saturate(1.5);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5), inset 0 1px 30px rgba(255, 255, 255, 0.3);
  opacity: 0;
  will-change: opacity;
  transition: opacity 1300ms var(--ease);
  pointer-events: none;
}

.project-card:hover .project-card__frost {
  opacity: 1;
}

/* Etched-glass grain, only visible once the frost kicks in */
.project-card:not(.project-card--placeholder)::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch' result='t'/%3E%3CfeColorMatrix in='t' type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 220px 220px;
  mix-blend-mode: overlay;
  opacity: 0;
  transition: opacity 1300ms var(--ease);
}

.project-card:not(.project-card--placeholder):hover::after {
  opacity: 0.08;
}

.project-card__text {
  position: absolute;
  left: var(--space-lg);
  right: var(--space-lg);
  bottom: var(--space-lg);
  z-index: 1;
}

/* Cards with a description reserve a fixed-size box up front and clip it,
   then slide the real content within via transform only. No property that
   affects layout ever animates, so this is pure compositor work (buttery
   smooth) instead of forcing a reflow every frame. Relies on descriptions
   staying roughly the same length (\~3 lines at this card width). */
.project-card__text--reveal {
  height: 7rem;
  overflow: hidden;
}

.project-card__text-inner {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  transform: translateY(5rem) translateZ(0);
  backface-visibility: hidden;
  will-change: transform;
  transition: transform 1300ms var(--ease);
}

.project-card:hover .project-card__text-inner {
  transform: translateY(0) translateZ(0);
}

.project-card__title {
  font-family: var(--font-body);
  font-size: clamp(1.3rem, 1.9vw, 1.65rem);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  color: #fff;
  transition: color 150ms ease;
}

.project-card:not(.project-card--placeholder):hover .project-card__title {
  color: var(--color-ink);
}

.project-card--placeholder .project-card__title {
  color: var(--color-ink);
}

.project-card__desc {
  display: block;
  opacity: 0;
  font-family: var(--font-body);
  font-size: 0.92rem;
  font-weight: 400;
  line-height: 1.45;
  color: var(--color-ink);
  transition: opacity 1300ms var(--ease);
}

.project-card:hover .project-card__desc {
  opacity: 1;
}

.project-card--placeholder {
  background: #EFEEEA;
  transition: background 250ms var(--ease);
}

.project-card--placeholder:hover {
  background: #E4E3DD;
}

/* Designed placeholder: a faint dot grid, a large ghosted project number,
   and a dashed "coming soon" chip, so the empty slots read as intentional
   on-brand holding cards rather than blank boxes. Fully monotone. */
.project-card__ph-grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(17, 18, 20, 0.08) 1px, transparent 1.5px);
  background-size: 22px 22px;
  background-position: center;
  -webkit-mask-image: radial-gradient(120% 100% at 50% 0%, #000 45%, transparent 100%);
  mask-image: radial-gradient(120% 100% at 50% 0%, #000 45%, transparent 100%);
  opacity: 0.9;
}

.project-card__ph-num {
  position: absolute;
  z-index: 0;
  top: 44%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-family: var(--font-logo);
  font-weight: 400;
  font-size: clamp(4rem, 11vw, 8.5rem);
  line-height: 1;
  letter-spacing: 0.02em;
  color: rgba(17, 18, 20, 0.09);
  pointer-events: none;
  transition: color 320ms var(--ease), transform 520ms var(--ease);
}

.project-card--placeholder:hover .project-card__ph-num {
  color: rgba(17, 18, 20, 0.14);
  transform: translate(-50%, -54%);
}

.project-card__ph-status {
  position: absolute;
  z-index: 2;
  top: var(--space-md);
  left: var(--space-md);
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.4em 0.75em;
  font-family: var(--font-body);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
  border: 1px dashed var(--color-border-strong);
  border-radius: 100px;
  background: rgba(250, 250, 249, 0.4);
}

.project-card__ph-status::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-ink-soft);
  opacity: 0.7;
}

/* ============================================================
   Generic page content (About / Contact)
   ============================================================ */
.page-hero {
  padding: var(--space-xl) 0 0;
}

.page-hero h1 {
  font-size: clamp(2rem, 4vw, 3rem);
}

.about-hero {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-xl);
  flex-wrap: wrap;
}

.about-hero__text {
  flex: 1;
  min-width: 260px;
}

.about-hero__photo {
  width: 220px;
  height: 220px;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
}

.about-hero__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.about-hero__contact {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  list-style: none;
  margin: 0;
  margin-left: calc(var(--space-xl) * -1 + var(--space-sm));
  padding: 0;
}

.about-hero__contact-item {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: 0.92rem;
  color: var(--color-ink);
  white-space: nowrap;
}

.about-hero__contact-item:nth-child(2) {
  margin-left: 9px;
}

.about-hero__contact-icon {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--color-ink);
  color: var(--color-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.about-hero__contact-icon svg {
  width: 15px;
  height: 15px;
}

.about__grid {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: var(--space-2xl);
  align-items: start;
}

.about__bio {
  font-size: 1.1rem;
  color: var(--color-ink-soft);
  line-height: 1.7;
}

.about__bio strong {
  color: var(--color-ink);
  font-weight: 600;
}

.about__bio+.about__bio {
  margin-top: var(--space-md);
}

.about__actions {
  margin-top: var(--space-lg);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

.about__side {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto auto;
  gap: var(--space-lg) var(--space-xl);
}

.info-block--education {
  grid-column: 1;
  grid-row: 1;
}

.about__side .about__tools {
  grid-column: 1;
  grid-row: 2;
}

.info-block--skills {
  grid-column: 2;
  grid-row: 1;
}

.info-block--fabrication {
  grid-column: 2;
  grid-row: 2;
}

.info-block h3 {
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
  margin-bottom: var(--space-sm);
}

.edu-item {
  padding: var(--space-sm) 0;
  border-top: 1px solid var(--color-border);
}

.edu-item:first-of-type {
  border-top: none;
  padding-top: 0;
}

.edu-item__school {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.98rem;
}

.edu-item__degree {
  font-size: 0.88rem;
  color: var(--color-ink-soft);
  margin-top: 0.15rem;
}

.edu-item__date {
  font-size: 0.76rem;
  color: var(--color-ink-soft);
  margin-top: 0.3rem;
  letter-spacing: 0.04em;
}

.about__tools h3 {
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
  margin-bottom: var(--space-md);
}

.tool-icons {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-md) var(--space-sm);
  list-style: none;
  margin: 0;
  padding: 0;
}

.tool-icon {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3xs);
}

.tool-icon__badge {
  width: 48px;
  height: 48px;
  margin: 0 auto;
  border-radius: 13px;
  overflow: hidden;
  display: block;
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}

.tool-icon__badge img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.tool-icon:hover .tool-icon__badge {
  transform: translateY(-3px) scale(1.05);
  box-shadow: var(--shadow-md);
}

.tool-icon__label {
  font-size: 0.75rem;
  color: var(--color-ink-soft);
  text-align: center;
  line-height: 1.3;
  transition: color 0.2s var(--ease);
}

.tool-icon:hover .tool-icon__label {
  color: var(--color-ink);
}

/* ============================================================
   About page flourishes (paired with about.js): kinetic headline,
   at-a-glance stat strip, and interactive hover polish. Monotone.
   ============================================================ */
/* Kinetic headline: each word rises into place on load. The title is
   held hidden only while JS is present (.about-js), so a no-JS or
   reduced-motion visitor still sees it immediately. */
.about-js .about-hero__title {
  opacity: 0;
}

.about-hero__title.is-split {
  opacity: 1;
}

.about-hero__title .word {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
}

.about-hero__title .word__inner {
  display: inline-block;
  transform: translateY(108%);
  opacity: 0;
  transition: transform 0.72s var(--ease), opacity 0.72s var(--ease);
}

.about-hero__title.is-ready .word__inner {
  transform: translateY(0);
  opacity: 1;
}

/* Headshot: lifts and the portrait eases in closer on hover. */
.about-hero__photo {
  transition: box-shadow 0.4s var(--ease), transform 0.4s var(--ease);
}

.about-hero__photo img {
  transition: transform 0.6s var(--ease);
}

.about-hero__photo:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

.about-hero__photo:hover img {
  transform: scale(1.06);
}

/* Skill / fabrication tags: outline darkens and lifts on hover. */
.info-block .tag {
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease), transform 0.2s var(--ease);
}

.info-block .tag:hover {
  border-color: var(--color-ink);
  color: var(--color-ink);
  transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {

  .about-js .about-hero__title,
  .about-hero__title .word__inner {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ---------- Contact (section on home page) ---------- */
.contact {
  border-top: 1px solid var(--color-border);
  text-align: center;
}

.contact__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.contact .eyebrow {
  justify-content: center;
}

.contact h2 {
  margin-top: var(--space-sm);
  font-size: clamp(1.8rem, 4vw, 2.8rem);
  max-width: 20ch;
}

.contact-block h1 {
  max-width: 18ch;
}

.contact__sub {
  margin-top: var(--space-md);
  max-width: 46ch;
  color: var(--color-ink-soft);
  font-size: 1.05rem;
}

.contact__actions {
  margin-top: var(--space-lg);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-sm);
}

/* ============================================================
   Sticky-reveal contact footer (home page)
   ============================================================ */
:root {
  --reveal-footer-h: 390px;
}

.page-shell {
  position: relative;
  z-index: 1;
  background: var(--color-bg);
  margin-bottom: var(--reveal-footer-h);
}

.reveal-footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: var(--reveal-footer-h);
  z-index: 0;
  overflow: hidden;
  display: flex;
  align-items: stretch;
  color: #F4F3F0;
}

/* Dynamic black: layered radials give the panel depth and a soft top glow
   instead of the flat grid. Neutral on the core pages; the Nek.io page
   tints the glow with its teal accent (override below). */
.reveal-footer__bg {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(125% 85% at 50% -15%, #24262c 0%, rgba(36, 38, 44, 0) 55%),
    radial-gradient(100% 120% at 50% 118%, #050507 0%, rgba(5, 5, 7, 0) 60%),
    #0d0e10;
}

.project-nekio .reveal-footer__bg {
  background:
    radial-gradient(125% 92% at 50% -16%, rgba(47, 198, 219, 0.18) 0%, rgba(47, 198, 219, 0) 54%),
    radial-gradient(120% 85% at 50% -12%, #1b2a30 0%, rgba(27, 42, 48, 0) 60%),
    radial-gradient(100% 120% at 50% 118%, #04080a 0%, rgba(4, 8, 10, 0) 60%),
    #0b0e10;
}

.reveal-footer__scrim {
  position: absolute;
  inset: 0;
  background: radial-gradient(60% 90% at 50% 40%, rgba(14, 15, 17, 0.35), rgba(14, 15, 17, 0.85));
}

/* Cursor glow that tracks the pointer across the contact panel (coords set in
   script.js). Nek.io page only; the core pages keep a flat footer. */
.project-nekio .reveal-footer::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(440px circle at var(--fmx, 50%) var(--fmy, 50%), rgba(47, 198, 219, 0.14), transparent 60%);
  opacity: 0;
  transition: opacity 320ms var(--ease);
}

.project-nekio .reveal-footer.is-hot::after {
  opacity: 1;
}

.reveal-footer__inner {
  position: relative;
  z-index: 1;
  width: 100%;
  text-align: center;
  display: grid;
  grid-template-rows: 1fr auto;
  justify-items: center;
  padding-bottom: var(--space-md);
}

.reveal-footer__main {
  align-self: center;
}

.reveal-footer__heading {
  font-family: var(--font-logo);
  font-size: clamp(2rem, 3.6vw, 2.6rem);
  font-weight: 400;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: #fff;
}

.reveal-footer__line {
  margin-top: var(--space-2xs);
  font-size: 1.05rem;
  color: #D6D6D3;
  transition: color 200ms var(--ease);
}

.reveal-footer__line:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.reveal-footer__line:first-of-type {
  margin-top: var(--space-sm);
}

.reveal-footer__icons {
  margin-top: var(--space-md);
  display: flex;
  justify-content: center;
  gap: var(--space-md);
}

.reveal-footer__icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  border: 1px solid rgba(244, 243, 240, 0.3);
  color: #D6D6D3;
  transition: background 200ms var(--ease), border-color 200ms var(--ease), color 200ms var(--ease);
}

.reveal-footer__icon-btn svg {
  width: 24px;
  height: 24px;
}

.reveal-footer__icon-btn:hover {
  background: #F4F3F0;
  border-color: #F4F3F0;
  color: #111214;
}

.reveal-footer__copyright {
  margin-top: var(--space-md);
  font-size: 0.78rem;
  color: #7D7E80;
}

/* ============================================================
   Footer
   ============================================================ */
.site-footer {
  border-top: 1px solid var(--color-border);
  color: var(--color-ink-soft);
  padding: var(--space-md) 0;
}

.site-footer__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-sm);
  font-size: 0.82rem;
}

.site-footer__links {
  display: flex;
  gap: var(--space-md);
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-footer a:hover {
  color: var(--color-ink);
}

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 640px) {
  :root {
    --reveal-footer-h: 540px;
  }
}

@media (max-width: 860px) {
  .nav__links {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    background: var(--color-bg);
    border-bottom: 1px solid var(--color-border);
    padding: var(--space-sm) var(--space-md) var(--space-md);
  }

  .nav__links.is-open {
    display: flex;
  }

  .nav__links a {
    padding: var(--space-xs) 0;
    width: 100%;
  }

  .nav-toggle {
    display: inline-flex;
  }

  .nav-toggle[aria-expanded="true"] .icon-menu {
    display: none;
  }

  .nav-toggle:not([aria-expanded="true"]) .icon-close {
    display: none;
  }

  .about__grid {
    grid-template-columns: 1fr;
    gap: var(--space-md);
  }

  .about__side {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
  }

  .info-block--education,
  .info-block--skills,
  .info-block--fabrication {
    grid-column: 1;
    grid-row: auto;
  }

  .about__side .about__tools {
    grid-column: 1;
    grid-row: auto;
  }

  /* Work grid: collapse the staggered brick into one full-width stack. */
  .work-grid {
    grid-template-columns: 1fr;
    grid-auto-rows: auto;
  }

  .work-grid .project-card {
    grid-column: 1 / -1;
    grid-row: auto;
    aspect-ratio: 4 / 3;
  }
}

@media (max-width: 480px) {
  :root {
    --space-2xl: 4rem;
    --space-3xl: 5rem;
  }

  .site-footer__inner {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ============================================================
   Project page: Nek.io
   Accent scheme layered over the site's paper background. The product
   (turntable) travels + rotates on scroll via a fixed canvas stage.
   ============================================================ */
.project-nekio {
  --nk-accent: #0A7D8C;
  /* text/links/labels: passes AA on paper */
  --nk-accent-bright: #2FC6DB;
  /* glows + graphic accents only (not text) */
  --nk-accent-tint: rgba(47, 198, 219, 0.10);
  --nk-screen: #0E1416;
  /* OLED-like dark screen background */
  --nk-dark: #101215;
  /* dark hero + dark tiles */
  --nk-dark-2: #16191d;
  /* dark tile surface */
  --nk-dark-border: rgba(244, 243, 240, 0.16);
  --nk-on-dark: #F4F3F0;
  /* text on dark */
  --nk-on-dark-soft: #9BA0A6;
  /* muted text on dark */
}

/* ============================================================
   NEK.IO project page: template rebuild (v6).
   Alternating dark/light rhythm over the paper background with a single
   teal accent. The hero is full-bleed dark; content bands alternate
   dark/light; the showcase turntable and build video carry the identity.
   ============================================================ */
.nk-main {
  position: relative;
  z-index: 1;
}

/* ---- Hero (full-bleed dark) + spec banner ---- */
.nk-hero {
  position: relative;
  overflow: hidden;
  /* Fit beneath the header spacer, leaving a small glimpse of the next section. */
  min-height: calc(100vh - clamp(9.5rem, 20vw, 12.5rem) + 24px);
  min-height: calc(100svh - clamp(9.5rem, 20vw, 12.5rem) + 24px);
  /* Override the general section padding; the container provides hero spacing. */
  padding: 0;
  display: flex;
  flex-direction: column;
  background:
    radial-gradient(120% 90% at 84% 22%, rgba(47, 198, 219, 0.14), transparent 55%),
    var(--nk-dark);
  color: var(--nk-on-dark);
}

.nk-hero>.container {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  row-gap: 32px;
  /* Vertical spacing only; keep the base container's horizontal gutter so
     hero text never runs to the screen edge on narrow viewports. */
  padding-top: calc(var(--space-xl) + var(--space-2xl));
  padding-bottom: max(48px, calc(var(--space-2xl) - 80px));
}

.nk-specs {
  margin-top: auto;
}

.nk-hero__scroll {
  position: absolute;
  bottom: var(--space-md);
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--nk-accent-bright);
  pointer-events: none;
}

/* Thin vertical track with a glowing teal segment that travels down and repeats. */
.nk-hero__scroll-line {
  display: block;
  position: relative;
  width: 2px;
  height: 58px;
  overflow: hidden;
  border-radius: 2px;
  background: rgba(47, 198, 219, 0.22);
}

.nk-hero__scroll-line::after {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 48%;
  border-radius: 2px;
  background: linear-gradient(to bottom, transparent, var(--nk-accent-bright));
  box-shadow: 0 0 14px 2px rgba(47, 198, 219, 0.9), 0 0 4px 1px rgba(47, 198, 219, 0.7);
  animation: nk-scrollline 1.9s var(--ease) infinite;
}

@keyframes nk-scrollline {
  0% {
    transform: translateY(-100%);
  }

  100% {
    transform: translateY(222%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .nk-hero__scroll-line::after {
    animation: none;
    transform: none;
    height: 100%;
    opacity: 0.5;
  }
}

.nk-hero__title {
  font-family: var(--font-logo);
  font-weight: 400;
  font-size: clamp(3.5rem, 11vw, 9rem);
  line-height: 0.9;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--nk-on-dark);
  /* Soft OLED-teal halo, nodding to the device's screen. */
  text-shadow: 0 0 26px rgba(47, 198, 219, 0.22);
}

.nk-hero__desc {
  margin-top: 34px;
  max-width: 56ch;
  font-size: 1.05rem;
  font-weight: 400;
  line-height: 1.65;
  color: var(--nk-on-dark-soft);
}

.nk-specs {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-md);
  padding: var(--space-lg) 0;
  border-top: 1px solid var(--nk-dark-border);
}

.nk-spec {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.nk-spec__icon {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  color: var(--nk-accent-bright);
}

.nk-spec__icon svg {
  width: 100%;
  height: 100%;
}

.nk-spec__text {
  display: flex;
  flex-direction: column;
}

.nk-spec__num {
  font-family: var(--font-logo);
  font-weight: 400;
  font-size: 2rem;
  line-height: 1;
  color: var(--nk-on-dark);
}

.nk-spec__label {
  margin-top: 0.2rem;
  max-width: 15ch;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--nk-on-dark-soft);
}

/* ---- Section scaffolding ---- */
.nk-section {
  padding: var(--space-2xl) 0;
  position: relative;
}

.nk-section__head {
  max-width: 66ch;
  margin-bottom: var(--space-xl);
}

.nk-label {
  color: var(--nk-accent);
  margin-bottom: var(--space-sm);
}

.nk-section h2,
.nk-details-band h2 {
  font-family: var(--font-logo);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 1;
  font-size: clamp(1.9rem, 3.6vw, 3rem);
}

.nk-section__lede {
  margin-top: var(--space-md);
  max-width: 68ch;
  font-size: 1.05rem;
  line-height: 1.65;
  color: var(--color-ink-soft);
}

.nk-section--center .nk-section__head {
  max-width: 60ch;
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.nk-section--center .nk-label {
  justify-content: center;
}

.nk-section--center .nk-section__lede {
  margin-left: auto;
  margin-right: auto;
}

/* ---- Dark section band (recolours contents + placeholders) ---- */
.nk-section--dark,
.nk-details-band {
  background:
    radial-gradient(120% 90% at 84% 16%, rgba(47, 198, 219, 0.12), transparent 55%),
    var(--nk-dark);
  color: var(--nk-on-dark);
  border-top: 1px solid var(--nk-dark-border);
  border-bottom: 1px solid var(--nk-dark-border);
}

.nk-section--dark h2,
.nk-details-band h2,
.nk-section--dark h3,
.nk-section--dark h4 {
  color: var(--nk-on-dark);
}

.nk-section--dark .nk-label,
.nk-details-band .nk-label {
  color: var(--nk-accent-bright);
}

.nk-section--dark .nk-section__lede,
.nk-details-band .nk-section__lede {
  color: var(--nk-on-dark-soft);
}

/* Inline reference link (e.g. the RoboEyes credit on the dark Software band). */
.nk-link {
  color: var(--nk-accent-bright);
  transition: color 180ms var(--ease);
}

.nk-link:hover,
.nk-link:focus-visible {
  color: #fff;
  outline: none;
}

/* ---- Overview (prose + objectives + image) ---- */
.nk-overview__head {
  max-width: 60ch;
  margin-bottom: var(--space-md);
}

.nk-overview__body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2xl);
  align-items: center;
}

.nk-overview__prose p {
  color: var(--color-ink-soft);
  font-size: 1.05rem;
  line-height: 1.65;
}

.nk-overview__prose p+p {
  margin-top: var(--space-sm);
}

.nk-overview__media {
  position: relative;
}

.nk-overview__tools {
  margin-top: 60px;
  padding-top: 0;
}

.nk-overview__tools-key {
  display: block;
  margin-bottom: var(--space-sm);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--nk-accent);
}

.nk-toolgrid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-sm);
}

.nk-toolgrid li {
  text-align: center;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--color-border-strong);
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--color-ink);
  background: var(--color-bg);
  cursor: default;
  transition: color 220ms var(--ease), border-color 220ms var(--ease),
    background 220ms var(--ease), box-shadow 220ms var(--ease), transform 220ms var(--ease);
}

.nk-toolgrid li:hover {
  color: var(--nk-accent);
  border-color: var(--nk-accent);
  background: var(--nk-accent-tint);
  box-shadow: var(--shadow-sm);
  transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
  .nk-toolgrid li:hover {
    transform: none;
  }
}

/* ---- Hardware: image-forward cards ---- */
.nk-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-md);
}

.nk-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  transition: border-color 200ms var(--ease), box-shadow 200ms var(--ease), transform 200ms var(--ease);
}

.nk-card:hover {
  border-color: var(--nk-accent);
  box-shadow: var(--shadow-md);
  transform: translateY(-3px);
}

.nk-card__body {
  padding: var(--space-lg) var(--space-md) var(--space-md);
}

.nk-card__sub {
  display: block;
  margin-bottom: var(--space-2xs);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--nk-accent);
}

.nk-card h3 {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: none;
  letter-spacing: -0.01em;
  font-size: 1.4rem;
  margin-bottom: var(--space-2xs);
}

.nk-card p {
  font-size: 0.92rem;
  color: var(--color-ink-soft);
  line-height: 1.55;
}

.nk-card__media {
  /* Fill the space below the copy so every card shows a consistent gap
     under its text and the photos share a baseline, instead of a fixed
     aspect box pinned to the bottom (which left uneven gaps when the
     paragraphs differed in length). */
  flex: 1 1 auto;
  min-height: 210px;
  border: none;
  border-radius: 0;
  border-top: 1px solid var(--color-border);
}

/* Duotone photo treatment: greyscale the image, then wash it in the teal
   accent with a blend mode so the build photos sit inside the theme. */
.nk-duo {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: var(--nk-dark);
}

.nk-duo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(0.35) contrast(1.01);
  transition: filter 360ms var(--ease);
}

.nk-duo::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--nk-accent);
  mix-blend-mode: color;
  opacity: 0.18;
  pointer-events: none;
  transition: opacity 360ms var(--ease);
}

/* Reveal the full, unfiltered photo on hover. */
.nk-card:hover .nk-duo img {
  filter: none;
}

.nk-card:hover .nk-duo::after {
  opacity: 0;
}

/* ---- Expression list: step name + trigger labels (used by the live face list) ---- */
.nk-step__name {
  margin: 0 0 0.2rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--nk-on-dark);
}

.nk-step__trigger {
  display: block;
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--nk-accent-bright);
}

/* ---- Final build / module (reference composition, no text overlap) ---- */
.nk-module__head {
  margin-bottom: var(--space-md);
}

.nk-module__title {
  color: var(--color-ink);
  font-size: clamp(1.9rem, 3.6vw, 3rem);
}

.nk-module__sub {
  margin-top: var(--space-2xs);
  font-size: 1.1rem;
  color: var(--color-ink-soft);
}

.nk-module__grid {
  display: grid;
  grid-template-columns: 1fr 1.3fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
}

.nk-module__text {
  max-width: 52ch;
}

.nk-module__text>p {
  color: var(--color-ink-soft);
  font-size: 1.05rem;
  line-height: 1.65;
}

.nk-module__text>p+p {
  margin-top: var(--space-sm);
}

/* Final build: the working-device clip (landscape) in a dark instrument-style
   frame, stacked beneath the write-up. */
.nk-buildvideo {
  position: relative;
  top: 20px;
  margin: 0;
  width: 100%;
  max-width: 760px;
  justify-self: end;
}

.nk-buildvideo__frame {
  position: relative;
  padding: 10px;
  border-radius: var(--radius-lg);
  background:
    radial-gradient(130% 120% at 80% 0%, rgba(47, 198, 219, 0.14), transparent 55%),
    var(--nk-dark);
  border: 1px solid var(--nk-dark-border);
  box-shadow: var(--shadow-lg), 0 0 0 1px rgba(47, 198, 219, 0.08) inset;
}

/* Top status strip: a recording-light motif that reads as a capture device. */
.nk-buildvideo__bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 2px 6px 9px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--nk-on-dark-soft);
}

.nk-buildvideo__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--nk-accent-bright);
  box-shadow: 0 0 8px 1px rgba(47, 198, 219, 0.8);
  animation: nk-bv-blink 1.8s steps(1) infinite;
}

.nk-buildvideo__label {
  color: var(--nk-on-dark);
}

.nk-buildvideo__rec {
  margin-left: auto;
  color: var(--nk-accent-bright);
}

@keyframes nk-bv-blink {

  0%,
  60% {
    opacity: 1;
  }

  61%,
  100% {
    opacity: 0.25;
  }
}

.nk-buildvideo__screen {
  position: relative;
  border-radius: calc(var(--radius-md));
  overflow: hidden;
}

.nk-buildvideo__el {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: #000;
  /* Give the video its own GPU layer so decode/compositing stays off the main
     thread and the overlays below don't force a per-frame software blend. */
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* Retro-tech overlay: moving film grain + faint CRT scanlines over the feed. */
.nk-buildvideo__grain,
.nk-buildvideo__scan {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
}

.nk-buildvideo__grain {
  /* Oversized so the layer's edges always stay outside the frame: the animation
     translates this box, and without the old blend mode a flush edge would show
     as a drifting rectangle. The extra margin keeps it off-screen. */
  inset: -25%;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size: 180px 180px;
  opacity: 0.1;
  /* Normal compositing instead of mix-blend-mode: blending a full-size layer
     against live video every frame is a heavy GPU cost on weaker hardware. */
  will-change: transform;
  animation: nk-grain 0.5s steps(5) infinite;
}

@keyframes nk-grain {
  0% {
    transform: translate(0, 0);
  }

  20% {
    transform: translate(-8%, 4%);
  }

  40% {
    transform: translate(6%, -6%);
  }

  60% {
    transform: translate(-4%, -8%);
  }

  80% {
    transform: translate(8%, 6%);
  }

  100% {
    transform: translate(0, 0);
  }
}

.nk-buildvideo__scan {
  background: repeating-linear-gradient(to bottom,
      rgba(0, 0, 0, 0.16) 0, rgba(0, 0, 0, 0.16) 1px,
      transparent 1px, transparent 3px);
  /* Dropped mix-blend-mode: multiply here; thin dark lines read almost
     identically with plain alpha, without the per-frame blend over video. */
  opacity: 0.5;
  animation: nk-scanflicker 3.2s steps(1) infinite;
}

/* A very subtle teal tint + vignette to tie the feed to the frame. */
.nk-buildvideo__screen::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  background:
    radial-gradient(130% 120% at 50% 45%, transparent 55%, rgba(0, 0, 0, 0.35)),
    linear-gradient(rgba(47, 198, 219, 0.05), rgba(47, 198, 219, 0.05));
  mix-blend-mode: normal;
}

@keyframes nk-scanflicker {

  0%,
  97% {
    opacity: 0.55;
  }

  98% {
    opacity: 0.4;
  }

  100% {
    opacity: 0.58;
  }
}

@media (prefers-reduced-motion: reduce) {

  .nk-buildvideo__grain,
  .nk-buildvideo__scan {
    animation: none;
  }
}

/* Thin corner reticles over the footage. */
.nk-buildvideo__corner {
  position: absolute;
  width: 16px;
  height: 16px;
  border: 1.5px solid rgba(47, 198, 219, 0.7);
  pointer-events: none;
  z-index: 2;
}

.nk-buildvideo__corner--tl {
  top: 8px;
  left: 8px;
  border-right: none;
  border-bottom: none;
}

.nk-buildvideo__corner--tr {
  top: 8px;
  right: 8px;
  border-left: none;
  border-bottom: none;
}

.nk-buildvideo__corner--bl {
  bottom: 8px;
  left: 8px;
  border-right: none;
  border-top: none;
}

.nk-buildvideo__corner--br {
  bottom: 8px;
  right: 8px;
  border-left: none;
  border-top: none;
}

/* Control bar beneath the footage. */
.nk-buildvideo__controls {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 4px 2px;
}

.nk-buildvideo__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--nk-dark-border);
  background: var(--nk-dark-2);
  color: var(--nk-on-dark);
  cursor: pointer;
  transition: background 160ms var(--ease), border-color 160ms var(--ease),
    color 160ms var(--ease), transform 160ms var(--ease);
}

.nk-buildvideo__btn:hover,
.nk-buildvideo__btn:focus-visible {
  outline: none;
  color: #fff;
  border-color: var(--nk-accent);
  background: var(--nk-accent);
  transform: translateY(-1px);
}

.nk-buildvideo__btn svg {
  width: 17px;
  height: 17px;
}

/* Icon swap: play/pause, mute/sound. */
.nk-buildvideo__i-pause,
.nk-buildvideo__i-sound {
  display: none;
}

.nk-buildvideo.is-playing .nk-buildvideo__i-play {
  display: none;
}

.nk-buildvideo.is-playing .nk-buildvideo__i-pause {
  display: block;
}

.nk-buildvideo.is-unmuted .nk-buildvideo__i-muted {
  display: none;
}

.nk-buildvideo.is-unmuted .nk-buildvideo__i-sound {
  display: block;
}

/* Seek track. */
.nk-buildvideo__track {
  position: relative;
  flex: 1;
  min-width: 40px;
  height: 20px;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.nk-buildvideo__track::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 3px;
  transform: translateY(-50%);
  border-radius: 3px;
  background: rgba(244, 243, 240, 0.16);
}

.nk-buildvideo__played {
  position: absolute;
  left: 0;
  top: 50%;
  height: 3px;
  width: 0;
  transform: translateY(-50%);
  border-radius: 3px;
  background: var(--nk-accent-bright);
}

.nk-buildvideo__buffer {
  display: none;
}

.nk-buildvideo__knob {
  position: absolute;
  top: 50%;
  left: 0;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(47, 198, 219, 0.35);
  transform: translate(-50%, -50%) scale(0);
  transition: transform 160ms var(--ease);
}

.nk-buildvideo__track:hover .nk-buildvideo__knob,
.nk-buildvideo__track:focus-visible .nk-buildvideo__knob {
  transform: translate(-50%, -50%) scale(1);
  outline: none;
}

/* ---- Up close: drag-to-spin 360 viewer + detail thumbnails in one dark band ---- */
.nk-details-band {
  padding: var(--space-2xl) 0;
}

.nk-showcase {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}

/* Drag-to-spin 360 viewer (continuous, either direction; not tied to scroll). */
.nk-turntable {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.nk-turntable__stage {
  position: relative;
  width: 100%;
  aspect-ratio: 3 / 2;
  border: 1px solid var(--nk-dark-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background:
    radial-gradient(58% 46% at 50% 40%, rgba(47, 198, 219, 0.30), transparent 70%),
    radial-gradient(140% 120% at 50% 118%, rgba(47, 198, 219, 0.12), transparent 60%),
    var(--nk-dark-2);
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
}

.nk-turntable__stage.is-grabbing {
  cursor: grabbing;
}

.nk-turntable__stage:focus-visible {
  outline: 2px solid var(--nk-accent-bright);
  outline-offset: 3px;
}

/* Soft contact shadow so the product sits on a surface. */
.nk-turntable__stage::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 7%;
  transform: translateX(-50%);
  width: 56%;
  height: 8%;
  border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(0, 0, 0, 0.55), transparent 72%);
  filter: blur(7px);
  z-index: 0;
  pointer-events: none;
}

.nk-turntable__frame {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  pointer-events: none;
  filter: drop-shadow(0 14px 16px rgba(0, 0, 0, 0.45));
}

.nk-turntable__frame.is-active {
  opacity: 1;
}

.nk-turntable__hud {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

.nk-turntable__eyebrow {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--nk-accent-bright);
}

.nk-turntable__angle {
  font-family: var(--font-logo);
  font-weight: 400;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--nk-on-dark);
  min-width: 3.4ch;
  text-align: center;
}

.nk-turntable__pips {
  display: flex;
  gap: 7px;
  margin-left: auto;
}

.nk-turntable__pip {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--nk-dark-border);
  transition: background 160ms var(--ease), transform 160ms var(--ease);
}

.nk-turntable__pip.is-active {
  background: var(--nk-accent-bright);
  transform: scale(1.3);
}

/* Up-close aside: reflective closing text. */
.nk-showcase__aside {
  display: flex;
  flex-direction: column;
}

.nk-showcase__aside .nk-section__head {
  margin-bottom: var(--space-md);
}

.nk-showcase__text+.nk-showcase__text {
  margin-top: var(--space-sm);
}

.nk-showcase__text {
  color: var(--nk-on-dark-soft);
  font-size: 1.05rem;
  line-height: 1.65;
}

@media (max-width: 960px) {
  .nk-showcase {
    grid-template-columns: 1fr;
    gap: var(--space-lg);
  }
}

/* ---- Other projects: product-style cards ---- */
.nk-more__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-md);
}

.nk-more__card {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-md);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  transition: border-color 200ms var(--ease), box-shadow 200ms var(--ease), transform 200ms var(--ease);
}

.nk-more__card:hover {
  border-color: var(--nk-accent);
  box-shadow: var(--shadow-md);
  transform: translateY(-3px);
}

.nk-more__thumb {
  aspect-ratio: 4 / 3;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  color: var(--color-border-strong);
  font-family: var(--font-logo);
  font-weight: 400;
  font-size: 2rem;
}

.nk-more__name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.1rem;
}

.nk-more__desc {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
}

/* ---- A closer look: build close-ups kept inside the live-demo band ----
   Text on one half, images on the other: two small shots side by side with a
   wider one beneath. Columns mirror the module grid above so the two blocks
   line up and read as one section. */
.nk-closer {
  display: grid;
  grid-template-columns: 1fr 1.3fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: start;
  margin-top: var(--space-lg);
}

.nk-closer__text {
  max-width: 46ch;
}

/* Build-detail bullets: teal dot markers to match the project accent. */
.nk-closer__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.nk-closer__list li {
  position: relative;
  padding-left: 1.5rem;
  color: var(--color-ink);
  font-size: 1.05rem;
  line-height: 1.55;
}

.nk-closer__list li+li {
  margin-top: var(--space-md);
}

.nk-closer__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--nk-accent);
  box-shadow: 0 0 0 3px var(--nk-accent-tint);
}

.nk-closer__media {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-sm);
}

/* Same outline treatment as the hardware cards: a thin border that lifts and
   lights up teal on hover. */
.nk-closer__fig {
  margin: 0;
  overflow: hidden;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: transform 220ms var(--ease), border-color 220ms var(--ease), box-shadow 220ms var(--ease);
}

.nk-closer__fig:hover {
  transform: translateY(-3px);
  border-color: var(--nk-accent);
  box-shadow: var(--shadow-md);
}

.nk-closer__media img {
  width: 100%;
  aspect-ratio: 1 / 1;
  display: block;
  height: auto;
  object-fit: cover;
}

@media (max-width: 960px) {
  .nk-closer {
    grid-template-columns: 1fr;
    gap: var(--space-lg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .nk-closer__fig:hover {
    transform: none;
  }
}

/* ---- Responsive ---- */
@media (max-width: 960px) {
  .nk-overview__body {
    grid-template-columns: 1fr;
    gap: var(--space-lg);
  }

  .nk-toolgrid {
    grid-template-columns: repeat(3, 1fr);
  }

  .nk-cards,
  .nk-more__grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .nk-specs {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Build: stack the text then the video, each full width, on narrow screens */
  .nk-module__grid {
    grid-template-columns: 1fr;
    gap: var(--space-lg);
  }

  .nk-buildvideo {
    max-width: none;
    justify-self: stretch;
  }
}

@media (max-width: 560px) {

  .nk-cards,
  .nk-more__grid,
  .nk-specs,
  .nk-toolgrid {
    grid-template-columns: 1fr;
  }
}

/* ============================================================
   NEK.IO interaction flourishes (paired with nekio-fx.js / nekio.js):
   live OLED face, cursor spotlight on dark bands, scroll progress bar,
   and the turntable gallery.
   ============================================================ */
/* ---- Side dot navigation (one dot per section) ---- */
.nk-dots {
  position: fixed;
  top: 50%;
  left: clamp(0.9rem, 2vw, 1.75rem);
  transform: translateY(-50%);
  z-index: 200;
  display: none;
  /* shown on desktop pointer devices (see media query below) */
  flex-direction: column;
  gap: 0.95rem;
  padding: 0.6rem 0.45rem;
}

.nk-dot {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.nk-dot::before {
  content: '';
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: transparent;
  border: 1.5px solid var(--color-border-strong);
  transition: background 220ms var(--ease), border-color 220ms var(--ease),
    transform 220ms var(--ease);
}

.nk-dot:hover::before,
.nk-dot:focus-visible::before {
  border-color: var(--nk-accent);
  transform: scale(1.18);
}

.nk-dot:focus-visible {
  outline: none;
}

.nk-dot.is-active::before {
  background: var(--nk-accent);
  border-color: var(--nk-accent);
  transform: scale(1.3);
  box-shadow: 0 0 0 4px var(--nk-accent-tint);
}

/* Section label revealed on hover / active / focus. */
.nk-dot__label {
  position: absolute;
  left: calc(100% + 12px);
  top: 50%;
  transform: translateY(-50%) translateX(-6px);
  white-space: nowrap;
  padding: 0.28rem 0.6rem;
  border-radius: var(--radius-sm);
  background: var(--nk-dark);
  color: var(--nk-on-dark);
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms var(--ease), transform 200ms var(--ease);
}

.nk-dot:hover .nk-dot__label,
.nk-dot:focus-visible .nk-dot__label {
  opacity: 1;
  transform: translateY(-50%) translateX(0);
}

/* Any programmatic/anchor scroll (mobile menu, dot-nav jumps) should land a
   section heading BELOW the fixed header, not tucked under it. Without this on
   mobile, jumping to a section clipped the top of its eyebrow/title. */
html:has(.project-nekio) {
  scroll-padding-top: 84px;
}

/* Side dot nav is shown on desktop pointer devices; sections keep their
   natural height and the page scrolls normally. scroll-padding-top only
   affects programmatic scrolls (the dot-nav jumps) so they land the section
   heading just under the fixed header, never manual wheel scrolling. */
@media (min-width: 961px) and (hover: hover) and (pointer: fine) {
  html:has(.project-nekio) {
    scroll-padding-top: clamp(3.75rem, 6vw, 5rem);
  }

  .nk-dots {
    display: flex;
  }
}

/* ---- Cursor spotlight on dark bands ---- */
.nk-has-spotlight {
  position: relative;
}

.nk-spotlight {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background: radial-gradient(440px circle at var(--mx, 50%) var(--my, 28%), rgba(47, 198, 219, 0.13), transparent 60%);
  opacity: 0;
  transition: opacity 320ms var(--ease);
}

.nk-has-spotlight.is-hot .nk-spotlight {
  opacity: 1;
}

.nk-has-spotlight>.container {
  position: relative;
  z-index: 1;
}

/* ---- Live OLED face (Software section) ---- */
.nk-face {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: var(--space-2xl);
  align-items: center;
}

.nk-face__stage {
  position: relative;
  isolation: isolate;
  aspect-ratio: 3 / 2;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background:
    radial-gradient(120% 120% at 50% 42%, rgba(47, 198, 219, 0.22), transparent 62%),
    var(--nk-screen);
  border: 1px solid var(--nk-dark-border);
  /* glass bezel: bright top rim, a soft inner vignette, and a lifted edge */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    inset 0 0 0 1px rgba(47, 198, 219, 0.14),
    inset 0 0 44px 10px rgba(0, 0, 0, 0.55),
    0 22px 44px -22px rgba(0, 0, 0, 0.75);
}

.nk-face__canvas {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  display: block;
  image-rendering: pixelated;
  filter: drop-shadow(0 0 3px rgba(47, 198, 219, 0.4));
}

/* ---- OLED screen treatment: CRT scanlines, static, glitch, glass sheen ---- */
.nk-face__scan,
.nk-face__static,
.nk-face__glass {
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
}

/* Fine horizontal scanlines that drift slowly down the panel. */
.nk-face__scan {
  z-index: 2;
  background: repeating-linear-gradient(to bottom,
      rgba(0, 0, 0, 0) 0,
      rgba(0, 0, 0, 0) 2px,
      rgba(0, 0, 0, 0.22) 3px,
      rgba(0, 0, 0, 0) 4px);
  mix-blend-mode: multiply;
  opacity: 0.5;
  animation: nk-face-scan 7s linear infinite;
}

/* Grainy static that shimmers faintly across the panel. */
.nk-face__static {
  z-index: 3;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size: 170px 170px;
  mix-blend-mode: screen;
  opacity: 0.07;
  animation: nk-face-static 0.5s steps(4) infinite;
}

/* Even vignette that deepens all four corners equally, like glass over a panel. */
.nk-face__glass {
  z-index: 4;
  background: radial-gradient(115% 115% at 50% 50%, transparent 52%, rgba(0, 0, 0, 0.4) 100%);
}

@keyframes nk-face-scan {
  from {
    background-position: 0 0;
  }

  to {
    background-position: 0 56px;
  }
}

@keyframes nk-face-static {
  from {
    background-position: 0 0;
  }

  to {
    background-position: 170px 90px;
  }
}

@media (prefers-reduced-motion: reduce) {

  .nk-face__scan,
  .nk-face__static {
    animation: none;
  }

  .nk-face__static {
    opacity: 0.05;
  }
}

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

.nk-face__item {
  display: flex;
  gap: var(--space-md);
  align-items: baseline;
  padding: var(--space-md) var(--space-sm);
  border-top: 1px solid var(--nk-dark-border);
  cursor: pointer;
  transition: background 200ms var(--ease), padding-left 200ms var(--ease);
}

.nk-face__item:last-child {
  border-bottom: 1px solid var(--nk-dark-border);
}

.nk-face__num {
  flex-shrink: 0;
  font-family: var(--font-logo);
  font-weight: 400;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--nk-on-dark-soft);
  transition: color 200ms var(--ease);
}

.nk-face__body h4 {
  color: var(--nk-on-dark);
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
  font-size: 1.05rem;
}

.nk-face__body .nk-step__trigger {
  color: var(--nk-accent-bright);
}

.nk-face__body p {
  margin-top: 0.25rem;
  color: var(--nk-on-dark-soft);
  font-size: 0.85rem;
  line-height: 1.5;
}

.nk-face__item:hover,
.nk-face__item.is-active {
  background: rgba(47, 198, 219, 0.07);
  padding-left: var(--space-md);
}

.nk-face__item:hover .nk-face__num,
.nk-face__item.is-active .nk-face__num {
  color: var(--nk-accent-bright);
}

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

@media (max-width: 960px) {
  .nk-face {
    grid-template-columns: 1fr;
    gap: var(--space-lg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .nk-spotlight {
    display: none;
  }
}

/* ---- Custom cursor: glowing dot + trailing dashed reticle ---- */
@media (hover: hover) and (pointer: fine) {

  .nk-cursor-on,
  .nk-cursor-on * {
    cursor: none !important;
  }
}

.nk-cursor__ring,
.nk-cursor__dot {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  opacity: 0;
  will-change: transform;
}

.nk-cursor-show .nk-cursor__ring,
.nk-cursor-show .nk-cursor__dot {
  opacity: 1;
}

.nk-cursor__ring {
  width: 38px;
  height: 38px;
  margin: -19px 0 0 -19px;
  z-index: 300;
  transition: width 0.25s var(--ease), height 0.25s var(--ease), margin 0.25s var(--ease), opacity 0.2s var(--ease);
}

.nk-cursor__ring::before {
  content: '';
  position: absolute;
  inset: 0;
  border: 1.5px dashed var(--nk-accent-bright);
  border-radius: 50%;
  animation: nk-cursor-spin 7s linear infinite;
}

.nk-cursor__dot {
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  z-index: 301;
  background: var(--nk-accent-bright);
  border-radius: 50%;
  box-shadow: 0 0 10px rgba(47, 198, 219, 0.85);
  transition: opacity 0.2s var(--ease);
}

.nk-cursor__ring.is-active {
  width: 62px;
  height: 62px;
  margin: -31px 0 0 -31px;
}

.nk-cursor__ring.is-active::before {
  border-style: solid;
  background: rgba(47, 198, 219, 0.08);
}

.nk-cursor__ring.is-down {
  width: 26px;
  height: 26px;
  margin: -13px 0 0 -13px;
}

@keyframes nk-cursor-spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {

  .nk-cursor__ring,
  .nk-cursor__dot {
    display: none;
  }
}

/* ---- OLED face: sound call-out typed above the screen ---- */
.nk-face__screen {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.nk-face__sound {
  min-height: 1.5em;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.86rem;
  letter-spacing: 0.02em;
  line-height: 1.5;
  color: var(--nk-accent-bright);
  text-shadow: 0 0 8px rgba(47, 198, 219, 0.4);
  white-space: nowrap;
  overflow: hidden;
}

.nk-face__sound.is-typing::after {
  content: '\2588';
  margin-left: 1px;
  animation: nk-caret 0.9s steps(1) infinite;
}

@keyframes nk-caret {

  0%,
  50% {
    opacity: 1;
  }

  50.01%,
  100% {
    opacity: 0;
  }
}

/* ---- Hero: faded product render behind the title ---- */
.nk-hero__render,
.nk-hero__eyes {
  position: absolute;
  z-index: 0;
  top: 75%;
  left: 81%;
  height: 190%;
  width: auto;
  max-width: 120%;
  opacity: 0.45;
  pointer-events: none;
}

.nk-hero__render {
  transform: translate(-50%, -50%) scaleX(-1);
  -webkit-mask-image:
    radial-gradient(64% 72% at 50% 42%, #000 32%, transparent 82%),
    linear-gradient(to bottom,
      transparent 0%,
      #000 40%,
      #000 60%,
      transparent 98%);
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(64% 72% at 50% 42%, #000 32%, transparent 82%),
    linear-gradient(to bottom,
      transparent 0%,
      #000 40%,
      #000 60%,
      transparent 98%);
  mask-composite: intersect;
}

/* The eyes share the render's exact box, so they stay where they were baked in,
   then slide a few px toward the cursor (vars set in nekio-fx.js) so nek.io
   appears to look at you. translate stays in screen space, so no mirror flip. */
.nk-hero__eyes {
  transform: translate(calc(-50% + var(--nk-eye-x, 0px)), calc(-50% + var(--nk-eye-y, 0px))) scaleX(-1);
  transition: transform 220ms var(--ease);
}

.nk-hero__copy {
  max-width: 56ch;
}

@media (max-width: 720px) {

  /* Stack the hero: copy up top on a clean dark field, product anchored to the
     bottom as the hero visual (was a huge faint render floating behind the text). */
  .nk-hero>.container {
    justify-content: flex-start;
    row-gap: 22px;
  }

  /* No scroll-cue indicator on mobile. */
  .nk-hero__scroll {
    display: none;
  }

  .nk-hero__render,
  .nk-hero__eyes {
    height: auto;
    width: 122%;
    max-width: 122%;
    left: 64%;
    top: auto;
    bottom: -2%;
    opacity: 0.6;
  }

  .nk-hero__render {
    transform: translateX(-50%) scaleX(-1);
  }

  .nk-hero__eyes {
    transform: translate(calc(-50% + var(--nk-eye-x, 0px)), var(--nk-eye-y, 0px)) scaleX(-1);
  }

  .nk-hero__copy {
    max-width: none;
    position: relative;
    z-index: 1;
  }
}

/* ---- Overview: interactive anatomy diagram (hover the pins) ---- */
.nk-anatomy {
  display: flex;
  align-items: center;
  justify-content: center;
}

.nk-anatomy__frame {
  position: relative;
  top: 40px;
  left: -20px;
  line-height: 0;
  width: 100%;
  max-width: min(520px, 62vw);
  margin: 0 auto;
}

.nk-anatomy__img {
  width: 100%;
  height: auto;
  display: block;
  filter:
    drop-shadow(0 0 1px rgba(47, 198, 219, 0.9)) drop-shadow(16px 18px 0 rgba(47, 198, 219, 0.2));
}

.nk-pin {
  position: absolute;
  width: 22px;
  height: 22px;
  margin: 0;
  padding: 0;
  border: 0;
  transform: translate(-50%, -50%);
  background: transparent;
  cursor: help;
  z-index: 3;
}

.nk-pin::before {
  content: '';
  position: absolute;
  inset: 7px;
  border-radius: 50%;
  background: var(--nk-accent-bright);
  box-shadow: 0 0 8px rgba(47, 198, 219, 0.7);
}

.nk-pin::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1.5px solid var(--nk-accent-bright);
  animation: nk-pin-pulse 2.4s var(--ease) infinite;
}

@keyframes nk-pin-pulse {
  0% {
    transform: scale(0.6);
    opacity: 0.9;
  }

  70% {
    transform: scale(1.7);
    opacity: 0;
  }

  100% {
    opacity: 0;
  }
}

.nk-pin:hover,
.nk-pin:focus-visible {
  z-index: 5;
  outline: none;
}

.nk-pin:hover::after,
.nk-pin:focus-visible::after {
  animation-play-state: paused;
  opacity: 1;
  transform: scale(1.25);
}

/* Glassy teal pill tag with a thin stem down to the pin. */
.nk-pin__tip {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 12px);
  transform: translate(-50%, 4px);
  white-space: nowrap;
  padding: 0.34rem 0.72rem;
  border-radius: 999px;
  background: rgba(12, 98, 110, 0.55);
  border: 1px solid rgba(47, 198, 219, 0.55);
  -webkit-backdrop-filter: blur(9px) saturate(1.4);
  backdrop-filter: blur(9px) saturate(1.4);
  color: #fff;
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
  box-shadow: 0 6px 18px rgba(8, 60, 68, 0.35);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease);
  z-index: 6;
}

.nk-pin__tip::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  width: 1px;
  height: 12px;
  background: var(--nk-accent-bright);
}

.nk-pin:hover .nk-pin__tip,
.nk-pin:focus-visible .nk-pin__tip {
  opacity: 1;
  transform: translate(-50%, 0);
}

@media (prefers-reduced-motion: reduce) {
  .nk-pin::after {
    animation: none;
    opacity: 0.6;
  }
}

/* Fade the visible crop boundaries, independent of image zoom. */
.nk-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom, var(--nk-dark), transparent 16%),
    linear-gradient(to top, var(--nk-dark), transparent 20%),
    linear-gradient(to right, var(--nk-dark), transparent 10%),
    linear-gradient(to left, var(--nk-dark), transparent 10%);
}

/* Software intro sits above the screen in the left column. */
.nk-face__screen .nk-section__head {
  margin-bottom: 40px;
}

.nk-face__screen .nk-section__lede {
  margin-top: 24px;
}

@media (min-width: 961px) {
  .nk-face {
    align-items: end;
  }
}

/* ---- Wiring overview: block diagram + pin-out sheet (dark section) ---- */
.nk-wiremap {
  margin-top: 0;
  padding: 0;
  border-radius: 0;
  border: none;
  background: transparent;
  box-shadow: none;
  color: var(--nk-on-dark);
}

.nk-wiremap__intro {
  margin-bottom: 0;
}

.nk-wiremap .nk-label {
  color: var(--nk-accent-bright);
}

.nk-wiremap__title {
  margin-bottom: var(--space-md);
  font-family: var(--font-logo);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 1;
  font-size: clamp(1.9rem, 3.6vw, 3rem);
  color: var(--nk-on-dark);
}

.nk-wiremap__intro p:not(.nk-label) {
  color: var(--nk-on-dark-soft);
  font-size: 1.05rem;
  line-height: 1.65;
}

.nk-wiremap__intro p+p {
  margin-top: var(--space-sm);
}

/* two columns: text + diagram stacked on the left, tall pin-out card on the
   right filling the full height alongside them. */
.nk-wiremap__layout {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: clamp(1.5rem, 3vw, 2.75rem);
  align-items: start;
}

.nk-wiremap__left {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

/* Small eyebrow label over each column (mirrors the pin-out card's title). */
.nk-wiremap__col-title {
  margin: 0 0 var(--space-md);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--nk-accent-bright);
}

.nk-wiremap__scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.nk-wiremap__svg {
  width: 100%;
  min-width: 460px;
  height: auto;
  display: block;
}

/* PCB-style signal traces: 45-degree routing, rounded joins, cyan glow. */
.nk-trace {
  stroke: rgba(47, 198, 219, 0.55);
  stroke-width: 2.5;
}

.nk-trace-pad circle {
  fill: var(--nk-accent-bright);
}

/* Traveling signal pulse: a soft point of light glides along each trace
   (paths use pathLength="100" so every wire pulses in step). A near-zero
   dash + round cap + layered glow reads as a moving glow, not a block. */
.nk-trace-pulse {
  stroke: #FFFFFF;
  stroke-width: 4;
  stroke-linecap: round;
  stroke-dasharray: 1.2 98.8;
  stroke-dashoffset: 100;
  filter:
    drop-shadow(0 0 3px #CFF4FB) drop-shadow(0 0 7px var(--nk-accent-bright)) drop-shadow(0 0 15px var(--nk-accent-bright));
  /* Each pulse shoots out fast, then eases as it reaches the component. */
  animation: nk-trace-flow 1.2s cubic-bezier(0.12, 0.85, 0.25, 1) infinite;
}

@keyframes nk-trace-flow {
  from {
    stroke-dashoffset: 100;
  }

  to {
    stroke-dashoffset: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .nk-trace-pulse {
    display: none;
  }
}

/* Component nodes on the dark wiring background. */
.nk-node-item {
  cursor: default;
}

.nk-node-item .nk-node__box {
  transition: stroke 200ms var(--ease), fill 200ms var(--ease), filter 200ms var(--ease);
}

.nk-node-item .nk-node__name,
.nk-node-item .nk-node__sub {
  transition: fill 200ms var(--ease);
}

/* Subtle hover: the component lights up (brighter border + glow). */
.nk-node-item:hover .nk-node__box {
  stroke: var(--nk-accent-bright);
  fill: #17242a;
  filter: drop-shadow(0 0 7px rgba(47, 198, 219, 0.55));
}

.nk-node-item:hover .nk-node__name {
  fill: var(--nk-accent-bright);
}

.nk-node-item:hover .nk-node__pad {
  stroke: var(--nk-accent-bright);
  filter: drop-shadow(0 0 6px rgba(47, 198, 219, 0.6));
}

/* Trace mode: while a component is hovered, its wires + the parts they reach
   stay lit and the rest of the board dims (driven by nekio-fx.js section 7). */
.nk-wiremap__svg .nk-node-item,
.nk-wiremap__svg .nk-trace,
.nk-wiremap__svg .nk-trace-pad,
.nk-wiremap__svg .nk-detail,
.nk-wiremap__svg .nk-trace-pulse {
  transition: opacity 240ms var(--ease);
}

.nk-wiremap__svg.is-tracing .nk-node-item,
.nk-wiremap__svg.is-tracing .nk-trace {
  opacity: 0.12;
}

.nk-wiremap__svg.is-tracing .nk-trace-pad,
.nk-wiremap__svg.is-tracing .nk-detail {
  opacity: 0.14;
}

.nk-wiremap__svg.is-tracing .nk-trace-pulse {
  opacity: 0;
}

.nk-wiremap__svg.is-tracing .nk-node-item.is-lit,
.nk-wiremap__svg.is-tracing .nk-trace.is-lit,
.nk-wiremap__svg.is-tracing .nk-trace-pulse.is-lit {
  opacity: 1;
}

.nk-wiremap__svg.is-tracing .nk-trace.is-lit {
  stroke: #CFF4FB;
  stroke-width: 2.8;
}

/* Lit components pick up the same glow as the hover state. */
.nk-wiremap__svg.is-tracing .nk-node-item.is-lit .nk-node__box {
  stroke: var(--nk-accent-bright);
  fill: #17242a;
  filter: drop-shadow(0 0 7px rgba(47, 198, 219, 0.55));
}

.nk-wiremap__svg.is-tracing .nk-node-item.is-lit .nk-node__box--hub {
  fill: #123f49;
  filter: drop-shadow(0 0 14px rgba(47, 198, 219, 0.6));
}

.nk-wiremap__svg.is-tracing .nk-node-item.is-lit .nk-node__name {
  fill: var(--nk-accent-bright);
}

.nk-wiremap__svg.is-tracing .nk-node-item.is-lit .nk-node__pad {
  stroke: var(--nk-accent-bright);
  filter: drop-shadow(0 0 6px rgba(47, 198, 219, 0.6));
}

.nk-node__box {
  fill: var(--nk-dark-2);
  stroke: rgba(47, 198, 219, 0.3);
  stroke-width: 1;
}

.nk-node__box--hub {
  fill: #0f3942;
  stroke: var(--nk-accent-bright);
  stroke-width: 1.5;
  filter: drop-shadow(0 0 10px rgba(47, 198, 219, 0.45));
}

/* Keep the hub's stronger glow on hover rather than the generic one. */
.nk-node-item:hover .nk-node__box--hub {
  fill: #123f49;
  filter: drop-shadow(0 0 14px rgba(47, 198, 219, 0.6));
}

/* Corner mounting pads on the hub. */
.nk-node__mount {
  fill: none;
  stroke: var(--nk-accent-bright);
  stroke-width: 1.5;
  opacity: 0.7;
}

.nk-node__pad {
  fill: var(--nk-dark-2);
  stroke: var(--nk-accent-bright);
  stroke-width: 1.5;
}

.nk-node__name {
  fill: var(--nk-on-dark);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 16px;
}

.nk-node__name--hub {
  fill: var(--nk-accent-bright);
  font-size: 18px;
}

.nk-node__sub {
  fill: var(--nk-on-dark-soft);
  font-family: var(--font-body);
  font-size: 11.5px;
  letter-spacing: 0.04em;
}

/* Schematic detail layer: pin labels on traces + ground/resistor/cap symbols. */
.nk-trace-label {
  fill: rgba(47, 198, 219, 0.72);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 9.5px;
  letter-spacing: 0.03em;
}

.nk-sym path,
.nk-sym rect {
  fill: none;
  stroke: rgba(47, 198, 219, 0.55);
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.nk-sym .nk-sym--pwr {
  fill: rgba(47, 198, 219, 0.55);
  stroke: none;
}

.nk-sym-label {
  fill: var(--nk-on-dark-soft);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 8.5px;
  letter-spacing: 0.02em;
  opacity: 0.85;
}

/* pin-out sheet: a dark card floating on the section, 3-column flow */
.nk-wiremap__sheet {
  padding: clamp(1.1rem, 2vw, 1.6rem) clamp(1.2rem, 2.2vw, 1.75rem);
  border-radius: var(--radius-lg);
  border: 1px solid var(--nk-dark-border);
  background:
    radial-gradient(120% 80% at 85% 0%, rgba(47, 198, 219, 0.08), transparent 55%),
    #0A0D10;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.35), inset 0 0 0 1px rgba(47, 198, 219, 0.05);
}

.nk-wiremap__sheet-title {
  margin: 0 0 var(--space-md);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--nk-accent-bright);
}

/* One clean table: a single column, each component a subheader, and the
   pin -> target columns aligned down the whole card. */
.nk-pinout {
  display: block;
}

.nk-pinout__group {
  margin-bottom: var(--space-sm);
}

.nk-pinout__group:last-child {
  margin-bottom: 0;
}

.nk-pinout__group h5 {
  margin: 0 0 0.5rem;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--nk-dark-border);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--nk-on-dark);
}

.nk-pinout__group ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.nk-pinout li {
  display: grid;
  grid-template-columns: 3.7em 1.3em 1fr;
  align-items: baseline;
  padding: 0.2rem 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8rem;
  line-height: 1.3;
}

.nk-pinout__a {
  text-align: left;
  color: var(--nk-on-dark-soft);
}

.nk-pinout li em {
  font-style: normal;
  color: var(--nk-accent-bright);
}

.nk-pinout__b {
  color: var(--nk-on-dark);
  font-weight: 600;
}

@media (max-width: 1024px) {
  .nk-wiremap__layout {
    grid-template-columns: 1fr;
  }
}

.nk-wiremap__sheet {
  background: transparent;
  box-shadow: none;
}

.nk-pinout {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.5rem;
  align-items: start;
}

.nk-pinout__group {
  margin-bottom: 0;
}

/* Stack on small screens */
@media (max-width: 480px) {
  .nk-pinout {
    grid-template-columns: 1fr;
  }
}


/* Independent pinout columns allow staggered component headings. */
.nk-pinout__column {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  min-width: 0;
}

.nk-pinout__column .nk-pinout__group {
  margin-bottom: 0;
}

/* Keep the label outside the frame and anchor both to the diagram. */
.nk-pinout-wrap {
  width: 80%;
  justify-self: end;
  align-self: end;
  min-width: 0;
}

.nk-pinout-wrap .nk-wiremap__sheet {
  width: 100%;
  margin-top: 0;
}

@media (max-width: 1024px) {
  .nk-pinout-wrap {
    width: 100%;
    align-self: start;
  }
}

.nk-pinout-wrap {
  transform: translateY(-10px);
}

.nk-closer__text > .nk-label {
  margin-bottom: 12px;
  color: var(--nk-accent);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

[data-nk-section="Hardware"] .nk-section__head {
  margin-bottom: 34px;
}