/* ==========================================================================
   Chay Johansson - dark portfolio
   ========================================================================== */

:root{
  --bg-top:    #24282F;   /* page gradient, top */
  --bg-bot:    #171D24;   /* page gradient, bottom */
  --bg:        #1e232b;   /* mid tone, for anything that needs a flat fill */
  --panel:     #1c212a;   /* tile placeholder before its thumbnail loads */
  --line:      rgba(255,255,255,.09);
  --line-soft: rgba(255,255,255,.05);
  --text:      #ededf2;
  --muted:     #8b8b97;
  --accent:    #7E8BDB;

  --header-h:  132px;   /* brand row + the centred nav beneath it */
  --tile:      265px;   /* ideal tile edge length */
  --gap:       18px;    /* padding between tiles within a belt */
  --strip-gap: 46px;    /* space between the two belts */
  --strip-top: 0px;     /* banner runs straight up to the header */
  --strip-pad: 34px;    /* breathing room below the belt */
  --lift-room: 36px;    /* headroom inside a belt for the hover lift + shadow */

  /* the two belts share the height below the header, capped at --tile */
  /* The banner is --hero-mult times a belt row. Both share the space under
     the header, so the row height is solved for (mult + 1) rows rather than
     assuming two equal ones - otherwise a taller banner pushes the belt off
     the bottom of the screen. */
  --hero-mult: 2.1;
  --strip-h:   min(var(--tile), calc((100vh - var(--header-h) - var(--strip-gap)
                                      - var(--strip-top) - var(--strip-pad)
                                      - var(--lift-room) * 2)
                                     / (var(--hero-mult) + 1)));
  --hero-h:    calc(var(--strip-h) * var(--hero-mult));
  --ease:      cubic-bezier(.22,.61,.36,1);
}

*,*::before,*::after{ box-sizing:border-box; }

html,body{ height:100%; }

body{
  margin:0;
  background:linear-gradient(180deg, var(--bg-top) 0%, var(--bg-bot) 100%);
  background-attachment:fixed;
  color:var(--text);
  font-family:"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size:15px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

body.is-home{ overflow:hidden; }          /* the grid does the scrolling */
body.is-locked{ overflow:hidden; }        /* lightbox open */

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

::selection{ background:var(--accent); color:#fff; }

:focus-visible{
  outline:2px solid var(--accent);
  outline-offset:3px;
  border-radius:2px;
}

/* --------------------------------------------------------------- header  */

.site-header{
  position:fixed;
  inset:0 0 auto 0;
  z-index:60;
  height:var(--header-h);

  /* One centred column sized to the widest child - the nav. Both rows sit in
     it, so the brand's left edge lines up with the first nav link. */
  display:grid;
  grid-template-columns:auto;
  justify-content:center;
  align-content:center;
  gap:12px;
  padding:0 clamp(18px, 3.2vw, 48px);
  background:var(--bg-top);
  border-bottom:1px solid var(--line-soft);
}

.brand{
  justify-self:start;      /* flush with the first nav link above/below it */
  display:flex;
  align-items:center;
  gap:clamp(9px, 1vw, 14px);
  color:var(--accent);
  font-family:"Space Grotesk", "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
  font-size:clamp(20px, 2.1vw, 30px);
  font-weight:700;
  letter-spacing:-.015em;
  line-height:1;
  white-space:nowrap;
  transition:color .25s var(--ease);
}

.brand__logo{
  display:block;
  width:clamp(30px, 2.9vw, 40px);
  height:auto;
  box-shadow:0 5px 14px -6px rgba(0,0,0,.85);
  transition:transform .3s var(--ease), box-shadow .3s var(--ease);
}
.brand:hover .brand__logo{
  transform:translateY(-1px) scale(1.05);
  box-shadow:0 8px 18px -6px rgba(0,0,0,.95);
}
.brand:hover{ color:#9BA6E8; }

.nav{
  justify-self:center;       /* centred over the two belts */
  display:flex;
  align-items:center;
  justify-content:center;
  flex-wrap:wrap;
  gap:clamp(16px, 2.2vw, 32px);
}

.nav a{
  position:relative;
  font-size:14px;
  font-weight:600;
  letter-spacing:.14em;
  text-transform:uppercase;
  white-space:nowrap;
  color:var(--muted);
  padding:6px 0;
  transition:color .25s var(--ease);
}
.nav a::after{
  content:"";
  position:absolute;
  left:0; bottom:0;
  width:100%; height:1px;
  background:var(--accent);
  transform:scaleX(0);
  transform-origin:left;
  transition:transform .32s var(--ease);
}
.nav a:hover{ color:var(--text); }
.nav a:hover::after{ transform:scaleX(1); }
.nav a.is-active{ color:var(--text); }
.nav a.is-active::after{ transform:scaleX(1); background:rgba(255,255,255,.28); }

.nav-toggle{
  display:none;
  position:absolute;
  top:50%;
  right:clamp(18px, 3.2vw, 48px);
  transform:translateY(-50%);
  width:40px; height:40px;
  padding:9px 8px;
  flex-direction:column;
  justify-content:space-between;
  background:none;
  border:1px solid var(--line);
  border-radius:8px;
  cursor:pointer;
}
.nav-toggle span{
  display:block;
  height:1.5px;
  background:var(--text);
  transition:transform .3s var(--ease), opacity .3s var(--ease);
}
.nav-toggle[aria-expanded="true"] span:nth-child(1){ transform:translateY(8.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2){ opacity:0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3){ transform:translateY(-8.5px) rotate(-45deg); }

/* ----------------------------------------------------- scrolling strips  */

/* Two horizontal belts of tiles below the header, travelling in opposite
   directions. Each belt repeats its list until it overruns the window, and
   its transform wraps by exactly one sequence width, so the loop has no seam.
   Hovering a belt stops that belt only - the other keeps going. */

.strips{
  position:fixed;
  inset:var(--header-h) 0 0 0;   /* below the header, never underneath it */
  display:flex;
  flex-direction:column;
  justify-content:flex-start;
  gap:var(--strip-gap);
  padding:var(--strip-top) 0 var(--strip-pad);
  overflow:hidden;
}

/* The showreel banner: a full-width strip cropped from the middle of the
   frame. The iframe is sized to the container's full width, so at 16:9 it is
   far taller than the strip; centring it and clipping shows a cinematic band
   from the middle. --hero-h controls how much of the frame you see - at 1500px
   wide the frame is ~845px tall, so 265px shows roughly a third of it. */

.hero{
  position:relative;
  flex:0 0 auto;
  height:var(--hero-h);
  overflow:hidden;
  cursor:pointer;
  background:#000;

  /* feather the top and bottom so the strip melts into the page instead of
     ending on a hard line */
  -webkit-mask-image:linear-gradient(180deg,
    #000 0%, #000 82%, transparent 100%);
          mask-image:linear-gradient(180deg,
    #000 0%, #000 82%, transparent 100%);
}

.hero__frame{
  position:absolute;
  top:50%;
  left:50%;
  width:calc(100% * var(--hero-zoom, 1));
  aspect-ratio:16 / 9;
  transform:translate(-50%, -50%);
  pointer-events:none;        /* clicks belong to the section */
}
.hero__frame iframe{
  display:block;
  width:100%;
  height:100%;
  border:0;
}


.strip{
  position:relative;
  flex:0 0 auto;

  /* drag to scroll: pan-y leaves vertical page scrolling to the browser and
     keeps the horizontal gesture for us */
  cursor:grab;
  touch-action:pan-y;
  -webkit-user-select:none;
          user-select:none;

  /* A mask clips its element to the border box - content cannot paint outside
     it, however the mask image is sized. So the belt is taller than its tiles
     by --lift-room top and bottom, giving the hover lift and its shadow space
     to grow into without being cropped. */
  height:calc(var(--strip-h) + var(--lift-room) * 2);

  /* fade both ends of the belt */
  -webkit-mask-image:linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%);
          mask-image:linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%);
}

.strip.is-dragging{ cursor:grabbing; }

.strip__track{
  position:absolute;
  top:var(--lift-room);
  left:0;
  height:var(--strip-h);
  display:flex;
  align-items:center;
  gap:var(--gap);
  will-change:transform;
}

.strip__track .tile{
  flex:0 0 auto;
  -webkit-user-drag:none;
  width:var(--strip-h);
  height:var(--strip-h);
}

/* --------------------------------------------------------------- tiles   */

.tile{
  --rx:0deg;               /* tilt, driven from js by the cursor position */
  --ry:0deg;
  --lift:0px;
  --scale:1;
  --mx:50%;                /* cursor position for the sheen highlight */
  --my:50%;

  position:relative;
  display:block;
  aspect-ratio:1 / 1;
  width:100%;
  overflow:hidden;
  border-radius:10px;
  background:var(--panel);
  border:1px solid var(--line-soft);
  box-shadow:
    0 18px 34px -14px rgba(0,0,0,.85),
    0 6px 14px -8px rgba(0,0,0,.6);
  isolation:isolate;
  will-change:transform;
  transform:perspective(900px)
            rotateX(var(--rx)) rotateY(var(--ry))
            translateY(var(--lift)) scale(var(--scale));
  transition:transform .5s var(--ease), border-color .4s var(--ease), box-shadow .5s var(--ease);
}

/* while lifted the tilt must track the cursor, so shorten the transform ease */
.tile.is-lifted{
  --lift:-8px;
  --scale:1.035;
  z-index:5;
  transition:transform .12s ease-out, border-color .4s var(--ease), box-shadow .4s var(--ease);
}

.tile__img{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  object-fit:cover;        /* fill, never stretch */
  object-position:center;
  display:block;
  transform:scale(1.01);
  transition:filter .45s var(--ease), transform .7s var(--ease);
}

/* the sheen: a soft highlight under the cursor plus a diagonal gloss band */
.tile__sheen{
  position:absolute;
  inset:0;
  z-index:3;
  pointer-events:none;
  opacity:0;
  background:
    radial-gradient(60% 60% at var(--mx) var(--my),
      rgba(255,255,255,.30) 0%,
      rgba(255,255,255,.10) 38%,
      rgba(255,255,255,0) 70%),
    linear-gradient(122deg,
      rgba(255,255,255,0) 38%,
      rgba(255,255,255,.14) 50%,
      rgba(255,255,255,0) 62%);
  mix-blend-mode:screen;
  transition:opacity .35s var(--ease);
}

.tile__veil{
  position:absolute;
  inset:0;
  background:linear-gradient(to top, rgba(0,0,0,.86) 0%, rgba(0,0,0,.22) 45%, rgba(0,0,0,0) 72%);
  opacity:0;
  transition:opacity .4s var(--ease);
}

.tile__meta{
  position:absolute;
  left:20px; right:20px; bottom:18px;
  z-index:4;
  display:flex;
  align-items:baseline;
  gap:10px;
  opacity:0;
  transform:translateY(8px);
  transition:opacity .4s var(--ease), transform .45s var(--ease);
}

.tile__title{
  font-size:14px;
  font-weight:700;
  letter-spacing:-.01em;
  line-height:1.3;
  flex:1 1 auto;
  min-width:0;
}

.tile__dur{
  flex:0 0 auto;
  font-size:11px;
  font-weight:500;
  letter-spacing:.08em;
  color:var(--muted);
  font-variant-numeric:tabular-nums;
}

.tile__play{
  position:absolute;
  top:50%; left:50%;
  z-index:4;
  width:64px; height:64px;
  margin:-32px 0 0 -32px;
  display:grid;
  place-items:center;
  border-radius:50%;
  border:1px solid rgba(255,255,255,.55);
  background:rgba(16,20,26,.4);
  backdrop-filter:blur(4px);
  -webkit-backdrop-filter:blur(4px);
  opacity:0;
  transform:scale(.82);
  transition:opacity .35s var(--ease), transform .45s var(--ease), background .35s var(--ease);
}
.tile__play svg{ width:18px; height:18px; margin-left:3px; fill:#fff; }

.tile:hover,
.tile:focus-visible,
.tile.is-lifted{
  border-color:rgba(255,255,255,.30);
  box-shadow:
    0 34px 70px -18px rgba(0,0,0,1),
    0 12px 24px -10px rgba(0,0,0,.8),
    0 0 0 1px rgba(255,255,255,.06),
    0 0 34px -6px rgba(126,139,219,.22);
}
.tile:hover .tile__img,
.tile:focus-visible .tile__img{
  filter:brightness(1.06) saturate(1.06);
  transform:scale(1.05);
}
.tile:hover .tile__sheen,
.tile:focus-visible .tile__sheen{ opacity:1; }
.tile:hover .tile__veil,
.tile:focus-visible .tile__veil{ opacity:1; }
.tile:hover .tile__meta,
.tile:focus-visible .tile__meta{ opacity:1; transform:translateY(0); }
.tile:hover .tile__play,
.tile:focus-visible .tile__play{ opacity:1; transform:scale(1); }
.tile:hover .tile__play{ background:rgba(126,139,219,.9); border-color:transparent; }

/* --------------------------------------------------------- lightbox      */

.lightbox{
  position:fixed;
  inset:0;
  z-index:100;
  display:grid;
  place-items:center;
  padding:clamp(16px, 5vw, 72px);
  background:rgba(16,20,26,.92);
  backdrop-filter:blur(18px);
  -webkit-backdrop-filter:blur(18px);
  opacity:0;
  transition:opacity .3s var(--ease);
}
.lightbox.is-open{ opacity:1; }
.lightbox[hidden]{ display:none; }

.lightbox__inner{
  width:min(1360px, 100%);
  transform:scale(.985);
  transition:transform .35s var(--ease);
}
.lightbox.is-open .lightbox__inner{ transform:scale(1); }

.lightbox__frame{
  position:relative;
  width:100%;
  aspect-ratio:16 / 9;
  background:#000;
  border-radius:10px;
  overflow:hidden;
  box-shadow:0 40px 120px -40px rgba(0,0,0,1);
}
.lightbox__frame iframe{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  border:0;
}

.lightbox__title{
  margin:16px 2px 0;
  font-size:13px;
  font-weight:500;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--muted);
}

.lightbox__close{
  position:absolute;
  top:clamp(14px, 2.4vw, 28px);
  right:clamp(14px, 2.4vw, 28px);
  width:46px; height:46px;
  display:grid;
  place-items:center;
  font-size:26px;
  line-height:1;
  color:var(--text);
  background:rgba(255,255,255,.06);
  border:1px solid var(--line);
  border-radius:50%;
  cursor:pointer;
  transition:background .25s var(--ease), transform .25s var(--ease);
}
.lightbox__close:hover{
  background:var(--accent);
  border-color:transparent;
  transform:rotate(90deg);
}

/* --------------------------------------------------------- credits       */

/* A release year often falls after the job ended, so a credit sits inside its
   company's block rather than at its own point on the spine - the year rides
   the connector line that reaches back to the timeline instead. */

.tl__projects{
  display:flex;
  flex-direction:column;
  gap:4px;
  margin-top:14px;
}

.proj{
  position:relative;
  display:flex;
  align-items:center;
  gap:14px;
  padding:8px 10px;
  border-radius:7px;
  border:1px solid transparent;
  transition:background .25s var(--ease), border-color .25s var(--ease);
}
.tl:nth-child(odd) .proj{ flex-direction:row-reverse; text-align:right; }

.proj:hover{
  background:rgba(255,255,255,.05);
  border-color:var(--line-soft);
}

/* rows with no imdb page are not links, so they do not react to hover */
.proj--plain:hover{ background:none; border-color:transparent; }
.proj--plain .proj__title{ color:var(--muted); }

/* the line back to the spine, with a tick where it meets */
.proj::after{
  content:"";
  position:absolute;
  top:50%;
  width:46px;
  height:1px;
  background:linear-gradient(90deg, var(--line-soft), var(--line));
}
.proj::before{
  content:"";
  position:absolute;
  top:50%;
  width:4px;
  height:4px;
  margin-top:-2px;
  border-radius:50%;
  background:var(--line);
}
.tl:nth-child(odd) .proj::after{ right:-46px; }
.tl:nth-child(odd) .proj::before{ right:-48px; }
.tl:nth-child(even) .proj::after{
  left:-46px;
  background:linear-gradient(90deg, var(--line), var(--line-soft));
}
.tl:nth-child(even) .proj::before{ left:-48px; }

.proj__year{
  flex:0 0 auto;
  min-width:30px;
  font-size:11px;
  font-weight:600;
  letter-spacing:.06em;
  color:var(--muted);
  font-variant-numeric:tabular-nums;
  transition:color .25s var(--ease);
}
.proj:hover .proj__year{ color:var(--accent); }

.proj__shot,
.proj__icon{
  flex:0 0 auto;
  width:72px;
  height:72px;
  border-radius:11px;
  position:relative;
  overflow:hidden;
  border:1px solid rgba(255,255,255,.16);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.34),
    inset 0 -7px 12px -9px rgba(0,0,0,.9),
    0 5px 12px -6px rgba(0,0,0,.85);
  transition:transform .25s var(--ease), filter .25s var(--ease),
             box-shadow .25s var(--ease);
}

.proj__shot{ background:var(--panel); }
.proj__shot img{ width:100%; height:100%; object-fit:cover; display:block; }

/* glossy chip: a lit dome over a colour taken from the title */
.proj__icon{
  display:grid;
  place-items:center;
  font-size:19px;
  font-weight:800;
  letter-spacing:.02em;
  color:rgba(255,255,255,.96);
  text-shadow:0 1px 2px rgba(0,0,0,.55);
  background:
    radial-gradient(115% 75% at 50% -25%,
      rgba(255,255,255,.55) 0%,
      rgba(255,255,255,.12) 45%,
      rgba(255,255,255,0) 62%),
    linear-gradient(160deg,
      hsl(var(--icon-hue, 210) 52% 44%) 0%,
      hsl(var(--icon-hue, 210) 58% 26%) 100%);
}

/* specular streak that sweeps across on hover */
.proj__shot::after,
.proj__icon::after{
  content:"";
  position:absolute;
  top:-30%;
  left:-60%;
  width:220%;
  height:160%;
  background:linear-gradient(115deg,
    rgba(255,255,255,0) 38%,
    rgba(255,255,255,.34) 50%,
    rgba(255,255,255,0) 62%);
  transform:translateX(-42%);
  transition:transform .55s var(--ease);
  pointer-events:none;
}

.proj:hover .proj__shot,
.proj:hover .proj__icon{
  transform:translateY(-1px) scale(1.06);
  filter:brightness(1.1) saturate(1.08);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.45),
    inset 0 -7px 12px -9px rgba(0,0,0,.9),
    0 8px 16px -6px rgba(0,0,0,.95);
}
.proj:hover .proj__shot::after,
.proj:hover .proj__icon::after{ transform:translateX(42%); }

.proj__title{
  font-size:14px;
  font-weight:600;
  line-height:1.3;
  color:var(--text);
}

@media (max-width:700px){
  .tl:nth-child(odd) .proj{ flex-direction:row; text-align:left; }

  .proj::after{ width:22px; }
  .tl:nth-child(odd) .proj::after,
  .tl:nth-child(even) .proj::after{
    left:-34px;
    right:auto;
    background:linear-gradient(90deg, var(--line), var(--line-soft));
  }
  .tl:nth-child(odd) .proj::before,
  .tl:nth-child(even) .proj::before{ left:-36px; right:auto; }
}

/* --------------------------------------------------- long-form research  */

.rsec__list{
  margin:0 0 18px;
  padding:0 0 0 20px;
  max-width:62ch;
  color:var(--muted);
  font-size:16px;
}
.rsec__list li{ margin:0 0 6px; }
.rsec__list li::marker{ color:var(--accent); }

.page code{
  padding:2px 6px;
  border-radius:5px;
  background:rgba(255,255,255,.06);
  border:1px solid var(--line-soft);
  font-family:"SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  font-size:.88em;
  color:var(--text);
  word-break:break-word;
}

/* dataset / source attribution */
.cite{
  margin:24px 0;
  padding:18px 20px;
  max-width:62ch;
  border-radius:9px;
  border:1px solid var(--line-soft);
  border-left:2px solid var(--accent);
  background:rgba(255,255,255,.025);
}
.cite__label{
  margin:0 0 8px !important;
  font-size:11px;
  font-weight:600;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--accent);
}
.page .cite p{ margin:0 0 8px; font-size:14px; }
.page .cite p:last-child{ margin-bottom:0; }

/* ------------------------------------------------------ page contents -- */

/* A sticky rail beside the sections. The list is built from the headings, so
   adding a section to the page adds it to the contents automatically. */

.doc{
  display:grid;
  grid-template-columns:minmax(0, 1fr) 210px;
  gap:clamp(30px, 4.5vw, 64px);
  align-items:start;
}

.toc{
  grid-column:2;
  grid-row:1;
  position:sticky;
  top:calc(var(--header-h) + 30px);
  max-height:calc(100vh - var(--header-h) - 70px);
  overflow-y:auto;
  scrollbar-width:thin;
}

.doc__body{ grid-column:1; grid-row:1; min-width:0; }

.toc__title{
  margin:0 0 12px;
  font-size:11px;
  font-weight:600;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--muted);
}

.toc__list{
  list-style:none;
  margin:0;
  padding:0;
  border-left:1px solid var(--line);
}

.page .toc__list a{
  display:block;
  padding:8px 0 8px 15px;
  margin-left:-1px;
  border-left:2px solid transparent;
  border-bottom:0;
  font-size:13px;
  font-weight:500;
  line-height:1.35;
  color:var(--muted);
  transition:color .25s var(--ease), border-color .25s var(--ease);
}
.page .toc__list a:hover{ color:var(--text); border-left-color:rgba(255,255,255,.28); }
.page .toc__list a.is-current{ color:var(--text); border-left-color:var(--accent); }

/* anchors must clear the fixed header when jumped to */
.rsec{ scroll-margin-top:calc(var(--header-h) + 24px); }

@media (max-width:900px){
  .doc{ grid-template-columns:1fr; gap:22px; }

  .toc,
  .doc__body{ grid-column:1; }
  .toc{ grid-row:1; position:static; max-height:none; margin-bottom:6px; }
  .doc__body{ grid-row:2; }

  /* a scrollable row of chips instead of a rail */
  .toc__list{
    display:flex;
    gap:8px;
    overflow-x:auto;
    border-left:0;
    padding-bottom:4px;
  }
  .page .toc__list a{
    white-space:nowrap;
    padding:8px 14px;
    margin-left:0;
    border:1px solid var(--line);
    border-radius:999px;
    font-size:12px;
  }
  .page .toc__list a.is-current{ border-color:var(--accent); color:var(--text); }
}

/* ---------------------------------------------------- research page      */

.rsec{ margin:56px 0 0; }
.rsec:first-of-type{ margin-top:36px; }

.rsec__title{
  font-size:clamp(20px, 2.4vw, 27px);
  font-weight:800;
  letter-spacing:-.02em;
  line-height:1.2;
  margin:0 0 14px;
  color:var(--text);
}

/* stills for sections that have no video */

.stills{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(min(330px, 100%), 1fr));
  gap:18px;
  margin:26px 0 0;
}

.still,
.rsec__still{
  display:block;
  margin:0;
  border-radius:10px;
  overflow:hidden;
  border:1px solid var(--line-soft);
  box-shadow:
    0 18px 34px -14px rgba(0,0,0,.85),
    0 6px 14px -8px rgba(0,0,0,.6);
  transition:transform .35s var(--ease), border-color .35s var(--ease),
             box-shadow .35s var(--ease);
}

.still img,
.rsec__still img{
  display:block;
  width:100%;
  height:auto;
}

.still:hover{
  transform:translateY(-3px);
  border-color:rgba(255,255,255,.2);
  box-shadow:
    0 26px 46px -18px rgba(0,0,0,.95),
    0 8px 18px -10px rgba(0,0,0,.7);
}

/* a lone still keeps its natural width rather than being upscaled */
.rsec__still{ margin-top:26px; max-width:708px; width:100%; }

.vgrid{
  display:grid;
  gap:22px;
  /* room on both sides: these sit between paragraphs, so they need to breathe
     below as well as above */
  margin:40px 0;
}
.vgrid--one{ grid-template-columns:1fr; }
.vgrid--two{ grid-template-columns:repeat(auto-fit, minmax(min(330px, 100%), 1fr)); }
.vgrid--half{ grid-template-columns:repeat(auto-fit, minmax(min(430px, 100%), 1fr)); }
.vgrid--small{
  grid-template-columns:repeat(auto-fill, minmax(min(228px, 100%), 1fr));
  gap:18px;
}

.vcard{
  display:flex;
  flex-direction:column;
  gap:11px;
}

.vcard__shot{
  position:relative;
  display:block;
  aspect-ratio:16 / 9;
  overflow:hidden;
  border-radius:10px;
  background:var(--panel);
}

.vcard__play{
  position:absolute;
  top:50%;
  left:50%;
  z-index:3;
  width:54px;
  height:54px;
  margin:-27px 0 0 -27px;
  display:grid;
  place-items:center;
  border-radius:50%;
  border:1px solid rgba(255,255,255,.5);
  background:rgba(16,20,26,.4);
  backdrop-filter:blur(4px);
  -webkit-backdrop-filter:blur(4px);
  opacity:0;
  transform:scale(.85);
  transition:opacity .3s var(--ease), transform .35s var(--ease), background .3s var(--ease);
}
.vcard__play svg{ width:16px; height:16px; margin-left:2px; fill:#fff; }

.vcard:hover .vcard__play{
  opacity:1;
  transform:scale(1);
  background:rgba(126,139,219,.92);
  border-color:transparent;
}

.vgrid--small .vcard__play{ width:42px; height:42px; margin:-21px 0 0 -21px; }
.vgrid--small .vcard__play svg{ width:13px; height:13px; }

.vcard__title{
  font-size:14px;
  font-weight:600;
  line-height:1.35;
  color:var(--text);
  transition:color .25s var(--ease);
}
.vcard:hover .vcard__title{ color:#fff; }
.vgrid--small .vcard__title{ font-size:12.5px; }

/* working filenames are not worth showing - the title still reaches screen
   readers through the link's aria-label */
.vgrid--untitled .vcard__title{ display:none; }

/* --------------------------------------------- steam workshop grid       */

.work-grid{
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(min(290px, 100%), 1fr));
  gap:30px 24px;
  margin-top:44px;
}

.work{
  display:flex;
  flex-direction:column;
  gap:2px;
}

.work__shot,
.vcard__shot{
  --rx:0deg;
  --ry:0deg;
  --lift:0px;
  --scale:1;
  --mx:50%;
  --my:50%;

  position:relative;
  display:block;
  aspect-ratio:16 / 9;
  margin-bottom:12px;
  overflow:hidden;
  border-radius:10px;
  background:var(--panel);
  border:1px solid var(--line-soft);
  box-shadow:
    0 18px 34px -14px rgba(0,0,0,.85),
    0 6px 14px -8px rgba(0,0,0,.6);
  isolation:isolate;
  transform:perspective(900px)
            rotateX(var(--rx)) rotateY(var(--ry))
            translateY(var(--lift)) scale(var(--scale));
  transition:transform .5s var(--ease), border-color .4s var(--ease), box-shadow .5s var(--ease);
}

.work__shot.is-lifted,
.vcard__shot.is-lifted{
  --lift:-6px;
  --scale:1.03;
  border-color:rgba(255,255,255,.30);
  box-shadow:
    0 34px 70px -18px rgba(0,0,0,1),
    0 12px 24px -10px rgba(0,0,0,.8),
    0 0 0 1px rgba(255,255,255,.06),
    0 0 34px -6px rgba(126,139,219,.22);
  transition:transform .12s ease-out, border-color .4s var(--ease), box-shadow .4s var(--ease);
}

.work__shot img,
.vcard__shot img{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center;
  display:block;
  transform:scale(var(--punch, 1));
  transition:filter .45s var(--ease), transform .7s var(--ease);
}
.work__shot.is-lifted img,
.vcard__shot.is-lifted img{
  filter:brightness(1.06) saturate(1.06);
  transform:scale(calc(var(--punch, 1) * 1.04));
}
.work__shot.is-lifted .tile__sheen,
.vcard__shot.is-lifted .tile__sheen{ opacity:1; }

.work__title{
  font-size:14px;
  font-weight:600;
  line-height:1.35;
  color:var(--text);
  transition:color .25s var(--ease);
}
.work:hover .work__title{ color:#fff; }

.work__app{
  font-size:11px;
  font-weight:500;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--muted);
}

.work-empty{ color:var(--muted); }

/* --------------------------------------------------------- contact       */

.email-wrap{ margin:26px 0 8px; }

.page a.email{
  font-size:clamp(21px, 3.2vw, 33px);
  font-weight:800;
  letter-spacing:-.02em;
  color:var(--text);
  border-bottom:2px solid var(--accent);
  padding-bottom:2px;
  transition:color .25s var(--ease), border-color .25s var(--ease);
}
.page a.email:hover{ color:var(--accent); border-color:var(--text); }

.clinks{
  display:flex;
  flex-wrap:wrap;
  gap:12px;
  margin-top:20px;
}

.page a.clink{
  padding:12px 20px;
  border:1px solid var(--line);
  border-bottom:1px solid var(--line);
  border-radius:9px;
  font-size:12px;
  font-weight:600;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--muted);
  background:rgba(255,255,255,.02);
  transition:color .25s var(--ease), border-color .25s var(--ease),
             background .25s var(--ease), transform .25s var(--ease);
}
.page a.clink:hover{
  color:#fff;
  border-color:rgba(255,255,255,.3);
  background:rgba(255,255,255,.06);
  transform:translateY(-2px);
}

/* --------------------------------------------------------- timeline      */

.section-title{
  font-size:13px;
  font-weight:600;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--muted);
  margin:0 0 8px;
}

.timeline{
  position:relative;
  margin:44px 0 20px;
  padding:8px 0;
}

/* the spine, fading out at both ends */
.timeline::before{
  content:"";
  position:absolute;
  left:50%;
  top:0;
  bottom:0;
  width:1px;
  margin-left:-.5px;
  background:linear-gradient(180deg,
    rgba(255,255,255,0) 0%,
    var(--line) 7%,
    var(--line) 93%,
    rgba(255,255,255,0) 100%);
}

.tl{
  position:relative;
  width:50%;
  padding:0 46px 40px 0;   /* left-hand side */
}
.tl:nth-child(even){
  margin-left:50%;
  padding:0 0 40px 46px;   /* right-hand side */
}

/* the dot where the entry meets the spine */
.tl__marker{
  position:absolute;
  top:30px;
  width:11px;
  height:11px;
  border-radius:50%;
  background:var(--accent);
  box-shadow:0 0 0 4px rgba(126,139,219,.15);
}
.tl:nth-child(odd) .tl__marker{ right:-5.5px; }
.tl:nth-child(even) .tl__marker{ left:-5.5px; }

.tl__card{
  display:flex;
  align-items:center;
  gap:16px;
  padding:18px 20px;
  border-radius:10px;
  background:rgba(255,255,255,.028);
  border:1px solid var(--line-soft);
  box-shadow:0 14px 28px -18px rgba(0,0,0,.9);
  transition:transform .35s var(--ease), border-color .35s var(--ease),
             background .35s var(--ease), box-shadow .35s var(--ease);
}
.tl:nth-child(odd) .tl__card{ flex-direction:row-reverse; text-align:right; }

.tl__card:hover{
  transform:translateY(-3px);
  background:rgba(255,255,255,.05);
  border-color:rgba(255,255,255,.16);
  box-shadow:0 22px 40px -20px rgba(0,0,0,1);
}

/* logo slot - shows the initials until a real logo is dropped in */
.tl__logo{
  flex:0 0 auto;
  width:52px;
  height:52px;
  display:grid;
  place-items:center;
  border-radius:9px;
  background:rgba(255,255,255,.05);
  border:1px solid var(--line-soft);
  font-size:12px;
  font-weight:700;
  letter-spacing:.06em;
  color:var(--muted);
  overflow:hidden;
}
.tl__logo img{ width:100%; height:100%; object-fit:contain; padding:6px; }

/* company logos are flattened onto white, so the box matches them */
.tl__logo--img{
  background:#fff;
  border-color:rgba(255,255,255,.28);
}

.tl__text{ min-width:0; }

.timeline .tl__year{
  margin:0;
  font-size:26px;
  font-weight:800;
  letter-spacing:-.02em;
  line-height:1;
  color:var(--accent);
}

.timeline .tl__place{
  margin:6px 0 0;
  font-size:17px;
  font-weight:700;
  letter-spacing:-.01em;
  line-height:1.25;
  color:var(--text);
}

.timeline .tl__span{
  margin:3px 0 0;
  max-width:none;
  font-size:11px;
  font-weight:500;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--muted);
}

/* revealed on scroll - only once js has taken over, so no-js keeps them all */
.timeline.has-reveal .tl{
  opacity:0;
  transform:translateY(16px);
  transition:opacity .45s var(--ease), transform .45s var(--ease);
}
.timeline.has-reveal .tl.is-in{ opacity:1; transform:none; }

@media (max-width:700px){
  .timeline::before{ left:6px; }

  .tl,
  .tl:nth-child(even){
    width:100%;
    margin-left:0;
    padding:0 0 26px 34px;
  }
  .tl:nth-child(odd) .tl__card{ flex-direction:row; text-align:left; }
  .tl:nth-child(odd) .tl__marker,
  .tl:nth-child(even) .tl__marker{ left:.5px; right:auto; }
}

/* --------------------------------------------------------- sub pages     */

.page{
  max-width:860px;
  margin:0 auto;
  padding:calc(var(--header-h) + clamp(48px, 10vh, 120px)) clamp(20px, 5vw, 40px) 120px;
}

.page--wide{ max-width:1400px; }   /* after .page: same specificity, later wins */

.page--research,
.page--games,
.page--cfx{ max-width:1220px; }   /* wide enough for the contents rail */   /* also after .page, for the same reason */

.page .page__lead{
  font-size:18px;
  line-height:1.65;
  color:#c9c9d4;
  max-width:64ch;
  margin:0 0 16px;
}

.page__kicker{
  font-size:11px;
  font-weight:600;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:var(--accent);
  margin:0 0 18px;
}

.page h1{
  font-size:clamp(34px, 6vw, 62px);
  font-weight:800;
  letter-spacing:-.03em;
  line-height:1.05;
  margin:0 0 20px;
}

.page p{
  color:var(--muted);
  font-size:16px;
  max-width:62ch;
  margin:0 0 18px;
}

.page a:not(.btn):not(.work):not(.proj):not(.vcard):not(.toc__link){
  color:var(--text);
  border-bottom:1px solid var(--accent);
  transition:color .25s var(--ease);
}
.page a:not(.btn):not(.work):not(.proj):not(.vcard):not(.toc__link):hover{ color:var(--accent); }

.page a.work,
.page a.proj,
.page a.vcard,
.page a.toc__link{ border-bottom:0; color:inherit; }

.rule{
  height:1px;
  background:var(--line);
  border:0;
  margin:48px 0;
}

.site-footer{
  padding:0 clamp(20px, 5vw, 40px) 60px;
  max-width:860px;
  margin:0 auto;
  font-size:12px;
  letter-spacing:.12em;
  text-transform:uppercase;
  color:#5c5c67;
}

.noscript{ padding:calc(var(--header-h) + 40px) 32px; color:var(--muted); }
.noscript a{ color:var(--accent); }

/* --------------------------------------------------------- responsive    */

@media (max-width:1024px){
  :root{ --tile:225px; --header-h:124px; }
}

@media (max-width:980px){
  :root{ --header-h:116px; }

  .nav{ gap:clamp(10px, 1.6vw, 18px); }
  .nav a{ font-size:11.5px; letter-spacing:.1em; }
}

@media (max-width:760px){
  :root{ --gap:12px; --strip-gap:28px; --strip-top:10px; --strip-pad:20px;
         --lift-room:24px; --header-h:64px; }

  .site-header{ justify-content:start; align-content:center; }

  .nav-toggle{ display:flex; }

  .nav{
    position:fixed;
    top:var(--header-h); left:0; right:0;
    flex-direction:column;
    align-items:flex-start;
    gap:2px;
    padding:14px clamp(18px,5vw,32px) 26px;
    background:var(--bg-top);
    border-bottom:1px solid var(--line);
    transform:translateY(-8px);
    opacity:0;
    pointer-events:none;
    transition:opacity .28s var(--ease), transform .28s var(--ease);
  }
  .nav.is-open{ opacity:1; transform:translateY(0); pointer-events:auto; }
  .nav a{ font-size:15px; padding:12px 0; letter-spacing:.14em; }
}

@media (hover:none){
  .tile__meta{ opacity:1; transform:none; }
  .tile__veil{ opacity:.9; }
  .tile__play{ display:none; }
}

@media (prefers-reduced-motion:reduce){
  *{ animation:none !important; transition-duration:.01ms !important; }
}
