/* Kiwimoov — /show, page vitrine scrollytelling (palier 1) */

/* ── TOKENS ── */
.show-page {
  --dot-size: 16px;
  --spine-w: 3px;
  --gutter: 28px;
  --header-h: 64px;
}

.show-page {
  background: var(--bg);
  /* Safety net: an off-screen absolutely-positioned element (e.g. an
     icon-only popover near a viewport edge) still counts toward the page's
     scrollable width even while invisible (opacity:0), which silently
     creates a horizontal scrollbar and throws off anything centered via
     viewport width. Clipping here costs nothing for in-bounds content. */
  overflow-x: hidden;
}

/* ── HEADER ──
   Not useful once scrolling through the timeline (the wordmark/contact
   chips only make sense over the hero), and `fixed` used to collide with
   the sticky "sans/avec" headers once those reached the same y. Absolute
   instead of fixed: still sits over the hero on load, then scrolls away
   with the page and never comes back. */
.show-header {
  position: absolute;
  top: 16px;
  left: 16px;
  right: 16px;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  pointer-events: none;
}

.show-wordmark,
.show-contact-trigger {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: rgba(24, 23, 21, 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--text-on-dark);
  font-weight: 600;
  font-size: 14px;
  text-decoration: none;
  padding: 8px 16px;
  border-radius: var(--r-pill);
  text-transform: lowercase;
}

.show-contact-trigger {
  text-transform: none;
}

/* ── HERO ── */
.show-hero {
  position: relative;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  text-align: center;
  padding: calc(var(--header-h) + 48px) 24px 64px;
  color: var(--text-on-dark);
}

.show-hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.show-hero-video,
.show-hero-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.show-hero-video {
  z-index: 1;
}

.show-hero-poster {
  z-index: 0;
}

.show-hero-vignette {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: linear-gradient(
    to bottom,
    rgba(17, 17, 17, 0.55) 0%,
    rgba(17, 17, 17, 0.45) 45%,
    rgba(17, 17, 17, 0.75) 100%
  );
}

.show-hero-content {
  position: relative;
  z-index: 3;
  max-width: 640px;
}

.show-hero-content h1 {
  font-size: clamp(1.75rem, 5vw, 3rem);
  line-height: 1.2;
  margin: 0 0 32px;
}

.show-hero-highlight-secondary {
  color: var(--secondary);
}

.show-hero-actions {
  display: flex;
  justify-content: center;
}

.show-cta {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-width: 56px;
  min-height: 56px;
  padding: 16px 32px;
  border-radius: var(--r-pill);
  background: var(--primary);
  color: #12140d;
  font-weight: 700;
  font-size: 16px;
  text-decoration: none;
  transition: padding 0.3s ease, width 0.3s ease, background 0.2s ease;
}

.show-cta:hover {
  background: var(--primary-dark);
  color: #fff;
}

.show-cta-label {
  transition: opacity 0.25s ease, transform 0.25s ease;
}

.show-cta-arrow {
  position: absolute;
  display: grid;
  place-items: center;
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 0.25s ease, transform 0.25s ease;
}

.show-cta[data-state="scrolled"] {
  padding: 16px;
  width: 56px;
}

.show-cta[data-state="scrolled"] .show-cta-label {
  opacity: 0;
  transform: translateY(6px);
  position: absolute;
}

.show-cta[data-state="scrolled"] .show-cta-arrow {
  opacity: 1;
  transform: translateY(0);
  animation: show-bounce 1.6s ease-in-out infinite;
}

@keyframes show-bounce {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(5px);
  }
}

/* ── TIMELINE SECTION ── */
.show-timeline {
  position: relative;
  padding: 96px 24px 140px;
}

.show-timeline-intro {
  max-width: 640px;
  margin: 0 auto 40px;
  text-align: center;
}

.show-timeline-tagline {
  margin: 0 0 12px;
  font-size: 16px;
  color: var(--text-muted);
}

.show-timeline-lead-in {
  margin: 20px 0 0;
  font-size: 15px;
  font-weight: 700;
  color: var(--text-strong);
}

.show-intro-highlight-primary {
  color: var(--primary-dark);
  font-weight: 700;
}

.show-intro-highlight-secondary {
  color: var(--secondary-dark);
  font-weight: 700;
}

.timeline-dot {
  position: fixed;
  top: 50vh;
  left: 50%;
  transform: translate(-50%, -50%);
  width: var(--dot-size);
  height: var(--dot-size);
  border-radius: 50%;
  background: var(--primary);
  box-shadow: 0 0 0 6px var(--primary-soft), 0 2px 12px rgba(151, 170, 58, 0.5);
  z-index: 1; /* background layer, just above the spine (0) — every card renders in front of it */
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s ease;
  pointer-events: none;
}

.timeline-dot.is-visible {
  opacity: 1;
  visibility: visible;
}

.timeline-track {
  position: relative;
  max-width: 960px;
  margin: 0 auto;
}

.timeline-spine {
  position: absolute;
  left: 50%;
  width: var(--spine-w);
  transform: translateX(-50%);
  z-index: 0;
}

/* Split in two by JS (timeline-observer.js) right at the "À venir" marker:
   solid line for what's shipped, dashed for the roadmap items after it.
   Heights/offsets default to a full solid line until JS measures the split. */
.timeline-spine-solid {
  top: 0;
  height: 100%;
  background: var(--border-md);
}

.timeline-spine-dashed {
  top: 100%;
  bottom: 0;
  background-image: linear-gradient(var(--border-md) 50%, transparent 50%);
  background-size: 100% 10px;
  background-repeat: repeat-y;
}

.node-pane[data-pane-side="upcoming-marker"] {
  flex: none;
  width: min(260px, 85%);
  text-align: center;
  padding: 14px 28px;
  border: 2px dashed var(--primary);
  border-radius: var(--r-pill);
}

.node-pane[data-pane-side="upcoming-marker"] h3 {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--primary-dark);
}

.timeline-node[data-step-kind="upcoming-marker"] .node-row {
  justify-content: center;
}

.timeline-headers {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  justify-content: space-between;
  padding: 20px 0 32px;
  background: var(--bg);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  pointer-events: none;
}

.timeline-header {
  flex: 1;
}

.timeline-header[data-pane-side="without"] {
  text-align: right;
  padding-right: calc(var(--gutter) + 24px);
  color: var(--text-faint);
}

.timeline-header[data-pane-side="with"] {
  text-align: left;
  padding-left: calc(var(--gutter) + 24px);
  color: var(--primary-dark);
}

.timeline-nodes {
  position: relative;
  z-index: 2; /* above the dot (1): default (non-shared) panes cover it too, not just the explicitly z-indexed cards below */
  list-style: none;
  margin: 0;
  padding: 0;
}

.timeline-node {
  display: flex;
  align-items: center;
  min-height: var(--dwell, 18vh);
}

/* Wraps the two panes as a single unit: the node centers this whole row
   vertically (even breathing room above/below within the dwell height),
   while the row itself top-aligns the panes so titles on both sides land
   at the same y regardless of how much text follows underneath. */
.node-row {
  position: relative; /* anchors the JS-inserted centering marker used to detect activation */
  display: flex;
  align-items: flex-start;
  width: 100%;
}

.timeline-node[data-step-kind="shared"] .node-row {
  justify-content: center;
}

.node-pane {
  flex: 1;
}

.node-pane[data-pane-side="shared"] {
  flex: none;
  width: min(260px, 80%);
  text-align: center;
  position: relative;
  z-index: 45; /* .timeline-nodes (2) already clears the dot (1); kept high so this card also wins over any sibling content */
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 14px 20px;
  box-shadow: var(--shadow-sm);
}

.node-pane[data-pane-side="shared"] h3 {
  font-size: 1.15rem;
}

.node-pane[data-pane-side="without"] {
  text-align: right;
  padding-right: calc(var(--gutter) + 24px);
}

/* "Rien..." — deliberately outside the normal reveal system: static, no
   animation, centered in the "sans" column (not aligned toward the spine
   like the rest of that column), permanently at the same visual size an
   active "avec" title reaches (its scale(1.05), baked in since this one
   never animates into that state). */
.node-pane[data-pane-side="filler"] {
  flex: 1;
  text-align: center;
  padding: 0 24px;
}

html.js .node-pane[data-pane-side="filler"] {
  opacity: 1;
  transform: scale(1.05);
  transition: none;
}

.node-pane[data-pane-side="with"] {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 8px;
  position: relative; /* anchors the icon-only popover */
  text-align: left;
  padding-left: calc(var(--gutter) + 24px);
}

.node-event-text {
  flex: 1;
  flex-basis: 100%;
  min-width: 0;
}

.node-icon-trigger {
  all: unset;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  padding: 4px;
  cursor: default;
}

.node-icon {
  width: 20px;
  height: 20px;
  color: var(--border-md);
}

/* Small connector between two concept icons in one compact entry (e.g.
   capture+share -> notify), not a concept of its own. */
.node-icon-chain-arrow {
  width: 14px;
  height: 14px;
  opacity: 0.5;
}

.timeline-node[data-role="prof"] .node-icon {
  color: var(--secondary);
}

.timeline-node[data-role="eleve"] .node-icon {
  color: var(--primary);
}

.node-pane h3 {
  font-size: clamp(1.1rem, 2vw, 1.4rem);
  margin: 0 0 8px;
}

.node-pane p {
  margin: 0;
  font-size: 14px;
  color: var(--text-muted);
}

.node-pane[data-pane-side="without"] h3 {
  color: var(--text-muted);
}

.node-pane[data-pane-side="with"] h3 {
  color: var(--primary-dark);
}

/* Role color-coding (kept on the text/marker directly — no more badge pill).
   Scoped to the "with" pane only: the "sans" side (e.g. the WhatsApp entry)
   must stay neutral/muted regardless of which role the "avec" side shows. */
.timeline-node[data-role="prof"] .node-pane[data-pane-side="with"] h3 {
  color: var(--secondary-dark);
}

.timeline-node[data-role="eleve"] .node-pane[data-pane-side="with"] h3 {
  color: var(--primary-dark);
}

.node-marker {
  position: absolute;
  top: 16px;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--border-md);
  z-index: 3;
}

.timeline-node[data-role="prof"] .node-marker {
  background: var(--secondary);
}

.timeline-node[data-role="eleve"] .node-marker {
  background: var(--primary);
}

/* Its own connector node now (data-node-type="connector"), sitting at icon
   level like a real entry — just without a marker dot or text. */
.node-flow-arrow {
  color: var(--primary);
  opacity: 0.6;
}

/* No slide/scale/fade for the connector's icon — it's a static bit of
   punctuation between two entries, not an entry animating in itself. */
html.js .timeline-node[data-node-type="connector"] .node-pane {
  opacity: 1;
  transform: none;
  transition: none;
}

/* One filler word covers a whole gap between central cards (not one per
   event) — sized like the titles opposite it so it reads as a real answer,
   not a footnote. */
.node-filler {
  margin: 0;
  font-size: clamp(1.1rem, 2vw, 1.4rem);
  font-weight: 700;
  color: var(--text-muted);
}

/* Icon-only repeats: the first occurrence of a data-event-type explains
   itself in full; later ones collapse to just the icon (see event-icons.js),
   with the title/description unfolding in normal flow below the icon on
   hover or click/tap — not a floating popup — click is what keeps this
   reachable without a mouse. */
html.js .timeline-node.is-icon-only .node-icon-trigger {
  cursor: pointer;
}

html.js .timeline-node.is-icon-only .node-event-text {
  flex-basis: 100%;
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-height 0.3s ease, opacity 0.3s ease;
}

/* Scoped to the trigger's own :hover/:focus (not the whole tall
   .timeline-node, whose dwell height would otherwise reveal the text just
   from the cursor passing through empty space anywhere in the row). */
html.js .timeline-node.is-icon-only .node-icon-trigger:hover ~ .node-event-text,
html.js .timeline-node.is-icon-only .node-icon-trigger:focus-visible ~ .node-event-text,
html.js .timeline-node.is-icon-only.is-revealed .node-event-text {
  max-height: 220px;
  opacity: 1;
}

/* Descriptions only show once the node is centered on the fixed dot — the
   title/icon stay put throughout, but the prose beneath only appears for
   whichever entry is "now", lightening the list while scrolling past the
   rest. Opacity (not max-height) so the layout doesn't reflow: the space
   the text would take stays reserved either way. */
html.js .node-pane[data-pane-side="with"] .node-event-text p,
html.js .node-pane[data-pane-side="without"] p {
  opacity: 0;
  transition: opacity 0.3s ease;
}

html.js .timeline-node.is-active .node-pane[data-pane-side="with"] .node-event-text p,
html.js .timeline-node.is-active .node-pane[data-pane-side="without"] p,
html.js .timeline-node.is-icon-only .node-icon-trigger:hover ~ .node-event-text p,
html.js .timeline-node.is-icon-only .node-icon-trigger:focus-visible ~ .node-event-text p,
html.js .timeline-node.is-icon-only.is-revealed .node-event-text p {
  opacity: 1;
}

/* ── SUB-ITEM STAGGER ── */
.sub-items {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.node-pane[data-pane-side="without"] .sub-items {
  align-items: flex-end;
}

.node-pane[data-pane-side="shared"] .sub-items {
  align-items: center;
}

.sub-item {
  display: inline-block;
  width: fit-content;
  font-size: 13px;
  font-weight: 600;
  padding: 6px 12px;
  border-radius: var(--r-sm);
  background: var(--primary-soft);
  color: var(--primary-dark);
}

/* States below only apply once JS has confirmed it's running — see NO-JS section */
html.js .node-pane {
  opacity: 0.45;
  transform: scale(0.92);
  transition: opacity 0.5s ease, transform 0.5s ease;
}

/* Non-central events arrive sliding in from the side they're positioned on
   (left panes from the left, right panes from the right) with a fade +
   scale, on top of the same dim-but-visible resting look as the shared
   cards (opacity inherited from the base .node-pane rule above). */
html.js .node-pane[data-pane-side="without"] {
  transform-origin: right center;
  transform: scale(0.92) translateX(-40px);
}

html.js .node-pane[data-pane-side="with"] {
  transform-origin: left center;
  transform: scale(0.92) translateX(40px);
}

html.js .timeline-node.is-active .node-pane {
  opacity: 1;
  transform: scale(1.05);
}

html.js .timeline-node.is-active .node-pane[data-pane-side="without"],
html.js .timeline-node.is-active .node-pane[data-pane-side="with"] {
  transform: scale(1.05) translateX(0);
}

html.js .node-pane[data-pane-side="shared"] {
  transition: opacity 0.5s ease, transform 0.5s ease, border-color 0.3s ease, box-shadow 0.3s ease;
}

html.js .timeline-node.is-active .node-pane[data-pane-side="shared"] {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-soft), var(--shadow-sm);
}

/* Once scrolled past, an element stays fully visible — no fade/shrink. */
html.js .timeline-node.is-past .node-pane {
  opacity: 1;
  transform: scale(1);
}

html.js .sub-item {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.4s ease, transform 0.4s ease;
  transition-delay: calc(var(--i, 0) * 150ms);
}

html.js .timeline-node.is-active .sub-item {
  opacity: 1;
  transform: translateY(0);
}

/* The shared session cards (Séance d'essai, Cours) already fade/scale in as
   a whole — an extra per-pill stagger on top reads as a duplicate
   animation. Pills there just follow the card's own opacity/transform. */
html.js .node-pane[data-pane-side="shared"] .sub-item {
  opacity: 1;
  transform: none;
  transition: none;
  transition-delay: 0s;
}

/* ── CONCLUSION ── */
.show-conclusion {
  max-width: 640px;
  margin: 0 auto;
  padding: 56px 24px 140px;
  text-align: center;
}

.show-conclusion h2 {
  font-size: clamp(1.5rem, 4vw, 2.2rem);
  margin: 0 0 16px;
  color: var(--text-strong);
}

.show-conclusion p {
  margin: 0 0 32px;
  color: var(--text-muted);
}

.show-conclusion-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.show-conclusion-cta {
  padding: 18px 40px;
  font-size: 17px;
}

.show-conclusion-note {
  margin-top: 64px;
  padding-top: 40px;
  border-top: 1px solid var(--border);
  text-align: left;
}

.show-conclusion-note p {
  margin: 0 0 16px;
  font-size: 14px;
  color: var(--text-muted);
}

.show-conclusion-note p:last-child {
  margin-bottom: 0;
}

.show-conclusion-bio {
  display: flex;
  align-items: flex-start;
  gap: 20px;
  margin-bottom: 16px;
}

.show-conclusion-bio p {
  margin: 0;
}

.show-conclusion-avatar {
  flex-shrink: 0;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  object-fit: cover;
}

/* ── CONTACT MODAL ── */
.contact-modal {
  border: none;
  border-radius: var(--r-lg);
  padding: 0;
  max-width: 420px;
  width: calc(100% - 48px);
  max-height: calc(100vh - 48px);
  max-height: calc(100dvh - 48px);
  overflow: hidden;
  box-shadow: var(--shadow-md);
}

/* Specificity has to beat the UA's own `dialog[open] { display: block }" rule. */
.contact-modal[open] {
  display: flex;
  flex-direction: column;
}

.contact-modal::backdrop {
  background: rgba(24, 23, 21, 0.55);
  backdrop-filter: blur(4px);
}

.contact-modal-form {
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  gap: 12px;
  padding: 32px 32px 0;
}

.contact-modal-scroll {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 12px;
  overflow-y: auto;
  overscroll-behavior: contain;
  min-height: 0;
  padding-bottom: 4px;
}

.contact-modal-footer {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: none;
  padding: 12px 0 32px;
  border-top: 1px solid var(--border-md);
}

.contact-modal-form input,
.contact-modal-form textarea,
.contact-modal-form select {
  font-family: var(--font);
  font-size: 14px;
  padding: 12px 14px;
  border: 1px solid var(--border-md);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text-main);
}

.contact-modal-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 2px;
  border: none;
  background: none;
  font-family: var(--font);
  font-size: 13px;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
}

.contact-modal-toggle-chevron {
  flex: none;
  transition: transform 0.2s ease;
}

.contact-modal-toggle[aria-expanded="true"] .contact-modal-toggle-chevron {
  transform: rotate(180deg);
}

.contact-modal-extra {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.contact-modal-field-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.contact-modal-question {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.contact-modal-extra[hidden],
.contact-modal-field-group[hidden] {
  display: none;
}

.contact-modal-elaborate {
  resize: none;
  overflow: hidden;
  min-height: 44px;
}

.contact-modal-field-label {
  font-size: 12px;
  color: var(--text-muted);
}

.contact-modal-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  background: var(--bg-alt);
  color: var(--text-muted);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}

.contact-modal-title {
  margin: 0 0 4px;
  padding-right: 32px;
  font-weight: 700;
  font-size: 18px;
  color: var(--text-strong);
}

.contact-modal-fallback {
  margin: 0;
  font-size: 12px;
  color: var(--text-faint);
}

/* ── REDUCED MOTION ── */
@media (prefers-reduced-motion: reduce) {
  .show-hero-video {
    display: none;
  }

  .show-cta,
  .show-cta-label,
  .show-cta-arrow,
  html.js .node-pane,
  html.js .sub-item {
    transition: none !important;
    animation: none !important;
  }
}

html.reduced-motion .show-hero-video {
  display: none;
}

html.reduced-motion .show-cta[data-state="scrolled"] .show-cta-arrow {
  animation: none;
}

/* ── NO-JS ──
   Without html.js on <html>, none of the ".js …" rules above apply: every
   node, pane and sub-item renders at full opacity/scale in normal document
   flow, fully readable top to bottom. */

/* ── RESPONSIVE ── */
@media (max-width: 720px) {
  .show-page {
    --gutter: 6px;
  }

  /* The spine, the dot and the marker are a background element: they stay
     centered at every width. Non-shared panes keep the same two-column,
     text-near-the-spine layout as desktop, just narrower/smaller — no card
     background. */

  .timeline-headers {
    gap: 8px;
  }

  .timeline-node {
    padding-block: 12px;
  }

  .node-pane h3 {
    font-size: 0.95rem;
  }

  .node-pane p {
    font-size: 12px;
  }

  .sub-item {
    font-size: 11px;
    padding: 5px 9px;
  }

  .node-pane[data-pane-side="shared"] {
    width: min(180px, 75%);
    padding: 10px 14px;
  }

  .node-pane[data-pane-side="shared"] h3 {
    font-size: 0.9rem;
    margin: 0 0 4px;
  }

  .show-conclusion-bio {
    flex-direction: column;
    align-items: center;
    text-align: center;
  }
}
