/* The car is drivable. Without a visible affordance nobody finds that out,
   and a mechanic nobody can reach is the same as no mechanic at all. */
@keyframes keyhint {
  0%, 100% { border-color: var(--line-2); }
  50%      { border-color: var(--leclerc); color: var(--fg); }
}
/* Once they have driven it, the hint has done its job. */

@media (max-width: 900px) {
    /* no keyboard on a phone */
}

/* Short viewports (360x640 and similar) overflowed the hero by ~53px.
   Tightening the type and rhythm keeps every line of the intro visible
   without scrolling past the fold. */
/* !important because the main stylesheet is inlined in <head> AFTER this
   file, so on equal specificity the later rule wins and these never applied. */
@media (max-height: 700px) and (max-width: 760px) {
  .hero { padding-top: clamp(3.5rem, 8vh, 5rem) !important; }
  .hero-title-wrap { padding: clamp(0.4rem, 1.2vh, 0.9rem) 0 !important; }
  .hero-title { font-size: clamp(2.2rem, 11vw, 4rem) !important; }
  .hero-sub { min-height: 2.4em !important; font-size: 0.95rem !important; }
  .hero-intro { margin-top: 0.6rem !important; font-size: 0.84rem !important; line-height: 1.5 !important; }
  .hero-bio { font-size: 0.82rem !important; line-height: 1.48 !important; }
  .hero-meta { font-size: 0.6rem !important; }
}

/* ── project card stats ────────────────────────────────────────
   The numbers are the argument. They sit above the fold on the
   card, not behind the "how" toggle. */
.card-stats {
  display: flex;
  gap: 1.25rem;
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
}
.card-stats li {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}
.card-stats b {
  font-size: 1.35rem;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--ac, var(--accent));
}
.card-stats span {
  font-family: var(--mono);
  font-size: 0.55rem;
  letter-spacing: 0.12em;
  text-transform: lowercase;
  color: var(--fg-3);
  white-space: nowrap;
}
@media (max-width: 560px) {
  .card-stats { gap: 0.9rem; }
  .card-stats b { font-size: 1.15rem; }
}

/* ── headline stat strip ───────────────────────────────────────── */
.stat-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: clamp(0.75rem, 2vw, 1.5rem);
  margin: 0 0 clamp(2.5rem, 6vw, 4.5rem);
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: clamp(1.25rem, 3vw, 2rem) 0;
}
.stat-strip li { display: flex; flex-direction: column; gap: 0.3rem; }
.stat-strip b {
  font-size: clamp(2rem, 5vw, 3.25rem);
  font-weight: 900;
  letter-spacing: -0.05em;
  line-height: 0.9;
  background: linear-gradient(100deg, var(--leclerc), var(--banana));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.stat-strip span {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--fg);
  letter-spacing: -0.015em;
}
.stat-strip em {
  font-family: var(--mono);
  font-style: normal;
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  color: var(--fg-3);
  /* long language lists must not orphan a single token onto its own line */
  text-wrap: pretty;
}
/* "ts · js · c++ · c# · go" is too long for a two-column phone grid —
   shorten it rather than let it wrap into a stray orphan. */
@media (max-width: 620px) {
  .stat-strip em { letter-spacing: 0.06em; }
}

/* ── gear spec strip ────────────────────────────────────────────
   Replaces a photo grid that had no photographs behind it. Real
   camera specs beat seven near-black boxes. */
.gear-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 0;
  margin: 0 0 clamp(2rem, 4vw, 3rem);
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line);
}
.gear-strip li {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 1.1rem 1rem 1.1rem 0;
  border-bottom: 1px solid var(--line);
}
.gear-strip b {
  font-family: var(--mono);
  font-size: 0.55rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 500;
}
.gear-strip span {
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--fg);
  letter-spacing: -0.015em;
}

/* The footer repo link inherits the tertiary grey, which fails AA against the
   page background. Give it the same treatment as the contact links. */
.foot a {
  color: var(--fg-2);
  text-decoration: none;
  border-bottom: 1px solid var(--line-2);
  padding-bottom: 1px;
  transition: color 0.3s, border-color 0.3s;
}
.foot a:hover,
.foot a:focus-visible { color: var(--leclerc); border-color: var(--leclerc); }

/* Without WebGL there is no car, so promising one is a lie. The hint retires
   on first input, but nobody can ever drive anything here. */

/* Identifiers must keep their real casing. The page is lowercase by design,
   but a GitHub handle lowercased to "neticytof" is a DIFFERENT string that
   404s — the same class of bug as the dead contact links. */
.spec-row b[data-exact] { text-transform: none; letter-spacing: -0.01em; }

/* ═══════════════════════════════════════════════════════════════════════
   v5 — the way out to the ten worlds. Everything above this line is v1.
   Added during the merge; v1 itself is unmodified.
   ═══════════════════════════════════════════════════════════════════════ */

.nav-link--demos {
  display: inline-flex; align-items: baseline; gap: .3em;
  color: var(--ink, #17151f);
}
.nav-link--demos i { font-style: normal; font-size: .8em; opacity: .55; }
.nav-link--demos::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -.25em;
  height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: left; transition: transform .25s ease;
}
.nav-link--demos:hover::after,
.nav-link--demos:focus-visible::after { transform: scaleX(1); }

.hero-demos { margin: 2.2rem 0 0; }
.hero-demos__btn {
  display: grid; gap: .45rem; text-decoration: none; color: inherit;
  padding: 1rem 1.25rem; max-width: 34rem;
  border: 1px solid color-mix(in oklab, currentColor 22%, transparent);
  border-radius: 10px;
  transition: border-color .25s ease, transform .25s ease;
}
.hero-demos__btn:hover,
.hero-demos__btn:focus-visible { border-color: currentColor; transform: translateY(-2px); }
.hero-demos__btn b { font-weight: 600; letter-spacing: -.01em; }
.hero-demos__btn span { opacity: .62; font-size: .92rem; line-height: 1.45; }

.demos { padding: 5rem 0 2rem; border-top: 1px solid color-mix(in oklab, currentColor 14%, transparent); }
.demos-h { margin: 0 0 .6rem; }
.demos-note { max-width: 44rem; opacity: .62; line-height: 1.55; margin: 0 0 2rem; }

.demos-grid {
  list-style: none; margin: 0 0 2rem; padding: 0;
  display: grid; gap: 1px; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  background: color-mix(in oklab, currentColor 12%, transparent);
  border: 1px solid color-mix(in oklab, currentColor 12%, transparent);
  border-radius: 10px; overflow: hidden;
}
.demos-grid a {
  display: grid; gap: .2rem; padding: 1rem 1.1rem; text-decoration: none;
  color: inherit; background: var(--paper, #f6f1e7);
  transition: background .2s ease;
}
.demos-grid a:hover, .demos-grid a:focus-visible { background: color-mix(in oklab, currentColor 6%, var(--paper, #f6f1e7)); }
.demos-grid b { font-weight: 600; }
.demos-grid span { font-size: .84rem; opacity: .55; }

.demos-foot { margin: 0; }
.btn-demos {
  display: inline-flex; align-items: baseline; gap: .5em;
  padding: .8rem 1.3rem; border-radius: 999px; text-decoration: none;
  color: var(--paper, #f6f1e7); background: var(--ink, #17151f);
  transition: transform .2s ease;
}
.btn-demos:hover, .btn-demos:focus-visible { transform: translateY(-2px); }
.btn-demos i { font-style: normal; }

.foot__demos { color: inherit; }

@media (prefers-reduced-motion: reduce) {
  .nav-link--demos::after, .hero-demos__btn, .btn-demos, .demos-grid a { transition: none; }
  .hero-demos__btn:hover, .btn-demos:hover { transform: none; }
}
