.layout {
  display: flex;
  flex-direction: row;
}
.projects {
  display: flex;
  flex-direction: column;
  gap: 10px;

  min-width: 160px;

  align-items: flex-start;

  button {
    white-space: nowrap;
  }
}

.about {
  margin-left: 180px;
}

.title {
  font-size: 20px;
}

.filteredimg {
  filter: grayscale(30%);
  /* Fixed width; the browser derives height from the file's own ratio. */
}

/* Portraits keep their upright 2:3. Pinning the ratio rather than leaving
   height auto means any future image that isn't exactly 2:3 gets cropped to
   match instead of standing a different height from its neighbours. */
.portrait {
  width: 195px;
  height: 266px;
  object-fit: cover;
}

.description {
  background-color: white;
  display: flex;
  flex-direction: row;
  gap: 20px;
  .content {
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-width: 300px;
    margin-left: 20px;
  }

  .annotation:last-child {
    margin-top: auto;
  }
}

.cv {
  margin-left: 20px;
  .emphasis {
    font-style: italic;
    font-size: 14px;
    color: gray;
  }
}

.annotation {
  font-size: 14px;
  color: gray;
  font-style: italic;
  max-width: 400px;
}
/* Video sits in the grid at the same width as the images. No controls —
   the element itself is the play/pause target, so it needs to look clickable. */
.video {
  width: 400px;
  aspect-ratio: 16 / 9;
  border: none;
  cursor: pointer;
}

.image-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;

  /* Without this, align-items defaults to stretch: any image sharing a row
     with a taller one gets pulled to match it, distorting its ratio. */
  align-items: flex-start;

  /* Flex items default to flex-shrink:1, so they compress below their stated
     width when the row runs out of room. Zero keeps every child at its own
     size and lets it wrap to the next line instead. */
  > * {
    flex-shrink: 0;
  }
}
.overlay {
  position: relative;
}

.overlay-text {
  opacity: 0;
  position: absolute;
  bottom: 10px;
  left: 10px;
  max-width: 300px;
}

.overlay:hover img {
  filter: invert(1);
  opacity: 0.3;
}

.overlay:hover .overlay-text {
  opacity: 1;
}

img {
  width: 400px;
  height: auto;
  display: block;
}

p {
  font-size: 16px;
}

button {
  border: none;
  background-color: transparent;
  font-family: "Times New Roman", Times, serif;
  font-size: 16px;
  padding: 0;
}

button:hover {
  font-style: italic;
}

summary::marker {
  content: ".";
}

details[open] summary::marker {
  content: "./";
}

/* ── 3D carousel ─────────────────────────────────────────────── */

/* The scene supplies perspective so child transforms look 3D. */
.carousel-scene {
  width: 400px;
  height: 560px;
  perspective: 800px;
}

/* The carousel lives in 3D and spins continuously. */
.carousel {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d;
  animation: carousel-spin 12s linear infinite;
}

/* Each image is positioned on one face of the carousel. With 3
   images the faces sit 120° apart; translateZ pushes them outward
   so they don't overlap at the centre. */
.carousel-cell {
  position: absolute;
  width: 400px;
  height: 560px;
  backface-visibility: hidden;
}

.carousel-cell img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.carousel-cell:nth-child(1) {
  transform: rotateY(0deg);
}
.carousel-cell:nth-child(2) {
  transform: rotateY(120deg);
}
.carousel-cell:nth-child(3) {
  transform: rotateY(240deg);
}

@keyframes carousel-spin {
  from {
    transform: rotateY(0deg);
  }
  to {
    transform: rotateY(360deg);
  }
}

/* ── Flying star ─────────────────────────────────────────────── */

.star {
  position: fixed;
  pointer-events: none;
}

/* Top-right → bottom-left */
.star-1 {
  animation: star-fly-1 30s infinite;
  animation-delay: 0s;
}

/* Bottom-left → top-right */
.star-2 {
  animation: star-fly-2 38s infinite;
  animation-delay: -8s;
}

/* Left → right, mid-height */
.star-3 {
  animation: star-fly-3 30s infinite;
  animation-delay: -15s;
}

/* Top-left → bottom-right */
.star-4 {
  animation: star-fly-4 42s infinite;
  animation-delay: -5s;
}

/* Right → left, high */
.star-5 {
  animation: star-fly-5 35s infinite;
  animation-delay: -20s;
}

@keyframes star-fly-1 {
  0% {
    top: -10vh;
    right: -5vw;
    opacity: 1;
  }
  10% {
    opacity: 0.8;
  }
  90% {
    opacity: 0.5;
  }
  100% {
    top: 90vh;
    right: 105vw;
    opacity: 0;
  }
}

@keyframes star-fly-2 {
  0% {
    top: -5vh;
    right: -10vw;
    opacity: 1;
  }
  10% {
    opacity: 0.8;
  }
  90% {
    opacity: 0.2;
  }
  100% {
    top: 85vh;
    right: 100vw;
    opacity: 0;
  }
}

@keyframes star-fly-3 {
  0% {
    top: -15vh;
    right: 10vw;
    opacity: 1;
  }
  10% {
    opacity: 1;
  }
  90% {
    opacity: 1;
  }
  100% {
    top: 80vh;
    right: 95vw;
    opacity: 0;
  }
}

@keyframes star-fly-4 {
  0% {
    top: -8vh;
    right: -15vw;
    opacity: 1;
  }
  10% {
    opacity: 1;
  }
  90% {
    opacity: 1;
  }
  100% {
    top: 95vh;
    right: 110vw;
    opacity: 0;
  }
}

@keyframes star-fly-5 {
  0% {
    top: -12vh;
    right: 5vw;
    opacity: 1;
  }
  10% {
    opacity: 1;
  }
  90% {
    opacity: 1;
  }
  100% {
    top: 75vh;
    right: 100vw;
    opacity: 1;
  }
}

.mountain {
  position: absolute;
  bottom: 100px;
}

@media screen and (max-width: 600px) {
  .layout {
    flex-direction: column;
  }

  .projects {
    flex-direction: row;
    flex-wrap: wrap;
  }
  .description {
    flex-direction: column;
    margin-top: 20px;
  }

  .cv {
    margin-top: 20px;
  }
}
