/* Inter Variable (rsms.me), self-hosted: Latin subset, wght 400–500, opsz kept */
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 400 500; font-display: swap;
  src: url(fonts/InterVariable-latin.woff2) format("woff2");
}

/* tokens — one family, three colours, two spacing units (8 / 24) */
:root {
  color-scheme: light;   /* one palette: light only */
  --bg: #faf9f7;
  --fg: #111111;
  --fg-2: #555555;      /* body text, one step lighter than headings */
  --muted: #6b6b6b;     /* secondary labels, links at rest — 5.1:1 on the ground */
  --line: #e6e4e1;
  --tile: #ecebe8;
  --font: "Inter", -apple-system, "Segoe UI", sans-serif;
  --u: 8px;             /* minor unit */
  --U: 24px;            /* major unit */
  --pad: var(--U);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --ease-out: cubic-bezier(.23, 1, .32, 1);
  --in: 200ms;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 400 16px/24px var(--font);
  -webkit-font-smoothing: antialiased;
  font-feature-settings: "liga" 1, "calt" 1;
  overflow: hidden;
  overscroll-behavior: none;
}
a { color: inherit; text-decoration: none; }
::selection { background: #e2dfda; color: var(--fg); }
a:focus { outline: none; }
a:focus-visible { outline: 1px solid var(--fg); outline-offset: 2px; border-radius: 2px; }
b { font-weight: 500; }
.muted { color: var(--muted); }

/* ---------- phone (base) ---------- */

/* chrome: name top-left, links top-right, tabs bottom */
.corner { position: fixed; z-index: 2; display: flex; gap: var(--U); font-size: 14px; line-height: 20px; }
.tl { top: var(--pad); left: var(--pad); }
.bl { top: var(--pad); right: var(--pad); gap: calc(var(--u) * 2); }
.tr { bottom: calc(var(--u) + var(--safe-b)); left: 50%; transform: translateX(-50%); min-height: 44px; align-items: center; }
.br { display: none; }
.name { font-weight: 500; }
.bl a, nav a, .name { color: var(--muted); padding: 12px var(--u); margin: -12px calc(-1 * var(--u)); }
.name { color: var(--fg); }
nav a[aria-current] { color: var(--fg); }
@media (hover: hover) and (pointer: fine) {
  .bl a, nav a { transition: color 120ms ease; }
  .bl a:hover, nav a:hover { color: var(--fg); }
}
.indicator {
  position: absolute; bottom: -4px; left: 0; width: 1px; height: 1px; background: var(--fg);
  transform-origin: left; transform: scaleX(0);
  transition: transform 160ms var(--ease-out);   /* translate + scaleX: compositor only */
}
.clock { color: var(--muted); font-variant-numeric: tabular-nums; }
.email.copied::after { content: " · copied"; color: var(--muted); }

/* stage: one screen, panel centred between the chrome */
main {
  position: relative; z-index: 1;
  height: 100vh; height: 100svh;
  display: grid; grid-template-columns: minmax(0, 1fr); align-items: center; justify-items: center;
  padding: calc(var(--pad) + 40px) var(--pad) calc(var(--pad) + 44px + var(--safe-b));
}
.panel { width: 100%; min-width: 0; }

/* about */
.panel p { margin: 0 0 var(--U); color: var(--fg-2); text-wrap: pretty; }
.panel > :last-child { margin-bottom: 0; }
.panel p a { color: var(--fg); border-bottom: 1px solid var(--line); }
@media (hover: hover) and (pointer: fine) { .panel p a { transition: border-color 120ms ease; } .panel p a:hover { border-color: var(--fg); } }

/* about: now / before */
.work { margin: 0 0 var(--U); padding: 0; display: grid; gap: var(--U); }   /* jobs are groups: major unit between them */
.work div { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: var(--u); }
.work dt { color: var(--muted); font-size: 14px; }
.work dd { margin: 0; color: var(--fg-2); }
.work dd a { color: var(--fg); border-bottom: 1px solid var(--line); }
@media (hover: hover) and (pointer: fine) { .work dd a { transition: border-color 120ms ease; } .work dd a:hover { border-color: var(--fg); } }
.work .when { color: var(--muted); font-size: 14px; font-variant-numeric: tabular-nums; margin-left: var(--u); }
.work .what { display: block; text-wrap: pretty; }

/* projects: stage + tray. every project is one .tile; .is-stage picks the one on stage.
   nodes never move (keeps <video> playback); CSS places them, View Transitions morph the rects. */
.sheet { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--U) var(--u); }
.tile { margin: 0; min-width: 0; display: grid; gap: calc(var(--u) / 2); position: relative; }
.tile.is-stage { flex: 0 0 100%; order: 0; gap: calc(var(--u) * 2); }
.tile:not(.is-stage) { flex: 0 0 128px; order: 1; }
.media {
  display: block; position: relative; aspect-ratio: 2 / 1; border-radius: 2px; overflow: hidden;
  background: var(--tile) center / cover no-repeat;
  box-shadow: 0 0 0 1px rgba(0,0,0,.1) inset;
  view-transition-class: media;
}
.is-stage .media { border-radius: 0; margin-inline: calc(-1 * var(--pad)); view-transition-class: media stage; box-shadow: none; }   /* phone: stage bleeds edge to edge, so no outline */
.media video { display: block; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 200ms ease; }
.media video.on { opacity: 1; }
/* pause control for the loop (WCAG 2.2.2: motion over 5s gets a pause) */
.vid-toggle {
  position: absolute; bottom: var(--u); right: var(--u); z-index: 1;
  width: 28px; height: 28px; padding: 0; border: 0; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer;
  background: rgba(250, 249, 247, .85); color: var(--fg);
  box-shadow: 0 0 0 1px rgba(0,0,0,.08);
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  transition: transform 120ms var(--ease-out);
}
.vid-toggle::before { content: ""; position: absolute; inset: -8px; }   /* 44px hit area */
.vid-toggle:active { transform: scale(.96); }
.vid-toggle svg { width: 12px; height: 12px; fill: currentColor; }
.vid-toggle .i-play, .vid-toggle[aria-pressed="true"] .i-pause { display: none; }
.vid-toggle[aria-pressed="true"] .i-play { display: inline; }
.tile:not(.is-stage) .vid-toggle { display: none; }
.stage-media { position: relative; min-width: 0; }
.vid-toggle:focus-visible { outline: 1px solid var(--fg); outline-offset: 2px; }

/* press feedback on every media link: 120ms ease-out, scale .96 */
.media { transition: transform 120ms var(--ease-out); }
.media:active { transform: scale(.96); }
.tile:not(.is-stage) .media { cursor: pointer; }
.tile:not(.is-stage) .cap { display: none; }
.is-stage .label { display: none; }
.label { view-transition-class: label; font-size: 14px; line-height: 20px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cap { display: grid; gap: 0; font-size: 14px; line-height: 20px; min-width: 0; }
.is-stage .cap { view-transition-name: caption; }
.t-head { display: flex; flex-wrap: wrap; column-gap: var(--u); row-gap: 0; align-items: baseline; min-width: 0; }   /* name + meta read as one header */
.t-name { flex-basis: 100%; font-size: 16px; line-height: 24px; font-weight: 500; color: var(--fg); white-space: nowrap; }
.t-stack { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.t-links { margin-left: auto; display: flex; gap: var(--u); white-space: nowrap; }
.t-links a { color: var(--muted); padding: 12px 0; margin: -12px 0; }
@media (hover: hover) and (pointer: fine) { .t-links a { transition: color 120ms ease; } .t-links a:hover { color: var(--fg); } }
.t-desc { color: var(--fg-2); min-width: 0; font-size: 16px; line-height: 24px; margin-top: var(--u); text-wrap: pretty; }

/* swap: position + size only, 220ms ease-in-out; old/new media never crossfade; caption fades out then in */
:root { view-transition-name: none; }
::view-transition-group(*) { animation-duration: 220ms; animation-timing-function: cubic-bezier(.77, 0, .175, 1); }
::view-transition-old(.media), ::view-transition-new(.media) { animation: none; mix-blend-mode: normal; height: 100%; object-fit: cover; overflow: clip; }
::view-transition-group(.stage) { z-index: 1; }                       /* the one growing rides on top */
::view-transition-old(caption), ::view-transition-old(.label) { animation: cap-out 90ms var(--ease-out) both; }
::view-transition-new(caption), ::view-transition-new(.label) { animation: cap-in 130ms var(--ease-out) 90ms both; }
@keyframes cap-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes cap-in  { from { opacity: 0; } to { opacity: 1; } }

/* motion: the staggered entrance plays once, on first load. tab switches swap at once;
   a pointer switch gets one 150ms opacity fade, a keyboard switch gets none. */
.ready:not(.settled) .panel > :not(.sheet), .ready:not(.settled) .tile { animation: in var(--in) var(--ease-out) both; animation-delay: calc(var(--i, 0) * 20ms); }
.panel.fade { animation: fade 150ms var(--ease-out) both; }
@keyframes in   { from { opacity: 0; transform: translateY(var(--u)); } to { opacity: 1; transform: none; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

/* ---------- desktop (enhancement) ---------- */
@media (min-width: 720px) {
  :root { --pad: clamp(var(--U), 4vw, 48px); }

  /* four corners */
  .bl { top: auto; right: auto; bottom: var(--pad); left: var(--pad); gap: var(--U); }
  .tr { bottom: auto; left: auto; transform: none; top: var(--pad); right: var(--pad); min-height: 0; }
  .br { display: flex; bottom: var(--pad); right: var(--pad); }

  main { height: 100vh; height: 100svh; align-items: center; justify-items: center; padding: calc(var(--pad) + var(--U) * 2) var(--pad); }
  .panel { width: min(560px, 100%); }


  /* stage left, height-bound; tray a column on the right */
  .panel--wide { width: 100%; }
  .sheet {
    --sh: min(calc(100svh - 300px), 480px);                  /* stage media height */
    --tw: 176px;                                              /* tray column (99px-tall thumbs) */
    width: min(100%, calc(var(--sh) * 16 / 9 + var(--tw) + var(--U)));
    margin: 0 auto;
    display: grid; grid-template-columns: minmax(0, 1fr) var(--tw); grid-template-rows: repeat(4, max-content);
    gap: var(--U); align-items: start;
  }
  .tile.is-stage { grid-column: 1; grid-row: 1 / -1; }
  .tile:not(.is-stage) { grid-column: 2; }
  /* one project: no tray column, stage alone, caption unclamped */
  .sheet:has(.tile:only-child) { width: min(100%, 560px); grid-template-columns: minmax(0, 1fr); grid-template-rows: max-content; }   /* same column as About */
  .tile:only-child { grid-column: 1; grid-row: 1; }
  .tile:only-child .t-desc { display: block; -webkit-line-clamp: none; overflow: visible; }
  .is-stage .media { border-radius: 2px; margin-inline: 0; box-shadow: 0 0 0 1px rgba(0,0,0,.1) inset; }
  .t-head { flex-wrap: nowrap; row-gap: 0; }
  .t-name { flex-basis: auto; }
  .t-desc { margin-top: 0; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
}

/* ---------- short viewports (phone landscape, small windows): chrome goes in flow, page scrolls ---------- */
@media (max-height: 600px) {
  html, body { height: auto; }
  body {
    min-height: 100svh; overflow-y: auto;
    display: grid; grid-template-columns: 1fr auto; grid-template-rows: auto 1fr auto;
    align-items: center; gap: var(--U); padding: var(--pad) var(--pad) calc(var(--pad) + var(--safe-b));
  }
  .corner { position: static; transform: none; min-height: 0; }
  .tr { position: relative; inset: auto; } /* keeps the indicator anchored; drops the phone offsets */
  .br { display: flex; }
  .bl { gap: var(--U); }
  main { grid-column: 1 / -1; height: auto; min-height: 0; padding: 0; }
  .sheet { --sh: min(50svh, 480px); }
  .tile.is-stage { max-width: calc(var(--sh) * 16 / 9); margin-inline: auto; }
  .is-stage .media { margin-inline: 0; border-radius: 2px; box-shadow: 0 0 0 1px rgba(0,0,0,.1) inset; }
}

@media (prefers-reduced-motion: reduce) {
  :root { --in: 0ms; }
  .panel.fade { animation: none; }
  .indicator { transition: none; }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none; }
}
