/* ---------- projects page ----------
   Same ground, frame and nav as the home page; no scene. Built on style.css. */

.page-projets .nav { position: absolute; }

/* The Cairn mark as particles, behind everything (js/projets-field.js). */
#field {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 1;
  pointer-events: none;
}
.nav-links a[aria-current="page"] { opacity: 1; text-decoration: underline; text-underline-offset: 6px; text-decoration-thickness: 1px; }

.projets {
  padding: 200px calc(var(--gutter) + 4px) 120px;
  max-width: 1440px;
  margin: 0 auto;
}

/* ---------- intro ---------- */
.intro { margin-bottom: clamp(96px, 12vw, 180px); }
.intro h1 { margin-bottom: 28px; }
.intro .lede { max-width: 26em; margin: 0; }

/* ---------- one project ---------- */
.projet {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
  gap: clamp(40px, 5vw, 88px);
  align-items: start;
  padding-top: clamp(40px, 5vw, 64px);
  border-top: 1px solid var(--line);
  margin-bottom: clamp(120px, 14vw, 200px);
}

.projet-text { position: sticky; top: 48px; }

.projet-num {
  font-family: var(--serif);
  font-size: 15px;
  color: var(--mint);
  letter-spacing: .1em;
  margin: 0 0 22px;
}
.projet h2 { font-size: clamp(32px, 3.4vw, 50px); margin-bottom: 14px; }
.projet-meta {
  font-size: 12px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 26px;
}

/* A site under construction: a small living light, not a static badge. */
.status {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 36px;
  padding: 7px 14px 7px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 13px;
  color: var(--ink);
}
.status-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--mint);
  box-shadow: 0 0 10px var(--mint);
  animation: breathe 2.4s ease-in-out infinite;
}
@keyframes breathe { 50% { opacity: .35; box-shadow: 0 0 2px var(--mint); } }

.projet-story { margin: 0 0 32px; }
.projet-story dt {
  font-size: 11px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--mint);
  margin: 0 0 8px;
}
.projet-story dd {
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(18px, 1.4vw, 21px);
  line-height: 1.45;
  color: var(--ink-body);
  margin: 0 0 24px;
}
.projet-story dd:last-child { margin-bottom: 0; }

.tags { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.tags li {
  padding: 6px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 13px;
  color: var(--ink-soft);
}

/* ---------- screenshots ---------- */
.projet-shots { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 3vw, 44px); }
.projet-shots.has-phone { grid-template-columns: minmax(0, 1fr) minmax(0, 13.5rem); }
.projet-shots.has-phone .shot-main { grid-column: 1 / -1; }

.shot { margin: 0; min-width: 0; }
.shot img, .shot video {
  display: block;
  width: 100%;
  height: auto;
  background: var(--panel);
}
/* Keeps the frame's shape before the video has loaded. */
.shot video { aspect-ratio: 16 / 10; object-fit: cover; }
/* Desktop shots sit in a quiet browser frame. */
.browser {
  display: flex;
  gap: 6px;
  padding: 11px 14px;
  background: #0f231b;
  border: 1px solid var(--line);
  border-bottom: 0;
  border-radius: 12px 12px 0 0;
}
.browser span { width: 8px; height: 8px; border-radius: 50%; background: rgba(214, 230, 220, .22); }
.browser + img, .browser + video {
  border: 1px solid var(--line);
  border-top: 0;
  border-radius: 0 0 12px 12px;
}
.shot-main img, .shot-main video, .shot-main .browser { box-shadow: 0 40px 80px -40px rgba(0, 0, 0, .7); }

/* A whole page inside the browser frame, scrolled by the visitor. */
.scroll-wrap {
  position: relative;
  border: 1px solid var(--line);
  border-top: 0;
  border-radius: 0 0 12px 12px;
  overflow: hidden;
  background: var(--panel);
}
.scroll-frame {
  aspect-ratio: 16 / 10;
  overflow-x: hidden;
  overflow-y: auto;
  scrollbar-width: none;
}
.scroll-frame::-webkit-scrollbar { display: none; }
.scroll-frame:focus-visible { outline: 1px solid var(--mint); outline-offset: -1px; }
.scroll-bar {
  position: absolute;
  top: 12px;
  bottom: 12px;
  right: 7px;
  width: 3px;
  border-radius: 3px;
  background: rgba(6, 17, 13, .16);
  opacity: 0;
  transition: opacity .35s ease;
  pointer-events: none;
}
.scroll-bar i { display: block; width: 100%; height: 24px; border-radius: 3px; background: var(--mint); }
.shot-scroll:hover .scroll-bar, .shot-scroll.is-scrolled .scroll-bar { opacity: 1; }
.scroll-hint {
  position: absolute;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  padding: 9px 16px;
  border-radius: 999px;
  background: rgba(6, 17, 13, .82);
  color: var(--ink);
  font-size: 12px;
  letter-spacing: .06em;
  white-space: nowrap;
  pointer-events: none;
  transition: opacity .35s ease;
}
.shot-scroll.is-scrolled .scroll-hint { opacity: 0; }

/* The phone shot: a rounded device edge, no chrome. */
/* The device edge is on the screen's wrapper, so it stays while the stage
   swaps or hides the screen inside it. */
.shot-phone .phone-screen {
  border: 6px solid #0f231b;
  outline: 1px solid var(--line);
  border-radius: 28px;
  overflow: hidden;
  transition: border-color .6s ease;
}
.shot-phone .phone-screen video, .shot-phone .phone-screen img { border-radius: 0; }
.shot-phone video { aspect-ratio: 600 / 1298; }
.shot-phone { align-self: end; }

.shot figcaption {
  margin-top: 14px;
  font-size: 12px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* Caption with the season switcher beside it (wraps under it when narrow). */
.shot-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 20px; }
.seasons { display: flex; flex-wrap: wrap; gap: 8px; }
.seasons button {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-soft);
  font: inherit;
  font-size: 13px;
  letter-spacing: 0;
  text-transform: none;
  cursor: pointer;
  transition: color .2s ease, border-color .2s ease, background .2s ease;
}
.seasons button:hover { color: var(--ink); border-color: rgba(214, 230, 220, .35); }
.seasons button[aria-pressed="true"] { color: var(--ink); border-color: var(--mint); background: rgba(108, 199, 157, .08); }
.seasons button:focus-visible { outline: 1px solid var(--mint); outline-offset: 3px; }
.seasons i { width: 8px; height: 8px; border-radius: 50%; }
.seasons [data-season="autumn"] i { background: #c8692e; }
.seasons [data-season="winter"] i { background: #b8242c; }
.seasons [data-season="spring"] i { background: #a58bd6; }
.seasons [data-season="summer"] i { background: #e9a23b; }
/* Swapping clips: a short fade so the change reads as intended. */
.shot-video { transition: opacity .25s ease; }
.shot-video.is-swapping { opacity: .35; }
@media (max-width: 560px) {
  .seasons { gap: 6px; }
  .seasons button { padding: 6px 10px; gap: 6px; font-size: 12.5px; }
}
@media (max-width: 400px) {
  .seasons { gap: 5px; }
  .seasons button { padding: 6px 8px; gap: 5px; font-size: 12px; }
  .seasons i { width: 7px; height: 7px; }
}

/* ---------- the stage (wide screens) ----------
   The particles are drawn into a funnel at the right of the screen, its light
   floods the page cream, and the two projects play in turn on it, pinned:
   Hagendorf (its shop scrolling with the page), then Tonio. Then the cream
   drains back and the page is dark again for the closing call.
   js/projets-stage.js drives it; every project text and window shares one
   grid cell per column, stacked. The
   heights here must match the timeline in that script (PIN + 1 = 12.4 screens). */
@media (min-width: 961px) and (min-height: 600px) {
  /* The intro (and the funnel beside it, placed from it) sits 10% of the
     screen lower. */
  .intro { margin-top: 10vh; }
  .showcase { height: 1240vh; }
  .stage {
    position: sticky;
    top: 0;
    height: 100vh;
    display: grid;
    grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
    align-content: center;
    column-gap: clamp(40px, 5vw, 88px);
  }
  .stage .projet, .stage .projet-shots { display: contents; }
  .stage .projet-text { grid-area: 1 / 1; align-self: center; position: static; }
  /* (.projet-shots in the selector outranks the stacked layout's has-phone span.) */
  .stage .projet-shots .shot { grid-area: 1 / 2; align-self: start; }
  /* Windows fit the screen's height as well as the column's width. */
  .stage .shot:not(.shot-phone) { width: min(100%, calc((100vh - 230px) * 1.6)); justify-self: end; }
  /* Tonio's phone stands over the window's lower right corner. */
  .stage .projet-shots .shot-phone { justify-self: end; align-self: end; width: clamp(8.5rem, 11vw, 11rem); margin-right: -14px; }
  .stage .shot-phone figcaption { text-align: right; }
  /* The page's own scroll moves the shop now: no scrolling inside, no hint. */
  .stage .scroll-frame { overflow-y: hidden; }
  .stage .scroll-hint { display: none; }
  /* The stage moves its windows itself; the one-off reveal would pin their
     transform (its fill keeps transform: none). */
  .stage .shot.rise.in { animation: none; }
  .stage .projet-story dd { font-size: clamp(17px, 1.25vw, 20px); }
  .stage .projet-story { margin-bottom: 26px; }
  .stage .status { margin-bottom: 28px; }
}

/* The particle transition between two windows (js/projets-morph.js): in the
   stage, over the windows, under Tonio's phone (and the nav). */
#morph {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 1;
  pointer-events: none;
}
.stage .shot-phone { position: relative; z-index: 2; }
/* Its particles go over the phone. */
#morph-phone {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 3;
  pointer-events: none;
}
/* The phone's second screen (Tonio's work) sits exactly over its hero video;
   only the stage shows it. */
.phone-screen { position: relative; }
.shot-phone .phone-work { display: none; }
@media (min-width: 961px) and (min-height: 600px) {
  .shot-phone .phone-work {
    display: block;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    visibility: hidden;
  }
}

/* On the cream: light window chrome, a softer shadow. */
body.is-light .browser { background: #e4ddcd; }
body.is-light .browser span { background: rgba(15, 42, 31, .22); }
body.is-light .shot-main img, body.is-light .shot-main video, body.is-light .shot-main .browser { box-shadow: 0 30px 60px -36px rgba(15, 42, 31, .35); }
body.is-light .shot-phone .phone-screen { border-color: #e4ddcd; }
.browser, .browser span, .tags li, .status { transition: background .6s ease, border-color .6s ease, color .6s ease; }

/* ---------- closing call ---------- */
.outro {
  text-align: center;
  /* Room above the heading for the particle mark to re-form in. */
  padding-top: clamp(300px, 46vh, 460px);
  border-top: 1px solid var(--line);
}
.outro h2 { font-size: clamp(34px, 3.8vw, 56px); }
.outro .body { margin-left: auto; margin-right: auto; }

/* ---------- reveal ----------
   Armed only when JS runs; the animation lives on the element that gets .in. */
.js .rise { opacity: 0; }
.js .rise.in { animation: rise .9s cubic-bezier(.2, .7, .2, 1) both; }
@keyframes rise { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
.projet-text .rise.in:nth-child(2) { animation-delay: .06s; }
.projet-text .rise.in:nth-child(3) { animation-delay: .12s; }
.projet-text .rise.in:nth-child(4) { animation-delay: .18s; }
.projet-text .rise.in:nth-child(5) { animation-delay: .24s; }
.projet-text .rise.in:nth-child(6) { animation-delay: .3s; }

@media (prefers-reduced-motion: reduce) {
  @keyframes rise { from { opacity: 0; } to { opacity: 1; } }
  .status-dot { animation-duration: 5s; }
}

/* ---------- small screens ---------- */
/* No room beside the intro: the particle mark forms under it instead. */
@media (max-width: 1100px) {
  .intro { margin-bottom: clamp(300px, 44vh, 460px); }
}
@media (max-width: 960px) {
  .projet { grid-template-columns: minmax(0, 1fr); }
  .projet-text { position: static; }
}
@media (max-width: 820px) {
  .projets { padding: 150px 28px 96px; }
  .projet-story dd { font-weight: 400; }
  .browser { padding: 8px 10px; border-radius: 9px 9px 0 0; }
  .browser span { width: 6px; height: 6px; }
  .browser + img, .browser + video, .scroll-wrap { border-radius: 0 0 9px 9px; }
}
@media (max-width: 560px) {
  .projet-shots.has-phone { grid-template-columns: minmax(0, 1fr); }
  .shot-phone { width: 62%; justify-self: center; }
}
