:root {
  color-scheme: dark;
  --bg: #0d0c0b;
  --ink: #ebe6dc;
  --soft: #7d776c;
  --rule: #2a2724;
  --mono: 'JetBrains Mono', ui-monospace, monospace;
  --gutter: clamp(16px, 4vw, 48px);
  --ease: cubic-bezier(.65, 0, .25, 1);
  --ease-out: cubic-bezier(.33, 0, .2, 1);
  --cap: 64px;   /* the gap above each picture, where the title shows */
}

* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.6 var(--mono);
  -webkit-font-smoothing: antialiased;
  transition: background-color .8s var(--ease), color .8s var(--ease);
}
a { color: inherit; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

.top {
  position: sticky; top: 0; z-index: 10;
  display: flex; justify-content: center; align-items: baseline; gap: 16px;
  padding: 20px var(--gutter);
  background: var(--bg);
  transition: background-color .8s var(--ease);
}
.name { font-weight: 600; }
.intro { max-width: 640px; margin: 0 auto; padding: 5vh var(--gutter) 0; text-align: center; }
.intro p:first-child { font-weight: 600; margin-bottom: 8px; }
.intro p + p { color: var(--soft); }
.sort { position: relative; z-index: 5; padding: 7vh var(--gutter) 0; text-align: center; }
.sort-btn {
  padding: 6px 12px; border: 1px solid var(--rule); border-radius: 999px;
  transition: border-color .2s;
}
.sort-btn:hover, .sort-btn[aria-expanded="true"] { border-color: var(--ink); }
.caret { color: var(--soft); }
.sort-menu {
  position: absolute; top: calc(100% + 6px); left: 50%; transform: translateX(-50%);
  list-style: none; min-width: 180px; padding: 6px 0;
  background: var(--bg); border: 1px solid var(--ink);
}
.sort-menu button { display: block; width: 100%; padding: 6px 14px; text-align: left; color: var(--soft); }
.sort-menu button:hover { color: var(--ink); }
.sort-menu button[aria-checked="true"] { color: var(--ink); }
.sort-menu button[aria-checked="true"]::before { content: '● '; font-size: 9px; vertical-align: 2px; }

/* every picture is a full-width background · the section title sits above it, on the lifeline */
.work { position: relative; }
.lifeline { position: absolute; inset: 0; pointer-events: none; transition: opacity .3s; }
.lifeline.is-moving { opacity: 0; transition: none; }
.lifeline span { position: absolute; left: 50%; width: 1px; }
.ll-track { background: var(--rule); }
.ll-fill { background: var(--ink); }
.ll-future { width: 0 !important; border-left: 1px dashed var(--soft); }
.dot { display: block; width: 9px; height: 9px; border-radius: 50%; background: var(--ink); margin: 0 auto 10px; }
.dot.is-birth { position: relative; background: none; width: 15px; height: 15px; }
.dot.is-birth::after { content: '✱'; position: absolute; inset: 0; display: grid; place-items: center; font-size: 20px; line-height: 1; color: var(--ink); }
.dot.is-future { background: var(--bg); border: 1px solid var(--soft); }
body[data-sort="recommended"] .lifeline span { display: none; }
/* recommended · the scribble in place of the straight line (main.js drawKnot) */
.ll-knot { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.ll-knot path { fill: none; stroke: var(--soft); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 1; stroke-dashoffset: 1; opacity: 0; transition: opacity .3s, stroke-dashoffset 0s .3s; }
/* it draws itself in down the page once the sections have landed */
body[data-sort="recommended"] .ll-knot path { opacity: 1; stroke-dashoffset: 0; transition: stroke-dashoffset 3s cubic-bezier(.45, 0, .3, 1) .7s; }
/* death · the end of the line, no picture under it */
.is-end .cap { padding-bottom: 40px; }
/* by birth · room under death, so it can still scroll up to the middle of the screen */
/* room under the footer so its contact link can scroll up to the middle of the screen */

/* by death (and recommended) · death comes first, and coming soon sits right under it (no gap, no second dot) */
body:is([data-sort="death"], [data-sort="recommended"]) .is-end .cap { height: auto; padding: 48px 0 2px; }
body:is([data-sort="death"], [data-sort="recommended"]) .is-end + .entry .cap { height: auto; }
body:is([data-sort="death"], [data-sort="recommended"]) .is-end + .entry .dot { visibility: hidden; height: 0; margin: 0; }

.entry {
  position: relative; z-index: 1;   /* above the lifeline · it shows in the gaps */
  scroll-margin-top: calc(var(--top, 62px) + var(--bar, 0px));
  text-align: center;
  transition: transform .7s var(--ease);
}
.cap { height: var(--cap); display: flex; flex-direction: column; align-items: center; justify-content: flex-end; padding-bottom: 14px; }
/* the title sits on a patch of background so the line passes behind it */
.cap .stage { padding: 2px 12px; background: var(--bg); color: var(--ink); font-size: 14px; font-weight: 600; }
.cap .stage a { text-decoration: none; }
.cap .stage a:hover { text-decoration: underline; text-underline-offset: 4px; }
.thumb { position: relative; display: block; aspect-ratio: 16 / 9; overflow: hidden; background: #000; }
/* title + picture together fill one screen under the header */
.entry .thumb { height: calc(100svh - var(--top, 62px) - var(--bar, 0px) - var(--cap)); aspect-ratio: auto; text-decoration: none; }
.thumb img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .8s var(--ease), opacity .3s var(--ease-out); }
.entry .thumb:hover img, .entry .thumb:hover video { transform: scale(1.015); }
.thumb video.loop { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .8s var(--ease); }
.thumb video.hover {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity .5s ease, transform .8s var(--ease);
}
.thumb.is-playing video.hover { opacity: 1; }
.thumb-empty { display: block; width: 100%; height: 100%; border: 1px dashed var(--rule); background: var(--bg); }

/* hover · like ksshanti.wiki: the picture fades back onto its own color, a big bold title on top */
.entry .thumb { background: var(--tint, #000); }
.entry .thumb:is(:hover, :focus-visible, .is-active) img { opacity: .7; }
.entry .thumb.is-playing img { opacity: 0; }
.entry .thumb.is-playing:is(:hover, :focus-visible, .is-active) video.hover { opacity: .7; }
.entry .thumb.is-light:is(:hover, :focus-visible, .is-active) img,
.entry .thumb.is-light.is-playing:is(:hover, :focus-visible, .is-active) video.hover { opacity: .35; }
.entry .thumb.is-light.is-playing img { opacity: 0; }
/* no text over it → the picture doesn't dim, it only zooms a little */
.entry .thumb.no-motto:is(:hover, :focus-visible, .is-active) img:not(.slide) { opacity: 1; }
/* slides stack over the first picture, each cutting in on its turn (no fade) */
.thumb img.slide { position: absolute; inset: 0; transition: transform .8s var(--ease); }
.entry .thumb img.slide:not(.is-on) { opacity: 0; }
/* while flipping: hard cuts, and only the picture on top shows (no see-through, no fade back) */
.entry .thumb.is-flipping img { transition: transform .8s var(--ease); }
.entry .thumb.is-slid img:not(.is-on) { opacity: 0; }
/* same on a full page's top picture */
.hero img.slide:not(.is-on), .hero.is-slid img:not(.is-on) { opacity: 0; }
.hero.is-flipping img { transition: transform .8s var(--ease); }
.overlay {
  position: absolute; inset: 0; z-index: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 24px var(--gutter); text-align: center;
  opacity: 0; transition: opacity .3s var(--ease-out);
}
.thumb:hover .overlay, .thumb:focus-visible .overlay, .thumb.is-active .overlay,
.no-thumb .overlay { opacity: 1; }
.overlay .motto {
  max-width: 18em; color: #fff;
  font: 700 clamp(28px, 4.2vw, 68px)/1.15 'Inter', Helvetica, Arial, sans-serif;
  letter-spacing: -.01em;
  text-shadow: 0 1px 24px rgba(0, 0, 0, .25);
}
/* a fire-colored title instead (mottoTone: 'fire' in work.js) · the picture dims as usual, so the yellow-orange reads on it */
.thumb.is-fire-motto .overlay .motto { color: #ffb627; text-shadow: 0 2px 18px rgba(0, 0, 0, .55); }
.stage { color: var(--soft); }
.title { font-size: 14px; font-weight: 600; }
.body p { margin-bottom: 10px; }

.title a { text-decoration: none; }
.title a:hover { text-decoration: underline; text-underline-offset: 4px; }
.more { display: inline-block; margin-top: 8px; color: var(--soft); text-decoration: none; }
.more:hover { color: var(--ink); }

/* full page */
.name, .back { text-decoration: none; }
.back { color: var(--soft); }
.back:hover { color: var(--ink); }
/* centered, like the main page */
.project { max-width: 1040px; margin: 0 auto; padding: 8vh var(--gutter) 64px; text-align: center; }

.hero { margin-bottom: 32px; }
.credit { margin: -24px 0 24px; font-size: 11px; color: var(--soft); }
.credit a { text-decoration: none; }
.credit a:hover { color: var(--ink); }
.project .title { font-size: clamp(24px, 4vw, 38px); line-height: 1.15; margin: 8px 0 20px; }

/* the projects inside a section */
.part { margin-top: 56px; padding-top: 28px; border-top: 1px solid var(--rule); }
.part-title { font-size: clamp(20px, 3vw, 28px); line-height: 1.2; }
/* under a page title, a project's name is a smaller heading */
.part-title.is-label { font-size: 18px; font-weight: 600; line-height: 1.3; color: var(--ink); }
.tagline { color: var(--soft); margin: 4px 0 20px; }
.part .body { margin-top: 16px; }
/* no picture and no page title → the first project starts the page, like the ARM page (no rule above it, the big title size) */
.no-hero .body:empty + .part { margin-top: 0; padding-top: 0; border-top: 0; }
.no-hero .body:empty + .part > h1.part-title { font-size: clamp(24px, 4vw, 38px); line-height: 1.15; margin: 8px 0 20px; }
.no-hero .body:empty + .part > h1.part-title + .body { margin-top: 0; }
.stream { position: relative; aspect-ratio: 16 / 9; background: #000; margin: 8px 0 20px; }
.stream.is-tall { aspect-ratio: 9 / 16; width: min(100%, calc(80svh * 9 / 16)); margin-left: auto; margin-right: auto; }
.stream iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
/* the teaser has a thin white line down its left edge · zoom in a hair so the frame crops it off */
.stream.is-tall { overflow: hidden; }
.stream.is-tall iframe { transform: scale(1.025); }

/* a warning label at the bottom of a full page, like the one on the products */
.warning-label {
  display: inline-block; margin-top: 56px; padding: 18px 28px;
  background: #fff; color: #000; border: 6px solid #000; outline: 2px solid #fff;
  font: 700 clamp(20px, 3vw, 30px)/1.2 'Inter', Helvetica, Arial, sans-serif;
}

/* the ARM participants */
.shown { max-width: 720px; margin: 32px auto 0; font-size: 16px; }
.shown b { font-weight: 700; color: #ffb627; }
/* the ARM site's own globe section, edge to edge, with the colors and type it expects */
.arm-globe {
  --ink: #f4efe9; --ink-dim: #b3a89c; --ember: #ff6a2b; --flame: #ffc233;
  width: 100vw; margin: 32px 0 0 calc(50% - 50vw); text-align: left; line-height: 1.55; font-family: 'Inter', system-ui, sans-serif;
}
/* fits under this site's header · the panels start just below it */
.arm-globe #globe-sec { height: calc(100svh - 62px); --g-top: 16px; }
/* two touches from the ARM site's other stylesheet */
.arm-globe .v2-log-note { margin: -4px 0 12px; font-size: 12px; line-height: 1.45; color: var(--ink-dim); }
.arm-globe .g-counters { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.arm-globe .g-counters dd { white-space: normal; overflow-wrap: anywhere; }
.arm-globe[hidden] { display: none; }

/* awards · an "achievement unlocked" toast, like a game */
.awards { margin: 40px 0 14px; font-size: 18px; font-weight: 600; line-height: 1.3; color: var(--ink); }
.achievement {
  display: flex; align-items: center; gap: 16px; max-width: 520px;
  padding: 12px 22px 12px 12px; border-radius: 999px;
  background: #1a1816; border: 1px solid var(--rule);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .4);
}
.achievement + .achievement { margin-top: 10px; }
.badge {
  flex: none; display: grid; place-items: center; width: 52px; height: 52px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #f6d77a, #b8860b 70%); color: #2a1d00;
}
.badge svg { width: 28px; height: 28px; }
.ach-text { display: flex; flex-direction: column; line-height: 1.35; }
.ach-name { font-size: 16px; font-weight: 600; }
.ach-detail { font-size: 13px; color: var(--ink); opacity: .75; }

.media { margin-top: 20px; display: grid; gap: 12px; }
.media figure { margin: 0; }
.media img, .media video { width: 100%; display: block; }
.media figcaption { margin-top: 6px; font-size: 12px; color: var(--soft); }
.media .is-wide { grid-column: 1 / -1; }
.media-grid.is-tall { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.media .tile-link { display: block; text-decoration: none; }
.media .tile-link img { transition: opacity .2s; }
.media .tile-link:hover img { opacity: .8; }
.media .tile-link:hover figcaption { color: var(--ink); }
.media-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 400px), 1fr)); gap: 16px; margin-top: 32px; }
/* small tiles · links to related pages (the other childhood classics) */
.media-grid.is-small { grid-template-columns: repeat(auto-fit, 220px); justify-content: center; gap: 12px; }
@media (max-width: 640px) { .media-grid.is-small { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* pictures and looping clips open bigger on click */
.media .zoom { cursor: zoom-in; }
.lightbox {
  position: fixed; inset: 0; z-index: 50;
  display: grid; place-items: center; padding: 24px;
  background: rgba(13, 12, 11, .94); cursor: zoom-out;
}
.lightbox img, .lightbox video { max-width: 100%; max-height: calc(100svh - 48px); object-fit: contain; }
.project .body { max-width: 720px; margin-left: auto; margin-right: auto; }
.project .achievement { margin-left: auto; margin-right: auto; text-align: left; }
.slot .frame { aspect-ratio: 16 / 9; border: 1px dashed var(--rule); }

.foot { margin: 0 var(--gutter); padding: 40px 0 56px; border-top: 1px solid var(--rule); text-align: center; }

/* the death page · the casket on one side, who I was on the other */
.death { display: grid; grid-template-columns: 1fr 1fr; min-height: calc(100svh - 62px); }
.death-frame { position: relative; min-height: 0; }
.death-pic { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.death-text { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 48px var(--gutter); text-align: center; }
.death-text h1 { font-size: clamp(24px, 4vw, 38px); line-height: 1.15; margin-bottom: 28px; }
.death-text .traits { margin-bottom: 18px; }
.death-text .good { font-weight: 600; margin-bottom: 32px; }
.death-text .bio { max-width: 30em; margin-bottom: 36px; color: var(--soft); }
.death-text .bio p + p { margin-top: 10px; }
.death-text a { text-underline-offset: 4px; }

/* phones · a full-height picture would crop too much, so each one keeps its 16:9 frame */
@media (max-width: 640px) {
  :root { --cap: 84px; }
  .entry .thumb { height: auto; aspect-ratio: 16 / 9; }
  .media-grid.is-tall { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .death { grid-template-columns: 1fr; min-height: 0; }
  .death-frame { aspect-ratio: 4 / 3; }
  /* a tile can go first on a phone (phoneFirst in work.js) */
  .media .is-phone-first { order: -1; }
}

.no-anim, .no-anim * { transition: none !important; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; }
}

/* the bottom of a full page · birth to death, left to right, this page on the line */
.lifebar { max-width: 720px; margin: 0 auto; padding: 0 24px; }   /* room for the Birth / Death labels at the ends */
.lb-track { position: relative; height: 15px; margin: 34px 0 30px; }
.lb-line { position: absolute; top: 7px; left: 0; height: 1px; background: var(--ink); }
.lb-line.is-future { right: 0; height: 0; background: none; border-top: 1px dashed var(--soft); }
/* the dots, labels and line slide when the sort changes */
.lb-line.is-lived, .lb-here, .lb-end { transition: left .7s var(--ease), width .7s var(--ease), opacity .3s; }
.lb-track .is-off { opacity: 0; pointer-events: none; }
.lb-dot { position: absolute; top: 3px; width: 9px; height: 9px; margin-left: -4.5px; border-radius: 50%; background: var(--ink); transition: transform .2s var(--ease-out), left .7s var(--ease), opacity .3s; }
.lb-dot:hover { transform: scale(1.6); }
.lb-dot.is-future { background: var(--bg); border: 1px solid var(--soft); }
.lb-dot.is-birth { top: 0; width: 15px; height: 15px; margin-left: -7.5px; background: none; }
.lb-dot.is-birth::after { content: ''; position: absolute; inset: 0; background: var(--ink); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cg stroke='%23000' stroke-width='3.4' stroke-linecap='round'%3E%3Cpath d='M10 2.5v15M3.5 6.25l13 7.5M3.5 13.75l13-7.5'/%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cg stroke='%23000' stroke-width='3.4' stroke-linecap='round'%3E%3Cpath d='M10 2.5v15M3.5 6.25l13 7.5M3.5 13.75l13-7.5'/%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat; }   /* drawn, not typed, so it sits dead center on the line like the dots */
.lb-dot.is-here { box-shadow: 0 0 0 4px var(--bg), 0 0 0 5px var(--ink); }
.lb-here, .lb-end { position: absolute; transform: translateX(-50%); white-space: nowrap; font-size: 12px; }
.lb-here { bottom: calc(100% + 10px); color: var(--ink); font-weight: 600; }
.lb-dot.is-birth.is-here { box-shadow: none; }
.lb-here.is-peek { transition: left .25s var(--ease-out); }   /* hovering another dot · its title, quick */
.lb-end { top: calc(100% + 8px); color: var(--soft); text-decoration: none; }
a.lb-end:hover { color: var(--ink); }
.lb-contact { display: inline-block; margin-top: 8px; text-underline-offset: 4px; }
/* the same line under the sort on the main page (test) */
/* sticks under the name once scrolled past · its dark band runs the full width so the pictures slide under it */
.lifebar.is-top { position: sticky; top: var(--top, 62px); z-index: 4; margin-top: 4vh; padding-top: 2px; padding-bottom: 2px;
  background: var(--bg); box-shadow: 0 0 0 100vmax var(--bg); clip-path: inset(0 -100vmax); }
.lifebar.is-top .lb-track { margin: 22px 0 40px; }   /* close under the name (room for the scribble's loops), more space below */
.lifebar.is-top .lb-contact { display: none; }
/* recommended · birth to death again at the bottom, the contact link under it */
.lifebar.is-foot { display: none; margin-bottom: 44px; }
.lifebar.is-foot .lb-contact { display: none; }
body[data-sort="recommended"] .lifebar.is-foot { display: block; }
/* recommended · the life line, knotted through the dots */
.lb-knot { position: absolute; left: 0; top: -22px; width: 100%; height: 60px; overflow: visible; pointer-events: none; }
.lb-knot path { fill: none; stroke: var(--ink); stroke-width: 1.75; vector-effect: non-scaling-stroke; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 1; stroke-dashoffset: 1; opacity: 0; transition: opacity .3s, stroke-dashoffset 0s .3s; }
/* switching to recommended · the scribble draws itself in, start to finish, the way it was drawn */
.lifebar.is-knotted .lb-knot path { opacity: 1; stroke-dashoffset: 0; transition: stroke-dashoffset 2s cubic-bezier(.45, 0, .3, 1) .2s; }
.lb-track .lb-line { transition: left .7s var(--ease), width .7s var(--ease), opacity .3s; }
.lifebar.is-knotted .lb-line { opacity: 0; }
/* once drawn in, solid all the way · phones can leave the dash a little short of the end (main.js) */
.ll-knot path.is-drawn, .lb-knot path.is-drawn { stroke-dasharray: none; }
/* the main page's bars · progress bars: the line sits dim and fills in as they scroll */
.lifebar.is-progress .lb-line.is-lived { background: var(--rule); }
.lb-fill { position: absolute; top: 7px; left: 0; width: 0; height: 1px; background: var(--ink); }
.lifebar.is-knotted .lb-fill { opacity: 0; }
.lb-knot path.ghost { stroke: var(--rule); stroke-dasharray: none; stroke-dashoffset: 0; transition: opacity .3s; }
.lifebar.is-knotted .lb-knot path.ghost { opacity: 1; }
/* scrolling sets how much is drawn, so no draw-in here */
.lifebar.is-scroll-knot .lb-knot path.ink, .lifebar.is-scroll-knot.is-knotted .lb-knot path.ink { transition: opacity .3s; }
/* recommended · the bar stays where it is */
body[data-sort="recommended"] .lifebar.is-top { position: relative; top: auto; margin-bottom: 36px; clip-path: none; box-shadow: none; }   /* not locked, so nothing to cut · the scribble's loops can reach above */

/* this fork · no lifeline, the title just sits above its picture */
.foot a { text-underline-offset: 4px; }
