/* =============================================================
   FASE 02 — Sistema de cases
   Primeiro conteúdo: NVFASE.

   Isto não é a secção da NVFASE. É a gramática com que qualquer
   trabalho entra no site. A NVFASE contribui com três imagens,
   dois textos de anotação e um parágrafo — tudo o resto aqui é
   reutilizável sem alterações.

   .case              invólucro          data-depth="featured|selected"
   .case__intro       frontispício
   .case__anchor      nome persistente
   .case__sequence    lista de momentos
     .moment          palco              data-hold="<ecrãs de fixação>"
     .moment__frame   uma peça no palco
     .mark            anotação editorial --mx --my
   .case__context     texto, depois

   PARA REVERTER: repor a pasta madebyrc-site-v2-fase01b.
   style.css e main.js não foram tocados.
   ============================================================= */

.case {
  /* Uma só declaração de colunas, partilhada pelo palco e pelas
     marcas — é o que garante que o filete de uma anotação começa
     exatamente onde a imagem começa. */
  --case-cols: minmax(0, 2.4fr) minmax(0, 9.6fr);
  --case-gap: clamp(1.5rem, 3vw, 2.75rem);
  --anchor-h: 2.75rem;
  --stage-top: calc(var(--rc-head, 5rem) + var(--anchor-h));
}

/* ---------- Frontispício ---------- */

.case__intro {
  display: grid;
  gap: clamp(1.75rem, 4vw, 2.5rem);
  padding-bottom: clamp(2.5rem, 6vw, 4rem);
}

.case__name {
  font-size: clamp(2.1rem, 5.2vw, 4.25rem);
  font-weight: 500;
  letter-spacing: -.03em;
  line-height: 1;
  margin: 0 0 .55em;
}

.case__desc {
  font-size: clamp(1.0625rem, 1.35vw, 1.1875rem);
  line-height: 1.5;
  color: var(--graphite);
  max-width: 42ch;
  margin: 0;
}

.case__meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.5rem;
}

.case__disciplines {
  display: flex;
  flex-wrap: wrap;
  gap: .25rem 1.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--mute);
  line-height: 1.9;
}

@media (min-width: 860px) {
  .case__intro { grid-template-columns: 1fr auto; align-items: end; }
  .case__meta { align-items: flex-end; text-align: right; }
  .case__disciplines { flex-direction: column; align-items: flex-end; gap: 0; }
}

/* ---------- Âncora ----------
   O nome fica no topo durante toda a sequência. A lição da Nothin':
   persistência produz mais presença do que escala. É por isso que
   o nome no frontispício não precisa de ser enorme. */

.case__anchor {
  position: sticky;
  top: var(--rc-head, 5rem);
  z-index: 5;
  background: var(--paper);
  height: var(--anchor-h);
  display: flex;
  align-items: center;
}

.case__anchor-inner {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  border-bottom: 1px solid var(--rule);
  padding-bottom: .55rem;
}

.case__anchor-name {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: .17em;
  text-transform: uppercase;
}

.case__anchor-note {
  font-size: var(--fs-label);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--mute);
}

/* ---------- Momento ---------- */

.moment {
  view-timeline-name: --moment;
  view-timeline-axis: block;
}

/* NOTA: a altura extra de um palco fixo vive junto da regra de
   fixação, lá em baixo, dentro das mesmas guardas. Se ficasse aqui,
   um telemóvel — ou um browser sem scroll-driven animations —
   herdaria dois ecrãs e meio de vazio sem nada preso lá dentro. */

.moment__stage { padding-block: clamp(2rem, 5vw, 3.5rem); }

.moment__grid {
  position: relative;
  display: grid;
  gap: var(--case-gap);
}

.moment__title {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--mute);
  margin: 0;
}

/* As peças empilham-se na mesma célula: o palco não muda, muda a peça. */
.moment__frames { display: grid; }
.moment__frame { grid-area: 1 / 1; margin: 0; }

/* O rácio é conteúdo, não sistema: o momento declara-o e as
   molduras herdam-no. Substitui os modificadores .shot--* antigos,
   que ficavam presos ao nome de um projeto. */
.moment[data-fit="portrait"] { --ar: 9 / 19.5; }

/* Em telemóvel, uma captura de desktop a 342px de largura seria
   ilegível. Recorte quadrado — a mesma decisão da Fase 01B, agora
   expressa dentro do sistema de cases. */
@media (max-width: 859px) {
  .moment:not([data-fit="portrait"]) .shot__frame { --ar: 1 / 1; }
}

/* ---------- Marca editorial ----------
   Um filete que sai da margem até um ponto da imagem, com um
   marcador na ponta e a nota ao lado. É a marca que se faz a lápis
   numa prova impressa. Sem caixa, sem seta, sem sombra. */

.mark { display: grid; gap: var(--case-gap); }

.mark__note {
  font-size: .8125rem;
  line-height: 1.5;
  color: var(--graphite);
  margin: 0;
}

.mark__note b {
  display: block;
  font-family: var(--serif, Georgia, serif);
  font-style: italic;
  font-weight: 400;
  color: var(--ink);
  font-size: .9375rem;
  margin-bottom: .35rem;
}

.mark__lead { position: relative; height: 1px; }

.mark__lead::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--mx, 50%);
  height: 1px;
  background: var(--ink);
  transform-origin: left;
}

.mark__lead::after {
  content: "";
  position: absolute;
  top: -2px;
  left: var(--mx, 50%);
  width: 5px;
  height: 5px;
  margin-left: -2.5px;
  background: var(--ink);
  border-radius: 50%;
}

/* ---------- Contexto ---------- */

.case__context {
  display: grid;
  gap: 1rem;
  margin-top: clamp(3rem, 7vw, 5rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
}

.case__context-body {
  font-size: clamp(1.0625rem, 1.35vw, 1.1875rem);
  line-height: 1.6;
  color: var(--graphite);
  max-width: 58ch;
  margin: 0;
}

@media (min-width: 860px) {
  .case__context { grid-template-columns: minmax(0,3fr) minmax(0,8fr); gap: var(--gutter); }
  .case__context-label { padding-top: .35em; }
}

/* =============================================================
   DESKTOP — o palco espacial
   ============================================================= */
@media (min-width: 860px) {

  .moment__grid { grid-template-columns: var(--case-cols); }

  /* A margem editorial não é decoração: é ela que mantém a imagem
     abaixo dos 1200 CSS, que é o limite de nitidez dos assets
     atuais a DPR 2. A composição e a resolução concordam. */
  .moment__margin {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
  }

  /* left/right pelo gutter, não 0: o contentor é um .wrap com
     padding, e uma caixa absoluta alinha pela padding box enquanto
     as colunas da grelha se calculam sobre a content box. Sem isto
     o filete da marca fica mais comprido do que a imagem. */
  .mark {
    position: absolute;
    left: var(--gutter);
    right: var(--gutter);
    top: var(--my, 50%);
    grid-template-columns: var(--case-cols);
    align-items: start;
  }

  .mark__note { text-align: right; margin-top: -.6em; }
  .mark__lead { align-self: start; margin-top: .1em; }

  /* Uma peça em retrato não pode ocupar a coluna toda: a 950px de
     largura teria 2000px de altura. Fica contida, e o filete da
     marca contrai-se com ela para que --mx continue a significar
     «percentagem da imagem» e não «percentagem da coluna». */
  .moment[data-fit="portrait"] { --frame-max: 360px; }
  .moment[data-fit="portrait"] .moment__frames,
  .moment[data-fit="portrait"] .mark__lead { max-width: var(--frame-max); }
}

/* =============================================================
   MOBILE — sequência editorial vertical
   Sem fixação: quatro ecrãs presos num telemóvel leem-se como
   «a página encravou». A identidade mantém-se, a coreografia não.
   ============================================================= */
@media (max-width: 859px) {

  .moment { min-height: 0; }

  .moment__frames { gap: clamp(2rem, 6vw, 3rem); }
  .moment__frame { grid-area: auto; }

  .moment__margin { margin-bottom: 1.25rem; }

  /* Sem margem lateral, a marca passa para baixo da imagem: um
     filete vertical a apontar para cima, e a nota por baixo. */
  .mark {
    margin-top: 1rem;
    padding-left: 1.75rem;
    position: relative;
  }

  .mark__lead { height: auto; }

  .mark__lead::before {
    inset: -1rem auto auto .5rem;
    width: 1px;
    height: 1.75rem;
    transform-origin: top;
  }

  .mark__lead::after {
    top: -1rem;
    left: .5rem;
  }

  .mark__note { text-align: left; }
}

/* =============================================================
   MOVIMENTO — sob as mesmas duas guardas da Fase 01B.
   Sem suporte ou com movimento reduzido: os palcos deixam de ser
   fixos, as peças ficam todas visíveis empilhadas, as marcas ficam
   desenhadas. A coreografia desaparece; a narrativa fica inteira.
   ============================================================= */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {

    @media (min-width: 860px) {
      /* Altura do percurso e fixação, sempre juntas. */
      .moment[data-stage="pinned"] {
        min-height: calc((1 + var(--hold, 1)) * 100svh);
      }

      .moment[data-stage="pinned"] .moment__stage {
        position: sticky;
        top: var(--stage-top);
        min-height: calc(100svh - var(--stage-top));
        display: flex;
        flex-direction: column;
        justify-content: center;
      }

      /* A abertura. A imagem não muda de escala em momento nenhum —
         só a janela por onde se vê. Zero custo de resolução, e é o
         gesto certo: a atenção alarga, não se aproxima. */
      .moment__frame[data-frame="0"] {
        animation: rc-aperture linear both;
        animation-timeline: --moment;
        animation-range: contain 0% contain 34%;
      }

      @keyframes rc-aperture {
        from { clip-path: inset(0 0 38% 0); }
        to   { clip-path: inset(0 0 0 0); }
      }

      /* A troca de peça. O palco fica quieto. */
      .moment__frame[data-frame="0"][data-fades] {
        animation:
          rc-aperture linear both,
          rc-piece-out linear both;
        animation-timeline: --moment, --moment;
        animation-range: contain 0% contain 34%, contain 54% contain 66%;
      }

      .moment__frame[data-frame="1"] {
        opacity: 0;
        animation: rc-piece-in linear both;
        animation-timeline: --moment;
        animation-range: contain 54% contain 66%;
      }

      @keyframes rc-piece-out { to { opacity: 0; } }
      @keyframes rc-piece-in  { to { opacity: 1; } }

      /* As marcas. O traço chega primeiro, a palavra depois —
         como numa prova. */
      .mark { opacity: 0; }

      .mark__lead::before { transform: scaleX(0); }

      .mark[data-at] {
        animation: rc-mark-in linear both;
        animation-timeline: --moment;
        animation-range: contain var(--at-from) contain var(--at-to);
      }

      .mark[data-at] .mark__lead::before {
        animation: rc-lead-draw linear both;
        animation-timeline: --moment;
        animation-range: contain var(--at-from) contain var(--at-to);
      }

      @keyframes rc-mark-in {
        0%   { opacity: 0; }
        35%  { opacity: 0; }
        100% { opacity: 1; }
      }

      @keyframes rc-lead-draw {
        0%  { transform: scaleX(0); }
        60% { transform: scaleX(1); }
        100%{ transform: scaleX(1); }
      }
    }

    /* Mobile: só as marcas aparecem, e sem fixação nenhuma. */
    @media (max-width: 859px) {
      .mark {
        opacity: 0;
        animation: rc-mark-in linear both;
        animation-timeline: view();
        animation-range: entry 20% entry 80%;
      }
      .mark__lead::before {
        transform: scaleY(0);
        animation: rc-lead-draw-v linear both;
        animation-timeline: view();
        animation-range: entry 20% entry 70%;
      }
      @keyframes rc-lead-draw-v { to { transform: scaleY(1); } }
    }
  }
}
