/* Piyush Kasle — night-sky portfolio.
   Tokens first, then base, layout, and one block per component.
   Colour channels are kept as "r, g, b" lists so any alpha can be mixed: rgba(var(--pk-ink-rgb), .6). */

/* fonts, served from this site (assets/fonts/, SIL Open Font License): Space Grotesk and JetBrains Mono, variable
   weight, latin and latin-ext subsets; the browser fetches latin-ext only for a character that needs it */
@font-face { font-family: "Space Grotesk"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("../fonts/space-grotesk-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Space Grotesk"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("../fonts/space-grotesk-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 500; font-display: swap; src: url("../fonts/jetbrains-mono-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 500; font-display: swap; src: url("../fonts/jetbrains-mono-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }

:root {
  /* sky tone: midnight blue. The design's darker, near black blue was #0a0e18 / 10,14,24 and #0e1322 / 14,19,34;
     its neutral black was #0b0b0c / 11,11,12 and #0d0d0e / 13,13,14 */
  --pk-bg: #0c1530;
  --pk-bg-rgb: 12, 21, 48;
  --pk-bg2: #111c3b;
  --pk-bg2-rgb: 17, 28, 59;

  --pk-ink: #ece9e3;
  --pk-ink-rgb: 236, 233, 227;
  --pk-accent: #f6a06b;           /* the canvas reads --pk-accent-rgb too */
  --pk-accent-rgb: 246, 160, 107;
  --pk-on-accent: #14100c;
  --pk-hot: #fff6ec;              /* white-hot star core */
  --pk-ok: #86dca6;               /* availability */
  --pk-ok-rgb: 134, 220, 166;
  --pk-ok-text: #9be7b8;
  --pk-sage: #aebf92;             /* known-limitation callout */
  --pk-sage-rgb: 174, 191, 146;

  --font-sans: "Space Grotesk", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, Menlo, monospace;

  /* the page grows with the window: 1080px on laptops, up to 1800px on big monitors (see "large screens") */
  --page-max: clamp(1080px, 86vw, 1800px);
  --page-pad: 28px;
  --dock-lane: 78px;
  /* right-hand padding that keeps text clear of the fixed dock (22px inset + 40px buttons + a gap);
     wide screens already have that room in their margin. The header uses it too so the edges line up. */
  --page-pad-end: max(var(--page-pad), calc(var(--dock-lane) - max(0px, (100vw - var(--page-max)) / 2)));
}

/* ── base ─────────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }
/* Both clip sideways. A body setting alone would be handed to the window as "hidden" and the page could still pan;
   with the root's own value going to the window, the body really clips, so the sun's glow can run off the right edge. */
html { scroll-behavior: smooth; overflow-x: clip; }
body {
  margin: 0; min-height: 100vh; overflow-x: clip;
  background: var(--pk-bg); color: var(--pk-ink);
  font-family: var(--font-sans); font-size: 15px; line-height: 1.55;
}
h1, h2, h3, h4 { margin: 0; font-family: var(--font-sans); line-height: 1.12; letter-spacing: -0.02em; }
p { margin: 0; }
ul, ol, dl, dd { margin: 0; padding: 0; list-style: none; }
img, svg { display: block; }
a { color: inherit; text-decoration: none; }
a:hover { color: var(--pk-accent); }
button { font: inherit; color: inherit; }
::selection { background: rgba(var(--pk-accent-rgb), .28); }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--pk-accent); outline-offset: 3px; }

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* a four-point star that slowly breathes */
.tw { display: inline-flex; color: var(--pk-accent); animation: pk-twinkle 3.6s ease-in-out infinite; }

/* ── backdrop: canvas sky + film grain ────────────────────────────────── */

.sky { position: fixed; inset: 0; z-index: 0; width: 100%; height: 100%; pointer-events: none; }
.grain {
  position: fixed; inset: 0; z-index: 1; pointer-events: none;
  opacity: .05; mix-blend-mode: overlay;
  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='3' stitchTiles='stitch'/></filter><rect width='160' height='160' filter='url(%23n)'/></svg>");
}

/* ── header ───────────────────────────────────────────────────────────── */

.site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 20;
  background: rgba(var(--pk-bg-rgb), .72);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border-bottom: 1px solid rgba(var(--pk-ink-rgb), .08);
  transition: opacity 1s ease .6s;
}
.site-header__inner {
  max-width: var(--page-max); margin: 0 auto; padding: 14px var(--page-pad-end) 14px var(--page-pad);
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
}
.brand {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .14em; text-transform: uppercase;
}
.brand:hover { color: var(--pk-ink); }
.site-nav { display: flex; flex-wrap: wrap; align-items: center; gap: 22px; min-width: 0; }
.site-nav a {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 0;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: rgba(var(--pk-ink-rgb), .55); white-space: nowrap;
}
.site-nav a:hover { color: rgba(var(--pk-ink-rgb), .9); }
.site-nav svg { opacity: 0; transform: scale(0); transition: opacity .3s ease, transform .3s ease; }
.site-nav a[aria-current] { color: var(--pk-accent); }
.site-nav a[aria-current] svg { opacity: 1; transform: none; }

/* ── page + sections ──────────────────────────────────────────────────── */

.page {
  position: relative; z-index: 2; max-width: var(--page-max); margin: 0 auto; padding: 0 var(--page-pad);
  padding-right: var(--page-pad-end);
}

.section { padding: 96px 0; border-top: 1px solid rgba(var(--pk-ink-rgb), .08); transition: opacity 1s ease .2s; }
.section__grid { display: grid; grid-template-columns: minmax(0, 180px) minmax(0, 1fr); gap: 44px; align-items: start; }
.section__label {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--font-mono); font-size: 11px; font-weight: 400; letter-spacing: .16em; text-transform: uppercase;
  color: rgba(var(--pk-ink-rgb), .62);
}

.headline {
  max-width: 760px; margin: 0 0 26px;
  font-size: clamp(28px, 3.6vw, 44px); line-height: 1.08; font-weight: 600; letter-spacing: -0.035em;
  text-wrap: balance; color: var(--pk-ink);
}
.section--projects .headline { margin-bottom: 34px; }
.section--experience .headline { margin-bottom: 40px; }
@supports (animation-timeline: view()) {
  .headline { animation: pk-head-in linear both; animation-timeline: view(); animation-range: entry 0% cover 26%; }
}
.shimmer {
  --pk-shimmer: linear-gradient(90deg, var(--pk-accent) 0%, #fff3e6 50%, var(--pk-accent) 100%);
  background-image: var(--pk-shimmer);
  background-size: 200% 100%; background-repeat: repeat-x;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: pk-shimmer 7s linear infinite;
}
/* While the black hole pulls on the page (page-bend.js), the text on screen is cut into one box per word so each
   word can move on its own; the text goes back as it was once everything settles. A shimmer cut into words gives
   each word its own slice of the sweep, sized to the whole phrase (--pk-sw) and shifted to where the word sits in
   it (--pk-ox), so the colours carry on without a jump. */
@property --pk-sweep { syntax: '<number>'; inherits: true; initial-value: 0; }
.pk-word { display: inline-block; }
.shimmer[data-pk-split] { background-image: none; }
.shimmer[data-pk-split] .pk-word {
  background-image: var(--pk-shimmer);
  background-size: calc(var(--pk-sw) * 2) 100%; background-repeat: repeat-x;
  background-position: calc(var(--pk-sw) * -2 * var(--pk-sweep) - var(--pk-ox)) 0;
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

/* small uppercase mono heading inside a section ("Decision log") */
.eyebrow {
  font-family: var(--font-mono); font-size: 11px; font-weight: 400; line-height: 1.55;
  letter-spacing: .14em; text-transform: uppercase; color: rgba(var(--pk-ink-rgb), .6);
}

/* ── hero ─────────────────────────────────────────────────────────────── */

.hero { min-height: 100vh; display: flex; flex-direction: column; justify-content: center; gap: 34px; padding: 140px 0 80px; }
.hero > :not(.pk-orb-wrap) { transition: opacity 1s ease, transform 1.2s cubic-bezier(.2, .7, .2, 1), filter 1s ease; }
.hero > :nth-child(2) { transition-delay: .12s; }
.hero > :nth-child(3) { transition-delay: .26s; }
.hero > :nth-child(4) { transition-delay: .4s; }
.hero > :nth-child(5) { transition-delay: .52s; }

/* the hyperspace intro hides the whole page until the sky drops out of warp: the hero rises in, the rest fades in.
   Everything hides, not just the hero, so a reload that restores a scrolled position never leaves content over the warp.
   Hiding is instant (no transition while the attribute is set); the reveal uses each element's own transition. */
html[data-pk-intro] .hero > :not(.pk-orb-wrap) { opacity: 0; transform: translateY(26px) scale(.98); filter: blur(8px); }
html[data-pk-intro] :is(.site-header, .section, .dock, .sky-hint, .pk-orb-wrap) { opacity: 0; transition: none; }

/* sun by day, moon by night (assets/js/sunmoon.js). It sits to the right of the name, level with it, behind
   the hero text: main.js measures the name and sets --orb-y (the name's centre), so a resize never pushes it up
   under the header. Its glow is part of the canvas, twice the body's width, and runs off the right edge
   (body has overflow-x: clip). On phones it shrinks and the caption hides. */
#hero { position: relative; }
#hero > *:not(.pk-orb-wrap) { position: relative; z-index: 1; }
.pk-orb-wrap {
  --orb: clamp(220px, 23vw, 330px);
  position: absolute; z-index: 0; width: calc(var(--orb) * 2); height: calc(var(--orb) * 2);
  right: calc(var(--orb) * -0.42); top: calc(var(--orb-y, 34vh) - var(--orb));
  pointer-events: none; opacity: 0; transition: opacity 1.4s ease .2s;
}
.pk-orb-wrap[data-ready] { opacity: 1; }
.pk-orb-inner { position: absolute; inset: 0; will-change: transform; }
.pk-orb-inner canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.pk-orb-cap {
  position: absolute; left: 50%; top: calc(50% + var(--orb) * 0.5 + 22px); transform: translateX(-50%); white-space: nowrap;
  font-family: 'JetBrains Mono', monospace; font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase;
  color: rgba(236, 233, 227, .58);
}
@media (max-width: 900px) {
  .pk-orb-wrap { --orb: clamp(112px, 22vw, 190px); top: calc(var(--orb-y, clamp(118px, 16vh, 200px)) - var(--orb)); right: calc(var(--orb) * -0.3); }
  .pk-orb-cap { display: none; }
}

.avail {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 12px;
  padding: 8px 18px 8px 12px; border-radius: 999px;
  border: 1px solid rgba(var(--pk-ok-rgb), .35); background: rgba(var(--pk-ok-rgb), .07);
  font-size: 13.5px; color: rgba(var(--pk-ink-rgb), .8);
}
.avail:hover { border-color: rgba(var(--pk-ok-rgb), .7); background: rgba(var(--pk-ok-rgb), .12); color: var(--pk-ink); }
.avail__star { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; color: var(--pk-ok); }
.avail__star svg { filter: drop-shadow(0 0 6px rgba(var(--pk-ok-rgb), .9)); }
.avail__ring {
  position: absolute; inset: -4px; border-radius: 999px; pointer-events: none;
  border: 1px solid rgba(var(--pk-ok-rgb), .75); animation: pk-ping 2.4s ease-out infinite;
}
.avail__status { font-weight: 600; color: var(--pk-ok-text); }
.avail__more { display: inline-flex; align-items: center; gap: 12px; }
.avail__sep { width: 1px; height: 14px; background: rgba(var(--pk-ink-rgb), .2); }

.hero__coords {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  color: rgba(var(--pk-ink-rgb), .62);
}
.hero__dot { color: rgba(var(--pk-ink-rgb), .25); }
.hero__lst { color: rgba(var(--pk-accent-rgb), .8); font-variant-numeric: tabular-nums; }
.hero__name {
  font-size: clamp(52px, 9vw, 112px); line-height: .94; font-weight: 600; letter-spacing: -0.04em;
  text-shadow: 0 0 48px rgba(var(--pk-accent-rgb), .16);
}
.hero__role { margin-top: -12px; font-size: clamp(19px, 2.3vw, 27px); font-weight: 500; letter-spacing: -0.015em; color: rgba(var(--pk-ink-rgb), .8); }

/* ── buttons ──────────────────────────────────────────────────────────── */

/* comet trail: an outline pill with a comet circling its edge (assets/js/comet.js draws the comet);
   on hover or focus it fills with the accent and glows */
.btn-comet {
  position: relative; display: inline-flex; align-items: center; gap: 10px;
  padding: 13px 24px 13px 20px; border-radius: 999px;
  border: 1px solid rgba(var(--pk-accent-rgb), .34);
  background: rgba(var(--pk-bg-rgb), .45); color: var(--pk-ink);
  font-family: var(--font-mono); font-size: 12.5px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  transition: background-color .3s ease, border-color .3s ease, color .3s ease, box-shadow .35s ease;
}
.btn-comet:hover, .btn-comet:focus-visible {
  background: var(--pk-accent); border-color: var(--pk-accent); color: var(--pk-on-accent);
  box-shadow: 0 0 22px rgba(var(--pk-accent-rgb), .55), 0 0 64px rgba(var(--pk-accent-rgb), .22);
}
.btn-comet__star { display: inline-flex; color: var(--pk-accent); transition: transform .55s cubic-bezier(.2, .7, .2, 1), color .3s ease; }
.btn-comet:hover .btn-comet__star, .btn-comet:focus-visible .btn-comet__star { color: currentColor; transform: rotate(90deg) scale(1.3); }
.btn-comet__arrow { display: inline-block; transition: transform .3s ease; }
.btn-comet:hover .btn-comet__arrow, .btn-comet:focus-visible .btn-comet__arrow { transform: translateX(4px); }

/* the comet itself: four dashes ending at one point, brightest and thickest at the head */
.comet {
  position: absolute; top: -1px; left: -1px; width: calc(100% + 2px); height: calc(100% + 2px);
  overflow: visible; pointer-events: none;
  filter: drop-shadow(0 0 3px rgba(var(--pk-accent-rgb), .9));
}
.comet__dash {
  fill: none; stroke: var(--pk-accent); stroke-linecap: round;
  animation: comet-orbit 3.6s linear infinite;
  transition: stroke .3s ease;
}
.comet__dash:nth-child(1) { stroke-width: 1; opacity: .14; }
.comet__dash:nth-child(2) { stroke-width: 1.3; opacity: .3; }
.comet__dash:nth-child(3) { stroke-width: 1.6; opacity: .6; }
.comet__dash:nth-child(4) { stroke-width: 2.4; stroke: var(--pk-hot); }
/* over the peach fill the whole comet turns white-hot */
.btn-comet:hover .comet__dash, .btn-comet:focus-visible .comet__dash { stroke: var(--pk-hot); }

/* pill links with a line-art icon: the floating dock and the contact row */
.pill-link {
  display: inline-flex; align-items: center; border-radius: 999px;
  border: 1px solid rgba(var(--pk-ink-rgb), .16);
  font-family: var(--font-mono); color: rgba(var(--pk-ink-rgb), .8);
}
.pill-link:hover { border-color: var(--pk-accent); color: var(--pk-accent); box-shadow: 0 0 18px rgba(var(--pk-accent-rgb), .3); }
.pill-link svg { flex: none; }
/* GitHub and LinkedIn marks stay white: their brand rules don't allow recolouring them to the accent */
.pill-link .brand-mark { color: var(--pk-ink); }
/* the resume link: a filled peach pill that glows on hover */
.pill-link--primary {
  border-color: transparent; background: var(--pk-accent); color: var(--pk-on-accent); font-weight: 600;
  transition: box-shadow .3s ease, filter .3s ease;
}
.pill-link--primary:hover {
  border-color: transparent; color: var(--pk-on-accent); filter: brightness(1.06);
  box-shadow: 0 0 22px rgba(var(--pk-accent-rgb), .55), 0 0 56px rgba(var(--pk-accent-rgb), .2);
}
.pill-link--primary .todo { color: inherit; opacity: .6; }

/* underline that draws in from the left */
.link {
  padding-bottom: 3px; font-family: var(--font-mono); font-size: 11px; color: rgba(var(--pk-ink-rgb), .58);
  background-image: linear-gradient(var(--pk-accent), var(--pk-accent)), linear-gradient(rgba(var(--pk-ink-rgb), .18), rgba(var(--pk-ink-rgb), .18));
  background-size: 0% 1px, 100% 1px; background-repeat: no-repeat; background-position: 0 100%, 0 100%;
  transition: background-size .4s ease, color .25s ease;
}
.link:hover { color: var(--pk-accent); background-size: 100% 1px, 100% 1px; }

/* ── about ────────────────────────────────────────────────────────────── */

.about__body { margin-bottom: 18px; font-size: clamp(19px, 2.3vw, 26px); line-height: 1.5; color: rgba(var(--pk-ink-rgb), .9); text-wrap: pretty; }
.about__note { font-family: var(--font-mono); font-size: 13px; line-height: 1.7; color: var(--pk-accent); }

/* ── stack ────────────────────────────────────────────────────────────── */

.stack { display: flex; flex-direction: column; gap: 30px; }
.stack__row {
  display: grid; grid-template-columns: minmax(0, 150px) minmax(0, 1fr); gap: 20px; align-items: start;
  padding-bottom: 26px; border-bottom: 1px solid rgba(var(--pk-ink-rgb), .06);
}
.stack__label {
  padding-top: 8px; font-family: var(--font-mono); font-size: 11px; font-weight: 400; line-height: 1.55;
  letter-spacing: .1em; text-transform: uppercase; color: rgba(var(--pk-ink-rgb), .6);
}
.chips { display: flex; flex-wrap: wrap; gap: 9px; }
.chip {
  display: inline-flex; align-items: center; gap: 9px; padding: 8px 14px 8px 10px; border-radius: 999px;
  border: 1px solid rgba(var(--pk-ink-rgb), .12); background: rgba(var(--pk-ink-rgb), .03);
  font-size: 13.5px; color: rgba(var(--pk-ink-rgb), .86);
}
.chip:hover { border-color: rgba(var(--pk-accent-rgb), .5); background: rgba(var(--pk-accent-rgb), .07); }
.chip img { width: 16px; height: 16px; opacity: .92; filter: grayscale(1) brightness(1.6); }

/* ── projects ─────────────────────────────────────────────────────────── */

/* project cards: square, each opening its write-up in a dialog. How many share a row depends on how many fit:
   1000px and wider: all four in one overlapping, slightly tilted row across the window (four cards of at least
     220px, overlapping by 8%, need 3.76 card widths plus the side lanes); while the deck is pinned
     (assets/js/project-deck.js sets --rise per card) they ride in one by one.
   Narrower: an upright grid, two to a row, and on phones one under another; each card rises in as it scrolls
     into view.
   A hovered card comes to the top, and keeps its place there until it has settled back. */
.pcards { display: grid; grid-template-columns: minmax(0, 1fr); gap: 22px; margin: 0; padding: 10px 6px 0; list-style: none; }
.pcards > li { position: relative; container-type: inline-size; transition: z-index 0s .45s; }
/* each card's resting tilt, its height offset in the row, and the spin it rides in with */
.pcards > li:nth-child(1) { --tilt: -2.5deg; --dy: 0px; --spin: -9deg; }
.pcards > li:nth-child(2) { --tilt: 1.5deg; --dy: 22px; --spin: 7deg; }
.pcards > li:nth-child(3) { --tilt: -1.5deg; --dy: -8px; --spin: -6deg; }
.pcards > li:nth-child(4) { --tilt: 3deg; --dy: 16px; --spin: 10deg; }
@media (max-width: 999px) {
  /* two to a row, lined up square to the page (nth-child(n) to outrank each card's own tilt above) */
  .pcards { grid-template-columns: repeat(2, minmax(0, 380px)); justify-content: center; gap: 26px; }
  .pcards > li:nth-child(n) { --tilt: 0deg; }
}
@media (max-width: 620px) {
  /* phones: one card under another */
  .pcards { grid-template-columns: minmax(0, 420px); gap: 22px; }
}
.pcards > li:hover, .pcards > li:focus-within { z-index: 10; transition: z-index 0s; }
@media (min-width: 1000px) {
  .pcards {
    /* four cards overlapping by 8% need 3.76 card widths; fill the space between the side lanes, mind the height */
    --card: clamp(220px, min((100vw - 2 * max(var(--page-pad), var(--dock-lane))) / 3.76, 100vh - 330px), 520px);
    display: flex; justify-content: center; align-items: center; gap: 0;
    width: 100vw; margin-left: calc(50% - 50vw); padding: 28px max(var(--page-pad), var(--dock-lane)) 0;
  }
  .pcards > li {
    flex: none; width: var(--card);
    transform: translate3d(0, calc(var(--dy, 0px) + (1 - var(--rise, 1)) * 105vh), 0) rotate(calc((1 - var(--rise, 1)) * var(--spin, 0deg)));
  }
  .pcards > li + li { margin-left: calc(var(--card) * -0.08); }
  /* keep each card's text clear of the neighbour that overlaps its right edge */
  .pcards > li:not(:last-child) .pcard { padding-right: calc(clamp(14px, 6.5cqi, 22px) + 6cqi); }
  .pcards > li:focus-within { --rise: 1 !important; }  /* tabbing to a card that hasn't ridden in yet shows it */
}
/* pinned: the stage holds still for a stretch of scrolling while the cards ride in */
.pdeck[data-pinned] { height: calc(100vh + 230vh); }
.pdeck[data-pinned] .pdeck__stage { position: sticky; top: 0; height: 100vh; display: flex; flex-direction: column; justify-content: center; padding-top: 56px; }
@supports (animation-timeline: view()) {
  @media (max-width: 999px) and (prefers-reduced-motion: no-preference) {
    .pcards > li { animation: pk-card-rise linear both; animation-timeline: view(); animation-range: entry 0% cover 32%; }
  }
}
.pcard {
  position: relative; display: flex; flex-direction: column; width: 100%; aspect-ratio: 1;
  gap: clamp(8px, 4cqi, 14px); padding: clamp(14px, 6.5cqi, 22px) clamp(14px, 6.5cqi, 22px) clamp(12px, 6cqi, 20px);
  border: 1px solid rgba(var(--pk-ink-rgb), .12); border-radius: 10px; cursor: pointer;
  font: inherit; color: var(--pk-ink); text-align: left;
  background:
    radial-gradient(120% 80% at 15% 0%, rgba(var(--pk-accent-rgb), .1), transparent 60%),
    linear-gradient(180deg, rgba(var(--pk-bg2-rgb), .97), rgba(var(--pk-bg-rgb), .97));
  box-shadow: 0 20px 44px -22px rgba(0, 0, 0, .7);
  transform: rotate(var(--tilt, 0deg));
  transition: transform .45s cubic-bezier(.2, .7, .2, 1), border-color .3s ease, box-shadow .35s ease;
}
.pcard:hover, .pcard:focus-visible {
  transform: rotate(0deg) translateY(-16px) scale(1.05); border-color: rgba(var(--pk-accent-rgb), .55);
  box-shadow: 0 28px 60px -24px rgba(0, 0, 0, .8), 0 0 44px rgba(var(--pk-accent-rgb), .16);
}
.pcard__top {
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--font-mono); font-size: clamp(9px, 3.2cqi, 11px); letter-spacing: .1em; text-transform: uppercase; color: rgba(var(--pk-ink-rgb), .55);
}
.pcard__num { color: var(--pk-accent); }
.pcard__go { font-size: 15px; color: var(--pk-accent); transition: transform .3s ease; }
.pcard:hover .pcard__go, .pcard:focus-visible .pcard__go { transform: translate(3px, -3px); }
.pcard__art { flex: 1 1 auto; min-height: 0; width: 100%; overflow: visible; }
.pcard__line { font-size: clamp(13px, 5cqi, 19px); line-height: 1.4; font-weight: 500; letter-spacing: -0.01em; text-wrap: pretty; }
.pcard__foot {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 6px 14px; padding-top: clamp(8px, 3.5cqi, 12px);
  border-top: 1px solid rgba(var(--pk-ink-rgb), .1);
  font-family: var(--font-mono); font-size: clamp(9.5px, 3.4cqi, 11.5px); color: rgba(var(--pk-ink-rgb), .6);
}
.pcard__title { color: var(--pk-ink); }
/* the cover drawings */
.pcard__art .a-grid { fill: none; stroke: rgba(var(--pk-ink-rgb), .07); }
.pcard__art .a-ink { fill: none; stroke: rgba(var(--pk-ink-rgb), .36); stroke-width: 1.5; stroke-linecap: round; }
.pcard__art .a-acc { fill: none; stroke: var(--pk-accent); stroke-width: 2; stroke-linecap: round; }
.pcard__art .a-dash { fill: none; stroke: rgba(var(--pk-ink-rgb), .3); stroke-width: 1.2; stroke-dasharray: 4 5; }
.pcard__art .a-flag { stroke: var(--pk-accent); }
.pcard__art .a-pole { stroke-width: 3; }
.pcard__art .a-fill { fill: rgba(var(--pk-accent-rgb), .75); }
.pcard__art .a-soft { fill: rgba(var(--pk-ink-rgb), .06); stroke: rgba(var(--pk-ink-rgb), .2); }
.pcard__art .a-label { fill: rgba(var(--pk-ink-rgb), .45); font-family: var(--font-mono); font-size: 10px; letter-spacing: .08em; }
.pcard__art .a-star { color: var(--pk-accent); }

/* a project's full write-up, in a dialog over the page */
.pdialog {
  width: min(880px, calc(100vw - 32px)); max-width: none; max-height: min(88vh, 980px); padding: 0;
  border: 1px solid rgba(var(--pk-ink-rgb), .14); border-radius: 18px; overflow: hidden;
  background: var(--pk-bg2); color: var(--pk-ink); box-shadow: 0 40px 120px rgba(0, 0, 0, .6);
}
.pdialog[open] { display: flex; flex-direction: column; animation: pk-dialog-in .32s cubic-bezier(.2, .7, .2, 1) both; }
/* ::backdrop doesn't see the page's custom properties in every browser, so the sky colour is written out */
.pdialog::backdrop { background: rgba(12, 21, 48, .72); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.pdialog[open]::backdrop { animation: pk-fade-in .32s ease both; }
.pdialog__panel { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 40px 44px 46px; }
.pdialog__close {
  position: absolute; top: 14px; right: 14px; z-index: 2; width: 38px; height: 38px; border-radius: 999px; cursor: pointer;
  border: 1px solid rgba(var(--pk-ink-rgb), .2); background: rgba(var(--pk-bg-rgb), .85); color: var(--pk-ink);
  font: inherit; font-size: 20px; line-height: 1; transition: border-color .25s ease, color .25s ease;
}
.pdialog__close:hover { border-color: var(--pk-accent); color: var(--pk-accent); }
.pdialog .project { padding: 0; border: 0; }
.pdialog .project__head { padding-right: 44px; }
html:has(.pdialog[open]) { overflow: hidden; }

/* one skeleton for every project: head, lede, tags, then whichever detail blocks it needs */
.projects { display: flex; flex-direction: column; }
.project {
  display: flex; flex-direction: column; gap: 22px; padding: 56px 0;
  border-top: 1px solid rgba(var(--pk-ink-rgb), .08); scroll-margin-top: 72px;
}
.project:last-child { padding-bottom: 0; }
.project__head { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: baseline; column-gap: 16px; row-gap: 8px; }
.project__num { font-family: var(--font-mono); font-size: 12px; color: var(--pk-accent); }
.project__title { font-size: clamp(24px, 3vw, 32px); font-weight: 600; line-height: 1.15; letter-spacing: -0.03em; overflow-wrap: anywhere; }
.project__links { display: flex; flex-wrap: wrap; gap: 16px; margin: 0; padding: 0; list-style: none; font-family: var(--font-mono); font-size: 11px; }
.project__meta {
  grid-column: 2 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: rgba(var(--pk-ink-rgb), .55);
}
.project__meta > span:not(.badge) + span::before { content: "·"; margin-right: 14px; color: rgba(var(--pk-ink-rgb), .35); }
.project__lede { max-width: 720px; font-size: 16.5px; line-height: 1.65; color: rgba(var(--pk-ink-rgb), .7); text-wrap: pretty; }
.project > .tags { margin-top: -6px; }

.badge {
  padding: 4px 10px; border-radius: 999px;
  background: rgba(var(--pk-accent-rgb), .14); color: var(--pk-accent);
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
}

.metrics {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 1px; overflow: hidden;
  background: rgba(var(--pk-ink-rgb), .1); border: 1px solid rgba(var(--pk-ink-rgb), .1); border-radius: 14px;
}
.metric { display: flex; flex-direction: column-reverse; justify-content: flex-end; gap: 6px; padding: 20px 18px; background: var(--pk-bg2); }
.metric:hover { background: radial-gradient(120% 90% at 50% 0%, rgba(var(--pk-accent-rgb), .10), var(--pk-bg2) 70%); }
.metric dd { font-size: clamp(24px, 3vw, 32px); font-weight: 600; letter-spacing: -0.03em; color: var(--pk-accent); }
.metric dt {
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase;
  color: rgba(var(--pk-ink-rgb), .62);
}

.decisions { display: flex; flex-direction: column; gap: 10px; }
.decision { overflow: hidden; border: 1px solid rgba(var(--pk-ink-rgb), .12); border-radius: 14px; background: rgba(var(--pk-ink-rgb), .02); }
.decision > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 16px 18px;
  list-style: none; cursor: pointer; font-size: 15.5px; font-weight: 500; line-height: 1.3;
}
.decision > summary::-webkit-details-marker { display: none; }
.decision > summary:hover { background: rgba(var(--pk-ink-rgb), .04); }
.decision__title { display: flex; align-items: center; gap: 12px; }
.decision__num { font-family: var(--font-mono); font-size: 11px; color: var(--pk-accent); }
.decision__sign { font-family: var(--font-mono); font-size: 16px; color: rgba(var(--pk-ink-rgb), .6); }
.decision__sign::before { content: "+"; }
.decision[open] .decision__sign::before { content: "\2212"; }
.decision__body { display: flex; flex-direction: column; gap: 12px; padding: 0 18px 18px 41px; animation: pk-rise .28s ease both; }
.decision__body p { max-width: 680px; font-size: 15px; line-height: 1.65; color: rgba(var(--pk-ink-rgb), .68); }
.decision__tags { display: flex; flex-wrap: wrap; gap: 8px; }

.pill { padding: 5px 11px; border-radius: 999px; font-family: var(--font-mono); font-size: 11px; }
.pill--accent { background: rgba(var(--pk-accent-rgb), .12); color: var(--pk-accent); }
.pill--outline { border: 1px solid rgba(var(--pk-ink-rgb), .14); color: rgba(var(--pk-ink-rgb), .6); }

.callout {
  display: flex; align-items: flex-start; gap: 14px; padding: 18px 20px; border-radius: 14px;
  border: 1px solid rgba(var(--pk-sage-rgb), .28); background: rgba(var(--pk-sage-rgb), .06);
}
.callout__label {
  padding-top: 2px; white-space: nowrap; color: var(--pk-sage);
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase;
}
.callout p { max-width: 640px; font-size: 15px; line-height: 1.6; color: rgba(var(--pk-ink-rgb), .72); }

.tags { display: flex; flex-wrap: wrap; gap: 8px; }
.tag {
  padding: 6px 12px; border-radius: 999px; border: 1px solid rgba(var(--pk-ink-rgb), .12);
  font-family: var(--font-mono); font-size: 11.5px; color: rgba(var(--pk-ink-rgb), .6);
}

/* key points of a project: a bold lead-in, then the detail */
.highlights { display: flex; flex-direction: column; gap: 12px; max-width: 720px; margin: 0; padding: 0; list-style: none; }
.highlights li { position: relative; padding-left: 20px; font-size: 15px; line-height: 1.65; color: rgba(var(--pk-ink-rgb), .68); }
.highlights li::before {
  content: ""; position: absolute; left: 2px; top: .62em; width: 6px; height: 6px;
  background: var(--pk-accent); transform: rotate(45deg); opacity: .8;
}
.highlights strong { font-weight: 500; color: var(--pk-ink); }
.highlights--compact { gap: 9px; }
.highlights--compact li { font-size: 14.5px; line-height: 1.6; }

/* Robocon: one card per season */
.seasons { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.season {
  display: flex; flex-direction: column; gap: 10px; padding: 18px 20px 20px;
  border: 1px solid rgba(var(--pk-ink-rgb), .1); border-radius: 14px; background: rgba(var(--pk-bg2-rgb), .7);
}
.season__year { font-family: var(--font-mono); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--pk-accent); }
.season__role { margin-bottom: 4px; font-size: 18px; font-weight: 600; letter-spacing: -0.02em; }

/* photos and screenshots. A gallery takes 1–3 figures: one fills the row, more put the first beside a stack */
.media {
  position: relative; margin: 0; overflow: hidden; aspect-ratio: 4 / 3;
  border: 1px solid rgba(var(--pk-ink-rgb), .1); border-radius: 14px; background: var(--pk-bg2);
}
.media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.media figcaption {
  position: absolute; left: 10px; bottom: 10px; padding: 4px 10px; border-radius: 999px;
  background: rgba(var(--pk-bg-rgb), .75); font-family: var(--font-mono); font-size: 11px; color: rgba(var(--pk-ink-rgb), .8);
}
.media--placeholder { display: grid; place-items: center; padding: 16px; border-style: dashed; text-align: center; font-family: var(--font-mono); font-size: 11px; }
.gallery { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 10px; }
.gallery > :first-child:not(:only-child) { grid-row: span 2; aspect-ratio: auto; }
.gallery > :only-child { grid-column: 1 / -1; aspect-ratio: 16 / 9; }

/* content still to be written: easy to spot on the page, easy to grep for in the HTML */
.todo { color: rgba(var(--pk-ink-rgb), .45); text-decoration: underline dashed rgba(var(--pk-accent-rgb), .55); text-underline-offset: 4px; }

/* ── experience: a trajectory that lights each stop as you scroll ─────── */

.timeline { position: relative; padding-left: 34px; }
.timeline__rail {
  position: absolute; left: 6px; top: 10px; bottom: 10px; width: 1px;
  background: repeating-linear-gradient(180deg, rgba(var(--pk-ink-rgb), .18) 0 3px, transparent 3px 8px);
}
.timeline__fill {
  position: absolute; left: 6px; top: 10px; width: 1px; height: 0;
  background: linear-gradient(180deg, rgba(var(--pk-accent-rgb), .1), var(--pk-accent));
  box-shadow: 0 0 8px rgba(var(--pk-accent-rgb), .55);
  transition: height .25s linear;
}
.timeline__fill::after {
  content: ""; position: absolute; left: -3px; bottom: -3px; width: 7px; height: 7px; border-radius: 999px;
  background: var(--pk-hot); box-shadow: 0 0 12px 3px rgba(var(--pk-accent-rgb), .75);
}
.timeline:not([data-armed]) .timeline__fill { display: none; }
.timeline__list { display: flex; flex-direction: column; gap: 52px; }
.timeline__item { position: relative; }
.timeline__star {
  position: absolute; left: -39px; top: -1px; width: 21px; height: 21px;
  display: flex; align-items: center; justify-content: center; border-radius: 999px; background: var(--pk-bg);
}
.timeline__star svg {
  width: 15px; height: 15px; color: var(--pk-accent);
  filter: drop-shadow(0 0 6px rgba(var(--pk-accent-rgb), .8));
  transition: width .5s ease, height .5s ease, color .5s ease, filter .5s ease;
}
.timeline__ring {
  position: absolute; inset: 0; border-radius: 999px; opacity: 0; pointer-events: none;
  border: 1px solid rgba(var(--pk-accent-rgb), .7);
}
.timeline__body { transition: opacity .7s ease, transform .8s cubic-bezier(.2, .7, .2, 1), filter .7s ease; }
.timeline[data-armed] .timeline__item:not([data-lit]) .timeline__body { opacity: .2; transform: translateX(22px); filter: blur(1.5px); }
.timeline[data-armed] .timeline__item:not([data-lit]) .timeline__star svg { width: 8px; height: 8px; color: rgba(var(--pk-ink-rgb), .4); filter: none; }
.timeline[data-armed] .timeline__item[data-lit] .timeline__star svg { animation: pk-twinkle 3.6s ease-in-out infinite .8s; }
.timeline[data-armed] .timeline__item[data-lit] .timeline__ring { animation: pk-burst .9s ease-out both; }

.timeline__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 8px; }
.timeline__dates { font-family: var(--font-mono); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--pk-accent); }
.timeline__place { font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .08em; color: rgba(var(--pk-ink-rgb), .58); }
.timeline__role { margin-bottom: 4px; font-size: 21px; font-weight: 600; letter-spacing: -0.02em; }
.timeline__org { margin-bottom: 10px; font-size: 14.5px; color: rgba(var(--pk-ink-rgb), .62); }
.timeline__note { max-width: 640px; font-size: 15px; line-height: 1.65; color: rgba(var(--pk-ink-rgb), .68); }
.timeline__points { display: flex; flex-direction: column; gap: 8px; max-width: 640px; margin: 12px 0 0; padding: 0; list-style: none; }
.timeline__points li { position: relative; padding-left: 18px; font-size: 14.5px; line-height: 1.6; color: rgba(var(--pk-ink-rgb), .66); }
.timeline__points li::before { content: ""; position: absolute; left: 2px; top: .62em; width: 5px; height: 5px; border-radius: 999px; background: rgba(var(--pk-accent-rgb), .75); }

/* ── contact + footer ─────────────────────────────────────────────────── */

.section--contact { padding-bottom: 60px; }
.contact { display: flex; flex-direction: column; gap: 28px; }
.contact__lede { max-width: 640px; font-size: clamp(24px, 3.4vw, 38px); line-height: 1.25; font-weight: 500; letter-spacing: -0.03em; }
.contact__links { display: flex; flex-wrap: wrap; gap: 10px; }
.contact__links .pill-link { gap: 10px; padding: 11px 18px; font-size: 12.5px; }
.contact__links .pill-link svg, .contact__links .btn-comet__icon { width: 17px; height: 17px; }
/* the resume: a comet trail pill, sized to sit in the row with the other links */
.contact__links .btn-comet { gap: 10px; padding: 11px 20px 11px 16px; font-size: 12.5px; letter-spacing: .04em; text-transform: none; }
.btn-comet__icon { flex: none; color: var(--pk-accent); transition: color .3s ease; }
.btn-comet:hover .btn-comet__icon, .btn-comet:focus-visible .btn-comet__icon { color: currentColor; }
.contact__links .btn-comet:hover .btn-comet__arrow, .contact__links .btn-comet:focus-visible .btn-comet__arrow { transform: translate(3px, -3px); }

.site-footer {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 14px;
  margin-top: 70px; padding-top: 22px; border-top: 1px solid rgba(var(--pk-ink-rgb), .08);
  font-family: var(--font-mono); font-size: 11px; color: rgba(var(--pk-ink-rgb), .56);
}
/* credits, on a line of their own: NASA for the black hole's sound (assets/js/hole-sound.js), Icons8 for the favicon */
.credits { flex-basis: 100%; color: rgba(var(--pk-ink-rgb), .4); }
.credits a { color: inherit; text-decoration: underline; text-decoration-color: rgba(var(--pk-ink-rgb), .2); text-underline-offset: 3px; }
.credits a:hover, .credits a:focus-visible { color: var(--pk-accent); text-decoration-color: currentColor; }
.credits__sound + .credits__icon::before { content: '·'; margin: 0 .7em; }
/* "Made with ♥ and Claude": the heart beats when you point at the line */
.made { display: inline-flex; align-items: center; gap: 6px; }
.made__heart { color: var(--pk-accent); }
.made__claude { display: block; }
.made:hover .made__heart { animation: pk-beat .9s ease-in-out infinite; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.replay { padding: 0; border: 0; background: none; cursor: pointer; font-family: var(--font-mono); font-size: 11px; color: rgba(var(--pk-ink-rgb), .58); }
.replay:hover { color: var(--pk-accent); }

/* ── enter screen ─────────────────────────────────────────────────────── */

/* over the starfield until the visitor enters; the page behind is hidden by data-pk-intro meanwhile */
.gate { display: none; }
html[data-pk-gate] .gate {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: 24px; text-align: center;
  transition: opacity .5s ease;
}
.gate:focus { outline: none; }  /* focused only so screen readers announce it; the buttons show their own focus */
html[data-pk-gate] .gate.is-leaving { opacity: 0; pointer-events: none; transition: opacity .4s ease .1s; }
.gate__inner { position: relative; display: flex; flex-direction: column; align-items: center; gap: 16px; }
.gate__inner > :not(.gate__ring, .gate__sat) { position: relative; z-index: 1; }
html .gate.is-leaving :is(.gate__inner) { opacity: 0; transform: scale(.97); transition: opacity .3s ease, transform .3s ease; }
/* the greeting types itself (enter-gate.js); then a second line types, deletes and retypes through a few lines */
.gate__hello { min-height: 1.1em; font-size: clamp(38px, 6.6vw, 74px); line-height: 1.1; font-weight: 600; letter-spacing: -0.035em; text-shadow: 0 0 48px rgba(var(--pk-accent-rgb), .16); }
.gate__caret {
  display: inline-block; width: .07em; height: .86em; margin-left: .07em; vertical-align: -0.06em;
  background: var(--pk-accent); box-shadow: 0 0 12px rgba(var(--pk-accent-rgb), .7); animation: pk-caret 1.05s steps(1) infinite;
}
.gate.is-typed .gate__hello .gate__caret { display: none; }  /* the caret moves down to the second line */
.gate__caret--line { display: none; width: .09em; }
.gate.is-typed .gate__caret--line { display: inline-block; }
.gate__lines { min-height: 1.5em; font-size: clamp(17px, 2.2vw, 23px); font-weight: 500; color: rgba(var(--pk-ink-rgb), .78); }
.gate__actions { display: flex; flex-direction: column; align-items: center; gap: 18px; margin-top: 30px; opacity: 0; transform: translateY(12px); transition: opacity .7s ease .3s, transform .7s cubic-bezier(.2, .7, .2, 1) .3s; }
.gate.is-typed .gate__actions { opacity: 1; transform: none; }
.gate__enter { text-transform: none; letter-spacing: .02em; font-size: 13.5px; font-weight: 500; }
.gate__enter strong { font-weight: 700; color: var(--pk-accent); transition: color .3s ease; }
.gate__enter:hover strong, .gate__enter:focus-visible strong { color: currentColor; }
.gate__quiet {
  padding: 3px 1px; border: 0; border-bottom: 1px solid rgba(var(--pk-ink-rgb), .22); background: none; cursor: pointer;
  font: inherit; font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .06em; color: rgba(var(--pk-ink-rgb), .55);
  transition: color .25s ease, border-color .25s ease;
}
.gate__quiet:hover, .gate__quiet:focus-visible { color: var(--pk-accent); border-color: var(--pk-accent); }

/* the orbit: a faint tilted ellipse around the greeting, and the satellite riding it */
.gate__ring {
  --orbit-a: min(430px, 44vw); --orbit-b: calc(var(--orbit-a) * .34);
  position: absolute; left: 50%; top: 42%; width: calc(var(--orbit-a) * 2); height: calc(var(--orbit-b) * 2);
  border: 1px dashed rgba(var(--pk-ink-rgb), .13); border-radius: 50%;
  transform: translate(-50%, -50%) rotate(-12deg); pointer-events: none;
}
.gate__sat { position: absolute; left: 50%; top: 42%; width: 34px; height: 21px; margin: -10.5px 0 0 -17px; overflow: visible; pointer-events: none; will-change: transform; }
.gate__sat-panel { fill: rgba(var(--pk-accent-rgb), .28); stroke: var(--pk-accent); stroke-width: 1; }
.gate__sat-grid { fill: none; stroke: rgba(var(--pk-accent-rgb), .55); stroke-width: .6; }
.gate__sat-arm { fill: none; stroke: rgba(var(--pk-ink-rgb), .7); stroke-width: 1.2; stroke-linecap: round; }
.gate__sat-body { fill: #d9d4cb; stroke: rgba(var(--pk-ink-rgb), .9); stroke-width: .8; }
.gate__sat-light { fill: #ff6b5a; animation: pk-blink 1.6s steps(1) infinite; filter: drop-shadow(0 0 3px #ff6b5a); }

/* ── 404 page ─────────────────────────────────────────────────────────── */

.lost { display: grid; place-items: center; min-height: 100vh; padding: 24px; text-align: center; }
.lost__inner { display: flex; flex-direction: column; align-items: center; gap: 16px; }
.lost__code { font-family: var(--font-mono); font-size: 11px; letter-spacing: .2em; text-transform: uppercase; color: var(--pk-accent); }
.lost__title { font-size: clamp(30px, 5vw, 52px); font-weight: 600; letter-spacing: -0.03em; }
.lost__text { color: rgba(var(--pk-ink-rgb), .7); }
.lost__home { margin-top: 12px; padding: 11px 20px; font-size: 12.5px; }
.lost__credits { position: fixed; left: 0; right: 0; bottom: 18px; font-family: var(--font-mono); font-size: 11px; }

/* ── email note ───────────────────────────────────────────────────────── */

.toast {
  position: fixed; left: 50%; bottom: 26px; z-index: 45; display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px;
  max-width: calc(100vw - 32px); padding: 12px 14px 12px 18px; border-radius: 14px;
  border: 1px solid rgba(var(--pk-accent-rgb), .35); background: rgba(var(--pk-bg2-rgb), .96);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .5), 0 0 30px rgba(var(--pk-accent-rgb), .12);
  font-family: var(--font-mono); font-size: 12px; color: var(--pk-ink);
  opacity: 0; transform: translate(-50%, 12px); transition: opacity .25s ease, transform .3s cubic-bezier(.2, .7, .2, 1);
}
.toast[hidden] { display: none; }
.toast.is-on { opacity: 1; transform: translate(-50%, 0); }
.toast__status { color: rgba(var(--pk-ink-rgb), .6); }
.toast__status.is-copied { color: var(--pk-ok-text); }
.toast__status.is-copied::before { content: "\2713  "; }
.toast__address { user-select: all; color: rgba(var(--pk-ink-rgb), .85); }
.toast__link { color: var(--pk-accent); border-bottom: 1px solid rgba(var(--pk-accent-rgb), .35); }
.toast__link:hover { border-color: var(--pk-accent); }
.toast__close { margin-left: 2px; padding: 0 4px; border: 0; background: none; color: rgba(var(--pk-ink-rgb), .6); font: inherit; font-size: 16px; cursor: pointer; }
.toast__close:hover { color: var(--pk-ink); }
@media (max-width: 620px) { .toast { bottom: 70px; } }  /* above the phone dock */

/* ── floating dock + gravity hint ─────────────────────────────────────── */

/* round icon buttons; each label slides out to the left on hover or focus. Hidden while the contact links are on screen. */
.dock {
  position: fixed; right: 22px; bottom: 22px; z-index: 30; display: flex; flex-direction: column; align-items: flex-end; gap: 9px;
  transition: opacity .5s ease, visibility 0s;
}
.dock .pill-link {
  position: relative; justify-content: center; width: 40px; height: 40px; padding: 0;
  background: rgba(var(--pk-bg-rgb), .72); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
.dock .pill-link--primary { background: var(--pk-accent); }  /* beats the translucent dock fill above */
.dock svg { width: 16px; height: 16px; }
.dock__label {
  position: absolute; right: calc(100% + 10px); top: 50%; padding: 6px 12px; border-radius: 999px; white-space: nowrap;
  border: 1px solid rgba(var(--pk-ink-rgb), .14); background: rgba(var(--pk-bg-rgb), .9); color: var(--pk-ink);
  font-size: 11px; font-weight: 400; letter-spacing: .06em;
  opacity: 0; transform: translate(6px, -50%); pointer-events: none; transition: opacity .2s ease, transform .2s ease;
}
.dock .pill-link:hover .dock__label, .dock .pill-link:focus-visible .dock__label { opacity: 1; transform: translate(0, -50%); }
/* touch screens have no hover to reveal a label, so it stays for screen readers only */
@media (hover: none) {
  .dock__label { position: absolute; width: 1px; height: 1px; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); }
}

.sky-hint {
  position: fixed; left: 22px; bottom: 22px; z-index: 30; pointer-events: none;
  display: inline-flex; align-items: center; gap: 9px; padding: 9px 15px; border-radius: 999px;
  border: 1px solid rgba(var(--pk-ink-rgb), .12); background: rgba(var(--pk-bg-rgb), .6);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .06em; color: rgba(var(--pk-ink-rgb), .55);
  transition: opacity .6s ease, visibility 0s;
}
html:not(.js) .sky-hint { display: none; }
/* main.js sets data-away: the hint only shows on the hero, the dock steps aside at the contact links */
.dock[data-away], .sky-hint[data-away] { opacity: 0; visibility: hidden; transition: opacity .4s ease, visibility 0s linear .4s; }
@media (hover: none) { .sky-hint { display: none; } }

/* ── the spacecraft cursor (assets/js/ship-cursor.js) ───────────────────── */

/* the page's own cursor goes only once the ship is flying, and only for a mouse or trackpad */
@media (hover: hover) and (pointer: fine) {
  html[data-pk-ship], html[data-pk-ship] *, html[data-pk-ship] ::backdrop { cursor: none !important; }
}
/* a manual popover, so it sits in the top layer; its own box is a point at the hotspot, which it turns about */
.ship {
  position: fixed; inset: 0 auto auto 0; width: 0; height: 0; margin: 0; padding: 0; border: 0;
  overflow: visible; background: none; color: inherit; pointer-events: none;
  opacity: 0; transition: opacity .2s ease; will-change: transform;
}
.ship.is-on { opacity: 1; }
/* the craft turns about the hotspot; the black hole beside it doesn't turn */
.ship__craft { position: absolute; left: 0; top: 0; width: 0; height: 0; }
/* sky.js draws the black hole here while the gravity well is held, above the page so nothing on it hides the hole */
.ship__hole { position: absolute; left: -100px; top: -100px; width: 200px; height: 200px; }
/* the drawing's nose is its right edge, centred on the hotspot */
.ship__body {
  position: absolute; right: 0; top: -9.6px; overflow: visible;
  transform-origin: 100% 50%;
  filter: drop-shadow(0 0 3px rgba(var(--pk-accent-rgb), .45)) drop-shadow(0 1px 2px rgba(0, 0, 0, .6));
  transition: transform .5s cubic-bezier(.3, 1.6, .5, 1) .1s, opacity .25s ease .1s;
}
.ship.is-press .ship__body { transform: scale(.82); transition-duration: .12s; transition-delay: 0s; }
/* held in the gravity well: it spirals down into the black hole, and flies back out on release */
.ship.is-swallowed .ship__body {
  transform: rotate(-320deg) scale(0); opacity: 0;
  transition: transform .42s cubic-bezier(.55, 0, .85, .35), opacity .3s ease .12s;
}
/* the engine: a longer burn the faster it flies, with a flicker */
.ship__flame {
  transform-box: fill-box; transform-origin: 100% 50%;
  transform: scaleX(calc(.35 + var(--thrust, 0) * 1.15));
}
.ship__flame path { transform-box: fill-box; transform-origin: 100% 50%; animation: ship-flicker .09s steps(2) infinite alternate; }
/* over anything clickable, a ring lights at the nose */
.ship__ring {
  position: absolute; left: -10px; top: -10px; width: 20px; height: 20px; border-radius: 999px;
  border: 1.5px solid var(--pk-accent); box-shadow: 0 0 10px rgba(var(--pk-accent-rgb), .55);
  opacity: 0; transform: scale(.3); transition: opacity .2s ease, transform .25s cubic-bezier(.3, 1.6, .5, 1);
}
.ship.is-target .ship__ring { opacity: 1; transform: scale(1); }
.ship.is-swallowed .ship__ring { opacity: 0; }
@keyframes ship-flicker { to { transform: scale(.84, .78); } }

/* ── large screens ────────────────────────────────────────────────────── */

/* Past about 1290px the page widens with the window instead of stopping at 1080px (--page-max). The extra room goes
   to side by side layouts; paragraphs keep a comfortable line length rather than stretching across it. */
@media (min-width: 1400px) {
  .section__grid { grid-template-columns: minmax(0, 200px) minmax(0, 1fr); gap: 64px; }
  .about__body { max-width: 34em; }
  /* stack: the groups in two columns, each label over its chips */
  .stack { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 30px 56px; }
  .stack__row { grid-template-columns: minmax(0, 1fr); align-content: start; gap: 12px; }
  .stack__label { padding-top: 0; }
  /* experience: dates, role and place on the left, what happened on the right */
  .timeline__body { display: grid; grid-template-columns: minmax(0, 300px) minmax(0, 1fr); grid-template-rows: auto 1fr; column-gap: 48px; }
  .timeline__head { grid-row: 1 / span 2; }
  .timeline__note, .timeline__points { grid-column: 2; max-width: 40em; }
  .timeline__points { align-self: start; }
  .contact__lede { max-width: 17em; }
}

/* big monitors: everything a size up, and About splits into the headline beside the text */
@media (min-width: 1700px) {
  :root { --page-pad: 40px; }
  .site-header__inner { padding-block: 16px; }
  .brand { font-size: 13px; }
  .site-nav { gap: 28px; }
  .site-nav a { font-size: 12px; }
  .section { padding: 120px 0; }
  .section__grid { grid-template-columns: minmax(0, 240px) minmax(0, 1fr); gap: 80px; }
  .section__label { font-size: 12px; }
  .headline { max-width: 17em; font-size: clamp(44px, 2.7vw, 62px); }

  .hero { gap: 40px; }
  .avail { font-size: 14.5px; }
  .hero__coords { font-size: 12px; }
  .hero__name { font-size: clamp(112px, 6.6vw, 168px); }
  .hero__role { margin-top: -14px; font-size: clamp(27px, 1.55vw, 36px); }
  .pk-orb-wrap { --orb: clamp(330px, 17.5vw, 380px); }

  .about { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); column-gap: 72px; align-items: start; }
  .about .headline { grid-row: 1 / span 2; margin: 0; }
  .about__body, .about__note { grid-column: 2; }
  .about__body { font-size: clamp(26px, 1.45vw, 31px); }
  .about__note { font-size: 14px; }

  .stack { gap: 34px 72px; }
  .stack__label { font-size: 12px; }
  .chips { gap: 10px; }
  .chip { gap: 10px; padding: 9px 16px 9px 11px; font-size: 14.5px; }
  .chip img { width: 17px; height: 17px; }

  .pcards { --card: clamp(220px, min((100vw - 2 * max(var(--page-pad), var(--dock-lane))) / 3.76, 100vh - 370px), 520px); }

  .timeline__body { grid-template-columns: minmax(0, 340px) minmax(0, 1fr); column-gap: 64px; }
  .timeline__dates { font-size: 12px; }
  .timeline__place { font-size: 11.5px; }
  .timeline__role { font-size: 24px; }
  .timeline__org { font-size: 15.5px; }
  .timeline__note { font-size: 16.5px; }
  .timeline__points li { font-size: 16px; }

  .contact__lede { max-width: 20em; font-size: clamp(38px, 2.2vw, 48px); }
  .contact__links .pill-link, .contact__links .btn-comet { font-size: 13.5px; }
  .site-footer { font-size: 12px; }
  .replay { font-size: 12px; }
}

/* ── small screens ────────────────────────────────────────────────────── */

/* tablets: four figures in a row get cramped beside the section label */
@media (max-width: 900px) {
  .metrics { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .metric:last-child:nth-child(odd) { grid-column: 1 / -1; }  /* three figures: the last one takes the full row */
}

@media (max-width: 760px) {
  :root { --page-pad: 20px; }
  .section { padding: 72px 0; }
  .section__grid { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .stack__row { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .stack__label { padding-top: 0; }
  .callout { flex-direction: column; gap: 8px; }
  .pdialog__panel { padding: 30px 22px 34px; }
  .project { padding: 44px 0; }
  .project__head { grid-template-columns: auto minmax(0, 1fr); }
  .project__links { grid-column: 2; }
  .gallery { grid-template-columns: minmax(0, 1fr); }
  .seasons { grid-template-columns: minmax(0, 1fr); }
  .gallery > :first-child:not(:only-child) { grid-row: auto; aspect-ratio: 4 / 3; }
}

@media (max-width: 620px) {
  .site-header__inner { gap: 16px; padding-block: 12px; }
  .site-nav { flex-wrap: nowrap; gap: 14px; overflow-x: auto; scrollbar-width: none; }
  .site-nav::-webkit-scrollbar { display: none; }
  .hero { padding-top: 120px; }
  .avail__more { display: none; }
  /* phones: the dock becomes one short row floating over the text instead of a column taking a lane */
  :root { --dock-lane: 0px; }
  .dock { right: 14px; bottom: 14px; flex-direction: row; }
  .dock .pill-link { width: 38px; height: 38px; }
  .section--contact { padding-bottom: 76px; }  /* the footer ends clear of the dock */
}

/* ── motion ───────────────────────────────────────────────────────────── */

@keyframes pk-rise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
@keyframes pk-twinkle {
  0%, 100% { opacity: .55; transform: scale(.8) rotate(0deg); }
  50% { opacity: 1; transform: scale(1.05) rotate(45deg); }
}
@keyframes pk-burst { 0% { opacity: .9; transform: scale(.3); } 100% { opacity: 0; transform: scale(2.6); } }
@keyframes pk-ping { 0% { transform: scale(.45); opacity: .95; } 100% { transform: scale(2.1); opacity: 0; } }
@keyframes pk-shimmer { to { background-position: 200% 0; --pk-sweep: 1; } }
@keyframes pk-beat { 0%, 100% { transform: scale(1); } 15% { transform: scale(1.25); } 30% { transform: scale(.95); } 45% { transform: scale(1.15); } }
@keyframes pk-caret { 50% { opacity: 0; } }
@keyframes pk-blink { 0%, 70% { opacity: 1; } 71%, 100% { opacity: .15; } }
@keyframes pk-card-rise { from { opacity: 0; transform: translateY(70px) rotate(5deg); } to { opacity: 1; transform: none; } }
@keyframes pk-dialog-in { from { opacity: 0; transform: translateY(16px) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes pk-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes pk-head-in { from { opacity: 0; transform: translateY(24px); filter: blur(5px); } to { opacity: 1; transform: none; filter: none; } }

/* each dash's head runs from the path's start round to the start again */
@keyframes comet-orbit {
  from { stroke-dashoffset: var(--len); }
  to { stroke-dashoffset: calc(var(--len) - var(--perimeter)); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .tw, .avail__ring, .shimmer, .headline, .decision__body, .timeline__star svg, .timeline__ring { animation: none !important; }
  .timeline__body, .timeline__fill { transition: none; }
  .sky-hint, .replay, .credits__sound { display: none; }  /* no gravity well or warp intro, so no black hole sound either */
  .credits__icon::before { content: none !important; }
  .comet { display: none; }  /* the outline pill stays, without the orbit */
  .pcard, .pcard__go { transition: none; }
  .toast { transition: none; }
  .made:hover .made__heart { animation: none; }
  .ship__flame path { animation: none; }
  .pcard:hover, .pcard:focus-visible { transform: rotate(var(--tilt, 0deg)); }
  .pdialog[open], .pdialog[open]::backdrop { animation: none; }
}
