/* ==========================================================================
   portfolio.css — portfolio page. Requires base.css.
   Built on the shared system: .page-title, .subtitle, the project card
   component (base.css), the --vw / --u scale and --radius-media.
   This file only holds what is specific to the large cards: their tokens
   and the sticky stacking behaviour.
   ========================================================================== */

/* ==========================================================================
   Projects — sticky stacking cards
   Every card sticks at the same position (--stack-top). Cards later in the
   list are painted above earlier ones (DOM order of positioned siblings),
   so each new card slides over and fully covers the previous one. Pure CSS:
   the motion is the native scroll, in both directions, with no animation.

   The card box itself is transparent: only the media and the info block are
   opaque. So a new card hides the one below everywhere except outside its
   rounded corners, where the previous card naturally shows through. Full
   cover relies on all cards having the same size (same media ratio,
   one-line category and title).
   ========================================================================== */

.projects {
  /* Card geometry (tokens read by the project card component, base.css) */
  --card-ratio: 21 / 9;                          /* panoramic band */
  --card-max-height: 0.45;                       /* media ≤ 45% of the screen height */
  --card-gap: max(2rem, 4 * var(--vw));          /* scroll distance between cards */
  --stack-gap: max(1rem, 2 * var(--vw));         /* space below the navbar */
  --stack-top: calc(var(--nav-height) + var(--stack-gap));
  /* svh: stable while the mobile address bar shows/hides (no resize jumps). */
  --stack-viewport: 100vh;
  --card-title-size: max(1.25rem, 1.8 * var(--vw));
  /* Page-coloured frame around each card visual (see .project-card__media). */
  --media-frame: max(0.375rem, 0.6 * var(--vw));
  /* A stuck card must fit in the visible area (or its title would be covered
     before being read): the media height is capped by the screen height,
     keeping 3 title-heights for the info block. On a short screen the media
     simply gets more panoramic; the card width never changes. */
  --media-max-height: min(
    var(--stack-viewport) * var(--card-max-height),
    var(--stack-viewport) - var(--stack-top) - var(--stack-gap) - 3 * var(--card-title-size)
  );

  margin-top: calc(6 * var(--vw));
}

@supports (height: 1svh) {
  .projects {
    --stack-viewport: 100svh;
  }
}

/* Desktop first screen: the first card's category and title are visible on
   arrival (16:9 reference, browser chrome included). The gap above the
   cards follows the screen height, and the media height is also capped by
   the room left under the page intro for the info block (≈ 2.7
   title-heights) and a little air. The intro height is estimated as
   22vw + 120u (measured ≈ 437px at 1366, 530px at 1920, 590px at 2560: the
   subtitle wraps on more lines on smaller screens). Floor at 28% of the
   screen so the band never gets thin; the existing caps still apply.
   All cards share the cap, so they keep the same size (full cover). */
@media (min-width: 811px) {
  .projects {
    --projects-space: min(6 * var(--vw), 4 * var(--stack-viewport) / 100);
    --intro-height: calc(22 * var(--vw) + 120 * var(--u));
    --first-screen-media: calc(
      var(--stack-viewport) - var(--intro-height) - var(--projects-space)
        - 2.7 * var(--card-title-size) - 24 * var(--u)
    );
    --media-max-height: min(
      var(--stack-viewport) * var(--card-max-height),
      var(--stack-viewport) - var(--stack-top) - var(--stack-gap) - 3 * var(--card-title-size),
      max(var(--stack-viewport) * 0.28, var(--first-screen-media))
    );

    margin-top: var(--projects-space);
  }
}

.project-stack {
  padding: 0;
  list-style: none;
}

/* Scroll reserve after the last card: lets it reach its sticky position even
   on very tall screens, and keeps it on screen a moment before the whole
   stack leaves. Inside the list, so the cards stay stuck through it. */
.project-stack::after {
  content: "";
  display: block;
  height: 20vh;
  height: 20svh;
}

.project-stack > .project-card {
  position: sticky;
  top: var(--stack-top);
  /* Same width as the CTA card below (shared token): edges align exactly. */
  width: var(--block-wide);
  margin: 0 auto;
  /* The gap is padding, not margin: a sticky box's margin counts against its
     container, so with margins the earlier cards would be pushed up when the
     last one arrives. Same padding on every card keeps them aligned. */
  padding-bottom: var(--card-gap);
  /* Jumping to a card (#projet-0X) lands it exactly at its sticky position. */
  scroll-margin-top: var(--stack-top);
}

/* Opaque so the previous card's title never shows under this one. It starts
   right below the media, leaving the media's rounded corners see-through. */
.project-stack .project-card__info {
  background-color: var(--color-bg);
}

/* ==========================================================================
   Responsive (≤ 810px)
   ========================================================================== */

@media (max-width: 810px) {
  .projects {
    --card-ratio: 16 / 10;
    --card-title-size: clamp(1.125rem, 5vw, 1.5rem);
    margin-top: clamp(2.5rem, 12vw, 4rem);
  }
}

/* Very short screens (landscape phones): a stuck card would leave almost
   no room, so cards simply scroll. */
@media (max-height: 30rem) {
  .project-stack > .project-card {
    position: static;
  }
}
