/* Gantry's root landing page (pages/overview): the thesis, the screencast carousel, the staged
   walkthrough of a job, and the further reading under it. The carousel is where this file's
   constraints are — one video slot two Stimulus controllers share, a dialog that repeats the
   frame, and an empty state that stands in for all of it before any screencast is published. */

.p-overview { display: flex; flex-direction: column; gap: clamp(var(--space-2xl), 8vw, 6rem); }
.p-overview__intro { display: flex; flex-direction: column; gap: var(--space-xl); align-items: center; text-align: center; padding-block: clamp(var(--space-xl), 8vw, 6rem) var(--space-lg); }
.p-overview__intro-copy { display: flex; flex-direction: column; gap: var(--space-md); align-items: center; max-width: var(--measure-wide); }
.p-overview__eyebrow {
  color: var(--accent);
  font-size: var(--text-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}
.p-overview__title {
  color: var(--text-bright);
  font-size: clamp(2.4rem, 1.45rem + 4vw, 5.8rem);
  font-weight: var(--fw-bold);
  line-height: 1;
  letter-spacing: 0;
  text-wrap: balance;
}
.p-overview__lead {
  color: var(--text-muted);
  font-size: var(--text-2xl);
  line-height: var(--lh-cell);
  max-width: var(--measure);
  text-wrap: balance;
}
.p-overview__thesis { display: flex; flex-direction: column; gap: var(--space-lg); max-width: var(--measure); }
.p-overview__thesis .c-prose { font-size: var(--text-xl); line-height: var(--lh-cell); text-wrap: balance; }
.p-overview__handoff {
  color: var(--text-bright);
  font-size: var(--text-3xl);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  text-wrap: balance;
}
.p-overview__caveat { margin-inline: auto; text-align: center; }
.p-overview__demo {
  width: min(100%, 66%);
  /* No bottom margin: the page's own gap is all that separates the carousel from the note under
     it, which puts that note the same distance from the carousel as from the first stage heading
     below it. */
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}
.p-overview__demo:focus { outline: none; }
.p-overview__demo:focus-visible .p-overview__demo-frame { outline: 2px solid var(--accent); outline-offset: 3px; }
/* The frame is a <button> that opens the modal, so it carries the window border and the chrome
   strip above the video and has to give up the UA button padding to do it. */
.p-overview__demo-frame {
  display: block;
  width: 100%;
  padding: 0;
  border: 2px solid var(--rule);
  border-radius: 4px;
  background: var(--field);
  overflow: hidden;
  cursor: zoom-in;
  position: relative;
  transition: border-color 0.2s ease;
}
.p-overview__demo-frame:hover { border-color: var(--accent); }
.p-overview__demo-frame:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.p-overview__chrome {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: 0.2rem var(--space-sm);
  background: var(--panel);
  border-block-end: 2px solid var(--rule);
}
.p-overview__chrome-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: left;
  font-size: var(--text-xs);
  color: var(--gray-muted);
  letter-spacing: 0;
  white-space: nowrap;
}
.p-overview__chrome-mark { color: var(--gray-text); }
.p-overview__chrome-meta { color: var(--gray-text); opacity: 0.7; }

/* One slot plays every clip in the roster, so the ratio is declared here and holds while the
   source is swapped or removed. screencast_carousel_controller.js adds is-fading and rewinds the
   clip 300ms later, which is what this duration has to match: any longer and the rewind lands
   mid-fade as the jump cut the fade exists to hide. The controller skips the fade under reduced
   motion, where the transition is off in any case. */
.p-overview__demo-video {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
  object-fit: cover;
  background: var(--surface-sunken);
  opacity: 1;
  transition: opacity 0.3s ease;
}
.p-overview__demo-video.is-fading { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .p-overview__demo-video { transition: none; }
}
.p-overview__demo-footer {
  order: 2;
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  margin-top: calc(-1 * var(--space-2xs));
}
/* The caption changes with every step through the roster, so it holds two lines' height whatever
   this clip's caption costs and the page below the carousel does not move under the reader. */
.p-overview__demo-caption {
  flex: 1;
  min-width: 0;
  min-height: calc(var(--text-sm) * var(--lh-copy) * 2);
  margin: 0;
  color: var(--text-dim);
  font-size: var(--text-sm);
  line-height: var(--lh-copy);
  text-align: left;
}
.p-overview__demo-caption-link {
  color: inherit;
  text-decoration-color: var(--line-strong);
}
.p-overview__demo-caption-link:hover {
  color: var(--text);
  text-decoration-color: var(--accent);
}
/* The roster is the list screencast_carousel_controller.js reads its clips from, one <li> per
   screencast, and is in the document for that rather than to be seen. */
.p-overview__demo-roster {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.p-overview__demo-expand {
  flex: none;
  display: grid;
  place-items: center;
  width: 1.1rem;
  height: 1.1rem;
  color: var(--gray-muted);
  font-size: var(--text-sm);
  line-height: 1;
  transition: color 0.2s ease;
}
.p-overview__demo-frame:hover .p-overview__demo-expand,
.p-overview__demo-frame:focus-visible .p-overview__demo-expand { color: var(--gray-bright); }
.p-overview__demo-nav {
  flex: none;
  display: flex;
  align-items: baseline;
  gap: var(--space-3xs);
  margin: 0;
}
.p-overview__demo-step {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-muted);
  font-size: var(--text-lg);
  line-height: 1;
  cursor: pointer;
  transition: color 0.2s ease;
}
.p-overview__demo-step:hover {
  color: var(--text-bright);
}
.p-overview__demo-step:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  color: var(--text-bright);
}
@media (prefers-reduced-motion: reduce) {
  .p-overview__demo-step { transition: none; }
}

/* With no published Replay carrying a video the template draws the same shell inert: a div rather
   than the modal button, a poster in place of the slot, and disabled arrows. The page keeps its
   shape either way, so the section above it is laid out against the same block. */
.p-overview__demo-frame--static { cursor: default; }
.p-overview__demo-frame--static:hover { border-color: var(--rule); }

.p-overview__demo-poster {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  align-items: center;
  justify-content: center;
  aspect-ratio: 16 / 9;
  color: var(--text-dim);
  /* The same scanline wash c-videoframe gives its own empty slot. */
  background:
    repeating-linear-gradient(0deg, transparent 0, transparent 3px, var(--surface-raised) 3px, var(--surface-raised) 4px);
}
.p-overview__demo-poster-glyph {
  font-size: var(--text-3xl);
  line-height: 1;
  color: var(--accent);
  /* The keyframes are c-videoframe's, and the duration folds --motion-scale as that component's
     does, so reduced motion holds the glyph still. */
  animation: gantry-videoframe-pulse calc(2.4s * var(--motion-scale)) ease-in-out infinite;
}
.p-overview__demo-poster-label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--text-dim);
}
.p-overview__demo-step:disabled {
  color: var(--text-dim);
  opacity: 0.4;
  cursor: default;
}
.p-overview__demo-step:disabled:hover { color: var(--text-dim); }

.p-overview__demo-dialog {
  width: min(92vw, 1400px);
  max-width: 92vw;
  max-height: 90vh;
  margin: auto; /* the reset's `* { margin: 0 }` takes the UA rule that centres a dialog */
  padding: 0;
  border: 0;
  background: none;
  overflow: visible;
}
/* The dialog itself is unstyled and this inner element is the window, so the caption and the
   arrows under it sit outside the border, on the backdrop. */
.p-overview__demo-dialog-window {
  border: 2px solid var(--rule);
  border-radius: 4px;
  background: var(--field);
  overflow: hidden;
}
.p-overview__demo-dialog::backdrop { background: rgba(0, 0, 0, 0.8); }
.p-overview__demo-dialog .p-overview__chrome-title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.p-overview__demo-dialog-video {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
  max-height: calc(90vh - 5rem);
  object-fit: contain;
  background: var(--surface-sunken);
}
.p-overview__demo-dialog-footer {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  padding: var(--space-xs) 0 0;
}
.p-overview__demo-dialog-nav {
  flex: none;
  display: flex;
  align-items: baseline;
  gap: var(--space-3xs);
}
.p-overview__demo-dialog-caption {
  flex: 1;
  min-width: 0;
  color: var(--text-dim);
  font-size: var(--text-xs);
  line-height: var(--lh-copy);
}
.p-overview__demo-close {
  flex: none;
  display: grid;
  place-items: center;
  width: 1.1rem;
  height: 1.1rem;
  border: none;
  border-radius: var(--radius);
  background: transparent;
  color: var(--gray-muted);
  font-size: var(--text-sm);
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.2s ease, color 0.2s ease;
}
.p-overview__demo-close:hover {
  background: rgba(0, 0, 0, 0.85);
  color: var(--gray-bright);
}
.p-overview__demo-close:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  color: var(--gray-bright);
}

.p-overview__stages { display: flex; flex-direction: column; gap: clamp(4rem, 11vw, 9rem); }

/* c-act is drawn for a walkthrough inside a page; here the stages are the page, so their titles
   are set larger than the component's default. */
.p-overview .c-act__title { font-size: clamp(2.4rem, 1.5rem + 3.2vw, 3.1rem); }
/* Every lead takes the column the intro thesis reads at and fills it evenly; text-wrap: balance
   would rag each lead to a width of its own, which down a page of stages reads as a mistake. */
.p-overview .c-act__lead { font-size: var(--text-xl); max-width: calc(var(--measure) / 1.4); text-wrap: pretty; }

/* Further reading: c-reading-box destinations over the newest posts. The boxes span the column the
   stages above them do and the post list keeps the prose measure, so the two read as a list under
   a row of boxes rather than as two rails of different widths. */
.p-overview__reading { display: flex; flex-direction: column; gap: clamp(var(--space-2xl), 5vw, 4rem); align-items: center; }
.p-overview__reading-posts {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  inline-size: 100%;
  max-inline-size: var(--measure);
  margin-inline: auto;
  list-style: none;
  padding: 0;
  text-align: start;
}
.p-overview__reading-post { display: flex; flex-direction: column; gap: var(--space-2xs); }
.p-overview__reading-post-date {
  color: var(--text-muted);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-label);
}
.p-overview__reading-post-title { font-size: var(--text-lg); font-weight: var(--fw-bold); }
.p-overview__reading-post-summary { color: var(--text-muted); max-width: var(--measure); }

@media (max-width: 40rem) {
  .p-overview__intro { padding-block-start: var(--space-2xl); }
  .p-overview__lead { font-size: var(--text-lg); }
  .p-overview__demo { width: min(100%, 96%); }
  /* The same captions wrap to three lines in this column, so the reservation grows with them. */
  .p-overview__demo-caption { min-height: calc(var(--text-sm) * var(--lh-copy) * 3); }
}
