/* Bike Fit Lab — scene3d.css · a sessão em cena 3D (fig-sessao3d.php)
 * CSS 3D real: .scene3d é o palco com perspective; .scene3d__world roda (preserve-3d) e contém os planos.
 * Unidades em cqw (largura do palco) para a profundidade escalar com a coluna. Estados: .is-step-1 … .is-step-9
 * no <figure>. Só transform e opacity animam; will-change só nos planos que se movem. Sem filtros nem sombras.
 * Dentro de .on-accent: --fg paper, --fg2 paper, --fg2-ink azul, --soft paper a 16 %, --paper azul.
 * Variáveis registadas (interpolam na transição): --yaw e --tilt (orientação do mundo), --orbit (órbita das etapas 4 e 6).
 */
@property --yaw { syntax: "<angle>"; inherits: true; initial-value: 0deg; }
@property --tilt { syntax: "<angle>"; inherits: true; initial-value: -10deg; }
@property --orbit { syntax: "<angle>"; inherits: true; initial-value: 0deg; }

.fig--sessao3d { max-width: none; margin-top: 2rem; outline-offset: 6px; }
.scene3d__sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

/* ===== Palco ===== */
.scene3d {
  position: relative; width: 100%; aspect-ratio: 4 / 3; overflow: hidden;
  container-type: inline-size;
  perspective: 170cqw; perspective-origin: 50% 40%;
  border: 1.5px solid var(--soft);
  pointer-events: none;
}
.scene3d__world {
  position: absolute; left: 50%; top: 50%; width: 0; height: 0;
  --k: 1;
  transform-style: preserve-3d;
  transform: scale3d(var(--k), var(--k), var(--k)) rotateX(var(--tilt)) rotateY(calc(var(--yaw) + var(--orbit)));
}
.scene3d__plane { position: absolute; left: 0; top: 0; }
.scene3d__plane > svg { display: block; width: 100%; height: 100%; overflow: visible; }

/* Posições (centro do plano em translate3d; chão em y = 24cqw) */
.scene3d__floor { width: 88cqw; height: 46cqw; margin: -23cqw 0 0 -44cqw; transform: translate3d(0, 24cqw, 0) rotateX(90deg); }
.scene3d__screen { width: 26cqw; height: 36cqw; margin: -18cqw 0 0 -13cqw; transform: translate3d(26cqw, 6cqw, -24cqw) rotateY(-18deg); }
.scene3d__cam { width: 46cqw; height: 30cqw; margin: -15cqw 0 0 -23cqw; }
.scene3d__cam--l { transform: translate3d(-23cqw, 9cqw, 6cqw) rotateY(18deg); }
.scene3d__cam--r { transform: translate3d(23cqw, 9cqw, 6cqw) rotateY(-18deg); }
.scene3d__bike { width: 54cqw; height: 36cqw; margin: -18cqw 0 0 -27cqw; transform: translate3d(0, 9.3cqw, 0); }
.scene3d__rider { width: 54cqw; height: 36cqw; margin: -18cqw 0 0 -27cqw; transform: translate3d(0, 9.3cqw, 2cqw); will-change: transform; }
.scene3d__cleat { width: 20cqw; height: 26cqw; margin: -13cqw 0 0 -10cqw; transform: translate3d(24cqw, 7cqw, 16cqw) scale(0.7); opacity: 0; will-change: transform, opacity; }
.scene3d__sheet { width: 14cqw; height: 18.4cqw; margin: -9.2cqw 0 0 -7cqw; transform: translate3d(26cqw, -3cqw, -22cqw) scale(0.35); opacity: 0; will-change: transform, opacity; }
.scene3d__tag, .scene3d__bubble { opacity: 0; width: max-content; max-width: 12rem; }
.scene3d__tag--saddle { transform: translate(-50%, -50%) translate3d(-22cqw, -4cqw, 1cqw); }
.scene3d__tag--crank { transform: translate(-50%, -50%) translate3d(-11cqw, 23cqw, 1cqw); }
.scene3d__bubble--talk { transform: translate(-50%, -50%) translate3d(16cqw, -22cqw, 4cqw); }
.scene3d__bubble--follow { transform: translate(-50%, -50%) translate3d(-22cqw, -19cqw, 8cqw); }

/* ===== Traços e preenchimentos ===== */
.s3-floor { fill: none; stroke: var(--fg); stroke-width: 2; opacity: 0.35; }
.s3-mat { fill: var(--soft); }
.s3-floor-line { stroke: var(--fg); stroke-width: 2; stroke-dasharray: 6 8; opacity: 0.3; }
.s3-foot-mark { fill: none; stroke: var(--fg); stroke-width: 2; opacity: 0.4; }

.s3-monitor { fill: var(--soft); stroke: var(--fg); stroke-width: 2; }
.s3-stand { stroke: var(--fg); stroke-width: 3; opacity: 0.75; }
.s3-stand--base { stroke-width: 5; }
.s3-screen-live polyline, .s3-screen-live circle { fill: none; stroke: var(--fg); stroke-width: 2; stroke-linecap: square; stroke-linejoin: miter; }
.s3-screen-live .s3-mini-j circle { fill: var(--fg); stroke: none; }
.s3-ui line { stroke: var(--fg); stroke-width: 3; }
.s3-screen-live { opacity: 0.35; }
.s3-screen-sheet line { stroke: var(--fg); stroke-width: 2.5; }
.s3-screen-sheet { opacity: 0; }

.s3-tripod { fill: none; stroke: var(--fg); stroke-width: 2.5; stroke-linecap: square; stroke-linejoin: miter; opacity: 0.85; }
.s3-camhead rect { fill: var(--paper); stroke: var(--fg); stroke-width: 2.5; }
.s3-camhead circle { fill: var(--fg2); }
.s3-beam { fill: var(--fg2); opacity: 0; }
.s3-sweep { stroke: var(--fg2); stroke-width: 1.5; opacity: 0; transform-box: view-box; transform-origin: 54px 60px; }

.s3-trainer-base { stroke: var(--fg); stroke-width: 5; stroke-linecap: square; }
.s3-trainer-body { fill: var(--soft); stroke: var(--fg); stroke-width: 2; stroke-linejoin: miter; }
.s3-fly circle { fill: var(--paper); stroke: var(--fg); stroke-width: 2.5; }
.s3-fly line { stroke: var(--fg); stroke-width: 2; stroke-linecap: square; }
.s3-fly { transform-box: fill-box; transform-origin: center; }
.s3-hub { fill: var(--fg); }
.fig--sessao3d .f-bike { opacity: 0.85; }
.s3-flags { opacity: 0; }
.s3-flags rect { fill: var(--fg2); }
.s3-flags line { stroke: var(--fg2); stroke-width: 1.5; }
.s3-adj { fill: none; stroke: var(--fg2); stroke-width: 2.5; stroke-linecap: square; stroke-linejoin: miter; opacity: 0; }
.s3-dims { opacity: 0; }
.s3-pose, .s3-stand, .s3-marks { opacity: 0; }
.s3-marks .f-joints circle { transform-box: fill-box; transform-origin: center; }

.s3-card { fill: var(--paper); stroke: var(--fg); stroke-width: 2; }
.s3-sole { fill: var(--soft); stroke: var(--fg); stroke-width: 3; stroke-linejoin: miter; }
.s3-cleat { fill: var(--paper); stroke: var(--fg); stroke-width: 3; stroke-linejoin: miter; }
.s3-slot { fill: var(--fg); }
.s3-foot { fill: none; stroke: var(--fg); stroke-width: 2.5; stroke-dasharray: 6 5; opacity: 0.6; }
.s3-axle { stroke: var(--fg2); stroke-width: 3; stroke-linecap: square; }

.s3-paper { fill: var(--fg); stroke: none; }
.s3-paper-lines line { stroke: var(--fg2-ink); stroke-width: 2.5; stroke-linecap: square; }

.scene3d__tag span { display: block; background: var(--fg2); color: var(--fg2-ink); font-size: 13px; font-weight: 600; line-height: 1.2; padding: 0.3rem 0.55rem; white-space: nowrap; }
.scene3d__bubble { position: absolute; background: var(--fg); color: var(--fg2-ink); font-size: 14px; line-height: 1.35; padding: 0.5rem 0.75rem; text-align: left; }
.scene3d__bubble::after { content: ""; position: absolute; left: 1rem; bottom: -0.3rem; width: 0.6rem; height: 0.6rem; background: var(--fg); transform: rotate(45deg); }
.scene3d__bubble--follow b { display: block; font-size: 1.25rem; font-weight: 600; line-height: 1.1; }
.scene3d__bubble--follow span { display: block; font-size: 13px; }

/* ===== Transições (só depois de scene3d.js arrancar: .is-live) ===== */
.fig--sessao3d.is-live .scene3d__world { transition: --yaw 800ms var(--ease-in-out), --tilt 800ms var(--ease-in-out), --orbit 800ms var(--ease-in-out); }
.fig--sessao3d.is-live .scene3d__plane { transition: transform 800ms var(--ease-in-out), opacity 600ms var(--ease-in-out); }
.fig--sessao3d.is-live .s3-saddle, .fig--sessao3d.is-live .s3-bars { transition: transform 900ms var(--ease-in-out); }
.fig--sessao3d.is-live :is(.s3-pose, .s3-stand, .s3-marks, .s3-beam, .s3-sweep, .s3-flags, .s3-adj, .s3-dims, .s3-screen-live, .s3-screen-sheet) { transition: opacity 600ms var(--ease-in-out); }

/* ===== Estados por etapa =====
 * --tilt negativo = vista de cima; --yaw negativo = vista de três quartos pela esquerda. */
.fig--sessao3d.is-step-1 { --tilt: -10deg; --yaw: -28deg; }
.fig--sessao3d.is-step-2 { --tilt: -8deg; --yaw: -16deg; }
.fig--sessao3d.is-step-3 { --tilt: -30deg; --yaw: -14deg; }
.fig--sessao3d.is-step-4 { --tilt: -12deg; --yaw: 0deg; }
.fig--sessao3d.is-step-5 { --tilt: -12deg; --yaw: 24deg; }
.fig--sessao3d.is-step-6 { --tilt: -12deg; --yaw: 0deg; }
.fig--sessao3d.is-step-7 { --tilt: -10deg; --yaw: -12deg; }
.fig--sessao3d.is-step-8 { --tilt: -4deg; --yaw: 0deg; }
.fig--sessao3d.is-step-9 { --tilt: -10deg; --yaw: -22deg; }

/* 1 Entrevista: ciclista na bicicleta, balão de conversa, câmaras apagadas */
.fig--sessao3d.is-step-1 .s3-pose--a { opacity: 1; }
.fig--sessao3d.is-step-1 .scene3d__bubble--talk { opacity: 1; }

/* 2 Avaliação e 3 Pé/sapato/cleat: o ciclista sai da bicicleta (o plano desliza) e aparecem as marcas de mobilidade */
.fig--sessao3d.is-step-2 .scene3d__rider, .fig--sessao3d.is-step-3 .scene3d__rider { transform: translate3d(-30cqw, 9.3cqw, 6cqw); }
.fig--sessao3d.is-step-2 .s3-stand, .fig--sessao3d.is-step-3 .s3-stand { opacity: 1; }

/* 3: a câmara desce e a sola com o cleat entra em primeiro plano */
.fig--sessao3d.is-step-3 .scene3d__cleat { opacity: 1; transform: translate3d(31cqw, 4cqw, 22cqw) scale(1); }

/* 4 Movimento 3D: o mundo orbita, as câmaras ligam os feixes, as articulações pulsam, os arcos aparecem */
@keyframes s3-orbit { 0%, 100% { --orbit: 0deg; } 25% { --orbit: 35deg; } 75% { --orbit: -35deg; } }
@keyframes s3-sweep { from { transform: rotate(-13deg); } to { transform: rotate(13deg); } }
@keyframes s3-spin { to { transform: rotate(360deg); } }
@keyframes s3-pulse { from { transform: scale(1); opacity: 1; } to { transform: scale(1.8); opacity: 0.45; } }
.fig--sessao3d.is-step-4 .scene3d__world, .fig--sessao3d.is-step-6 .scene3d__world { animation: s3-orbit 8s var(--ease-in-out) infinite; }
.fig--sessao3d.is-step-4 .s3-pose--a { opacity: 1; }
.fig--sessao3d.is-step-4 .s3-pose--a .s3-marks, .fig--sessao3d.is-step-6 .s3-pose--b .s3-marks { opacity: 1; }
.fig--sessao3d.is-step-4 .s3-marks .f-joints circle { animation: s3-pulse 1.1s var(--ease-in-out) infinite alternate; }
.fig--sessao3d.is-step-4 .s3-beam, .fig--sessao3d.is-step-6 .s3-beam { opacity: 0.25; }
.fig--sessao3d.is-step-4 .s3-sweep, .fig--sessao3d.is-step-6 .s3-sweep { opacity: 0.7; animation: s3-sweep 2.2s var(--ease-in-out) infinite alternate; }
.fig--sessao3d.is-step-6 .scene3d__cam--r .s3-sweep { animation-direction: alternate-reverse; }
.fig--sessao3d.is-step-4 .s3-fly, .fig--sessao3d.is-step-6 .s3-fly { animation: s3-spin 2.4s linear infinite; }
.fig--sessao3d.is-step-4 .s3-screen-live, .fig--sessao3d.is-step-6 .s3-screen-live { opacity: 1; }

/* 5 Ajustes: o selim sobe e recua, o guiador desce; a partir daqui a posição é a nova */
.fig--sessao3d:is(.is-step-5, .is-step-6, .is-step-7, .is-step-8, .is-step-9) .s3-saddle { transform: translate(-2px, -5px); }
.fig--sessao3d:is(.is-step-5, .is-step-6, .is-step-7, .is-step-8, .is-step-9) .s3-bars { transform: translate(0, 5px); }
.fig--sessao3d:is(.is-step-5, .is-step-6, .is-step-7, .is-step-8, .is-step-9) .s3-pose--b { opacity: 1; }
.fig--sessao3d.is-step-5 .s3-adj { opacity: 1; }

/* 7 Recomendações: etiquetas de componente */
.fig--sessao3d.is-step-7 .scene3d__tag { opacity: 1; }
.fig--sessao3d.is-step-7 .s3-flags { opacity: 1; }

/* 8 Medições finais: cotas; a ficha nasce no ecrã */
.fig--sessao3d.is-step-8 .s3-dims { opacity: 1; }
.fig--sessao3d.is-step-8 .s3-screen-sheet, .fig--sessao3d.is-step-9 .s3-screen-sheet { opacity: 1; }
.fig--sessao3d.is-step-8 .s3-screen-live, .fig--sessao3d.is-step-9 .s3-screen-live { opacity: 0; }
.fig--sessao3d.is-step-8 .scene3d__sheet { opacity: 1; }

/* 9 Acompanhamento: a ficha sai do ecrã para a frente; fica o balão "2 meses" */
.fig--sessao3d.is-step-9 .scene3d__sheet { opacity: 1; transform: translate3d(33cqw, -3cqw, 18cqw) scale(1); }
.fig--sessao3d.is-step-9 .scene3d__bubble--follow { opacity: 1; }

/* ===== Controlo: rótulo da etapa, nove pontos, pausa (só com JS) ===== */
.scene3d__ctl { display: none; }
.js .scene3d__ctl { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 1rem; margin-top: 0.75rem; }
.scene3d__label { flex: 1 1 auto; display: flex; align-items: center; gap: 0.6rem; margin: 0; font-size: 15px; line-height: 1.3; min-height: 2.75rem; }
.scene3d__dots { flex: 1 1 100%; }
.scene3d__num { display: inline-grid; place-items: center; flex: 0 0 auto; width: 1.5rem; height: 1.5rem; background: var(--fg2); color: var(--fg2-ink); font-weight: 600; font-size: 13px; }
.scene3d__dots { display: flex; margin: 0 0 0 -0.75rem; padding: 0; list-style: none; }
.scene3d__dots button { display: grid; place-items: center; width: 2.75rem; height: 2.75rem; }
.scene3d__dots button::before { content: ""; width: 0.625rem; height: 0.625rem; background: var(--fg); opacity: 0.4; transition: opacity var(--t-ui) ease, width var(--t-ui) ease, height var(--t-ui) ease; }
.scene3d__dots button[aria-pressed="true"]::before { opacity: 1; width: 0.875rem; height: 0.875rem; }
@media (hover: hover) and (pointer: fine) { .scene3d__dots button:hover::before { opacity: 0.8; } }
.scene3d__play { margin-left: auto; min-height: 2.75rem; padding: 0 0.8rem; border: 1.5px solid var(--fg); color: var(--fg); font-size: 13px; font-weight: 600; }
@media (hover: hover) and (pointer: fine) { .scene3d__play:hover { background: var(--fg); color: var(--fg2-ink); } }
.fig--sessao3d figcaption { margin-top: 0.75rem; }

/* A linha da etapa ativa no talão (ligação feita por scene3d.js) e a dica, só com JS */
.js .steps .slip__row.is-active { background: var(--surface); margin-inline: -0.75rem; padding-inline: 0.75rem; }
.js .steps .slip__row { transition: background-color var(--t-ui) ease; cursor: pointer; }
.scene3d__hint { display: none; }
.js .scene3d__hint { display: block; max-width: var(--measure); }

/* ===== Telemóvel: palco quadrado, mundo um pouco maior e mais alto ===== */
@media (max-width: 56.24em) {
  .scene3d { aspect-ratio: 1 / 1; perspective-origin: 50% 42%; }
  .scene3d__world { --k: 1.1; top: 47%; }
  .fig--sessao3d.is-step-3 .scene3d__cleat { transform: translate3d(27cqw, 4cqw, 22cqw) scale(1); }
  .fig--sessao3d.is-step-9 .scene3d__sheet { transform: translate3d(30cqw, -3cqw, 18cqw) scale(1); }
  .scene3d__dots button { width: 2.25rem; }
  .scene3d__dots { margin-left: -0.5rem; }
}

/* ===== Movimento reduzido: sem órbita, varrimentos nem pulsos; os estados mudam por clique ===== */
@media (prefers-reduced-motion: reduce) {
  .fig--sessao3d:is(.is-step-4, .is-step-6) .scene3d__world,
  .fig--sessao3d:is(.is-step-4, .is-step-6) .s3-sweep,
  .fig--sessao3d:is(.is-step-4, .is-step-6) .s3-fly,
  .fig--sessao3d.is-step-4 .s3-marks .f-joints circle { animation: none; }
  .fig--sessao3d:is(.is-step-4, .is-step-6) .s3-sweep { transform: none; }
  .fig--sessao3d.is-live .scene3d__world, .fig--sessao3d.is-live .scene3d__plane, .fig--sessao3d.is-live .s3-saddle, .fig--sessao3d.is-live .s3-bars { transition: none; }
}
