/* The story: the app's own interface (the demo, built into demo/ from the app, see
   packages/app/src/renderer/demo) pinned on a stage while the page scrolls past a step per scene
   and a gap between each two. On a step, its scene holds still; through a gap, the captions fade
   and the camera pans and zooms the window (drawn at the app's 1280×800) from one scene's part of
   it to the next's, as far as the page has scrolled (story.js). It isn't meant to be clicked.
   Shared by the pages with a story. */
.story { position: relative; --stage-top: 56px; --stage-height: calc(100svh - var(--stage-top)); }
.stage { position: sticky; top: var(--stage-top); height: var(--stage-height); overflow: hidden; }
.camera {
  position: absolute; top: 0; left: 0; width: 1280px; height: 800px; transform-origin: 0 0;
  border-radius: 12px; overflow: hidden; background: var(--app-bg); /* the app's own background, light or dark, while it loads */ border: 1px solid var(--window-border); box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08), 0 24px 60px rgba(0, 0, 0, 0.18);
}
/* The hero's two windows (the home page): the one showing in place, the other waiting to the side,
   faded out. Draft → highlight, the second comes in from the right as the first goes left; back,
   the other way. Once the story moves on, the first window's back. */
.camera { transition: opacity 0.6s ease, translate 0.6s cubic-bezier(0.3, 0, 0.2, 1); }
.camera.alt { opacity: 0; translate: 6% 0; pointer-events: none; }
.stage.on-hero[data-hero="focus"] .camera:not(.alt) { opacity: 0; translate: -6% 0; }
.stage.on-hero[data-hero="focus"] .camera.alt { opacity: 1; translate: 0 0; }
/* The second window of a step with two: placed and faded in by story.js. */
.camera.second { opacity: 0; transition: none; pointer-events: none; }
.camera iframe { display: block; width: 1280px; height: 800px; border: 0; pointer-events: none; opacity: 0; transition: opacity 0.4s; }
.camera iframe.loaded { opacity: 1; }
/* Shown instead of the demo on a page opened as a file, where browsers block it. */
.camera .needs-server { position: absolute; inset: 0; display: grid; place-content: center; gap: 8px; padding: 40px; text-align: center; font-size: 22px; color: #6e6e73; }
.camera .needs-server code { font-size: 20px; color: #1d1d1f; }
.steps { position: relative; margin-top: calc(-1 * var(--stage-height)); pointer-events: none; }
.step { min-height: calc(var(--stage-height) * 0.7); }
.step:first-child { min-height: calc(var(--stage-height) * 0.5); }
.step[data-side="below"] { min-height: calc(var(--stage-height) * 1.5); } /* the hero, its tools under it: held a while, to try them */
.step:last-child { min-height: calc(var(--stage-height) * 0.4); } /* "settle": back to the whole window before the page moves on */
.step[data-scene="upload"] { min-height: calc(var(--stage-height) * 1.2); } /* room to drag the file in */
.gap { height: calc(var(--stage-height) * 1.4); } /* where one scene changes to the next: long, so the window moves slowly (the user found it fast) */
/* The captions stay still on the stage, on the page's background: each fades in for its scene, on
   its side, and out for the next, as the page scrolls through the gaps (--show and --shift, set by
   story.js). The camera keeps the window clear of them. */
.caption { position: absolute; top: 50%; left: 48px; width: 344px; opacity: var(--show, 0); visibility: hidden; text-align: left; transform: translateY(calc(-50% + var(--shift, 32px))); }
/* Each side's captions share one column (COLUMN in story.js, 440px from the screen's edge), centred
   in it, so they line up from scene to scene; a caption on the left is aligned towards the window,
   which meets the column's edge where it can. */
.caption[data-side="right"] { left: auto; right: 48px; }
.caption[data-side="left"] { text-align: right; }
/* Below the window, across the foot (the home page's hero: its tools, under the window they change). */
.caption[data-side="below"] { top: auto; bottom: 28px; left: 50%; width: min(720px, calc(100% - 80px)); text-align: center; transform: translate(-50%, var(--shift, 32px)); }
.hero-caption .hero-tools { margin: 0 0 14px; }
.hero-caption .lede { margin-bottom: 0; }
/* Across the top, over a window using the full width under it (story.js frames it). */
.caption[data-side="top"] { top: 28px; left: 50%; width: min(640px, calc(100% - 80px)); text-align: center; transform: translate(-50%, var(--shift, 32px)); }
/* Across the foot, under a window that runs up under the page's header: where story.js moves a
   caption when the window has to be cropped up and down. */
.caption[data-side="bottom"] { top: auto; bottom: 28px; left: 50%; width: min(640px, calc(100% - 80px)); text-align: center; transform: translate(-50%, var(--shift, 32px)); }
.agent { text-align: left; }
.caption h2 { margin-bottom: 12px; font-size: clamp(26px, 3vw, 38px); text-wrap: balance; }
/* No short word alone on a line: headings wrap into even lines, paragraphs avoid a last line of
   one word (and story.js ties each one's last two words together, for browsers without these). */
.caption p { text-wrap: pretty; }
.caption > p:last-of-type { margin: 0; color: var(--muted); font-size: 17px; }
.caption .kicker { color: var(--blue); }
.caption.highlight .kicker { color: var(--brown); }
/* A file beside the window, under a caption (the first scene's): dragged onto the window and
   dropped as the page scrolls through its step (placeFile in story.js), as from the desktop. */
.drag-file { display: inline-grid; justify-items: center; gap: 6px; margin-top: 24px; width: 140px; font-size: 13px; font-weight: 500; color: var(--text); text-align: center; }
.drag-file-icon { display: grid; place-items: end center; width: 56px; height: 70px; padding-bottom: 8px; border-radius: 4px 14px 4px 4px; background: #fff; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.12); font-size: 11px; font-weight: 800; color: #d64545; }
.drag-file.picked { visibility: hidden; }
.drag-ghost > span:last-child { padding: 1px 6px; border-radius: 4px; background: #2f6fde; color: #fff; } /* as macOS labels a file being dragged */
.drag-ghost { position: absolute; z-index: 3; margin: 0; pointer-events: none; filter: drop-shadow(0 10px 18px rgba(0, 0, 0, 0.3)); }
.drag-ghost[hidden] { display: none; }

/* Progress through the story: a dot per captioned scene beside the caption, on its side (a set
   on each side, the one in use slid in from the window's edge). Scenes passed are blue, those
   to come grey, and the current one is a taller pill filling with blue as the page scrolls
   through it (--fill, see track()). */
.progress { position: absolute; top: 50%; display: flex; flex-direction: column; align-items: center; gap: 8px; opacity: 0; transition: opacity 0.4s, transform 0.5s cubic-bezier(0.3, 0, 0.2, 1); pointer-events: none; }
.progress[data-side="left"] { left: 20px; transform: translate(-56px, -50%); }
.progress[data-side="right"] { right: 20px; transform: translate(56px, -50%); }
.progress.shown { opacity: 1; transform: translate(0, -50%); }
.dot { position: relative; width: 7px; height: 7px; border-radius: 4px; background: var(--line); overflow: hidden; transition: height 0.35s; }
.dot::after { content: ""; position: absolute; inset: 0; background: var(--blue); transform: scaleY(var(--fill, 0)); transform-origin: top; }
.dot.passed { --fill: 1; }
.dot.current { height: 34px; }
/* The agent's side: a window of its own floating over the app's, as another app on the desktop
   would, over the app window's left side (placed by story.js) so the cards appearing in its right
   margin stay in view. The demo tells the page what the agent is doing: the user's prompt, the
   agent's replies (typed out) and each step it takes, drawn as the app's chat draws them. Its height is fixed: what's new comes in at the bottom and the oldest scrolls
   off the top. It shows while it has something to say. Generic, standing for whichever agent the
   visitor uses. */
.agent { position: absolute; bottom: 32px; left: 32px; z-index: 2; display: flex; flex-direction: column; width: 400px; height: 560px; transform-origin: bottom left; border-radius: 10px; overflow: hidden; background: #1c1c1e; color: #f2f2f4; font-size: 13px; line-height: 1.45; text-align: left; border: 1px solid rgba(255, 255, 255, 0.1); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12), 0 18px 48px rgba(0, 0, 0, 0.22); opacity: 0; transform: translateY(16px) scale(0.98); transition: opacity 0.35s, transform 0.35s; pointer-events: none; }
.agent.shown { opacity: 1; transform: none; }
/* Its header as the app's chat has one: on the window's own background, the name at the side. */
.agent-bar { position: relative; flex: none; margin: 0; padding: 10px 12px 4px 72px; font-size: 12px; font-weight: 600; color: #8e8e93; }
.agent-lights { position: absolute; left: 12px; top: 50%; display: flex; gap: 6px; transform: translateY(-30%); }
.agent-lights i { width: 10px; height: 10px; border-radius: 50%; background: #ff5f57; }
.agent-lights i:nth-child(2) { background: #febc2e; }
.agent-lights i:nth-child(3) { background: #28c840; }
/* Newest at the bottom; what doesn't fit goes off the top, fading out as it goes. Its lines as the
   app's chat draws them: the prompt in a bubble, each step a muted line, replies plain. */
.agent-body { flex: 1; min-height: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 10px; padding: 12px; overflow: hidden; mask-image: linear-gradient(to bottom, transparent 0, #000 40px); }
.agent-body > * { flex: none; margin: 0; max-width: 92%; animation: agent-in 0.3s ease-out; }
.agent-prompt { align-self: flex-end; padding: 7px 10px; border-radius: 12px 12px 4px 12px; background: #0a84ff; color: #fff; }
.agent-say { align-self: flex-start; }
.agent-tool { align-self: flex-start; min-width: 0; font-size: 12px; color: #8e8e93; }
.agent-tool::before { content: "•"; margin-right: 6px; }
.agent-tool b { font-weight: 400; }
.agent-tool span:not(:empty)::before { content: ": "; }
@keyframes agent-in { from { opacity: 0; transform: translateY(4px); } }
/* The chat's window: the app's own chat (the demo's demo-chat.html), frameless, floating by the app
   window's right edge as it does in the app, placed and scaled with it (placeChat in story.js), and
   faded in while the demo says it shows. SmartDoc's: SmartSpec has the agent's window instead. */
.camera.chat { width: 400px; height: 660px; border-radius: 10px; opacity: 0; transition: opacity 0.35s; pointer-events: none; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12), 0 18px 48px rgba(0, 0, 0, 0.22); }
.camera.chat.shown { opacity: 1; }
.camera.chat iframe { width: 400px; height: 660px; }
/* Narrow: the window and the caption one above the other, either way round (story.js places
   them), and the progress dots in a row, centred at the foot, the current one long. */
@media (max-width: 899px) {
  .caption, .caption[data-side="right"], .caption[data-side="left"], .caption[data-side="top"], .caption[data-side="bottom"], .caption[data-side="below"] { top: var(--narrow-top, 50%); bottom: auto; left: 16px; right: 16px; width: auto; text-align: left; transform: translateY(var(--shift, 32px)); }
  .caption[data-side="below"] { text-align: center; }
  .progress[data-side] { top: auto; bottom: 16px; left: 50%; right: auto; flex-direction: row; transform: translate(-50%, 12px); }
  .progress.shown { transform: translateX(-50%); }
  .dot { transition: width 0.35s; }
  .dot::after { transform: scaleX(var(--fill, 0)); transform-origin: left; }
  .dot.current { width: 34px; height: 7px; }
  .caption h2 { font-size: 24px; margin-bottom: 6px; }
  .caption > p:last-of-type { font-size: 15px; }
  /* docked over the lower part of the window (story.js sets its top and height), across its width */
  .agent { bottom: auto; left: 12px; right: 12px; width: auto; font-size: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .camera, .caption, .progress, .dot { transition: none; }
  .agent, .agent-body > *, .agent-tool::before { animation: none; transition: none; }
}

/* Phones and upright tablets: the story isn't played (story.js), but each step is a block of the
   page, its caption over a still of its scene (site/shots, made from the demo by scripts/shots.mjs). */
.story-flat { display: none; }
@media (max-width: 899px) {
  .story { display: none; }
  .story-flat { display: grid; gap: 56px; padding: 24px 16px 48px; }
  .flat-step { display: grid; gap: 18px; }
  .flat-step .caption { position: static; inset: auto; width: auto; transform: none; opacity: 1; visibility: visible; text-align: left; }
  .flat-step picture, .flat-step img { display: block; width: 100%; height: auto; }
  .flat-step .hero-tools { display: none; }
}
