Files
Tom Huang bc6a246c65 feat(slides): enhance deck project experience (#5083)
* feat(deck): enhance slide deck functionality with speaker notes and navigation improvements

- Added a switch for including speaker notes in slide decks, defaulting to true.
- Updated keyboard navigation to include 'R' for resetting to the first slide.
- Implemented click navigation for half-slide transitions.
- Enhanced the deck framework to support hidden programmatic prev/next controls.
- Improved handling of file inputs in question forms to support file submissions.

This update aims to improve user experience in creating and presenting slide decks, ensuring better accessibility and functionality.

* feat(artifacts): enforce semantic naming for user-facing deliverables

- Updated guidelines to require semantic filenames derived from user briefs for new artifacts, moving away from defaulting to `index.html`.
- Enhanced documentation to clarify naming conventions for HTML files, emphasizing the use of descriptive names like `investor-pitch-deck.html`.
- Adjusted prompts and hints across the system to reflect these changes, ensuring consistency in user-facing outputs.
- Improved test coverage to validate the new naming conventions and ensure proper implementation in various contexts.

This update aims to enhance clarity and usability in project file management, promoting better organization and user experience.

* feat(file-viewer): enhance speaker notes display and improve file workspace functionality

- Updated the speaker notes section to include a styled placeholder for empty notes, improving user experience.
- Changed the icon in the file workspace from "slides" to "panel-left" for better clarity.
- Introduced new sub-category filtering options in the file workspace, enhancing organization and navigation.
- Improved styling for the page creator search input and added visual feedback for loading states.

These changes aim to enhance usability and visual consistency across the file viewer and workspace components.

* test(web): align workspace tests with pages switcher

* test(e2e): open design files through pages menu

* fix(deck): keep source mode reachable

* fix(workspace): restore uploaded file tabs

* feat(deck-thumbnail): implement virtualized thumbnail rail for improved performance

- Introduced a new `DeckThumbnailRail` component to optimize the rendering of deck thumbnails, reducing memory usage and improving load times.
- Enhanced the `FileViewer` to integrate the new thumbnail rail, allowing for lazy loading of thumbnails based on viewport visibility.
- Added tests for the `DeckThumbnailRail` to ensure correct functionality and caching behavior.
- Updated styles for better visual consistency and performance during thumbnail rendering.

These changes aim to enhance user experience by providing a smoother and more efficient way to navigate through deck slides.

* feat(deck): enhance deck rendering with thumbnail support and keyboard shortcuts

- Integrated `DeckSlideThumbnail` for rendering individual slides in a shadow root, improving performance and reducing main-thread load.
- Updated `DeckThumbnailRail` to utilize the new thumbnail component, allowing for efficient slide navigation.
- Implemented keyboard shortcuts for deck navigation, enhancing user experience during presentations.
- Added tests for `buildDeckRenderInput` to ensure proper functionality of the deck stage fallback.
- Improved styling for loading states in the viewer, providing a smoother visual experience.

These changes aim to optimize the deck viewing experience by reducing resource consumption and enhancing interactivity.

* feat(deck): improve thumbnail loading and speaker notes editing experience

- Refactored `DeckSlideThumbnail` to enhance loading states with a new shimmer effect, improving visual feedback during thumbnail rendering.
- Updated `DeckThumbnailRail` to manage loading states for thumbnails, ensuring a smoother user experience.
- Simplified the speaker notes editing interface by removing the toggle switch, allowing direct editing from the notes body.
- Enhanced accessibility by adding roles and focus states to speaker notes elements.
- Added tests to verify the new loading states and speaker notes functionality.

These changes aim to optimize the user experience in deck navigation and speaker notes management, providing a more intuitive and responsive interface.

* feat(file-viewer): enhance version export functionality and speaker notes interaction

- Introduced new export options for file versions, including PDF and image formats, improving the ability to download and share content.
- Implemented a streamlined process for exporting version content, with progress indicators and error handling for a better user experience.
- Enhanced speaker notes editing by refining event handling to prevent unintended focus shifts, ensuring a smoother editing experience.
- Updated styles for improved visual consistency in the file version download interface.
- Added tests to verify the functionality of version exports and speaker notes interactions.

These changes aim to optimize the file viewer's usability and enhance the overall experience when managing and exporting project files.

* fix(web): polish export menus and creator filters

* fix(file-viewer): fall back to preview exports

* test(file-viewer): cover version export fallbacks

* test(file-viewer): assert loading skeleton by role

* fix(file-viewer): restore html source mode affordance

* fix(file-viewer): capture full version fallback snapshots

* docs: trim slides handoff eof

* test(exports): cover full preview snapshot requests

* test(file-viewer): account for snapshot options arg

* refactor(file-viewer, file-workspace): streamline export functions and enhance page creator dialog visibility

* test(file-workspace): enhance slide template creation and mock plugin responses

* feat(export): add support for versioned exports and enhance HTML export functionality

* feat(export): implement versioned export support across multiple formats and enhance related tests

* feat(file-viewer): enhance manual edit functionality with commit sequence tracking and add test for inline text session saving

* style(speaker-notes): update filmstrip and thumb-frame styles for improved responsiveness and add corresponding tests

* feat(file-viewer): enhance comment composer functionality with portal metrics and improve draw toolbar layout for mobile views

* feat(analytics): track slide deck viewing experience

Add analytics for the new deck/slides experience introduced in this PR:
the deck viewer surface, in-deck slide navigation, thumbnail rail, and
speaker-notes authoring. Presentation entry stays on the existing
present_popover click to avoid double-counting.

- contracts: DeckViewerSurfaceViewProps (surface_view),
  DeckViewerClickProps (ui_click), SpeakerNotesSaveResultProps
  (new speaker_notes_save_result event), wired into the event unions.
- web: track* wrappers + fire helpers in FileViewer — deck_viewer
  surface_view on deck mount, slide_prev/next/reset, thumbnail_select,
  thumbnail_rail_toggle (expand/collapse), speaker_notes_edit, and
  speaker_notes_save_result (preview + presenter surfaces).
- tests: deck analytics suite asserting the emitted (event, props) pairs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(file-viewer, file-workspace): enhance export toast functionality and improve localization for page creation

* feat(home-view, plugins-home-section, agent-skill): update default facet preference, enhance category selection handling, and improve localization support

- Set `preferDefaultFacet` to true in HomeView component for better user experience.
- Introduced `handlePickCategory` function in PluginsHomeSection to manage category selection based on card layout visibility.
- Updated PRIMARY_CATEGORIES to reflect the new order and added localization for titles and descriptions in adaptAgentSkill.
- Enhanced tests to verify the correct handling of display copy and tags from SKILL frontmatter.

* feat(plugins-home, file-workspace): introduce commercial category labels and enhance deck handling

- Added a new module for resolving and localizing commercial category labels for plugins.
- Updated the FileWorkspace and PluginCard components to display the commercial category label on deck cards.
- Enhanced the PageCreatorPresetFrame to adjust frame classes based on deck presets.
- Refactored subcategory handling in facets to align with the new commercial category taxonomy.
- Improved localization support for new category labels across multiple languages.

* feat(deck-preview): implement deck preview scaling and enhance home hero layout

- Introduced `useDeckPreviewScale` hook to manage scaling of deck previews within a fixed 1280×720 logical viewport, ensuring proportional rendering across various templates.
- Updated `FileWorkspace`, `HomeHero`, and `PluginCard` components to utilize the new scaling functionality for improved visual consistency.
- Enhanced the layout of the home hero section to accommodate new subtype chips and descriptions, including a "More" dropdown for overflow handling.
- Improved localization support for new UI elements across multiple languages.

* fix(PreviewModal): clarify sidebar prop documentation and update test description

- Updated the documentation for the `PreviewSidebar` interface to specify that the sidebar's stage-edge handles are not shown when the sidebar prop is absent.
- Modified the test suite description for `PreviewModal` to be more concise and relevant.

* test(e2e): select prototype visual card

---------

Co-authored-by: free666799 <293857035+free666799@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 09:41:47 +00:00

339 lines
18 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Run a Metrics Standup like a Data-Driven Ops Lead - Data, KPI &amp; finance</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap');
/* tokens: off-black ground, single emerald accent, status-report mono */
:root {
--bg: #121417;
--ink: #edefe9;
--muted: #a3aaa1;
--line: rgba(237, 239, 233, 0.14);
--line-strong: rgba(237, 239, 233, 0.34);
--accent: #3ecf8e;
--accent-deep: #0e8a55;
--accent-ink: #0c1410;
--display: 'Archivo', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
--ease: cubic-bezier(.16, 1, .3, 1);
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; background: var(--bg); color: var(--ink); font-family: var(--display); -webkit-font-smoothing: antialiased; }
body { overflow: hidden; }
.deck {
display: flex;
width: 100vw; height: 100vh;
overflow-x: auto;
overflow-y: hidden;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
scrollbar-width: none;
}
.deck::-webkit-scrollbar { display: none; }
.slide {
flex: 0 0 100vw; height: 100vh;
display: flex; align-items: center; justify-content: center;
padding: 56px 96px;
scroll-snap-align: start;
position: relative;
}
.slide-inner { width: 100%; max-width: 1100px; }
.crumb {
position: absolute; top: 28px; left: 40px;
font-family: var(--mono); font-size: 11px; color: var(--muted);
text-transform: uppercase; letter-spacing: 0.14em;
}
.crumb::before { content: ''; display: inline-block; width: 18px; height: 1px; background: var(--accent); vertical-align: middle; margin-right: 10px; }
.pageno {
position: absolute; bottom: 28px; right: 40px;
font-family: var(--mono); font-size: 11px; color: var(--muted); letter-spacing: 0.06em;
}
.nav {
position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%);
display: flex; gap: 7px; z-index: 5;
}
.nav .dot {
width: 16px; height: 2px; border-radius: 0; background: var(--line-strong);
cursor: pointer; transition: background .2s var(--ease);
}
.nav .dot:hover { background: var(--muted); }
.nav .dot.active { background: var(--accent); }
/* entrance: transform+opacity only, staggered, reduced-motion safe */
@keyframes rise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
.slide-inner > * { animation: rise .6s var(--ease) both; }
.slide-inner > *:nth-child(2) { animation-delay: .07s; }
.slide-inner > *:nth-child(3) { animation-delay: .14s; }
.slide-inner > *:nth-child(4) { animation-delay: .21s; }
@media (prefers-reduced-motion: reduce) { .slide-inner > * { animation: none; } }
/* Cover */
.cover { display: flex; flex-direction: column; gap: 30px; }
.cover .badge { display: inline-flex; align-items: center; gap: 10px; padding: 7px 12px; border: 1px solid var(--line-strong); align-self: flex-start; font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--muted); }
.cover .badge .dot { width: 6px; height: 6px; background: var(--accent); }
.cover h1 { font-size: clamp(56px, 8vw, 112px); margin: 0; line-height: 0.96; letter-spacing: -0.035em; font-weight: 700; }
.cover h1 em { font-style: normal; color: var(--accent); }
.cover .meta { display: flex; gap: 40px; color: var(--muted); font-family: var(--mono); font-size: 12px; text-transform: uppercase; letter-spacing: 0.07em; border-top: 1px solid var(--line); padding-top: 22px; }
/* Headline */
.headline { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; align-items: center; }
.headline-num { font-size: clamp(120px, 17vw, 210px); line-height: 0.9; letter-spacing: -0.045em; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
.headline-num small { display: block; font-size: 12px; color: var(--muted); font-weight: 400; letter-spacing: 0.1em; margin-top: 18px; font-family: var(--mono); text-transform: uppercase; }
.headline-text h2 { font-size: 42px; line-height: 1.08; letter-spacing: -0.025em; margin: 0 0 18px; font-weight: 600; }
.headline-text p { color: var(--muted); font-size: 17px; max-width: 38ch; line-height: 1.6; margin: 0; }
/* Section title */
.section-title { font-size: clamp(32px, 4vw, 54px); margin: 0 0 40px; line-height: 1.05; letter-spacing: -0.025em; font-weight: 600; }
.section-title em { font-style: normal; color: var(--accent); }
/* Lists of items: hairline ledger rows, no cards */
.item-list { display: flex; flex-direction: column; border-top: 1px solid var(--line-strong); }
.item { display: grid; grid-template-columns: 56px 1fr auto; gap: 24px; align-items: center; padding: 24px 0; border-bottom: 1px solid var(--line); }
.item-num { font-family: var(--mono); font-size: 12px; color: var(--accent); }
.item-title { font-size: 21px; font-weight: 500; letter-spacing: -0.01em; line-height: 1.3; }
.item-meta { font-family: var(--mono); font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; }
.av-row { display: flex; }
.av { width: 30px; height: 30px; border: 1px solid var(--line-strong); background: var(--bg); margin-left: -9px; font-family: var(--mono); font-size: 10px; font-weight: 500; color: var(--muted); display: inline-flex; align-items: center; justify-content: center; }
.av:first-child { margin-left: 0; }
.av-2 { background: #1b1f23; color: var(--ink); }
.av-3 { background: #15211b; color: var(--accent); border-color: rgba(62, 207, 142, 0.4); }
/* Blocked / problem statement: accent rule, no gradient card */
.blocked-block { padding: 8px 0 8px 36px; border-left: 3px solid var(--accent); }
.blocked-block h3 { font-size: 32px; margin: 0 0 14px; letter-spacing: -0.02em; font-weight: 600; line-height: 1.15; }
.blocked-block p { color: var(--muted); margin: 0 0 26px; font-size: 17px; line-height: 1.6; max-width: 62ch; }
.blocked-ask { display: inline-flex; padding: 12px 22px; background: var(--accent); color: var(--accent-ink); font-weight: 600; font-size: 14.5px; letter-spacing: -0.005em; }
/* Charts: hairline columns, flat strokes, single accent */
.chart-grid { display: grid; grid-template-columns: 1fr 1fr; border-top: 1px solid var(--line-strong); }
.chart { padding: 30px 36px 8px 0; }
.chart + .chart { border-left: 1px solid var(--line); padding-left: 36px; padding-right: 0; }
.chart h4 { margin: 0 0 6px; font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
.chart .sub { font-family: var(--mono); font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; }
.chart svg { width: 100%; height: 200px; display: block; margin-top: 18px; border-bottom: 1px solid var(--line); }
.chart svg polyline { stroke: var(--accent); vector-effect: non-scaling-stroke; }
.chart svg circle { fill: var(--accent); }
.chart svg line { stroke: var(--line); vector-effect: non-scaling-stroke; }
.big-num { font-size: 68px; font-weight: 700; letter-spacing: -0.035em; line-height: 1; color: var(--ink); margin-top: 22px; font-variant-numeric: tabular-nums; }
.delta { font-family: var(--mono); font-size: 12px; color: var(--accent); margin-top: 10px; letter-spacing: 0.02em; }
/* Asks / outputs: hairline quadrant, no cards */
.asks { display: grid; grid-template-columns: 1fr 1fr; border-top: 1px solid var(--line-strong); }
.ask { padding: 30px 36px 30px 0; display: flex; flex-direction: column; gap: 12px; border-bottom: 1px solid var(--line); }
.ask:nth-child(even) { border-left: 1px solid var(--line); padding-left: 36px; padding-right: 0; }
.ask .who { display: flex; align-items: center; gap: 12px; font-family: var(--mono); font-size: 11px; color: var(--accent); text-transform: uppercase; letter-spacing: 0.1em; }
.ask .who .av { width: 26px; height: 26px; margin-left: 0; }
.ask h3 { font-size: 21px; line-height: 1.25; margin: 0; letter-spacing: -0.015em; font-weight: 600; }
.ask p { margin: 0; color: var(--muted); font-size: 14.5px; line-height: 1.55; max-width: 44ch; }
/* Closer: the deck's single deliberate inversion */
.invert { background: var(--ink); color: var(--bg); }
.invert .crumb, .invert .pageno { color: rgba(18, 20, 23, 0.72); }
.closer { display: flex; flex-direction: column; gap: 28px; align-items: flex-start; }
.closer h2 { font-size: clamp(44px, 6vw, 84px); margin: 0; line-height: 1.02; letter-spacing: -0.035em; font-weight: 700; }
.closer h2 em { font-style: normal; color: var(--accent-deep); }
.closer p { color: rgba(18, 20, 23, 0.74); font-size: 18px; max-width: 56ch; line-height: 1.6; margin: 0; }
.closer .signature { display: flex; align-items: center; gap: 16px; padding-top: 26px; border-top: 1px solid rgba(18, 20, 23, 0.22); width: 100%; }
.closer .signature .av { width: 44px; height: 44px; font-size: 14px; background: var(--accent-deep); border: none; color: var(--ink); font-weight: 600; }
.closer .signature strong { display: block; font-size: 16px; letter-spacing: -0.01em; }
.closer .signature span { color: rgba(18, 20, 23, 0.68); font-size: 13px; font-family: var(--mono); }
@media (max-width: 760px) {
.slide { padding: 48px 28px; }
.headline { grid-template-columns: 1fr; }
.chart-grid, .asks { grid-template-columns: 1fr; }
.chart + .chart, .ask:nth-child(even) { border-left: none; padding-left: 0; }
}
</style>
</head>
<body>
<div class="deck" id="deck">
<!-- 1. Cover -->
<section class="slide">
<span class="crumb">Data, KPI &amp; Finance · standup</span>
<div class="slide-inner cover">
<div class="badge"><span class="dot"></span>Week of Jul 6 · Ops &amp; Growth standup</div>
<h1>One number, <em>one decision</em>.</h1>
<div class="meta">
<span>Metrics standup · Open Design growth &amp; activation</span>
<span>Prepared for Ops &amp; Growth · Jul 9, 2026</span>
</div>
</div>
<span class="pageno">01 / 08</span>
</section>
<!-- 2. Headline number -->
<section class="slide">
<span class="crumb">Headline answer</span>
<div class="slide-inner headline">
<div class="headline-num">41%<small>Signup → first-render conversion, −6pp WoW</small></div>
<div class="headline-text">
<h2>The stars are up. The unit economics aren't.</h2>
<p>GitHub stars grew 1.3% WoW to 68.4K, but signup-to-first-render conversion fell to 41% from 47% — the third straight week that step alone has dropped.</p>
</div>
</div>
<span class="pageno">02 / 08</span>
</section>
<!-- 3. Metric proof -->
<section class="slide">
<span class="crumb">Metric proof</span>
<div class="slide-inner">
<h2 class="section-title">The proof, <em>line by line</em>.</h2>
<div class="item-list">
<div class="item"><span class="item-num">01</span><span class="item-title">Weekly active builders — 14,220 sessions, +4% WoW</span><span class="item-meta">Core · Activation</span></div>
<div class="item"><span class="item-num">02</span><span class="item-title">Signup → first-render conversion — 41%, −6pp WoW</span><span class="item-meta">Funnel · Down</span></div>
<div class="item"><span class="item-num">03</span><span class="item-title">BYOK agent connections — 9,800 linked keys across 21 agents, +2%</span><span class="item-meta">Agents · Flat</span></div>
<div class="item"><span class="item-num">04</span><span class="item-title">Plugin installs — 214,000 cumulative, +11,400 this week</span><span class="item-meta">Distribution</span></div>
</div>
</div>
<span class="pageno">03 / 08</span>
</section>
<!-- 4. Driver tree -->
<section class="slide">
<span class="crumb">Driver tree</span>
<div class="slide-inner">
<h2 class="section-title">Why conversion <em>slipped</em>.</h2>
<div class="item-list">
<div class="item"><span class="item-num">01</span><span class="item-title">Default agent timeout raised p95 render latency 8.1s → 14.4s</span><div class="av-row"><span class="av">OD</span></div></div>
<div class="item"><span class="item-num">02</span><span class="item-title">61% of the drop concentrates in Safari desktop, React-based templates</span><div class="av-row"><span class="av av-2">MR</span><span class="av">SL</span></div></div>
<div class="item"><span class="item-num">03</span><span class="item-title">New od-reframe flow added one extra confirm step before render</span><div class="av-row"><span class="av av-2">CA</span></div></div>
<div class="item"><span class="item-num">04</span><span class="item-title">Everything else — agent choice, BYOK setup, plugin discovery — flat WoW</span><div class="av-row"><span class="av av-3">PB</span></div></div>
</div>
</div>
<span class="pageno">04 / 08</span>
</section>
<!-- 5. The anomaly -->
<section class="slide">
<span class="crumb">The anomaly</span>
<div class="slide-inner">
<h2 class="section-title">One thing broke the <em>pattern</em>.</h2>
<div class="blocked-block">
<h3>Safari desktop first-render latency nearly doubled.</h3>
<p>Every other channel held steady or improved this week. Safari desktop alone jumped from 8.1s to 14.4s p95, and it's driving almost two-thirds of the conversion drop. That forces a call: roll back the od-reframe confirm step, or ship a Safari-specific render path before Friday's release cut.</p>
<span class="blocked-ask">Decision needed: roll back or patch by Thu 18:00</span>
</div>
</div>
<span class="pageno">05 / 08</span>
</section>
<!-- 6. Forecast -->
<section class="slide">
<span class="crumb">Forecast</span>
<div class="slide-inner">
<h2 class="section-title">If we don't fix it by <em>Friday</em>.</h2>
<div class="chart-grid">
<div class="chart">
<h4>First-render conversion · 4-week trailing</h4>
<div class="sub">Higher is better</div>
<svg viewBox="0 0 600 220" preserveAspectRatio="none">
<polyline fill="none" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"
points="20,60 110,72 200,90 290,108 380,124 470,148 560,164" />
<circle cx="560" cy="164" r="5"/>
</svg>
<div class="big-num">41%</div>
<div class="delta">▼ −6pp this week, tracking to 33% by month end if unresolved</div>
</div>
<div class="chart">
<h4>p95 render latency · Safari desktop</h4>
<div class="sub">Lower is better</div>
<svg viewBox="0 0 600 220" preserveAspectRatio="none">
<polyline fill="none" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"
points="20,160 110,150 200,140 290,124 380,108 470,80 560,52" />
<circle cx="560" cy="52" r="5"/>
</svg>
<div class="big-num">14.4s</div>
<div class="delta">▲ +78% WoW, breaches the 12s render SLA</div>
</div>
</div>
</div>
<span class="pageno">06 / 08</span>
</section>
<!-- 7. Recommended move -->
<section class="slide">
<span class="crumb">Recommended move</span>
<div class="slide-inner">
<h2 class="section-title">The one decision, <em>and who owns it</em>.</h2>
<div class="asks">
<div class="ask">
<div class="who"><span class="av av-2">EN</span>Engineering</div>
<h3>Ship the Safari-specific fallback render path by Thursday EOD.</h3>
<p>Bypasses the timeout path causing the 14.4s p95 without touching the other 39% of the drop.</p>
</div>
<div class="ask">
<div class="who"><span class="av av-3">PM</span>Product</div>
<h3>Pull the extra confirm step from od-reframe pending re-test.</h3>
<p>It was added for clarity, not speed — re-run the A/B once the Safari fix lands.</p>
</div>
<div class="ask">
<div class="who"><span class="av">GR</span>Growth</div>
<h3>Hold paid acquisition spend flat until conversion clears 45%.</h3>
<p>No point buying more traffic into a funnel step that's currently losing 6pp of it.</p>
</div>
<div class="ask">
<div class="who"><span class="av av-2">DA</span>Data</div>
<h3>Split Safari desktop out of the funnel dashboard going forward.</h3>
<p>This anomaly stayed hidden inside a blended average for two weeks — that can't repeat.</p>
</div>
</div>
</div>
<span class="pageno">07 / 08</span>
</section>
<!-- 8. Decision -->
<section class="slide invert">
<span class="crumb">Decision</span>
<div class="slide-inner closer">
<h2>Ship the <em>fallback</em>, not more spend.</h2>
<p>The data says one thing: fix the render path before we spend another dollar acquiring users into a slower funnel. Engineering owns Thursday's patch, Growth holds spend flat until conversion recovers, and Data splits Safari out so this doesn't hide again.</p>
<div class="signature">
<span class="av">OD</span>
<div><strong>Analytics &amp; Ops</strong><span>Weekly metrics standup · ping #growth-metrics</span></div>
</div>
</div>
<span class="pageno">08 / 08</span>
</section>
</div>
<div class="nav" id="nav"></div>
<script>
const deck = document.getElementById('deck');
const slides = deck.querySelectorAll('.slide');
const nav = document.getElementById('nav');
slides.forEach((_, i) => {
const d = document.createElement('span');
d.className = 'dot' + (i === 0 ? ' active' : '');
d.addEventListener('click', () => deck.scrollTo({ left: window.innerWidth * i, behavior: 'smooth' }));
nav.appendChild(d);
});
function activeIndex() {
return Math.round(deck.scrollLeft / window.innerWidth);
}
deck.addEventListener('scroll', () => {
const idx = activeIndex();
nav.querySelectorAll('.dot').forEach((d, i) => d.classList.toggle('active', i === idx));
}, { passive: true });
document.addEventListener('keydown', (e) => {
const idx = activeIndex();
if (e.key === 'ArrowRight' || e.key === 'PageDown') {
const next = Math.min(slides.length - 1, idx + 1);
deck.scrollTo({ left: window.innerWidth * next, behavior: 'smooth' });
} else if (e.key === 'ArrowLeft' || e.key === 'PageUp') {
const prev = Math.max(0, idx - 1);
deck.scrollTo({ left: window.innerWidth * prev, behavior: 'smooth' });
}
});
</script>
</body>
</html>